OSDN Git Service

paride: convert pd to blk-mq
authorJens Axboe <axboe@kernel.dk>
Mon, 15 Oct 2018 19:53:50 +0000 (13:53 -0600)
committerJens Axboe <axboe@kernel.dk>
Tue, 16 Oct 2018 02:08:12 +0000 (20:08 -0600)
Tested-by: Ondrej Zary <linux@rainbow-software.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/paride/pd.c

index 7cf9475..ae4971e 100644 (file)
@@ -151,7 +151,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV};
 #include <linux/delay.h>
 #include <linux/hdreg.h>
 #include <linux/cdrom.h>       /* for the eject ioctl */
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/blkpg.h>
 #include <linux/kernel.h>
 #include <linux/mutex.h>
@@ -236,6 +236,8 @@ struct pd_unit {
        int alt_geom;
        char name[PD_NAMELEN];  /* pda, pdb, etc ... */
        struct gendisk *gd;
+       struct blk_mq_tag_set tag_set;
+       struct list_head rq_list;
 };
 
 static struct pd_unit pd[PD_UNITS];
@@ -399,9 +401,17 @@ static int set_next_request(void)
                if (++pd_queue == PD_UNITS)
                        pd_queue = 0;
                if (q) {
-                       pd_req = blk_fetch_request(q);
-                       if (pd_req)
-                               break;
+                       struct pd_unit *disk = q->queuedata;
+
+                       if (list_empty(&disk->rq_list))
+                               continue;
+
+                       pd_req = list_first_entry(&disk->rq_list,
+                                                       struct request,
+                                                       queuelist);
+                       list_del_init(&pd_req->queuelist);
+                       blk_mq_start_request(pd_req);
+                       break;
                }
        } while (pd_queue != old_pos);
 
@@ -412,7 +422,6 @@ static void run_fsm(void)
 {
        while (1) {
                enum action res;
-               unsigned long saved_flags;
                int stop = 0;
 
                if (!phase) {
@@ -433,19 +442,24 @@ static void run_fsm(void)
                }
 
                switch(res = phase()) {
-                       case Ok: case Fail:
+                       case Ok: case Fail: {
+                               blk_status_t err;
+
+                               err = res == Ok ? 0 : BLK_STS_IOERR;
                                pi_disconnect(pi_current);
                                pd_claimed = 0;
                                phase = NULL;
-                               spin_lock_irqsave(&pd_lock, saved_flags);
-                               if (!__blk_end_request_cur(pd_req,
-                                               res == Ok ? 0 : BLK_STS_IOERR)) {
-                                       if (!set_next_request())
-                                               stop = 1;
+                               spin_lock_irq(&pd_lock);
+                               if (!blk_update_request(pd_req, err,
+                                               blk_rq_cur_bytes(pd_req))) {
+                                       __blk_mq_end_request(pd_req, err);
+                                       pd_req = NULL;
+                                       stop = !set_next_request();
                                }
-                               spin_unlock_irqrestore(&pd_lock, saved_flags);
+                               spin_unlock_irq(&pd_lock);
                                if (stop)
                                        return;
+                               }
                                /* fall through */
                        case Hold:
                                schedule_fsm();
@@ -505,11 +519,17 @@ static int pd_next_buf(void)
        if (pd_count)
                return 0;
        spin_lock_irqsave(&pd_lock, saved_flags);
-       __blk_end_request_cur(pd_req, 0);
-       pd_count = blk_rq_cur_sectors(pd_req);
-       pd_buf = bio_data(pd_req->bio);
+       if (!blk_update_request(pd_req, 0, blk_rq_cur_bytes(pd_req))) {
+               __blk_mq_end_request(pd_req, 0);
+               pd_req = NULL;
+               pd_count = 0;
+               pd_buf = NULL;
+       } else {
+               pd_count = blk_rq_cur_sectors(pd_req);
+               pd_buf = bio_data(pd_req->bio);
+       }
        spin_unlock_irqrestore(&pd_lock, saved_flags);
-       return 0;
+       return !pd_count;
 }
 
 static unsigned long pd_timeout;
@@ -726,15 +746,21 @@ static enum action pd_identify(struct pd_unit *disk)
 
 /* end of io request engine */
 
-static void do_pd_request(struct request_queue * q)
+static blk_status_t pd_queue_rq(struct blk_mq_hw_ctx *hctx,
+                               const struct blk_mq_queue_data *bd)
 {
-       if (pd_req)
-               return;
-       pd_req = blk_fetch_request(q);
-       if (!pd_req)
-               return;
+       struct pd_unit *disk = hctx->queue->queuedata;
+
+       spin_lock_irq(&pd_lock);
+       if (!pd_req) {
+               pd_req = bd->rq;
+               blk_mq_start_request(pd_req);
+       } else
+               list_add_tail(&bd->rq->queuelist, &disk->rq_list);
+       spin_unlock_irq(&pd_lock);
 
-       schedule_fsm();
+       run_fsm();
+       return BLK_STS_OK;
 }
 
 static int pd_special_command(struct pd_unit *disk,
@@ -847,23 +873,33 @@ static const struct block_device_operations pd_fops = {
 
 /* probing */
 
+static const struct blk_mq_ops pd_mq_ops = {
+       .queue_rq       = pd_queue_rq,
+};
+
 static void pd_probe_drive(struct pd_unit *disk)
 {
-       struct gendisk *p = alloc_disk(1 << PD_BITS);
+       struct gendisk *p;
+
+       p = alloc_disk(1 << PD_BITS);
        if (!p)
                return;
+
        strcpy(p->disk_name, disk->name);
        p->fops = &pd_fops;
        p->major = major;
        p->first_minor = (disk - pd) << PD_BITS;
        disk->gd = p;
        p->private_data = disk;
-       p->queue = blk_init_queue(do_pd_request, &pd_lock);
-       if (!p->queue) {
-               disk->gd = NULL;
-               put_disk(p);
+
+       p->queue = blk_mq_init_sq_queue(&disk->tag_set, &pd_mq_ops, 2,
+                               BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING);
+       if (IS_ERR(p->queue)) {
+               p->queue = NULL;
                return;
        }
+
+       p->queue->queuedata = disk;
        blk_queue_max_hw_sectors(p->queue, cluster);
        blk_queue_bounce_limit(p->queue, BLK_BOUNCE_HIGH);
 
@@ -895,6 +931,7 @@ static int pd_detect(void)
                disk->standby = parm[D_SBY];
                if (parm[D_PRT])
                        pd_drive_count++;
+               INIT_LIST_HEAD(&disk->rq_list);
        }
 
        par_drv = pi_register_driver(name);
@@ -972,6 +1009,7 @@ static void __exit pd_exit(void)
                        disk->gd = NULL;
                        del_gendisk(p);
                        blk_cleanup_queue(p->queue);
+                       blk_mq_free_tag_set(&disk->tag_set);
                        put_disk(p);
                        pi_release(disk->pi);
                }