aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-06-30 05:18:12 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-07-01 16:35:50 -0400
commit75865858971add95809c5c9cd35dc4cfba08e33b (patch)
treee8b3fe78e15696f36156d1f94d35b7711590365f /drivers/pci
parent299de0343c7d18448a69c635378342e9214b14af (diff)
[PATCH] PCI: clean up dynamic pci id logic
The dynamic pci id logic has been bothering me for a while, and now that I started to look into how to move some of this to the driver core, I thought it was time to clean it all up. It ends up making the code smaller, and easier to follow, and fixes a few bugs at the same time (dynamic ids were not being matched everywhere, and so could be missed on some call paths for new devices, semaphore not needed to be grabbed when adding a new id and calling the driver core, etc.) I also renamed the function pci_match_device() to pci_match_id() as that's what it really does. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci')
-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);