aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci-driver.c')
-rw-r--r--drivers/pci/pci-driver.c196
1 files changed, 71 insertions, 125 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index e65bf2b395aa..aac6de9568e5 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -7,7 +7,6 @@
7#include <linux/module.h> 7#include <linux/module.h>
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/device.h> 9#include <linux/device.h>
10#include <linux/pci-dynids.h>
11#include "pci.h" 10#include "pci.h"
12 11
13/* 12/*
@@ -19,35 +18,11 @@
19 */ 18 */
20 19
21#ifdef CONFIG_HOTPLUG 20#ifdef CONFIG_HOTPLUG
22/**
23 * pci_device_probe_dynamic()
24 *
25 * Walk the dynamic ID list looking for a match.
26 * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error.
27 */
28static int
29pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev)
30{
31 int error = -ENODEV;
32 struct list_head *pos;
33 struct dynid *dynid;
34 21
35 spin_lock(&drv->dynids.lock); 22struct pci_dynid {
36 list_for_each(pos, &drv->dynids.list) { 23 struct list_head node;
37 dynid = list_entry(pos, struct dynid, node); 24 struct pci_device_id id;
38 if (pci_match_one_device(&dynid->id, pci_dev)) { 25};
39 spin_unlock(&drv->dynids.lock);
40 error = drv->probe(pci_dev, &dynid->id);
41 if (error >= 0) {
42 pci_dev->driver = drv;
43 return 0;
44 }
45 return error;
46 }
47 }
48 spin_unlock(&drv->dynids.lock);
49 return error;
50}
51 26
52/** 27/**
53 * store_new_id 28 * store_new_id
@@ -58,8 +33,7 @@ pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev)
58static inline ssize_t 33static inline ssize_t
59store_new_id(struct device_driver *driver, const char *buf, size_t count) 34store_new_id(struct device_driver *driver, const char *buf, size_t count)
60{ 35{
61 struct dynid *dynid; 36 struct pci_dynid *dynid;
62 struct bus_type * bus;
63 struct pci_driver *pdrv = to_pci_driver(driver); 37 struct pci_driver *pdrv = to_pci_driver(driver);
64 __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, 38 __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID,
65 subdevice=PCI_ANY_ID, class=0, class_mask=0; 39 subdevice=PCI_ANY_ID, class=0, class_mask=0;
@@ -91,37 +65,22 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
91 list_add_tail(&pdrv->dynids.list, &dynid->node); 65 list_add_tail(&pdrv->dynids.list, &dynid->node);
92 spin_unlock(&pdrv->dynids.lock); 66 spin_unlock(&pdrv->dynids.lock);
93 67
94 bus = get_bus(pdrv->driver.bus); 68 if (get_driver(&pdrv->driver)) {
95 if (bus) { 69 driver_attach(&pdrv->driver);
96 if (get_driver(&pdrv->driver)) { 70 put_driver(&pdrv->driver);
97 down_write(&bus->subsys.rwsem);
98 driver_attach(&pdrv->driver);
99 up_write(&bus->subsys.rwsem);
100 put_driver(&pdrv->driver);
101 }
102 put_bus(bus);
103 } 71 }
104 72
105 return count; 73 return count;
106} 74}
107
108static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); 75static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
109static inline void
110pci_init_dynids(struct pci_dynids *dynids)
111{
112 spin_lock_init(&dynids->lock);
113 INIT_LIST_HEAD(&dynids->list);
114}
115 76
116static void 77static void
117pci_free_dynids(struct pci_driver *drv) 78pci_free_dynids(struct pci_driver *drv)
118{ 79{
119 struct list_head *pos, *n; 80 struct pci_dynid *dynid, *n;
120 struct dynid *dynid;
121 81
122 spin_lock(&drv->dynids.lock); 82 spin_lock(&drv->dynids.lock);
123 list_for_each_safe(pos, n, &drv->dynids.list) { 83 list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
124 dynid = list_entry(pos, struct dynid, node);
125 list_del(&dynid->node); 84 list_del(&dynid->node);
126 kfree(dynid); 85 kfree(dynid);
127 } 86 }
@@ -138,83 +97,70 @@ pci_create_newid_file(struct pci_driver *drv)
138 return error; 97 return error;
139} 98}
140 99
141static int
142pci_bus_match_dynids(const struct pci_dev *pci_dev, struct pci_driver *pci_drv)
143{
144 struct list_head *pos;
145 struct dynid *dynid;
146
147 spin_lock(&pci_drv->dynids.lock);
148 list_for_each(pos, &pci_drv->dynids.list) {
149 dynid = list_entry(pos, struct dynid, node);
150 if (pci_match_one_device(&dynid->id, pci_dev)) {
151 spin_unlock(&pci_drv->dynids.lock);
152 return 1;
153 }
154 }
155 spin_unlock(&pci_drv->dynids.lock);
156 return 0;
157}
158
159#else /* !CONFIG_HOTPLUG */ 100#else /* !CONFIG_HOTPLUG */
160static inline int pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev)
161{
162 return -ENODEV;
163}
164static inline void pci_init_dynids(struct pci_dynids *dynids) {}
165static inline void pci_free_dynids(struct pci_driver *drv) {} 101static inline void pci_free_dynids(struct pci_driver *drv) {}
166static inline int pci_create_newid_file(struct pci_driver *drv) 102static inline int pci_create_newid_file(struct pci_driver *drv)
167{ 103{
168 return 0; 104 return 0;
169} 105}
170static inline int pci_bus_match_dynids(const struct pci_dev *pci_dev, struct pci_driver *pci_drv)
171{
172 return 0;
173}
174#endif 106#endif
175 107
176/** 108/**
177 * pci_match_device - Tell if a PCI device structure has a matching 109 * pci_match_id - See if a pci device matches a given pci_id table
178 * PCI device id structure
179 * @ids: array of PCI device id structures to search in 110 * @ids: array of PCI device id structures to search in
180 * @dev: the PCI device structure to match against 111 * @dev: the PCI device structure to match against.
181 * 112 *
182 * Used by a driver to check whether a PCI device present in the 113 * Used by a driver to check whether a PCI device present in the
183 * system is in its list of supported devices.Returns the matching 114 * system is in its list of supported devices. Returns the matching
184 * pci_device_id structure or %NULL if there is no match. 115 * pci_device_id structure or %NULL if there is no match.
116 *
117 * Depreciated, don't use this as it will not catch any dynamic ids
118 * that a driver might want to check for.
185 */ 119 */
186const struct pci_device_id * 120const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
187pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) 121 struct pci_dev *dev)
188{ 122{
189 while (ids->vendor || ids->subvendor || ids->class_mask) { 123 if (ids) {
190 if (pci_match_one_device(ids, dev)) 124 while (ids->vendor || ids->subvendor || ids->class_mask) {
191 return ids; 125 if (pci_match_one_device(ids, dev))
192 ids++; 126 return ids;
127 ids++;
128 }
193 } 129 }
194 return NULL; 130 return NULL;
195} 131}
196 132
197/** 133/**
198 * pci_device_probe_static() 134 * pci_match_device - Tell if a PCI device structure has a matching
199 * 135 * PCI device id structure
200 * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error. 136 * @ids: array of PCI device id structures to search in
137 * @dev: the PCI device structure to match against
138 * @drv: the PCI driver to match against
139 *
140 * Used by a driver to check whether a PCI device present in the
141 * system is in its list of supported devices. Returns the matching
142 * pci_device_id structure or %NULL if there is no match.
201 */ 143 */
202static int 144const struct pci_device_id *pci_match_device(struct pci_driver *drv,
203pci_device_probe_static(struct pci_driver *drv, struct pci_dev *pci_dev) 145 struct pci_dev *dev)
204{ 146{
205 int error = -ENODEV;
206 const struct pci_device_id *id; 147 const struct pci_device_id *id;
148 struct pci_dynid *dynid;
207 149
208 if (!drv->id_table) 150 id = pci_match_id(drv->id_table, dev);
209 return error;
210 id = pci_match_device(drv->id_table, pci_dev);
211 if (id) 151 if (id)
212 error = drv->probe(pci_dev, id); 152 return id;
213 if (error >= 0) { 153
214 pci_dev->driver = drv; 154 /* static ids didn't match, lets look at the dynamic ones */
215 error = 0; 155 spin_lock(&drv->dynids.lock);
156 list_for_each_entry(dynid, &drv->dynids.list, node) {
157 if (pci_match_one_device(&dynid->id, dev)) {
158 spin_unlock(&drv->dynids.lock);
159 return &dynid->id;
160 }
216 } 161 }
217 return error; 162 spin_unlock(&drv->dynids.lock);
163 return NULL;
218} 164}
219 165
220/** 166/**
@@ -225,13 +171,20 @@ pci_device_probe_static(struct pci_driver *drv, struct pci_dev *pci_dev)
225 */ 171 */
226static int 172static int
227__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) 173__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
228{ 174{
175 const struct pci_device_id *id;
229 int error = 0; 176 int error = 0;
230 177
231 if (!pci_dev->driver && drv->probe) { 178 if (!pci_dev->driver && drv->probe) {
232 error = pci_device_probe_static(drv, pci_dev); 179 error = -ENODEV;
233 if (error == -ENODEV) 180
234 error = pci_device_probe_dynamic(drv, pci_dev); 181 id = pci_match_device(drv, pci_dev);
182 if (id)
183 error = drv->probe(pci_dev, id);
184 if (error >= 0) {
185 pci_dev->driver = drv;
186 error = 0;
187 }
235 } 188 }
236 return error; 189 return error;
237} 190}
@@ -371,12 +324,6 @@ static struct kobj_type pci_driver_kobj_type = {
371 .sysfs_ops = &pci_driver_sysfs_ops, 324 .sysfs_ops = &pci_driver_sysfs_ops,
372}; 325};
373 326
374static int
375pci_populate_driver_dir(struct pci_driver *drv)
376{
377 return pci_create_newid_file(drv);
378}
379
380/** 327/**
381 * pci_register_driver - register a new pci driver 328 * pci_register_driver - register a new pci driver
382 * @drv: the driver structure to register 329 * @drv: the driver structure to register
@@ -401,13 +348,15 @@ int pci_register_driver(struct pci_driver *drv)
401 drv->driver.shutdown = pci_device_shutdown; 348 drv->driver.shutdown = pci_device_shutdown;
402 drv->driver.owner = drv->owner; 349 drv->driver.owner = drv->owner;
403 drv->driver.kobj.ktype = &pci_driver_kobj_type; 350 drv->driver.kobj.ktype = &pci_driver_kobj_type;
404 pci_init_dynids(&drv->dynids); 351
352 spin_lock_init(&drv->dynids.lock);
353 INIT_LIST_HEAD(&drv->dynids.list);
405 354
406 /* register with core */ 355 /* register with core */
407 error = driver_register(&drv->driver); 356 error = driver_register(&drv->driver);
408 357
409 if (!error) 358 if (!error)
410 pci_populate_driver_dir(drv); 359 error = pci_create_newid_file(drv);
411 360
412 return error; 361 return error;
413} 362}
@@ -463,21 +412,17 @@ pci_dev_driver(const struct pci_dev *dev)
463 * system is in its list of supported devices.Returns the matching 412 * system is in its list of supported devices.Returns the matching
464 * pci_device_id structure or %NULL if there is no match. 413 * pci_device_id structure or %NULL if there is no match.
465 */ 414 */
466static int pci_bus_match(struct device * dev, struct device_driver * drv) 415static int pci_bus_match(struct device *dev, struct device_driver *drv)
467{ 416{
468 const struct pci_dev * pci_dev = to_pci_dev(dev); 417 struct pci_dev *pci_dev = to_pci_dev(dev);
469 struct pci_driver * pci_drv = to_pci_driver(drv); 418 struct pci_driver *pci_drv = to_pci_driver(drv);
470 const struct pci_device_id * ids = pci_drv->id_table;
471 const struct pci_device_id *found_id; 419 const struct pci_device_id *found_id;
472 420
473 if (!ids) 421 found_id = pci_match_device(pci_drv, pci_dev);
474 return 0;
475
476 found_id = pci_match_device(ids, pci_dev);
477 if (found_id) 422 if (found_id)
478 return 1; 423 return 1;
479 424
480 return pci_bus_match_dynids(pci_dev, pci_drv); 425 return 0;
481} 426}
482 427
483/** 428/**
@@ -536,6 +481,7 @@ static int __init pci_driver_init(void)
536 481
537postcore_initcall(pci_driver_init); 482postcore_initcall(pci_driver_init);
538 483
484EXPORT_SYMBOL(pci_match_id);
539EXPORT_SYMBOL(pci_match_device); 485EXPORT_SYMBOL(pci_match_device);
540EXPORT_SYMBOL(pci_register_driver); 486EXPORT_SYMBOL(pci_register_driver);
541EXPORT_SYMBOL(pci_unregister_driver); 487EXPORT_SYMBOL(pci_unregister_driver);