Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / drivers / ide / ide-scan-pci.c
1 /*
2  * support for probing IDE PCI devices in the PCI bus order
3  *
4  * Copyright (c) 1998-2000  Andre Hedrick <andre@linux-ide.org>
5  * Copyright (c) 1995-1998  Mark Lord
6  *
7  * May be copied or modified under the terms of the GNU General Public License
8  */
9
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/module.h>
13 #include <linux/ide.h>
14
15 /*
16  *      Module interfaces
17  */
18
19 static int pre_init = 1;                /* Before first ordered IDE scan */
20 static LIST_HEAD(ide_pci_drivers);
21
22 /*
23  *      __ide_pci_register_driver       -       attach IDE driver
24  *      @driver: pci driver
25  *      @module: owner module of the driver
26  *
27  *      Registers a driver with the IDE layer. The IDE layer arranges that
28  *      boot time setup is done in the expected device order and then
29  *      hands the controllers off to the core PCI code to do the rest of
30  *      the work.
31  *
32  *      Returns are the same as for pci_register_driver
33  */
34
35 int __ide_pci_register_driver(struct pci_driver *driver, struct module *module,
36                               const char *mod_name)
37 {
38         if (!pre_init)
39                 return __pci_register_driver(driver, module, mod_name);
40         driver->driver.owner = module;
41         list_add_tail(&driver->node, &ide_pci_drivers);
42         return 0;
43 }
44 EXPORT_SYMBOL_GPL(__ide_pci_register_driver);
45
46 /**
47  *      ide_scan_pcidev         -       find an IDE driver for a device
48  *      @dev: PCI device to check
49  *
50  *      Look for an IDE driver to handle the device we are considering.
51  *      This is only used during boot up to get the ordering correct. After
52  *      boot up the pci layer takes over the job.
53  */
54
55 static int __init ide_scan_pcidev(struct pci_dev *dev)
56 {
57         struct list_head *l;
58         struct pci_driver *d;
59         int ret;
60
61         list_for_each(l, &ide_pci_drivers) {
62                 d = list_entry(l, struct pci_driver, node);
63                 if (d->id_table) {
64                         const struct pci_device_id *id =
65                                 pci_match_id(d->id_table, dev);
66
67                         if (id != NULL) {
68                                 pci_assign_irq(dev);
69                                 ret = d->probe(dev, id);
70                                 if (ret >= 0) {
71                                         dev->driver = d;
72                                         pci_dev_get(dev);
73                                         return 1;
74                                 }
75                         }
76                 }
77         }
78         return 0;
79 }
80
81 /**
82  *      ide_scan_pcibus         -       perform the initial IDE driver scan
83  *
84  *      Perform the initial bus rather than driver ordered scan of the
85  *      PCI drivers. After this all IDE pci handling becomes standard
86  *      module ordering not traditionally ordered.
87  */
88
89 static int __init ide_scan_pcibus(void)
90 {
91         struct pci_dev *dev = NULL;
92         struct pci_driver *d;
93         struct list_head *l, *n;
94
95         pre_init = 0;
96         for_each_pci_dev(dev)
97                 ide_scan_pcidev(dev);
98
99         /*
100          *      Hand the drivers over to the PCI layer now we
101          *      are post init.
102          */
103
104         list_for_each_safe(l, n, &ide_pci_drivers) {
105                 list_del(l);
106                 d = list_entry(l, struct pci_driver, node);
107                 if (__pci_register_driver(d, d->driver.owner,
108                                           d->driver.mod_name))
109                         printk(KERN_ERR "%s: failed to register %s driver\n",
110                                         __func__, d->driver.mod_name);
111         }
112
113         return 0;
114 }
115 device_initcall(ide_scan_pcibus);