Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit efdc87da authored by Yinghai Lu's avatar Yinghai Lu Committed by Jesse Barnes
Browse files

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: default avatarMatthew Wilcox <matthew@wil.cx>
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent ac205b7b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -207,6 +207,8 @@ enum pci_bar_type {
	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_read_base(struct pci_dev *dev, enum pci_bar_type type,
				struct resource *res, unsigned int reg);
+31 −17
Original line number Diff line number Diff line
@@ -1118,40 +1118,54 @@ struct pci_dev *alloc_pci_dev(void)
}
EXPORT_SYMBOL(alloc_pci_dev);

/*
 * Read the config data for a PCI device, sanity-check it
 * and fill in the dev structure...
 */
static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l,
				 int crs_timeout)
{
	struct pci_dev *dev;
	u32 l;
	int delay = 1;

	if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
		return NULL;
	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 NULL;
	if (*l == 0xffffffff || *l == 0x00000000 ||
	    *l == 0x0000ffff || *l == 0xffff0000)
		return false;

	/* Configuration request Retry Status */
	while (l == 0xffff0001) {
	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 NULL;
		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 > 60 * 1000) {
		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 NULL;
			return false;
		}
	}

	return true;
}
EXPORT_SYMBOL(pci_bus_read_dev_vendor_id);

/*
 * Read the config data for a PCI device, sanity-check it
 * and fill in the dev structure...
 */
static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
{
	struct pci_dev *dev;
	u32 l;

	if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000))
		return NULL;

	dev = alloc_pci_dev();
	if (!dev)
		return NULL;