pci-driver.c revision 2debb4d2019fa05a0896f1591dea0e0dc21bc046
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * drivers/pci/pci-driver.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
42b937303188807b498d1a3163f60305f0941538eGreg Kroah-Hartman * (C) Copyright 2002-2004, 2007 Greg Kroah-Hartman <greg@kroah.com>
52b937303188807b498d1a3163f60305f0941538eGreg Kroah-Hartman * (C) Copyright 2007 Novell Inc.
62b937303188807b498d1a3163f60305f0941538eGreg Kroah-Hartman *
72b937303188807b498d1a3163f60305f0941538eGreg Kroah-Hartman * Released under the GPL v2 only.
82b937303188807b498d1a3163f60305f0941538eGreg Kroah-Hartman *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h>
15d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#include <linux/mempolicy.h>
164e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/string.h>
174e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/slab.h>
188c65b4a60450590e79a28e9717ceffa9e4debb3fTim Schmielau#include <linux/sched.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pci.h"
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dynamic device IDs are disabled for !CONFIG_HOTPLUG
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanstruct pci_dynid {
2675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct list_head node;
2775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_device_id id;
2875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman};
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
303d3c2ae1101c1f2dff7e2f9d514769779dbd2737Greg Kroah-Hartman#ifdef CONFIG_HOTPLUG
313d3c2ae1101c1f2dff7e2f9d514769779dbd2737Greg Kroah-Hartman
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
338f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * store_new_id - add a new PCI device ID to this driver and re-probe devices
348f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @driver: target device driver
358f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @buf: buffer for scanning device ID data
368f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @count: input size
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adds a new dynamic pci device ID to this driver,
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and causes the driver to probe for all devices again.
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
41f8eb1005a5bdb019d2a4ff3ef8d8e8015b22afcbRandy Dunlapstatic ssize_t
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstore_new_id(struct device_driver *driver, const char *buf, size_t count)
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_dynid *dynid;
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver *pdrv = to_pci_driver(driver);
46b41d6cf38e27a940d998d989526a9748de1bf028Jean Delvare	const struct pci_device_id *ids = pdrv->id_table;
476ba186361ed2cda7e174856a3ab8a8e3237b3c3dJean Delvare	__u32 vendor, device, subvendor=PCI_ANY_ID,
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		subdevice=PCI_ANY_ID, class=0, class_mask=0;
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long driver_data=0;
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int fields=0;
512debb4d2019fa05a0896f1591dea0e0dc21bc046Chris Wright	int retval=0;
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53b41d6cf38e27a940d998d989526a9748de1bf028Jean Delvare	fields = sscanf(buf, "%x %x %x %x %x %x %lx",
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&vendor, &device, &subvendor, &subdevice,
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&class, &class_mask, &driver_data);
566ba186361ed2cda7e174856a3ab8a8e3237b3c3dJean Delvare	if (fields < 2)
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59b41d6cf38e27a940d998d989526a9748de1bf028Jean Delvare	/* Only accept driver_data values that match an existing id_table
60b41d6cf38e27a940d998d989526a9748de1bf028Jean Delvare	   entry */
612debb4d2019fa05a0896f1591dea0e0dc21bc046Chris Wright	if (ids) {
622debb4d2019fa05a0896f1591dea0e0dc21bc046Chris Wright		retval = -EINVAL;
632debb4d2019fa05a0896f1591dea0e0dc21bc046Chris Wright		while (ids->vendor || ids->subvendor || ids->class_mask) {
642debb4d2019fa05a0896f1591dea0e0dc21bc046Chris Wright			if (driver_data == ids->driver_data) {
652debb4d2019fa05a0896f1591dea0e0dc21bc046Chris Wright				retval = 0;
662debb4d2019fa05a0896f1591dea0e0dc21bc046Chris Wright				break;
672debb4d2019fa05a0896f1591dea0e0dc21bc046Chris Wright			}
682debb4d2019fa05a0896f1591dea0e0dc21bc046Chris Wright			ids++;
69b41d6cf38e27a940d998d989526a9748de1bf028Jean Delvare		}
702debb4d2019fa05a0896f1591dea0e0dc21bc046Chris Wright		if (retval)	/* No match */
712debb4d2019fa05a0896f1591dea0e0dc21bc046Chris Wright			return retval;
72b41d6cf38e27a940d998d989526a9748de1bf028Jean Delvare	}
73b41d6cf38e27a940d998d989526a9748de1bf028Jean Delvare
74f5afe8064f3087bead8fea7e32547c2a3ada5fd0Eric Sesterhenn	dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dynid)
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.vendor = vendor;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.device = device;
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.subvendor = subvendor;
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.subdevice = subdevice;
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.class = class;
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dynid->id.class_mask = class_mask;
84edbc25caaa492a82e19baa915f1f6b0a0db6554dMilton Miller	dynid->id.driver_data = driver_data;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&pdrv->dynids.lock);
87a56bc69a182f501582557af7fad5bc882b1c856cMichael Ellerman	list_add_tail(&dynid->node, &pdrv->dynids.list);
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&pdrv->dynids.lock);
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	if (get_driver(&pdrv->driver)) {
91b19441af185559118e8247382ea4f2f76ebffc6dGreg Kroah-Hartman		retval = driver_attach(&pdrv->driver);
9275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		put_driver(&pdrv->driver);
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
95b19441af185559118e8247382ea4f2f76ebffc6dGreg Kroah-Hartman	if (retval)
96b19441af185559118e8247382ea4f2f76ebffc6dGreg Kroah-Hartman		return retval;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return count;
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_free_dynids(struct pci_driver *drv)
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_dynid *dynid, *n;
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&drv->dynids.lock);
10775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_del(&dynid->node);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(dynid);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&drv->dynids.lock);
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_create_newid_file(struct pci_driver *drv)
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv->probe != NULL)
11903d43b19b9f56c1d18bc8f2f7890534fbe6a285dGreg Kroah-Hartman		error = driver_create_file(&drv->driver, &driver_attr_new_id);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12303d43b19b9f56c1d18bc8f2f7890534fbe6a285dGreg Kroah-Hartmanstatic void pci_remove_newid_file(struct pci_driver *drv)
12403d43b19b9f56c1d18bc8f2f7890534fbe6a285dGreg Kroah-Hartman{
12503d43b19b9f56c1d18bc8f2f7890534fbe6a285dGreg Kroah-Hartman	driver_remove_file(&drv->driver, &driver_attr_new_id);
12603d43b19b9f56c1d18bc8f2f7890534fbe6a285dGreg Kroah-Hartman}
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* !CONFIG_HOTPLUG */
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void pci_free_dynids(struct pci_driver *drv) {}
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int pci_create_newid_file(struct pci_driver *drv)
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13303d43b19b9f56c1d18bc8f2f7890534fbe6a285dGreg Kroah-Hartmanstatic inline void pci_remove_newid_file(struct pci_driver *drv) {}
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
13775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * pci_match_id - See if a pci device matches a given pci_id table
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @ids: array of PCI device id structures to search in
13975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * @dev: the PCI device structure to match against.
14075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman *
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used by a driver to check whether a PCI device present in the
14275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * system is in its list of supported devices.  Returns the matching
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_device_id structure or %NULL if there is no match.
14475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman *
1458b60756a628a73bc8bf8b59d8716cb3f09b7e7ebRandy Dunlap * Deprecated, don't use this as it will not catch any dynamic ids
14675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * that a driver might want to check for.
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanconst struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
14975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman					 struct pci_dev *dev)
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	if (ids) {
15275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		while (ids->vendor || ids->subvendor || ids->class_mask) {
15375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			if (pci_match_one_device(ids, dev))
15475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman				return ids;
15575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			ids++;
15675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		}
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
162ae9608af9e300395ec032479621f32688c121141Randy Dunlap * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure
16375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * @drv: the PCI driver to match against
16439ba487fe22a63b3df7c543c82d01db0f0fed700Henrik Kretzschmar * @dev: the PCI device structure to match against
16575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman *
16675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * Used by a driver to check whether a PCI device present in the
16775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * system is in its list of supported devices.  Returns the matching
16875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman * pci_device_id structure or %NULL if there is no match.
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
170d73460d79bc88de74221d73723ed61a0081b7a36Adrian Bunkstatic const struct pci_device_id *pci_match_device(struct pci_driver *drv,
171d73460d79bc88de74221d73723ed61a0081b7a36Adrian Bunk						    struct pci_dev *dev)
17275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman{
17375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_dynid *dynid;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1757461b60afa62b26943e97861d87b9f9a32d7fd9cRussell King	/* Look at the dynamic ids first, before the static ones */
17675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	spin_lock(&drv->dynids.lock);
17775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	list_for_each_entry(dynid, &drv->dynids.list, node) {
17875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		if (pci_match_one_device(&dynid->id, dev)) {
17975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			spin_unlock(&drv->dynids.lock);
18075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			return &dynid->id;
18175865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		}
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	spin_unlock(&drv->dynids.lock);
1847461b60afa62b26943e97861d87b9f9a32d7fd9cRussell King
1857461b60afa62b26943e97861d87b9f9a32d7fd9cRussell King	return pci_match_id(drv->id_table, dev);
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
188d42c69972b853fd33a26c8c7405624be41a22136Andi Kleenstatic int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
189d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen			  const struct pci_device_id *id)
190d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen{
191d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	int error;
192d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#ifdef CONFIG_NUMA
193d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	/* Execute driver initialization on node where the
194d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	   device's bus is attached to.  This way the driver likely
195d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	   allocates its local memory on the right node without
196d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	   any need to change it. */
197d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	struct mempolicy *oldpol;
198d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	cpumask_t oldmask = current->cpus_allowed;
1994efeb4dd3c0bf534e431a8e7c72d0afbd4cd24aaYinghai Lu	int node = dev_to_node(&dev->dev);
200f70316dace2bb99730800d47044acb818c6735f6Mike Travis
201f70316dace2bb99730800d47044acb818c6735f6Mike Travis	if (node >= 0) {
202f70316dace2bb99730800d47044acb818c6735f6Mike Travis		node_to_cpumask_ptr(nodecpumask, node);
203f70316dace2bb99730800d47044acb818c6735f6Mike Travis		set_cpus_allowed_ptr(current, nodecpumask);
204f70316dace2bb99730800d47044acb818c6735f6Mike Travis	}
205d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	/* And set default memory allocation policy */
206d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	oldpol = current->mempolicy;
20774e27e44b0407fb1f6e8d1f7b7818f108463c4b8Lee Schermerhorn	current->mempolicy = NULL;	/* fall back to system default policy */
208d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#endif
209d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	error = drv->probe(dev, id);
210d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#ifdef CONFIG_NUMA
211f70316dace2bb99730800d47044acb818c6735f6Mike Travis	set_cpus_allowed_ptr(current, &oldmask);
212d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	current->mempolicy = oldpol;
213d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen#endif
214d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen	return error;
215d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen}
216d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * __pci_device_probe()
2198f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @drv: driver to call to check if it wants the PCI device
2208f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @pci_dev: PCI device being probed
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2228f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * returns 0 on success, else error.
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
22775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman{
22875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	const struct pci_device_id *id;
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!pci_dev->driver && drv->probe) {
23275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		error = -ENODEV;
23375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman
23475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		id = pci_match_device(drv, pci_dev);
23575865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		if (id)
236d42c69972b853fd33a26c8c7405624be41a22136Andi Kleen			error = pci_call_probe(drv, pci_dev, id);
23775865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		if (error >= 0) {
23875865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			pci_dev->driver = drv;
23975865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman			error = 0;
24075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman		}
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_probe(struct device * dev)
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver *drv;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *pci_dev;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv = to_pci_driver(dev->driver);
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dev = to_pci_dev(dev);
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dev_get(pci_dev);
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = __pci_device_probe(drv, pci_dev);
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (error)
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_dev_put(pci_dev);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pci_device_remove(struct device * dev)
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * drv = pci_dev->driver;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drv) {
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (drv->remove)
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			drv->remove(pci_dev);
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_dev->driver = NULL;
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2732449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li	 * If the device is still on, set the power state as "unknown",
2742449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li	 * since it might change by the next time we load the driver.
2752449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li	 */
2762449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li	if (pci_dev->current_state == PCI_D0)
2772449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li		pci_dev->current_state = PCI_UNKNOWN;
2782449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li
2792449e06a5696b7af1c8a369b04c97f3b139cf3bbShaohua Li	/*
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We would love to complain here if pci_dev->is_enabled is set, that
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the driver should have called pci_disable_device(), but the
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * unfortunate fact is there are too many odd BIOS and bridge setups
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * that don't like drivers doing that all of the time.
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Oh well, we can dream of sane hardware when we sleep, no matter how
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * horrible the crap we have to deal with is when we are awake...
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_dev_put(pci_dev);
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
292bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic void pci_device_shutdown(struct device *dev)
293bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
294bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct pci_dev *pci_dev = to_pci_dev(dev);
295bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct pci_driver *drv = pci_dev->driver;
296bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
297bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->shutdown)
298bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		drv->shutdown(pci_dev);
299bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	pci_msi_shutdown(pci_dev);
300bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	pci_msix_shutdown(pci_dev);
301bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
302bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
303bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#ifdef CONFIG_PM_SLEEP
304bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
305355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysockistatic bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
306355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki{
307355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	struct pci_driver *drv = pci_dev->driver;
308355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki
309355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	return drv && (drv->suspend || drv->suspend_late || drv->resume
310355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki		|| drv->resume_early);
311355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki}
312355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki
313bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki/*
314bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki * Default "suspend" method for devices that have no driver provided suspend,
315bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki * or not even a driver at all.
316bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki */
317bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic void pci_default_pm_suspend(struct pci_dev *pci_dev)
318bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
319bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	pci_save_state(pci_dev);
320bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	/*
321bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	 * mark its power state as "unknown", since we don't know if
322bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	 * e.g. the BIOS will change its device state when we suspend.
323bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	 */
324bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (pci_dev->current_state == PCI_D0)
325bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		pci_dev->current_state = PCI_UNKNOWN;
326bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
327bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
328bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki/*
329bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki * Default "resume" method for devices that have no driver provided resume,
330355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki * or not even a driver at all (first part).
331bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki */
332355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysockistatic void pci_default_pm_resume_early(struct pci_dev *pci_dev)
333bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
334bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	/* restore the PCI config space */
335bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	pci_restore_state(pci_dev);
336355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki}
337355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki
338355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki/*
339355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki * Default "resume" method for devices that have no driver provided resume,
340355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki * or not even a driver at all (second part).
341355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki */
342355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysockistatic int pci_default_pm_resume_late(struct pci_dev *pci_dev)
343355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki{
344355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	int retval;
345355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki
346bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	/* if the device was enabled before suspend, reenable */
347bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	retval = pci_reenable_device(pci_dev);
348bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	/*
349bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	 * if the device was busmaster before the suspend, make it busmaster
350bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	 * again
351bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	 */
352bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (pci_dev->is_busmaster)
353bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		pci_set_master(pci_dev);
354bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
355bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return retval;
356bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
357bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
358bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_legacy_suspend(struct device *dev, pm_message_t state)
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * drv = pci_dev->driver;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
364026694920579590c73b5c56705d543568ed5ad41Andrew Morton	if (drv && drv->suspend) {
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = drv->suspend(pci_dev, state);
366026694920579590c73b5c56705d543568ed5ad41Andrew Morton		suspend_report_result(drv->suspend, i);
367026694920579590c73b5c56705d543568ed5ad41Andrew Morton	} else {
368bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		pci_default_pm_suspend(pci_dev);
369026694920579590c73b5c56705d543568ed5ad41Andrew Morton	}
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return i;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
373bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_legacy_suspend_late(struct device *dev, pm_message_t state)
374cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds{
375cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
376cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	struct pci_driver * drv = pci_dev->driver;
377cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	int i = 0;
378cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds
379cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	if (drv && drv->suspend_late) {
380cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds		i = drv->suspend_late(pci_dev, state);
381cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds		suspend_report_result(drv->suspend_late, i);
382cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	}
383cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	return i;
384cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds}
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
386bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_legacy_resume(struct device *dev)
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3888d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare	int error;
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_driver * drv = pci_dev->driver;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
392355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	if (drv && drv->resume) {
3938d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare		error = drv->resume(pci_dev);
394355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else {
395355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki		pci_default_pm_resume_early(pci_dev);
396355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki		error = pci_default_pm_resume_late(pci_dev);
397355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	}
3988d92bc2270d67a43b1d7e94a8cb6f81f1435fe9aJean Delvare	return error;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_legacy_resume_early(struct device *dev)
402cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds{
403cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	int error = 0;
404cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	struct pci_dev * pci_dev = to_pci_dev(dev);
405cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	struct pci_driver * drv = pci_dev->driver;
406cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds
407cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	if (drv && drv->resume_early)
408cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds		error = drv->resume_early(pci_dev);
409cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	return error;
410cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds}
411cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds
412bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_prepare(struct device *dev)
413bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
414bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct device_driver *drv = dev->driver;
415bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	int error = 0;
416bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
417bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm && drv->pm->prepare)
418bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = drv->pm->prepare(dev);
419bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
420bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
421bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
422bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
423bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic void pci_pm_complete(struct device *dev)
424bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
425bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct device_driver *drv = dev->driver;
426bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
427bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm && drv->pm->complete)
428bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		drv->pm->complete(dev);
429bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
430bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
431bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#ifdef CONFIG_SUSPEND
432bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
433bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_suspend(struct device *dev)
434bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
435bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct pci_dev *pci_dev = to_pci_dev(dev);
436bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct device_driver *drv = dev->driver;
437bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	int error = 0;
438bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
439bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm) {
440bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		if (drv->pm->suspend) {
441bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			error = drv->pm->suspend(dev);
442bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			suspend_report_result(drv->pm->suspend, error);
443bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		}
444355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else if (pci_has_legacy_pm_support(pci_dev)) {
445bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = pci_legacy_suspend(dev, PMSG_SUSPEND);
446bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	}
447bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	pci_fixup_device(pci_fixup_suspend, pci_dev);
448bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
449bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
450bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
451bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
452bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_suspend_noirq(struct device *dev)
453c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman{
454355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	struct pci_dev *pci_dev = to_pci_dev(dev);
455adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	struct device_driver *drv = dev->driver;
456bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	int error = 0;
457c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman
458bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm) {
459bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		if (drv->pm->suspend_noirq) {
460bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			error = drv->pm->suspend_noirq(dev);
461bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			suspend_report_result(drv->pm->suspend_noirq, error);
462bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		}
463355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else if (pci_has_legacy_pm_support(pci_dev)) {
464bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = pci_legacy_suspend_late(dev, PMSG_SUSPEND);
465355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else {
466355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki		pci_default_pm_suspend(pci_dev);
467bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	}
468bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
469bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
470c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman}
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
472bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_resume(struct device *dev)
473bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
474bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct pci_dev *pci_dev = to_pci_dev(dev);
475bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct device_driver *drv = dev->driver;
476355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	int error = 0;
477bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
478bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	pci_fixup_device(pci_fixup_resume, pci_dev);
479bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
480bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm) {
481355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki		if (drv->pm->resume)
482355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki			error = drv->pm->resume(dev);
483355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else if (pci_has_legacy_pm_support(pci_dev)) {
484bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = pci_legacy_resume(dev);
485355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else {
486355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki		error = pci_default_pm_resume_late(pci_dev);
487bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	}
488bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
489bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
490bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
491bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
492bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_resume_noirq(struct device *dev)
493bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
494355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	struct pci_dev *pci_dev = to_pci_dev(dev);
495adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	struct device_driver *drv = dev->driver;
496bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	int error = 0;
497bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
498adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	pci_fixup_device(pci_fixup_resume_early, to_pci_dev(dev));
499bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
500bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm) {
501bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		if (drv->pm->resume_noirq)
502bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			error = drv->pm->resume_noirq(dev);
503355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else if (pci_has_legacy_pm_support(pci_dev)) {
504bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = pci_legacy_resume_early(dev);
505355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else {
506355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki		pci_default_pm_resume_early(pci_dev);
507bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	}
508bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
509bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
510bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
511bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
512bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#else /* !CONFIG_SUSPEND */
513bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
514bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define pci_pm_suspend		NULL
515bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define pci_pm_suspend_noirq	NULL
516bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define pci_pm_resume		NULL
517bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define pci_pm_resume_noirq	NULL
518bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
519bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#endif /* !CONFIG_SUSPEND */
520bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
521bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#ifdef CONFIG_HIBERNATION
522bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
523bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_freeze(struct device *dev)
524bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
525bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct pci_dev *pci_dev = to_pci_dev(dev);
526bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct device_driver *drv = dev->driver;
527bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	int error = 0;
528bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
529bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm) {
530bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		if (drv->pm->freeze) {
531bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			error = drv->pm->freeze(dev);
532bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			suspend_report_result(drv->pm->freeze, error);
533bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		}
534355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else if (pci_has_legacy_pm_support(pci_dev)) {
535bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = pci_legacy_suspend(dev, PMSG_FREEZE);
536bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		pci_fixup_device(pci_fixup_suspend, pci_dev);
537bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	}
538bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
539bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
540bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
541bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
542bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_freeze_noirq(struct device *dev)
543bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
544355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	struct pci_dev *pci_dev = to_pci_dev(dev);
545adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	struct device_driver *drv = dev->driver;
546bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	int error = 0;
547bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
548bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm) {
549bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		if (drv->pm->freeze_noirq) {
550bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			error = drv->pm->freeze_noirq(dev);
551bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			suspend_report_result(drv->pm->freeze_noirq, error);
552bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		}
553355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else if (pci_has_legacy_pm_support(pci_dev)) {
554bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = pci_legacy_suspend_late(dev, PMSG_FREEZE);
555355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else {
556355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki		pci_default_pm_suspend(pci_dev);
557bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	}
558bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
559bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
560bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
561bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
562bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_thaw(struct device *dev)
563bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
564355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	struct pci_dev *pci_dev = to_pci_dev(dev);
565bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct device_driver *drv = dev->driver;
566bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	int error = 0;
567bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
568bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm) {
569bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		if (drv->pm->thaw)
570bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			error =  drv->pm->thaw(dev);
571355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else if (pci_has_legacy_pm_support(pci_dev)) {
572355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki		pci_fixup_device(pci_fixup_resume, pci_dev);
573bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = pci_legacy_resume(dev);
574bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	}
575bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
576bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
577bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
578bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
579bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_thaw_noirq(struct device *dev)
580bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
581355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	struct pci_dev *pci_dev = to_pci_dev(dev);
582adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	struct device_driver *drv = dev->driver;
583bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	int error = 0;
584bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
585bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm) {
586bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		if (drv->pm->thaw_noirq)
587bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			error = drv->pm->thaw_noirq(dev);
588355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else if (pci_has_legacy_pm_support(pci_dev)) {
589adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki		pci_fixup_device(pci_fixup_resume_early, to_pci_dev(dev));
590bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = pci_legacy_resume_early(dev);
591bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	}
592bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
593bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
594bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
595bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
596bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_poweroff(struct device *dev)
597bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
598355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	struct pci_dev *pci_dev = to_pci_dev(dev);
599bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct device_driver *drv = dev->driver;
600bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	int error = 0;
601bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
602355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	pci_fixup_device(pci_fixup_suspend, pci_dev);
603bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
604bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm) {
605bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		if (drv->pm->poweroff) {
606bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			error = drv->pm->poweroff(dev);
607bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			suspend_report_result(drv->pm->poweroff, error);
608bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		}
609355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else if (pci_has_legacy_pm_support(pci_dev)) {
610bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = pci_legacy_suspend(dev, PMSG_HIBERNATE);
611bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	}
612bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
613bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
614bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
615bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
616bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_poweroff_noirq(struct device *dev)
617bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
618adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	struct device_driver *drv = dev->driver;
619bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	int error = 0;
620bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
621bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm) {
622bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		if (drv->pm->poweroff_noirq) {
623bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			error = drv->pm->poweroff_noirq(dev);
624bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			suspend_report_result(drv->pm->poweroff_noirq, error);
625bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		}
626355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else if (pci_has_legacy_pm_support(to_pci_dev(dev))) {
627bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
628bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	}
629bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
630bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
631bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
632bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
633bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_restore(struct device *dev)
634bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
635bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct pci_dev *pci_dev = to_pci_dev(dev);
636bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct device_driver *drv = dev->driver;
637355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	int error = 0;
638bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
639bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm) {
640355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki		if (drv->pm->restore)
641355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki			error = drv->pm->restore(dev);
642355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else if (pci_has_legacy_pm_support(pci_dev)) {
643bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = pci_legacy_resume(dev);
644355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else {
645355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki		error = pci_default_pm_resume_late(pci_dev);
646bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	}
647bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	pci_fixup_device(pci_fixup_resume, pci_dev);
648bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
649bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
650bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki}
651bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
652bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysockistatic int pci_pm_restore_noirq(struct device *dev)
653bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki{
654bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	struct pci_dev *pci_dev = to_pci_dev(dev);
655adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	struct device_driver *drv = dev->driver;
656bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	int error = 0;
657bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
658bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	pci_fixup_device(pci_fixup_resume, pci_dev);
659bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
660bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	if (drv && drv->pm) {
661bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		if (drv->pm->restore_noirq)
662bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki			error = drv->pm->restore_noirq(dev);
663355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else if (pci_has_legacy_pm_support(pci_dev)) {
664bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki		error = pci_legacy_resume_early(dev);
665355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki	} else {
666355a72d75b3b4f4877db4c9070c798238028ecb5Rafael J. Wysocki		pci_default_pm_resume_early(pci_dev);
667bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	}
668bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	pci_fixup_device(pci_fixup_resume_early, pci_dev);
669bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
670bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	return error;
671c8958177224622411b9979eabb5610e30b06034bGreg Kroah-Hartman}
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
673bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#else /* !CONFIG_HIBERNATION */
674bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
675bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define pci_pm_freeze		NULL
676bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define pci_pm_freeze_noirq	NULL
677bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define pci_pm_thaw		NULL
678bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define pci_pm_thaw_noirq	NULL
679bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define pci_pm_poweroff		NULL
680bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define pci_pm_poweroff_noirq	NULL
681bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define pci_pm_restore		NULL
682bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define pci_pm_restore_noirq	NULL
683bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
684bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#endif /* !CONFIG_HIBERNATION */
685bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
686adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysockistruct dev_pm_ops pci_dev_pm_ops = {
687adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	.prepare = pci_pm_prepare,
688adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	.complete = pci_pm_complete,
689adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	.suspend = pci_pm_suspend,
690adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	.resume = pci_pm_resume,
691adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	.freeze = pci_pm_freeze,
692adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	.thaw = pci_pm_thaw,
693adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	.poweroff = pci_pm_poweroff,
694adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki	.restore = pci_pm_restore,
695bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	.suspend_noirq = pci_pm_suspend_noirq,
696bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	.resume_noirq = pci_pm_resume_noirq,
697bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	.freeze_noirq = pci_pm_freeze_noirq,
698bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	.thaw_noirq = pci_pm_thaw_noirq,
699bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	.poweroff_noirq = pci_pm_poweroff_noirq,
700bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	.restore_noirq = pci_pm_restore_noirq,
701bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki};
702bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
703adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki#define PCI_PM_OPS_PTR	(&pci_dev_pm_ops)
704bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
705bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#else /* !CONFIG_PM_SLEEP */
706bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
707bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#define PCI_PM_OPS_PTR	NULL
708bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
709bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki#endif /* !CONFIG_PM_SLEEP */
710bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
712863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffard * __pci_register_driver - register a new pci driver
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drv: the driver structure to register
714863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffard * @owner: owner module of drv
715f95d882d81ee731be2a4a3b34f86810e29b68836Randy Dunlap * @mod_name: module name string
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adds the driver structure to the list of registered drivers.
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns a negative value on error, otherwise 0.
719eaae4b3a84a3781543a32bcaf0a33306ae915574Steven Cole * If no error occurred, the driver remains registered even if
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * no device was claimed during registration.
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
722725522b5453dd680412f2b6463a988e4fd148757Greg Kroah-Hartmanint __pci_register_driver(struct pci_driver *drv, struct module *owner,
723725522b5453dd680412f2b6463a988e4fd148757Greg Kroah-Hartman			  const char *mod_name)
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error;
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* initialize common driver fields */
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.name = drv->name;
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.bus = &pci_bus_type;
730863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffard	drv->driver.owner = owner;
731725522b5453dd680412f2b6463a988e4fd148757Greg Kroah-Hartman	drv->driver.mod_name = mod_name;
73250b0075520a0acba9cabab5203bbce918b966d9aAlan Cox
73375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	spin_lock_init(&drv->dynids.lock);
73475865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	INIT_LIST_HEAD(&drv->dynids.list);
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* register with core */
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = driver_register(&drv->driver);
73850bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita	if (error)
73950bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita		return error;
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
74150bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita	error = pci_create_newid_file(drv);
74250bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita	if (error)
74350bf14b3ff05fb6e10688021b96f95d30a300f8dAkinobu Mita		driver_unregister(&drv->driver);
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_unregister_driver - unregister a pci driver
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @drv: the driver structure to unregister
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Deletes the driver structure from the list of registered PCI drivers,
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * gives it a chance to clean up by calling its remove() function for
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * each device it was responsible for, and marks those devices as
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driverless.
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_unregister_driver(struct pci_driver *drv)
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
76103d43b19b9f56c1d18bc8f2f7890534fbe6a285dGreg Kroah-Hartman	pci_remove_newid_file(drv);
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	driver_unregister(&drv->driver);
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_free_dynids(drv);
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver pci_compat_driver = {
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name = "compat"
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_driver - get the pci_driver of a device
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the device to query
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the appropriate pci_driver structure or %NULL if there is no
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registered driver for the device.
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_driver *
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_dev_driver(const struct pci_dev *dev)
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->driver)
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return dev->driver;
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int i;
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for(i=0; i<=PCI_ROM_RESOURCE; i++)
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (dev->resource[i].flags & IORESOURCE_BUSY)
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return &pci_compat_driver;
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the PCI device structure to match against
7948f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * @drv: the device driver to search for matching PCI device id structures
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Used by a driver to check whether a PCI device present in the
7978f7020d36374dda9366fee1343f8eacfe8f5e641Randy Dunlap * system is in its list of supported devices. Returns the matching
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_device_id structure or %NULL if there is no match.
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
80075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartmanstatic int pci_bus_match(struct device *dev, struct device_driver *drv)
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
80275865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_dev *pci_dev = to_pci_dev(dev);
80375865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	struct pci_driver *pci_drv = to_pci_driver(drv);
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct pci_device_id *found_id;
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
80675865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	found_id = pci_match_device(pci_drv, pci_dev);
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (found_id)
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-Hartman	return 0;
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_get - increments the reference count of the pci device structure
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: the device being referenced
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Each live reference to a device should be refcounted.
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Drivers for PCI devices should normally record such references in
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * their probe() methods, when they bind to a device, and release
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * them by calling pci_dev_put(), in their disconnect() methods.
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A pointer to the device with the incremented reference counter is returned.
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_dev *pci_dev_get(struct pci_dev *dev)
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev)
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		get_device(&dev->dev);
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return dev;
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_dev_put - release a use of the pci device structure
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: device that's been disconnected
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Must be called when a user of a device is finished with it.  When the last
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user of the device calls this function, the memory of the device is freed.
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid pci_dev_put(struct pci_dev *dev)
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev)
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_device(&dev->dev);
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_HOTPLUG
8467eff2e7a8b65c25920207324e56611150eb1cd9aKay Sieversint pci_uevent(struct device *dev, struct kobj_uevent_env *env)
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENODEV;
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type pci_bus_type = {
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "pci",
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.match		= pci_bus_match,
855312c004d36ce6c739512bac83b452f4c20ab1f62Kay Sievers	.uevent		= pci_uevent,
856b15d686a2b589c9e4f1ea116553e9c3c3d030daeRussell King	.probe		= pci_device_probe,
857b15d686a2b589c9e4f1ea116553e9c3c3d030daeRussell King	.remove		= pci_device_remove,
858cbd69dbbf1adfce6e048f15afc8629901ca9dae5Linus Torvalds	.shutdown	= pci_device_shutdown,
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.dev_attrs	= pci_dev_attrs,
860bbb44d9f23d868a2837c6b22b8dfb123d8e7800cRafael J. Wysocki	.pm		= PCI_PM_OPS_PTR,
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init pci_driver_init(void)
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return bus_register(&pci_bus_type);
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspostcore_initcall(pci_driver_init);
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
87075865858971add95809c5c9cd35dc4cfba08e33bGreg Kroah-HartmanEXPORT_SYMBOL(pci_match_id);
871863b18f4b5e7d9e6903b353328cf6fa084dbb619Laurent riffardEXPORT_SYMBOL(__pci_register_driver);
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_unregister_driver);
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_driver);
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_bus_type);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_get);
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_dev_put);
877