diff options
author | Jens Axboe <axboe@kernel.dk> | 2018-10-15 11:05:59 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-10-15 22:08:24 -0400 |
commit | 804186fa95c871aba621da280284d3bc46746d50 (patch) | |
tree | 0998bf27ab51bc1008b510c20ff9b418bfb5d158 | |
parent | 77218ddf46d8d71161776a37739cd1723706ec95 (diff) |
xsysace: convert to blk-mq
Straight forward conversion, using an internal list to enable the
driver to pull requests at will.
Acked-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | drivers/block/xsysace.c | 80 |
1 files changed, 55 insertions, 25 deletions
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index c24589414c75..87ccef4bd69e 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c | |||
@@ -88,7 +88,7 @@ | |||
88 | #include <linux/kernel.h> | 88 | #include <linux/kernel.h> |
89 | #include <linux/delay.h> | 89 | #include <linux/delay.h> |
90 | #include <linux/slab.h> | 90 | #include <linux/slab.h> |
91 | #include <linux/blkdev.h> | 91 | #include <linux/blk-mq.h> |
92 | #include <linux/mutex.h> | 92 | #include <linux/mutex.h> |
93 | #include <linux/ata.h> | 93 | #include <linux/ata.h> |
94 | #include <linux/hdreg.h> | 94 | #include <linux/hdreg.h> |
@@ -209,6 +209,8 @@ struct ace_device { | |||
209 | struct device *dev; | 209 | struct device *dev; |
210 | struct request_queue *queue; | 210 | struct request_queue *queue; |
211 | struct gendisk *gd; | 211 | struct gendisk *gd; |
212 | struct blk_mq_tag_set tag_set; | ||
213 | struct list_head rq_list; | ||
212 | 214 | ||
213 | /* Inserted CF card parameters */ | 215 | /* Inserted CF card parameters */ |
214 | u16 cf_id[ATA_ID_WORDS]; | 216 | u16 cf_id[ATA_ID_WORDS]; |
@@ -462,18 +464,26 @@ static inline void ace_fsm_yieldirq(struct ace_device *ace) | |||
462 | ace->fsm_continue_flag = 0; | 464 | ace->fsm_continue_flag = 0; |
463 | } | 465 | } |
464 | 466 | ||
467 | static bool ace_has_next_request(struct request_queue *q) | ||
468 | { | ||
469 | struct ace_device *ace = q->queuedata; | ||
470 | |||
471 | return !list_empty(&ace->rq_list); | ||
472 | } | ||
473 | |||
465 | /* Get the next read/write request; ending requests that we don't handle */ | 474 | /* Get the next read/write request; ending requests that we don't handle */ |
466 | static struct request *ace_get_next_request(struct request_queue *q) | 475 | static struct request *ace_get_next_request(struct request_queue *q) |
467 | { | 476 | { |
468 | struct request *req; | 477 | struct ace_device *ace = q->queuedata; |
478 | struct request *rq; | ||
469 | 479 | ||
470 | while ((req = blk_peek_request(q)) != NULL) { | 480 | rq = list_first_entry_or_null(&ace->rq_list, struct request, queuelist); |
471 | if (!blk_rq_is_passthrough(req)) | 481 | if (rq) { |
472 | break; | 482 | list_del_init(&rq->queuelist); |
473 | blk_start_request(req); | 483 | blk_mq_start_request(rq); |
474 | __blk_end_request_all(req, BLK_STS_IOERR); | ||
475 | } | 484 | } |
476 | return req; | 485 | |
486 | return NULL; | ||
477 | } | 487 | } |
478 | 488 | ||
479 | static void ace_fsm_dostate(struct ace_device *ace) | 489 | static void ace_fsm_dostate(struct ace_device *ace) |
@@ -499,11 +509,11 @@ static void ace_fsm_dostate(struct ace_device *ace) | |||
499 | 509 | ||
500 | /* Drop all in-flight and pending requests */ | 510 | /* Drop all in-flight and pending requests */ |
501 | if (ace->req) { | 511 | if (ace->req) { |
502 | __blk_end_request_all(ace->req, BLK_STS_IOERR); | 512 | blk_mq_end_request(ace->req, BLK_STS_IOERR); |
503 | ace->req = NULL; | 513 | ace->req = NULL; |
504 | } | 514 | } |
505 | while ((req = blk_fetch_request(ace->queue)) != NULL) | 515 | while ((req = ace_get_next_request(ace->queue)) != NULL) |
506 | __blk_end_request_all(req, BLK_STS_IOERR); | 516 | blk_mq_end_request(req, BLK_STS_IOERR); |
507 | 517 | ||
508 | /* Drop back to IDLE state and notify waiters */ | 518 | /* Drop back to IDLE state and notify waiters */ |
509 | ace->fsm_state = ACE_FSM_STATE_IDLE; | 519 | ace->fsm_state = ACE_FSM_STATE_IDLE; |
@@ -517,7 +527,7 @@ static void ace_fsm_dostate(struct ace_device *ace) | |||
517 | switch (ace->fsm_state) { | 527 | switch (ace->fsm_state) { |
518 | case ACE_FSM_STATE_IDLE: | 528 | case ACE_FSM_STATE_IDLE: |
519 | /* See if there is anything to do */ | 529 | /* See if there is anything to do */ |
520 | if (ace->id_req_count || ace_get_next_request(ace->queue)) { | 530 | if (ace->id_req_count || ace_has_next_request(ace->queue)) { |
521 | ace->fsm_iter_num++; | 531 | ace->fsm_iter_num++; |
522 | ace->fsm_state = ACE_FSM_STATE_REQ_LOCK; | 532 | ace->fsm_state = ACE_FSM_STATE_REQ_LOCK; |
523 | mod_timer(&ace->stall_timer, jiffies + HZ); | 533 | mod_timer(&ace->stall_timer, jiffies + HZ); |
@@ -651,7 +661,6 @@ static void ace_fsm_dostate(struct ace_device *ace) | |||
651 | ace->fsm_state = ACE_FSM_STATE_IDLE; | 661 | ace->fsm_state = ACE_FSM_STATE_IDLE; |
652 | break; | 662 | break; |
653 | } | 663 | } |
654 | blk_start_request(req); | ||
655 | 664 | ||
656 | /* Okay, it's a data request, set it up for transfer */ | 665 | /* Okay, it's a data request, set it up for transfer */ |
657 | dev_dbg(ace->dev, | 666 | dev_dbg(ace->dev, |
@@ -728,7 +737,8 @@ static void ace_fsm_dostate(struct ace_device *ace) | |||
728 | } | 737 | } |
729 | 738 | ||
730 | /* bio finished; is there another one? */ | 739 | /* bio finished; is there another one? */ |
731 | if (__blk_end_request_cur(ace->req, BLK_STS_OK)) { | 740 | if (blk_update_request(ace->req, BLK_STS_OK, |
741 | blk_rq_cur_bytes(ace->req))) { | ||
732 | /* dev_dbg(ace->dev, "next block; h=%u c=%u\n", | 742 | /* dev_dbg(ace->dev, "next block; h=%u c=%u\n", |
733 | * blk_rq_sectors(ace->req), | 743 | * blk_rq_sectors(ace->req), |
734 | * blk_rq_cur_sectors(ace->req)); | 744 | * blk_rq_cur_sectors(ace->req)); |
@@ -854,17 +864,23 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id) | |||
854 | /* --------------------------------------------------------------------- | 864 | /* --------------------------------------------------------------------- |
855 | * Block ops | 865 | * Block ops |
856 | */ | 866 | */ |
857 | static void ace_request(struct request_queue * q) | 867 | static blk_status_t ace_queue_rq(struct blk_mq_hw_ctx *hctx, |
868 | const struct blk_mq_queue_data *bd) | ||
858 | { | 869 | { |
859 | struct request *req; | 870 | struct ace_device *ace = hctx->queue->queuedata; |
860 | struct ace_device *ace; | 871 | struct request *req = bd->rq; |
861 | |||
862 | req = ace_get_next_request(q); | ||
863 | 872 | ||
864 | if (req) { | 873 | if (blk_rq_is_passthrough(req)) { |
865 | ace = req->rq_disk->private_data; | 874 | blk_mq_start_request(req); |
866 | tasklet_schedule(&ace->fsm_tasklet); | 875 | return BLK_STS_IOERR; |
867 | } | 876 | } |
877 | |||
878 | spin_lock_irq(&ace->lock); | ||
879 | list_add_tail(&req->queuelist, &ace->rq_list); | ||
880 | spin_unlock_irq(&ace->lock); | ||
881 | |||
882 | tasklet_schedule(&ace->fsm_tasklet); | ||
883 | return BLK_STS_OK; | ||
868 | } | 884 | } |
869 | 885 | ||
870 | static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing) | 886 | static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing) |
@@ -957,6 +973,10 @@ static const struct block_device_operations ace_fops = { | |||
957 | .getgeo = ace_getgeo, | 973 | .getgeo = ace_getgeo, |
958 | }; | 974 | }; |
959 | 975 | ||
976 | static const struct blk_mq_ops ace_mq_ops = { | ||
977 | .queue_rq = ace_queue_rq, | ||
978 | }; | ||
979 | |||
960 | /* -------------------------------------------------------------------- | 980 | /* -------------------------------------------------------------------- |
961 | * SystemACE device setup/teardown code | 981 | * SystemACE device setup/teardown code |
962 | */ | 982 | */ |
@@ -972,6 +992,7 @@ static int ace_setup(struct ace_device *ace) | |||
972 | 992 | ||
973 | spin_lock_init(&ace->lock); | 993 | spin_lock_init(&ace->lock); |
974 | init_completion(&ace->id_completion); | 994 | init_completion(&ace->id_completion); |
995 | INIT_LIST_HEAD(&ace->rq_list); | ||
975 | 996 | ||
976 | /* | 997 | /* |
977 | * Map the device | 998 | * Map the device |
@@ -989,9 +1010,15 @@ static int ace_setup(struct ace_device *ace) | |||
989 | /* | 1010 | /* |
990 | * Initialize the request queue | 1011 | * Initialize the request queue |
991 | */ | 1012 | */ |
992 | ace->queue = blk_init_queue(ace_request, &ace->lock); | 1013 | ace->queue = blk_mq_init_sq_queue(&ace->tag_set, &ace_mq_ops, 2, |
993 | if (ace->queue == NULL) | 1014 | BLK_MQ_F_SHOULD_MERGE); |
1015 | if (IS_ERR(ace->queue)) { | ||
1016 | rc = PTR_ERR(ace->queue); | ||
1017 | ace->queue = NULL; | ||
994 | goto err_blk_initq; | 1018 | goto err_blk_initq; |
1019 | } | ||
1020 | ace->queue->queuedata = ace; | ||
1021 | |||
995 | blk_queue_logical_block_size(ace->queue, 512); | 1022 | blk_queue_logical_block_size(ace->queue, 512); |
996 | blk_queue_bounce_limit(ace->queue, BLK_BOUNCE_HIGH); | 1023 | blk_queue_bounce_limit(ace->queue, BLK_BOUNCE_HIGH); |
997 | 1024 | ||
@@ -1066,6 +1093,7 @@ err_read: | |||
1066 | put_disk(ace->gd); | 1093 | put_disk(ace->gd); |
1067 | err_alloc_disk: | 1094 | err_alloc_disk: |
1068 | blk_cleanup_queue(ace->queue); | 1095 | blk_cleanup_queue(ace->queue); |
1096 | blk_mq_free_tag_set(&ace->tag_set); | ||
1069 | err_blk_initq: | 1097 | err_blk_initq: |
1070 | iounmap(ace->baseaddr); | 1098 | iounmap(ace->baseaddr); |
1071 | err_ioremap: | 1099 | err_ioremap: |
@@ -1081,8 +1109,10 @@ static void ace_teardown(struct ace_device *ace) | |||
1081 | put_disk(ace->gd); | 1109 | put_disk(ace->gd); |
1082 | } | 1110 | } |
1083 | 1111 | ||
1084 | if (ace->queue) | 1112 | if (ace->queue) { |
1085 | blk_cleanup_queue(ace->queue); | 1113 | blk_cleanup_queue(ace->queue); |
1114 | blk_mq_free_tag_set(&ace->tag_set); | ||
1115 | } | ||
1086 | 1116 | ||
1087 | tasklet_kill(&ace->fsm_tasklet); | 1117 | tasklet_kill(&ace->fsm_tasklet); |
1088 | 1118 | ||