pcd: cleanup initialization
Refactor the pcd 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
7d8b72aadd
commit
af761f277b
@ -183,8 +183,6 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
|
|||||||
static int pcd_packet(struct cdrom_device_info *cdi,
|
static int pcd_packet(struct cdrom_device_info *cdi,
|
||||||
struct packet_command *cgc);
|
struct packet_command *cgc);
|
||||||
|
|
||||||
static int pcd_detect(void);
|
|
||||||
static void pcd_probe_capabilities(void);
|
|
||||||
static void do_pcd_read_drq(void);
|
static void do_pcd_read_drq(void);
|
||||||
static blk_status_t pcd_queue_rq(struct blk_mq_hw_ctx *hctx,
|
static blk_status_t pcd_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||||
const struct blk_mq_queue_data *bd);
|
const struct blk_mq_queue_data *bd);
|
||||||
@ -302,53 +300,6 @@ static const struct blk_mq_ops pcd_mq_ops = {
|
|||||||
.queue_rq = pcd_queue_rq,
|
.queue_rq = pcd_queue_rq,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void pcd_init_units(void)
|
|
||||||
{
|
|
||||||
struct pcd_unit *cd;
|
|
||||||
int unit;
|
|
||||||
|
|
||||||
pcd_drive_count = 0;
|
|
||||||
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
|
|
||||||
struct gendisk *disk;
|
|
||||||
|
|
||||||
if (blk_mq_alloc_sq_tag_set(&cd->tag_set, &pcd_mq_ops, 1,
|
|
||||||
BLK_MQ_F_SHOULD_MERGE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
disk = blk_mq_alloc_disk(&cd->tag_set, cd);
|
|
||||||
if (IS_ERR(disk)) {
|
|
||||||
blk_mq_free_tag_set(&cd->tag_set);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&cd->rq_list);
|
|
||||||
blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
|
|
||||||
cd->disk = disk;
|
|
||||||
cd->pi = &cd->pia;
|
|
||||||
cd->present = 0;
|
|
||||||
cd->last_sense = 0;
|
|
||||||
cd->changed = 1;
|
|
||||||
cd->drive = (*drives[unit])[D_SLV];
|
|
||||||
if ((*drives[unit])[D_PRT])
|
|
||||||
pcd_drive_count++;
|
|
||||||
|
|
||||||
cd->name = &cd->info.name[0];
|
|
||||||
snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit);
|
|
||||||
cd->info.ops = &pcd_dops;
|
|
||||||
cd->info.handle = cd;
|
|
||||||
cd->info.speed = 0;
|
|
||||||
cd->info.capacity = 1;
|
|
||||||
cd->info.mask = 0;
|
|
||||||
disk->major = major;
|
|
||||||
disk->first_minor = unit;
|
|
||||||
disk->minors = 1;
|
|
||||||
strcpy(disk->disk_name, cd->name); /* umm... */
|
|
||||||
disk->fops = &pcd_bdops;
|
|
||||||
disk->flags = GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
|
|
||||||
disk->events = DISK_EVENT_MEDIA_CHANGE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pcd_open(struct cdrom_device_info *cdi, int purpose)
|
static int pcd_open(struct cdrom_device_info *cdi, int purpose)
|
||||||
{
|
{
|
||||||
struct pcd_unit *cd = cdi->handle;
|
struct pcd_unit *cd = cdi->handle;
|
||||||
@ -679,19 +630,16 @@ static int pcd_probe(struct pcd_unit *cd, int ms)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pcd_probe_capabilities(void)
|
static int pcd_probe_capabilities(struct pcd_unit *cd)
|
||||||
{
|
{
|
||||||
int unit, r;
|
|
||||||
char buffer[32];
|
|
||||||
char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 };
|
char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 };
|
||||||
struct pcd_unit *cd;
|
char buffer[32];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities");
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
|
|
||||||
if (!cd->present)
|
|
||||||
continue;
|
|
||||||
r = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities");
|
|
||||||
if (r)
|
|
||||||
continue;
|
|
||||||
/* we should now have the cap page */
|
/* we should now have the cap page */
|
||||||
if ((buffer[11] & 1) == 0)
|
if ((buffer[11] & 1) == 0)
|
||||||
cd->info.mask |= CDC_CD_R;
|
cd->info.mask |= CDC_CD_R;
|
||||||
@ -705,64 +653,8 @@ static void pcd_probe_capabilities(void)
|
|||||||
cd->info.mask |= CDC_OPEN_TRAY;
|
cd->info.mask |= CDC_OPEN_TRAY;
|
||||||
if ((buffer[14] >> 6) == 0)
|
if ((buffer[14] >> 6) == 0)
|
||||||
cd->info.mask |= CDC_CLOSE_TRAY;
|
cd->info.mask |= CDC_CLOSE_TRAY;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pcd_detect(void)
|
|
||||||
{
|
|
||||||
int k, unit;
|
|
||||||
struct pcd_unit *cd;
|
|
||||||
|
|
||||||
printk("%s: %s version %s, major %d, nice %d\n",
|
|
||||||
name, name, PCD_VERSION, major, nice);
|
|
||||||
|
|
||||||
par_drv = pi_register_driver(name);
|
|
||||||
if (!par_drv) {
|
|
||||||
pr_err("failed to register %s driver\n", name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
k = 0;
|
|
||||||
if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
|
|
||||||
cd = pcd;
|
|
||||||
if (cd->disk && pi_init(cd->pi, 1, -1, -1, -1, -1, -1,
|
|
||||||
pcd_buffer, PI_PCD, verbose, cd->name)) {
|
|
||||||
if (!pcd_probe(cd, -1)) {
|
|
||||||
cd->present = 1;
|
|
||||||
k++;
|
|
||||||
} else
|
|
||||||
pi_release(cd->pi);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
|
|
||||||
int *conf = *drives[unit];
|
|
||||||
if (!conf[D_PRT])
|
|
||||||
continue;
|
|
||||||
if (!cd->disk)
|
|
||||||
continue;
|
|
||||||
if (!pi_init(cd->pi, 0, conf[D_PRT], conf[D_MOD],
|
|
||||||
conf[D_UNI], conf[D_PRO], conf[D_DLY],
|
|
||||||
pcd_buffer, PI_PCD, verbose, cd->name))
|
|
||||||
continue;
|
|
||||||
if (!pcd_probe(cd, conf[D_SLV])) {
|
|
||||||
cd->present = 1;
|
|
||||||
k++;
|
|
||||||
} else
|
|
||||||
pi_release(cd->pi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (k)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
printk("%s: No CD-ROM drive found\n", name);
|
|
||||||
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
|
|
||||||
if (!cd->disk)
|
|
||||||
continue;
|
|
||||||
blk_cleanup_disk(cd->disk);
|
|
||||||
blk_mq_free_tag_set(&cd->tag_set);
|
|
||||||
}
|
|
||||||
pi_unregister_driver(par_drv);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* I/O request processing */
|
/* I/O request processing */
|
||||||
@ -999,43 +891,121 @@ static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pcd_init_unit(struct pcd_unit *cd, 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(&cd->tag_set, &pcd_mq_ops, 1,
|
||||||
|
BLK_MQ_F_SHOULD_MERGE);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
disk = blk_mq_alloc_disk(&cd->tag_set, cd);
|
||||||
|
if (IS_ERR(disk)) {
|
||||||
|
ret = PTR_ERR(disk);
|
||||||
|
goto out_free_tag_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&cd->rq_list);
|
||||||
|
blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH);
|
||||||
|
cd->disk = disk;
|
||||||
|
cd->pi = &cd->pia;
|
||||||
|
cd->present = 0;
|
||||||
|
cd->last_sense = 0;
|
||||||
|
cd->changed = 1;
|
||||||
|
cd->drive = (*drives[cd - pcd])[D_SLV];
|
||||||
|
|
||||||
|
cd->name = &cd->info.name[0];
|
||||||
|
snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit);
|
||||||
|
cd->info.ops = &pcd_dops;
|
||||||
|
cd->info.handle = cd;
|
||||||
|
cd->info.speed = 0;
|
||||||
|
cd->info.capacity = 1;
|
||||||
|
cd->info.mask = 0;
|
||||||
|
disk->major = major;
|
||||||
|
disk->first_minor = unit;
|
||||||
|
disk->minors = 1;
|
||||||
|
strcpy(disk->disk_name, cd->name); /* umm... */
|
||||||
|
disk->fops = &pcd_bdops;
|
||||||
|
disk->flags = GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
|
||||||
|
disk->events = DISK_EVENT_MEDIA_CHANGE;
|
||||||
|
|
||||||
|
if (!pi_init(cd->pi, autoprobe, port, mode, unit, protocol, delay,
|
||||||
|
pcd_buffer, PI_PCD, verbose, cd->name))
|
||||||
|
goto out_free_disk;
|
||||||
|
if (pcd_probe(cd, ms))
|
||||||
|
goto out_pi_release;
|
||||||
|
|
||||||
|
cd->present = 1;
|
||||||
|
pcd_probe_capabilities(cd);
|
||||||
|
register_cdrom(cd->disk, &cd->info);
|
||||||
|
add_disk(cd->disk);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_pi_release:
|
||||||
|
pi_release(cd->pi);
|
||||||
|
out_free_disk:
|
||||||
|
blk_cleanup_disk(cd->disk);
|
||||||
|
out_free_tag_set:
|
||||||
|
blk_mq_free_tag_set(&cd->tag_set);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int __init pcd_init(void)
|
static int __init pcd_init(void)
|
||||||
{
|
{
|
||||||
struct pcd_unit *cd;
|
int found = 0, unit;
|
||||||
int unit;
|
|
||||||
|
|
||||||
if (disable)
|
if (disable)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
pcd_init_units();
|
if (register_blkdev(major, name))
|
||||||
|
|
||||||
if (pcd_detect())
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
/* get the atapi capabilities page */
|
|
||||||
pcd_probe_capabilities();
|
|
||||||
|
|
||||||
if (register_blkdev(major, name)) {
|
|
||||||
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
|
|
||||||
if (!cd->disk)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
blk_cleanup_queue(cd->disk->queue);
|
|
||||||
blk_mq_free_tag_set(&cd->tag_set);
|
|
||||||
put_disk(cd->disk);
|
|
||||||
}
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
|
pr_info("%s: %s version %s, major %d, nice %d\n",
|
||||||
|
name, name, PCD_VERSION, major, nice);
|
||||||
|
|
||||||
|
par_drv = pi_register_driver(name);
|
||||||
|
if (!par_drv) {
|
||||||
|
pr_err("failed to register %s driver\n", name);
|
||||||
|
goto out_unregister_blkdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
|
for (unit = 0; unit < PCD_UNITS; unit++) {
|
||||||
if (cd->present) {
|
if ((*drives[unit])[D_PRT])
|
||||||
register_cdrom(cd->disk, &cd->info);
|
pcd_drive_count++;
|
||||||
cd->disk->private_data = cd;
|
|
||||||
add_disk(cd->disk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
|
||||||
|
if (!pcd_init_unit(pcd, 1, -1, -1, -1, -1, -1, -1))
|
||||||
|
found++;
|
||||||
|
} else {
|
||||||
|
for (unit = 0; unit < PCD_UNITS; unit++) {
|
||||||
|
struct pcd_unit *cd = &pcd[unit];
|
||||||
|
int *conf = *drives[unit];
|
||||||
|
|
||||||
|
if (!conf[D_PRT])
|
||||||
|
continue;
|
||||||
|
if (!pcd_init_unit(cd, 0, conf[D_PRT], conf[D_MOD],
|
||||||
|
conf[D_UNI], conf[D_PRO], conf[D_DLY],
|
||||||
|
conf[D_SLV]))
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
pr_info("%s: No CD-ROM drive found\n", name);
|
||||||
|
goto out_unregister_pi_driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 pcd_exit(void)
|
static void __exit pcd_exit(void)
|
||||||
@ -1044,20 +1014,18 @@ static void __exit pcd_exit(void)
|
|||||||
int unit;
|
int unit;
|
||||||
|
|
||||||
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
|
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
|
||||||
if (!cd->disk)
|
if (!cd->present)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (cd->present) {
|
|
||||||
del_gendisk(cd->disk);
|
del_gendisk(cd->disk);
|
||||||
pi_release(cd->pi);
|
pi_release(cd->pi);
|
||||||
unregister_cdrom(&cd->info);
|
unregister_cdrom(&cd->info);
|
||||||
}
|
blk_cleanup_disk(cd->disk);
|
||||||
blk_cleanup_queue(cd->disk->queue);
|
|
||||||
blk_mq_free_tag_set(&cd->tag_set);
|
blk_mq_free_tag_set(&cd->tag_set);
|
||||||
put_disk(cd->disk);
|
|
||||||
}
|
}
|
||||||
unregister_blkdev(major, name);
|
|
||||||
pi_unregister_driver(par_drv);
|
pi_unregister_driver(par_drv);
|
||||||
|
unregister_blkdev(major, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
Loading…
Reference in New Issue
Block a user