ps3disk: convert to blk-mq
authorJens Axboe <axboe@kernel.dk>
Mon, 15 Oct 2018 19:32:01 +0000 (13:32 -0600)
committerJens Axboe <axboe@kernel.dk>
Tue, 16 Oct 2018 02:07:56 +0000 (20:07 -0600)
Convert from the old request_fn style driver to blk-mq.

Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Tested-by: Geoff Levand <geoff@infradead.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/ps3disk.c

index 29a4419e8ba3e93feff187f86b381ef37f6a2ac4..4e1d9b31f60caed9f4f0960c9af550582c454c75 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 #include <linux/ata.h>
-#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 
@@ -42,6 +42,7 @@
 struct ps3disk_private {
        spinlock_t lock;                /* Request queue spinlock */
        struct request_queue *queue;
+       struct blk_mq_tag_set tag_set;
        struct gendisk *gendisk;
        unsigned int blocking_factor;
        struct request *req;
@@ -118,8 +119,8 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
        }
 }
 
-static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
-                                    struct request *req)
+static blk_status_t ps3disk_submit_request_sg(struct ps3_storage_device *dev,
+                                             struct request *req)
 {
        struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
        int write = rq_data_dir(req), res;
@@ -158,16 +159,15 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
        if (res) {
                dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
                        __LINE__, op, res);
-               __blk_end_request_all(req, BLK_STS_IOERR);
-               return 0;
+               return BLK_STS_IOERR;
        }
 
        priv->req = req;
-       return 1;
+       return BLK_STS_OK;
 }
 
-static int ps3disk_submit_flush_request(struct ps3_storage_device *dev,
-                                       struct request *req)
+static blk_status_t ps3disk_submit_flush_request(struct ps3_storage_device *dev,
+                                                struct request *req)
 {
        struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
        u64 res;
@@ -180,50 +180,45 @@ static int ps3disk_submit_flush_request(struct ps3_storage_device *dev,
        if (res) {
                dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
                        __func__, __LINE__, res);
-               __blk_end_request_all(req, BLK_STS_IOERR);
-               return 0;
+               return BLK_STS_IOERR;
        }
 
        priv->req = req;
-       return 1;
+       return BLK_STS_OK;
 }
 
-static void ps3disk_do_request(struct ps3_storage_device *dev,
-                              struct request_queue *q)
+static blk_status_t ps3disk_do_request(struct ps3_storage_device *dev,
+                                      struct request *req)
 {
-       struct request *req;
-
        dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
 
-       while ((req = blk_fetch_request(q))) {
-               switch (req_op(req)) {
-               case REQ_OP_FLUSH:
-                       if (ps3disk_submit_flush_request(dev, req))
-                               return;
-                       break;
-               case REQ_OP_READ:
-               case REQ_OP_WRITE:
-                       if (ps3disk_submit_request_sg(dev, req))
-                               return;
-                       break;
-               default:
-                       blk_dump_rq_flags(req, DEVICE_NAME " bad request");
-                       __blk_end_request_all(req, BLK_STS_IOERR);
-               }
+       switch (req_op(req)) {
+       case REQ_OP_FLUSH:
+               return ps3disk_submit_flush_request(dev, req);
+       case REQ_OP_READ:
+       case REQ_OP_WRITE:
+               return ps3disk_submit_request_sg(dev, req);
+       default:
+               blk_dump_rq_flags(req, DEVICE_NAME " bad request");
+               return BLK_STS_IOERR;
        }
 }
 
-static void ps3disk_request(struct request_queue *q)
+static blk_status_t ps3disk_queue_rq(struct blk_mq_hw_ctx *hctx,
+                                    const struct blk_mq_queue_data *bd)
 {
+       struct request_queue *q = hctx->queue;
        struct ps3_storage_device *dev = q->queuedata;
        struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
+       blk_status_t ret;
 
-       if (priv->req) {
-               dev_dbg(&dev->sbd.core, "%s:%u busy\n", __func__, __LINE__);
-               return;
-       }
+       blk_mq_start_request(bd->rq);
+
+       spin_lock_irq(&priv->lock);
+       ret = ps3disk_do_request(dev, bd->rq);
+       spin_unlock_irq(&priv->lock);
 
-       ps3disk_do_request(dev, q);
+       return ret;
 }
 
 static irqreturn_t ps3disk_interrupt(int irq, void *data)
@@ -280,11 +275,11 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
        }
 
        spin_lock(&priv->lock);
-       __blk_end_request_all(req, error);
        priv->req = NULL;
-       ps3disk_do_request(dev, priv->queue);
+       blk_mq_end_request(req, error);
        spin_unlock(&priv->lock);
 
+       blk_mq_run_hw_queues(priv->queue, true);
        return IRQ_HANDLED;
 }
 
@@ -404,6 +399,10 @@ static unsigned long ps3disk_mask;
 
 static DEFINE_MUTEX(ps3disk_mask_mutex);
 
+static const struct blk_mq_ops ps3disk_mq_ops = {
+       .queue_rq       = ps3disk_queue_rq,
+};
+
 static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 {
        struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
@@ -454,11 +453,12 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 
        ps3disk_identify(dev);
 
-       queue = blk_init_queue(ps3disk_request, &priv->lock);
-       if (!queue) {
-               dev_err(&dev->sbd.core, "%s:%u: blk_init_queue failed\n",
+       queue = blk_mq_init_sq_queue(&priv->tag_set, &ps3disk_mq_ops, 1,
+                                       BLK_MQ_F_SHOULD_MERGE);
+       if (IS_ERR(queue)) {
+               dev_err(&dev->sbd.core, "%s:%u: blk_mq_init_queue failed\n",
                        __func__, __LINE__);
-               error = -ENOMEM;
+               error = PTR_ERR(queue);
                goto fail_teardown;
        }
 
@@ -505,6 +505,7 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 
 fail_cleanup_queue:
        blk_cleanup_queue(queue);
+       blk_mq_free_tag_set(&priv->tag_set);
 fail_teardown:
        ps3stor_teardown(dev);
 fail_free_bounce:
@@ -530,6 +531,7 @@ static int ps3disk_remove(struct ps3_system_bus_device *_dev)
        mutex_unlock(&ps3disk_mask_mutex);
        del_gendisk(priv->gendisk);
        blk_cleanup_queue(priv->queue);
+       blk_mq_free_tag_set(&priv->tag_set);
        put_disk(priv->gendisk);
        dev_notice(&dev->sbd.core, "Synchronizing disk cache\n");
        ps3disk_sync_cache(dev);