diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_nvme.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nvme.c | 107 |
1 files changed, 82 insertions, 25 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 609a908ea9db..0024de1c6c1f 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c | |||
@@ -316,7 +316,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, | |||
316 | bf_set(wqe_dfctl, &wqe->gen_req.wge_ctl, 0); | 316 | bf_set(wqe_dfctl, &wqe->gen_req.wge_ctl, 0); |
317 | bf_set(wqe_si, &wqe->gen_req.wge_ctl, 1); | 317 | bf_set(wqe_si, &wqe->gen_req.wge_ctl, 1); |
318 | bf_set(wqe_la, &wqe->gen_req.wge_ctl, 1); | 318 | bf_set(wqe_la, &wqe->gen_req.wge_ctl, 1); |
319 | bf_set(wqe_rctl, &wqe->gen_req.wge_ctl, FC_RCTL_DD_UNSOL_CTL); | 319 | bf_set(wqe_rctl, &wqe->gen_req.wge_ctl, FC_RCTL_ELS4_REQ); |
320 | bf_set(wqe_type, &wqe->gen_req.wge_ctl, FC_TYPE_NVME); | 320 | bf_set(wqe_type, &wqe->gen_req.wge_ctl, FC_TYPE_NVME); |
321 | 321 | ||
322 | /* Word 6 */ | 322 | /* Word 6 */ |
@@ -620,15 +620,15 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, | |||
620 | * Embed the payload in the last half of the WQE | 620 | * Embed the payload in the last half of the WQE |
621 | * WQE words 16-30 get the NVME CMD IU payload | 621 | * WQE words 16-30 get the NVME CMD IU payload |
622 | * | 622 | * |
623 | * WQE Word 16 is already setup with flags | 623 | * WQE words 16-19 get payload Words 1-4 |
624 | * WQE words 17-19 get payload Words 2-4 | ||
625 | * WQE words 20-21 get payload Words 6-7 | 624 | * WQE words 20-21 get payload Words 6-7 |
626 | * WQE words 22-29 get payload Words 16-23 | 625 | * WQE words 22-29 get payload Words 16-23 |
627 | */ | 626 | */ |
628 | wptr = &wqe->words[17]; /* WQE ptr */ | 627 | wptr = &wqe->words[16]; /* WQE ptr */ |
629 | dptr = (uint32_t *)nCmd->cmdaddr; /* payload ptr */ | 628 | dptr = (uint32_t *)nCmd->cmdaddr; /* payload ptr */ |
630 | dptr += 2; /* Skip Words 0-1 in payload */ | 629 | dptr++; /* Skip Word 0 in payload */ |
631 | 630 | ||
631 | *wptr++ = *dptr++; /* Word 1 */ | ||
632 | *wptr++ = *dptr++; /* Word 2 */ | 632 | *wptr++ = *dptr++; /* Word 2 */ |
633 | *wptr++ = *dptr++; /* Word 3 */ | 633 | *wptr++ = *dptr++; /* Word 3 */ |
634 | *wptr++ = *dptr++; /* Word 4 */ | 634 | *wptr++ = *dptr++; /* Word 4 */ |
@@ -978,9 +978,6 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, | |||
978 | bf_set(wqe_cmd_type, &wqe->generic.wqe_com, | 978 | bf_set(wqe_cmd_type, &wqe->generic.wqe_com, |
979 | NVME_WRITE_CMD); | 979 | NVME_WRITE_CMD); |
980 | 980 | ||
981 | /* Word 16 */ | ||
982 | wqe->words[16] = LPFC_NVME_EMBED_WRITE; | ||
983 | |||
984 | phba->fc4NvmeOutputRequests++; | 981 | phba->fc4NvmeOutputRequests++; |
985 | } else { | 982 | } else { |
986 | /* Word 7 */ | 983 | /* Word 7 */ |
@@ -1002,9 +999,6 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, | |||
1002 | bf_set(wqe_cmd_type, &wqe->generic.wqe_com, | 999 | bf_set(wqe_cmd_type, &wqe->generic.wqe_com, |
1003 | NVME_READ_CMD); | 1000 | NVME_READ_CMD); |
1004 | 1001 | ||
1005 | /* Word 16 */ | ||
1006 | wqe->words[16] = LPFC_NVME_EMBED_READ; | ||
1007 | |||
1008 | phba->fc4NvmeInputRequests++; | 1002 | phba->fc4NvmeInputRequests++; |
1009 | } | 1003 | } |
1010 | } else { | 1004 | } else { |
@@ -1026,9 +1020,6 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, | |||
1026 | /* Word 11 */ | 1020 | /* Word 11 */ |
1027 | bf_set(wqe_cmd_type, &wqe->generic.wqe_com, NVME_READ_CMD); | 1021 | bf_set(wqe_cmd_type, &wqe->generic.wqe_com, NVME_READ_CMD); |
1028 | 1022 | ||
1029 | /* Word 16 */ | ||
1030 | wqe->words[16] = LPFC_NVME_EMBED_CMD; | ||
1031 | |||
1032 | phba->fc4NvmeControlRequests++; | 1023 | phba->fc4NvmeControlRequests++; |
1033 | } | 1024 | } |
1034 | /* | 1025 | /* |
@@ -1286,6 +1277,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport, | |||
1286 | pnvme_fcreq->private = (void *)lpfc_ncmd; | 1277 | pnvme_fcreq->private = (void *)lpfc_ncmd; |
1287 | lpfc_ncmd->nvmeCmd = pnvme_fcreq; | 1278 | lpfc_ncmd->nvmeCmd = pnvme_fcreq; |
1288 | lpfc_ncmd->nrport = rport; | 1279 | lpfc_ncmd->nrport = rport; |
1280 | lpfc_ncmd->ndlp = ndlp; | ||
1289 | lpfc_ncmd->start_time = jiffies; | 1281 | lpfc_ncmd->start_time = jiffies; |
1290 | 1282 | ||
1291 | lpfc_nvme_prep_io_cmd(vport, lpfc_ncmd, ndlp); | 1283 | lpfc_nvme_prep_io_cmd(vport, lpfc_ncmd, ndlp); |
@@ -1319,7 +1311,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport, | |||
1319 | "sid: x%x did: x%x oxid: x%x\n", | 1311 | "sid: x%x did: x%x oxid: x%x\n", |
1320 | ret, vport->fc_myDID, ndlp->nlp_DID, | 1312 | ret, vport->fc_myDID, ndlp->nlp_DID, |
1321 | lpfc_ncmd->cur_iocbq.sli4_xritag); | 1313 | lpfc_ncmd->cur_iocbq.sli4_xritag); |
1322 | ret = -EINVAL; | 1314 | ret = -EBUSY; |
1323 | goto out_free_nvme_buf; | 1315 | goto out_free_nvme_buf; |
1324 | } | 1316 | } |
1325 | 1317 | ||
@@ -1821,10 +1813,10 @@ lpfc_post_nvme_sgl_list(struct lpfc_hba *phba, | |||
1821 | pdma_phys_sgl1, cur_xritag); | 1813 | pdma_phys_sgl1, cur_xritag); |
1822 | if (status) { | 1814 | if (status) { |
1823 | /* failure, put on abort nvme list */ | 1815 | /* failure, put on abort nvme list */ |
1824 | lpfc_ncmd->exch_busy = 1; | 1816 | lpfc_ncmd->flags |= LPFC_SBUF_XBUSY; |
1825 | } else { | 1817 | } else { |
1826 | /* success, put on NVME buffer list */ | 1818 | /* success, put on NVME buffer list */ |
1827 | lpfc_ncmd->exch_busy = 0; | 1819 | lpfc_ncmd->flags &= ~LPFC_SBUF_XBUSY; |
1828 | lpfc_ncmd->status = IOSTAT_SUCCESS; | 1820 | lpfc_ncmd->status = IOSTAT_SUCCESS; |
1829 | num_posted++; | 1821 | num_posted++; |
1830 | } | 1822 | } |
@@ -1854,10 +1846,10 @@ lpfc_post_nvme_sgl_list(struct lpfc_hba *phba, | |||
1854 | struct lpfc_nvme_buf, list); | 1846 | struct lpfc_nvme_buf, list); |
1855 | if (status) { | 1847 | if (status) { |
1856 | /* failure, put on abort nvme list */ | 1848 | /* failure, put on abort nvme list */ |
1857 | lpfc_ncmd->exch_busy = 1; | 1849 | lpfc_ncmd->flags |= LPFC_SBUF_XBUSY; |
1858 | } else { | 1850 | } else { |
1859 | /* success, put on NVME buffer list */ | 1851 | /* success, put on NVME buffer list */ |
1860 | lpfc_ncmd->exch_busy = 0; | 1852 | lpfc_ncmd->flags &= ~LPFC_SBUF_XBUSY; |
1861 | lpfc_ncmd->status = IOSTAT_SUCCESS; | 1853 | lpfc_ncmd->status = IOSTAT_SUCCESS; |
1862 | num_posted++; | 1854 | num_posted++; |
1863 | } | 1855 | } |
@@ -2099,7 +2091,7 @@ lpfc_release_nvme_buf(struct lpfc_hba *phba, struct lpfc_nvme_buf *lpfc_ncmd) | |||
2099 | unsigned long iflag = 0; | 2091 | unsigned long iflag = 0; |
2100 | 2092 | ||
2101 | lpfc_ncmd->nonsg_phys = 0; | 2093 | lpfc_ncmd->nonsg_phys = 0; |
2102 | if (lpfc_ncmd->exch_busy) { | 2094 | if (lpfc_ncmd->flags & LPFC_SBUF_XBUSY) { |
2103 | spin_lock_irqsave(&phba->sli4_hba.abts_nvme_buf_list_lock, | 2095 | spin_lock_irqsave(&phba->sli4_hba.abts_nvme_buf_list_lock, |
2104 | iflag); | 2096 | iflag); |
2105 | lpfc_ncmd->nvmeCmd = NULL; | 2097 | lpfc_ncmd->nvmeCmd = NULL; |
@@ -2135,11 +2127,12 @@ lpfc_release_nvme_buf(struct lpfc_hba *phba, struct lpfc_nvme_buf *lpfc_ncmd) | |||
2135 | int | 2127 | int |
2136 | lpfc_nvme_create_localport(struct lpfc_vport *vport) | 2128 | lpfc_nvme_create_localport(struct lpfc_vport *vport) |
2137 | { | 2129 | { |
2130 | int ret = 0; | ||
2138 | struct lpfc_hba *phba = vport->phba; | 2131 | struct lpfc_hba *phba = vport->phba; |
2139 | struct nvme_fc_port_info nfcp_info; | 2132 | struct nvme_fc_port_info nfcp_info; |
2140 | struct nvme_fc_local_port *localport; | 2133 | struct nvme_fc_local_port *localport; |
2141 | struct lpfc_nvme_lport *lport; | 2134 | struct lpfc_nvme_lport *lport; |
2142 | int len, ret = 0; | 2135 | int len; |
2143 | 2136 | ||
2144 | /* Initialize this localport instance. The vport wwn usage ensures | 2137 | /* Initialize this localport instance. The vport wwn usage ensures |
2145 | * that NPIV is accounted for. | 2138 | * that NPIV is accounted for. |
@@ -2156,8 +2149,12 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport) | |||
2156 | /* localport is allocated from the stack, but the registration | 2149 | /* localport is allocated from the stack, but the registration |
2157 | * call allocates heap memory as well as the private area. | 2150 | * call allocates heap memory as well as the private area. |
2158 | */ | 2151 | */ |
2152 | #if (IS_ENABLED(CONFIG_NVME_FC)) | ||
2159 | ret = nvme_fc_register_localport(&nfcp_info, &lpfc_nvme_template, | 2153 | ret = nvme_fc_register_localport(&nfcp_info, &lpfc_nvme_template, |
2160 | &vport->phba->pcidev->dev, &localport); | 2154 | &vport->phba->pcidev->dev, &localport); |
2155 | #else | ||
2156 | ret = -ENOMEM; | ||
2157 | #endif | ||
2161 | if (!ret) { | 2158 | if (!ret) { |
2162 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME | LOG_NVME_DISC, | 2159 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME | LOG_NVME_DISC, |
2163 | "6005 Successfully registered local " | 2160 | "6005 Successfully registered local " |
@@ -2173,10 +2170,10 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport) | |||
2173 | lport->vport = vport; | 2170 | lport->vport = vport; |
2174 | INIT_LIST_HEAD(&lport->rport_list); | 2171 | INIT_LIST_HEAD(&lport->rport_list); |
2175 | vport->nvmei_support = 1; | 2172 | vport->nvmei_support = 1; |
2173 | len = lpfc_new_nvme_buf(vport, phba->sli4_hba.nvme_xri_max); | ||
2174 | vport->phba->total_nvme_bufs += len; | ||
2176 | } | 2175 | } |
2177 | 2176 | ||
2178 | len = lpfc_new_nvme_buf(vport, phba->sli4_hba.nvme_xri_max); | ||
2179 | vport->phba->total_nvme_bufs += len; | ||
2180 | return ret; | 2177 | return ret; |
2181 | } | 2178 | } |
2182 | 2179 | ||
@@ -2193,6 +2190,7 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport) | |||
2193 | void | 2190 | void |
2194 | lpfc_nvme_destroy_localport(struct lpfc_vport *vport) | 2191 | lpfc_nvme_destroy_localport(struct lpfc_vport *vport) |
2195 | { | 2192 | { |
2193 | #if (IS_ENABLED(CONFIG_NVME_FC)) | ||
2196 | struct nvme_fc_local_port *localport; | 2194 | struct nvme_fc_local_port *localport; |
2197 | struct lpfc_nvme_lport *lport; | 2195 | struct lpfc_nvme_lport *lport; |
2198 | struct lpfc_nvme_rport *rport = NULL, *rport_next = NULL; | 2196 | struct lpfc_nvme_rport *rport = NULL, *rport_next = NULL; |
@@ -2208,7 +2206,6 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport) | |||
2208 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME, | 2206 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME, |
2209 | "6011 Destroying NVME localport %p\n", | 2207 | "6011 Destroying NVME localport %p\n", |
2210 | localport); | 2208 | localport); |
2211 | |||
2212 | list_for_each_entry_safe(rport, rport_next, &lport->rport_list, list) { | 2209 | list_for_each_entry_safe(rport, rport_next, &lport->rport_list, list) { |
2213 | /* The last node ref has to get released now before the rport | 2210 | /* The last node ref has to get released now before the rport |
2214 | * private memory area is released by the transport. | 2211 | * private memory area is released by the transport. |
@@ -2222,6 +2219,7 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport) | |||
2222 | "6008 rport fail destroy %x\n", ret); | 2219 | "6008 rport fail destroy %x\n", ret); |
2223 | wait_for_completion_timeout(&rport->rport_unreg_done, 5); | 2220 | wait_for_completion_timeout(&rport->rport_unreg_done, 5); |
2224 | } | 2221 | } |
2222 | |||
2225 | /* lport's rport list is clear. Unregister | 2223 | /* lport's rport list is clear. Unregister |
2226 | * lport and release resources. | 2224 | * lport and release resources. |
2227 | */ | 2225 | */ |
@@ -2245,6 +2243,7 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport) | |||
2245 | "Failed, status x%x\n", | 2243 | "Failed, status x%x\n", |
2246 | ret); | 2244 | ret); |
2247 | } | 2245 | } |
2246 | #endif | ||
2248 | } | 2247 | } |
2249 | 2248 | ||
2250 | void | 2249 | void |
@@ -2275,6 +2274,7 @@ lpfc_nvme_update_localport(struct lpfc_vport *vport) | |||
2275 | int | 2274 | int |
2276 | lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | 2275 | lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
2277 | { | 2276 | { |
2277 | #if (IS_ENABLED(CONFIG_NVME_FC)) | ||
2278 | int ret = 0; | 2278 | int ret = 0; |
2279 | struct nvme_fc_local_port *localport; | 2279 | struct nvme_fc_local_port *localport; |
2280 | struct lpfc_nvme_lport *lport; | 2280 | struct lpfc_nvme_lport *lport; |
@@ -2348,7 +2348,6 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
2348 | rpinfo.port_role |= FC_PORT_ROLE_NVME_INITIATOR; | 2348 | rpinfo.port_role |= FC_PORT_ROLE_NVME_INITIATOR; |
2349 | rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn); | 2349 | rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn); |
2350 | rpinfo.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn); | 2350 | rpinfo.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn); |
2351 | |||
2352 | ret = nvme_fc_register_remoteport(localport, &rpinfo, | 2351 | ret = nvme_fc_register_remoteport(localport, &rpinfo, |
2353 | &remote_port); | 2352 | &remote_port); |
2354 | if (!ret) { | 2353 | if (!ret) { |
@@ -2384,6 +2383,9 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
2384 | ndlp->nlp_type, ndlp->nlp_DID, ndlp); | 2383 | ndlp->nlp_type, ndlp->nlp_DID, ndlp); |
2385 | } | 2384 | } |
2386 | return ret; | 2385 | return ret; |
2386 | #else | ||
2387 | return 0; | ||
2388 | #endif | ||
2387 | } | 2389 | } |
2388 | 2390 | ||
2389 | /* lpfc_nvme_unregister_port - unbind the DID and port_role from this rport. | 2391 | /* lpfc_nvme_unregister_port - unbind the DID and port_role from this rport. |
@@ -2401,6 +2403,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
2401 | void | 2403 | void |
2402 | lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | 2404 | lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
2403 | { | 2405 | { |
2406 | #if (IS_ENABLED(CONFIG_NVME_FC)) | ||
2404 | int ret; | 2407 | int ret; |
2405 | struct nvme_fc_local_port *localport; | 2408 | struct nvme_fc_local_port *localport; |
2406 | struct lpfc_nvme_lport *lport; | 2409 | struct lpfc_nvme_lport *lport; |
@@ -2458,7 +2461,61 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
2458 | return; | 2461 | return; |
2459 | 2462 | ||
2460 | input_err: | 2463 | input_err: |
2464 | #endif | ||
2461 | lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, | 2465 | lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, |
2462 | "6168: State error: lport %p, rport%p FCID x%06x\n", | 2466 | "6168: State error: lport %p, rport%p FCID x%06x\n", |
2463 | vport->localport, ndlp->rport, ndlp->nlp_DID); | 2467 | vport->localport, ndlp->rport, ndlp->nlp_DID); |
2464 | } | 2468 | } |
2469 | |||
2470 | /** | ||
2471 | * lpfc_sli4_nvme_xri_aborted - Fast-path process of NVME xri abort | ||
2472 | * @phba: pointer to lpfc hba data structure. | ||
2473 | * @axri: pointer to the fcp xri abort wcqe structure. | ||
2474 | * | ||
2475 | * This routine is invoked by the worker thread to process a SLI4 fast-path | ||
2476 | * FCP aborted xri. | ||
2477 | **/ | ||
2478 | void | ||
2479 | lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba, | ||
2480 | struct sli4_wcqe_xri_aborted *axri) | ||
2481 | { | ||
2482 | uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); | ||
2483 | uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri); | ||
2484 | struct lpfc_nvme_buf *lpfc_ncmd, *next_lpfc_ncmd; | ||
2485 | struct lpfc_nodelist *ndlp; | ||
2486 | unsigned long iflag = 0; | ||
2487 | int rrq_empty = 0; | ||
2488 | |||
2489 | if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) | ||
2490 | return; | ||
2491 | spin_lock_irqsave(&phba->hbalock, iflag); | ||
2492 | spin_lock(&phba->sli4_hba.abts_nvme_buf_list_lock); | ||
2493 | list_for_each_entry_safe(lpfc_ncmd, next_lpfc_ncmd, | ||
2494 | &phba->sli4_hba.lpfc_abts_nvme_buf_list, | ||
2495 | list) { | ||
2496 | if (lpfc_ncmd->cur_iocbq.sli4_xritag == xri) { | ||
2497 | list_del(&lpfc_ncmd->list); | ||
2498 | lpfc_ncmd->flags &= ~LPFC_SBUF_XBUSY; | ||
2499 | lpfc_ncmd->status = IOSTAT_SUCCESS; | ||
2500 | spin_unlock( | ||
2501 | &phba->sli4_hba.abts_nvme_buf_list_lock); | ||
2502 | |||
2503 | rrq_empty = list_empty(&phba->active_rrq_list); | ||
2504 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
2505 | ndlp = lpfc_ncmd->ndlp; | ||
2506 | if (ndlp) { | ||
2507 | lpfc_set_rrq_active( | ||
2508 | phba, ndlp, | ||
2509 | lpfc_ncmd->cur_iocbq.sli4_lxritag, | ||
2510 | rxid, 1); | ||
2511 | lpfc_sli4_abts_err_handler(phba, ndlp, axri); | ||
2512 | } | ||
2513 | lpfc_release_nvme_buf(phba, lpfc_ncmd); | ||
2514 | if (rrq_empty) | ||
2515 | lpfc_worker_wake_up(phba); | ||
2516 | return; | ||
2517 | } | ||
2518 | } | ||
2519 | spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock); | ||
2520 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
2521 | } | ||