diff options
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r-- | drivers/ide/ide.c | 307 |
1 files changed, 25 insertions, 282 deletions
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 973dec799b5c..dae1bd5b8c3e 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -196,8 +196,6 @@ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ | |||
196 | 196 | ||
197 | EXPORT_SYMBOL(ide_hwifs); | 197 | EXPORT_SYMBOL(ide_hwifs); |
198 | 198 | ||
199 | static struct list_head ide_drives = LIST_HEAD_INIT(ide_drives); | ||
200 | |||
201 | /* | 199 | /* |
202 | * Do not even *think* about calling this! | 200 | * Do not even *think* about calling this! |
203 | */ | 201 | */ |
@@ -358,54 +356,6 @@ static int ide_system_bus_speed(void) | |||
358 | return system_bus_speed; | 356 | return system_bus_speed; |
359 | } | 357 | } |
360 | 358 | ||
361 | /* | ||
362 | * drives_lock protects the list of drives, drivers_lock the | ||
363 | * list of drivers. Currently nobody takes both at once. | ||
364 | */ | ||
365 | |||
366 | static DEFINE_SPINLOCK(drives_lock); | ||
367 | static DEFINE_SPINLOCK(drivers_lock); | ||
368 | static LIST_HEAD(drivers); | ||
369 | |||
370 | /* Iterator for the driver list. */ | ||
371 | |||
372 | static void *m_start(struct seq_file *m, loff_t *pos) | ||
373 | { | ||
374 | struct list_head *p; | ||
375 | loff_t l = *pos; | ||
376 | spin_lock(&drivers_lock); | ||
377 | list_for_each(p, &drivers) | ||
378 | if (!l--) | ||
379 | return list_entry(p, ide_driver_t, drivers); | ||
380 | return NULL; | ||
381 | } | ||
382 | |||
383 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) | ||
384 | { | ||
385 | struct list_head *p = ((ide_driver_t *)v)->drivers.next; | ||
386 | (*pos)++; | ||
387 | return p==&drivers ? NULL : list_entry(p, ide_driver_t, drivers); | ||
388 | } | ||
389 | |||
390 | static void m_stop(struct seq_file *m, void *v) | ||
391 | { | ||
392 | spin_unlock(&drivers_lock); | ||
393 | } | ||
394 | |||
395 | static int show_driver(struct seq_file *m, void *v) | ||
396 | { | ||
397 | ide_driver_t *driver = v; | ||
398 | seq_printf(m, "%s version %s\n", driver->name, driver->version); | ||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | struct seq_operations ide_drivers_op = { | ||
403 | .start = m_start, | ||
404 | .next = m_next, | ||
405 | .stop = m_stop, | ||
406 | .show = show_driver | ||
407 | }; | ||
408 | |||
409 | #ifdef CONFIG_PROC_FS | 359 | #ifdef CONFIG_PROC_FS |
410 | struct proc_dir_entry *proc_ide_root; | 360 | struct proc_dir_entry *proc_ide_root; |
411 | #endif | 361 | #endif |
@@ -630,7 +580,7 @@ void ide_unregister(unsigned int index) | |||
630 | ide_hwif_t *hwif, *g; | 580 | ide_hwif_t *hwif, *g; |
631 | static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */ | 581 | static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */ |
632 | ide_hwgroup_t *hwgroup; | 582 | ide_hwgroup_t *hwgroup; |
633 | int irq_count = 0, unit, i; | 583 | int irq_count = 0, unit; |
634 | 584 | ||
635 | BUG_ON(index >= MAX_HWIFS); | 585 | BUG_ON(index >= MAX_HWIFS); |
636 | 586 | ||
@@ -643,23 +593,22 @@ void ide_unregister(unsigned int index) | |||
643 | goto abort; | 593 | goto abort; |
644 | for (unit = 0; unit < MAX_DRIVES; ++unit) { | 594 | for (unit = 0; unit < MAX_DRIVES; ++unit) { |
645 | drive = &hwif->drives[unit]; | 595 | drive = &hwif->drives[unit]; |
646 | if (!drive->present) | 596 | if (!drive->present) { |
597 | if (drive->devfs_name[0] != '\0') { | ||
598 | devfs_remove(drive->devfs_name); | ||
599 | drive->devfs_name[0] = '\0'; | ||
600 | } | ||
647 | continue; | 601 | continue; |
648 | if (drive->usage || DRIVER(drive)->busy) | 602 | } |
649 | goto abort; | 603 | spin_unlock_irq(&ide_lock); |
650 | drive->dead = 1; | 604 | device_unregister(&drive->gendev); |
605 | down(&drive->gendev_rel_sem); | ||
606 | spin_lock_irq(&ide_lock); | ||
651 | } | 607 | } |
652 | hwif->present = 0; | 608 | hwif->present = 0; |
653 | 609 | ||
654 | spin_unlock_irq(&ide_lock); | 610 | spin_unlock_irq(&ide_lock); |
655 | 611 | ||
656 | for (unit = 0; unit < MAX_DRIVES; ++unit) { | ||
657 | drive = &hwif->drives[unit]; | ||
658 | if (!drive->present) | ||
659 | continue; | ||
660 | DRIVER(drive)->cleanup(drive); | ||
661 | } | ||
662 | |||
663 | destroy_proc_ide_interface(hwif); | 612 | destroy_proc_ide_interface(hwif); |
664 | 613 | ||
665 | hwgroup = hwif->hwgroup; | 614 | hwgroup = hwif->hwgroup; |
@@ -687,44 +636,6 @@ void ide_unregister(unsigned int index) | |||
687 | * Remove us from the hwgroup, and free | 636 | * Remove us from the hwgroup, and free |
688 | * the hwgroup if we were the only member | 637 | * the hwgroup if we were the only member |
689 | */ | 638 | */ |
690 | for (i = 0; i < MAX_DRIVES; ++i) { | ||
691 | drive = &hwif->drives[i]; | ||
692 | if (drive->devfs_name[0] != '\0') { | ||
693 | devfs_remove(drive->devfs_name); | ||
694 | drive->devfs_name[0] = '\0'; | ||
695 | } | ||
696 | if (!drive->present) | ||
697 | continue; | ||
698 | if (drive == drive->next) { | ||
699 | /* special case: last drive from hwgroup. */ | ||
700 | BUG_ON(hwgroup->drive != drive); | ||
701 | hwgroup->drive = NULL; | ||
702 | } else { | ||
703 | ide_drive_t *walk; | ||
704 | |||
705 | walk = hwgroup->drive; | ||
706 | while (walk->next != drive) | ||
707 | walk = walk->next; | ||
708 | walk->next = drive->next; | ||
709 | if (hwgroup->drive == drive) { | ||
710 | hwgroup->drive = drive->next; | ||
711 | hwgroup->hwif = HWIF(hwgroup->drive); | ||
712 | } | ||
713 | } | ||
714 | BUG_ON(hwgroup->drive == drive); | ||
715 | if (drive->id != NULL) { | ||
716 | kfree(drive->id); | ||
717 | drive->id = NULL; | ||
718 | } | ||
719 | drive->present = 0; | ||
720 | /* Messed up locking ... */ | ||
721 | spin_unlock_irq(&ide_lock); | ||
722 | blk_cleanup_queue(drive->queue); | ||
723 | device_unregister(&drive->gendev); | ||
724 | down(&drive->gendev_rel_sem); | ||
725 | spin_lock_irq(&ide_lock); | ||
726 | drive->queue = NULL; | ||
727 | } | ||
728 | if (hwif->next == hwif) { | 639 | if (hwif->next == hwif) { |
729 | BUG_ON(hwgroup->hwif != hwif); | 640 | BUG_ON(hwgroup->hwif != hwif); |
730 | kfree(hwgroup); | 641 | kfree(hwgroup); |
@@ -1304,73 +1215,6 @@ int system_bus_clock (void) | |||
1304 | 1215 | ||
1305 | EXPORT_SYMBOL(system_bus_clock); | 1216 | EXPORT_SYMBOL(system_bus_clock); |
1306 | 1217 | ||
1307 | /* | ||
1308 | * Locking is badly broken here - since way back. That sucker is | ||
1309 | * root-only, but that's not an excuse... The real question is what | ||
1310 | * exclusion rules do we want here. | ||
1311 | */ | ||
1312 | int ide_replace_subdriver (ide_drive_t *drive, const char *driver) | ||
1313 | { | ||
1314 | if (!drive->present || drive->usage || drive->dead) | ||
1315 | goto abort; | ||
1316 | if (DRIVER(drive)->cleanup(drive)) | ||
1317 | goto abort; | ||
1318 | strlcpy(drive->driver_req, driver, sizeof(drive->driver_req)); | ||
1319 | if (ata_attach(drive)) { | ||
1320 | spin_lock(&drives_lock); | ||
1321 | list_del_init(&drive->list); | ||
1322 | spin_unlock(&drives_lock); | ||
1323 | drive->driver_req[0] = 0; | ||
1324 | ata_attach(drive); | ||
1325 | } else { | ||
1326 | drive->driver_req[0] = 0; | ||
1327 | } | ||
1328 | if (drive->driver && !strcmp(drive->driver->name, driver)) | ||
1329 | return 0; | ||
1330 | abort: | ||
1331 | return 1; | ||
1332 | } | ||
1333 | |||
1334 | /** | ||
1335 | * ata_attach - attach an ATA/ATAPI device | ||
1336 | * @drive: drive to attach | ||
1337 | * | ||
1338 | * Takes a drive that is as yet not assigned to any midlayer IDE | ||
1339 | * driver (or is assigned to the default driver) and figures out | ||
1340 | * which driver would like to own it. If nobody claims the drive | ||
1341 | * then it is automatically attached to the default driver used for | ||
1342 | * unclaimed objects. | ||
1343 | * | ||
1344 | * A return of zero indicates attachment to a driver, of one | ||
1345 | * attachment to the default driver. | ||
1346 | * | ||
1347 | * Takes drivers_lock. | ||
1348 | */ | ||
1349 | |||
1350 | int ata_attach(ide_drive_t *drive) | ||
1351 | { | ||
1352 | struct list_head *p; | ||
1353 | spin_lock(&drivers_lock); | ||
1354 | list_for_each(p, &drivers) { | ||
1355 | ide_driver_t *driver = list_entry(p, ide_driver_t, drivers); | ||
1356 | if (!try_module_get(driver->owner)) | ||
1357 | continue; | ||
1358 | spin_unlock(&drivers_lock); | ||
1359 | if (driver->attach(drive) == 0) { | ||
1360 | module_put(driver->owner); | ||
1361 | drive->gendev.driver = &driver->gen_driver; | ||
1362 | return 0; | ||
1363 | } | ||
1364 | spin_lock(&drivers_lock); | ||
1365 | module_put(driver->owner); | ||
1366 | } | ||
1367 | drive->gendev.driver = NULL; | ||
1368 | spin_unlock(&drivers_lock); | ||
1369 | if (ide_register_subdriver(drive, NULL)) | ||
1370 | panic("ide: default attach failed"); | ||
1371 | return 1; | ||
1372 | } | ||
1373 | |||
1374 | static int generic_ide_suspend(struct device *dev, pm_message_t state) | 1218 | static int generic_ide_suspend(struct device *dev, pm_message_t state) |
1375 | { | 1219 | { |
1376 | ide_drive_t *drive = dev->driver_data; | 1220 | ide_drive_t *drive = dev->driver_data; |
@@ -2013,27 +1857,11 @@ static void __init probe_for_hwifs (void) | |||
2013 | #endif | 1857 | #endif |
2014 | } | 1858 | } |
2015 | 1859 | ||
2016 | int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) | 1860 | void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) |
2017 | { | 1861 | { |
2018 | unsigned long flags; | ||
2019 | |||
2020 | spin_lock_irqsave(&ide_lock, flags); | ||
2021 | if (!drive->present || drive->driver != NULL || | ||
2022 | drive->usage || drive->dead) { | ||
2023 | spin_unlock_irqrestore(&ide_lock, flags); | ||
2024 | return 1; | ||
2025 | } | ||
2026 | drive->driver = driver; | ||
2027 | spin_unlock_irqrestore(&ide_lock, flags); | ||
2028 | spin_lock(&drives_lock); | ||
2029 | list_add_tail(&drive->list, driver ? &driver->drives : &ide_drives); | ||
2030 | spin_unlock(&drives_lock); | ||
2031 | // printk(KERN_INFO "%s: attached %s driver.\n", drive->name, driver->name); | ||
2032 | #ifdef CONFIG_PROC_FS | 1862 | #ifdef CONFIG_PROC_FS |
2033 | if (driver) | 1863 | ide_add_proc_entries(drive->proc, driver->proc, drive); |
2034 | ide_add_proc_entries(drive->proc, driver->proc, drive); | ||
2035 | #endif | 1864 | #endif |
2036 | return 0; | ||
2037 | } | 1865 | } |
2038 | 1866 | ||
2039 | EXPORT_SYMBOL(ide_register_subdriver); | 1867 | EXPORT_SYMBOL(ide_register_subdriver); |
@@ -2041,136 +1869,51 @@ EXPORT_SYMBOL(ide_register_subdriver); | |||
2041 | /** | 1869 | /** |
2042 | * ide_unregister_subdriver - disconnect drive from driver | 1870 | * ide_unregister_subdriver - disconnect drive from driver |
2043 | * @drive: drive to unplug | 1871 | * @drive: drive to unplug |
1872 | * @driver: driver | ||
2044 | * | 1873 | * |
2045 | * Disconnect a drive from the driver it was attached to and then | 1874 | * Disconnect a drive from the driver it was attached to and then |
2046 | * clean up the various proc files and other objects attached to it. | 1875 | * clean up the various proc files and other objects attached to it. |
2047 | * | 1876 | * |
2048 | * Takes ide_setting_sem, ide_lock and drives_lock. | 1877 | * Takes ide_setting_sem and ide_lock. |
2049 | * Caller must hold none of the locks. | 1878 | * Caller must hold none of the locks. |
2050 | * | ||
2051 | * No locking versus subdriver unload because we are moving to the | ||
2052 | * default driver anyway. Wants double checking. | ||
2053 | */ | 1879 | */ |
2054 | 1880 | ||
2055 | int ide_unregister_subdriver (ide_drive_t *drive) | 1881 | void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver) |
2056 | { | 1882 | { |
2057 | unsigned long flags; | 1883 | unsigned long flags; |
2058 | 1884 | ||
2059 | down(&ide_setting_sem); | 1885 | down(&ide_setting_sem); |
2060 | spin_lock_irqsave(&ide_lock, flags); | 1886 | spin_lock_irqsave(&ide_lock, flags); |
2061 | if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) { | ||
2062 | spin_unlock_irqrestore(&ide_lock, flags); | ||
2063 | up(&ide_setting_sem); | ||
2064 | return 1; | ||
2065 | } | ||
2066 | #ifdef CONFIG_PROC_FS | 1887 | #ifdef CONFIG_PROC_FS |
2067 | ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc); | 1888 | ide_remove_proc_entries(drive->proc, driver->proc); |
2068 | #endif | 1889 | #endif |
2069 | auto_remove_settings(drive); | 1890 | auto_remove_settings(drive); |
2070 | drive->driver = NULL; | ||
2071 | spin_unlock_irqrestore(&ide_lock, flags); | 1891 | spin_unlock_irqrestore(&ide_lock, flags); |
2072 | up(&ide_setting_sem); | 1892 | up(&ide_setting_sem); |
2073 | spin_lock(&drives_lock); | ||
2074 | list_del_init(&drive->list); | ||
2075 | spin_unlock(&drives_lock); | ||
2076 | /* drive will be added to &ide_drives in ata_attach() */ | ||
2077 | return 0; | ||
2078 | } | 1893 | } |
2079 | 1894 | ||
2080 | EXPORT_SYMBOL(ide_unregister_subdriver); | 1895 | EXPORT_SYMBOL(ide_unregister_subdriver); |
2081 | 1896 | ||
2082 | static int ide_drive_remove(struct device * dev) | ||
2083 | { | ||
2084 | ide_drive_t * drive = container_of(dev,ide_drive_t,gendev); | ||
2085 | DRIVER(drive)->cleanup(drive); | ||
2086 | return 0; | ||
2087 | } | ||
2088 | |||
2089 | /** | ||
2090 | * ide_register_driver - register IDE device driver | ||
2091 | * @driver: the IDE device driver | ||
2092 | * | ||
2093 | * Register a new device driver and then scan the devices | ||
2094 | * on the IDE bus in case any should be attached to the | ||
2095 | * driver we have just registered. If so attach them. | ||
2096 | * | ||
2097 | * Takes drivers_lock and drives_lock. | ||
2098 | */ | ||
2099 | |||
2100 | int ide_register_driver(ide_driver_t *driver) | ||
2101 | { | ||
2102 | struct list_head list; | ||
2103 | struct list_head *list_loop; | ||
2104 | struct list_head *tmp_storage; | ||
2105 | |||
2106 | spin_lock(&drivers_lock); | ||
2107 | list_add(&driver->drivers, &drivers); | ||
2108 | spin_unlock(&drivers_lock); | ||
2109 | |||
2110 | INIT_LIST_HEAD(&list); | ||
2111 | spin_lock(&drives_lock); | ||
2112 | list_splice_init(&ide_drives, &list); | ||
2113 | spin_unlock(&drives_lock); | ||
2114 | |||
2115 | list_for_each_safe(list_loop, tmp_storage, &list) { | ||
2116 | ide_drive_t *drive = container_of(list_loop, ide_drive_t, list); | ||
2117 | list_del_init(&drive->list); | ||
2118 | if (drive->present) | ||
2119 | ata_attach(drive); | ||
2120 | } | ||
2121 | driver->gen_driver.name = (char *) driver->name; | ||
2122 | driver->gen_driver.bus = &ide_bus_type; | ||
2123 | driver->gen_driver.remove = ide_drive_remove; | ||
2124 | return driver_register(&driver->gen_driver); | ||
2125 | } | ||
2126 | |||
2127 | EXPORT_SYMBOL(ide_register_driver); | ||
2128 | |||
2129 | /** | ||
2130 | * ide_unregister_driver - unregister IDE device driver | ||
2131 | * @driver: the IDE device driver | ||
2132 | * | ||
2133 | * Called when a driver module is being unloaded. We reattach any | ||
2134 | * devices to whatever driver claims them next (typically the default | ||
2135 | * driver). | ||
2136 | * | ||
2137 | * Takes drivers_lock and called functions will take ide_setting_sem. | ||
2138 | */ | ||
2139 | |||
2140 | void ide_unregister_driver(ide_driver_t *driver) | ||
2141 | { | ||
2142 | ide_drive_t *drive; | ||
2143 | |||
2144 | spin_lock(&drivers_lock); | ||
2145 | list_del(&driver->drivers); | ||
2146 | spin_unlock(&drivers_lock); | ||
2147 | |||
2148 | driver_unregister(&driver->gen_driver); | ||
2149 | |||
2150 | while(!list_empty(&driver->drives)) { | ||
2151 | drive = list_entry(driver->drives.next, ide_drive_t, list); | ||
2152 | if (driver->cleanup(drive)) { | ||
2153 | printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); | ||
2154 | BUG(); | ||
2155 | } | ||
2156 | ata_attach(drive); | ||
2157 | } | ||
2158 | } | ||
2159 | |||
2160 | EXPORT_SYMBOL(ide_unregister_driver); | ||
2161 | |||
2162 | /* | 1897 | /* |
2163 | * Probe module | 1898 | * Probe module |
2164 | */ | 1899 | */ |
2165 | 1900 | ||
2166 | EXPORT_SYMBOL(ide_lock); | 1901 | EXPORT_SYMBOL(ide_lock); |
2167 | 1902 | ||
1903 | static int ide_bus_match(struct device *dev, struct device_driver *drv) | ||
1904 | { | ||
1905 | return 1; | ||
1906 | } | ||
1907 | |||
2168 | struct bus_type ide_bus_type = { | 1908 | struct bus_type ide_bus_type = { |
2169 | .name = "ide", | 1909 | .name = "ide", |
1910 | .match = ide_bus_match, | ||
2170 | .suspend = generic_ide_suspend, | 1911 | .suspend = generic_ide_suspend, |
2171 | .resume = generic_ide_resume, | 1912 | .resume = generic_ide_resume, |
2172 | }; | 1913 | }; |
2173 | 1914 | ||
1915 | EXPORT_SYMBOL_GPL(ide_bus_type); | ||
1916 | |||
2174 | /* | 1917 | /* |
2175 | * This is gets invoked once during initialization, to set *everything* up | 1918 | * This is gets invoked once during initialization, to set *everything* up |
2176 | */ | 1919 | */ |