Commit 84e0faa0 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Adam Belay

[PATCH] PCI: Fix pci_bus_find_capability()

pci_bus_find_capability() is currently broken.  It checks the wrong
device's hdr_type for being a cardbus bridge or not.  This patch pulls
the guts of pci_bus_find_capability() and pci_find_capability() into a
new function __pci_bus_find_cap() and changes these two functions to
call it.
parent 2d130cd0
...@@ -67,6 +67,39 @@ pci_max_busnr(void) ...@@ -67,6 +67,39 @@ pci_max_busnr(void)
return max; return max;
} }
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;
pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
if (!(status & PCI_STATUS_CAP_LIST))
return 0;
switch (hdr_type) {
case PCI_HEADER_TYPE_NORMAL:
case PCI_HEADER_TYPE_BRIDGE:
pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos);
break;
case PCI_HEADER_TYPE_CARDBUS:
pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos);
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;
}
/** /**
* pci_find_capability - query for devices' capabilities * pci_find_capability - query for devices' capabilities
* @dev: PCI device to query * @dev: PCI device to query
...@@ -94,34 +127,7 @@ pci_max_busnr(void) ...@@ -94,34 +127,7 @@ pci_max_busnr(void)
int int
pci_find_capability(struct pci_dev *dev, int cap) pci_find_capability(struct pci_dev *dev, int cap)
{ {
u16 status; return __pci_bus_find_cap(dev->bus, dev->devfn, dev->hdr_type, cap);
u8 pos, id;
int ttl = 48;
pci_read_config_word(dev, PCI_STATUS, &status);
if (!(status & PCI_STATUS_CAP_LIST))
return 0;
switch (dev->hdr_type) {
case PCI_HEADER_TYPE_NORMAL:
case PCI_HEADER_TYPE_BRIDGE:
pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos);
break;
case PCI_HEADER_TYPE_CARDBUS:
pci_read_config_byte(dev, PCI_CB_CAPABILITY_LIST, &pos);
break;
default:
return 0;
}
while (ttl-- && pos >= 0x40) {
pos &= ~3;
pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id);
if (id == 0xff)
break;
if (id == cap)
return pos;
pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos);
}
return 0;
} }
/** /**
...@@ -139,35 +145,11 @@ pci_find_capability(struct pci_dev *dev, int cap) ...@@ -139,35 +145,11 @@ pci_find_capability(struct pci_dev *dev, int cap)
*/ */
int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap) int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
{ {
u16 status; u8 hdr_type;
u8 pos, id;
int ttl = 48;
struct pci_dev *dev = bus->self;
pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type);
if (!(status & PCI_STATUS_CAP_LIST))
return 0; return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap);
switch (dev->hdr_type) {
case PCI_HEADER_TYPE_NORMAL:
case PCI_HEADER_TYPE_BRIDGE:
pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos);
break;
case PCI_HEADER_TYPE_CARDBUS:
pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos);
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;
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment