diff options
author | Yinghai Lu <yinghai@kernel.org> | 2012-01-27 13:55:10 -0500 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2012-02-14 11:44:59 -0500 |
commit | efdc87dab1cdf25ba631181ac0ead3fb2023dd10 (patch) | |
tree | f55b7d0b2e9bbfd9dd280c85166aef423bf68d75 /drivers/pci/probe.c | |
parent | ac205b7bb72fa4227d2e79979bbe2b4687cdf44d (diff) |
PCI: Separate pci_bus_read_dev_vendor_id from pci_scan_device
We can reuse it for pciehp probing.
-v2: according to Kenji, fix crs timeout checking, and export the function
for later use when pciehp is compiled as a module.
Suggested-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index aad7d0ff6b08..9f2ff8c5dc2f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -1118,40 +1118,54 @@ struct pci_dev *alloc_pci_dev(void) | |||
1118 | } | 1118 | } |
1119 | EXPORT_SYMBOL(alloc_pci_dev); | 1119 | EXPORT_SYMBOL(alloc_pci_dev); |
1120 | 1120 | ||
1121 | /* | 1121 | bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l, |
1122 | * Read the config data for a PCI device, sanity-check it | 1122 | int crs_timeout) |
1123 | * and fill in the dev structure... | ||
1124 | */ | ||
1125 | static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) | ||
1126 | { | 1123 | { |
1127 | struct pci_dev *dev; | ||
1128 | u32 l; | ||
1129 | int delay = 1; | 1124 | int delay = 1; |
1130 | 1125 | ||
1131 | if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l)) | 1126 | if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l)) |
1132 | return NULL; | 1127 | return false; |
1133 | 1128 | ||
1134 | /* some broken boards return 0 or ~0 if a slot is empty: */ | 1129 | /* some broken boards return 0 or ~0 if a slot is empty: */ |
1135 | if (l == 0xffffffff || l == 0x00000000 || | 1130 | if (*l == 0xffffffff || *l == 0x00000000 || |
1136 | l == 0x0000ffff || l == 0xffff0000) | 1131 | *l == 0x0000ffff || *l == 0xffff0000) |
1137 | return NULL; | 1132 | return false; |
1138 | 1133 | ||
1139 | /* Configuration request Retry Status */ | 1134 | /* Configuration request Retry Status */ |
1140 | while (l == 0xffff0001) { | 1135 | while (*l == 0xffff0001) { |
1136 | if (!crs_timeout) | ||
1137 | return false; | ||
1138 | |||
1141 | msleep(delay); | 1139 | msleep(delay); |
1142 | delay *= 2; | 1140 | delay *= 2; |
1143 | if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l)) | 1141 | if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l)) |
1144 | return NULL; | 1142 | return false; |
1145 | /* Card hasn't responded in 60 seconds? Must be stuck. */ | 1143 | /* Card hasn't responded in 60 seconds? Must be stuck. */ |
1146 | if (delay > 60 * 1000) { | 1144 | if (delay > crs_timeout) { |
1147 | printk(KERN_WARNING "pci %04x:%02x:%02x.%d: not " | 1145 | printk(KERN_WARNING "pci %04x:%02x:%02x.%d: not " |
1148 | "responding\n", pci_domain_nr(bus), | 1146 | "responding\n", pci_domain_nr(bus), |
1149 | bus->number, PCI_SLOT(devfn), | 1147 | bus->number, PCI_SLOT(devfn), |
1150 | PCI_FUNC(devfn)); | 1148 | PCI_FUNC(devfn)); |
1151 | return NULL; | 1149 | return false; |
1152 | } | 1150 | } |
1153 | } | 1151 | } |
1154 | 1152 | ||
1153 | return true; | ||
1154 | } | ||
1155 | EXPORT_SYMBOL(pci_bus_read_dev_vendor_id); | ||
1156 | |||
1157 | /* | ||
1158 | * Read the config data for a PCI device, sanity-check it | ||
1159 | * and fill in the dev structure... | ||
1160 | */ | ||
1161 | static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) | ||
1162 | { | ||
1163 | struct pci_dev *dev; | ||
1164 | u32 l; | ||
1165 | |||
1166 | if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000)) | ||
1167 | return NULL; | ||
1168 | |||
1155 | dev = alloc_pci_dev(); | 1169 | dev = alloc_pci_dev(); |
1156 | if (!dev) | 1170 | if (!dev) |
1157 | return NULL; | 1171 | return NULL; |