xref: /openbmc/linux/drivers/pci/pci-driver.c (revision 725522b5453dd680412f2b6463a988e4fd148757)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * drivers/pci/pci-driver.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  */
51da177e4SLinus Torvalds 
61da177e4SLinus Torvalds #include <linux/pci.h>
71da177e4SLinus Torvalds #include <linux/module.h>
81da177e4SLinus Torvalds #include <linux/init.h>
91da177e4SLinus Torvalds #include <linux/device.h>
10d42c6997SAndi Kleen #include <linux/mempolicy.h>
114e57b681STim Schmielau #include <linux/string.h>
124e57b681STim Schmielau #include <linux/slab.h>
138c65b4a6STim Schmielau #include <linux/sched.h>
141da177e4SLinus Torvalds #include "pci.h"
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds /*
171da177e4SLinus Torvalds  *  Registration of PCI drivers and handling of hot-pluggable devices.
181da177e4SLinus Torvalds  */
191da177e4SLinus Torvalds 
200f397f86SGreg Kroah-Hartman /* multithreaded probe logic */
210f397f86SGreg Kroah-Hartman static int pci_multithread_probe =
220f397f86SGreg Kroah-Hartman #ifdef CONFIG_PCI_MULTITHREAD_PROBE
230f397f86SGreg Kroah-Hartman 	1;
240f397f86SGreg Kroah-Hartman #else
250f397f86SGreg Kroah-Hartman 	0;
260f397f86SGreg Kroah-Hartman #endif
270f397f86SGreg Kroah-Hartman __module_param_call("", pci_multithread_probe, param_set_bool, param_get_bool, &pci_multithread_probe, 0644);
280f397f86SGreg Kroah-Hartman 
290f397f86SGreg Kroah-Hartman 
301da177e4SLinus Torvalds /*
311da177e4SLinus Torvalds  * Dynamic device IDs are disabled for !CONFIG_HOTPLUG
321da177e4SLinus Torvalds  */
331da177e4SLinus Torvalds 
3475865858SGreg Kroah-Hartman struct pci_dynid {
3575865858SGreg Kroah-Hartman 	struct list_head node;
3675865858SGreg Kroah-Hartman 	struct pci_device_id id;
3775865858SGreg Kroah-Hartman };
381da177e4SLinus Torvalds 
393d3c2ae1SGreg KH #ifdef CONFIG_HOTPLUG
403d3c2ae1SGreg KH 
411da177e4SLinus Torvalds /**
428f7020d3SRandy Dunlap  * store_new_id - add a new PCI device ID to this driver and re-probe devices
438f7020d3SRandy Dunlap  * @driver: target device driver
448f7020d3SRandy Dunlap  * @buf: buffer for scanning device ID data
458f7020d3SRandy Dunlap  * @count: input size
461da177e4SLinus Torvalds  *
471da177e4SLinus Torvalds  * Adds a new dynamic pci device ID to this driver,
481da177e4SLinus Torvalds  * and causes the driver to probe for all devices again.
491da177e4SLinus Torvalds  */
50f8eb1005SRandy Dunlap static ssize_t
511da177e4SLinus Torvalds store_new_id(struct device_driver *driver, const char *buf, size_t count)
521da177e4SLinus Torvalds {
5375865858SGreg Kroah-Hartman 	struct pci_dynid *dynid;
541da177e4SLinus Torvalds 	struct pci_driver *pdrv = to_pci_driver(driver);
551da177e4SLinus Torvalds 	__u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID,
561da177e4SLinus Torvalds 		subdevice=PCI_ANY_ID, class=0, class_mask=0;
571da177e4SLinus Torvalds 	unsigned long driver_data=0;
581da177e4SLinus Torvalds 	int fields=0;
59b19441afSGreg Kroah-Hartman 	int retval = 0;
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds 	fields = sscanf(buf, "%x %x %x %x %x %x %lux",
621da177e4SLinus Torvalds 			&vendor, &device, &subvendor, &subdevice,
631da177e4SLinus Torvalds 			&class, &class_mask, &driver_data);
641da177e4SLinus Torvalds 	if (fields < 0)
651da177e4SLinus Torvalds 		return -EINVAL;
661da177e4SLinus Torvalds 
67f5afe806SEric Sesterhenn 	dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
681da177e4SLinus Torvalds 	if (!dynid)
691da177e4SLinus Torvalds 		return -ENOMEM;
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds 	INIT_LIST_HEAD(&dynid->node);
721da177e4SLinus Torvalds 	dynid->id.vendor = vendor;
731da177e4SLinus Torvalds 	dynid->id.device = device;
741da177e4SLinus Torvalds 	dynid->id.subvendor = subvendor;
751da177e4SLinus Torvalds 	dynid->id.subdevice = subdevice;
761da177e4SLinus Torvalds 	dynid->id.class = class;
771da177e4SLinus Torvalds 	dynid->id.class_mask = class_mask;
781da177e4SLinus Torvalds 	dynid->id.driver_data = pdrv->dynids.use_driver_data ?
791da177e4SLinus Torvalds 		driver_data : 0UL;
801da177e4SLinus Torvalds 
811da177e4SLinus Torvalds 	spin_lock(&pdrv->dynids.lock);
821da177e4SLinus Torvalds 	list_add_tail(&pdrv->dynids.list, &dynid->node);
831da177e4SLinus Torvalds 	spin_unlock(&pdrv->dynids.lock);
841da177e4SLinus Torvalds 
851da177e4SLinus Torvalds 	if (get_driver(&pdrv->driver)) {
86b19441afSGreg Kroah-Hartman 		retval = driver_attach(&pdrv->driver);
871da177e4SLinus Torvalds 		put_driver(&pdrv->driver);
881da177e4SLinus Torvalds 	}
891da177e4SLinus Torvalds 
90b19441afSGreg Kroah-Hartman 	if (retval)
91b19441afSGreg Kroah-Hartman 		return retval;
921da177e4SLinus Torvalds 	return count;
931da177e4SLinus Torvalds }
941da177e4SLinus Torvalds static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds static void
971da177e4SLinus Torvalds pci_free_dynids(struct pci_driver *drv)
981da177e4SLinus Torvalds {
9975865858SGreg Kroah-Hartman 	struct pci_dynid *dynid, *n;
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds 	spin_lock(&drv->dynids.lock);
10275865858SGreg Kroah-Hartman 	list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
1031da177e4SLinus Torvalds 		list_del(&dynid->node);
1041da177e4SLinus Torvalds 		kfree(dynid);
1051da177e4SLinus Torvalds 	}
1061da177e4SLinus Torvalds 	spin_unlock(&drv->dynids.lock);
1071da177e4SLinus Torvalds }
1081da177e4SLinus Torvalds 
1091da177e4SLinus Torvalds static int
1101da177e4SLinus Torvalds pci_create_newid_file(struct pci_driver *drv)
1111da177e4SLinus Torvalds {
1121da177e4SLinus Torvalds 	int error = 0;
1131da177e4SLinus Torvalds 	if (drv->probe != NULL)
1141da177e4SLinus Torvalds 		error = sysfs_create_file(&drv->driver.kobj,
1151da177e4SLinus Torvalds 					  &driver_attr_new_id.attr);
1161da177e4SLinus Torvalds 	return error;
1171da177e4SLinus Torvalds }
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds #else /* !CONFIG_HOTPLUG */
1201da177e4SLinus Torvalds static inline void pci_free_dynids(struct pci_driver *drv) {}
1211da177e4SLinus Torvalds static inline int pci_create_newid_file(struct pci_driver *drv)
1221da177e4SLinus Torvalds {
1231da177e4SLinus Torvalds 	return 0;
1241da177e4SLinus Torvalds }
1251da177e4SLinus Torvalds #endif
1261da177e4SLinus Torvalds 
1271da177e4SLinus Torvalds /**
12875865858SGreg Kroah-Hartman  * pci_match_id - See if a pci device matches a given pci_id table
1291da177e4SLinus Torvalds  * @ids: array of PCI device id structures to search in
13075865858SGreg Kroah-Hartman  * @dev: the PCI device structure to match against.
1311da177e4SLinus Torvalds  *
1321da177e4SLinus Torvalds  * Used by a driver to check whether a PCI device present in the
1331da177e4SLinus Torvalds  * system is in its list of supported devices.  Returns the matching
1341da177e4SLinus Torvalds  * pci_device_id structure or %NULL if there is no match.
13575865858SGreg Kroah-Hartman  *
13675865858SGreg Kroah-Hartman  * Depreciated, don't use this as it will not catch any dynamic ids
13775865858SGreg Kroah-Hartman  * that a driver might want to check for.
1381da177e4SLinus Torvalds  */
13975865858SGreg Kroah-Hartman const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
14075865858SGreg Kroah-Hartman 					 struct pci_dev *dev)
1411da177e4SLinus Torvalds {
14275865858SGreg Kroah-Hartman 	if (ids) {
1431da177e4SLinus Torvalds 		while (ids->vendor || ids->subvendor || ids->class_mask) {
1441da177e4SLinus Torvalds 			if (pci_match_one_device(ids, dev))
1451da177e4SLinus Torvalds 				return ids;
1461da177e4SLinus Torvalds 			ids++;
1471da177e4SLinus Torvalds 		}
14875865858SGreg Kroah-Hartman 	}
1491da177e4SLinus Torvalds 	return NULL;
1501da177e4SLinus Torvalds }
1511da177e4SLinus Torvalds 
1521da177e4SLinus Torvalds /**
153ae9608afSRandy Dunlap  * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure
15475865858SGreg Kroah-Hartman  * @drv: the PCI driver to match against
15539ba487fSHenrik Kretzschmar  * @dev: the PCI device structure to match against
1561da177e4SLinus Torvalds  *
15775865858SGreg Kroah-Hartman  * Used by a driver to check whether a PCI device present in the
15875865858SGreg Kroah-Hartman  * system is in its list of supported devices.  Returns the matching
15975865858SGreg Kroah-Hartman  * pci_device_id structure or %NULL if there is no match.
1601da177e4SLinus Torvalds  */
16175865858SGreg Kroah-Hartman const struct pci_device_id *pci_match_device(struct pci_driver *drv,
16275865858SGreg Kroah-Hartman 					     struct pci_dev *dev)
1631da177e4SLinus Torvalds {
16475865858SGreg Kroah-Hartman 	struct pci_dynid *dynid;
1651da177e4SLinus Torvalds 
1667461b60aSRussell King 	/* Look at the dynamic ids first, before the static ones */
16775865858SGreg Kroah-Hartman 	spin_lock(&drv->dynids.lock);
16875865858SGreg Kroah-Hartman 	list_for_each_entry(dynid, &drv->dynids.list, node) {
16975865858SGreg Kroah-Hartman 		if (pci_match_one_device(&dynid->id, dev)) {
17075865858SGreg Kroah-Hartman 			spin_unlock(&drv->dynids.lock);
17175865858SGreg Kroah-Hartman 			return &dynid->id;
1721da177e4SLinus Torvalds 		}
17375865858SGreg Kroah-Hartman 	}
17475865858SGreg Kroah-Hartman 	spin_unlock(&drv->dynids.lock);
1757461b60aSRussell King 
1767461b60aSRussell King 	return pci_match_id(drv->id_table, dev);
1771da177e4SLinus Torvalds }
1781da177e4SLinus Torvalds 
179d42c6997SAndi Kleen static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
180d42c6997SAndi Kleen 			  const struct pci_device_id *id)
181d42c6997SAndi Kleen {
182d42c6997SAndi Kleen 	int error;
183d42c6997SAndi Kleen #ifdef CONFIG_NUMA
184d42c6997SAndi Kleen 	/* Execute driver initialization on node where the
185d42c6997SAndi Kleen 	   device's bus is attached to.  This way the driver likely
186d42c6997SAndi Kleen 	   allocates its local memory on the right node without
187d42c6997SAndi Kleen 	   any need to change it. */
188d42c6997SAndi Kleen 	struct mempolicy *oldpol;
189d42c6997SAndi Kleen 	cpumask_t oldmask = current->cpus_allowed;
190d42c6997SAndi Kleen 	int node = pcibus_to_node(dev->bus);
191d42c6997SAndi Kleen 	if (node >= 0 && node_online(node))
192d42c6997SAndi Kleen 	    set_cpus_allowed(current, node_to_cpumask(node));
193d42c6997SAndi Kleen 	/* And set default memory allocation policy */
194d42c6997SAndi Kleen 	oldpol = current->mempolicy;
195d42c6997SAndi Kleen 	current->mempolicy = &default_policy;
196d42c6997SAndi Kleen 	mpol_get(current->mempolicy);
197d42c6997SAndi Kleen #endif
198d42c6997SAndi Kleen 	error = drv->probe(dev, id);
199d42c6997SAndi Kleen #ifdef CONFIG_NUMA
200d42c6997SAndi Kleen 	set_cpus_allowed(current, oldmask);
201d42c6997SAndi Kleen 	mpol_free(current->mempolicy);
202d42c6997SAndi Kleen 	current->mempolicy = oldpol;
203d42c6997SAndi Kleen #endif
204d42c6997SAndi Kleen 	return error;
205d42c6997SAndi Kleen }
206d42c6997SAndi Kleen 
2071da177e4SLinus Torvalds /**
2081da177e4SLinus Torvalds  * __pci_device_probe()
2098f7020d3SRandy Dunlap  * @drv: driver to call to check if it wants the PCI device
2108f7020d3SRandy Dunlap  * @pci_dev: PCI device being probed
2111da177e4SLinus Torvalds  *
2121da177e4SLinus Torvalds  * returns 0 on success, else error.
2131da177e4SLinus Torvalds  * side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
2141da177e4SLinus Torvalds  */
2151da177e4SLinus Torvalds static int
2161da177e4SLinus Torvalds __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
2171da177e4SLinus Torvalds {
21875865858SGreg Kroah-Hartman 	const struct pci_device_id *id;
2191da177e4SLinus Torvalds 	int error = 0;
2201da177e4SLinus Torvalds 
2211da177e4SLinus Torvalds 	if (!pci_dev->driver && drv->probe) {
22275865858SGreg Kroah-Hartman 		error = -ENODEV;
22375865858SGreg Kroah-Hartman 
22475865858SGreg Kroah-Hartman 		id = pci_match_device(drv, pci_dev);
22575865858SGreg Kroah-Hartman 		if (id)
226d42c6997SAndi Kleen 			error = pci_call_probe(drv, pci_dev, id);
22775865858SGreg Kroah-Hartman 		if (error >= 0) {
22875865858SGreg Kroah-Hartman 			pci_dev->driver = drv;
22975865858SGreg Kroah-Hartman 			error = 0;
23075865858SGreg Kroah-Hartman 		}
2311da177e4SLinus Torvalds 	}
2321da177e4SLinus Torvalds 	return error;
2331da177e4SLinus Torvalds }
2341da177e4SLinus Torvalds 
2351da177e4SLinus Torvalds static int pci_device_probe(struct device * dev)
2361da177e4SLinus Torvalds {
2371da177e4SLinus Torvalds 	int error = 0;
2381da177e4SLinus Torvalds 	struct pci_driver *drv;
2391da177e4SLinus Torvalds 	struct pci_dev *pci_dev;
2401da177e4SLinus Torvalds 
2411da177e4SLinus Torvalds 	drv = to_pci_driver(dev->driver);
2421da177e4SLinus Torvalds 	pci_dev = to_pci_dev(dev);
2431da177e4SLinus Torvalds 	pci_dev_get(pci_dev);
2441da177e4SLinus Torvalds 	error = __pci_device_probe(drv, pci_dev);
2451da177e4SLinus Torvalds 	if (error)
2461da177e4SLinus Torvalds 		pci_dev_put(pci_dev);
2471da177e4SLinus Torvalds 
2481da177e4SLinus Torvalds 	return error;
2491da177e4SLinus Torvalds }
2501da177e4SLinus Torvalds 
2511da177e4SLinus Torvalds static int pci_device_remove(struct device * dev)
2521da177e4SLinus Torvalds {
2531da177e4SLinus Torvalds 	struct pci_dev * pci_dev = to_pci_dev(dev);
2541da177e4SLinus Torvalds 	struct pci_driver * drv = pci_dev->driver;
2551da177e4SLinus Torvalds 
2561da177e4SLinus Torvalds 	if (drv) {
2571da177e4SLinus Torvalds 		if (drv->remove)
2581da177e4SLinus Torvalds 			drv->remove(pci_dev);
2591da177e4SLinus Torvalds 		pci_dev->driver = NULL;
2601da177e4SLinus Torvalds 	}
2611da177e4SLinus Torvalds 
2621da177e4SLinus Torvalds 	/*
2632449e06aSShaohua Li 	 * If the device is still on, set the power state as "unknown",
2642449e06aSShaohua Li 	 * since it might change by the next time we load the driver.
2652449e06aSShaohua Li 	 */
2662449e06aSShaohua Li 	if (pci_dev->current_state == PCI_D0)
2672449e06aSShaohua Li 		pci_dev->current_state = PCI_UNKNOWN;
2682449e06aSShaohua Li 
2692449e06aSShaohua Li 	/*
2701da177e4SLinus Torvalds 	 * We would love to complain here if pci_dev->is_enabled is set, that
2711da177e4SLinus Torvalds 	 * the driver should have called pci_disable_device(), but the
2721da177e4SLinus Torvalds 	 * unfortunate fact is there are too many odd BIOS and bridge setups
2731da177e4SLinus Torvalds 	 * that don't like drivers doing that all of the time.
2741da177e4SLinus Torvalds 	 * Oh well, we can dream of sane hardware when we sleep, no matter how
2751da177e4SLinus Torvalds 	 * horrible the crap we have to deal with is when we are awake...
2761da177e4SLinus Torvalds 	 */
2771da177e4SLinus Torvalds 
2781da177e4SLinus Torvalds 	pci_dev_put(pci_dev);
2791da177e4SLinus Torvalds 	return 0;
2801da177e4SLinus Torvalds }
2811da177e4SLinus Torvalds 
2821da177e4SLinus Torvalds static int pci_device_suspend(struct device * dev, pm_message_t state)
2831da177e4SLinus Torvalds {
2841da177e4SLinus Torvalds 	struct pci_dev * pci_dev = to_pci_dev(dev);
2851da177e4SLinus Torvalds 	struct pci_driver * drv = pci_dev->driver;
2861da177e4SLinus Torvalds 	int i = 0;
2871da177e4SLinus Torvalds 
28802669492SAndrew Morton 	if (drv && drv->suspend) {
2891da177e4SLinus Torvalds 		i = drv->suspend(pci_dev, state);
29002669492SAndrew Morton 		suspend_report_result(drv->suspend, i);
29102669492SAndrew Morton 	} else {
2921da177e4SLinus Torvalds 		pci_save_state(pci_dev);
2932449e06aSShaohua Li 		/*
2942449e06aSShaohua Li 		 * mark its power state as "unknown", since we don't know if
2952449e06aSShaohua Li 		 * e.g. the BIOS will change its device state when we suspend.
2962449e06aSShaohua Li 		 */
2972449e06aSShaohua Li 		if (pci_dev->current_state == PCI_D0)
2982449e06aSShaohua Li 			pci_dev->current_state = PCI_UNKNOWN;
29902669492SAndrew Morton 	}
3001da177e4SLinus Torvalds 	return i;
3011da177e4SLinus Torvalds }
3021da177e4SLinus Torvalds 
303cbd69dbbSLinus Torvalds static int pci_device_suspend_late(struct device * dev, pm_message_t state)
304cbd69dbbSLinus Torvalds {
305cbd69dbbSLinus Torvalds 	struct pci_dev * pci_dev = to_pci_dev(dev);
306cbd69dbbSLinus Torvalds 	struct pci_driver * drv = pci_dev->driver;
307cbd69dbbSLinus Torvalds 	int i = 0;
308cbd69dbbSLinus Torvalds 
309cbd69dbbSLinus Torvalds 	if (drv && drv->suspend_late) {
310cbd69dbbSLinus Torvalds 		i = drv->suspend_late(pci_dev, state);
311cbd69dbbSLinus Torvalds 		suspend_report_result(drv->suspend_late, i);
312cbd69dbbSLinus Torvalds 	}
313cbd69dbbSLinus Torvalds 	return i;
314cbd69dbbSLinus Torvalds }
3151da177e4SLinus Torvalds 
3161da177e4SLinus Torvalds /*
3171da177e4SLinus Torvalds  * Default resume method for devices that have no driver provided resume,
3181da177e4SLinus Torvalds  * or not even a driver at all.
3191da177e4SLinus Torvalds  */
3208d92bc22SJean Delvare static int pci_default_resume(struct pci_dev *pci_dev)
3211da177e4SLinus Torvalds {
3228d92bc22SJean Delvare 	int retval = 0;
32395a62965SGreg Kroah-Hartman 
3241da177e4SLinus Torvalds 	/* restore the PCI config space */
3251da177e4SLinus Torvalds 	pci_restore_state(pci_dev);
3261da177e4SLinus Torvalds 	/* if the device was enabled before suspend, reenable */
327bae94d02SInaky Perez-Gonzalez 	if (atomic_read(&pci_dev->enable_cnt))
328bae94d02SInaky Perez-Gonzalez 		retval = __pci_enable_device(pci_dev);
3291da177e4SLinus Torvalds 	/* if the device was busmaster before the suspend, make it busmaster again */
3301da177e4SLinus Torvalds 	if (pci_dev->is_busmaster)
3311da177e4SLinus Torvalds 		pci_set_master(pci_dev);
3328d92bc22SJean Delvare 
3338d92bc22SJean Delvare 	return retval;
3341da177e4SLinus Torvalds }
3351da177e4SLinus Torvalds 
3361da177e4SLinus Torvalds static int pci_device_resume(struct device * dev)
3371da177e4SLinus Torvalds {
3388d92bc22SJean Delvare 	int error;
3391da177e4SLinus Torvalds 	struct pci_dev * pci_dev = to_pci_dev(dev);
3401da177e4SLinus Torvalds 	struct pci_driver * drv = pci_dev->driver;
3411da177e4SLinus Torvalds 
3421da177e4SLinus Torvalds 	if (drv && drv->resume)
3438d92bc22SJean Delvare 		error = drv->resume(pci_dev);
3441da177e4SLinus Torvalds 	else
3458d92bc22SJean Delvare 		error = pci_default_resume(pci_dev);
3468d92bc22SJean Delvare 	return error;
3471da177e4SLinus Torvalds }
3481da177e4SLinus Torvalds 
349cbd69dbbSLinus Torvalds static int pci_device_resume_early(struct device * dev)
350cbd69dbbSLinus Torvalds {
351cbd69dbbSLinus Torvalds 	int error = 0;
352cbd69dbbSLinus Torvalds 	struct pci_dev * pci_dev = to_pci_dev(dev);
353cbd69dbbSLinus Torvalds 	struct pci_driver * drv = pci_dev->driver;
354cbd69dbbSLinus Torvalds 
3551597cacbSAlan Cox 	pci_fixup_device(pci_fixup_resume, pci_dev);
3561597cacbSAlan Cox 
357cbd69dbbSLinus Torvalds 	if (drv && drv->resume_early)
358cbd69dbbSLinus Torvalds 		error = drv->resume_early(pci_dev);
359cbd69dbbSLinus Torvalds 	return error;
360cbd69dbbSLinus Torvalds }
361cbd69dbbSLinus Torvalds 
362c8958177SGreg KH static void pci_device_shutdown(struct device *dev)
363c8958177SGreg KH {
364c8958177SGreg KH 	struct pci_dev *pci_dev = to_pci_dev(dev);
365c8958177SGreg KH 	struct pci_driver *drv = pci_dev->driver;
366c8958177SGreg KH 
367c8958177SGreg KH 	if (drv && drv->shutdown)
368c8958177SGreg KH 		drv->shutdown(pci_dev);
369c8958177SGreg KH }
3701da177e4SLinus Torvalds 
3711da177e4SLinus Torvalds #define kobj_to_pci_driver(obj) container_of(obj, struct device_driver, kobj)
3721da177e4SLinus Torvalds #define attr_to_driver_attribute(obj) container_of(obj, struct driver_attribute, attr)
3731da177e4SLinus Torvalds 
3741da177e4SLinus Torvalds static ssize_t
3751da177e4SLinus Torvalds pci_driver_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
3761da177e4SLinus Torvalds {
3771da177e4SLinus Torvalds 	struct device_driver *driver = kobj_to_pci_driver(kobj);
3781da177e4SLinus Torvalds 	struct driver_attribute *dattr = attr_to_driver_attribute(attr);
379fc7e4828SDmitry Torokhov 	ssize_t ret;
3801da177e4SLinus Torvalds 
381fc7e4828SDmitry Torokhov 	if (!get_driver(driver))
382fc7e4828SDmitry Torokhov 		return -ENODEV;
383fc7e4828SDmitry Torokhov 
384fc7e4828SDmitry Torokhov 	ret = dattr->show ? dattr->show(driver, buf) : -EIO;
385fc7e4828SDmitry Torokhov 
3861da177e4SLinus Torvalds 	put_driver(driver);
3871da177e4SLinus Torvalds 	return ret;
3881da177e4SLinus Torvalds }
3891da177e4SLinus Torvalds 
3901da177e4SLinus Torvalds static ssize_t
3911da177e4SLinus Torvalds pci_driver_attr_store(struct kobject * kobj, struct attribute *attr,
3921da177e4SLinus Torvalds 		      const char *buf, size_t count)
3931da177e4SLinus Torvalds {
3941da177e4SLinus Torvalds 	struct device_driver *driver = kobj_to_pci_driver(kobj);
3951da177e4SLinus Torvalds 	struct driver_attribute *dattr = attr_to_driver_attribute(attr);
396fc7e4828SDmitry Torokhov 	ssize_t ret;
3971da177e4SLinus Torvalds 
398fc7e4828SDmitry Torokhov 	if (!get_driver(driver))
399fc7e4828SDmitry Torokhov 		return -ENODEV;
400fc7e4828SDmitry Torokhov 
401fc7e4828SDmitry Torokhov 	ret = dattr->store ? dattr->store(driver, buf, count) : -EIO;
402fc7e4828SDmitry Torokhov 
4031da177e4SLinus Torvalds 	put_driver(driver);
4041da177e4SLinus Torvalds 	return ret;
4051da177e4SLinus Torvalds }
4061da177e4SLinus Torvalds 
4071da177e4SLinus Torvalds static struct sysfs_ops pci_driver_sysfs_ops = {
4081da177e4SLinus Torvalds 	.show = pci_driver_attr_show,
4091da177e4SLinus Torvalds 	.store = pci_driver_attr_store,
4101da177e4SLinus Torvalds };
4111da177e4SLinus Torvalds static struct kobj_type pci_driver_kobj_type = {
4121da177e4SLinus Torvalds 	.sysfs_ops = &pci_driver_sysfs_ops,
4131da177e4SLinus Torvalds };
4141da177e4SLinus Torvalds 
4151da177e4SLinus Torvalds /**
416863b18f4SLaurent riffard  * __pci_register_driver - register a new pci driver
4171da177e4SLinus Torvalds  * @drv: the driver structure to register
418863b18f4SLaurent riffard  * @owner: owner module of drv
4191da177e4SLinus Torvalds  *
4201da177e4SLinus Torvalds  * Adds the driver structure to the list of registered drivers.
4211da177e4SLinus Torvalds  * Returns a negative value on error, otherwise 0.
422eaae4b3aSSteven Cole  * If no error occurred, the driver remains registered even if
4231da177e4SLinus Torvalds  * no device was claimed during registration.
4241da177e4SLinus Torvalds  */
425*725522b5SGreg Kroah-Hartman int __pci_register_driver(struct pci_driver *drv, struct module *owner,
426*725522b5SGreg Kroah-Hartman 			  const char *mod_name)
4271da177e4SLinus Torvalds {
4281da177e4SLinus Torvalds 	int error;
4291da177e4SLinus Torvalds 
4301da177e4SLinus Torvalds 	/* initialize common driver fields */
4311da177e4SLinus Torvalds 	drv->driver.name = drv->name;
4321da177e4SLinus Torvalds 	drv->driver.bus = &pci_bus_type;
433863b18f4SLaurent riffard 	drv->driver.owner = owner;
434*725522b5SGreg Kroah-Hartman 	drv->driver.mod_name = mod_name;
4351da177e4SLinus Torvalds 	drv->driver.kobj.ktype = &pci_driver_kobj_type;
43650b00755SAlan Cox 
43750b00755SAlan Cox 	if (pci_multithread_probe)
4380f397f86SGreg Kroah-Hartman 		drv->driver.multithread_probe = pci_multithread_probe;
43950b00755SAlan Cox 	else
44050b00755SAlan Cox 		drv->driver.multithread_probe = drv->multithread_probe;
44175865858SGreg Kroah-Hartman 
44275865858SGreg Kroah-Hartman 	spin_lock_init(&drv->dynids.lock);
44375865858SGreg Kroah-Hartman 	INIT_LIST_HEAD(&drv->dynids.list);
4441da177e4SLinus Torvalds 
4451da177e4SLinus Torvalds 	/* register with core */
4461da177e4SLinus Torvalds 	error = driver_register(&drv->driver);
44750bf14b3SAkinobu Mita 	if (error)
44850bf14b3SAkinobu Mita 		return error;
4491da177e4SLinus Torvalds 
45075865858SGreg Kroah-Hartman 	error = pci_create_newid_file(drv);
45150bf14b3SAkinobu Mita 	if (error)
45250bf14b3SAkinobu Mita 		driver_unregister(&drv->driver);
4531da177e4SLinus Torvalds 
4541da177e4SLinus Torvalds 	return error;
4551da177e4SLinus Torvalds }
4561da177e4SLinus Torvalds 
4571da177e4SLinus Torvalds /**
4581da177e4SLinus Torvalds  * pci_unregister_driver - unregister a pci driver
4591da177e4SLinus Torvalds  * @drv: the driver structure to unregister
4601da177e4SLinus Torvalds  *
4611da177e4SLinus Torvalds  * Deletes the driver structure from the list of registered PCI drivers,
4621da177e4SLinus Torvalds  * gives it a chance to clean up by calling its remove() function for
4631da177e4SLinus Torvalds  * each device it was responsible for, and marks those devices as
4641da177e4SLinus Torvalds  * driverless.
4651da177e4SLinus Torvalds  */
4661da177e4SLinus Torvalds 
4671da177e4SLinus Torvalds void
4681da177e4SLinus Torvalds pci_unregister_driver(struct pci_driver *drv)
4691da177e4SLinus Torvalds {
4701da177e4SLinus Torvalds 	driver_unregister(&drv->driver);
4711da177e4SLinus Torvalds 	pci_free_dynids(drv);
4721da177e4SLinus Torvalds }
4731da177e4SLinus Torvalds 
4741da177e4SLinus Torvalds static struct pci_driver pci_compat_driver = {
4751da177e4SLinus Torvalds 	.name = "compat"
4761da177e4SLinus Torvalds };
4771da177e4SLinus Torvalds 
4781da177e4SLinus Torvalds /**
4791da177e4SLinus Torvalds  * pci_dev_driver - get the pci_driver of a device
4801da177e4SLinus Torvalds  * @dev: the device to query
4811da177e4SLinus Torvalds  *
4821da177e4SLinus Torvalds  * Returns the appropriate pci_driver structure or %NULL if there is no
4831da177e4SLinus Torvalds  * registered driver for the device.
4841da177e4SLinus Torvalds  */
4851da177e4SLinus Torvalds struct pci_driver *
4861da177e4SLinus Torvalds pci_dev_driver(const struct pci_dev *dev)
4871da177e4SLinus Torvalds {
4881da177e4SLinus Torvalds 	if (dev->driver)
4891da177e4SLinus Torvalds 		return dev->driver;
4901da177e4SLinus Torvalds 	else {
4911da177e4SLinus Torvalds 		int i;
4921da177e4SLinus Torvalds 		for(i=0; i<=PCI_ROM_RESOURCE; i++)
4931da177e4SLinus Torvalds 			if (dev->resource[i].flags & IORESOURCE_BUSY)
4941da177e4SLinus Torvalds 				return &pci_compat_driver;
4951da177e4SLinus Torvalds 	}
4961da177e4SLinus Torvalds 	return NULL;
4971da177e4SLinus Torvalds }
4981da177e4SLinus Torvalds 
4991da177e4SLinus Torvalds /**
5001da177e4SLinus Torvalds  * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
5011da177e4SLinus Torvalds  * @dev: the PCI device structure to match against
5028f7020d3SRandy Dunlap  * @drv: the device driver to search for matching PCI device id structures
5031da177e4SLinus Torvalds  *
5041da177e4SLinus Torvalds  * Used by a driver to check whether a PCI device present in the
5051da177e4SLinus Torvalds  * system is in its list of supported devices. Returns the matching
5061da177e4SLinus Torvalds  * pci_device_id structure or %NULL if there is no match.
5071da177e4SLinus Torvalds  */
5081da177e4SLinus Torvalds static int pci_bus_match(struct device *dev, struct device_driver *drv)
5091da177e4SLinus Torvalds {
51075865858SGreg Kroah-Hartman 	struct pci_dev *pci_dev = to_pci_dev(dev);
5111da177e4SLinus Torvalds 	struct pci_driver *pci_drv = to_pci_driver(drv);
5121da177e4SLinus Torvalds 	const struct pci_device_id *found_id;
5131da177e4SLinus Torvalds 
51475865858SGreg Kroah-Hartman 	found_id = pci_match_device(pci_drv, pci_dev);
5151da177e4SLinus Torvalds 	if (found_id)
5161da177e4SLinus Torvalds 		return 1;
5171da177e4SLinus Torvalds 
51875865858SGreg Kroah-Hartman 	return 0;
5191da177e4SLinus Torvalds }
5201da177e4SLinus Torvalds 
5211da177e4SLinus Torvalds /**
5221da177e4SLinus Torvalds  * pci_dev_get - increments the reference count of the pci device structure
5231da177e4SLinus Torvalds  * @dev: the device being referenced
5241da177e4SLinus Torvalds  *
5251da177e4SLinus Torvalds  * Each live reference to a device should be refcounted.
5261da177e4SLinus Torvalds  *
5271da177e4SLinus Torvalds  * Drivers for PCI devices should normally record such references in
5281da177e4SLinus Torvalds  * their probe() methods, when they bind to a device, and release
5291da177e4SLinus Torvalds  * them by calling pci_dev_put(), in their disconnect() methods.
5301da177e4SLinus Torvalds  *
5311da177e4SLinus Torvalds  * A pointer to the device with the incremented reference counter is returned.
5321da177e4SLinus Torvalds  */
5331da177e4SLinus Torvalds struct pci_dev *pci_dev_get(struct pci_dev *dev)
5341da177e4SLinus Torvalds {
5351da177e4SLinus Torvalds 	if (dev)
5361da177e4SLinus Torvalds 		get_device(&dev->dev);
5371da177e4SLinus Torvalds 	return dev;
5381da177e4SLinus Torvalds }
5391da177e4SLinus Torvalds 
5401da177e4SLinus Torvalds /**
5411da177e4SLinus Torvalds  * pci_dev_put - release a use of the pci device structure
5421da177e4SLinus Torvalds  * @dev: device that's been disconnected
5431da177e4SLinus Torvalds  *
5441da177e4SLinus Torvalds  * Must be called when a user of a device is finished with it.  When the last
5451da177e4SLinus Torvalds  * user of the device calls this function, the memory of the device is freed.
5461da177e4SLinus Torvalds  */
5471da177e4SLinus Torvalds void pci_dev_put(struct pci_dev *dev)
5481da177e4SLinus Torvalds {
5491da177e4SLinus Torvalds 	if (dev)
5501da177e4SLinus Torvalds 		put_device(&dev->dev);
5511da177e4SLinus Torvalds }
5521da177e4SLinus Torvalds 
5531da177e4SLinus Torvalds #ifndef CONFIG_HOTPLUG
554312c004dSKay Sievers int pci_uevent(struct device *dev, char **envp, int num_envp,
5551da177e4SLinus Torvalds 	       char *buffer, int buffer_size)
5561da177e4SLinus Torvalds {
5571da177e4SLinus Torvalds 	return -ENODEV;
5581da177e4SLinus Torvalds }
5591da177e4SLinus Torvalds #endif
5601da177e4SLinus Torvalds 
5611da177e4SLinus Torvalds struct bus_type pci_bus_type = {
5621da177e4SLinus Torvalds 	.name		= "pci",
5631da177e4SLinus Torvalds 	.match		= pci_bus_match,
564312c004dSKay Sievers 	.uevent		= pci_uevent,
565b15d686aSRussell King 	.probe		= pci_device_probe,
566b15d686aSRussell King 	.remove		= pci_device_remove,
5671da177e4SLinus Torvalds 	.suspend	= pci_device_suspend,
568cbd69dbbSLinus Torvalds 	.suspend_late	= pci_device_suspend_late,
569cbd69dbbSLinus Torvalds 	.resume_early	= pci_device_resume_early,
5701da177e4SLinus Torvalds 	.resume		= pci_device_resume,
571cbd69dbbSLinus Torvalds 	.shutdown	= pci_device_shutdown,
5721da177e4SLinus Torvalds 	.dev_attrs	= pci_dev_attrs,
5731da177e4SLinus Torvalds };
5741da177e4SLinus Torvalds 
5751da177e4SLinus Torvalds static int __init pci_driver_init(void)
5761da177e4SLinus Torvalds {
5771da177e4SLinus Torvalds 	return bus_register(&pci_bus_type);
5781da177e4SLinus Torvalds }
5791da177e4SLinus Torvalds 
5801da177e4SLinus Torvalds postcore_initcall(pci_driver_init);
5811da177e4SLinus Torvalds 
58275865858SGreg Kroah-Hartman EXPORT_SYMBOL(pci_match_id);
5831da177e4SLinus Torvalds EXPORT_SYMBOL(pci_match_device);
584863b18f4SLaurent riffard EXPORT_SYMBOL(__pci_register_driver);
5851da177e4SLinus Torvalds EXPORT_SYMBOL(pci_unregister_driver);
5861da177e4SLinus Torvalds EXPORT_SYMBOL(pci_dev_driver);
5871da177e4SLinus Torvalds EXPORT_SYMBOL(pci_bus_type);
5881da177e4SLinus Torvalds EXPORT_SYMBOL(pci_dev_get);
5891da177e4SLinus Torvalds EXPORT_SYMBOL(pci_dev_put);
590