pf: cleanup initialization
Refactor the pf initialization to have a dedicated helper to initialize a single disk. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
af761f277b
commit
fb367e6bae
@ -214,7 +214,6 @@ static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo);
|
|||||||
|
|
||||||
static void pf_release(struct gendisk *disk, fmode_t mode);
|
static void pf_release(struct gendisk *disk, fmode_t mode);
|
||||||
|
|
||||||
static int pf_detect(void);
|
|
||||||
static void do_pf_read(void);
|
static void do_pf_read(void);
|
||||||
static void do_pf_read_start(void);
|
static void do_pf_read_start(void);
|
||||||
static void do_pf_write(void);
|
static void do_pf_write(void);
|
||||||
@ -285,45 +284,6 @@ static const struct blk_mq_ops pf_mq_ops = {
|
|||||||
.queue_rq = pf_queue_rq,
|
.queue_rq = pf_queue_rq,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __init pf_init_units(void)
|
|
||||||
{
|
|
||||||
struct pf_unit *pf;
|
|
||||||
int unit;
|
|
||||||
|
|
||||||
pf_drive_count = 0;
|
|
||||||
for (unit = 0, pf = units; unit < PF_UNITS; unit++, pf++) {
|
|
||||||
struct gendisk *disk;
|
|
||||||
|
|
||||||
if (blk_mq_alloc_sq_tag_set(&pf->tag_set, &pf_mq_ops, 1,
|
|
||||||
BLK_MQ_F_SHOULD_MERGE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
disk = blk_mq_alloc_disk(&pf->tag_set, pf);
|
|
||||||
if (IS_ERR(disk)) {
|
|
||||||
blk_mq_free_tag_set(&pf->tag_set);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&pf->rq_list);
|
|
||||||
blk_queue_max_segments(disk->queue, cluster);
|
|
||||||
blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
|
|
||||||
pf->disk = disk;
|
|
||||||
pf->pi = &pf->pia;
|
|
||||||
pf->media_status = PF_NM;
|
|
||||||
pf->drive = (*drives[unit])[D_SLV];
|
|
||||||
pf->lun = (*drives[unit])[D_LUN];
|
|
||||||
snprintf(pf->name, PF_NAMELEN, "%s%d", name, unit);
|
|
||||||
disk->major = major;
|
|
||||||
disk->first_minor = unit;
|
|
||||||
disk->minors = 1;
|
|
||||||
strcpy(disk->disk_name, pf->name);
|
|
||||||
disk->fops = &pf_fops;
|
|
||||||
disk->events = DISK_EVENT_MEDIA_CHANGE;
|
|
||||||
if (!(*drives[unit])[D_PRT])
|
|
||||||
pf_drive_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pf_open(struct block_device *bdev, fmode_t mode)
|
static int pf_open(struct block_device *bdev, fmode_t mode)
|
||||||
{
|
{
|
||||||
struct pf_unit *pf = bdev->bd_disk->private_data;
|
struct pf_unit *pf = bdev->bd_disk->private_data;
|
||||||
@ -718,59 +678,6 @@ static int pf_probe(struct pf_unit *pf)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pf_detect(void)
|
|
||||||
{
|
|
||||||
struct pf_unit *pf = units;
|
|
||||||
int k, unit;
|
|
||||||
|
|
||||||
printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
|
|
||||||
name, name, PF_VERSION, major, cluster, nice);
|
|
||||||
|
|
||||||
par_drv = pi_register_driver(name);
|
|
||||||
if (!par_drv) {
|
|
||||||
pr_err("failed to register %s driver\n", name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
k = 0;
|
|
||||||
if (pf_drive_count == 0) {
|
|
||||||
if (pi_init(pf->pi, 1, -1, -1, -1, -1, -1, pf_scratch, PI_PF,
|
|
||||||
verbose, pf->name)) {
|
|
||||||
if (!pf_probe(pf) && pf->disk) {
|
|
||||||
pf->present = 1;
|
|
||||||
k++;
|
|
||||||
} else
|
|
||||||
pi_release(pf->pi);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else
|
|
||||||
for (unit = 0; unit < PF_UNITS; unit++, pf++) {
|
|
||||||
int *conf = *drives[unit];
|
|
||||||
if (!conf[D_PRT])
|
|
||||||
continue;
|
|
||||||
if (pi_init(pf->pi, 0, conf[D_PRT], conf[D_MOD],
|
|
||||||
conf[D_UNI], conf[D_PRO], conf[D_DLY],
|
|
||||||
pf_scratch, PI_PF, verbose, pf->name)) {
|
|
||||||
if (pf->disk && !pf_probe(pf)) {
|
|
||||||
pf->present = 1;
|
|
||||||
k++;
|
|
||||||
} else
|
|
||||||
pi_release(pf->pi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (k)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
printk("%s: No ATAPI disk detected\n", name);
|
|
||||||
for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
|
|
||||||
if (!pf->disk)
|
|
||||||
continue;
|
|
||||||
blk_cleanup_disk(pf->disk);
|
|
||||||
blk_mq_free_tag_set(&pf->tag_set);
|
|
||||||
}
|
|
||||||
pi_unregister_driver(par_drv);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The i/o request engine */
|
/* The i/o request engine */
|
||||||
|
|
||||||
static int pf_start(struct pf_unit *pf, int cmd, int b, int c)
|
static int pf_start(struct pf_unit *pf, int cmd, int b, int c)
|
||||||
@ -1014,61 +921,129 @@ static void do_pf_write_done(void)
|
|||||||
next_request(0);
|
next_request(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __init pf_init_unit(struct pf_unit *pf, bool autoprobe, int port,
|
||||||
|
int mode, int unit, int protocol, int delay, int ms)
|
||||||
|
{
|
||||||
|
struct gendisk *disk;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = blk_mq_alloc_sq_tag_set(&pf->tag_set, &pf_mq_ops, 1,
|
||||||
|
BLK_MQ_F_SHOULD_MERGE);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
disk = blk_mq_alloc_disk(&pf->tag_set, pf);
|
||||||
|
if (IS_ERR(disk)) {
|
||||||
|
ret = PTR_ERR(disk);
|
||||||
|
goto out_free_tag_set;
|
||||||
|
}
|
||||||
|
disk->major = major;
|
||||||
|
disk->first_minor = pf - units;
|
||||||
|
disk->minors = 1;
|
||||||
|
strcpy(disk->disk_name, pf->name);
|
||||||
|
disk->fops = &pf_fops;
|
||||||
|
disk->events = DISK_EVENT_MEDIA_CHANGE;
|
||||||
|
disk->private_data = pf;
|
||||||
|
|
||||||
|
blk_queue_max_segments(disk->queue, cluster);
|
||||||
|
blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&pf->rq_list);
|
||||||
|
pf->disk = disk;
|
||||||
|
pf->pi = &pf->pia;
|
||||||
|
pf->media_status = PF_NM;
|
||||||
|
pf->drive = (*drives[disk->first_minor])[D_SLV];
|
||||||
|
pf->lun = (*drives[disk->first_minor])[D_LUN];
|
||||||
|
snprintf(pf->name, PF_NAMELEN, "%s%d", name, disk->first_minor);
|
||||||
|
|
||||||
|
if (!pi_init(pf->pi, autoprobe, port, mode, unit, protocol, delay,
|
||||||
|
pf_scratch, PI_PF, verbose, pf->name))
|
||||||
|
goto out_free_disk;
|
||||||
|
if (pf_probe(pf))
|
||||||
|
goto out_pi_release;
|
||||||
|
|
||||||
|
add_disk(disk);
|
||||||
|
pf->present = 1;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_pi_release:
|
||||||
|
pi_release(pf->pi);
|
||||||
|
out_free_disk:
|
||||||
|
blk_cleanup_disk(pf->disk);
|
||||||
|
out_free_tag_set:
|
||||||
|
blk_mq_free_tag_set(&pf->tag_set);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int __init pf_init(void)
|
static int __init pf_init(void)
|
||||||
{ /* preliminary initialisation */
|
{ /* preliminary initialisation */
|
||||||
struct pf_unit *pf;
|
struct pf_unit *pf;
|
||||||
int unit;
|
int found = 0, unit;
|
||||||
|
|
||||||
if (disable)
|
if (disable)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
pf_init_units();
|
if (register_blkdev(major, name))
|
||||||
|
|
||||||
if (pf_detect())
|
|
||||||
return -ENODEV;
|
|
||||||
pf_busy = 0;
|
|
||||||
|
|
||||||
if (register_blkdev(major, name)) {
|
|
||||||
for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
|
|
||||||
if (!pf->disk)
|
|
||||||
continue;
|
|
||||||
blk_cleanup_queue(pf->disk->queue);
|
|
||||||
blk_mq_free_tag_set(&pf->tag_set);
|
|
||||||
put_disk(pf->disk);
|
|
||||||
}
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
|
printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
|
||||||
|
name, name, PF_VERSION, major, cluster, nice);
|
||||||
|
|
||||||
|
par_drv = pi_register_driver(name);
|
||||||
|
if (!par_drv) {
|
||||||
|
pr_err("failed to register %s driver\n", name);
|
||||||
|
goto out_unregister_blkdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
|
for (unit = 0; unit < PF_UNITS; unit++) {
|
||||||
struct gendisk *disk = pf->disk;
|
if (!(*drives[unit])[D_PRT])
|
||||||
|
pf_drive_count++;
|
||||||
if (!pf->present)
|
|
||||||
continue;
|
|
||||||
disk->private_data = pf;
|
|
||||||
add_disk(disk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pf = units;
|
||||||
|
if (pf_drive_count == 0) {
|
||||||
|
if (pf_init_unit(pf, 1, -1, -1, -1, -1, -1, verbose))
|
||||||
|
found++;
|
||||||
|
} else {
|
||||||
|
for (unit = 0; unit < PF_UNITS; unit++, pf++) {
|
||||||
|
int *conf = *drives[unit];
|
||||||
|
if (!conf[D_PRT])
|
||||||
|
continue;
|
||||||
|
if (pf_init_unit(pf, 0, conf[D_PRT], conf[D_MOD],
|
||||||
|
conf[D_UNI], conf[D_PRO], conf[D_DLY],
|
||||||
|
verbose))
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
printk("%s: No ATAPI disk detected\n", name);
|
||||||
|
goto out_unregister_pi_driver;
|
||||||
|
}
|
||||||
|
pf_busy = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_unregister_pi_driver:
|
||||||
|
pi_unregister_driver(par_drv);
|
||||||
|
out_unregister_blkdev:
|
||||||
|
unregister_blkdev(major, name);
|
||||||
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit pf_exit(void)
|
static void __exit pf_exit(void)
|
||||||
{
|
{
|
||||||
struct pf_unit *pf;
|
struct pf_unit *pf;
|
||||||
int unit;
|
int unit;
|
||||||
unregister_blkdev(major, name);
|
|
||||||
for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
|
for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
|
||||||
if (!pf->disk)
|
if (!pf->present)
|
||||||
continue;
|
continue;
|
||||||
|
del_gendisk(pf->disk);
|
||||||
if (pf->present)
|
blk_cleanup_disk(pf->disk);
|
||||||
del_gendisk(pf->disk);
|
|
||||||
|
|
||||||
blk_cleanup_queue(pf->disk->queue);
|
|
||||||
blk_mq_free_tag_set(&pf->tag_set);
|
blk_mq_free_tag_set(&pf->tag_set);
|
||||||
put_disk(pf->disk);
|
pi_release(pf->pi);
|
||||||
|
|
||||||
if (pf->present)
|
|
||||||
pi_release(pf->pi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unregister_blkdev(major, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
Loading…
Reference in New Issue
Block a user