Commit 794b6dd5 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] floppy.c: better floppy_init error handling

From: "Randy.Dunlap" <rddunlap@osdl.org>

From: "Luiz Fernando N. Capitulino" <lcapitulino@prefeitura.sp.gov.br>

Adds a better audit for floppy_init().  Fixes one real bug (in calling
blk_queue_max_sectors()).
parent 2d976592
...@@ -4247,35 +4247,40 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) ...@@ -4247,35 +4247,40 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
int __init floppy_init(void) int __init floppy_init(void)
{ {
int i, unit, drive; int i, unit, drive;
int err; int err, dr;
raw_cmd = NULL; raw_cmd = NULL;
i = 0;
for (i = 0; i < N_DRIVE; i++) { for (dr = 0; dr < N_DRIVE; dr++) {
disks[i] = alloc_disk(1); disks[dr] = alloc_disk(1);
if (!disks[i]) if (!disks[dr]) {
goto Enomem; err = -ENOMEM;
goto out_put_disk;
}
disks[i]->major = FLOPPY_MAJOR; disks[dr]->major = FLOPPY_MAJOR;
disks[i]->first_minor = TOMINOR(i); disks[dr]->first_minor = TOMINOR(i);
disks[i]->fops = &floppy_fops; disks[dr]->fops = &floppy_fops;
sprintf(disks[i]->disk_name, "fd%d", i); sprintf(disks[dr]->disk_name, "fd%d", dr);
init_timer(&motor_off_timer[i]); init_timer(&motor_off_timer[dr]);
motor_off_timer[i].data = i; motor_off_timer[dr].data = dr;
motor_off_timer[i].function = motor_off_callback; motor_off_timer[dr].function = motor_off_callback;
} }
devfs_mk_dir("floppy"); devfs_mk_dir("floppy");
if ((err = register_blkdev(FLOPPY_MAJOR, "fd")))
goto out; err = register_blkdev(FLOPPY_MAJOR, "fd");
if (err)
goto out_devfs_remove;
floppy_queue = blk_init_queue(do_fd_request, &floppy_lock); floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
blk_queue_max_sectors(floppy_queue, 64);
if (!floppy_queue) { if (!floppy_queue) {
err = -ENOMEM; err = -ENOMEM;
goto fail_queue; goto out_unreg_blkdev;
} }
blk_queue_max_sectors(floppy_queue, 64);
blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE, blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
floppy_find, NULL, NULL); floppy_find, NULL, NULL);
...@@ -4306,17 +4311,20 @@ int __init floppy_init(void) ...@@ -4306,17 +4311,20 @@ int __init floppy_init(void)
use_virtual_dma = can_use_virtual_dma & 1; use_virtual_dma = can_use_virtual_dma & 1;
fdc_state[0].address = FDC1; fdc_state[0].address = FDC1;
if (fdc_state[0].address == -1) { if (fdc_state[0].address == -1) {
del_timer(&fd_timeout);
err = -ENODEV; err = -ENODEV;
goto out1; goto out_unreg_region;
} }
#if N_FDC > 1 #if N_FDC > 1
fdc_state[1].address = FDC2; fdc_state[1].address = FDC2;
#endif #endif
fdc = 0; /* reset fdc in case of unexpected interrupt */ fdc = 0; /* reset fdc in case of unexpected interrupt */
if (floppy_grab_irq_and_dma()) { err = floppy_grab_irq_and_dma();
if (err) {
del_timer(&fd_timeout);
err = -EBUSY; err = -EBUSY;
goto out1; goto out_unreg_region;
} }
/* initialise drive state */ /* initialise drive state */
...@@ -4373,11 +4381,8 @@ int __init floppy_init(void) ...@@ -4373,11 +4381,8 @@ int __init floppy_init(void)
initialising = 0; initialising = 0;
if (have_no_fdc) { if (have_no_fdc) {
DPRINT("no floppy controllers found\n"); DPRINT("no floppy controllers found\n");
flush_scheduled_work();
if (usage_count)
floppy_release_irq_and_dma();
err = have_no_fdc; err = have_no_fdc;
goto out2; goto out_flush_work;
} }
for (drive = 0; drive < N_DRIVE; drive++) { for (drive = 0; drive < N_DRIVE; drive++) {
...@@ -4392,26 +4397,37 @@ int __init floppy_init(void) ...@@ -4392,26 +4397,37 @@ int __init floppy_init(void)
add_disk(disks[drive]); add_disk(disks[drive]);
} }
platform_device_register(&floppy_device); err = platform_device_register(&floppy_device);
if (err)
goto out_del_disk;
return 0; return 0;
out1: out_del_disk:
del_timer(&fd_timeout); for (drive = 0; drive < N_DRIVE; drive++) {
out2: if (!(allowed_drive_mask & (1 << drive)))
continue;
if (fdc_state[FDC(drive)].version == FDC_NONE)
continue;
del_gendisk(disks[drive]);
}
out_flush_work:
flush_scheduled_work();
if (usage_count)
floppy_release_irq_and_dma();
out_unreg_region:
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
blk_cleanup_queue(floppy_queue); blk_cleanup_queue(floppy_queue);
fail_queue: out_unreg_blkdev:
unregister_blkdev(FLOPPY_MAJOR, "fd"); unregister_blkdev(FLOPPY_MAJOR, "fd");
out: out_devfs_remove:
for (i = 0; i < N_DRIVE; i++)
put_disk(disks[i]);
devfs_remove("floppy"); devfs_remove("floppy");
out_put_disk:
while (dr--) {
del_timer(&motor_off_timer[dr]);
put_disk(disks[dr]);
}
return err; return err;
Enomem:
while (i--)
put_disk(disks[i]);
return -ENOMEM;
} }
static spinlock_t floppy_usage_lock = SPIN_LOCK_UNLOCKED; static spinlock_t floppy_usage_lock = SPIN_LOCK_UNLOCKED;
......
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