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:
Родитель
7d8b72aadd
Коммит
af761f277b
|
@ -183,8 +183,6 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
|
|||
static int pcd_packet(struct cdrom_device_info *cdi,
|
||||
struct packet_command *cgc);
|
||||
|
||||
static int pcd_detect(void);
|
||||
static void pcd_probe_capabilities(void);
|
||||
static void do_pcd_read_drq(void);
|
||||
static blk_status_t pcd_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||
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,
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
struct pcd_unit *cd = cdi->handle;
|
||||
|
@ -679,90 +630,31 @@ static int pcd_probe(struct pcd_unit *cd, int ms)
|
|||
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 };
|
||||
struct pcd_unit *cd;
|
||||
char buffer[32];
|
||||
int 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 */
|
||||
if ((buffer[11] & 1) == 0)
|
||||
cd->info.mask |= CDC_CD_R;
|
||||
if ((buffer[11] & 2) == 0)
|
||||
cd->info.mask |= CDC_CD_RW;
|
||||
if ((buffer[12] & 1) == 0)
|
||||
cd->info.mask |= CDC_PLAY_AUDIO;
|
||||
if ((buffer[14] & 1) == 0)
|
||||
cd->info.mask |= CDC_LOCK;
|
||||
if ((buffer[14] & 8) == 0)
|
||||
cd->info.mask |= CDC_OPEN_TRAY;
|
||||
if ((buffer[14] >> 6) == 0)
|
||||
cd->info.mask |= CDC_CLOSE_TRAY;
|
||||
}
|
||||
}
|
||||
ret = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
static int pcd_detect(void)
|
||||
{
|
||||
int k, unit;
|
||||
struct pcd_unit *cd;
|
||||
/* we should now have the cap page */
|
||||
if ((buffer[11] & 1) == 0)
|
||||
cd->info.mask |= CDC_CD_R;
|
||||
if ((buffer[11] & 2) == 0)
|
||||
cd->info.mask |= CDC_CD_RW;
|
||||
if ((buffer[12] & 1) == 0)
|
||||
cd->info.mask |= CDC_PLAY_AUDIO;
|
||||
if ((buffer[14] & 1) == 0)
|
||||
cd->info.mask |= CDC_LOCK;
|
||||
if ((buffer[14] & 8) == 0)
|
||||
cd->info.mask |= CDC_OPEN_TRAY;
|
||||
if ((buffer[14] >> 6) == 0)
|
||||
cd->info.mask |= CDC_CLOSE_TRAY;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* I/O request processing */
|
||||
|
@ -999,43 +891,121 @@ static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
|
|||
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)
|
||||
{
|
||||
struct pcd_unit *cd;
|
||||
int unit;
|
||||
int found = 0, unit;
|
||||
|
||||
if (disable)
|
||||
return -EINVAL;
|
||||
|
||||
pcd_init_units();
|
||||
|
||||
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);
|
||||
}
|
||||
if (register_blkdev(major, name))
|
||||
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++) {
|
||||
if (cd->present) {
|
||||
register_cdrom(cd->disk, &cd->info);
|
||||
cd->disk->private_data = cd;
|
||||
add_disk(cd->disk);
|
||||
for (unit = 0; unit < PCD_UNITS; unit++) {
|
||||
if ((*drives[unit])[D_PRT])
|
||||
pcd_drive_count++;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
out_unregister_pi_driver:
|
||||
pi_unregister_driver(par_drv);
|
||||
out_unregister_blkdev:
|
||||
unregister_blkdev(major, name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void __exit pcd_exit(void)
|
||||
|
@ -1044,20 +1014,18 @@ static void __exit pcd_exit(void)
|
|||
int unit;
|
||||
|
||||
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
|
||||
if (!cd->disk)
|
||||
if (!cd->present)
|
||||
continue;
|
||||
|
||||
if (cd->present) {
|
||||
del_gendisk(cd->disk);
|
||||
pi_release(cd->pi);
|
||||
unregister_cdrom(&cd->info);
|
||||
}
|
||||
blk_cleanup_queue(cd->disk->queue);
|
||||
del_gendisk(cd->disk);
|
||||
pi_release(cd->pi);
|
||||
unregister_cdrom(&cd->info);
|
||||
blk_cleanup_disk(cd->disk);
|
||||
|
||||
blk_mq_free_tag_set(&cd->tag_set);
|
||||
put_disk(cd->disk);
|
||||
}
|
||||
unregister_blkdev(major, name);
|
||||
pi_unregister_driver(par_drv);
|
||||
unregister_blkdev(major, name);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
Загрузка…
Ссылка в новой задаче