aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/nvme/host/core.c6
-rw-r--r--drivers/nvme/host/fc.c121
-rw-r--r--drivers/nvme/host/pci.c6
-rw-r--r--drivers/nvme/target/fc.c101
-rw-r--r--include/linux/nvme-fc.h19
-rw-r--r--include/linux/nvme.h2
6 files changed, 145 insertions, 110 deletions
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 3b77cfe5aa1e..c49f1f8b2e57 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1995,6 +1995,9 @@ static ssize_t wwid_show(struct device *dev, struct device_attribute *attr,
1995 int serial_len = sizeof(ctrl->serial); 1995 int serial_len = sizeof(ctrl->serial);
1996 int model_len = sizeof(ctrl->model); 1996 int model_len = sizeof(ctrl->model);
1997 1997
1998 if (!uuid_is_null(&ns->uuid))
1999 return sprintf(buf, "uuid.%pU\n", &ns->uuid);
2000
1998 if (memchr_inv(ns->nguid, 0, sizeof(ns->nguid))) 2001 if (memchr_inv(ns->nguid, 0, sizeof(ns->nguid)))
1999 return sprintf(buf, "eui.%16phN\n", ns->nguid); 2002 return sprintf(buf, "eui.%16phN\n", ns->nguid);
2000 2003
@@ -2709,7 +2712,8 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl)
2709 mutex_lock(&ctrl->namespaces_mutex); 2712 mutex_lock(&ctrl->namespaces_mutex);
2710 2713
2711 /* Forcibly unquiesce queues to avoid blocking dispatch */ 2714 /* Forcibly unquiesce queues to avoid blocking dispatch */
2712 blk_mq_unquiesce_queue(ctrl->admin_q); 2715 if (ctrl->admin_q)
2716 blk_mq_unquiesce_queue(ctrl->admin_q);
2713 2717
2714 list_for_each_entry(ns, &ctrl->namespaces, list) { 2718 list_for_each_entry(ns, &ctrl->namespaces, list) {
2715 /* 2719 /*
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index d666ada39a9b..5c2a08ef08ba 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -1888,7 +1888,7 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
1888 * the target device is present 1888 * the target device is present
1889 */ 1889 */
1890 if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE) 1890 if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE)
1891 return BLK_STS_IOERR; 1891 goto busy;
1892 1892
1893 if (!nvme_fc_ctrl_get(ctrl)) 1893 if (!nvme_fc_ctrl_get(ctrl))
1894 return BLK_STS_IOERR; 1894 return BLK_STS_IOERR;
@@ -1958,22 +1958,25 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
1958 queue->lldd_handle, &op->fcp_req); 1958 queue->lldd_handle, &op->fcp_req);
1959 1959
1960 if (ret) { 1960 if (ret) {
1961 if (op->rq) /* normal request */ 1961 if (!(op->flags & FCOP_FLAGS_AEN))
1962 nvme_fc_unmap_data(ctrl, op->rq, op); 1962 nvme_fc_unmap_data(ctrl, op->rq, op);
1963 /* else - aen. no cleanup needed */
1964 1963
1965 nvme_fc_ctrl_put(ctrl); 1964 nvme_fc_ctrl_put(ctrl);
1966 1965
1967 if (ret != -EBUSY) 1966 if (ctrl->rport->remoteport.port_state == FC_OBJSTATE_ONLINE &&
1967 ret != -EBUSY)
1968 return BLK_STS_IOERR; 1968 return BLK_STS_IOERR;
1969 1969
1970 if (op->rq) 1970 goto busy;
1971 blk_mq_delay_run_hw_queue(queue->hctx, NVMEFC_QUEUE_DELAY);
1972
1973 return BLK_STS_RESOURCE;
1974 } 1971 }
1975 1972
1976 return BLK_STS_OK; 1973 return BLK_STS_OK;
1974
1975busy:
1976 if (!(op->flags & FCOP_FLAGS_AEN) && queue->hctx)
1977 blk_mq_delay_run_hw_queue(queue->hctx, NVMEFC_QUEUE_DELAY);
1978
1979 return BLK_STS_RESOURCE;
1977} 1980}
1978 1981
1979static blk_status_t 1982static blk_status_t
@@ -2802,66 +2805,70 @@ out_fail:
2802 return ERR_PTR(ret); 2805 return ERR_PTR(ret);
2803} 2806}
2804 2807
2805enum {
2806 FCT_TRADDR_ERR = 0,
2807 FCT_TRADDR_WWNN = 1 << 0,
2808 FCT_TRADDR_WWPN = 1 << 1,
2809};
2810 2808
2811struct nvmet_fc_traddr { 2809struct nvmet_fc_traddr {
2812 u64 nn; 2810 u64 nn;
2813 u64 pn; 2811 u64 pn;
2814}; 2812};
2815 2813
2816static const match_table_t traddr_opt_tokens = {
2817 { FCT_TRADDR_WWNN, "nn-%s" },
2818 { FCT_TRADDR_WWPN, "pn-%s" },
2819 { FCT_TRADDR_ERR, NULL }
2820};
2821
2822static int 2814static int
2823nvme_fc_parse_address(struct nvmet_fc_traddr *traddr, char *buf) 2815__nvme_fc_parse_u64(substring_t *sstr, u64 *val)
2824{ 2816{
2825 substring_t args[MAX_OPT_ARGS];
2826 char *options, *o, *p;
2827 int token, ret = 0;
2828 u64 token64; 2817 u64 token64;
2829 2818
2830 options = o = kstrdup(buf, GFP_KERNEL); 2819 if (match_u64(sstr, &token64))
2831 if (!options) 2820 return -EINVAL;
2832 return -ENOMEM; 2821 *val = token64;
2833 2822
2834 while ((p = strsep(&o, ":\n")) != NULL) { 2823 return 0;
2835 if (!*p) 2824}
2836 continue;
2837 2825
2838 token = match_token(p, traddr_opt_tokens, args); 2826/*
2839 switch (token) { 2827 * This routine validates and extracts the WWN's from the TRADDR string.
2840 case FCT_TRADDR_WWNN: 2828 * As kernel parsers need the 0x to determine number base, universally
2841 if (match_u64(args, &token64)) { 2829 * build string to parse with 0x prefix before parsing name strings.
2842 ret = -EINVAL; 2830 */
2843 goto out; 2831static int
2844 } 2832nvme_fc_parse_traddr(struct nvmet_fc_traddr *traddr, char *buf, size_t blen)
2845 traddr->nn = token64; 2833{
2846 break; 2834 char name[2 + NVME_FC_TRADDR_HEXNAMELEN + 1];
2847 case FCT_TRADDR_WWPN: 2835 substring_t wwn = { name, &name[sizeof(name)-1] };
2848 if (match_u64(args, &token64)) { 2836 int nnoffset, pnoffset;
2849 ret = -EINVAL; 2837
2850 goto out; 2838 /* validate it string one of the 2 allowed formats */
2851 } 2839 if (strnlen(buf, blen) == NVME_FC_TRADDR_MAXLENGTH &&
2852 traddr->pn = token64; 2840 !strncmp(buf, "nn-0x", NVME_FC_TRADDR_OXNNLEN) &&
2853 break; 2841 !strncmp(&buf[NVME_FC_TRADDR_MAX_PN_OFFSET],
2854 default: 2842 "pn-0x", NVME_FC_TRADDR_OXNNLEN)) {
2855 pr_warn("unknown traddr token or missing value '%s'\n", 2843 nnoffset = NVME_FC_TRADDR_OXNNLEN;
2856 p); 2844 pnoffset = NVME_FC_TRADDR_MAX_PN_OFFSET +
2857 ret = -EINVAL; 2845 NVME_FC_TRADDR_OXNNLEN;
2858 goto out; 2846 } else if ((strnlen(buf, blen) == NVME_FC_TRADDR_MINLENGTH &&
2859 } 2847 !strncmp(buf, "nn-", NVME_FC_TRADDR_NNLEN) &&
2860 } 2848 !strncmp(&buf[NVME_FC_TRADDR_MIN_PN_OFFSET],
2849 "pn-", NVME_FC_TRADDR_NNLEN))) {
2850 nnoffset = NVME_FC_TRADDR_NNLEN;
2851 pnoffset = NVME_FC_TRADDR_MIN_PN_OFFSET + NVME_FC_TRADDR_NNLEN;
2852 } else
2853 goto out_einval;
2861 2854
2862out: 2855 name[0] = '0';
2863 kfree(options); 2856 name[1] = 'x';
2864 return ret; 2857 name[2 + NVME_FC_TRADDR_HEXNAMELEN] = 0;
2858
2859 memcpy(&name[2], &buf[nnoffset], NVME_FC_TRADDR_HEXNAMELEN);
2860 if (__nvme_fc_parse_u64(&wwn, &traddr->nn))
2861 goto out_einval;
2862
2863 memcpy(&name[2], &buf[pnoffset], NVME_FC_TRADDR_HEXNAMELEN);
2864 if (__nvme_fc_parse_u64(&wwn, &traddr->pn))
2865 goto out_einval;
2866
2867 return 0;
2868
2869out_einval:
2870 pr_warn("%s: bad traddr string\n", __func__);
2871 return -EINVAL;
2865} 2872}
2866 2873
2867static struct nvme_ctrl * 2874static struct nvme_ctrl *
@@ -2875,11 +2882,11 @@ nvme_fc_create_ctrl(struct device *dev, struct nvmf_ctrl_options *opts)
2875 unsigned long flags; 2882 unsigned long flags;
2876 int ret; 2883 int ret;
2877 2884
2878 ret = nvme_fc_parse_address(&raddr, opts->traddr); 2885 ret = nvme_fc_parse_traddr(&raddr, opts->traddr, NVMF_TRADDR_SIZE);
2879 if (ret || !raddr.nn || !raddr.pn) 2886 if (ret || !raddr.nn || !raddr.pn)
2880 return ERR_PTR(-EINVAL); 2887 return ERR_PTR(-EINVAL);
2881 2888
2882 ret = nvme_fc_parse_address(&laddr, opts->host_traddr); 2889 ret = nvme_fc_parse_traddr(&laddr, opts->host_traddr, NVMF_TRADDR_SIZE);
2883 if (ret || !laddr.nn || !laddr.pn) 2890 if (ret || !laddr.nn || !laddr.pn)
2884 return ERR_PTR(-EINVAL); 2891 return ERR_PTR(-EINVAL);
2885 2892
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 8569ee771269..cd888a47d0fc 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -1619,7 +1619,7 @@ static void nvme_free_host_mem(struct nvme_dev *dev)
1619static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred) 1619static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred)
1620{ 1620{
1621 struct nvme_host_mem_buf_desc *descs; 1621 struct nvme_host_mem_buf_desc *descs;
1622 u32 chunk_size, max_entries; 1622 u32 chunk_size, max_entries, len;
1623 int i = 0; 1623 int i = 0;
1624 void **bufs; 1624 void **bufs;
1625 u64 size = 0, tmp; 1625 u64 size = 0, tmp;
@@ -1638,10 +1638,10 @@ retry:
1638 if (!bufs) 1638 if (!bufs)
1639 goto out_free_descs; 1639 goto out_free_descs;
1640 1640
1641 for (size = 0; size < preferred; size += chunk_size) { 1641 for (size = 0; size < preferred; size += len) {
1642 u32 len = min_t(u64, chunk_size, preferred - size);
1643 dma_addr_t dma_addr; 1642 dma_addr_t dma_addr;
1644 1643
1644 len = min_t(u64, chunk_size, preferred - size);
1645 bufs[i] = dma_alloc_attrs(dev->dev, len, &dma_addr, GFP_KERNEL, 1645 bufs[i] = dma_alloc_attrs(dev->dev, len, &dma_addr, GFP_KERNEL,
1646 DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN); 1646 DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
1647 if (!bufs[i]) 1647 if (!bufs[i])
diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
index d5801c150b1c..31ca55dfcb1d 100644
--- a/drivers/nvme/target/fc.c
+++ b/drivers/nvme/target/fc.c
@@ -2293,66 +2293,70 @@ nvmet_fc_rcv_fcp_abort(struct nvmet_fc_target_port *target_port,
2293} 2293}
2294EXPORT_SYMBOL_GPL(nvmet_fc_rcv_fcp_abort); 2294EXPORT_SYMBOL_GPL(nvmet_fc_rcv_fcp_abort);
2295 2295
2296enum {
2297 FCT_TRADDR_ERR = 0,
2298 FCT_TRADDR_WWNN = 1 << 0,
2299 FCT_TRADDR_WWPN = 1 << 1,
2300};
2301 2296
2302struct nvmet_fc_traddr { 2297struct nvmet_fc_traddr {
2303 u64 nn; 2298 u64 nn;
2304 u64 pn; 2299 u64 pn;
2305}; 2300};
2306 2301
2307static const match_table_t traddr_opt_tokens = {
2308 { FCT_TRADDR_WWNN, "nn-%s" },
2309 { FCT_TRADDR_WWPN, "pn-%s" },
2310 { FCT_TRADDR_ERR, NULL }
2311};
2312
2313static int 2302static int
2314nvmet_fc_parse_traddr(struct nvmet_fc_traddr *traddr, char *buf) 2303__nvme_fc_parse_u64(substring_t *sstr, u64 *val)
2315{ 2304{
2316 substring_t args[MAX_OPT_ARGS];
2317 char *options, *o, *p;
2318 int token, ret = 0;
2319 u64 token64; 2305 u64 token64;
2320 2306
2321 options = o = kstrdup(buf, GFP_KERNEL); 2307 if (match_u64(sstr, &token64))
2322 if (!options) 2308 return -EINVAL;
2323 return -ENOMEM; 2309 *val = token64;
2324 2310
2325 while ((p = strsep(&o, ":\n")) != NULL) { 2311 return 0;
2326 if (!*p) 2312}
2327 continue;
2328 2313
2329 token = match_token(p, traddr_opt_tokens, args); 2314/*
2330 switch (token) { 2315 * This routine validates and extracts the WWN's from the TRADDR string.
2331 case FCT_TRADDR_WWNN: 2316 * As kernel parsers need the 0x to determine number base, universally
2332 if (match_u64(args, &token64)) { 2317 * build string to parse with 0x prefix before parsing name strings.
2333 ret = -EINVAL; 2318 */
2334 goto out; 2319static int
2335 } 2320nvme_fc_parse_traddr(struct nvmet_fc_traddr *traddr, char *buf, size_t blen)
2336 traddr->nn = token64; 2321{
2337 break; 2322 char name[2 + NVME_FC_TRADDR_HEXNAMELEN + 1];
2338 case FCT_TRADDR_WWPN: 2323 substring_t wwn = { name, &name[sizeof(name)-1] };
2339 if (match_u64(args, &token64)) { 2324 int nnoffset, pnoffset;
2340 ret = -EINVAL; 2325
2341 goto out; 2326 /* validate it string one of the 2 allowed formats */
2342 } 2327 if (strnlen(buf, blen) == NVME_FC_TRADDR_MAXLENGTH &&
2343 traddr->pn = token64; 2328 !strncmp(buf, "nn-0x", NVME_FC_TRADDR_OXNNLEN) &&
2344 break; 2329 !strncmp(&buf[NVME_FC_TRADDR_MAX_PN_OFFSET],
2345 default: 2330 "pn-0x", NVME_FC_TRADDR_OXNNLEN)) {
2346 pr_warn("unknown traddr token or missing value '%s'\n", 2331 nnoffset = NVME_FC_TRADDR_OXNNLEN;
2347 p); 2332 pnoffset = NVME_FC_TRADDR_MAX_PN_OFFSET +
2348 ret = -EINVAL; 2333 NVME_FC_TRADDR_OXNNLEN;
2349 goto out; 2334 } else if ((strnlen(buf, blen) == NVME_FC_TRADDR_MINLENGTH &&
2350 } 2335 !strncmp(buf, "nn-", NVME_FC_TRADDR_NNLEN) &&
2351 } 2336 !strncmp(&buf[NVME_FC_TRADDR_MIN_PN_OFFSET],
2337 "pn-", NVME_FC_TRADDR_NNLEN))) {
2338 nnoffset = NVME_FC_TRADDR_NNLEN;
2339 pnoffset = NVME_FC_TRADDR_MIN_PN_OFFSET + NVME_FC_TRADDR_NNLEN;
2340 } else
2341 goto out_einval;
2342
2343 name[0] = '0';
2344 name[1] = 'x';
2345 name[2 + NVME_FC_TRADDR_HEXNAMELEN] = 0;
2346
2347 memcpy(&name[2], &buf[nnoffset], NVME_FC_TRADDR_HEXNAMELEN);
2348 if (__nvme_fc_parse_u64(&wwn, &traddr->nn))
2349 goto out_einval;
2350
2351 memcpy(&name[2], &buf[pnoffset], NVME_FC_TRADDR_HEXNAMELEN);
2352 if (__nvme_fc_parse_u64(&wwn, &traddr->pn))
2353 goto out_einval;
2352 2354
2353out: 2355 return 0;
2354 kfree(options); 2356
2355 return ret; 2357out_einval:
2358 pr_warn("%s: bad traddr string\n", __func__);
2359 return -EINVAL;
2356} 2360}
2357 2361
2358static int 2362static int
@@ -2370,7 +2374,8 @@ nvmet_fc_add_port(struct nvmet_port *port)
2370 2374
2371 /* map the traddr address info to a target port */ 2375 /* map the traddr address info to a target port */
2372 2376
2373 ret = nvmet_fc_parse_traddr(&traddr, port->disc_addr.traddr); 2377 ret = nvme_fc_parse_traddr(&traddr, port->disc_addr.traddr,
2378 sizeof(port->disc_addr.traddr));
2374 if (ret) 2379 if (ret)
2375 return ret; 2380 return ret;
2376 2381
diff --git a/include/linux/nvme-fc.h b/include/linux/nvme-fc.h
index 21c37e39e41a..36cca93a5ff2 100644
--- a/include/linux/nvme-fc.h
+++ b/include/linux/nvme-fc.h
@@ -334,5 +334,24 @@ struct fcnvme_ls_disconnect_acc {
334#define NVME_FC_LS_TIMEOUT_SEC 2 /* 2 seconds */ 334#define NVME_FC_LS_TIMEOUT_SEC 2 /* 2 seconds */
335#define NVME_FC_TGTOP_TIMEOUT_SEC 2 /* 2 seconds */ 335#define NVME_FC_TGTOP_TIMEOUT_SEC 2 /* 2 seconds */
336 336
337/*
338 * TRADDR string must be of form "nn-<16hexdigits>:pn-<16hexdigits>"
339 * the string is allowed to be specified with or without a "0x" prefix
340 * infront of the <16hexdigits>. Without is considered the "min" string
341 * and with is considered the "max" string. The hexdigits may be upper
342 * or lower case.
343 */
344#define NVME_FC_TRADDR_NNLEN 3 /* "?n-" */
345#define NVME_FC_TRADDR_OXNNLEN 5 /* "?n-0x" */
346#define NVME_FC_TRADDR_HEXNAMELEN 16
347#define NVME_FC_TRADDR_MINLENGTH \
348 (2 * (NVME_FC_TRADDR_NNLEN + NVME_FC_TRADDR_HEXNAMELEN) + 1)
349#define NVME_FC_TRADDR_MAXLENGTH \
350 (2 * (NVME_FC_TRADDR_OXNNLEN + NVME_FC_TRADDR_HEXNAMELEN) + 1)
351#define NVME_FC_TRADDR_MIN_PN_OFFSET \
352 (NVME_FC_TRADDR_NNLEN + NVME_FC_TRADDR_HEXNAMELEN + 1)
353#define NVME_FC_TRADDR_MAX_PN_OFFSET \
354 (NVME_FC_TRADDR_OXNNLEN + NVME_FC_TRADDR_HEXNAMELEN + 1)
355
337 356
338#endif /* _NVME_FC_H */ 357#endif /* _NVME_FC_H */
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index bc74da018bdc..25d8225dbd04 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -1006,7 +1006,7 @@ static inline bool nvme_is_write(struct nvme_command *cmd)
1006 * Why can't we simply have a Fabrics In and Fabrics out command? 1006 * Why can't we simply have a Fabrics In and Fabrics out command?
1007 */ 1007 */
1008 if (unlikely(cmd->common.opcode == nvme_fabrics_command)) 1008 if (unlikely(cmd->common.opcode == nvme_fabrics_command))
1009 return cmd->fabrics.opcode & 1; 1009 return cmd->fabrics.fctype & 1;
1010 return cmd->common.opcode & 1; 1010 return cmd->common.opcode & 1;
1011} 1011}
1012 1012