linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jiang Liu <liuj97@gmail.com>
To: Bjorn Helgaas <bhelgaas@google.com>, Don Dutile <ddutile@redhat.com>
Cc: Jiang Liu <jiang.liu@huawei.com>, Yinghai Lu <yinghai@kernel.org>,
	Taku Izumi <izumi.taku@jp.fujitsu.com>,
	"Rafael J . Wysocki" <rjw@sisk.pl>,
	Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>,
	Yijing Wang <wangyijing@huawei.com>,
	linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org,
	Jiang Liu <liuj97@gmail.com>
Subject: [RFC PATCH v2 04/32] PCI: add PCIe capabilities access functions to hide differences among PCIe specs
Date: Wed, 25 Jul 2012 00:31:16 +0800	[thread overview]
Message-ID: <1343147504-25891-5-git-send-email-jiang.liu@huawei.com> (raw)
In-Reply-To: <1343147504-25891-1-git-send-email-jiang.liu@huawei.com>

From: Jiang Liu <jiang.liu@huawei.com>

Introduce five configuration access functions for PCIe capabilities registers
to hide differences among PCIe Base Spec versions.

Function pci_pcie_capability_read_word/dword() stores the PCIe Capabilities
register value by the passed parameter val. If related PCIe Capabilities
register is not implemented on the PCIe device, the passed parameter val
will be set 0.

Function pci_pcie_capability_write_word/dowrd() writes the value to PCIe
Capability register.

Function pci_pcie_capability_reg_implemeneted() checks whether a Capabilities
register is implemented by the PCIe device.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 drivers/pci/access.c     |  157 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pci.h      |    6 ++
 include/linux/pci_regs.h |    2 +
 3 files changed, 165 insertions(+)

diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index ba91a7e..59409e8 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -469,3 +469,160 @@ void pci_cfg_access_unlock(struct pci_dev *dev)
 	raw_spin_unlock_irqrestore(&pci_lock, flags);
 }
 EXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
+
+static inline int pci_pcie_cap_version(const struct pci_dev *dev)
+{
+	return dev->pcie_flags_reg & PCI_EXP_FLAGS_VERS;
+}
+
+static inline bool pci_pcie_cap_has_devctl(const struct pci_dev *dev)
+{
+	return true;
+}
+
+static inline bool pci_pcie_cap_has_lnkctl(const struct pci_dev *dev)
+{
+	int type = pci_pcie_type(dev);
+
+	return pci_pcie_cap_version(dev) > 1 ||
+	       type == PCI_EXP_TYPE_ROOT_PORT ||
+	       type == PCI_EXP_TYPE_ENDPOINT ||
+	       type == PCI_EXP_TYPE_LEG_END;
+}
+
+static inline bool pci_pcie_cap_has_sltctl(const struct pci_dev *dev)
+{
+	int type = pci_pcie_type(dev);
+
+	return pci_pcie_cap_version(dev) > 1 ||
+	       type == PCI_EXP_TYPE_ROOT_PORT ||
+	       (type == PCI_EXP_TYPE_DOWNSTREAM &&
+		dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT);
+}
+
+static inline bool pci_pcie_cap_has_rtctl(const struct pci_dev *dev)
+{
+	int type = pci_pcie_type(dev);
+
+	return pci_pcie_cap_version(dev) > 1 ||
+	       type == PCI_EXP_TYPE_ROOT_PORT ||
+	       type == PCI_EXP_TYPE_RC_EC;
+}
+
+bool pci_pcie_capability_reg_implemented(struct pci_dev *dev, int pos)
+{
+	if (!pci_is_pcie(dev))
+		return false;
+
+	switch (pos) {
+	case PCI_EXP_FLAGS_TYPE:
+		return true;
+	case PCI_EXP_DEVCAP:
+	case PCI_EXP_DEVCTL:
+	case PCI_EXP_DEVSTA:
+		return pci_pcie_cap_has_devctl(dev);
+	case PCI_EXP_LNKCAP:
+	case PCI_EXP_LNKCTL:
+	case PCI_EXP_LNKSTA:
+		return pci_pcie_cap_has_lnkctl(dev);
+	case PCI_EXP_SLTCAP:
+	case PCI_EXP_SLTCTL:
+	case PCI_EXP_SLTSTA:
+		return pci_pcie_cap_has_sltctl(dev);
+	case PCI_EXP_RTCTL:
+	case PCI_EXP_RTCAP:
+	case PCI_EXP_RTSTA:
+		return pci_pcie_cap_has_rtctl(dev);
+	case PCI_EXP_DEVCAP2:
+	case PCI_EXP_DEVCTL2:
+	case PCI_EXP_LNKCAP2:
+	case PCI_EXP_LNKCTL2:
+	case PCI_EXP_LNKSTA2:
+		return pci_pcie_cap_version(dev) > 1;
+	default:
+		return false;
+	}
+}
+EXPORT_SYMBOL(pci_pcie_capability_reg_implemented);
+
+/*
+ * Quotation from PCIe Base Spec 3.0:
+ * For Functions that do not implement the Slot Capabilities,
+ * Slot Status, and Slot Control registers, these spaces must
+ * be hardwired to 0b, with the exception of the Presence Detect
+ * State bit in the Slot Status register of Downstream Ports,
+ * which must be hardwired to 1b.
+ */
+int pci_pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val)
+{
+	int ret = 0;
+
+	*val = 0;
+	if (pos & 1)
+		return -EINVAL;
+
+	if (pci_pcie_capability_reg_implemented(dev, pos)) {
+		ret = pci_read_config_word(dev, pci_pcie_cap(dev) + pos, val);
+		/*
+		 * Reset *val to 0 if pci_read_config_word() fails, it may
+		 * have been written as 0xFFFF if hardware error happens
+		 * during pci_read_config_word().
+		 */
+		if (ret)
+			*val = 0;
+	} else if (pos == PCI_EXP_SLTSTA &&
+		 pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) {
+		*val = PCI_EXP_SLTSTA_PDS;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(pci_pcie_capability_read_word);
+
+int pci_pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val)
+{
+	int ret = 0;
+
+	*val = 0;
+	if (pos & 3)
+		return -EINVAL;
+
+	if (pci_pcie_capability_reg_implemented(dev, pos)) {
+		ret = pci_read_config_dword(dev, pci_pcie_cap(dev) + pos, val);
+		/*
+		 * Reset *val to 0 if pci_read_config_dword() fails, it may
+		 * have been written as 0xFFFFFFFF if hardware error happens
+		 * during pci_read_config_dword().
+		 */
+		if (ret)
+			*val = 0;
+	} else if (pos == PCI_EXP_SLTCTL &&
+		 pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) {
+		*val = PCI_EXP_SLTSTA_PDS;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(pci_pcie_capability_read_dword);
+
+int pci_pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val)
+{
+	if (pos & 1)
+		return -EINVAL;
+	else if (!pci_pcie_capability_reg_implemented(dev, pos))
+		return 0;
+
+	return pci_write_config_word(dev, pci_pcie_cap(dev) + pos, val);
+}
+EXPORT_SYMBOL(pci_pcie_capability_write_word);
+
+int pci_pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val)
+{
+	if (pos & 3)
+		return -EINVAL;
+	else if (!pci_pcie_capability_reg_implemented(dev, pos))
+		return 0;
+
+	return pci_write_config_dword(dev, pci_pcie_cap(dev) + pos, val);
+}
+EXPORT_SYMBOL(pci_pcie_capability_write_dword);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9807da5..a9b7605 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -816,6 +816,12 @@ static inline int pci_write_config_dword(const struct pci_dev *dev, int where,
 	return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
 }
 
+int pci_pcie_capability_read_word(struct pci_dev *dev, int where, u16 *val);
+int pci_pcie_capability_read_dword(struct pci_dev *dev, int where, u32 *val);
+int pci_pcie_capability_write_word(struct pci_dev *dev, int where, u16 val);
+int pci_pcie_capability_write_dword(struct pci_dev *dev, int where, u32 val);
+bool pci_pcie_capability_reg_implemented(struct pci_dev *dev, int where);
+
 /* user-space driven config access */
 int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
 int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index 53274bf..5300fdf 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -543,7 +543,9 @@
 #define  PCI_EXP_OBFF_MSGB_EN	0x4000	/* OBFF enable with Message type B */
 #define  PCI_EXP_OBFF_WAKE_EN	0x6000	/* OBFF using WAKE# signaling */
 #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2	44	/* v2 endpoints end here */
+#define PCI_EXP_LNKCAP2		44	/* Link Capabilities 2 */
 #define PCI_EXP_LNKCTL2		48	/* Link Control 2 */
+#define PCI_EXP_LNKSTA2		50	/* Link Status 2 */
 #define PCI_EXP_SLTCTL2		56	/* Slot Control 2 */
 
 /* Extended Capabilities (PCI-X 2.0 and Express) */
-- 
1.7.9.5


  parent reply	other threads:[~2012-07-24 16:33 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-24 16:31 [RFC PATCH v2 00/32] provide interfaces to access PCIe capabilities registers Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 01/32] PCI: add pcie_flags_reg into struct pci_dev to cache PCIe capabilities register Jiang Liu
2012-07-25 15:12   ` Don Dutile
2012-07-26 13:47     ` Yijing Wang
2012-07-24 16:31 ` [RFC PATCH v2 02/32] PCI: introduce pci_pcie_type(dev) to replace pci_dev->pcie_type Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 03/32] PCI: remove unused field pcie_type from struct pci_dev Jiang Liu
2012-07-24 16:31 ` Jiang Liu [this message]
2012-07-24 21:12   ` [RFC PATCH v2 04/32] PCI: add PCIe capabilities access functions to hide differences among PCIe specs Don Dutile
2012-07-29 16:22     ` Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 05/32] PCI/core: use PCIe capabilities access functions to simplify implementation Jiang Liu
2012-07-25 21:12   ` Don Dutile
2012-07-29  2:12     ` Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 06/32] PCI/hotplug: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 07/32] PCI/portdrv: " Jiang Liu
2012-07-25  5:51   ` Kaneshige, Kenji
2012-07-25  9:44     ` Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 08/32] PCI/pciehp: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 09/32] PCI/PME: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 10/32] PCI/AER: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 11/32] PCI/ASPM: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 12/32] PCI/ARM: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 13/32] PCI/MIPS: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 14/32] PCI/tile: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 15/32] PCI/r8169: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 16/32] PCI/broadcom: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 17/32] PCI/igb: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 18/32] PCI/vxge: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 19/32] PCI/mlx4: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 20/32] PCI/niu: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 21/32] PCI/myri10ge: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 22/32] PCI/chelsio: " Jiang Liu
2012-07-24 16:31 ` [RFC PATCH v2 23/32] PCI/atl1c: " Jiang Liu
2012-07-24 21:09 ` [RFC PATCH v2 00/32] provide interfaces to access PCIe capabilities registers Don Dutile
2012-07-29  2:26   ` Jiang Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1343147504-25891-5-git-send-email-jiang.liu@huawei.com \
    --to=liuj97@gmail.com \
    --cc=bhelgaas@google.com \
    --cc=ddutile@redhat.com \
    --cc=izumi.taku@jp.fujitsu.com \
    --cc=jiang.liu@huawei.com \
    --cc=kaneshige.kenji@jp.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=rjw@sisk.pl \
    --cc=wangyijing@huawei.com \
    --cc=yinghai@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).