blob: 4042d211c3e548b7b4796661ceb0842cf6949ef5 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * drivers/pci/pci-driver.c
3 *
Greg Kroah-Hartman2b937302007-11-28 12:23:18 -08004 * (C) Copyright 2002-2004, 2007 Greg Kroah-Hartman <greg@kroah.com>
5 * (C) Copyright 2007 Novell Inc.
6 *
7 * Released under the GPL v2 only.
8 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
11#include <linux/pci.h>
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/device.h>
Andi Kleend42c6992005-07-06 19:56:03 +020015#include <linux/mempolicy.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -080016#include <linux/string.h>
17#include <linux/slab.h>
Tim Schmielau8c65b4a2005-11-07 00:59:43 -080018#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include "pci.h"
20
21/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 * Dynamic device IDs are disabled for !CONFIG_HOTPLUG
23 */
24
Greg Kroah-Hartman75865852005-06-30 02:18:12 -070025struct pci_dynid {
26 struct list_head node;
27 struct pci_device_id id;
28};
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
Greg KH3d3c2ae2005-07-06 09:09:38 -070030#ifdef CONFIG_HOTPLUG
31
Linus Torvalds1da177e2005-04-16 15:20:36 -070032/**
Randy Dunlap8f7020d2005-10-23 11:57:38 -070033 * store_new_id - add a new PCI device ID to this driver and re-probe devices
34 * @driver: target device driver
35 * @buf: buffer for scanning device ID data
36 * @count: input size
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 *
38 * Adds a new dynamic pci device ID to this driver,
39 * and causes the driver to probe for all devices again.
40 */
Randy Dunlapf8eb1002005-10-28 20:36:51 -070041static ssize_t
Linus Torvalds1da177e2005-04-16 15:20:36 -070042store_new_id(struct device_driver *driver, const char *buf, size_t count)
43{
Greg Kroah-Hartman75865852005-06-30 02:18:12 -070044 struct pci_dynid *dynid;
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 struct pci_driver *pdrv = to_pci_driver(driver);
Jean Delvareb41d6cf2008-08-17 21:06:59 +020046 const struct pci_device_id *ids = pdrv->id_table;
Jean Delvare6ba18632007-04-07 17:21:28 +020047 __u32 vendor, device, subvendor=PCI_ANY_ID,
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 subdevice=PCI_ANY_ID, class=0, class_mask=0;
49 unsigned long driver_data=0;
50 int fields=0;
Jean Delvareb41d6cf2008-08-17 21:06:59 +020051 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
Jean Delvareb41d6cf2008-08-17 21:06:59 +020053 fields = sscanf(buf, "%x %x %x %x %x %x %lx",
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 &vendor, &device, &subvendor, &subdevice,
55 &class, &class_mask, &driver_data);
Jean Delvare6ba18632007-04-07 17:21:28 +020056 if (fields < 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 return -EINVAL;
58
Jean Delvareb41d6cf2008-08-17 21:06:59 +020059 /* Only accept driver_data values that match an existing id_table
60 entry */
61 retval = -EINVAL;
62 while (ids->vendor || ids->subvendor || ids->class_mask) {
63 if (driver_data == ids->driver_data) {
64 retval = 0;
65 break;
66 }
67 ids++;
68 }
69 if (retval) /* No match */
70 return retval;
71
Eric Sesterhennf5afe802006-02-28 15:34:49 +010072 dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 if (!dynid)
74 return -ENOMEM;
75
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 dynid->id.vendor = vendor;
77 dynid->id.device = device;
78 dynid->id.subvendor = subvendor;
79 dynid->id.subdevice = subdevice;
80 dynid->id.class = class;
81 dynid->id.class_mask = class_mask;
Milton Milleredbc25c2008-07-10 16:29:37 -050082 dynid->id.driver_data = driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
84 spin_lock(&pdrv->dynids.lock);
Michael Ellermana56bc692007-09-14 15:33:13 +100085 list_add_tail(&dynid->node, &pdrv->dynids.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 spin_unlock(&pdrv->dynids.lock);
87
Greg Kroah-Hartman75865852005-06-30 02:18:12 -070088 if (get_driver(&pdrv->driver)) {
Greg Kroah-Hartmanb19441a2006-08-28 11:43:25 -070089 retval = driver_attach(&pdrv->driver);
Greg Kroah-Hartman75865852005-06-30 02:18:12 -070090 put_driver(&pdrv->driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 }
92
Greg Kroah-Hartmanb19441a2006-08-28 11:43:25 -070093 if (retval)
94 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 return count;
96}
Linus Torvalds1da177e2005-04-16 15:20:36 -070097static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
99static void
100pci_free_dynids(struct pci_driver *drv)
101{
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700102 struct pci_dynid *dynid, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104 spin_lock(&drv->dynids.lock);
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700105 list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 list_del(&dynid->node);
107 kfree(dynid);
108 }
109 spin_unlock(&drv->dynids.lock);
110}
111
112static int
113pci_create_newid_file(struct pci_driver *drv)
114{
115 int error = 0;
116 if (drv->probe != NULL)
Greg Kroah-Hartman03d43b12007-11-28 12:23:18 -0800117 error = driver_create_file(&drv->driver, &driver_attr_new_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 return error;
119}
120
Greg Kroah-Hartman03d43b12007-11-28 12:23:18 -0800121static void pci_remove_newid_file(struct pci_driver *drv)
122{
123 driver_remove_file(&drv->driver, &driver_attr_new_id);
124}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125#else /* !CONFIG_HOTPLUG */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126static inline void pci_free_dynids(struct pci_driver *drv) {}
127static inline int pci_create_newid_file(struct pci_driver *drv)
128{
129 return 0;
130}
Greg Kroah-Hartman03d43b12007-11-28 12:23:18 -0800131static inline void pci_remove_newid_file(struct pci_driver *drv) {}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132#endif
133
134/**
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700135 * pci_match_id - See if a pci device matches a given pci_id table
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 * @ids: array of PCI device id structures to search in
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700137 * @dev: the PCI device structure to match against.
138 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 * Used by a driver to check whether a PCI device present in the
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700140 * system is in its list of supported devices. Returns the matching
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 * pci_device_id structure or %NULL if there is no match.
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700142 *
Randy Dunlap8b607562007-05-09 07:19:14 +0200143 * Deprecated, don't use this as it will not catch any dynamic ids
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700144 * that a driver might want to check for.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 */
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700146const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
147 struct pci_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148{
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700149 if (ids) {
150 while (ids->vendor || ids->subvendor || ids->class_mask) {
151 if (pci_match_one_device(ids, dev))
152 return ids;
153 ids++;
154 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 }
156 return NULL;
157}
158
159/**
Randy Dunlapae9608a2007-01-09 21:41:01 -0800160 * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700161 * @drv: the PCI driver to match against
Henrik Kretzschmar39ba4872006-08-15 10:57:16 +0200162 * @dev: the PCI device structure to match against
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700163 *
164 * Used by a driver to check whether a PCI device present in the
165 * system is in its list of supported devices. Returns the matching
166 * pci_device_id structure or %NULL if there is no match.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 */
Adrian Bunkd73460d2007-10-24 18:27:18 +0200168static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
169 struct pci_dev *dev)
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700170{
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700171 struct pci_dynid *dynid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
Russell King7461b602006-11-29 21:18:04 +0000173 /* Look at the dynamic ids first, before the static ones */
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700174 spin_lock(&drv->dynids.lock);
175 list_for_each_entry(dynid, &drv->dynids.list, node) {
176 if (pci_match_one_device(&dynid->id, dev)) {
177 spin_unlock(&drv->dynids.lock);
178 return &dynid->id;
179 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 }
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700181 spin_unlock(&drv->dynids.lock);
Russell King7461b602006-11-29 21:18:04 +0000182
183 return pci_match_id(drv->id_table, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184}
185
Andi Kleend42c6992005-07-06 19:56:03 +0200186static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
187 const struct pci_device_id *id)
188{
189 int error;
190#ifdef CONFIG_NUMA
191 /* Execute driver initialization on node where the
192 device's bus is attached to. This way the driver likely
193 allocates its local memory on the right node without
194 any need to change it. */
195 struct mempolicy *oldpol;
196 cpumask_t oldmask = current->cpus_allowed;
Yinghai Lu4efeb4d2008-05-12 21:21:05 +0200197 int node = dev_to_node(&dev->dev);
Mike Travisf70316d2008-04-04 18:11:06 -0700198
199 if (node >= 0) {
200 node_to_cpumask_ptr(nodecpumask, node);
201 set_cpus_allowed_ptr(current, nodecpumask);
202 }
Andi Kleend42c6992005-07-06 19:56:03 +0200203 /* And set default memory allocation policy */
204 oldpol = current->mempolicy;
Lee Schermerhorn74e27e42007-11-21 15:07:05 -0800205 current->mempolicy = NULL; /* fall back to system default policy */
Andi Kleend42c6992005-07-06 19:56:03 +0200206#endif
207 error = drv->probe(dev, id);
208#ifdef CONFIG_NUMA
Mike Travisf70316d2008-04-04 18:11:06 -0700209 set_cpus_allowed_ptr(current, &oldmask);
Andi Kleend42c6992005-07-06 19:56:03 +0200210 current->mempolicy = oldpol;
211#endif
212 return error;
213}
214
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215/**
216 * __pci_device_probe()
Randy Dunlap8f7020d2005-10-23 11:57:38 -0700217 * @drv: driver to call to check if it wants the PCI device
218 * @pci_dev: PCI device being probed
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 *
Randy Dunlap8f7020d2005-10-23 11:57:38 -0700220 * returns 0 on success, else error.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 * side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
222 */
223static int
224__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700225{
226 const struct pci_device_id *id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 int error = 0;
228
229 if (!pci_dev->driver && drv->probe) {
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700230 error = -ENODEV;
231
232 id = pci_match_device(drv, pci_dev);
233 if (id)
Andi Kleend42c6992005-07-06 19:56:03 +0200234 error = pci_call_probe(drv, pci_dev, id);
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700235 if (error >= 0) {
236 pci_dev->driver = drv;
237 error = 0;
238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 }
240 return error;
241}
242
243static int pci_device_probe(struct device * dev)
244{
245 int error = 0;
246 struct pci_driver *drv;
247 struct pci_dev *pci_dev;
248
249 drv = to_pci_driver(dev->driver);
250 pci_dev = to_pci_dev(dev);
251 pci_dev_get(pci_dev);
252 error = __pci_device_probe(drv, pci_dev);
253 if (error)
254 pci_dev_put(pci_dev);
255
256 return error;
257}
258
259static int pci_device_remove(struct device * dev)
260{
261 struct pci_dev * pci_dev = to_pci_dev(dev);
262 struct pci_driver * drv = pci_dev->driver;
263
264 if (drv) {
265 if (drv->remove)
266 drv->remove(pci_dev);
267 pci_dev->driver = NULL;
268 }
269
270 /*
Shaohua Li2449e062006-10-20 14:45:32 -0700271 * If the device is still on, set the power state as "unknown",
272 * since it might change by the next time we load the driver.
273 */
274 if (pci_dev->current_state == PCI_D0)
275 pci_dev->current_state = PCI_UNKNOWN;
276
277 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 * We would love to complain here if pci_dev->is_enabled is set, that
279 * the driver should have called pci_disable_device(), but the
280 * unfortunate fact is there are too many odd BIOS and bridge setups
281 * that don't like drivers doing that all of the time.
282 * Oh well, we can dream of sane hardware when we sleep, no matter how
283 * horrible the crap we have to deal with is when we are awake...
284 */
285
286 pci_dev_put(pci_dev);
287 return 0;
288}
289
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200290static void pci_device_shutdown(struct device *dev)
291{
292 struct pci_dev *pci_dev = to_pci_dev(dev);
293 struct pci_driver *drv = pci_dev->driver;
294
295 if (drv && drv->shutdown)
296 drv->shutdown(pci_dev);
297 pci_msi_shutdown(pci_dev);
298 pci_msix_shutdown(pci_dev);
299}
300
301#ifdef CONFIG_PM_SLEEP
302
303/*
304 * Default "suspend" method for devices that have no driver provided suspend,
305 * or not even a driver at all.
306 */
307static void pci_default_pm_suspend(struct pci_dev *pci_dev)
308{
309 pci_save_state(pci_dev);
310 /*
311 * mark its power state as "unknown", since we don't know if
312 * e.g. the BIOS will change its device state when we suspend.
313 */
314 if (pci_dev->current_state == PCI_D0)
315 pci_dev->current_state = PCI_UNKNOWN;
316}
317
318/*
319 * Default "resume" method for devices that have no driver provided resume,
320 * or not even a driver at all.
321 */
322static int pci_default_pm_resume(struct pci_dev *pci_dev)
323{
324 int retval = 0;
325
326 /* restore the PCI config space */
327 pci_restore_state(pci_dev);
328 /* if the device was enabled before suspend, reenable */
329 retval = pci_reenable_device(pci_dev);
330 /*
331 * if the device was busmaster before the suspend, make it busmaster
332 * again
333 */
334 if (pci_dev->is_busmaster)
335 pci_set_master(pci_dev);
336
337 return retval;
338}
339
340static int pci_legacy_suspend(struct device *dev, pm_message_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341{
342 struct pci_dev * pci_dev = to_pci_dev(dev);
343 struct pci_driver * drv = pci_dev->driver;
344 int i = 0;
345
Andrew Morton02669492006-03-23 01:38:34 -0800346 if (drv && drv->suspend) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 i = drv->suspend(pci_dev, state);
Andrew Morton02669492006-03-23 01:38:34 -0800348 suspend_report_result(drv->suspend, i);
349 } else {
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200350 pci_default_pm_suspend(pci_dev);
Andrew Morton02669492006-03-23 01:38:34 -0800351 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 return i;
353}
354
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200355static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)
Linus Torvaldscbd69db2006-06-24 14:50:29 -0700356{
357 struct pci_dev * pci_dev = to_pci_dev(dev);
358 struct pci_driver * drv = pci_dev->driver;
359 int i = 0;
360
361 if (drv && drv->suspend_late) {
362 i = drv->suspend_late(pci_dev, state);
363 suspend_report_result(drv->suspend_late, i);
364 }
365 return i;
366}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200368static int pci_legacy_resume(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369{
Jean Delvare8d92bc22006-04-18 14:49:56 +0200370 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 struct pci_dev * pci_dev = to_pci_dev(dev);
372 struct pci_driver * drv = pci_dev->driver;
373
374 if (drv && drv->resume)
Jean Delvare8d92bc22006-04-18 14:49:56 +0200375 error = drv->resume(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 else
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200377 error = pci_default_pm_resume(pci_dev);
Jean Delvare8d92bc22006-04-18 14:49:56 +0200378 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379}
380
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200381static int pci_legacy_resume_early(struct device *dev)
Linus Torvaldscbd69db2006-06-24 14:50:29 -0700382{
383 int error = 0;
384 struct pci_dev * pci_dev = to_pci_dev(dev);
385 struct pci_driver * drv = pci_dev->driver;
386
387 if (drv && drv->resume_early)
388 error = drv->resume_early(pci_dev);
389 return error;
390}
391
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200392static int pci_pm_prepare(struct device *dev)
393{
394 struct device_driver *drv = dev->driver;
395 int error = 0;
396
397 if (drv && drv->pm && drv->pm->prepare)
398 error = drv->pm->prepare(dev);
399
400 return error;
401}
402
403static void pci_pm_complete(struct device *dev)
404{
405 struct device_driver *drv = dev->driver;
406
407 if (drv && drv->pm && drv->pm->complete)
408 drv->pm->complete(dev);
409}
410
411#ifdef CONFIG_SUSPEND
412
413static int pci_pm_suspend(struct device *dev)
414{
415 struct pci_dev *pci_dev = to_pci_dev(dev);
416 struct device_driver *drv = dev->driver;
417 int error = 0;
418
419 if (drv && drv->pm) {
420 if (drv->pm->suspend) {
421 error = drv->pm->suspend(dev);
422 suspend_report_result(drv->pm->suspend, error);
423 } else {
424 pci_default_pm_suspend(pci_dev);
425 }
426 } else {
427 error = pci_legacy_suspend(dev, PMSG_SUSPEND);
428 }
429 pci_fixup_device(pci_fixup_suspend, pci_dev);
430
431 return error;
432}
433
434static int pci_pm_suspend_noirq(struct device *dev)
Greg KHc8958172005-04-08 14:53:31 +0900435{
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200436 struct device_driver *drv = dev->driver;
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200437 int error = 0;
Greg KHc8958172005-04-08 14:53:31 +0900438
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200439 if (drv && drv->pm) {
440 if (drv->pm->suspend_noirq) {
441 error = drv->pm->suspend_noirq(dev);
442 suspend_report_result(drv->pm->suspend_noirq, error);
443 }
444 } else {
445 error = pci_legacy_suspend_late(dev, PMSG_SUSPEND);
446 }
447
448 return error;
Greg KHc8958172005-04-08 14:53:31 +0900449}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200451static int pci_pm_resume(struct device *dev)
452{
453 struct pci_dev *pci_dev = to_pci_dev(dev);
454 struct device_driver *drv = dev->driver;
455 int error;
456
457 pci_fixup_device(pci_fixup_resume, pci_dev);
458
459 if (drv && drv->pm) {
460 error = drv->pm->resume ? drv->pm->resume(dev) :
461 pci_default_pm_resume(pci_dev);
462 } else {
463 error = pci_legacy_resume(dev);
464 }
465
466 return error;
467}
468
469static int pci_pm_resume_noirq(struct device *dev)
470{
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200471 struct device_driver *drv = dev->driver;
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200472 int error = 0;
473
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200474 pci_fixup_device(pci_fixup_resume_early, to_pci_dev(dev));
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200475
476 if (drv && drv->pm) {
477 if (drv->pm->resume_noirq)
478 error = drv->pm->resume_noirq(dev);
479 } else {
480 error = pci_legacy_resume_early(dev);
481 }
482
483 return error;
484}
485
486#else /* !CONFIG_SUSPEND */
487
488#define pci_pm_suspend NULL
489#define pci_pm_suspend_noirq NULL
490#define pci_pm_resume NULL
491#define pci_pm_resume_noirq NULL
492
493#endif /* !CONFIG_SUSPEND */
494
495#ifdef CONFIG_HIBERNATION
496
497static int pci_pm_freeze(struct device *dev)
498{
499 struct pci_dev *pci_dev = to_pci_dev(dev);
500 struct device_driver *drv = dev->driver;
501 int error = 0;
502
503 if (drv && drv->pm) {
504 if (drv->pm->freeze) {
505 error = drv->pm->freeze(dev);
506 suspend_report_result(drv->pm->freeze, error);
507 } else {
508 pci_default_pm_suspend(pci_dev);
509 }
510 } else {
511 error = pci_legacy_suspend(dev, PMSG_FREEZE);
512 pci_fixup_device(pci_fixup_suspend, pci_dev);
513 }
514
515 return error;
516}
517
518static int pci_pm_freeze_noirq(struct device *dev)
519{
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200520 struct device_driver *drv = dev->driver;
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200521 int error = 0;
522
523 if (drv && drv->pm) {
524 if (drv->pm->freeze_noirq) {
525 error = drv->pm->freeze_noirq(dev);
526 suspend_report_result(drv->pm->freeze_noirq, error);
527 }
528 } else {
529 error = pci_legacy_suspend_late(dev, PMSG_FREEZE);
530 }
531
532 return error;
533}
534
535static int pci_pm_thaw(struct device *dev)
536{
537 struct device_driver *drv = dev->driver;
538 int error = 0;
539
540 if (drv && drv->pm) {
541 if (drv->pm->thaw)
542 error = drv->pm->thaw(dev);
543 } else {
544 pci_fixup_device(pci_fixup_resume, to_pci_dev(dev));
545 error = pci_legacy_resume(dev);
546 }
547
548 return error;
549}
550
551static int pci_pm_thaw_noirq(struct device *dev)
552{
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200553 struct device_driver *drv = dev->driver;
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200554 int error = 0;
555
556 if (drv && drv->pm) {
557 if (drv->pm->thaw_noirq)
558 error = drv->pm->thaw_noirq(dev);
559 } else {
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200560 pci_fixup_device(pci_fixup_resume_early, to_pci_dev(dev));
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200561 error = pci_legacy_resume_early(dev);
562 }
563
564 return error;
565}
566
567static int pci_pm_poweroff(struct device *dev)
568{
569 struct device_driver *drv = dev->driver;
570 int error = 0;
571
572 pci_fixup_device(pci_fixup_suspend, to_pci_dev(dev));
573
574 if (drv && drv->pm) {
575 if (drv->pm->poweroff) {
576 error = drv->pm->poweroff(dev);
577 suspend_report_result(drv->pm->poweroff, error);
578 }
579 } else {
580 error = pci_legacy_suspend(dev, PMSG_HIBERNATE);
581 }
582
583 return error;
584}
585
586static int pci_pm_poweroff_noirq(struct device *dev)
587{
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200588 struct device_driver *drv = dev->driver;
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200589 int error = 0;
590
591 if (drv && drv->pm) {
592 if (drv->pm->poweroff_noirq) {
593 error = drv->pm->poweroff_noirq(dev);
594 suspend_report_result(drv->pm->poweroff_noirq, error);
595 }
596 } else {
597 error = pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
598 }
599
600 return error;
601}
602
603static int pci_pm_restore(struct device *dev)
604{
605 struct pci_dev *pci_dev = to_pci_dev(dev);
606 struct device_driver *drv = dev->driver;
607 int error;
608
609 if (drv && drv->pm) {
610 error = drv->pm->restore ? drv->pm->restore(dev) :
611 pci_default_pm_resume(pci_dev);
612 } else {
613 error = pci_legacy_resume(dev);
614 }
615 pci_fixup_device(pci_fixup_resume, pci_dev);
616
617 return error;
618}
619
620static int pci_pm_restore_noirq(struct device *dev)
621{
622 struct pci_dev *pci_dev = to_pci_dev(dev);
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200623 struct device_driver *drv = dev->driver;
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200624 int error = 0;
625
626 pci_fixup_device(pci_fixup_resume, pci_dev);
627
628 if (drv && drv->pm) {
629 if (drv->pm->restore_noirq)
630 error = drv->pm->restore_noirq(dev);
631 } else {
632 error = pci_legacy_resume_early(dev);
633 }
634 pci_fixup_device(pci_fixup_resume_early, pci_dev);
635
636 return error;
637}
638
639#else /* !CONFIG_HIBERNATION */
640
641#define pci_pm_freeze NULL
642#define pci_pm_freeze_noirq NULL
643#define pci_pm_thaw NULL
644#define pci_pm_thaw_noirq NULL
645#define pci_pm_poweroff NULL
646#define pci_pm_poweroff_noirq NULL
647#define pci_pm_restore NULL
648#define pci_pm_restore_noirq NULL
649
650#endif /* !CONFIG_HIBERNATION */
651
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200652struct dev_pm_ops pci_dev_pm_ops = {
653 .prepare = pci_pm_prepare,
654 .complete = pci_pm_complete,
655 .suspend = pci_pm_suspend,
656 .resume = pci_pm_resume,
657 .freeze = pci_pm_freeze,
658 .thaw = pci_pm_thaw,
659 .poweroff = pci_pm_poweroff,
660 .restore = pci_pm_restore,
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200661 .suspend_noirq = pci_pm_suspend_noirq,
662 .resume_noirq = pci_pm_resume_noirq,
663 .freeze_noirq = pci_pm_freeze_noirq,
664 .thaw_noirq = pci_pm_thaw_noirq,
665 .poweroff_noirq = pci_pm_poweroff_noirq,
666 .restore_noirq = pci_pm_restore_noirq,
667};
668
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200669#define PCI_PM_OPS_PTR (&pci_dev_pm_ops)
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200670
671#else /* !CONFIG_PM_SLEEP */
672
673#define PCI_PM_OPS_PTR NULL
674
675#endif /* !CONFIG_PM_SLEEP */
676
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677/**
Laurent riffard863b18f2005-10-27 23:12:54 +0200678 * __pci_register_driver - register a new pci driver
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 * @drv: the driver structure to register
Laurent riffard863b18f2005-10-27 23:12:54 +0200680 * @owner: owner module of drv
Randy Dunlapf95d8822007-02-10 14:41:56 -0800681 * @mod_name: module name string
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 *
683 * Adds the driver structure to the list of registered drivers.
684 * Returns a negative value on error, otherwise 0.
Steven Coleeaae4b32005-05-03 18:38:30 -0600685 * If no error occurred, the driver remains registered even if
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 * no device was claimed during registration.
687 */
Greg Kroah-Hartman725522b2007-01-15 11:50:02 -0800688int __pci_register_driver(struct pci_driver *drv, struct module *owner,
689 const char *mod_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690{
691 int error;
692
693 /* initialize common driver fields */
694 drv->driver.name = drv->name;
695 drv->driver.bus = &pci_bus_type;
Laurent riffard863b18f2005-10-27 23:12:54 +0200696 drv->driver.owner = owner;
Greg Kroah-Hartman725522b2007-01-15 11:50:02 -0800697 drv->driver.mod_name = mod_name;
Alan Cox50b00752006-08-16 17:42:18 +0100698
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700699 spin_lock_init(&drv->dynids.lock);
700 INIT_LIST_HEAD(&drv->dynids.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701
702 /* register with core */
703 error = driver_register(&drv->driver);
Akinobu Mita50bf14b2006-11-08 19:53:59 -0800704 if (error)
705 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
Akinobu Mita50bf14b2006-11-08 19:53:59 -0800707 error = pci_create_newid_file(drv);
708 if (error)
709 driver_unregister(&drv->driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
711 return error;
712}
713
714/**
715 * pci_unregister_driver - unregister a pci driver
716 * @drv: the driver structure to unregister
717 *
718 * Deletes the driver structure from the list of registered PCI drivers,
719 * gives it a chance to clean up by calling its remove() function for
720 * each device it was responsible for, and marks those devices as
721 * driverless.
722 */
723
724void
725pci_unregister_driver(struct pci_driver *drv)
726{
Greg Kroah-Hartman03d43b12007-11-28 12:23:18 -0800727 pci_remove_newid_file(drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 driver_unregister(&drv->driver);
729 pci_free_dynids(drv);
730}
731
732static struct pci_driver pci_compat_driver = {
733 .name = "compat"
734};
735
736/**
737 * pci_dev_driver - get the pci_driver of a device
738 * @dev: the device to query
739 *
740 * Returns the appropriate pci_driver structure or %NULL if there is no
741 * registered driver for the device.
742 */
743struct pci_driver *
744pci_dev_driver(const struct pci_dev *dev)
745{
746 if (dev->driver)
747 return dev->driver;
748 else {
749 int i;
750 for(i=0; i<=PCI_ROM_RESOURCE; i++)
751 if (dev->resource[i].flags & IORESOURCE_BUSY)
752 return &pci_compat_driver;
753 }
754 return NULL;
755}
756
757/**
758 * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 * @dev: the PCI device structure to match against
Randy Dunlap8f7020d2005-10-23 11:57:38 -0700760 * @drv: the device driver to search for matching PCI device id structures
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 *
762 * Used by a driver to check whether a PCI device present in the
Randy Dunlap8f7020d2005-10-23 11:57:38 -0700763 * system is in its list of supported devices. Returns the matching
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 * pci_device_id structure or %NULL if there is no match.
765 */
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700766static int pci_bus_match(struct device *dev, struct device_driver *drv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767{
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700768 struct pci_dev *pci_dev = to_pci_dev(dev);
769 struct pci_driver *pci_drv = to_pci_driver(drv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 const struct pci_device_id *found_id;
771
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700772 found_id = pci_match_device(pci_drv, pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 if (found_id)
774 return 1;
775
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700776 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777}
778
779/**
780 * pci_dev_get - increments the reference count of the pci device structure
781 * @dev: the device being referenced
782 *
783 * Each live reference to a device should be refcounted.
784 *
785 * Drivers for PCI devices should normally record such references in
786 * their probe() methods, when they bind to a device, and release
787 * them by calling pci_dev_put(), in their disconnect() methods.
788 *
789 * A pointer to the device with the incremented reference counter is returned.
790 */
791struct pci_dev *pci_dev_get(struct pci_dev *dev)
792{
793 if (dev)
794 get_device(&dev->dev);
795 return dev;
796}
797
798/**
799 * pci_dev_put - release a use of the pci device structure
800 * @dev: device that's been disconnected
801 *
802 * Must be called when a user of a device is finished with it. When the last
803 * user of the device calls this function, the memory of the device is freed.
804 */
805void pci_dev_put(struct pci_dev *dev)
806{
807 if (dev)
808 put_device(&dev->dev);
809}
810
811#ifndef CONFIG_HOTPLUG
Kay Sievers7eff2e72007-08-14 15:15:12 +0200812int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813{
814 return -ENODEV;
815}
816#endif
817
818struct bus_type pci_bus_type = {
819 .name = "pci",
820 .match = pci_bus_match,
Kay Sievers312c0042005-11-16 09:00:00 +0100821 .uevent = pci_uevent,
Russell Kingb15d6862006-01-05 14:30:22 +0000822 .probe = pci_device_probe,
823 .remove = pci_device_remove,
Linus Torvaldscbd69db2006-06-24 14:50:29 -0700824 .shutdown = pci_device_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 .dev_attrs = pci_dev_attrs,
Rafael J. Wysockibbb44d92008-05-20 00:49:04 +0200826 .pm = PCI_PM_OPS_PTR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827};
828
829static int __init pci_driver_init(void)
830{
831 return bus_register(&pci_bus_type);
832}
833
834postcore_initcall(pci_driver_init);
835
Greg Kroah-Hartman75865852005-06-30 02:18:12 -0700836EXPORT_SYMBOL(pci_match_id);
Laurent riffard863b18f2005-10-27 23:12:54 +0200837EXPORT_SYMBOL(__pci_register_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838EXPORT_SYMBOL(pci_unregister_driver);
839EXPORT_SYMBOL(pci_dev_driver);
840EXPORT_SYMBOL(pci_bus_type);
841EXPORT_SYMBOL(pci_dev_get);
842EXPORT_SYMBOL(pci_dev_put);