pci-driver.c revision 8c65b4a60450590e79a28e9717ceffa9e4debb3f
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * drivers/pci/pci-driver.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h>
10d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#include <linux/mempolicy.h>
114e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/string.h>
124e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/slab.h>
138c65b4a60450590e79a28e9717ceffa9e4debb3fTim Schmielau#include <linux/sched.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pci.h"
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Registration of PCI drivers and handling of hot-pluggable devices.
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dynamic device IDs are disabled for !CONFIG_HOTPLUG
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanstruct pci_dynid {
2575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct list_head node;
2675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_device_id id;
2775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman};
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
293d3c2ae1101c1f2dff7e2f9d514769779dbd2737Greg Kroah-Hartman#ifdef CONFIG_HOTPLUG
303d3c2ae1101c1f2dff7e2f9d514769779dbd2737Greg Kroah-Hartman
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
328f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * store_new_id - add a new PCI device ID to this driver and re-probe devices
338f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @driver: target device driver
348f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @buf: buffer for scanning device ID data
358f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @count: input size
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adds a new dynamic pci device ID to this driver,
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and causes the driver to probe for all devices again.
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline ssize_t
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstore_new_id(struct device_driver *driver, const char *buf, size_t count)
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_dynid *dynid;
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver *pdrv = to_pci_driver(driver);
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID,
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		subdevice=PCI_ANY_ID, class=0, class_mask=0;
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long driver_data=0;
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int fields=0;
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fields = sscanf(buf, "%x %x %x %x %x %x %lux",
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&vendor, &device, &subvendor, &subdevice,
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&class, &class_mask, &driver_data);
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fields < 0)
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid = kmalloc(sizeof(*dynid), GFP_KERNEL);
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dynid)
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(dynid, 0, sizeof(*dynid));
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&dynid->node);
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.vendor = vendor;
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.device = device;
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.subvendor = subvendor;
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.subdevice = subdevice;
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.class = class;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.class_mask = class_mask;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.driver_data = pdrv->dynids.use_driver_data ?
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		driver_data : 0UL;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&pdrv->dynids.lock);
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_add_tail(&pdrv->dynids.list, &dynid->node);
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&pdrv->dynids.lock);
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	if (get_driver(&pdrv->driver)) {
7675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		driver_attach(&pdrv->driver);
7775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		put_driver(&pdrv->driver);
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_free_dynids(struct pci_driver *drv)
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_dynid *dynid, *n;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&drv->dynids.lock);
9075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del(&dynid->node);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(dynid);
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&drv->dynids.lock);
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_create_newid_file(struct pci_driver *drv)
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv->probe != NULL)
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		error = sysfs_create_file(&drv->driver.kobj,
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					  &driver_attr_new_id.attr);
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* !CONFIG_HOTPLUG */
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void pci_free_dynids(struct pci_driver *drv) {}
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int pci_create_newid_file(struct pci_driver *drv)
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
11675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * pci_match_id - See if a pci device matches a given pci_id table
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ids: array of PCI device id structures to search in
11875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * @dev: the PCI device structure to match against.
11975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman *
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used by a driver to check whether a PCI device present in the
12175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * system is in its list of supported devices.  Returns the matching
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_device_id structure or %NULL if there is no match.
12375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman *
12475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * Depreciated, don't use this as it will not catch any dynamic ids
12575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * that a driver might want to check for.
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
12775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanconst struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
12875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman					 struct pci_dev *dev)
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	if (ids) {
13175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		while (ids->vendor || ids->subvendor || ids->class_mask) {
13275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			if (pci_match_one_device(ids, dev))
13375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman				return ids;
13475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			ids++;
13575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		}
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
14175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * pci_match_device - Tell if a PCI device structure has a matching
14275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman *                    PCI device id structure
14375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * @ids: array of PCI device id structures to search in
14475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * @dev: the PCI device structure to match against
14575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * @drv: the PCI driver to match against
14675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman *
14775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * Used by a driver to check whether a PCI device present in the
14875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * system is in its list of supported devices.  Returns the matching
14975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * pci_device_id structure or %NULL if there is no match.
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
15175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanconst struct pci_device_id *pci_match_device(struct pci_driver *drv,
15275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman					     struct pci_dev *dev)
15375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman{
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct pci_device_id *id;
15575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_dynid *dynid;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	id = pci_match_id(drv->id_table, dev);
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (id)
15975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		return id;
16075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman
16175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	/* static ids didn't match, lets look at the dynamic ones */
16275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	spin_lock(&drv->dynids.lock);
16375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	list_for_each_entry(dynid, &drv->dynids.list, node) {
16475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		if (pci_match_one_device(&dynid->id, dev)) {
16575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			spin_unlock(&drv->dynids.lock);
16675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			return &dynid->id;
16775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		}
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	spin_unlock(&drv->dynids.lock);
17075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	return NULL;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
173d42c69972b853fd33a26c8c7405624be41a22136Andi Kleenstatic int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
174d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen			  const struct pci_device_id *id)
175d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen{
176d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	int error;
177d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#ifdef CONFIG_NUMA
178d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	/* Execute driver initialization on node where the
179d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	   device's bus is attached to.  This way the driver likely
180d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	   allocates its local memory on the right node without
181d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	   any need to change it. */
182d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	struct mempolicy *oldpol;
183d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	cpumask_t oldmask = current->cpus_allowed;
184d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	int node = pcibus_to_node(dev->bus);
185d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	if (node >= 0 && node_online(node))
186d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	    set_cpus_allowed(current, node_to_cpumask(node));
187d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	/* And set default memory allocation policy */
188d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	oldpol = current->mempolicy;
189d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	current->mempolicy = &default_policy;
190d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	mpol_get(current->mempolicy);
191d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#endif
192d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	error = drv->probe(dev, id);
193d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#ifdef CONFIG_NUMA
194d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	set_cpus_allowed(current, oldmask);
195d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	mpol_free(current->mempolicy);
196d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	current->mempolicy = oldpol;
197d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#endif
198d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	return error;
199d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen}
200d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * __pci_device_probe()
2038f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @drv: driver to call to check if it wants the PCI device
2048f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @pci_dev: PCI device being probed
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2068f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * returns 0 on success, else error.
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
21175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman{
21275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	const struct pci_device_id *id;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!pci_dev->driver && drv->probe) {
21675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		error = -ENODEV;
21775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman
21875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		id = pci_match_device(drv, pci_dev);
21975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		if (id)
220d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen			error = pci_call_probe(drv, pci_dev, id);
22175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		if (error >= 0) {
22275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			pci_dev->driver = drv;
22375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			error = 0;
22475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		}
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_probe(struct device * dev)
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver *drv;
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *pci_dev;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv = to_pci_driver(dev->driver);
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dev = to_pci_dev(dev);
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dev_get(pci_dev);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = __pci_device_probe(drv, pci_dev);
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (error)
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_dev_put(pci_dev);
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_remove(struct device * dev)
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * drv = pci_dev->driver;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv) {
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (drv->remove)
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			drv->remove(pci_dev);
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_dev->driver = NULL;
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We would love to complain here if pci_dev->is_enabled is set, that
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the driver should have called pci_disable_device(), but the
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * unfortunate fact is there are too many odd BIOS and bridge setups
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * that don't like drivers doing that all of the time.
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Oh well, we can dream of sane hardware when we sleep, no matter how
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * horrible the crap we have to deal with is when we are awake...
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dev_put(pci_dev);
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_suspend(struct device * dev, pm_message_t state)
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * drv = pci_dev->driver;
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0;
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv && drv->suspend)
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = drv->suspend(pci_dev, state);
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_save_state(pci_dev);
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return i;
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28395a629657dbe28e44a312c47815b3dc3f1ce0970Greg Kroah-Hartman/*
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Default resume method for devices that have no driver provided resume,
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or not even a driver at all.
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pci_default_resume(struct pci_dev *pci_dev)
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28995a629657dbe28e44a312c47815b3dc3f1ce0970Greg Kroah-Hartman	int retval;
29095a629657dbe28e44a312c47815b3dc3f1ce0970Greg Kroah-Hartman
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* restore the PCI config space */
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_restore_state(pci_dev);
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if the device was enabled before suspend, reenable */
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pci_dev->is_enabled)
29595a629657dbe28e44a312c47815b3dc3f1ce0970Greg Kroah-Hartman		retval = pci_enable_device(pci_dev);
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if the device was busmaster before the suspend, make it busmaster again */
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pci_dev->is_busmaster)
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_set_master(pci_dev);
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_resume(struct device * dev)
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * drv = pci_dev->driver;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv && drv->resume)
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		drv->resume(pci_dev);
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_default_resume(pci_dev);
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
313c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartmanstatic void pci_device_shutdown(struct device *dev)
314c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman{
315c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman	struct pci_dev *pci_dev = to_pci_dev(dev);
316c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman	struct pci_driver *drv = pci_dev->driver;
317c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman
318c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman	if (drv && drv->shutdown)
319c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman		drv->shutdown(pci_dev);
320c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman}
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define kobj_to_pci_driver(obj) container_of(obj, struct device_driver, kobj)
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define attr_to_driver_attribute(obj) container_of(obj, struct driver_attribute, attr)
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_driver_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct device_driver *driver = kobj_to_pci_driver(kobj);
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct driver_attribute *dattr = attr_to_driver_attribute(attr);
330fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	ssize_t ret;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
332fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	if (!get_driver(driver))
333fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov		return -ENODEV;
334fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov
335fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	ret = dattr->show ? dattr->show(driver, buf) : -EIO;
336fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov
337fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	put_driver(driver);
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_driver_attr_store(struct kobject * kobj, struct attribute *attr,
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      const char *buf, size_t count)
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct device_driver *driver = kobj_to_pci_driver(kobj);
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct driver_attribute *dattr = attr_to_driver_attribute(attr);
347fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	ssize_t ret;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
349fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	if (!get_driver(driver))
350fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov		return -ENODEV;
351fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov
352fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	ret = dattr->store ? dattr->store(driver, buf, count) : -EIO;
353fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov
354fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	put_driver(driver);
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sysfs_ops pci_driver_sysfs_ops = {
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.show = pci_driver_attr_show,
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.store = pci_driver_attr_store,
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct kobj_type pci_driver_kobj_type = {
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.sysfs_ops = &pci_driver_sysfs_ops,
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_register_driver - register a new pci driver
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drv: the driver structure to register
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adds the driver structure to the list of registered drivers.
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns a negative value on error, otherwise 0.
372eaae4b3a84a3781543a32bcaf0a33306ae915574Steven Cole * If no error occurred, the driver remains registered even if
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * no device was claimed during registration.
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pci_register_driver(struct pci_driver *drv)
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error;
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* initialize common driver fields */
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.name = drv->name;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.bus = &pci_bus_type;
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.probe = pci_device_probe;
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.remove = pci_device_remove;
384794f5bfa77955c4455f6d72d8b0e2bee25f1ff0cChristoph Hellwig	/* FIXME, once all of the existing PCI drivers have been fixed to set
385794f5bfa77955c4455f6d72d8b0e2bee25f1ff0cChristoph Hellwig	 * the pci shutdown function, this test can go away. */
386794f5bfa77955c4455f6d72d8b0e2bee25f1ff0cChristoph Hellwig	if (!drv->driver.shutdown)
387c83d9945c05570ba6b8ec5460c99d1ab7c6e6671Mika Kukkonen		drv->driver.shutdown = pci_device_shutdown;
388a1720fdbd0f90e64668a59a304d01c5ba001b450Russell King	else
389a1720fdbd0f90e64668a59a304d01c5ba001b450Russell King		printk(KERN_WARNING "Warning: PCI driver %s has a struct "
390a1720fdbd0f90e64668a59a304d01c5ba001b450Russell King			"device_driver shutdown method, please update!\n",
391a1720fdbd0f90e64668a59a304d01c5ba001b450Russell King			drv->name);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.owner = drv->owner;
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.kobj.ktype = &pci_driver_kobj_type;
39475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman
39575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	spin_lock_init(&drv->dynids.lock);
39675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	INIT_LIST_HEAD(&drv->dynids.list);
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* register with core */
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = driver_register(&drv->driver);
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!error)
40275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		error = pci_create_newid_file(drv);
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_unregister_driver - unregister a pci driver
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drv: the driver structure to unregister
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Deletes the driver structure from the list of registered PCI drivers,
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * gives it a chance to clean up by calling its remove() function for
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * each device it was responsible for, and marks those devices as
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driverless.
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_unregister_driver(struct pci_driver *drv)
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	driver_unregister(&drv->driver);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_dynids(drv);
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver pci_compat_driver = {
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name = "compat"
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_driver - get the pci_driver of a device
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the device to query
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the appropriate pci_driver structure or %NULL if there is no
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registered driver for the device.
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_driver *
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_dev_driver(const struct pci_dev *dev)
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->driver)
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return dev->driver;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int i;
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for(i=0; i<=PCI_ROM_RESOURCE; i++)
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (dev->resource[i].flags & IORESOURCE_BUSY)
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return &pci_compat_driver;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the PCI device structure to match against
4528f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @drv: the device driver to search for matching PCI device id structures
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used by a driver to check whether a PCI device present in the
4558f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * system is in its list of supported devices. Returns the matching
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_device_id structure or %NULL if there is no match.
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
45875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanstatic int pci_bus_match(struct device *dev, struct device_driver *drv)
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
46075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_dev *pci_dev = to_pci_dev(dev);
46175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_driver *pci_drv = to_pci_driver(drv);
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct pci_device_id *found_id;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	found_id = pci_match_device(pci_drv, pci_dev);
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (found_id)
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	return 0;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_get - increments the reference count of the pci device structure
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the device being referenced
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Each live reference to a device should be refcounted.
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Drivers for PCI devices should normally record such references in
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * their probe() methods, when they bind to a device, and release
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * them by calling pci_dev_put(), in their disconnect() methods.
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A pointer to the device with the incremented reference counter is returned.
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_dev *pci_dev_get(struct pci_dev *dev)
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev)
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		get_device(&dev->dev);
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return dev;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_put - release a use of the pci device structure
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: device that's been disconnected
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Must be called when a user of a device is finished with it.  When the last
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user of the device calls this function, the memory of the device is freed.
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid pci_dev_put(struct pci_dev *dev)
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev)
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_device(&dev->dev);
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_HOTPLUG
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pci_hotplug (struct device *dev, char **envp, int num_envp,
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 char *buffer, int buffer_size)
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENODEV;
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type pci_bus_type = {
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "pci",
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.match		= pci_bus_match,
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.hotplug	= pci_hotplug,
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= pci_device_suspend,
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume		= pci_device_resume,
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.dev_attrs	= pci_dev_attrs,
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init pci_driver_init(void)
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return bus_register(&pci_bus_type);
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspostcore_initcall(pci_driver_init);
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-HartmanEXPORT_SYMBOL(pci_match_id);
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_match_device);
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_register_driver);
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_unregister_driver);
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_driver);
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_bus_type);
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_get);
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_put);
535