diff options
author | Asai Thambi SP <asamymuthupa@micron.com> | 2016-02-25 00:21:13 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2016-03-03 11:08:44 -0500 |
commit | abb0ccd185c9e31847709b86192e6c815d1f57ad (patch) | |
tree | 8c3b372c23cd4b5d0281072eb4fd504617d325d5 | |
parent | aae4a033868c496adae86fc6f9c3e0c405bbf360 (diff) |
mtip32xx: Implement timeout handler
Added timeout handler. Replaced blk_mq_end_request() with
blk_mq_complete_request() to avoid double completion of a request.
Signed-off-by: Selvan Mani <smani@micron.com>
Signed-off-by: Rajesh Kumar Sambandam <rsambandam@micron.com>
Signed-off-by: Asai Thambi S P <asamymuthupa@micron.com>
Cc: stable@vger.kernel.org
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | drivers/block/mtip32xx/mtip32xx.c | 95 | ||||
-rw-r--r-- | drivers/block/mtip32xx/mtip32xx.h | 7 |
2 files changed, 92 insertions, 10 deletions
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index a64da08ccd3e..c8f5d8c393f7 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c | |||
@@ -233,15 +233,9 @@ static void mtip_async_complete(struct mtip_port *port, | |||
233 | "Command tag %d failed due to TFE\n", tag); | 233 | "Command tag %d failed due to TFE\n", tag); |
234 | } | 234 | } |
235 | 235 | ||
236 | /* Unmap the DMA scatter list entries */ | ||
237 | dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents, cmd->direction); | ||
238 | |||
239 | rq = mtip_rq_from_tag(dd, tag); | 236 | rq = mtip_rq_from_tag(dd, tag); |
240 | 237 | ||
241 | if (unlikely(cmd->unaligned)) | 238 | blk_mq_complete_request(rq, status); |
242 | up(&port->cmd_slot_unal); | ||
243 | |||
244 | blk_mq_end_request(rq, status ? -EIO : 0); | ||
245 | } | 239 | } |
246 | 240 | ||
247 | /* | 241 | /* |
@@ -2889,6 +2883,42 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd) | |||
2889 | return -EFAULT; | 2883 | return -EFAULT; |
2890 | } | 2884 | } |
2891 | 2885 | ||
2886 | static void mtip_softirq_done_fn(struct request *rq) | ||
2887 | { | ||
2888 | struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq); | ||
2889 | struct driver_data *dd = rq->q->queuedata; | ||
2890 | |||
2891 | /* Unmap the DMA scatter list entries */ | ||
2892 | dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents, | ||
2893 | cmd->direction); | ||
2894 | |||
2895 | if (unlikely(cmd->unaligned)) | ||
2896 | up(&dd->port->cmd_slot_unal); | ||
2897 | |||
2898 | blk_mq_end_request(rq, rq->errors); | ||
2899 | } | ||
2900 | |||
2901 | static void mtip_abort_cmd(struct request *req, void *data, | ||
2902 | bool reserved) | ||
2903 | { | ||
2904 | struct driver_data *dd = data; | ||
2905 | |||
2906 | dbg_printk(MTIP_DRV_NAME " Aborting request, tag = %d\n", req->tag); | ||
2907 | |||
2908 | clear_bit(req->tag, dd->port->cmds_to_issue); | ||
2909 | req->errors = -EIO; | ||
2910 | mtip_softirq_done_fn(req); | ||
2911 | } | ||
2912 | |||
2913 | static void mtip_queue_cmd(struct request *req, void *data, | ||
2914 | bool reserved) | ||
2915 | { | ||
2916 | struct driver_data *dd = data; | ||
2917 | |||
2918 | set_bit(req->tag, dd->port->cmds_to_issue); | ||
2919 | blk_abort_request(req); | ||
2920 | } | ||
2921 | |||
2892 | /* | 2922 | /* |
2893 | * service thread to issue queued commands | 2923 | * service thread to issue queued commands |
2894 | * | 2924 | * |
@@ -2901,7 +2931,7 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd) | |||
2901 | static int mtip_service_thread(void *data) | 2931 | static int mtip_service_thread(void *data) |
2902 | { | 2932 | { |
2903 | struct driver_data *dd = (struct driver_data *)data; | 2933 | struct driver_data *dd = (struct driver_data *)data; |
2904 | unsigned long slot, slot_start, slot_wrap; | 2934 | unsigned long slot, slot_start, slot_wrap, to; |
2905 | unsigned int num_cmd_slots = dd->slot_groups * 32; | 2935 | unsigned int num_cmd_slots = dd->slot_groups * 32; |
2906 | struct mtip_port *port = dd->port; | 2936 | struct mtip_port *port = dd->port; |
2907 | 2937 | ||
@@ -2938,6 +2968,32 @@ restart_eh: | |||
2938 | if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) | 2968 | if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) |
2939 | goto restart_eh; | 2969 | goto restart_eh; |
2940 | 2970 | ||
2971 | if (test_bit(MTIP_PF_TO_ACTIVE_BIT, &port->flags)) { | ||
2972 | to = jiffies + msecs_to_jiffies(5000); | ||
2973 | |||
2974 | do { | ||
2975 | mdelay(100); | ||
2976 | } while (atomic_read(&dd->irq_workers_active) != 0 && | ||
2977 | time_before(jiffies, to)); | ||
2978 | |||
2979 | if (atomic_read(&dd->irq_workers_active) != 0) | ||
2980 | dev_warn(&dd->pdev->dev, | ||
2981 | "Completion workers still active!"); | ||
2982 | |||
2983 | spin_lock(dd->queue->queue_lock); | ||
2984 | blk_mq_all_tag_busy_iter(*dd->tags.tags, | ||
2985 | mtip_queue_cmd, dd); | ||
2986 | spin_unlock(dd->queue->queue_lock); | ||
2987 | |||
2988 | set_bit(MTIP_PF_ISSUE_CMDS_BIT, &dd->port->flags); | ||
2989 | |||
2990 | if (mtip_device_reset(dd)) | ||
2991 | blk_mq_all_tag_busy_iter(*dd->tags.tags, | ||
2992 | mtip_abort_cmd, dd); | ||
2993 | |||
2994 | clear_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags); | ||
2995 | } | ||
2996 | |||
2941 | if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) { | 2997 | if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) { |
2942 | slot = 1; | 2998 | slot = 1; |
2943 | /* used to restrict the loop to one iteration */ | 2999 | /* used to restrict the loop to one iteration */ |
@@ -3803,11 +3859,33 @@ static int mtip_init_cmd(void *data, struct request *rq, unsigned int hctx_idx, | |||
3803 | return 0; | 3859 | return 0; |
3804 | } | 3860 | } |
3805 | 3861 | ||
3862 | static enum blk_eh_timer_return mtip_cmd_timeout(struct request *req, | ||
3863 | bool reserved) | ||
3864 | { | ||
3865 | struct driver_data *dd = req->q->queuedata; | ||
3866 | int ret = BLK_EH_RESET_TIMER; | ||
3867 | |||
3868 | if (reserved) | ||
3869 | goto exit_handler; | ||
3870 | |||
3871 | if (test_bit(req->tag, dd->port->cmds_to_issue)) | ||
3872 | goto exit_handler; | ||
3873 | |||
3874 | if (test_and_set_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags)) | ||
3875 | goto exit_handler; | ||
3876 | |||
3877 | wake_up_interruptible(&dd->port->svc_wait); | ||
3878 | exit_handler: | ||
3879 | return ret; | ||
3880 | } | ||
3881 | |||
3806 | static struct blk_mq_ops mtip_mq_ops = { | 3882 | static struct blk_mq_ops mtip_mq_ops = { |
3807 | .queue_rq = mtip_queue_rq, | 3883 | .queue_rq = mtip_queue_rq, |
3808 | .map_queue = blk_mq_map_queue, | 3884 | .map_queue = blk_mq_map_queue, |
3809 | .init_request = mtip_init_cmd, | 3885 | .init_request = mtip_init_cmd, |
3810 | .exit_request = mtip_free_cmd, | 3886 | .exit_request = mtip_free_cmd, |
3887 | .complete = mtip_softirq_done_fn, | ||
3888 | .timeout = mtip_cmd_timeout, | ||
3811 | }; | 3889 | }; |
3812 | 3890 | ||
3813 | /* | 3891 | /* |
@@ -3883,6 +3961,7 @@ static int mtip_block_initialize(struct driver_data *dd) | |||
3883 | dd->tags.numa_node = dd->numa_node; | 3961 | dd->tags.numa_node = dd->numa_node; |
3884 | dd->tags.flags = BLK_MQ_F_SHOULD_MERGE; | 3962 | dd->tags.flags = BLK_MQ_F_SHOULD_MERGE; |
3885 | dd->tags.driver_data = dd; | 3963 | dd->tags.driver_data = dd; |
3964 | dd->tags.timeout = MTIP_NCQ_CMD_TIMEOUT_MS; | ||
3886 | 3965 | ||
3887 | rv = blk_mq_alloc_tag_set(&dd->tags); | 3966 | rv = blk_mq_alloc_tag_set(&dd->tags); |
3888 | if (rv) { | 3967 | if (rv) { |
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 50af742421e2..7617888f7944 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h | |||
@@ -134,10 +134,12 @@ enum { | |||
134 | MTIP_PF_EH_ACTIVE_BIT = 1, /* error handling */ | 134 | MTIP_PF_EH_ACTIVE_BIT = 1, /* error handling */ |
135 | MTIP_PF_SE_ACTIVE_BIT = 2, /* secure erase */ | 135 | MTIP_PF_SE_ACTIVE_BIT = 2, /* secure erase */ |
136 | MTIP_PF_DM_ACTIVE_BIT = 3, /* download microcde */ | 136 | MTIP_PF_DM_ACTIVE_BIT = 3, /* download microcde */ |
137 | MTIP_PF_TO_ACTIVE_BIT = 9, /* timeout handling */ | ||
137 | MTIP_PF_PAUSE_IO = ((1 << MTIP_PF_IC_ACTIVE_BIT) | | 138 | MTIP_PF_PAUSE_IO = ((1 << MTIP_PF_IC_ACTIVE_BIT) | |
138 | (1 << MTIP_PF_EH_ACTIVE_BIT) | | 139 | (1 << MTIP_PF_EH_ACTIVE_BIT) | |
139 | (1 << MTIP_PF_SE_ACTIVE_BIT) | | 140 | (1 << MTIP_PF_SE_ACTIVE_BIT) | |
140 | (1 << MTIP_PF_DM_ACTIVE_BIT)), | 141 | (1 << MTIP_PF_DM_ACTIVE_BIT) | |
142 | (1 << MTIP_PF_TO_ACTIVE_BIT)), | ||
141 | 143 | ||
142 | MTIP_PF_SVC_THD_ACTIVE_BIT = 4, | 144 | MTIP_PF_SVC_THD_ACTIVE_BIT = 4, |
143 | MTIP_PF_ISSUE_CMDS_BIT = 5, | 145 | MTIP_PF_ISSUE_CMDS_BIT = 5, |
@@ -147,7 +149,8 @@ enum { | |||
147 | MTIP_PF_SVC_THD_WORK = ((1 << MTIP_PF_EH_ACTIVE_BIT) | | 149 | MTIP_PF_SVC_THD_WORK = ((1 << MTIP_PF_EH_ACTIVE_BIT) | |
148 | (1 << MTIP_PF_ISSUE_CMDS_BIT) | | 150 | (1 << MTIP_PF_ISSUE_CMDS_BIT) | |
149 | (1 << MTIP_PF_REBUILD_BIT) | | 151 | (1 << MTIP_PF_REBUILD_BIT) | |
150 | (1 << MTIP_PF_SVC_THD_STOP_BIT)), | 152 | (1 << MTIP_PF_SVC_THD_STOP_BIT) | |
153 | (1 << MTIP_PF_TO_ACTIVE_BIT)), | ||
151 | 154 | ||
152 | /* below are bit numbers in 'dd_flag' defined in driver_data */ | 155 | /* below are bit numbers in 'dd_flag' defined in driver_data */ |
153 | MTIP_DDF_SEC_LOCK_BIT = 0, | 156 | MTIP_DDF_SEC_LOCK_BIT = 0, |