aboutsummaryrefslogtreecommitdiffstats
path: root/pci
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-11-02 10:40:50 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2005-11-02 10:40:50 -0800
commit64b3970c3dce724cffdb06e990344dd75dc50f9c (patch)
treef170aec229c53b1fe71ea8f950ba12708ee5e549 /pci
parent42e1a3772cffc1ff4b2ae97ce5738992138e8970 (diff)
downloadpatches-64b3970c3dce724cffdb06e990344dd75dc50f9c.tar.gz
added a pci patch
Diffstat (limited to 'pci')
-rw-r--r--pci/pci_find_next_capability.patch129
1 files changed, 129 insertions, 0 deletions
diff --git a/pci/pci_find_next_capability.patch b/pci/pci_find_next_capability.patch
new file mode 100644
index 0000000000000..93fd5b3e991b0
--- /dev/null
+++ b/pci/pci_find_next_capability.patch
@@ -0,0 +1,129 @@
+From owner-linux-pci@atrey.karlin.mff.cuni.cz Fri Oct 28 17:42:52 2005
+To: gregkh@suse.de
+Subject: PCI: add pci_find_next_capability()
+From: Roland Dreier <rolandd@cisco.com>
+Date: Fri, 28 Oct 2005 17:35:34 -0700
+Message-ID: <52u0f1p3c9.fsf@cisco.com>
+
+Some devices have more than one capability of the same type. For
+example, the PCI header for the PathScale InfiniPath looks like:
+
+ 04:01.0 InfiniBand: Unknown device 1fc1:000d (rev 02)
+ Subsystem: Unknown device 1fc1:000d
+ Flags: bus master, fast devsel, latency 0, IRQ 193
+ Memory at fea00000 (64-bit, non-prefetchable) [size=2M]
+ Capabilities: [c0] HyperTransport: Slave or Primary Interface
+ Capabilities: [f8] HyperTransport: Interrupt Discovery and Configuration
+
+There are _two_ HyperTransport capabilities, and the PathScale driver
+wants to look at both of them.
+
+The current pci_find_capability() API doesn't work for this, since it
+only allows us to get to the first capability of a given type. The
+patch below introduces a new pci_find_next_capability(), which can be
+used in a loop like
+
+ for (pos = pci_find_capability(pdev, <ID>);
+ pos;
+ pos = pci_find_next_capability(pdev, pos, <ID>)) {
+ /* ... */
+ }
+
+Signed-off-by: Roland Dreier <rolandd@cisco.com>
+Signed-off-by: Matthew Wilcox <matthew@wil.cx>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+ drivers/pci/pci.c | 46 ++++++++++++++++++++++++++++++++--------------
+ include/linux/pci.h | 2 ++
+ 2 files changed, 34 insertions(+), 14 deletions(-)
+
+--- gregkh-2.6.orig/drivers/pci/pci.c 2005-11-02 09:26:01.000000000 -0800
++++ gregkh-2.6/drivers/pci/pci.c 2005-11-02 10:35:48.000000000 -0800
+@@ -63,11 +63,38 @@
+ return max;
+ }
+
++static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap)
++{
++ u8 id;
++ int ttl = 48;
++
++ while (ttl--) {
++ pci_bus_read_config_byte(bus, devfn, pos, &pos);
++ if (pos < 0x40)
++ break;
++ pos &= ~3;
++ pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID,
++ &id);
++ if (id == 0xff)
++ break;
++ if (id == cap)
++ return pos;
++ pos += PCI_CAP_LIST_NEXT;
++ }
++ return 0;
++}
++
++int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
++{
++ return __pci_find_next_cap(dev->bus, dev->devfn,
++ pos + PCI_CAP_LIST_NEXT, cap);
++}
++EXPORT_SYMBOL_GPL(pci_find_next_capability);
++
+ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap)
+ {
+ u16 status;
+- u8 pos, id;
+- int ttl = 48;
++ u8 pos;
+
+ pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
+ if (!(status & PCI_STATUS_CAP_LIST))
+@@ -76,24 +103,15 @@
+ switch (hdr_type) {
+ case PCI_HEADER_TYPE_NORMAL:
+ case PCI_HEADER_TYPE_BRIDGE:
+- pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos);
++ pos = PCI_CAPABILITY_LIST;
+ break;
+ case PCI_HEADER_TYPE_CARDBUS:
+- pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos);
++ pos = PCI_CB_CAPABILITY_LIST;
+ break;
+ default:
+ return 0;
+ }
+- while (ttl-- && pos >= 0x40) {
+- pos &= ~3;
+- pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id);
+- if (id == 0xff)
+- break;
+- if (id == cap)
+- return pos;
+- pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos);
+- }
+- return 0;
++ return __pci_find_next_cap(bus, devfn, pos, cap);
+ }
+
+ /**
+--- gregkh-2.6.orig/include/linux/pci.h 2005-11-02 09:25:08.000000000 -0800
++++ gregkh-2.6/include/linux/pci.h 2005-11-02 10:35:48.000000000 -0800
+@@ -338,6 +338,7 @@
+ struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int device, const struct pci_dev *from);
+ struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
+ 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);
+ struct pci_bus * pci_find_next_bus(const struct pci_bus *from);
+
+@@ -550,6 +551,7 @@
+ static inline int pci_register_driver(struct pci_driver *drv) { return 0;}
+ static inline void pci_unregister_driver(struct pci_driver *drv) { }
+ static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
++static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; }
+ static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; }
+ static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; }
+