aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-11-26 03:08:36 -0500
committerJens Axboe <axboe@fb.com>2015-12-01 12:59:38 -0500
commit21d34711e1b5970acfb22bddf1fefbfbd7e0123b (patch)
tree3b5c0d963a5a0f0bd5dc3382a9c1fb1e31ae9c0c
parent71bd150c71072014d98bff6dc2db3229306ece35 (diff)
nvme: split command submission helpers out of pci.c
Create a new core.c and start by adding the command submission helpers to it, which are already abstracted away from the actual hardware queues by the block layer. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--drivers/nvme/host/Makefile2
-rw-r--r--drivers/nvme/host/core.c173
-rw-r--r--drivers/nvme/host/nvme.h3
-rw-r--r--drivers/nvme/host/pci.c155
4 files changed, 178 insertions, 155 deletions
diff --git a/drivers/nvme/host/Makefile b/drivers/nvme/host/Makefile
index 219dc206fa5f..3e26dc921c38 100644
--- a/drivers/nvme/host/Makefile
+++ b/drivers/nvme/host/Makefile
@@ -1,4 +1,4 @@
1 1
2obj-$(CONFIG_BLK_DEV_NVME) += nvme.o 2obj-$(CONFIG_BLK_DEV_NVME) += nvme.o
3 3
4nvme-y += pci.o scsi.o lightnvm.o 4nvme-y += core.o pci.o scsi.o lightnvm.o
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
new file mode 100644
index 000000000000..ce938a428928
--- /dev/null
+++ b/drivers/nvme/host/core.c
@@ -0,0 +1,173 @@
1/*
2 * NVM Express device driver
3 * Copyright (c) 2011-2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/blkdev.h>
16#include <linux/blk-mq.h>
17#include <linux/errno.h>
18#include <linux/kernel.h>
19#include <linux/slab.h>
20#include <linux/types.h>
21
22#include "nvme.h"
23
24/*
25 * Returns 0 on success. If the result is negative, it's a Linux error code;
26 * if the result is positive, it's an NVM Express status code
27 */
28int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
29 void *buffer, void __user *ubuffer, unsigned bufflen,
30 u32 *result, unsigned timeout)
31{
32 bool write = cmd->common.opcode & 1;
33 struct bio *bio = NULL;
34 struct request *req;
35 int ret;
36
37 req = blk_mq_alloc_request(q, write, 0);
38 if (IS_ERR(req))
39 return PTR_ERR(req);
40
41 req->cmd_type = REQ_TYPE_DRV_PRIV;
42 req->cmd_flags |= REQ_FAILFAST_DRIVER;
43 req->__data_len = 0;
44 req->__sector = (sector_t) -1;
45 req->bio = req->biotail = NULL;
46
47 req->timeout = timeout ? timeout : ADMIN_TIMEOUT;
48
49 req->cmd = (unsigned char *)cmd;
50 req->cmd_len = sizeof(struct nvme_command);
51 req->special = (void *)0;
52
53 if (buffer && bufflen) {
54 ret = blk_rq_map_kern(q, req, buffer, bufflen, GFP_KERNEL);
55 if (ret)
56 goto out;
57 } else if (ubuffer && bufflen) {
58 ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen,
59 GFP_KERNEL);
60 if (ret)
61 goto out;
62 bio = req->bio;
63 }
64
65 blk_execute_rq(req->q, NULL, req, 0);
66 if (bio)
67 blk_rq_unmap_user(bio);
68 if (result)
69 *result = (u32)(uintptr_t)req->special;
70 ret = req->errors;
71 out:
72 blk_mq_free_request(req);
73 return ret;
74}
75
76int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
77 void *buffer, unsigned bufflen)
78{
79 return __nvme_submit_sync_cmd(q, cmd, buffer, NULL, bufflen, NULL, 0);
80}
81
82int nvme_identify_ctrl(struct nvme_dev *dev, struct nvme_id_ctrl **id)
83{
84 struct nvme_command c = { };
85 int error;
86
87 /* gcc-4.4.4 (at least) has issues with initializers and anon unions */
88 c.identify.opcode = nvme_admin_identify;
89 c.identify.cns = cpu_to_le32(1);
90
91 *id = kmalloc(sizeof(struct nvme_id_ctrl), GFP_KERNEL);
92 if (!*id)
93 return -ENOMEM;
94
95 error = nvme_submit_sync_cmd(dev->admin_q, &c, *id,
96 sizeof(struct nvme_id_ctrl));
97 if (error)
98 kfree(*id);
99 return error;
100}
101
102int nvme_identify_ns(struct nvme_dev *dev, unsigned nsid,
103 struct nvme_id_ns **id)
104{
105 struct nvme_command c = { };
106 int error;
107
108 /* gcc-4.4.4 (at least) has issues with initializers and anon unions */
109 c.identify.opcode = nvme_admin_identify,
110 c.identify.nsid = cpu_to_le32(nsid),
111
112 *id = kmalloc(sizeof(struct nvme_id_ns), GFP_KERNEL);
113 if (!*id)
114 return -ENOMEM;
115
116 error = nvme_submit_sync_cmd(dev->admin_q, &c, *id,
117 sizeof(struct nvme_id_ns));
118 if (error)
119 kfree(*id);
120 return error;
121}
122
123int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
124 dma_addr_t dma_addr, u32 *result)
125{
126 struct nvme_command c;
127
128 memset(&c, 0, sizeof(c));
129 c.features.opcode = nvme_admin_get_features;
130 c.features.nsid = cpu_to_le32(nsid);
131 c.features.prp1 = cpu_to_le64(dma_addr);
132 c.features.fid = cpu_to_le32(fid);
133
134 return __nvme_submit_sync_cmd(dev->admin_q, &c, NULL, NULL, 0,
135 result, 0);
136}
137
138int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
139 dma_addr_t dma_addr, u32 *result)
140{
141 struct nvme_command c;
142
143 memset(&c, 0, sizeof(c));
144 c.features.opcode = nvme_admin_set_features;
145 c.features.prp1 = cpu_to_le64(dma_addr);
146 c.features.fid = cpu_to_le32(fid);
147 c.features.dword11 = cpu_to_le32(dword11);
148
149 return __nvme_submit_sync_cmd(dev->admin_q, &c, NULL, NULL, 0,
150 result, 0);
151}
152
153int nvme_get_log_page(struct nvme_dev *dev, struct nvme_smart_log **log)
154{
155 struct nvme_command c = { };
156 int error;
157
158 c.common.opcode = nvme_admin_get_log_page,
159 c.common.nsid = cpu_to_le32(0xFFFFFFFF),
160 c.common.cdw10[0] = cpu_to_le32(
161 (((sizeof(struct nvme_smart_log) / 4) - 1) << 16) |
162 NVME_LOG_SMART),
163
164 *log = kmalloc(sizeof(struct nvme_smart_log), GFP_KERNEL);
165 if (!*log)
166 return -ENOMEM;
167
168 error = nvme_submit_sync_cmd(dev->admin_q, &c, *log,
169 sizeof(struct nvme_smart_log));
170 if (error)
171 kfree(*log);
172 return error;
173}
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 2cead2c98163..a53977cc9fc2 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -22,6 +22,9 @@
22extern unsigned char nvme_io_timeout; 22extern unsigned char nvme_io_timeout;
23#define NVME_IO_TIMEOUT (nvme_io_timeout * HZ) 23#define NVME_IO_TIMEOUT (nvme_io_timeout * HZ)
24 24
25extern unsigned char admin_timeout;
26#define ADMIN_TIMEOUT (admin_timeout * HZ)
27
25enum { 28enum {
26 NVME_NS_LBA = 0, 29 NVME_NS_LBA = 0,
27 NVME_NS_LIGHTNVM = 1, 30 NVME_NS_LIGHTNVM = 1,
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 0f24d3c531c0..996356261c6b 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -52,10 +52,9 @@
52#define NVME_AQ_DEPTH 256 52#define NVME_AQ_DEPTH 256
53#define SQ_SIZE(depth) (depth * sizeof(struct nvme_command)) 53#define SQ_SIZE(depth) (depth * sizeof(struct nvme_command))
54#define CQ_SIZE(depth) (depth * sizeof(struct nvme_completion)) 54#define CQ_SIZE(depth) (depth * sizeof(struct nvme_completion))
55#define ADMIN_TIMEOUT (admin_timeout * HZ)
56#define SHUTDOWN_TIMEOUT (shutdown_timeout * HZ) 55#define SHUTDOWN_TIMEOUT (shutdown_timeout * HZ)
57 56
58static unsigned char admin_timeout = 60; 57unsigned char admin_timeout = 60;
59module_param(admin_timeout, byte, 0644); 58module_param(admin_timeout, byte, 0644);
60MODULE_PARM_DESC(admin_timeout, "timeout in seconds for admin commands"); 59MODULE_PARM_DESC(admin_timeout, "timeout in seconds for admin commands");
61 60
@@ -1045,65 +1044,6 @@ static int nvme_poll(struct blk_mq_hw_ctx *hctx, unsigned int tag)
1045 return 0; 1044 return 0;
1046} 1045}
1047 1046
1048/*
1049 * Returns 0 on success. If the result is negative, it's a Linux error code;
1050 * if the result is positive, it's an NVM Express status code
1051 */
1052int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
1053 void *buffer, void __user *ubuffer, unsigned bufflen,
1054 u32 *result, unsigned timeout)
1055{
1056 bool write = cmd->common.opcode & 1;
1057 struct bio *bio = NULL;
1058 struct request *req;
1059 int ret;
1060
1061 req = blk_mq_alloc_request(q, write, 0);
1062 if (IS_ERR(req))
1063 return PTR_ERR(req);
1064
1065 req->cmd_type = REQ_TYPE_DRV_PRIV;
1066 req->cmd_flags |= REQ_FAILFAST_DRIVER;
1067 req->__data_len = 0;
1068 req->__sector = (sector_t) -1;
1069 req->bio = req->biotail = NULL;
1070
1071 req->timeout = timeout ? timeout : ADMIN_TIMEOUT;
1072
1073 req->cmd = (unsigned char *)cmd;
1074 req->cmd_len = sizeof(struct nvme_command);
1075 req->special = (void *)0;
1076
1077 if (buffer && bufflen) {
1078 ret = blk_rq_map_kern(q, req, buffer, bufflen,
1079 __GFP_DIRECT_RECLAIM);
1080 if (ret)
1081 goto out;
1082 } else if (ubuffer && bufflen) {
1083 ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen,
1084 __GFP_DIRECT_RECLAIM);
1085 if (ret)
1086 goto out;
1087 bio = req->bio;
1088 }
1089
1090 blk_execute_rq(req->q, NULL, req, 0);
1091 if (bio)
1092 blk_rq_unmap_user(bio);
1093 if (result)
1094 *result = (u32)(uintptr_t)req->special;
1095 ret = req->errors;
1096 out:
1097 blk_mq_free_request(req);
1098 return ret;
1099}
1100
1101int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
1102 void *buffer, unsigned bufflen)
1103{
1104 return __nvme_submit_sync_cmd(q, cmd, buffer, NULL, bufflen, NULL, 0);
1105}
1106
1107static int nvme_submit_async_admin_req(struct nvme_dev *dev) 1047static int nvme_submit_async_admin_req(struct nvme_dev *dev)
1108{ 1048{
1109 struct nvme_queue *nvmeq = dev->queues[0]; 1049 struct nvme_queue *nvmeq = dev->queues[0];
@@ -1216,99 +1156,6 @@ static int adapter_delete_sq(struct nvme_dev *dev, u16 sqid)
1216 return adapter_delete_queue(dev, nvme_admin_delete_sq, sqid); 1156 return adapter_delete_queue(dev, nvme_admin_delete_sq, sqid);
1217} 1157}
1218 1158
1219int nvme_identify_ctrl(struct nvme_dev *dev, struct nvme_id_ctrl **id)
1220{
1221 struct nvme_command c = { };
1222 int error;
1223
1224 /* gcc-4.4.4 (at least) has issues with initializers and anon unions */
1225 c.identify.opcode = nvme_admin_identify;
1226 c.identify.cns = cpu_to_le32(1);
1227
1228 *id = kmalloc(sizeof(struct nvme_id_ctrl), GFP_KERNEL);
1229 if (!*id)
1230 return -ENOMEM;
1231
1232 error = nvme_submit_sync_cmd(dev->admin_q, &c, *id,
1233 sizeof(struct nvme_id_ctrl));
1234 if (error)
1235 kfree(*id);
1236 return error;
1237}
1238
1239int nvme_identify_ns(struct nvme_dev *dev, unsigned nsid,
1240 struct nvme_id_ns **id)
1241{
1242 struct nvme_command c = { };
1243 int error;
1244
1245 /* gcc-4.4.4 (at least) has issues with initializers and anon unions */
1246 c.identify.opcode = nvme_admin_identify,
1247 c.identify.nsid = cpu_to_le32(nsid),
1248
1249 *id = kmalloc(sizeof(struct nvme_id_ns), GFP_KERNEL);
1250 if (!*id)
1251 return -ENOMEM;
1252
1253 error = nvme_submit_sync_cmd(dev->admin_q, &c, *id,
1254 sizeof(struct nvme_id_ns));
1255 if (error)
1256 kfree(*id);
1257 return error;
1258}
1259
1260int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
1261 dma_addr_t dma_addr, u32 *result)
1262{
1263 struct nvme_command c;
1264
1265 memset(&c, 0, sizeof(c));
1266 c.features.opcode = nvme_admin_get_features;
1267 c.features.nsid = cpu_to_le32(nsid);
1268 c.features.prp1 = cpu_to_le64(dma_addr);
1269 c.features.fid = cpu_to_le32(fid);
1270
1271 return __nvme_submit_sync_cmd(dev->admin_q, &c, NULL, NULL, 0,
1272 result, 0);
1273}
1274
1275int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
1276 dma_addr_t dma_addr, u32 *result)
1277{
1278 struct nvme_command c;
1279
1280 memset(&c, 0, sizeof(c));
1281 c.features.opcode = nvme_admin_set_features;
1282 c.features.prp1 = cpu_to_le64(dma_addr);
1283 c.features.fid = cpu_to_le32(fid);
1284 c.features.dword11 = cpu_to_le32(dword11);
1285
1286 return __nvme_submit_sync_cmd(dev->admin_q, &c, NULL, NULL, 0,
1287 result, 0);
1288}
1289
1290int nvme_get_log_page(struct nvme_dev *dev, struct nvme_smart_log **log)
1291{
1292 struct nvme_command c = { };
1293 int error;
1294
1295 c.common.opcode = nvme_admin_get_log_page,
1296 c.common.nsid = cpu_to_le32(0xFFFFFFFF),
1297 c.common.cdw10[0] = cpu_to_le32(
1298 (((sizeof(struct nvme_smart_log) / 4) - 1) << 16) |
1299 NVME_LOG_SMART),
1300
1301 *log = kmalloc(sizeof(struct nvme_smart_log), GFP_KERNEL);
1302 if (!*log)
1303 return -ENOMEM;
1304
1305 error = nvme_submit_sync_cmd(dev->admin_q, &c, *log,
1306 sizeof(struct nvme_smart_log));
1307 if (error)
1308 kfree(*log);
1309 return error;
1310}
1311
1312/** 1159/**
1313 * nvme_abort_req - Attempt aborting a request 1160 * nvme_abort_req - Attempt aborting a request
1314 * 1161 *