Blame view

drivers/pci/pci-driver.c 30.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * drivers/pci/pci-driver.c
   *
2b9373031   Greg Kroah-Hartman   PCI: remove fooli...
4
5
6
7
8
   * (C) Copyright 2002-2004, 2007 Greg Kroah-Hartman <greg@kroah.com>
   * (C) Copyright 2007 Novell Inc.
   *
   * Released under the GPL v2 only.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
   */
  
  #include <linux/pci.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/device.h>
d42c69972   Andi Kleen   [PATCH] PCI: Run ...
15
  #include <linux/mempolicy.h>
4e57b6817   Tim Schmielau   [PATCH] fix missi...
16
17
  #include <linux/string.h>
  #include <linux/slab.h>
8c65b4a60   Tim Schmielau   [PATCH] fix remai...
18
  #include <linux/sched.h>
873392ca5   Rusty Russell   PCI: work_on_cpu:...
19
  #include <linux/cpu.h>
6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
20
  #include <linux/pm_runtime.h>
eea3fc035   Rafael J. Wysocki   PCI / PM: Detect ...
21
  #include <linux/suspend.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include "pci.h"
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
23
24
25
26
  struct pci_dynid {
  	struct list_head node;
  	struct pci_device_id id;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27

9dba910e9   Tejun Heo   PCI: separate out...
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  /**
   * pci_add_dynid - add a new PCI device ID to this driver and re-probe devices
   * @drv: target pci driver
   * @vendor: PCI vendor ID
   * @device: PCI device ID
   * @subvendor: PCI subvendor ID
   * @subdevice: PCI subdevice ID
   * @class: PCI class
   * @class_mask: PCI class mask
   * @driver_data: private driver data
   *
   * Adds a new dynamic pci device ID to this driver and causes the
   * driver to probe for all devices again.  @drv must have been
   * registered prior to calling this function.
   *
   * CONTEXT:
   * Does GFP_KERNEL allocation.
   *
   * RETURNS:
   * 0 on success, -errno on failure.
   */
  int pci_add_dynid(struct pci_driver *drv,
  		  unsigned int vendor, unsigned int device,
  		  unsigned int subvendor, unsigned int subdevice,
  		  unsigned int class, unsigned int class_mask,
  		  unsigned long driver_data)
  {
  	struct pci_dynid *dynid;
  	int retval;
  
  	dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
  	if (!dynid)
  		return -ENOMEM;
  
  	dynid->id.vendor = vendor;
  	dynid->id.device = device;
  	dynid->id.subvendor = subvendor;
  	dynid->id.subdevice = subdevice;
  	dynid->id.class = class;
  	dynid->id.class_mask = class_mask;
  	dynid->id.driver_data = driver_data;
3d3c2ae11   Greg Kroah-Hartman   [PATCH] PCI: fix ...
69

9dba910e9   Tejun Heo   PCI: separate out...
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  	spin_lock(&drv->dynids.lock);
  	list_add_tail(&dynid->node, &drv->dynids.list);
  	spin_unlock(&drv->dynids.lock);
  
  	get_driver(&drv->driver);
  	retval = driver_attach(&drv->driver);
  	put_driver(&drv->driver);
  
  	return retval;
  }
  
  static void pci_free_dynids(struct pci_driver *drv)
  {
  	struct pci_dynid *dynid, *n;
3d3c2ae11   Greg Kroah-Hartman   [PATCH] PCI: fix ...
84

9dba910e9   Tejun Heo   PCI: separate out...
85
86
87
88
89
90
91
92
93
94
95
96
  	spin_lock(&drv->dynids.lock);
  	list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
  		list_del(&dynid->node);
  		kfree(dynid);
  	}
  	spin_unlock(&drv->dynids.lock);
  }
  
  /*
   * Dynamic device ID manipulation via sysfs is disabled for !CONFIG_HOTPLUG
   */
  #ifdef CONFIG_HOTPLUG
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  /**
9dba910e9   Tejun Heo   PCI: separate out...
98
   * store_new_id - sysfs frontend to pci_add_dynid()
8f7020d36   Randy Dunlap   [PATCH] kernel-do...
99
100
101
   * @driver: target device driver
   * @buf: buffer for scanning device ID data
   * @count: input size
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
   *
9dba910e9   Tejun Heo   PCI: separate out...
103
   * Allow PCI IDs to be added to an existing driver via sysfs.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
   */
f8eb1005a   Randy Dunlap   [PATCH] pci-drive...
105
  static ssize_t
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
  store_new_id(struct device_driver *driver, const char *buf, size_t count)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  	struct pci_driver *pdrv = to_pci_driver(driver);
b41d6cf38   Jean Delvare   PCI: Check dynids...
109
  	const struct pci_device_id *ids = pdrv->id_table;
6ba186361   Jean Delvare   PCI: Require vend...
110
  	__u32 vendor, device, subvendor=PCI_ANY_ID,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
  		subdevice=PCI_ANY_ID, class=0, class_mask=0;
  	unsigned long driver_data=0;
  	int fields=0;
9dba910e9   Tejun Heo   PCI: separate out...
114
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115

b41d6cf38   Jean Delvare   PCI: Check dynids...
116
  	fields = sscanf(buf, "%x %x %x %x %x %x %lx",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
  			&vendor, &device, &subvendor, &subdevice,
  			&class, &class_mask, &driver_data);
6ba186361   Jean Delvare   PCI: Require vend...
119
  	if (fields < 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  		return -EINVAL;
b41d6cf38   Jean Delvare   PCI: Check dynids...
121
122
  	/* Only accept driver_data values that match an existing id_table
  	   entry */
2debb4d20   Chris Wright   PCI: allow pci dr...
123
124
125
126
127
128
129
130
  	if (ids) {
  		retval = -EINVAL;
  		while (ids->vendor || ids->subvendor || ids->class_mask) {
  			if (driver_data == ids->driver_data) {
  				retval = 0;
  				break;
  			}
  			ids++;
b41d6cf38   Jean Delvare   PCI: Check dynids...
131
  		}
2debb4d20   Chris Wright   PCI: allow pci dr...
132
133
  		if (retval)	/* No match */
  			return retval;
b41d6cf38   Jean Delvare   PCI: Check dynids...
134
  	}
b41d6cf38   Jean Delvare   PCI: Check dynids...
135

9dba910e9   Tejun Heo   PCI: separate out...
136
137
  	retval = pci_add_dynid(pdrv, vendor, device, subvendor, subdevice,
  			       class, class_mask, driver_data);
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
138
139
  	if (retval)
  		return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
  	return count;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143

0994375e9   Chris Wright   PCI: add remove_i...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  /**
   * store_remove_id - remove a PCI device ID from this driver
   * @driver: target device driver
   * @buf: buffer for scanning device ID data
   * @count: input size
   *
   * Removes a dynamic pci device ID to this driver.
   */
  static ssize_t
  store_remove_id(struct device_driver *driver, const char *buf, size_t count)
  {
  	struct pci_dynid *dynid, *n;
  	struct pci_driver *pdrv = to_pci_driver(driver);
  	__u32 vendor, device, subvendor = PCI_ANY_ID,
  		subdevice = PCI_ANY_ID, class = 0, class_mask = 0;
  	int fields = 0;
  	int retval = -ENODEV;
  
  	fields = sscanf(buf, "%x %x %x %x %x %x",
  			&vendor, &device, &subvendor, &subdevice,
  			&class, &class_mask);
  	if (fields < 2)
  		return -EINVAL;
  
  	spin_lock(&pdrv->dynids.lock);
  	list_for_each_entry_safe(dynid, n, &pdrv->dynids.list, node) {
  		struct pci_device_id *id = &dynid->id;
  		if ((id->vendor == vendor) &&
  		    (id->device == device) &&
  		    (subvendor == PCI_ANY_ID || id->subvendor == subvendor) &&
  		    (subdevice == PCI_ANY_ID || id->subdevice == subdevice) &&
  		    !((id->class ^ class) & class_mask)) {
  			list_del(&dynid->node);
  			kfree(dynid);
  			retval = 0;
  			break;
  		}
  	}
  	spin_unlock(&pdrv->dynids.lock);
  
  	if (retval)
  		return retval;
  	return count;
  }
  static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
192
193
  static int
  pci_create_newid_file(struct pci_driver *drv)
  {
  	int error = 0;
  	if (drv->probe != NULL)
03d43b19b   Greg Kroah-Hartman   PCI: use proper c...
194
  		error = driver_create_file(&drv->driver, &driver_attr_new_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
  	return error;
  }
03d43b19b   Greg Kroah-Hartman   PCI: use proper c...
197
198
199
200
  static void pci_remove_newid_file(struct pci_driver *drv)
  {
  	driver_remove_file(&drv->driver, &driver_attr_new_id);
  }
0994375e9   Chris Wright   PCI: add remove_i...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  
  static int
  pci_create_removeid_file(struct pci_driver *drv)
  {
  	int error = 0;
  	if (drv->probe != NULL)
  		error = driver_create_file(&drv->driver,&driver_attr_remove_id);
  	return error;
  }
  
  static void pci_remove_removeid_file(struct pci_driver *drv)
  {
  	driver_remove_file(&drv->driver, &driver_attr_remove_id);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  #else /* !CONFIG_HOTPLUG */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
  static inline int pci_create_newid_file(struct pci_driver *drv)
  {
  	return 0;
  }
03d43b19b   Greg Kroah-Hartman   PCI: use proper c...
220
  static inline void pci_remove_newid_file(struct pci_driver *drv) {}
0994375e9   Chris Wright   PCI: add remove_i...
221
222
223
224
225
  static inline int pci_create_removeid_file(struct pci_driver *drv)
  {
  	return 0;
  }
  static inline void pci_remove_removeid_file(struct pci_driver *drv) {}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
228
  #endif
  
  /**
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
229
   * pci_match_id - See if a pci device matches a given pci_id table
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
   * @ids: array of PCI device id structures to search in
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
231
232
   * @dev: the PCI device structure to match against.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
   * Used by a driver to check whether a PCI device present in the
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
234
   * system is in its list of supported devices.  Returns the matching
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
   * pci_device_id structure or %NULL if there is no match.
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
236
   *
8b60756a6   Randy Dunlap   Fix more "depreca...
237
   * Deprecated, don't use this as it will not catch any dynamic ids
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
238
   * that a driver might want to check for.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
   */
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
240
241
  const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
  					 struct pci_dev *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
  {
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
243
244
245
246
247
248
  	if (ids) {
  		while (ids->vendor || ids->subvendor || ids->class_mask) {
  			if (pci_match_one_device(ids, dev))
  				return ids;
  			ids++;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
253
  	}
  	return NULL;
  }
  
  /**
ae9608af9   Randy Dunlap   PCI: fix pci-driv...
254
   * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
255
   * @drv: the PCI driver to match against
39ba487fe   Henrik Kretzschmar   [PATCH] PCI: kern...
256
   * @dev: the PCI device structure to match against
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
257
258
259
260
   *
   * Used by a driver to check whether a PCI device present in the
   * system is in its list of supported devices.  Returns the matching
   * pci_device_id structure or %NULL if there is no match.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
   */
d73460d79   Adrian Bunk   PCI: make pci_mat...
262
263
  static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
  						    struct pci_dev *dev)
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
264
  {
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
265
  	struct pci_dynid *dynid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266

7461b60af   Russell King   PCI: use /sys/bus...
267
  	/* Look at the dynamic ids first, before the static ones */
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
268
269
270
271
272
273
  	spin_lock(&drv->dynids.lock);
  	list_for_each_entry(dynid, &drv->dynids.list, node) {
  		if (pci_match_one_device(&dynid->id, dev)) {
  			spin_unlock(&drv->dynids.lock);
  			return &dynid->id;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  	}
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
275
  	spin_unlock(&drv->dynids.lock);
7461b60af   Russell King   PCI: use /sys/bus...
276
277
  
  	return pci_match_id(drv->id_table, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
  }
873392ca5   Rusty Russell   PCI: work_on_cpu:...
279
280
281
282
283
284
285
286
287
  struct drv_dev_and_id {
  	struct pci_driver *drv;
  	struct pci_dev *dev;
  	const struct pci_device_id *id;
  };
  
  static long local_pci_probe(void *_ddi)
  {
  	struct drv_dev_and_id *ddi = _ddi;
f3ec4f87d   Alan Stern   PCI: change devic...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  	struct device *dev = &ddi->dev->dev;
  	int rc;
  
  	/* Unbound PCI devices are always set to disabled and suspended.
  	 * During probe, the device is set to enabled and active and the
  	 * usage count is incremented.  If the driver supports runtime PM,
  	 * it should call pm_runtime_put_noidle() in its probe routine and
  	 * pm_runtime_get_noresume() in its remove routine.
  	 */
  	pm_runtime_get_noresume(dev);
  	pm_runtime_set_active(dev);
  	pm_runtime_enable(dev);
  
  	rc = ddi->drv->probe(ddi->dev, ddi->id);
  	if (rc) {
  		pm_runtime_disable(dev);
  		pm_runtime_set_suspended(dev);
  		pm_runtime_put_noidle(dev);
  	}
  	return rc;
873392ca5   Rusty Russell   PCI: work_on_cpu:...
308
  }
d42c69972   Andi Kleen   [PATCH] PCI: Run ...
309
310
311
  static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
  			  const struct pci_device_id *id)
  {
873392ca5   Rusty Russell   PCI: work_on_cpu:...
312
313
314
315
316
317
318
319
  	int error, node;
  	struct drv_dev_and_id ddi = { drv, dev, id };
  
  	/* Execute driver initialization on node where the device's
  	   bus is attached to.  This way the driver likely allocates
  	   its local memory on the right node without any need to
  	   change it. */
  	node = dev_to_node(&dev->dev);
f70316dac   Mike Travis   generic: use new ...
320
  	if (node >= 0) {
873392ca5   Rusty Russell   PCI: work_on_cpu:...
321
  		int cpu;
873392ca5   Rusty Russell   PCI: work_on_cpu:...
322
323
  
  		get_online_cpus();
a70f73028   Rusty Russell   cpumask: replace ...
324
  		cpu = cpumask_any_and(cpumask_of_node(node), cpu_online_mask);
873392ca5   Rusty Russell   PCI: work_on_cpu:...
325
326
327
328
329
330
331
  		if (cpu < nr_cpu_ids)
  			error = work_on_cpu(cpu, local_pci_probe, &ddi);
  		else
  			error = local_pci_probe(&ddi);
  		put_online_cpus();
  	} else
  		error = local_pci_probe(&ddi);
d42c69972   Andi Kleen   [PATCH] PCI: Run ...
332
333
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
  /**
23ea3793f   Randy Dunlap   PCI: fix __pci_de...
335
   * __pci_device_probe - check if a driver wants to claim a specific PCI device
8f7020d36   Randy Dunlap   [PATCH] kernel-do...
336
337
   * @drv: driver to call to check if it wants the PCI device
   * @pci_dev: PCI device being probed
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
   * 
8f7020d36   Randy Dunlap   [PATCH] kernel-do...
339
   * returns 0 on success, else error.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
342
343
   * side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
   */
  static int
  __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
344
345
  {
  	const struct pci_device_id *id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
348
  	int error = 0;
  
  	if (!pci_dev->driver && drv->probe) {
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
349
350
351
352
  		error = -ENODEV;
  
  		id = pci_match_device(drv, pci_dev);
  		if (id)
d42c69972   Andi Kleen   [PATCH] PCI: Run ...
353
  			error = pci_call_probe(drv, pci_dev, id);
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
354
355
356
357
  		if (error >= 0) {
  			pci_dev->driver = drv;
  			error = 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
  	}
  	return error;
  }
  
  static int pci_device_probe(struct device * dev)
  {
  	int error = 0;
  	struct pci_driver *drv;
  	struct pci_dev *pci_dev;
  
  	drv = to_pci_driver(dev->driver);
  	pci_dev = to_pci_dev(dev);
  	pci_dev_get(pci_dev);
  	error = __pci_device_probe(drv, pci_dev);
  	if (error)
  		pci_dev_put(pci_dev);
  
  	return error;
  }
  
  static int pci_device_remove(struct device * dev)
  {
  	struct pci_dev * pci_dev = to_pci_dev(dev);
  	struct pci_driver * drv = pci_dev->driver;
  
  	if (drv) {
f3ec4f87d   Alan Stern   PCI: change devic...
384
385
  		if (drv->remove) {
  			pm_runtime_get_sync(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
  			drv->remove(pci_dev);
f3ec4f87d   Alan Stern   PCI: change devic...
387
388
  			pm_runtime_put_noidle(dev);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
390
  		pci_dev->driver = NULL;
  	}
f3ec4f87d   Alan Stern   PCI: change devic...
391
392
393
394
  	/* Undo the runtime PM settings in local_pci_probe() */
  	pm_runtime_disable(dev);
  	pm_runtime_set_suspended(dev);
  	pm_runtime_put_noidle(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  	/*
2449e06a5   Shaohua Li   PCI: reset pci de...
396
397
398
399
400
401
402
  	 * If the device is still on, set the power state as "unknown",
  	 * since it might change by the next time we load the driver.
  	 */
  	if (pci_dev->current_state == PCI_D0)
  		pci_dev->current_state = PCI_UNKNOWN;
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
406
407
408
409
410
411
412
413
  	 * We would love to complain here if pci_dev->is_enabled is set, that
  	 * the driver should have called pci_disable_device(), but the
  	 * unfortunate fact is there are too many odd BIOS and bridge setups
  	 * that don't like drivers doing that all of the time.  
  	 * Oh well, we can dream of sane hardware when we sleep, no matter how
  	 * horrible the crap we have to deal with is when we are awake...
  	 */
  
  	pci_dev_put(pci_dev);
  	return 0;
  }
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
414
415
416
417
418
419
420
421
422
423
  static void pci_device_shutdown(struct device *dev)
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	struct pci_driver *drv = pci_dev->driver;
  
  	if (drv && drv->shutdown)
  		drv->shutdown(pci_dev);
  	pci_msi_shutdown(pci_dev);
  	pci_msix_shutdown(pci_dev);
  }
aa3386015   Rafael J. Wysocki   PM: Remove CONFIG...
424
  #ifdef CONFIG_PM
6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
  
  /* Auxiliary functions used for system resume and run-time resume. */
  
  /**
   * pci_restore_standard_config - restore standard config registers of PCI device
   * @pci_dev: PCI device to handle
   */
  static int pci_restore_standard_config(struct pci_dev *pci_dev)
  {
  	pci_update_current_state(pci_dev, PCI_UNKNOWN);
  
  	if (pci_dev->current_state != PCI_D0) {
  		int error = pci_set_power_state(pci_dev, PCI_D0);
  		if (error)
  			return error;
  	}
1d3c16a81   Jon Mason   PCI: make pci_res...
441
442
  	pci_restore_state(pci_dev);
  	return 0;
6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
443
444
445
446
447
448
449
450
451
  }
  
  static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
  {
  	pci_restore_standard_config(pci_dev);
  	pci_fixup_device(pci_fixup_resume_early, pci_dev);
  }
  
  #endif
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
452
453
454
455
  #ifdef CONFIG_PM_SLEEP
  
  /*
   * Default "suspend" method for devices that have no driver provided suspend,
fa58d305d   Rafael J. Wysocki   PCI PM: Add suspe...
456
   * or not even a driver at all (second part).
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
457
   */
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
458
  static void pci_pm_set_unknown_state(struct pci_dev *pci_dev)
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
459
  {
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
460
461
462
463
464
465
466
467
468
469
  	/*
  	 * mark its power state as "unknown", since we don't know if
  	 * e.g. the BIOS will change its device state when we suspend.
  	 */
  	if (pci_dev->current_state == PCI_D0)
  		pci_dev->current_state = PCI_UNKNOWN;
  }
  
  /*
   * Default "resume" method for devices that have no driver provided resume,
355a72d75   Rafael J. Wysocki   PCI: Rework defau...
470
471
   * or not even a driver at all (second part).
   */
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
472
  static int pci_pm_reenable_device(struct pci_dev *pci_dev)
355a72d75   Rafael J. Wysocki   PCI: Rework defau...
473
474
  {
  	int retval;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
475
476
477
478
479
480
481
482
483
484
485
486
487
  	/* if the device was enabled before suspend, reenable */
  	retval = pci_reenable_device(pci_dev);
  	/*
  	 * if the device was busmaster before the suspend, make it busmaster
  	 * again
  	 */
  	if (pci_dev->is_busmaster)
  		pci_set_master(pci_dev);
  
  	return retval;
  }
  
  static int pci_legacy_suspend(struct device *dev, pm_message_t state)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
489
490
  {
  	struct pci_dev * pci_dev = to_pci_dev(dev);
  	struct pci_driver * drv = pci_dev->driver;
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
491

026694920   Andrew Morton   [PATCH] pm: print...
492
  	if (drv && drv->suspend) {
99dadce87   Rafael J. Wysocki   PCI PM: Fix savin...
493
  		pci_power_t prev = pci_dev->current_state;
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
494
  		int error;
aa8c6c937   Rafael J. Wysocki   PCI PM: Restore s...
495

57ef80266   Frans Pop   PCI PM: Consisten...
496
497
498
499
  		error = drv->suspend(pci_dev, state);
  		suspend_report_result(drv->suspend, error);
  		if (error)
  			return error;
aa8c6c937   Rafael J. Wysocki   PCI PM: Restore s...
500

46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
501
  		if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
99dadce87   Rafael J. Wysocki   PCI PM: Fix savin...
502
503
504
505
506
  		    && pci_dev->current_state != PCI_UNKNOWN) {
  			WARN_ONCE(pci_dev->current_state != prev,
  				"PCI PM: Device state not saved by %pF
  ",
  				drv->suspend);
99dadce87   Rafael J. Wysocki   PCI PM: Fix savin...
507
  		}
026694920   Andrew Morton   [PATCH] pm: print...
508
  	}
ad8cfa1de   Rafael J. Wysocki   PCI PM: Call pci_...
509
510
  
  	pci_fixup_device(pci_fixup_suspend, pci_dev);
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
511
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512
  }
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
513
  static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)
cbd69dbbf   Linus Torvalds   Suspend changes f...
514
515
516
  {
  	struct pci_dev * pci_dev = to_pci_dev(dev);
  	struct pci_driver * drv = pci_dev->driver;
cbd69dbbf   Linus Torvalds   Suspend changes f...
517
518
  
  	if (drv && drv->suspend_late) {
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
519
520
  		pci_power_t prev = pci_dev->current_state;
  		int error;
57ef80266   Frans Pop   PCI PM: Consisten...
521
522
  		error = drv->suspend_late(pci_dev, state);
  		suspend_report_result(drv->suspend_late, error);
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
523
524
525
526
527
528
529
530
531
532
533
  		if (error)
  			return error;
  
  		if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
  		    && pci_dev->current_state != PCI_UNKNOWN) {
  			WARN_ONCE(pci_dev->current_state != prev,
  				"PCI PM: Device state not saved by %pF
  ",
  				drv->suspend_late);
  			return 0;
  		}
cbd69dbbf   Linus Torvalds   Suspend changes f...
534
  	}
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
535
536
537
538
539
540
541
  
  	if (!pci_dev->state_saved)
  		pci_save_state(pci_dev);
  
  	pci_pm_set_unknown_state(pci_dev);
  
  	return 0;
cbd69dbbf   Linus Torvalds   Suspend changes f...
542
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543

f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
544
545
  static int pci_legacy_resume_early(struct device *dev)
  {
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
546
547
  	struct pci_dev * pci_dev = to_pci_dev(dev);
  	struct pci_driver * drv = pci_dev->driver;
aa8c6c937   Rafael J. Wysocki   PCI PM: Restore s...
548
549
  	return drv && drv->resume_early ?
  			drv->resume_early(pci_dev) : 0;
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
550
  }
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
551
  static int pci_legacy_resume(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
553
554
  {
  	struct pci_dev * pci_dev = to_pci_dev(dev);
  	struct pci_driver * drv = pci_dev->driver;
ad8cfa1de   Rafael J. Wysocki   PCI PM: Call pci_...
555
  	pci_fixup_device(pci_fixup_resume, pci_dev);
aa8c6c937   Rafael J. Wysocki   PCI PM: Restore s...
556
557
  	return drv && drv->resume ?
  			drv->resume(pci_dev) : pci_pm_reenable_device(pci_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
  }
571ff7584   Rafael J. Wysocki   PCI PM: Power-man...
559
  /* Auxiliary functions used by the new power management framework */
5294e2567   Rafael J. Wysocki   PCI PM: make the ...
560
  static void pci_pm_default_resume(struct pci_dev *pci_dev)
571ff7584   Rafael J. Wysocki   PCI PM: Power-man...
561
  {
734104292   Rafael J. Wysocki   PCI PM: Avoid tou...
562
  	pci_fixup_device(pci_fixup_resume, pci_dev);
5294e2567   Rafael J. Wysocki   PCI PM: make the ...
563
564
  	if (!pci_is_bridge(pci_dev))
  		pci_enable_wake(pci_dev, PCI_D0, false);
571ff7584   Rafael J. Wysocki   PCI PM: Power-man...
565
  }
5294e2567   Rafael J. Wysocki   PCI PM: make the ...
566
  static void pci_pm_default_suspend(struct pci_dev *pci_dev)
734104292   Rafael J. Wysocki   PCI PM: Avoid tou...
567
  {
5294e2567   Rafael J. Wysocki   PCI PM: make the ...
568
  	/* Disable non-bridge devices without PM support */
cbbc2f6b0   Rafael J. Wysocki   PCI PM: Do not di...
569
570
  	if (!pci_is_bridge(pci_dev))
  		pci_disable_enabled_device(pci_dev);
734104292   Rafael J. Wysocki   PCI PM: Avoid tou...
571
  }
07e836e8d   Rafael J. Wysocki   PCI PM: Move pci_...
572
573
574
  static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
  {
  	struct pci_driver *drv = pci_dev->driver;
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
575
  	bool ret = drv && (drv->suspend || drv->suspend_late || drv->resume
07e836e8d   Rafael J. Wysocki   PCI PM: Move pci_...
576
  		|| drv->resume_early);
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
577
578
579
580
581
582
  
  	/*
  	 * Legacy PM support is used by default, so warn if the new framework is
  	 * supported as well.  Drivers are supposed to support either the
  	 * former, or the latter, but not both at the same time.
  	 */
82440a825   David Fries   PCI: pci_has_lega...
583
584
585
  	WARN(ret && drv->driver.pm, "driver %s device %04x:%04x
  ",
  		drv->name, pci_dev->vendor, pci_dev->device);
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
586
587
  
  	return ret;
07e836e8d   Rafael J. Wysocki   PCI PM: Move pci_...
588
  }
571ff7584   Rafael J. Wysocki   PCI PM: Power-man...
589
  /* New power management framework */
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
590
591
592
593
  static int pci_pm_prepare(struct device *dev)
  {
  	struct device_driver *drv = dev->driver;
  	int error = 0;
6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
594
  	/*
eea3fc035   Rafael J. Wysocki   PCI / PM: Detect ...
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
  	 * If a PCI device configured to wake up the system from sleep states
  	 * has been suspended at run time and there's a resume request pending
  	 * for it, this is equivalent to the device signaling wakeup, so the
  	 * system suspend operation should be aborted.
  	 */
  	pm_runtime_get_noresume(dev);
  	if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
  		pm_wakeup_event(dev, 0);
  
  	if (pm_wakeup_pending()) {
  		pm_runtime_put_sync(dev);
  		return -EBUSY;
  	}
  
  	/*
6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
610
611
612
613
614
615
616
617
  	 * PCI devices suspended at run time need to be resumed at this
  	 * point, because in general it is necessary to reconfigure them for
  	 * system suspend.  Namely, if the device is supposed to wake up the
  	 * system from the sleep state, we may need to reconfigure it for this
  	 * purpose.  In turn, if the device is not supposed to wake up the
  	 * system from the sleep state, we'll have to prevent it from signaling
  	 * wake-up.
  	 */
eea3fc035   Rafael J. Wysocki   PCI / PM: Detect ...
618
  	pm_runtime_resume(dev);
6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
619

bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
620
621
622
623
624
625
626
627
628
629
630
631
  	if (drv && drv->pm && drv->pm->prepare)
  		error = drv->pm->prepare(dev);
  
  	return error;
  }
  
  static void pci_pm_complete(struct device *dev)
  {
  	struct device_driver *drv = dev->driver;
  
  	if (drv && drv->pm && drv->pm->complete)
  		drv->pm->complete(dev);
a5f76d5eb   Rafael J. Wysocki   PCI / PM: Block r...
632
633
  
  	pm_runtime_put_sync(dev);
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
634
  }
6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
635
636
637
638
639
640
  #else /* !CONFIG_PM_SLEEP */
  
  #define pci_pm_prepare	NULL
  #define pci_pm_complete	NULL
  
  #endif /* !CONFIG_PM_SLEEP */
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
641
642
643
644
645
  #ifdef CONFIG_SUSPEND
  
  static int pci_pm_suspend(struct device *dev)
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
8150f32b9   Dmitry Torokhov   Driver Core: Make...
646
  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
647

ad8cfa1de   Rafael J. Wysocki   PCI PM: Call pci_...
648
649
  	if (pci_has_legacy_pm_support(pci_dev))
  		return pci_legacy_suspend(dev, PMSG_SUSPEND);
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
650

5294e2567   Rafael J. Wysocki   PCI PM: make the ...
651
652
653
654
  	if (!pm) {
  		pci_pm_default_suspend(pci_dev);
  		goto Fixup;
  	}
5294e2567   Rafael J. Wysocki   PCI PM: make the ...
655
656
657
  	if (pm->suspend) {
  		pci_power_t prev = pci_dev->current_state;
  		int error;
ddb7c9d29   Rafael J. Wysocki   PCI PM: Fix handl...
658
659
  		error = pm->suspend(dev);
  		suspend_report_result(pm->suspend, error);
5294e2567   Rafael J. Wysocki   PCI PM: make the ...
660
661
  		if (error)
  			return error;
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
662
  		if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
5294e2567   Rafael J. Wysocki   PCI PM: make the ...
663
664
665
666
667
  		    && pci_dev->current_state != PCI_UNKNOWN) {
  			WARN_ONCE(pci_dev->current_state != prev,
  				"PCI PM: State of device not saved by %pF
  ",
  				pm->suspend);
5294e2567   Rafael J. Wysocki   PCI PM: make the ...
668
  		}
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
669
  	}
fa58d305d   Rafael J. Wysocki   PCI PM: Add suspe...
670

5294e2567   Rafael J. Wysocki   PCI PM: make the ...
671
672
673
674
   Fixup:
  	pci_fixup_device(pci_fixup_suspend, pci_dev);
  
  	return 0;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
675
676
677
  }
  
  static int pci_pm_suspend_noirq(struct device *dev)
c89581772   Greg Kroah-Hartman   [PATCH] PCI: Add ...
678
  {
355a72d75   Rafael J. Wysocki   PCI: Rework defau...
679
  	struct pci_dev *pci_dev = to_pci_dev(dev);
8150f32b9   Dmitry Torokhov   Driver Core: Make...
680
  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
c89581772   Greg Kroah-Hartman   [PATCH] PCI: Add ...
681

bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
682
683
  	if (pci_has_legacy_pm_support(pci_dev))
  		return pci_legacy_suspend_late(dev, PMSG_SUSPEND);
931ff68a5   Rafael J. Wysocki   PCI PM: Restore c...
684
685
  	if (!pm) {
  		pci_save_state(pci_dev);
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
686
  		return 0;
931ff68a5   Rafael J. Wysocki   PCI PM: Restore c...
687
  	}
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
  
  	if (pm->suspend_noirq) {
  		pci_power_t prev = pci_dev->current_state;
  		int error;
  
  		error = pm->suspend_noirq(dev);
  		suspend_report_result(pm->suspend_noirq, error);
  		if (error)
  			return error;
  
  		if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
  		    && pci_dev->current_state != PCI_UNKNOWN) {
  			WARN_ONCE(pci_dev->current_state != prev,
  				"PCI PM: State of device not saved by %pF
  ",
  				pm->suspend_noirq);
  			return 0;
  		}
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
706
  	}
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
707
708
709
710
711
  	if (!pci_dev->state_saved) {
  		pci_save_state(pci_dev);
  		if (!pci_is_bridge(pci_dev))
  			pci_prepare_to_sleep(pci_dev);
  	}
d67e37d79   Rafael J. Wysocki   PCI PM: Run defau...
712

46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
713
714
715
  	pci_pm_set_unknown_state(pci_dev);
  
  	return 0;
c89581772   Greg Kroah-Hartman   [PATCH] PCI: Add ...
716
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717

f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
718
  static int pci_pm_resume_noirq(struct device *dev)
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
719
720
721
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	struct device_driver *drv = dev->driver;
355a72d75   Rafael J. Wysocki   PCI: Rework defau...
722
  	int error = 0;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
723

6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
724
  	pci_pm_default_resume_early(pci_dev);
aa8c6c937   Rafael J. Wysocki   PCI PM: Restore s...
725

ad8cfa1de   Rafael J. Wysocki   PCI PM: Call pci_...
726
  	if (pci_has_legacy_pm_support(pci_dev))
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
727
  		return pci_legacy_resume_early(dev);
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
728

f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
729
730
  	if (drv && drv->pm && drv->pm->resume_noirq)
  		error = drv->pm->resume_noirq(dev);
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
731
732
733
  
  	return error;
  }
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
734
  static int pci_pm_resume(struct device *dev)
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
735
  {
355a72d75   Rafael J. Wysocki   PCI: Rework defau...
736
  	struct pci_dev *pci_dev = to_pci_dev(dev);
8150f32b9   Dmitry Torokhov   Driver Core: Make...
737
  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
738
  	int error = 0;
418e4da33   Rafael J. Wysocki   PCI PM: Fix suspe...
739
740
741
742
743
744
  	/*
  	 * This is necessary for the suspend error path in which resume is
  	 * called without restoring the standard config registers of the device.
  	 */
  	if (pci_dev->state_saved)
  		pci_restore_standard_config(pci_dev);
ad8cfa1de   Rafael J. Wysocki   PCI PM: Call pci_...
745
  	if (pci_has_legacy_pm_support(pci_dev))
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
746
  		return pci_legacy_resume(dev);
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
747

5294e2567   Rafael J. Wysocki   PCI PM: make the ...
748
  	pci_pm_default_resume(pci_dev);
734104292   Rafael J. Wysocki   PCI PM: Avoid tou...
749

5294e2567   Rafael J. Wysocki   PCI PM: make the ...
750
751
752
753
754
755
  	if (pm) {
  		if (pm->resume)
  			error = pm->resume(dev);
  	} else {
  		pci_pm_reenable_device(pci_dev);
  	}
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
756

999cce4a5   Rafael J. Wysocki   PCI PM: Return er...
757
  	return error;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
758
759
760
761
762
763
764
765
766
767
  }
  
  #else /* !CONFIG_SUSPEND */
  
  #define pci_pm_suspend		NULL
  #define pci_pm_suspend_noirq	NULL
  #define pci_pm_resume		NULL
  #define pci_pm_resume_noirq	NULL
  
  #endif /* !CONFIG_SUSPEND */
1f112cee0   Rafael J. Wysocki   PM / Hibernate: I...
768
  #ifdef CONFIG_HIBERNATE_CALLBACKS
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
769
770
771
772
  
  static int pci_pm_freeze(struct device *dev)
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
8150f32b9   Dmitry Torokhov   Driver Core: Make...
773
  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
774

ad8cfa1de   Rafael J. Wysocki   PCI PM: Call pci_...
775
776
  	if (pci_has_legacy_pm_support(pci_dev))
  		return pci_legacy_suspend(dev, PMSG_FREEZE);
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
777

5294e2567   Rafael J. Wysocki   PCI PM: make the ...
778
779
780
  	if (!pm) {
  		pci_pm_default_suspend(pci_dev);
  		return 0;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
781
  	}
5294e2567   Rafael J. Wysocki   PCI PM: make the ...
782
783
784
785
786
787
788
789
  	if (pm->freeze) {
  		int error;
  
  		error = pm->freeze(dev);
  		suspend_report_result(pm->freeze, error);
  		if (error)
  			return error;
  	}
5294e2567   Rafael J. Wysocki   PCI PM: make the ...
790
  	return 0;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
791
792
793
794
  }
  
  static int pci_pm_freeze_noirq(struct device *dev)
  {
355a72d75   Rafael J. Wysocki   PCI: Rework defau...
795
  	struct pci_dev *pci_dev = to_pci_dev(dev);
adf094931   Rafael J. Wysocki   PM: Simplify the ...
796
  	struct device_driver *drv = dev->driver;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
797

bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
798
799
  	if (pci_has_legacy_pm_support(pci_dev))
  		return pci_legacy_suspend_late(dev, PMSG_FREEZE);
d67e37d79   Rafael J. Wysocki   PCI PM: Run defau...
800
  	if (drv && drv->pm && drv->pm->freeze_noirq) {
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
801
  		int error;
d67e37d79   Rafael J. Wysocki   PCI PM: Run defau...
802
803
  		error = drv->pm->freeze_noirq(dev);
  		suspend_report_result(drv->pm->freeze_noirq, error);
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
804
805
  		if (error)
  			return error;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
806
  	}
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
807
808
  	if (!pci_dev->state_saved)
  		pci_save_state(pci_dev);
d67e37d79   Rafael J. Wysocki   PCI PM: Run defau...
809

46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
810
811
812
  	pci_pm_set_unknown_state(pci_dev);
  
  	return 0;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
813
  }
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
814
  static int pci_pm_thaw_noirq(struct device *dev)
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
815
  {
355a72d75   Rafael J. Wysocki   PCI: Rework defau...
816
  	struct pci_dev *pci_dev = to_pci_dev(dev);
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
817
818
  	struct device_driver *drv = dev->driver;
  	int error = 0;
ad8cfa1de   Rafael J. Wysocki   PCI PM: Call pci_...
819
  	if (pci_has_legacy_pm_support(pci_dev))
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
820
  		return pci_legacy_resume_early(dev);
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
821

f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
822
  	pci_update_current_state(pci_dev, PCI_D0);
d67e37d79   Rafael J. Wysocki   PCI PM: Run defau...
823

f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
824
825
  	if (drv && drv->pm && drv->pm->thaw_noirq)
  		error = drv->pm->thaw_noirq(dev);
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
826
827
828
  
  	return error;
  }
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
829
  static int pci_pm_thaw(struct device *dev)
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
830
  {
355a72d75   Rafael J. Wysocki   PCI: Rework defau...
831
  	struct pci_dev *pci_dev = to_pci_dev(dev);
8150f32b9   Dmitry Torokhov   Driver Core: Make...
832
  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
833
  	int error = 0;
ad8cfa1de   Rafael J. Wysocki   PCI PM: Call pci_...
834
  	if (pci_has_legacy_pm_support(pci_dev))
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
835
  		return pci_legacy_resume(dev);
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
836

5294e2567   Rafael J. Wysocki   PCI PM: make the ...
837
838
839
840
841
842
  	if (pm) {
  		if (pm->thaw)
  			error = pm->thaw(dev);
  	} else {
  		pci_pm_reenable_device(pci_dev);
  	}
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
843

4b77b0a2b   Rafael J. Wysocki   PCI: Clear saved_...
844
  	pci_dev->state_saved = false;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
845
846
847
848
849
  	return error;
  }
  
  static int pci_pm_poweroff(struct device *dev)
  {
355a72d75   Rafael J. Wysocki   PCI: Rework defau...
850
  	struct pci_dev *pci_dev = to_pci_dev(dev);
8150f32b9   Dmitry Torokhov   Driver Core: Make...
851
  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
852

ad8cfa1de   Rafael J. Wysocki   PCI PM: Call pci_...
853
854
  	if (pci_has_legacy_pm_support(pci_dev))
  		return pci_legacy_suspend(dev, PMSG_HIBERNATE);
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
855

5294e2567   Rafael J. Wysocki   PCI PM: make the ...
856
857
858
859
  	if (!pm) {
  		pci_pm_default_suspend(pci_dev);
  		goto Fixup;
  	}
5294e2567   Rafael J. Wysocki   PCI PM: make the ...
860
  	if (pm->poweroff) {
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
861
  		int error;
ddb7c9d29   Rafael J. Wysocki   PCI PM: Fix handl...
862
863
  		error = pm->poweroff(dev);
  		suspend_report_result(pm->poweroff, error);
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
864
865
  		if (error)
  			return error;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
866
  	}
5294e2567   Rafael J. Wysocki   PCI PM: make the ...
867
868
   Fixup:
  	pci_fixup_device(pci_fixup_suspend, pci_dev);
c9b9972b3   Rafael J. Wysocki   PCI PM: Fix power...
869

46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
870
  	return 0;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
871
872
873
874
  }
  
  static int pci_pm_poweroff_noirq(struct device *dev)
  {
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
875
  	struct pci_dev *pci_dev = to_pci_dev(dev);
adf094931   Rafael J. Wysocki   PM: Simplify the ...
876
  	struct device_driver *drv = dev->driver;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
877

bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
878
879
  	if (pci_has_legacy_pm_support(to_pci_dev(dev)))
  		return pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
880
881
882
883
884
  	if (!drv || !drv->pm)
  		return 0;
  
  	if (drv->pm->poweroff_noirq) {
  		int error;
d67e37d79   Rafael J. Wysocki   PCI PM: Run defau...
885
886
  		error = drv->pm->poweroff_noirq(dev);
  		suspend_report_result(drv->pm->poweroff_noirq, error);
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
887
888
  		if (error)
  			return error;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
889
  	}
46939f8b1   Rafael J. Wysocki   PCI PM: Put devic...
890
891
892
893
  	if (!pci_dev->state_saved && !pci_is_bridge(pci_dev))
  		pci_prepare_to_sleep(pci_dev);
  
  	return 0;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
894
  }
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
895
  static int pci_pm_restore_noirq(struct device *dev)
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
896
897
898
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	struct device_driver *drv = dev->driver;
355a72d75   Rafael J. Wysocki   PCI: Rework defau...
899
  	int error = 0;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
900

6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
901
  	pci_pm_default_resume_early(pci_dev);
aa8c6c937   Rafael J. Wysocki   PCI PM: Restore s...
902

ad8cfa1de   Rafael J. Wysocki   PCI PM: Call pci_...
903
  	if (pci_has_legacy_pm_support(pci_dev))
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
904
  		return pci_legacy_resume_early(dev);
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
905

f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
906
907
  	if (drv && drv->pm && drv->pm->restore_noirq)
  		error = drv->pm->restore_noirq(dev);
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
908
909
910
  
  	return error;
  }
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
911
  static int pci_pm_restore(struct device *dev)
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
912
913
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
8150f32b9   Dmitry Torokhov   Driver Core: Make...
914
  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
915
  	int error = 0;
418e4da33   Rafael J. Wysocki   PCI PM: Fix suspe...
916
917
918
919
920
921
  	/*
  	 * This is necessary for the hibernation error path in which restore is
  	 * called without restoring the standard config registers of the device.
  	 */
  	if (pci_dev->state_saved)
  		pci_restore_standard_config(pci_dev);
ad8cfa1de   Rafael J. Wysocki   PCI PM: Call pci_...
922
  	if (pci_has_legacy_pm_support(pci_dev))
f6dc1e5e3   Rafael J. Wysocki   PCI PM: Put PM ca...
923
  		return pci_legacy_resume(dev);
bb8089454   Rafael J. Wysocki   PCI PM: Rearrange...
924

5294e2567   Rafael J. Wysocki   PCI PM: make the ...
925
  	pci_pm_default_resume(pci_dev);
734104292   Rafael J. Wysocki   PCI PM: Avoid tou...
926

5294e2567   Rafael J. Wysocki   PCI PM: make the ...
927
928
929
930
931
932
  	if (pm) {
  		if (pm->restore)
  			error = pm->restore(dev);
  	} else {
  		pci_pm_reenable_device(pci_dev);
  	}
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
933
934
  
  	return error;
c89581772   Greg Kroah-Hartman   [PATCH] PCI: Add ...
935
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936

1f112cee0   Rafael J. Wysocki   PM / Hibernate: I...
937
  #else /* !CONFIG_HIBERNATE_CALLBACKS */
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
938
939
940
941
942
943
944
945
946
  
  #define pci_pm_freeze		NULL
  #define pci_pm_freeze_noirq	NULL
  #define pci_pm_thaw		NULL
  #define pci_pm_thaw_noirq	NULL
  #define pci_pm_poweroff		NULL
  #define pci_pm_poweroff_noirq	NULL
  #define pci_pm_restore		NULL
  #define pci_pm_restore_noirq	NULL
1f112cee0   Rafael J. Wysocki   PM / Hibernate: I...
947
  #endif /* !CONFIG_HIBERNATE_CALLBACKS */
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
948

6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
  #ifdef CONFIG_PM_RUNTIME
  
  static int pci_pm_runtime_suspend(struct device *dev)
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
  	pci_power_t prev = pci_dev->current_state;
  	int error;
  
  	if (!pm || !pm->runtime_suspend)
  		return -ENOSYS;
  
  	error = pm->runtime_suspend(dev);
  	suspend_report_result(pm->runtime_suspend, error);
  	if (error)
  		return error;
  
  	pci_fixup_device(pci_fixup_suspend, pci_dev);
  
  	if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
  	    && pci_dev->current_state != PCI_UNKNOWN) {
  		WARN_ONCE(pci_dev->current_state != prev,
  			"PCI PM: State of device not saved by %pF
  ",
  			pm->runtime_suspend);
  		return 0;
  	}
  
  	if (!pci_dev->state_saved)
  		pci_save_state(pci_dev);
  
  	pci_finish_runtime_suspend(pci_dev);
  
  	return 0;
  }
  
  static int pci_pm_runtime_resume(struct device *dev)
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
  
  	if (!pm || !pm->runtime_resume)
  		return -ENOSYS;
  
  	pci_pm_default_resume_early(pci_dev);
  	__pci_enable_wake(pci_dev, PCI_D0, true, false);
  	pci_fixup_device(pci_fixup_resume, pci_dev);
  
  	return pm->runtime_resume(dev);
  }
  
  static int pci_pm_runtime_idle(struct device *dev)
  {
  	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
  
  	if (!pm)
  		return -ENOSYS;
  
  	if (pm->runtime_idle) {
  		int ret = pm->runtime_idle(dev);
  		if (ret)
  			return ret;
  	}
  
  	pm_runtime_suspend(dev);
  
  	return 0;
  }
  
  #else /* !CONFIG_PM_RUNTIME */
  
  #define pci_pm_runtime_suspend	NULL
  #define pci_pm_runtime_resume	NULL
  #define pci_pm_runtime_idle	NULL
  
  #endif /* !CONFIG_PM_RUNTIME */
aa3386015   Rafael J. Wysocki   PM: Remove CONFIG...
1025
  #ifdef CONFIG_PM
6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
1026

8150f32b9   Dmitry Torokhov   Driver Core: Make...
1027
  const struct dev_pm_ops pci_dev_pm_ops = {
adf094931   Rafael J. Wysocki   PM: Simplify the ...
1028
1029
1030
1031
1032
1033
1034
1035
  	.prepare = pci_pm_prepare,
  	.complete = pci_pm_complete,
  	.suspend = pci_pm_suspend,
  	.resume = pci_pm_resume,
  	.freeze = pci_pm_freeze,
  	.thaw = pci_pm_thaw,
  	.poweroff = pci_pm_poweroff,
  	.restore = pci_pm_restore,
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
1036
1037
1038
1039
1040
1041
  	.suspend_noirq = pci_pm_suspend_noirq,
  	.resume_noirq = pci_pm_resume_noirq,
  	.freeze_noirq = pci_pm_freeze_noirq,
  	.thaw_noirq = pci_pm_thaw_noirq,
  	.poweroff_noirq = pci_pm_poweroff_noirq,
  	.restore_noirq = pci_pm_restore_noirq,
6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
1042
1043
1044
  	.runtime_suspend = pci_pm_runtime_suspend,
  	.runtime_resume = pci_pm_runtime_resume,
  	.runtime_idle = pci_pm_runtime_idle,
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
1045
  };
adf094931   Rafael J. Wysocki   PM: Simplify the ...
1046
  #define PCI_PM_OPS_PTR	(&pci_dev_pm_ops)
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
1047

6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
1048
  #else /* !COMFIG_PM_OPS */
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
1049
1050
  
  #define PCI_PM_OPS_PTR	NULL
6cbf82148   Rafael J. Wysocki   PCI PM: Run-time ...
1051
  #endif /* !COMFIG_PM_OPS */
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
1052

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1053
  /**
863b18f4b   Laurent riffard   [PATCH] PCI: auto...
1054
   * __pci_register_driver - register a new pci driver
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1055
   * @drv: the driver structure to register
863b18f4b   Laurent riffard   [PATCH] PCI: auto...
1056
   * @owner: owner module of drv
f95d882d8   Randy Dunlap   PCI/sysfs/kobject...
1057
   * @mod_name: module name string
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1058
1059
1060
   * 
   * Adds the driver structure to the list of registered drivers.
   * Returns a negative value on error, otherwise 0. 
eaae4b3a8   Steven Cole   [PATCH] PCI: Spel...
1061
   * If no error occurred, the driver remains registered even if 
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1062
1063
   * no device was claimed during registration.
   */
725522b54   Greg Kroah-Hartman   PCI: add the sysf...
1064
1065
  int __pci_register_driver(struct pci_driver *drv, struct module *owner,
  			  const char *mod_name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1066
1067
1068
1069
1070
1071
  {
  	int error;
  
  	/* initialize common driver fields */
  	drv->driver.name = drv->name;
  	drv->driver.bus = &pci_bus_type;
863b18f4b   Laurent riffard   [PATCH] PCI: auto...
1072
  	drv->driver.owner = owner;
725522b54   Greg Kroah-Hartman   PCI: add the sysf...
1073
  	drv->driver.mod_name = mod_name;
50b007552   Alan Cox   PCI: Multiprobe s...
1074

758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
1075
1076
  	spin_lock_init(&drv->dynids.lock);
  	INIT_LIST_HEAD(&drv->dynids.list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1077
1078
1079
  
  	/* register with core */
  	error = driver_register(&drv->driver);
50bf14b3f   Akinobu Mita   pci: fix __pci_re...
1080
  	if (error)
0994375e9   Chris Wright   PCI: add remove_i...
1081
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1082

50bf14b3f   Akinobu Mita   pci: fix __pci_re...
1083
1084
  	error = pci_create_newid_file(drv);
  	if (error)
0994375e9   Chris Wright   PCI: add remove_i...
1085
  		goto out_newid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086

0994375e9   Chris Wright   PCI: add remove_i...
1087
1088
1089
1090
  	error = pci_create_removeid_file(drv);
  	if (error)
  		goto out_removeid;
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1091
  	return error;
0994375e9   Chris Wright   PCI: add remove_i...
1092
1093
1094
1095
1096
1097
  
  out_removeid:
  	pci_remove_newid_file(drv);
  out_newid:
  	driver_unregister(&drv->driver);
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
  }
  
  /**
   * pci_unregister_driver - unregister a pci driver
   * @drv: the driver structure to unregister
   * 
   * Deletes the driver structure from the list of registered PCI drivers,
   * gives it a chance to clean up by calling its remove() function for
   * each device it was responsible for, and marks those devices as
   * driverless.
   */
  
  void
  pci_unregister_driver(struct pci_driver *drv)
  {
0994375e9   Chris Wright   PCI: add remove_i...
1113
  	pci_remove_removeid_file(drv);
03d43b19b   Greg Kroah-Hartman   PCI: use proper c...
1114
  	pci_remove_newid_file(drv);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
  	driver_unregister(&drv->driver);
  	pci_free_dynids(drv);
  }
  
  static struct pci_driver pci_compat_driver = {
  	.name = "compat"
  };
  
  /**
   * pci_dev_driver - get the pci_driver of a device
   * @dev: the device to query
   *
   * Returns the appropriate pci_driver structure or %NULL if there is no 
   * registered driver for the device.
   */
  struct pci_driver *
  pci_dev_driver(const struct pci_dev *dev)
  {
  	if (dev->driver)
  		return dev->driver;
  	else {
  		int i;
  		for(i=0; i<=PCI_ROM_RESOURCE; i++)
  			if (dev->resource[i].flags & IORESOURCE_BUSY)
  				return &pci_compat_driver;
  	}
  	return NULL;
  }
  
  /**
   * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1146
   * @dev: the PCI device structure to match against
8f7020d36   Randy Dunlap   [PATCH] kernel-do...
1147
   * @drv: the device driver to search for matching PCI device id structures
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1148
1149
   * 
   * Used by a driver to check whether a PCI device present in the
8f7020d36   Randy Dunlap   [PATCH] kernel-do...
1150
   * system is in its list of supported devices. Returns the matching
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1151
1152
   * pci_device_id structure or %NULL if there is no match.
   */
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
1153
  static int pci_bus_match(struct device *dev, struct device_driver *drv)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1154
  {
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
1155
1156
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	struct pci_driver *pci_drv = to_pci_driver(drv);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1157
  	const struct pci_device_id *found_id;
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
1158
  	found_id = pci_match_device(pci_drv, pci_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159
1160
  	if (found_id)
  		return 1;
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
1161
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
  }
  
  /**
   * pci_dev_get - increments the reference count of the pci device structure
   * @dev: the device being referenced
   *
   * Each live reference to a device should be refcounted.
   *
   * Drivers for PCI devices should normally record such references in
   * their probe() methods, when they bind to a device, and release
   * them by calling pci_dev_put(), in their disconnect() methods.
   *
   * A pointer to the device with the incremented reference counter is returned.
   */
  struct pci_dev *pci_dev_get(struct pci_dev *dev)
  {
  	if (dev)
  		get_device(&dev->dev);
  	return dev;
  }
  
  /**
   * pci_dev_put - release a use of the pci device structure
   * @dev: device that's been disconnected
   *
   * Must be called when a user of a device is finished with it.  When the last
   * user of the device calls this function, the memory of the device is freed.
   */
  void pci_dev_put(struct pci_dev *dev)
  {
  	if (dev)
  		put_device(&dev->dev);
  }
  
  #ifndef CONFIG_HOTPLUG
7eff2e7a8   Kay Sievers   Driver core: chan...
1197
  int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1198
1199
1200
1201
1202
1203
1204
1205
  {
  	return -ENODEV;
  }
  #endif
  
  struct bus_type pci_bus_type = {
  	.name		= "pci",
  	.match		= pci_bus_match,
312c004d3   Kay Sievers   [PATCH] driver co...
1206
  	.uevent		= pci_uevent,
b15d686a2   Russell King   [PATCH] Add pci_b...
1207
1208
  	.probe		= pci_device_probe,
  	.remove		= pci_device_remove,
cbd69dbbf   Linus Torvalds   Suspend changes f...
1209
  	.shutdown	= pci_device_shutdown,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1210
  	.dev_attrs	= pci_dev_attrs,
705b1aaa8   Alex Chiang   PCI: Introduce /s...
1211
  	.bus_attrs	= pci_bus_attrs,
bbb44d9f2   Rafael J. Wysocki   PCI: implement ne...
1212
  	.pm		= PCI_PM_OPS_PTR,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1213
1214
1215
1216
1217
1218
1219
1220
  };
  
  static int __init pci_driver_init(void)
  {
  	return bus_register(&pci_bus_type);
  }
  
  postcore_initcall(pci_driver_init);
9dba910e9   Tejun Heo   PCI: separate out...
1221
  EXPORT_SYMBOL_GPL(pci_add_dynid);
758658589   Greg Kroah-Hartman   [PATCH] PCI: clea...
1222
  EXPORT_SYMBOL(pci_match_id);
863b18f4b   Laurent riffard   [PATCH] PCI: auto...
1223
  EXPORT_SYMBOL(__pci_register_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224
1225
1226
1227
1228
  EXPORT_SYMBOL(pci_unregister_driver);
  EXPORT_SYMBOL(pci_dev_driver);
  EXPORT_SYMBOL(pci_bus_type);
  EXPORT_SYMBOL(pci_dev_get);
  EXPORT_SYMBOL(pci_dev_put);