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

lpfc: nvmet: Add support for NVME LS request hosthandle

As the nvmet layer does not have the concept of a remoteport object, which
can be used to identify the entity on the other end of the fabric that is
to receive an LS, the hosthandle was introduced. The driver passes the
hosthandle, a value representative of the remote port, with a ls request
receive. The LS request will create the association. The transport will
remember the hosthandle for the association, and if there is a need to
initiate a LS request to the remote port for the association, the
hosthandle will be used. When the driver loses connectivity with the
remote port, it needs to notify the transport that the hosthandle is no
longer valid, allowing the transport to terminate associations related to
the hosthandle.

This patch adds support to the driver for the hosthandle. The driver will
use the ndlp pointer of the remote port for the hosthandle in calls to
nvmet_fc_rcv_ls_req(). The discovery engine is updated to invalidate the
hosthandle whenever connectivity with the remote port is lost.

Signed-off-by: Paul Ely <paul.ely@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

James Smart and committed by
Jens Axboe
4c2805aa 9aa09e98

+74 -1
+2
drivers/scsi/lpfc/lpfc_crtn.h
··· 571 571 struct rqb_dmabuf *nvmebuf, uint64_t isr_ts, 572 572 uint8_t cqflag); 573 573 void lpfc_nvme_mod_param_dep(struct lpfc_hba *phba); 574 + void lpfc_nvmet_invalidate_host(struct lpfc_hba *phba, 575 + struct lpfc_nodelist *ndlp); 574 576 void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba, 575 577 struct lpfc_iocbq *cmdiocb, 576 578 struct lpfc_wcqe_complete *abts_cmpl);
+6
drivers/scsi/lpfc/lpfc_hbadisc.c
··· 823 823 if ((phba->sli_rev < LPFC_SLI_REV4) && 824 824 (!remove && ndlp->nlp_type & NLP_FABRIC)) 825 825 continue; 826 + 827 + /* Notify transport of connectivity loss to trigger cleanup. */ 828 + if (phba->nvmet_support && 829 + ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) 830 + lpfc_nvmet_invalidate_host(phba, ndlp); 831 + 826 832 lpfc_disc_state_machine(vport, ndlp, NULL, 827 833 remove 828 834 ? NLP_EVT_DEVICE_RM
+11
drivers/scsi/lpfc/lpfc_nportdisc.c
··· 489 489 (unsigned long long) 490 490 wwn_to_u64(sp->portName.u.wwn)); 491 491 492 + /* Notify transport of connectivity loss to trigger cleanup. */ 493 + if (phba->nvmet_support && 494 + ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) 495 + lpfc_nvmet_invalidate_host(phba, ndlp); 496 + 492 497 ndlp->nlp_prev_state = ndlp->nlp_state; 493 498 /* rport needs to be unregistered first */ 494 499 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); ··· 844 839 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); 845 840 else 846 841 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); 842 + 843 + /* Notify transport of connectivity loss to trigger cleanup. */ 844 + if (phba->nvmet_support && 845 + ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) 846 + lpfc_nvmet_invalidate_host(phba, ndlp); 847 + 847 848 if (ndlp->nlp_DID == Fabric_DID) { 848 849 if (vport->port_state <= LPFC_FDISC) 849 850 goto out;
+3
drivers/scsi/lpfc/lpfc_nvme.h
··· 98 98 #define LPFC_NVMET_WAIT_TMO (5 * MSEC_PER_SEC) 99 99 100 100 /* Used for NVME Target */ 101 + #define LPFC_NVMET_INV_HOST_ACTIVE 1 102 + 101 103 struct lpfc_nvmet_tgtport { 102 104 struct lpfc_hba *phba; 103 105 struct completion *tport_unreg_cmp; 106 + atomic_t state; /* tracks nvmet hosthandle invalidation */ 104 107 105 108 /* Stats counters - lpfc_nvmet_unsol_ls_buffer */ 106 109 atomic_t rcv_ls_req_in;
+52 -1
drivers/scsi/lpfc/lpfc_nvmet.c
··· 1283 1283 } 1284 1284 1285 1285 static void 1286 + lpfc_nvmet_host_release(void *hosthandle) 1287 + { 1288 + struct lpfc_nodelist *ndlp = hosthandle; 1289 + struct lpfc_hba *phba = NULL; 1290 + struct lpfc_nvmet_tgtport *tgtp; 1291 + 1292 + phba = ndlp->phba; 1293 + if (!phba->targetport || !phba->targetport->private) 1294 + return; 1295 + 1296 + lpfc_printf_log(phba, KERN_ERR, LOG_NVME, 1297 + "6202 NVMET XPT releasing hosthandle x%px\n", 1298 + hosthandle); 1299 + tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; 1300 + atomic_set(&tgtp->state, 0); 1301 + } 1302 + 1303 + static void 1286 1304 lpfc_nvmet_discovery_event(struct nvmet_fc_target_port *tgtport) 1287 1305 { 1288 1306 struct lpfc_nvmet_tgtport *tgtp; ··· 1324 1306 .fcp_req_release = lpfc_nvmet_xmt_fcp_release, 1325 1307 .defer_rcv = lpfc_nvmet_defer_rcv, 1326 1308 .discovery_event = lpfc_nvmet_discovery_event, 1309 + .host_release = lpfc_nvmet_host_release, 1327 1310 1328 1311 .max_hw_queues = 1, 1329 1312 .max_sgl_segments = LPFC_NVMET_DEFAULT_SEGS, ··· 2063 2044 2064 2045 atomic_inc(&tgtp->rcv_ls_req_in); 2065 2046 2066 - rc = nvmet_fc_rcv_ls_req(phba->targetport, NULL, &axchg->ls_rsp, 2047 + /* 2048 + * Driver passes the ndlp as the hosthandle argument allowing 2049 + * the transport to generate LS requests for any associateions 2050 + * that are created. 2051 + */ 2052 + rc = nvmet_fc_rcv_ls_req(phba->targetport, axchg->ndlp, &axchg->ls_rsp, 2067 2053 axchg->payload, axchg->size); 2068 2054 2069 2055 lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC, ··· 3499 3475 lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS, 3500 3476 "6056 Failed to Issue ABTS. Status x%x\n", rc); 3501 3477 return 0; 3478 + } 3479 + 3480 + /** 3481 + * lpfc_nvmet_invalidate_host 3482 + * 3483 + * @phba - pointer to the driver instance bound to an adapter port. 3484 + * @ndlp - pointer to an lpfc_nodelist type 3485 + * 3486 + * This routine upcalls the nvmet transport to invalidate an NVME 3487 + * host to which this target instance had active connections. 3488 + */ 3489 + void 3490 + lpfc_nvmet_invalidate_host(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) 3491 + { 3492 + struct lpfc_nvmet_tgtport *tgtp; 3493 + 3494 + lpfc_printf_log(phba, KERN_INFO, LOG_NVME | LOG_NVME_ABTS, 3495 + "6203 Invalidating hosthandle x%px\n", 3496 + ndlp); 3497 + 3498 + tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; 3499 + atomic_set(&tgtp->state, LPFC_NVMET_INV_HOST_ACTIVE); 3500 + 3501 + #if (IS_ENABLED(CONFIG_NVME_TARGET_FC)) 3502 + /* Need to get the nvmet_fc_target_port pointer here.*/ 3503 + nvmet_fc_invalidate_host(phba->targetport, ndlp); 3504 + #endif 3502 3505 }