pci-driver.c revision 50bf14b3ff05fb6e10688021b96f95d30a300f8d
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
200f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman/* multithreaded probe logic */
210f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartmanstatic int pci_multithread_probe =
220f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman#ifdef CONFIG_PCI_MULTITHREAD_PROBE
230f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman	1;
240f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman#else
250f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman	0;
260f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman#endif
270f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman__module_param_call("", pci_multithread_probe, param_set_bool, param_get_bool, &pci_multithread_probe, 0644);
280f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman
290f397f865076e3471ec884ee73ad5e34165fac2aGreg Kroah-Hartman
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dynamic device IDs are disabled for !CONFIG_HOTPLUG
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanstruct pci_dynid {
3575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct list_head node;
3675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_device_id id;
3775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman};
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
393d3c2ae1101c1f2dff7e2f9d514769779dbd2737Greg Kroah-Hartman#ifdef CONFIG_HOTPLUG
403d3c2ae1101c1f2dff7e2f9d514769779dbd2737Greg Kroah-Hartman
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
428f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * store_new_id - add a new PCI device ID to this driver and re-probe devices
438f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @driver: target device driver
448f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @buf: buffer for scanning device ID data
458f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @count: input size
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adds a new dynamic pci device ID to this driver,
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and causes the driver to probe for all devices again.
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
50f8eb1005a5bdb019d2a4ff3ef8d8e8015b22afcbRandy Dunlapstatic ssize_t
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstore_new_id(struct device_driver *driver, const char *buf, size_t count)
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_dynid *dynid;
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver *pdrv = to_pci_driver(driver);
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID,
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		subdevice=PCI_ANY_ID, class=0, class_mask=0;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long driver_data=0;
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int fields=0;
59b19441af185559118e8247382ea4f2f76ebffc6dGreg Kroah-Hartman	int retval = 0;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fields = sscanf(buf, "%x %x %x %x %x %x %lux",
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&vendor, &device, &subvendor, &subdevice,
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&class, &class_mask, &driver_data);
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fields < 0)
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
67f5afe8064f3087bead8fea7e32547c2a3ada5fd0Eric Sesterhenn	dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dynid)
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	INIT_LIST_HEAD(&dynid->node);
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.vendor = vendor;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.device = device;
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.subvendor = subvendor;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.subdevice = subdevice;
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.class = class;
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.class_mask = class_mask;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.driver_data = pdrv->dynids.use_driver_data ?
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		driver_data : 0UL;
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&pdrv->dynids.lock);
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_add_tail(&pdrv->dynids.list, &dynid->node);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&pdrv->dynids.lock);
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	if (get_driver(&pdrv->driver)) {
86b19441af185559118e8247382ea4f2f76ebffc6dGreg Kroah-Hartman		retval = driver_attach(&pdrv->driver);
8775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		put_driver(&pdrv->driver);
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
90b19441af185559118e8247382ea4f2f76ebffc6dGreg Kroah-Hartman	if (retval)
91b19441af185559118e8247382ea4f2f76ebffc6dGreg Kroah-Hartman		return retval;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_free_dynids(struct pci_driver *drv)
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_dynid *dynid, *n;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&drv->dynids.lock);
10275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del(&dynid->node);
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(dynid);
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&drv->dynids.lock);
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_create_newid_file(struct pci_driver *drv)
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv->probe != NULL)
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		error = sysfs_create_file(&drv->driver.kobj,
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					  &driver_attr_new_id.attr);
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* !CONFIG_HOTPLUG */
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void pci_free_dynids(struct pci_driver *drv) {}
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int pci_create_newid_file(struct pci_driver *drv)
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
12875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * pci_match_id - See if a pci device matches a given pci_id table
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ids: array of PCI device id structures to search in
13075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * @dev: the PCI device structure to match against.
13175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman *
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used by a driver to check whether a PCI device present in the
13375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * system is in its list of supported devices.  Returns the matching
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_device_id structure or %NULL if there is no match.
13575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman *
13675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * Depreciated, don't use this as it will not catch any dynamic ids
13775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * that a driver might want to check for.
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
13975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanconst struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
14075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman					 struct pci_dev *dev)
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	if (ids) {
14375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		while (ids->vendor || ids->subvendor || ids->class_mask) {
14475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			if (pci_match_one_device(ids, dev))
14575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman				return ids;
14675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			ids++;
14775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		}
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
15375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * pci_match_device - Tell if a PCI device structure has a matching
15475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman *                    PCI device id structure
15575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * @drv: the PCI driver to match against
15639ba487fe22a63b3df7c543c82d01db0f0fed700Henrik Kretzschmar * @dev: the PCI device structure to match against
15775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman *
15875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * Used by a driver to check whether a PCI device present in the
15975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * system is in its list of supported devices.  Returns the matching
16075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * pci_device_id structure or %NULL if there is no match.
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
16275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanconst struct pci_device_id *pci_match_device(struct pci_driver *drv,
16375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman					     struct pci_dev *dev)
16475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman{
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct pci_device_id *id;
16675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_dynid *dynid;
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	id = pci_match_id(drv->id_table, dev);
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (id)
17075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		return id;
17175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman
17275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	/* static ids didn't match, lets look at the dynamic ones */
17375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	spin_lock(&drv->dynids.lock);
17475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	list_for_each_entry(dynid, &drv->dynids.list, node) {
17575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		if (pci_match_one_device(&dynid->id, dev)) {
17675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			spin_unlock(&drv->dynids.lock);
17775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			return &dynid->id;
17875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		}
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	spin_unlock(&drv->dynids.lock);
18175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	return NULL;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
184d42c69972b853fd33a26c8c7405624be41a22136Andi Kleenstatic int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
185d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen			  const struct pci_device_id *id)
186d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen{
187d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	int error;
188d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#ifdef CONFIG_NUMA
189d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	/* Execute driver initialization on node where the
190d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	   device's bus is attached to.  This way the driver likely
191d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	   allocates its local memory on the right node without
192d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	   any need to change it. */
193d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	struct mempolicy *oldpol;
194d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	cpumask_t oldmask = current->cpus_allowed;
195d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	int node = pcibus_to_node(dev->bus);
196d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	if (node >= 0 && node_online(node))
197d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	    set_cpus_allowed(current, node_to_cpumask(node));
198d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	/* And set default memory allocation policy */
199d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	oldpol = current->mempolicy;
200d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	current->mempolicy = &default_policy;
201d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	mpol_get(current->mempolicy);
202d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#endif
203d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	error = drv->probe(dev, id);
204d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#ifdef CONFIG_NUMA
205d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	set_cpus_allowed(current, oldmask);
206d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	mpol_free(current->mempolicy);
207d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	current->mempolicy = oldpol;
208d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#endif
209d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	return error;
210d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen}
211d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * __pci_device_probe()
2148f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @drv: driver to call to check if it wants the PCI device
2158f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @pci_dev: PCI device being probed
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2178f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * returns 0 on success, else error.
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
22275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman{
22375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	const struct pci_device_id *id;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!pci_dev->driver && drv->probe) {
22775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		error = -ENODEV;
22875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman
22975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		id = pci_match_device(drv, pci_dev);
23075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		if (id)
231d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen			error = pci_call_probe(drv, pci_dev, id);
23275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		if (error >= 0) {
23375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			pci_dev->driver = drv;
23475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			error = 0;
23575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		}
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_probe(struct device * dev)
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver *drv;
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *pci_dev;
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv = to_pci_driver(dev->driver);
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dev = to_pci_dev(dev);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dev_get(pci_dev);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = __pci_device_probe(drv, pci_dev);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (error)
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_dev_put(pci_dev);
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_remove(struct device * dev)
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * drv = pci_dev->driver;
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv) {
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (drv->remove)
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			drv->remove(pci_dev);
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_dev->driver = NULL;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2682449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li	 * If the device is still on, set the power state as "unknown",
2692449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li	 * since it might change by the next time we load the driver.
2702449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li	 */
2712449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li	if (pci_dev->current_state == PCI_D0)
2722449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li		pci_dev->current_state = PCI_UNKNOWN;
2732449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li
2742449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li	/*
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We would love to complain here if pci_dev->is_enabled is set, that
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the driver should have called pci_disable_device(), but the
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * unfortunate fact is there are too many odd BIOS and bridge setups
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * that don't like drivers doing that all of the time.
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Oh well, we can dream of sane hardware when we sleep, no matter how
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * horrible the crap we have to deal with is when we are awake...
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dev_put(pci_dev);
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_suspend(struct device * dev, pm_message_t state)
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * drv = pci_dev->driver;
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
293026694920579590c73b5c56705d543568ed5ad41Andrew Morton	if (drv && drv->suspend) {
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = drv->suspend(pci_dev, state);
295026694920579590c73b5c56705d543568ed5ad41Andrew Morton		suspend_report_result(drv->suspend, i);
296026694920579590c73b5c56705d543568ed5ad41Andrew Morton	} else {
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_save_state(pci_dev);
2982449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li		/*
2992449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li		 * mark its power state as "unknown", since we don't know if
3002449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li		 * e.g. the BIOS will change its device state when we suspend.
3012449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li		 */
3022449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li		if (pci_dev->current_state == PCI_D0)
3032449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li			pci_dev->current_state = PCI_UNKNOWN;
304026694920579590c73b5c56705d543568ed5ad41Andrew Morton	}
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return i;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
308cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvaldsstatic int pci_device_suspend_late(struct device * dev, pm_message_t state)
309cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds{
310cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
311cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	struct pci_driver * drv = pci_dev->driver;
312cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	int i = 0;
313cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds
314cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	if (drv && drv->suspend_late) {
315cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds		i = drv->suspend_late(pci_dev, state);
316cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds		suspend_report_result(drv->suspend_late, i);
317cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	}
318cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	return i;
319cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds}
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32195a629657dbe28e44a312c47815b3dc3f1ce0970Greg Kroah-Hartman/*
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Default resume method for devices that have no driver provided resume,
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or not even a driver at all.
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3258d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvarestatic int pci_default_resume(struct pci_dev *pci_dev)
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3278d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare	int retval = 0;
32895a629657dbe28e44a312c47815b3dc3f1ce0970Greg Kroah-Hartman
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* restore the PCI config space */
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_restore_state(pci_dev);
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if the device was enabled before suspend, reenable */
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pci_dev->is_enabled)
33395a629657dbe28e44a312c47815b3dc3f1ce0970Greg Kroah-Hartman		retval = pci_enable_device(pci_dev);
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if the device was busmaster before the suspend, make it busmaster again */
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pci_dev->is_busmaster)
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_set_master(pci_dev);
3378d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare
3388d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare	return retval;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_resume(struct device * dev)
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3438d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare	int error;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * drv = pci_dev->driver;
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv && drv->resume)
3488d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare		error = drv->resume(pci_dev);
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
3508d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare		error = pci_default_resume(pci_dev);
3518d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare	return error;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
354cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvaldsstatic int pci_device_resume_early(struct device * dev)
355cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds{
356cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	int error = 0;
357cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
358cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	struct pci_driver * drv = pci_dev->driver;
359cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds
360cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	if (drv && drv->resume_early)
361cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds		error = drv->resume_early(pci_dev);
362cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	return error;
363cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds}
364cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds
365c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartmanstatic void pci_device_shutdown(struct device *dev)
366c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman{
367c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman	struct pci_dev *pci_dev = to_pci_dev(dev);
368c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman	struct pci_driver *drv = pci_dev->driver;
369c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman
370c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman	if (drv && drv->shutdown)
371c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman		drv->shutdown(pci_dev);
372c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman}
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define kobj_to_pci_driver(obj) container_of(obj, struct device_driver, kobj)
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define attr_to_driver_attribute(obj) container_of(obj, struct driver_attribute, attr)
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_driver_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct device_driver *driver = kobj_to_pci_driver(kobj);
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct driver_attribute *dattr = attr_to_driver_attribute(attr);
382fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	ssize_t ret;
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
384fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	if (!get_driver(driver))
385fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov		return -ENODEV;
386fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov
387fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	ret = dattr->show ? dattr->show(driver, buf) : -EIO;
388fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov
389fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	put_driver(driver);
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_driver_attr_store(struct kobject * kobj, struct attribute *attr,
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      const char *buf, size_t count)
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct device_driver *driver = kobj_to_pci_driver(kobj);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct driver_attribute *dattr = attr_to_driver_attribute(attr);
399fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	ssize_t ret;
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	if (!get_driver(driver))
402fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov		return -ENODEV;
403fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov
404fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	ret = dattr->store ? dattr->store(driver, buf, count) : -EIO;
405fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov
406fc7e4828995d8c9e4c9597f8a19179e4ab53f73eDmitry Torokhov	put_driver(driver);
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sysfs_ops pci_driver_sysfs_ops = {
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.show = pci_driver_attr_show,
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.store = pci_driver_attr_store,
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct kobj_type pci_driver_kobj_type = {
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.sysfs_ops = &pci_driver_sysfs_ops,
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
419863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffard * __pci_register_driver - register a new pci driver
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drv: the driver structure to register
421863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffard * @owner: owner module of drv
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adds the driver structure to the list of registered drivers.
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns a negative value on error, otherwise 0.
425eaae4b3a84a3781543a32bcaf0a33306ae915574Steven Cole * If no error occurred, the driver remains registered even if
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * no device was claimed during registration.
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
428863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffardint __pci_register_driver(struct pci_driver *drv, struct module *owner)
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error;
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* initialize common driver fields */
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.name = drv->name;
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.bus = &pci_bus_type;
435863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffard	drv->driver.owner = owner;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.kobj.ktype = &pci_driver_kobj_type;
43750b0075520a0acba9cabab5203bbce918b966d9aAlan Cox
43850b0075520a0acba9cabab5203bbce918b966d9aAlan Cox	if (pci_multithread_probe)
43950b0075520a0acba9cabab5203bbce918b966d9aAlan Cox		drv->driver.multithread_probe = pci_multithread_probe;
44050b0075520a0acba9cabab5203bbce918b966d9aAlan Cox	else
44150b0075520a0acba9cabab5203bbce918b966d9aAlan Cox		drv->driver.multithread_probe = drv->multithread_probe;
44275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman
44375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	spin_lock_init(&drv->dynids.lock);
44475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	INIT_LIST_HEAD(&drv->dynids.list);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* register with core */
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = driver_register(&drv->driver);
44850bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita	if (error)
44950bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita		return error;
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45150bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita	error = pci_create_newid_file(drv);
45250bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita	if (error)
45350bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita		driver_unregister(&drv->driver);
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_unregister_driver - unregister a pci driver
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drv: the driver structure to unregister
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Deletes the driver structure from the list of registered PCI drivers,
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * gives it a chance to clean up by calling its remove() function for
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * each device it was responsible for, and marks those devices as
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driverless.
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_unregister_driver(struct pci_driver *drv)
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	driver_unregister(&drv->driver);
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_dynids(drv);
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver pci_compat_driver = {
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name = "compat"
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_driver - get the pci_driver of a device
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the device to query
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the appropriate pci_driver structure or %NULL if there is no
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registered driver for the device.
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_driver *
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_dev_driver(const struct pci_dev *dev)
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->driver)
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return dev->driver;
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int i;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for(i=0; i<=PCI_ROM_RESOURCE; i++)
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (dev->resource[i].flags & IORESOURCE_BUSY)
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return &pci_compat_driver;
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the PCI device structure to match against
5038f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @drv: the device driver to search for matching PCI device id structures
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used by a driver to check whether a PCI device present in the
5068f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * system is in its list of supported devices. Returns the matching
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_device_id structure or %NULL if there is no match.
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
50975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanstatic int pci_bus_match(struct device *dev, struct device_driver *drv)
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
51175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_dev *pci_dev = to_pci_dev(dev);
51275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_driver *pci_drv = to_pci_driver(drv);
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct pci_device_id *found_id;
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	found_id = pci_match_device(pci_drv, pci_dev);
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (found_id)
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	return 0;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_get - increments the reference count of the pci device structure
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the device being referenced
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Each live reference to a device should be refcounted.
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Drivers for PCI devices should normally record such references in
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * their probe() methods, when they bind to a device, and release
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * them by calling pci_dev_put(), in their disconnect() methods.
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A pointer to the device with the incremented reference counter is returned.
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_dev *pci_dev_get(struct pci_dev *dev)
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev)
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		get_device(&dev->dev);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return dev;
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_put - release a use of the pci device structure
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: device that's been disconnected
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Must be called when a user of a device is finished with it.  When the last
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user of the device calls this function, the memory of the device is freed.
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid pci_dev_put(struct pci_dev *dev)
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev)
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_device(&dev->dev);
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_HOTPLUG
555312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sieversint pci_uevent(struct device *dev, char **envp, int num_envp,
556312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sievers	       char *buffer, int buffer_size)
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENODEV;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type pci_bus_type = {
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "pci",
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.match		= pci_bus_match,
565312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sievers	.uevent		= pci_uevent,
566b15d686a2b589c9e4f1ea116553e9c3c3d030daeRussell King	.probe		= pci_device_probe,
567b15d686a2b589c9e4f1ea116553e9c3c3d030daeRussell King	.remove		= pci_device_remove,
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= pci_device_suspend,
569cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	.suspend_late	= pci_device_suspend_late,
570cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	.resume_early	= pci_device_resume_early,
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume		= pci_device_resume,
572cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	.shutdown	= pci_device_shutdown,
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.dev_attrs	= pci_dev_attrs,
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init pci_driver_init(void)
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return bus_register(&pci_bus_type);
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspostcore_initcall(pci_driver_init);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
58375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-HartmanEXPORT_SYMBOL(pci_match_id);
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_match_device);
585863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffardEXPORT_SYMBOL(__pci_register_driver);
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_unregister_driver);
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_driver);
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_bus_type);
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_get);
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_put);
591