Commit 0033a9b4 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe

amiflop: use separate gendisks for Amiga vs MS-DOS mode

Use separate gendisks (which share a tag_set) for the native Amgiga vs
the MS-DOS mode instead of redirecting the gendisk lookup using a probe
callback.  This avoids potential problems with aliased block_device
instances and will eventually allow for removing the blk_register_region
framework.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 302cfee1
...@@ -201,7 +201,7 @@ struct amiga_floppy_struct { ...@@ -201,7 +201,7 @@ struct amiga_floppy_struct {
int busy; /* true when drive is active */ int busy; /* true when drive is active */
int dirty; /* true when trackbuf is not on disk */ int dirty; /* true when trackbuf is not on disk */
int status; /* current error code for unit */ int status; /* current error code for unit */
struct gendisk *gendisk; struct gendisk *gendisk[2];
struct blk_mq_tag_set tag_set; struct blk_mq_tag_set tag_set;
}; };
...@@ -1669,6 +1669,11 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) ...@@ -1669,6 +1669,11 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
return -EBUSY; return -EBUSY;
} }
if (unit[drive].type->code == FD_NODRIVE) {
mutex_unlock(&amiflop_mutex);
return -ENXIO;
}
if (mode & (FMODE_READ|FMODE_WRITE)) { if (mode & (FMODE_READ|FMODE_WRITE)) {
bdev_check_media_change(bdev); bdev_check_media_change(bdev);
if (mode & FMODE_WRITE) { if (mode & FMODE_WRITE) {
...@@ -1695,7 +1700,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) ...@@ -1695,7 +1700,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
unit[drive].dtype=&data_types[system]; unit[drive].dtype=&data_types[system];
unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks* unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks*
data_types[system].sects*unit[drive].type->sect_mult; data_types[system].sects*unit[drive].type->sect_mult;
set_capacity(unit[drive].gendisk, unit[drive].blocks); set_capacity(unit[drive].gendisk[system], unit[drive].blocks);
printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive, printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive,
unit[drive].type->name, data_types[system].name); unit[drive].type->name, data_types[system].name);
...@@ -1772,36 +1777,68 @@ static const struct blk_mq_ops amiflop_mq_ops = { ...@@ -1772,36 +1777,68 @@ static const struct blk_mq_ops amiflop_mq_ops = {
.queue_rq = amiflop_queue_rq, .queue_rq = amiflop_queue_rq,
}; };
static struct gendisk *fd_alloc_disk(int drive) static int fd_alloc_disk(int drive, int system)
{ {
struct gendisk *disk; struct gendisk *disk;
disk = alloc_disk(1); disk = alloc_disk(1);
if (!disk) if (!disk)
goto out; goto out;
disk->queue = blk_mq_init_queue(&unit[drive].tag_set);
if (IS_ERR(disk->queue))
goto out_put_disk;
disk->major = FLOPPY_MAJOR;
disk->first_minor = drive + system;
disk->fops = &floppy_fops;
disk->events = DISK_EVENT_MEDIA_CHANGE;
if (system)
sprintf(disk->disk_name, "fd%d_msdos", drive);
else
sprintf(disk->disk_name, "fd%d", drive);
disk->private_data = &unit[drive];
set_capacity(disk, 880 * 2);
unit[drive].gendisk[system] = disk;
add_disk(disk);
return 0;
disk->queue = blk_mq_init_sq_queue(&unit[drive].tag_set, &amiflop_mq_ops, out_put_disk:
2, BLK_MQ_F_SHOULD_MERGE);
if (IS_ERR(disk->queue)) {
disk->queue = NULL; disk->queue = NULL;
goto out_put_disk; put_disk(disk);
} out:
return -ENOMEM;
}
static int fd_alloc_drive(int drive)
{
unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL); unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL);
if (!unit[drive].trackbuf) if (!unit[drive].trackbuf)
goto out_cleanup_queue; goto out;
return disk; memset(&unit[drive].tag_set, 0, sizeof(unit[drive].tag_set));
unit[drive].tag_set.ops = &amiflop_mq_ops;
unit[drive].tag_set.nr_hw_queues = 1;
unit[drive].tag_set.nr_maps = 1;
unit[drive].tag_set.queue_depth = 2;
unit[drive].tag_set.numa_node = NUMA_NO_NODE;
unit[drive].tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
if (blk_mq_alloc_tag_set(&unit[drive].tag_set))
goto out_cleanup_trackbuf;
out_cleanup_queue: pr_cont(" fd%d", drive);
blk_cleanup_queue(disk->queue);
disk->queue = NULL; if (fd_alloc_disk(drive, 0) || fd_alloc_disk(drive, 1))
goto out_cleanup_tagset;
return 0;
out_cleanup_tagset:
blk_mq_free_tag_set(&unit[drive].tag_set); blk_mq_free_tag_set(&unit[drive].tag_set);
out_put_disk: out_cleanup_trackbuf:
put_disk(disk); kfree(unit[drive].trackbuf);
out: out:
unit[drive].type->code = FD_NODRIVE; unit[drive].type->code = FD_NODRIVE;
return NULL; return -ENOMEM;
} }
static int __init fd_probe_drives(void) static int __init fd_probe_drives(void)
...@@ -1812,29 +1849,16 @@ static int __init fd_probe_drives(void) ...@@ -1812,29 +1849,16 @@ static int __init fd_probe_drives(void)
drives=0; drives=0;
nomem=0; nomem=0;
for(drive=0;drive<FD_MAX_UNITS;drive++) { for(drive=0;drive<FD_MAX_UNITS;drive++) {
struct gendisk *disk;
fd_probe(drive); fd_probe(drive);
if (unit[drive].type->code == FD_NODRIVE) if (unit[drive].type->code == FD_NODRIVE)
continue; continue;
disk = fd_alloc_disk(drive); if (fd_alloc_drive(drive) < 0) {
if (!disk) {
pr_cont(" no mem for fd%d", drive); pr_cont(" no mem for fd%d", drive);
nomem = 1; nomem = 1;
continue; continue;
} }
unit[drive].gendisk = disk;
drives++; drives++;
pr_cont(" fd%d",drive);
disk->major = FLOPPY_MAJOR;
disk->first_minor = drive;
disk->fops = &floppy_fops;
disk->events = DISK_EVENT_MEDIA_CHANGE;
sprintf(disk->disk_name, "fd%d", drive);
disk->private_data = &unit[drive];
set_capacity(disk, 880*2);
add_disk(disk);
} }
if ((drives > 0) || (nomem == 0)) { if ((drives > 0) || (nomem == 0)) {
if (drives == 0) if (drives == 0)
...@@ -1846,15 +1870,6 @@ static int __init fd_probe_drives(void) ...@@ -1846,15 +1870,6 @@ static int __init fd_probe_drives(void)
return -ENOMEM; return -ENOMEM;
} }
static struct kobject *floppy_find(dev_t dev, int *part, void *data)
{
int drive = *part & 3;
if (unit[drive].type->code == FD_NODRIVE)
return NULL;
*part = 0;
return get_disk_and_module(unit[drive].gendisk);
}
static int __init amiga_floppy_probe(struct platform_device *pdev) static int __init amiga_floppy_probe(struct platform_device *pdev)
{ {
int i, ret; int i, ret;
...@@ -1884,9 +1899,6 @@ static int __init amiga_floppy_probe(struct platform_device *pdev) ...@@ -1884,9 +1899,6 @@ static int __init amiga_floppy_probe(struct platform_device *pdev)
if (fd_probe_drives() < 1) /* No usable drives */ if (fd_probe_drives() < 1) /* No usable drives */
goto out_probe; goto out_probe;
blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
floppy_find, NULL, NULL);
/* initialize variables */ /* initialize variables */
timer_setup(&motor_on_timer, motor_on_callback, 0); timer_setup(&motor_on_timer, motor_on_callback, 0);
motor_on_timer.expires = 0; motor_on_timer.expires = 0;
......
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