All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bjorn Helgaas <bhelgaas@google.com>
To: linux-pci@vger.kernel.org
Subject: [PATCH 1/2] PCI: add pci_find_next_ext_capability()
Date: Fri, 13 Jul 2012 15:57:45 -0600	[thread overview]
Message-ID: <20120713215745.21756.79478.stgit@bhelgaas.mtv.corp.google.com> (raw)
In-Reply-To: <20120713215258.21756.42132.stgit@bhelgaas.mtv.corp.google.com>

Some extended capabilities, e.g., the vendor-specific capability, can
occur several times.  The existing pci_find_ext_capability() always finds
the first occurrence.  This adds pci_find_next_ext_capability(), which can
iterate through all of them.

Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 drivers/pci/pci.c   |   40 ++++++++++++++++++++++++++++++----------
 include/linux/pci.h |    3 +--
 2 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 447e834..fa0aa94 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -278,20 +278,17 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
 }
 
 /**
- * pci_find_ext_capability - Find an extended capability
+ * pci_find_next_ext_capability - Find an extended capability
  * @dev: PCI device to query
+ * @start: address at which to start looking (0 to start at beginning of list)
  * @cap: capability code
  *
- * Returns the address of the requested extended capability structure
+ * Returns the address of the next matching extended capability structure
  * within the device's PCI configuration space or 0 if the device does
- * not support it.  Possible values for @cap:
- *
- *  %PCI_EXT_CAP_ID_ERR		Advanced Error Reporting
- *  %PCI_EXT_CAP_ID_VC		Virtual Channel
- *  %PCI_EXT_CAP_ID_DSN		Device Serial Number
- *  %PCI_EXT_CAP_ID_PWR		Power Budgeting
+ * not support it.  Some capabilities can occur several times, e.g., the
+ * vendor-specific capability, and this provides a way to find them all.
  */
-int pci_find_ext_capability(struct pci_dev *dev, int cap)
+int pci_find_next_ext_capability(struct pci_dev *dev, int start, int cap)
 {
 	u32 header;
 	int ttl;
@@ -303,6 +300,9 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
 	if (dev->cfg_size <= PCI_CFG_SPACE_SIZE)
 		return 0;
 
+	if (start)
+		pos = start;
+
 	if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
 		return 0;
 
@@ -314,7 +314,7 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
 		return 0;
 
 	while (ttl-- > 0) {
-		if (PCI_EXT_CAP_ID(header) == cap)
+		if (PCI_EXT_CAP_ID(header) == cap && pos != start)
 			return pos;
 
 		pos = PCI_EXT_CAP_NEXT(header);
@@ -327,6 +327,26 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(pci_find_next_ext_capability);
+
+/**
+ * pci_find_ext_capability - Find an extended capability
+ * @dev: PCI device to query
+ * @cap: capability code
+ *
+ * Returns the address of the requested extended capability structure
+ * within the device's PCI configuration space or 0 if the device does
+ * not support it.  Possible values for @cap:
+ *
+ *  %PCI_EXT_CAP_ID_ERR		Advanced Error Reporting
+ *  %PCI_EXT_CAP_ID_VC		Virtual Channel
+ *  %PCI_EXT_CAP_ID_DSN		Device Serial Number
+ *  %PCI_EXT_CAP_ID_PWR		Power Budgeting
+ */
+int pci_find_ext_capability(struct pci_dev *dev, int cap)
+{
+	return pci_find_next_ext_capability(dev, 0, cap);
+}
 EXPORT_SYMBOL_GPL(pci_find_ext_capability);
 
 /**
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d8c379d..39d2fe0 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -714,8 +714,7 @@ enum pci_lost_interrupt_reason pci_lost_interrupt(struct pci_dev *dev);
 int pci_find_capability(struct pci_dev *dev, int cap);
 int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
 int pci_find_ext_capability(struct pci_dev *dev, int cap);
-int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
-				int cap);
+int pci_find_next_ext_capability(struct pci_dev *dev, int pos, int cap);
 int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
 int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
 struct pci_bus *pci_find_next_bus(const struct pci_bus *from);


  reply	other threads:[~2012-07-13 21:57 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-13 21:57 [PATCH 0/2] Infrastructure for Vendor-Specific extended capabilities Bjorn Helgaas
2012-07-13 21:57 ` Bjorn Helgaas [this message]
2012-07-13 21:57 ` [PATCH 2/2] PCI: add Vendor-Specific Extended Capability header info Bjorn Helgaas
2012-08-24 21:26 ` [PATCH 0/2] Infrastructure for Vendor-Specific extended capabilities Bjorn Helgaas

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=20120713215745.21756.79478.stgit@bhelgaas.mtv.corp.google.com \
    --to=bhelgaas@google.com \
    --cc=linux-pci@vger.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.