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>
This commit is contained in:
@@ -207,6 +207,8 @@ enum pci_bar_type {
|
|||||||
pci_bar_mem64, /* A 64-bit memory BAR */
|
pci_bar_mem64, /* A 64-bit memory BAR */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *pl,
|
||||||
|
int crs_timeout);
|
||||||
extern int pci_setup_device(struct pci_dev *dev);
|
extern int pci_setup_device(struct pci_dev *dev);
|
||||||
extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
||||||
struct resource *res, unsigned int reg);
|
struct resource *res, unsigned int reg);
|
||||||
|
@@ -1118,6 +1118,42 @@ struct pci_dev *alloc_pci_dev(void)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(alloc_pci_dev);
|
EXPORT_SYMBOL(alloc_pci_dev);
|
||||||
|
|
||||||
|
bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l,
|
||||||
|
int crs_timeout)
|
||||||
|
{
|
||||||
|
int delay = 1;
|
||||||
|
|
||||||
|
if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* some broken boards return 0 or ~0 if a slot is empty: */
|
||||||
|
if (*l == 0xffffffff || *l == 0x00000000 ||
|
||||||
|
*l == 0x0000ffff || *l == 0xffff0000)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Configuration request Retry Status */
|
||||||
|
while (*l == 0xffff0001) {
|
||||||
|
if (!crs_timeout)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
msleep(delay);
|
||||||
|
delay *= 2;
|
||||||
|
if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))
|
||||||
|
return false;
|
||||||
|
/* Card hasn't responded in 60 seconds? Must be stuck. */
|
||||||
|
if (delay > crs_timeout) {
|
||||||
|
printk(KERN_WARNING "pci %04x:%02x:%02x.%d: not "
|
||||||
|
"responding\n", pci_domain_nr(bus),
|
||||||
|
bus->number, PCI_SLOT(devfn),
|
||||||
|
PCI_FUNC(devfn));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(pci_bus_read_dev_vendor_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the config data for a PCI device, sanity-check it
|
* Read the config data for a PCI device, sanity-check it
|
||||||
* and fill in the dev structure...
|
* and fill in the dev structure...
|
||||||
@@ -1126,32 +1162,10 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
|
|||||||
{
|
{
|
||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
u32 l;
|
u32 l;
|
||||||
int delay = 1;
|
|
||||||
|
|
||||||
if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
|
if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* some broken boards return 0 or ~0 if a slot is empty: */
|
|
||||||
if (l == 0xffffffff || l == 0x00000000 ||
|
|
||||||
l == 0x0000ffff || l == 0xffff0000)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Configuration request Retry Status */
|
|
||||||
while (l == 0xffff0001) {
|
|
||||||
msleep(delay);
|
|
||||||
delay *= 2;
|
|
||||||
if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
|
|
||||||
return NULL;
|
|
||||||
/* Card hasn't responded in 60 seconds? Must be stuck. */
|
|
||||||
if (delay > 60 * 1000) {
|
|
||||||
printk(KERN_WARNING "pci %04x:%02x:%02x.%d: not "
|
|
||||||
"responding\n", pci_domain_nr(bus),
|
|
||||||
bus->number, PCI_SLOT(devfn),
|
|
||||||
PCI_FUNC(devfn));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dev = alloc_pci_dev();
|
dev = alloc_pci_dev();
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Reference in New Issue
Block a user