Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NVMe: Abort timed out commands

Send nvme abort command to io requests that have timed out on an
initialized device. If the command is not returned after another timeout,
schedule the controller for reset.

Signed-off-by: Keith Busch <keith.busch@intel.com>
[fix endianness issues]
Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>

authored by

Keith Busch and committed by
Matthew Wilcox
c30341dc d4b4ff8e

+79 -1
+67 -1
drivers/block/nvme-core.c
··· 83 83 u16 sq_head; 84 84 u16 sq_tail; 85 85 u16 cq_head; 86 + u16 qid; 86 87 u8 cq_phase; 87 88 u8 cqe_seen; 88 89 u8 q_suspended; ··· 101 100 BUILD_BUG_ON(sizeof(struct nvme_delete_queue) != 64); 102 101 BUILD_BUG_ON(sizeof(struct nvme_features) != 64); 103 102 BUILD_BUG_ON(sizeof(struct nvme_format_cmd) != 64); 103 + BUILD_BUG_ON(sizeof(struct nvme_abort_cmd) != 64); 104 104 BUILD_BUG_ON(sizeof(struct nvme_command) != 64); 105 105 BUILD_BUG_ON(sizeof(struct nvme_id_ctrl) != 4096); 106 106 BUILD_BUG_ON(sizeof(struct nvme_id_ns) != 4096); ··· 116 114 nvme_completion_fn fn; 117 115 void *ctx; 118 116 unsigned long timeout; 117 + int aborted; 119 118 }; 120 119 121 120 static struct nvme_cmd_info *nvme_cmd_info(struct nvme_queue *nvmeq) ··· 160 157 info[cmdid].fn = handler; 161 158 info[cmdid].ctx = ctx; 162 159 info[cmdid].timeout = jiffies + timeout; 160 + info[cmdid].aborted = 0; 163 161 return cmdid; 164 162 } 165 163 ··· 179 175 #define CMD_CTX_COMPLETED (0x310 + CMD_CTX_BASE) 180 176 #define CMD_CTX_INVALID (0x314 + CMD_CTX_BASE) 181 177 #define CMD_CTX_FLUSH (0x318 + CMD_CTX_BASE) 178 + #define CMD_CTX_ABORT (0x31C + CMD_CTX_BASE) 182 179 183 180 static void special_completion(struct nvme_dev *dev, void *ctx, 184 181 struct nvme_completion *cqe) ··· 188 183 return; 189 184 if (ctx == CMD_CTX_FLUSH) 190 185 return; 186 + if (ctx == CMD_CTX_ABORT) { 187 + ++dev->abort_limit; 188 + return; 189 + } 191 190 if (ctx == CMD_CTX_COMPLETED) { 192 191 dev_warn(&dev->pci_dev->dev, 193 192 "completed id %d twice on queue %d\n", ··· 1014 1005 } 1015 1006 1016 1007 /** 1008 + * nvme_abort_cmd - Attempt aborting a command 1009 + * @cmdid: Command id of a timed out IO 1010 + * @queue: The queue with timed out IO 1011 + * 1012 + * Schedule controller reset if the command was already aborted once before and 1013 + * still hasn't been returned to the driver, or if this is the admin queue. 1014 + */ 1015 + static void nvme_abort_cmd(int cmdid, struct nvme_queue *nvmeq) 1016 + { 1017 + int a_cmdid; 1018 + struct nvme_command cmd; 1019 + struct nvme_dev *dev = nvmeq->dev; 1020 + struct nvme_cmd_info *info = nvme_cmd_info(nvmeq); 1021 + 1022 + if (!nvmeq->qid || info[cmdid].aborted) { 1023 + if (work_busy(&dev->reset_work)) 1024 + return; 1025 + list_del_init(&dev->node); 1026 + dev_warn(&dev->pci_dev->dev, 1027 + "I/O %d QID %d timeout, reset controller\n", cmdid, 1028 + nvmeq->qid); 1029 + INIT_WORK(&dev->reset_work, nvme_reset_failed_dev); 1030 + queue_work(nvme_workq, &dev->reset_work); 1031 + return; 1032 + } 1033 + 1034 + if (!dev->abort_limit) 1035 + return; 1036 + 1037 + a_cmdid = alloc_cmdid(dev->queues[0], CMD_CTX_ABORT, special_completion, 1038 + ADMIN_TIMEOUT); 1039 + if (a_cmdid < 0) 1040 + return; 1041 + 1042 + memset(&cmd, 0, sizeof(cmd)); 1043 + cmd.abort.opcode = nvme_admin_abort_cmd; 1044 + cmd.abort.cid = cmdid; 1045 + cmd.abort.sqid = cpu_to_le16(nvmeq->qid); 1046 + cmd.abort.command_id = a_cmdid; 1047 + 1048 + --dev->abort_limit; 1049 + info[cmdid].aborted = 1; 1050 + info[cmdid].timeout = jiffies + ADMIN_TIMEOUT; 1051 + 1052 + dev_warn(nvmeq->q_dmadev, "Aborting I/O %d QID %d\n", cmdid, 1053 + nvmeq->qid); 1054 + nvme_submit_cmd(dev->queues[0], &cmd); 1055 + } 1056 + 1057 + /** 1017 1058 * nvme_cancel_ios - Cancel outstanding I/Os 1018 1059 * @queue: The queue to cancel I/Os on 1019 1060 * @timeout: True to only cancel I/Os which have timed out ··· 1086 1027 continue; 1087 1028 if (info[cmdid].ctx == CMD_CTX_CANCELLED) 1088 1029 continue; 1089 - dev_warn(nvmeq->q_dmadev, "Cancelling I/O %d\n", cmdid); 1030 + if (timeout && nvmeq->dev->initialized) { 1031 + nvme_abort_cmd(cmdid, nvmeq); 1032 + continue; 1033 + } 1034 + dev_warn(nvmeq->q_dmadev, "Cancelling I/O %d QID %d\n", cmdid, 1035 + nvmeq->qid); 1090 1036 ctx = cancel_cmdid(nvmeq, cmdid, &fn); 1091 1037 fn(nvmeq->dev, ctx, &cqe); 1092 1038 } ··· 1183 1119 nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride]; 1184 1120 nvmeq->q_depth = depth; 1185 1121 nvmeq->cq_vector = vector; 1122 + nvmeq->qid = qid; 1186 1123 nvmeq->q_suspended = 1; 1187 1124 dev->queue_count++; 1188 1125 ··· 1994 1929 ctrl = mem; 1995 1930 nn = le32_to_cpup(&ctrl->nn); 1996 1931 dev->oncs = le16_to_cpup(&ctrl->oncs); 1932 + dev->abort_limit = ctrl->acl + 1; 1997 1933 memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn)); 1998 1934 memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn)); 1999 1935 memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
+1
include/linux/nvme.h
··· 95 95 u32 max_hw_sectors; 96 96 u32 stripe_size; 97 97 u16 oncs; 98 + u16 abort_limit; 98 99 u8 initialized; 99 100 }; 100 101
+11
include/uapi/linux/nvme.h
··· 350 350 __u32 rsvd11[5]; 351 351 }; 352 352 353 + struct nvme_abort_cmd { 354 + __u8 opcode; 355 + __u8 flags; 356 + __u16 command_id; 357 + __u32 rsvd1[9]; 358 + __le16 sqid; 359 + __u16 cid; 360 + __u32 rsvd11[5]; 361 + }; 362 + 353 363 struct nvme_download_firmware { 354 364 __u8 opcode; 355 365 __u8 flags; ··· 394 384 struct nvme_download_firmware dlfw; 395 385 struct nvme_format_cmd format; 396 386 struct nvme_dsm_cmd dsm; 387 + struct nvme_abort_cmd abort; 397 388 }; 398 389 }; 399 390