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: Christoph Hellwig <hch@lst.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Родитель
302cfee150
Коммит
0033a9b41f
|
@ -201,7 +201,7 @@ struct amiga_floppy_struct {
|
|||
int busy; /* true when drive is active */
|
||||
int dirty; /* true when trackbuf is not on disk */
|
||||
int status; /* current error code for unit */
|
||||
struct gendisk *gendisk;
|
||||
struct gendisk *gendisk[2];
|
||||
struct blk_mq_tag_set tag_set;
|
||||
};
|
||||
|
||||
|
@ -1669,6 +1669,11 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (unit[drive].type->code == FD_NODRIVE) {
|
||||
mutex_unlock(&amiflop_mutex);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (mode & (FMODE_READ|FMODE_WRITE)) {
|
||||
bdev_check_media_change(bdev);
|
||||
if (mode & FMODE_WRITE) {
|
||||
|
@ -1695,7 +1700,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
|
|||
unit[drive].dtype=&data_types[system];
|
||||
unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks*
|
||||
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,
|
||||
unit[drive].type->name, data_types[system].name);
|
||||
|
@ -1772,36 +1777,68 @@ static const struct blk_mq_ops amiflop_mq_ops = {
|
|||
.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;
|
||||
|
||||
disk = alloc_disk(1);
|
||||
if (!disk)
|
||||
goto out;
|
||||
|
||||
disk->queue = blk_mq_init_sq_queue(&unit[drive].tag_set, &amiflop_mq_ops,
|
||||
2, BLK_MQ_F_SHOULD_MERGE);
|
||||
if (IS_ERR(disk->queue)) {
|
||||
disk->queue = NULL;
|
||||
disk->queue = blk_mq_init_queue(&unit[drive].tag_set);
|
||||
if (IS_ERR(disk->queue))
|
||||
goto out_put_disk;
|
||||
}
|
||||
|
||||
unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL);
|
||||
if (!unit[drive].trackbuf)
|
||||
goto out_cleanup_queue;
|
||||
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);
|
||||
|
||||
return disk;
|
||||
unit[drive].gendisk[system] = disk;
|
||||
add_disk(disk);
|
||||
return 0;
|
||||
|
||||
out_cleanup_queue:
|
||||
blk_cleanup_queue(disk->queue);
|
||||
disk->queue = NULL;
|
||||
blk_mq_free_tag_set(&unit[drive].tag_set);
|
||||
out_put_disk:
|
||||
disk->queue = NULL;
|
||||
put_disk(disk);
|
||||
out:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int fd_alloc_drive(int drive)
|
||||
{
|
||||
unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL);
|
||||
if (!unit[drive].trackbuf)
|
||||
goto out;
|
||||
|
||||
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;
|
||||
|
||||
pr_cont(" fd%d", drive);
|
||||
|
||||
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);
|
||||
out_cleanup_trackbuf:
|
||||
kfree(unit[drive].trackbuf);
|
||||
out:
|
||||
unit[drive].type->code = FD_NODRIVE;
|
||||
return NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int __init fd_probe_drives(void)
|
||||
|
@ -1812,29 +1849,16 @@ static int __init fd_probe_drives(void)
|
|||
drives=0;
|
||||
nomem=0;
|
||||
for(drive=0;drive<FD_MAX_UNITS;drive++) {
|
||||
struct gendisk *disk;
|
||||
fd_probe(drive);
|
||||
if (unit[drive].type->code == FD_NODRIVE)
|
||||
continue;
|
||||
|
||||
disk = fd_alloc_disk(drive);
|
||||
if (!disk) {
|
||||
if (fd_alloc_drive(drive) < 0) {
|
||||
pr_cont(" no mem for fd%d", drive);
|
||||
nomem = 1;
|
||||
continue;
|
||||
}
|
||||
unit[drive].gendisk = disk;
|
||||
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)
|
||||
|
@ -1846,15 +1870,6 @@ static int __init fd_probe_drives(void)
|
|||
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)
|
||||
{
|
||||
int i, ret;
|
||||
|
@ -1884,9 +1899,6 @@ static int __init amiga_floppy_probe(struct platform_device *pdev)
|
|||
if (fd_probe_drives() < 1) /* No usable drives */
|
||||
goto out_probe;
|
||||
|
||||
blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
|
||||
floppy_find, NULL, NULL);
|
||||
|
||||
/* initialize variables */
|
||||
timer_setup(&motor_on_timer, motor_on_callback, 0);
|
||||
motor_on_timer.expires = 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче