pcd: cleanup initialization
authorChristoph Hellwig <hch@lst.de>
Mon, 27 Sep 2021 22:01:04 +0000 (15:01 -0700)
committerJens Axboe <axboe@kernel.dk>
Mon, 18 Oct 2021 20:41:36 +0000 (14:41 -0600)
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>
drivers/block/paride/pcd.c

index 8903fda..93ed636 100644 (file)
@@ -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;
-
-       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;
-       }
-}
-
-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);
+       char buffer[32];
+       int ret;
 
-       par_drv = pi_register_driver(name);
-       if (!par_drv) {
-               pr_err("failed to register %s driver\n", name);
-               return -1;
-       }
+       ret = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities");
+       if (ret)
+               return ret;
+
+       /* 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;
 
-       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 (register_blkdev(major, name))
+               return -EBUSY;
 
-       if (pcd_detect())
-               return -ENODEV;
+       pr_info("%s: %s version %s, major %d, nice %d\n",
+               name, name, PCD_VERSION, major, nice);
 
-       /* get the atapi capabilities page */
-       pcd_probe_capabilities();
+       par_drv = pi_register_driver(name);
+       if (!par_drv) {
+               pr_err("failed to register %s driver\n", name);
+               goto out_unregister_blkdev;
+       }
 
-       if (register_blkdev(major, name)) {
-               for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
-                       if (!cd->disk)
-                               continue;
+       for (unit = 0; unit < PCD_UNITS; unit++) {
+               if ((*drives[unit])[D_PRT])
+                       pcd_drive_count++;
+       }
 
-                       blk_cleanup_queue(cd->disk->queue);
-                       blk_mq_free_tag_set(&cd->tag_set);
-                       put_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++;
                }
-               return -EBUSY;
        }
 
-       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);
-               }
+       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");