diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2005-11-02 10:40:50 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-11-02 10:40:50 -0800 |
commit | 64b3970c3dce724cffdb06e990344dd75dc50f9c (patch) | |
tree | f170aec229c53b1fe71ea8f950ba12708ee5e549 /pci | |
parent | 42e1a3772cffc1ff4b2ae97ce5738992138e8970 (diff) | |
download | patches-64b3970c3dce724cffdb06e990344dd75dc50f9c.tar.gz |
added a pci patch
Diffstat (limited to 'pci')
-rw-r--r-- | pci/pci_find_next_capability.patch | 129 |
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; } + |