Commit b20830fb authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] turn ide_reinit_drive() into ata_attach()

ide_reinit_drive() turned into ata_attach().  Said beast takes a drive,
tries to feed it to high-level drivers and drops it on the ata_unused if
nobody claims the sucker.  IOW, that's what ide_register_module() used
to do, but for a single drive.

ideprobe_init() calls ata_attach() instead of putting on ata_unused.

ide_register_module() eliminated.  Some of the callers do not need it
anymore, some (ide_replace_subdriver()) actually want ata_attach(drive).

ide_scan_devices() is gone.  There were two remaining callers - in
ide_register_module() and ide_unregister_module().  The former had been
turned into "put driver on the list, empty ata_unused into temporary
list and call ata_attach() on all drives there".  The latter is "remove
driver from the list, call ->cleanup() and ata_attach() for all drives"
(->cleanup() gives the drive up, ata_attach() gives the remaining
drivers a shot for that drive; if nobody claims it - it's put on
ata_unused).
parent ce3058ec
...@@ -988,9 +988,6 @@ static ide_module_t ideprobe_module = { ...@@ -988,9 +988,6 @@ static ide_module_t ideprobe_module = {
NULL NULL
}; };
extern struct list_head ata_unused; /* temporary */
extern spinlock_t ata_drives_lock; /* temporary */
int ideprobe_init (void) int ideprobe_init (void)
{ {
unsigned int index; unsigned int index;
...@@ -1016,12 +1013,8 @@ int ideprobe_init (void) ...@@ -1016,12 +1013,8 @@ int ideprobe_init (void)
int unit; int unit;
if (!hwif->present) if (!hwif->present)
continue; continue;
for (unit = 0; unit < MAX_DRIVES; ++unit) { for (unit = 0; unit < MAX_DRIVES; ++unit)
ide_drive_t *drive = &hwif->drives[unit]; ata_attach(&hwif->drives[unit]);
spin_lock(&ata_drives_lock);
list_add(&drive->list, &ata_unused);
spin_unlock(&ata_drives_lock);
}
} }
if (!ide_probe) if (!ide_probe)
ide_probe = &ideprobe_module; ide_probe = &ideprobe_module;
......
...@@ -1849,31 +1849,12 @@ static void ide_probe_module (void) ...@@ -1849,31 +1849,12 @@ static void ide_probe_module (void)
revalidate_drives(); revalidate_drives();
} }
static void ide_driver_module (void)
{
int index;
ide_module_t *module = ide_modules;
for (index = 0; index < MAX_HWIFS; ++index)
if (ide_hwifs[index].present)
goto search;
ide_probe_module();
search:
while (module) {
(void) module->init();
module = module->next;
}
revalidate_drives();
}
static int ide_open (struct inode * inode, struct file * filp) static int ide_open (struct inode * inode, struct file * filp)
{ {
ide_drive_t *drive; ide_drive_t *drive;
if ((drive = get_info_ptr(inode->i_rdev)) == NULL) if ((drive = get_info_ptr(inode->i_rdev)) == NULL)
return -ENXIO; return -ENXIO;
if (drive->driver == NULL)
ide_driver_module();
#ifdef CONFIG_KMOD #ifdef CONFIG_KMOD
if (drive->driver == NULL) { if (drive->driver == NULL) {
if (drive->media == ide_disk) if (drive->media == ide_disk)
...@@ -1916,6 +1897,15 @@ static int ide_release (struct inode * inode, struct file * file) ...@@ -1916,6 +1897,15 @@ static int ide_release (struct inode * inode, struct file * file)
return 0; return 0;
} }
static LIST_HEAD(ata_unused);
static spinlock_t drives_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;
/*
* Locking is badly broken here - since way back. That sucker is
* root-only, but that's not an excuse... The real question is what
* exclusion rules do we want here.
*/
int ide_replace_subdriver (ide_drive_t *drive, const char *driver) int ide_replace_subdriver (ide_drive_t *drive, const char *driver)
{ {
if (!drive->present || drive->busy || drive->usage) if (!drive->present || drive->busy || drive->usage)
...@@ -1923,9 +1913,17 @@ int ide_replace_subdriver (ide_drive_t *drive, const char *driver) ...@@ -1923,9 +1913,17 @@ int ide_replace_subdriver (ide_drive_t *drive, const char *driver)
if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
goto abort; goto abort;
strncpy(drive->driver_req, driver, 9); strncpy(drive->driver_req, driver, 9);
ide_driver_module(); if (ata_attach(drive)) {
drive->driver_req[0] = 0; spin_lock(&drives_lock);
ide_driver_module(); list_del_init(&drive->list);
spin_unlock(&drives_lock);
drive->driver_req[0] = 0;
ata_attach(drive);
revalidate_drives();
} else {
drive->driver_req[0] = 0;
revalidate_drives();
}
if (DRIVER(drive) && !strcmp(DRIVER(drive)->name, driver)) if (DRIVER(drive) && !strcmp(DRIVER(drive)->name, driver))
return 0; return 0;
abort: abort:
...@@ -2002,12 +2000,6 @@ void ide_unregister (unsigned int index) ...@@ -2002,12 +2000,6 @@ void ide_unregister (unsigned int index)
goto abort; goto abort;
} }
hwif->present = 0; hwif->present = 0;
spin_lock(&ata_drives_lock);
for (unit = 0; unit < MAX_DRIVES; ++unit) {
drive = &hwif->drives[unit];
list_del_init(&drive->list);
}
spin_unlock(&ata_drives_lock);
/* /*
* All clear? Then blow away the buffer cache * All clear? Then blow away the buffer cache
...@@ -2227,7 +2219,6 @@ int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp) ...@@ -2227,7 +2219,6 @@ int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
create_proc_ide_interfaces(); create_proc_ide_interfaces();
#endif #endif
ide_driver_module();
} }
if (hwifp) if (hwifp)
...@@ -2515,9 +2506,7 @@ int system_bus_clock (void) ...@@ -2515,9 +2506,7 @@ int system_bus_clock (void)
return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed )); return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
} }
static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED; int ata_attach(ide_drive_t *drive)
int ide_reinit_drive (ide_drive_t *drive)
{ {
ide_module_t *module; ide_module_t *module;
spin_lock(&drivers_lock); spin_lock(&drivers_lock);
...@@ -2536,6 +2525,9 @@ int ide_reinit_drive (ide_drive_t *drive) ...@@ -2536,6 +2525,9 @@ int ide_reinit_drive (ide_drive_t *drive)
__MOD_DEC_USE_COUNT(driver->owner); __MOD_DEC_USE_COUNT(driver->owner);
} }
spin_unlock(&drivers_lock); spin_unlock(&drivers_lock);
spin_lock(&drives_lock);
list_add(&drive->list, &ata_unused);
spin_unlock(&drives_lock);
return 1; return 1;
} }
...@@ -3480,23 +3472,6 @@ static void setup_driver_defaults (ide_drive_t *drive) ...@@ -3480,23 +3472,6 @@ static void setup_driver_defaults (ide_drive_t *drive)
if (d->reinit == NULL) d->reinit = default_reinit; if (d->reinit == NULL) d->reinit = default_reinit;
} }
static ide_drive_t *ide_scan_devices(ide_driver_t *driver, int n)
{
unsigned int unit, index, i;
for (index = 0, i = 0; index < MAX_HWIFS; ++index) {
ide_hwif_t *hwif = &ide_hwifs[index];
if (!hwif->present)
continue;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
if (drive->driver == driver && ++i > n)
return drive;
}
}
return NULL;
}
int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version) int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version)
{ {
unsigned long flags; unsigned long flags;
...@@ -3510,10 +3485,9 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int versio ...@@ -3510,10 +3485,9 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int versio
drive->driver = driver; drive->driver = driver;
setup_driver_defaults(drive); setup_driver_defaults(drive);
spin_unlock_irqrestore(&ide_lock, flags); spin_unlock_irqrestore(&ide_lock, flags);
spin_lock(&ata_drives_lock); spin_lock(&drives_lock);
list_del(&drive->list); /* will die */
list_add(&drive->list, &driver->drives); list_add(&drive->list, &driver->drives);
spin_unlock(&ata_drives_lock); spin_unlock(&drives_lock);
if (drive->autotune != 2) { if (drive->autotune != 2) {
if (!driver->supports_dma && HWIF(drive)->dmaproc != NULL) if (!driver->supports_dma && HWIF(drive)->dmaproc != NULL)
(void) (HWIF(drive)->dmaproc(ide_dma_off_quietly, drive)); (void) (HWIF(drive)->dmaproc(ide_dma_off_quietly, drive));
...@@ -3529,11 +3503,6 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int versio ...@@ -3529,11 +3503,6 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int versio
return 0; return 0;
} }
LIST_HEAD(ata_unused);
spinlock_t ata_drives_lock = SPIN_LOCK_UNLOCKED;
EXPORT_SYMBOL(ata_unused); /* temporary export */
EXPORT_SYMBOL(ata_drives_lock); /* temporary export */
int ide_unregister_subdriver (ide_drive_t *drive) int ide_unregister_subdriver (ide_drive_t *drive)
{ {
unsigned long flags; unsigned long flags;
...@@ -3554,25 +3523,16 @@ int ide_unregister_subdriver (ide_drive_t *drive) ...@@ -3554,25 +3523,16 @@ int ide_unregister_subdriver (ide_drive_t *drive)
auto_remove_settings(drive); auto_remove_settings(drive);
drive->driver = NULL; drive->driver = NULL;
spin_unlock_irqrestore(&ide_lock, flags); spin_unlock_irqrestore(&ide_lock, flags);
spin_lock(&ata_drives_lock); spin_lock(&drives_lock);
list_del(&drive->list); list_del_init(&drive->list);
list_add(&drive->list, &ata_unused); spin_unlock(&drives_lock);
spin_unlock(&ata_drives_lock);
return 0; return 0;
} }
int ide_register_module (ide_module_t *module) int ide_register_module (ide_module_t *module)
{ {
ide_driver_t *driver = module->info;
ide_module_t *p; ide_module_t *p;
ide_drive_t *drive; struct list_head list;
int failed = 0;
while ((drive = ide_scan_devices (NULL, failed++)) != NULL) {
if (driver->reinit(drive))
continue;
failed--;
}
spin_lock(&drivers_lock); spin_lock(&drivers_lock);
for (p = ide_modules; p; p = p->next) { for (p = ide_modules; p; p = p->next) {
...@@ -3584,6 +3544,17 @@ int ide_register_module (ide_module_t *module) ...@@ -3584,6 +3544,17 @@ int ide_register_module (ide_module_t *module)
module->next = ide_modules; module->next = ide_modules;
ide_modules = module; ide_modules = module;
spin_unlock(&drivers_lock); spin_unlock(&drivers_lock);
spin_lock(&drives_lock);
INIT_LIST_HEAD(&list);
list_splice_init(&ata_unused, &list);
spin_unlock(&drives_lock);
while (!list_empty(&list)) {
ide_drive_t *drive = list_entry(list.next, ide_drive_t, list);
list_del_init(&drive->list);
ata_attach(drive);
}
revalidate_drives(); revalidate_drives();
return 0; return 0;
} }
...@@ -3593,12 +3564,18 @@ void ide_unregister_module (ide_module_t *module) ...@@ -3593,12 +3564,18 @@ void ide_unregister_module (ide_module_t *module)
ide_driver_t *driver = module->info; ide_driver_t *driver = module->info;
ide_module_t **p; ide_module_t **p;
ide_drive_t *drive; ide_drive_t *drive;
int failed = 0;
while ((drive = ide_scan_devices(driver, failed)) != NULL) { spin_lock(&drivers_lock);
for (p = &ide_modules; (*p) && (*p) != module; p = &((*p)->next));
if (*p)
*p = (*p)->next;
spin_unlock(&drivers_lock);
while(!list_empty(&driver->drives)) {
drive = list_entry(driver->drives.next, ide_drive_t, list);
if (driver->cleanup(drive)) { if (driver->cleanup(drive)) {
printk ("%s: cleanup_module() called while still busy\n", drive->name); printk("%s: cleanup_module() called while still busy\n", drive->name);
failed++; BUG();
} }
/* We must remove proc entries defined in this module. /* We must remove proc entries defined in this module.
Otherwise we oops while accessing these entries */ Otherwise we oops while accessing these entries */
...@@ -3606,13 +3583,8 @@ void ide_unregister_module (ide_module_t *module) ...@@ -3606,13 +3583,8 @@ void ide_unregister_module (ide_module_t *module)
if (drive->proc) if (drive->proc)
ide_remove_proc_entries(drive->proc, driver->proc); ide_remove_proc_entries(drive->proc, driver->proc);
#endif #endif
ata_attach(drive);
} }
spin_lock(&drivers_lock);
for (p = &ide_modules; (*p) && (*p) != module; p = &((*p)->next));
if (*p)
*p = (*p)->next;
spin_unlock(&drivers_lock);
} }
struct block_device_operations ide_fops[] = {{ struct block_device_operations ide_fops[] = {{
...@@ -3688,7 +3660,7 @@ EXPORT_SYMBOL(current_capacity); ...@@ -3688,7 +3660,7 @@ EXPORT_SYMBOL(current_capacity);
EXPORT_SYMBOL(system_bus_clock); EXPORT_SYMBOL(system_bus_clock);
EXPORT_SYMBOL(ide_reinit_drive); EXPORT_SYMBOL(ata_attach);
static int ide_notify_reboot (struct notifier_block *this, unsigned long event, void *x) static int ide_notify_reboot (struct notifier_block *this, unsigned long event, void *x)
{ {
......
...@@ -1213,7 +1213,7 @@ extern struct block_device_operations ide_fops[]; ...@@ -1213,7 +1213,7 @@ extern struct block_device_operations ide_fops[];
extern ide_proc_entry_t generic_subdriver_entries[]; extern ide_proc_entry_t generic_subdriver_entries[];
#endif #endif
int ide_reinit_drive (ide_drive_t *drive); int ata_attach(ide_drive_t *drive);
#ifdef _IDE_C #ifdef _IDE_C
#ifdef CONFIG_BLK_DEV_IDE #ifdef CONFIG_BLK_DEV_IDE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment