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

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
Loading
Loading
Loading
Loading
+55 −43
Original line number Diff line number Diff line
@@ -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_queue(&unit[drive].tag_set);
	if (IS_ERR(disk->queue))
		goto out_put_disk;

	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->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;

out_put_disk:
	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);
	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:
	blk_cleanup_queue(disk->queue);
	disk->queue = NULL;
	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_put_disk:
	put_disk(disk);
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;