diff options
author | James Smart <james.smart@emulex.com> | 2013-01-03 15:43:37 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-01-29 19:21:21 -0500 |
commit | 6dd9e31ccbc4dbe2d730937cb5728673f71e4ba8 (patch) | |
tree | cb05a597d5dea2bfe03fe337d4655ca15c710e2c | |
parent | 7b15db32d3a585e5f7e304b4728b29daa534e039 (diff) |
[SCSI] lpfc 8.3.37: Fixed no-context ABTS failed with BA_RJT
Fixed no-context ABTS received on unsolicited receive queue failed with BA_RJT
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 8 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.c | 51 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 37 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 151 |
5 files changed, 168 insertions, 83 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index df4c13a5534c..9b7fbaf07a55 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -466,11 +466,13 @@ enum intr_type_t { | |||
466 | MSIX, | 466 | MSIX, |
467 | }; | 467 | }; |
468 | 468 | ||
469 | #define LPFC_CT_CTX_MAX 64 | ||
469 | struct unsol_rcv_ct_ctx { | 470 | struct unsol_rcv_ct_ctx { |
470 | uint32_t ctxt_id; | 471 | uint32_t ctxt_id; |
471 | uint32_t SID; | 472 | uint32_t SID; |
472 | uint32_t flags; | 473 | uint32_t valid; |
473 | #define UNSOL_VALID 0x00000001 | 474 | #define UNSOL_INVALID 0 |
475 | #define UNSOL_VALID 1 | ||
474 | uint16_t oxid; | 476 | uint16_t oxid; |
475 | uint16_t rxid; | 477 | uint16_t rxid; |
476 | }; | 478 | }; |
@@ -938,7 +940,7 @@ struct lpfc_hba { | |||
938 | 940 | ||
939 | spinlock_t ct_ev_lock; /* synchronize access to ct_ev_waiters */ | 941 | spinlock_t ct_ev_lock; /* synchronize access to ct_ev_waiters */ |
940 | struct list_head ct_ev_waiters; | 942 | struct list_head ct_ev_waiters; |
941 | struct unsol_rcv_ct_ctx ct_ctx[64]; | 943 | struct unsol_rcv_ct_ctx ct_ctx[LPFC_CT_CTX_MAX]; |
942 | uint32_t ctx_idx; | 944 | uint32_t ctx_idx; |
943 | 945 | ||
944 | uint8_t menlo_flag; /* menlo generic flags */ | 946 | uint8_t menlo_flag; /* menlo generic flags */ |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index f7368eb80415..32d5683e6181 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
@@ -955,9 +955,9 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
955 | spin_lock_irqsave(&phba->ct_ev_lock, flags); | 955 | spin_lock_irqsave(&phba->ct_ev_lock, flags); |
956 | if (phba->sli_rev == LPFC_SLI_REV4) { | 956 | if (phba->sli_rev == LPFC_SLI_REV4) { |
957 | evt_dat->immed_dat = phba->ctx_idx; | 957 | evt_dat->immed_dat = phba->ctx_idx; |
958 | phba->ctx_idx = (phba->ctx_idx + 1) % 64; | 958 | phba->ctx_idx = (phba->ctx_idx + 1) % LPFC_CT_CTX_MAX; |
959 | /* Provide warning for over-run of the ct_ctx array */ | 959 | /* Provide warning for over-run of the ct_ctx array */ |
960 | if (phba->ct_ctx[evt_dat->immed_dat].flags & | 960 | if (phba->ct_ctx[evt_dat->immed_dat].valid == |
961 | UNSOL_VALID) | 961 | UNSOL_VALID) |
962 | lpfc_printf_log(phba, KERN_WARNING, LOG_ELS, | 962 | lpfc_printf_log(phba, KERN_WARNING, LOG_ELS, |
963 | "2717 CT context array entry " | 963 | "2717 CT context array entry " |
@@ -973,7 +973,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
973 | piocbq->iocb.unsli3.rcvsli3.ox_id; | 973 | piocbq->iocb.unsli3.rcvsli3.ox_id; |
974 | phba->ct_ctx[evt_dat->immed_dat].SID = | 974 | phba->ct_ctx[evt_dat->immed_dat].SID = |
975 | piocbq->iocb.un.rcvels.remoteID; | 975 | piocbq->iocb.un.rcvels.remoteID; |
976 | phba->ct_ctx[evt_dat->immed_dat].flags = UNSOL_VALID; | 976 | phba->ct_ctx[evt_dat->immed_dat].valid = UNSOL_VALID; |
977 | } else | 977 | } else |
978 | evt_dat->immed_dat = piocbq->iocb.ulpContext; | 978 | evt_dat->immed_dat = piocbq->iocb.ulpContext; |
979 | 979 | ||
@@ -1013,6 +1013,47 @@ error_ct_unsol_exit: | |||
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | /** | 1015 | /** |
1016 | * lpfc_bsg_ct_unsol_abort - handler ct abort to management plane | ||
1017 | * @phba: Pointer to HBA context object. | ||
1018 | * @dmabuf: pointer to a dmabuf that describes the FC sequence | ||
1019 | * | ||
1020 | * This function handles abort to the CT command toward management plane | ||
1021 | * for SLI4 port. | ||
1022 | * | ||
1023 | * If the pending context of a CT command to management plane present, clears | ||
1024 | * such context and returns 1 for handled; otherwise, it returns 0 indicating | ||
1025 | * no context exists. | ||
1026 | **/ | ||
1027 | int | ||
1028 | lpfc_bsg_ct_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf) | ||
1029 | { | ||
1030 | struct fc_frame_header fc_hdr; | ||
1031 | struct fc_frame_header *fc_hdr_ptr = &fc_hdr; | ||
1032 | int ctx_idx, handled = 0; | ||
1033 | uint16_t oxid, rxid; | ||
1034 | uint32_t sid; | ||
1035 | |||
1036 | memcpy(fc_hdr_ptr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header)); | ||
1037 | sid = sli4_sid_from_fc_hdr(fc_hdr_ptr); | ||
1038 | oxid = be16_to_cpu(fc_hdr_ptr->fh_ox_id); | ||
1039 | rxid = be16_to_cpu(fc_hdr_ptr->fh_rx_id); | ||
1040 | |||
1041 | for (ctx_idx = 0; ctx_idx < LPFC_CT_CTX_MAX; ctx_idx++) { | ||
1042 | if (phba->ct_ctx[ctx_idx].valid != UNSOL_VALID) | ||
1043 | continue; | ||
1044 | if (phba->ct_ctx[ctx_idx].rxid != rxid) | ||
1045 | continue; | ||
1046 | if (phba->ct_ctx[ctx_idx].oxid != oxid) | ||
1047 | continue; | ||
1048 | if (phba->ct_ctx[ctx_idx].SID != sid) | ||
1049 | continue; | ||
1050 | phba->ct_ctx[ctx_idx].valid = UNSOL_INVALID; | ||
1051 | handled = 1; | ||
1052 | } | ||
1053 | return handled; | ||
1054 | } | ||
1055 | |||
1056 | /** | ||
1016 | * lpfc_bsg_hba_set_event - process a SET_EVENT bsg vendor command | 1057 | * lpfc_bsg_hba_set_event - process a SET_EVENT bsg vendor command |
1017 | * @job: SET_EVENT fc_bsg_job | 1058 | * @job: SET_EVENT fc_bsg_job |
1018 | **/ | 1059 | **/ |
@@ -1318,7 +1359,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag, | |||
1318 | icmd->ulpClass = CLASS3; | 1359 | icmd->ulpClass = CLASS3; |
1319 | if (phba->sli_rev == LPFC_SLI_REV4) { | 1360 | if (phba->sli_rev == LPFC_SLI_REV4) { |
1320 | /* Do not issue unsol response if oxid not marked as valid */ | 1361 | /* Do not issue unsol response if oxid not marked as valid */ |
1321 | if (!(phba->ct_ctx[tag].flags & UNSOL_VALID)) { | 1362 | if (phba->ct_ctx[tag].valid != UNSOL_VALID) { |
1322 | rc = IOCB_ERROR; | 1363 | rc = IOCB_ERROR; |
1323 | goto issue_ct_rsp_exit; | 1364 | goto issue_ct_rsp_exit; |
1324 | } | 1365 | } |
@@ -1352,7 +1393,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag, | |||
1352 | phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | 1393 | phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; |
1353 | 1394 | ||
1354 | /* The exchange is done, mark the entry as invalid */ | 1395 | /* The exchange is done, mark the entry as invalid */ |
1355 | phba->ct_ctx[tag].flags &= ~UNSOL_VALID; | 1396 | phba->ct_ctx[tag].valid = UNSOL_INVALID; |
1356 | } else | 1397 | } else |
1357 | icmd->ulpContext = (ushort) tag; | 1398 | icmd->ulpContext = (ushort) tag; |
1358 | 1399 | ||
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 69d66e3662cb..76ca65dae781 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -164,8 +164,7 @@ void lpfc_hb_timeout_handler(struct lpfc_hba *); | |||
164 | 164 | ||
165 | void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, | 165 | void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, |
166 | struct lpfc_iocbq *); | 166 | struct lpfc_iocbq *); |
167 | void lpfc_sli4_ct_abort_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, | 167 | int lpfc_ct_handle_unsol_abort(struct lpfc_hba *, struct hbq_dmabuf *); |
168 | struct lpfc_iocbq *); | ||
169 | int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t); | 168 | int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t); |
170 | int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int); | 169 | int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int); |
171 | void lpfc_fdmi_tmo(unsigned long); | 170 | void lpfc_fdmi_tmo(unsigned long); |
@@ -427,6 +426,7 @@ int lpfc_bsg_request(struct fc_bsg_job *); | |||
427 | int lpfc_bsg_timeout(struct fc_bsg_job *); | 426 | int lpfc_bsg_timeout(struct fc_bsg_job *); |
428 | int lpfc_bsg_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, | 427 | int lpfc_bsg_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, |
429 | struct lpfc_iocbq *); | 428 | struct lpfc_iocbq *); |
429 | int lpfc_bsg_ct_unsol_abort(struct lpfc_hba *, struct hbq_dmabuf *); | ||
430 | void __lpfc_sli_ringtx_put(struct lpfc_hba *, struct lpfc_sli_ring *, | 430 | void __lpfc_sli_ringtx_put(struct lpfc_hba *, struct lpfc_sli_ring *, |
431 | struct lpfc_iocbq *); | 431 | struct lpfc_iocbq *); |
432 | struct lpfc_iocbq *lpfc_sli_ringtx_get(struct lpfc_hba *, | 432 | struct lpfc_iocbq *lpfc_sli_ringtx_get(struct lpfc_hba *, |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 65f9fb6862e6..7bff3a19af56 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -164,37 +164,24 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
164 | } | 164 | } |
165 | 165 | ||
166 | /** | 166 | /** |
167 | * lpfc_sli4_ct_abort_unsol_event - Default handle for sli4 unsol abort | 167 | * lpfc_ct_handle_unsol_abort - ct upper level protocol abort handler |
168 | * @phba: Pointer to HBA context object. | 168 | * @phba: Pointer to HBA context object. |
169 | * @pring: Pointer to the driver internal I/O ring. | 169 | * @dmabuf: pointer to a dmabuf that describes the FC sequence |
170 | * @piocbq: Pointer to the IOCBQ. | ||
171 | * | 170 | * |
172 | * This function serves as the default handler for the sli4 unsolicited | 171 | * This function serves as the upper level protocol abort handler for CT |
173 | * abort event. It shall be invoked when there is no application interface | 172 | * protocol. |
174 | * registered unsolicited abort handler. This handler does nothing but | 173 | * |
175 | * just simply releases the dma buffer used by the unsol abort event. | 174 | * Return 1 if abort has been handled, 0 otherwise. |
176 | **/ | 175 | **/ |
177 | void | 176 | int |
178 | lpfc_sli4_ct_abort_unsol_event(struct lpfc_hba *phba, | 177 | lpfc_ct_handle_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf) |
179 | struct lpfc_sli_ring *pring, | ||
180 | struct lpfc_iocbq *piocbq) | ||
181 | { | 178 | { |
182 | IOCB_t *icmd = &piocbq->iocb; | 179 | int handled; |
183 | struct lpfc_dmabuf *bdeBuf; | ||
184 | uint32_t size; | ||
185 | 180 | ||
186 | /* Forward abort event to any process registered to receive ct event */ | 181 | /* CT upper level goes through BSG */ |
187 | if (lpfc_bsg_ct_unsol_event(phba, pring, piocbq) == 0) | 182 | handled = lpfc_bsg_ct_unsol_abort(phba, dmabuf); |
188 | return; | ||
189 | 183 | ||
190 | /* If there is no BDE associated with IOCB, there is nothing to do */ | 184 | return handled; |
191 | if (icmd->ulpBdeCount == 0) | ||
192 | return; | ||
193 | bdeBuf = piocbq->context2; | ||
194 | piocbq->context2 = NULL; | ||
195 | size = icmd->un.cont64[0].tus.f.bdeSize; | ||
196 | lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf, size); | ||
197 | lpfc_in_buf_free(phba, bdeBuf); | ||
198 | } | 185 | } |
199 | 186 | ||
200 | static void | 187 | static void |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 624eab370396..bf32da9cfe84 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -8855,12 +8855,6 @@ lpfc_sli_setup(struct lpfc_hba *phba) | |||
8855 | pring->prt[3].type = FC_TYPE_CT; | 8855 | pring->prt[3].type = FC_TYPE_CT; |
8856 | pring->prt[3].lpfc_sli_rcv_unsol_event = | 8856 | pring->prt[3].lpfc_sli_rcv_unsol_event = |
8857 | lpfc_ct_unsol_event; | 8857 | lpfc_ct_unsol_event; |
8858 | /* abort unsolicited sequence */ | ||
8859 | pring->prt[4].profile = 0; /* Mask 4 */ | ||
8860 | pring->prt[4].rctl = FC_RCTL_BA_ABTS; | ||
8861 | pring->prt[4].type = FC_TYPE_BLS; | ||
8862 | pring->prt[4].lpfc_sli_rcv_unsol_event = | ||
8863 | lpfc_sli4_ct_abort_unsol_event; | ||
8864 | break; | 8858 | break; |
8865 | } | 8859 | } |
8866 | totiocbsize += (pring->sli.sli3.numCiocb * | 8860 | totiocbsize += (pring->sli.sli3.numCiocb * |
@@ -14063,6 +14057,40 @@ lpfc_sli4_abort_partial_seq(struct lpfc_vport *vport, | |||
14063 | } | 14057 | } |
14064 | 14058 | ||
14065 | /** | 14059 | /** |
14060 | * lpfc_sli4_abort_ulp_seq - Abort assembled unsol sequence from ulp | ||
14061 | * @vport: pointer to a vitural port | ||
14062 | * @dmabuf: pointer to a dmabuf that describes the FC sequence | ||
14063 | * | ||
14064 | * This function tries to abort from the assembed sequence from upper level | ||
14065 | * protocol, described by the information from basic abbort @dmabuf. It | ||
14066 | * checks to see whether such pending context exists at upper level protocol. | ||
14067 | * If so, it shall clean up the pending context. | ||
14068 | * | ||
14069 | * Return | ||
14070 | * true -- if there is matching pending context of the sequence cleaned | ||
14071 | * at ulp; | ||
14072 | * false -- if there is no matching pending context of the sequence present | ||
14073 | * at ulp. | ||
14074 | **/ | ||
14075 | static bool | ||
14076 | lpfc_sli4_abort_ulp_seq(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) | ||
14077 | { | ||
14078 | struct lpfc_hba *phba = vport->phba; | ||
14079 | int handled; | ||
14080 | |||
14081 | /* Accepting abort at ulp with SLI4 only */ | ||
14082 | if (phba->sli_rev < LPFC_SLI_REV4) | ||
14083 | return false; | ||
14084 | |||
14085 | /* Register all caring upper level protocols to attend abort */ | ||
14086 | handled = lpfc_ct_handle_unsol_abort(phba, dmabuf); | ||
14087 | if (handled) | ||
14088 | return true; | ||
14089 | |||
14090 | return false; | ||
14091 | } | ||
14092 | |||
14093 | /** | ||
14066 | * lpfc_sli4_seq_abort_rsp_cmpl - BLS ABORT RSP seq abort iocb complete handler | 14094 | * lpfc_sli4_seq_abort_rsp_cmpl - BLS ABORT RSP seq abort iocb complete handler |
14067 | * @phba: Pointer to HBA context object. | 14095 | * @phba: Pointer to HBA context object. |
14068 | * @cmd_iocbq: pointer to the command iocbq structure. | 14096 | * @cmd_iocbq: pointer to the command iocbq structure. |
@@ -14077,8 +14105,14 @@ lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba, | |||
14077 | struct lpfc_iocbq *cmd_iocbq, | 14105 | struct lpfc_iocbq *cmd_iocbq, |
14078 | struct lpfc_iocbq *rsp_iocbq) | 14106 | struct lpfc_iocbq *rsp_iocbq) |
14079 | { | 14107 | { |
14080 | if (cmd_iocbq) | 14108 | struct lpfc_nodelist *ndlp; |
14109 | |||
14110 | if (cmd_iocbq) { | ||
14111 | ndlp = (struct lpfc_nodelist *)cmd_iocbq->context1; | ||
14112 | lpfc_nlp_put(ndlp); | ||
14113 | lpfc_nlp_not_used(ndlp); | ||
14081 | lpfc_sli_release_iocbq(phba, cmd_iocbq); | 14114 | lpfc_sli_release_iocbq(phba, cmd_iocbq); |
14115 | } | ||
14082 | 14116 | ||
14083 | /* Failure means BLS ABORT RSP did not get delivered to remote node*/ | 14117 | /* Failure means BLS ABORT RSP did not get delivered to remote node*/ |
14084 | if (rsp_iocbq && rsp_iocbq->iocb.ulpStatus) | 14118 | if (rsp_iocbq && rsp_iocbq->iocb.ulpStatus) |
@@ -14118,9 +14152,10 @@ lpfc_sli4_xri_inrange(struct lpfc_hba *phba, | |||
14118 | * event after aborting the sequence handling. | 14152 | * event after aborting the sequence handling. |
14119 | **/ | 14153 | **/ |
14120 | static void | 14154 | static void |
14121 | lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, | 14155 | lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, |
14122 | struct fc_frame_header *fc_hdr) | 14156 | struct fc_frame_header *fc_hdr, bool aborted) |
14123 | { | 14157 | { |
14158 | struct lpfc_hba *phba = vport->phba; | ||
14124 | struct lpfc_iocbq *ctiocb = NULL; | 14159 | struct lpfc_iocbq *ctiocb = NULL; |
14125 | struct lpfc_nodelist *ndlp; | 14160 | struct lpfc_nodelist *ndlp; |
14126 | uint16_t oxid, rxid, xri, lxri; | 14161 | uint16_t oxid, rxid, xri, lxri; |
@@ -14135,12 +14170,27 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, | |||
14135 | oxid = be16_to_cpu(fc_hdr->fh_ox_id); | 14170 | oxid = be16_to_cpu(fc_hdr->fh_ox_id); |
14136 | rxid = be16_to_cpu(fc_hdr->fh_rx_id); | 14171 | rxid = be16_to_cpu(fc_hdr->fh_rx_id); |
14137 | 14172 | ||
14138 | ndlp = lpfc_findnode_did(phba->pport, sid); | 14173 | ndlp = lpfc_findnode_did(vport, sid); |
14139 | if (!ndlp) { | 14174 | if (!ndlp) { |
14140 | lpfc_printf_log(phba, KERN_WARNING, LOG_ELS, | 14175 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
14141 | "1268 Find ndlp returned NULL for oxid:x%x " | 14176 | if (!ndlp) { |
14142 | "SID:x%x\n", oxid, sid); | 14177 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, |
14143 | return; | 14178 | "1268 Failed to allocate ndlp for " |
14179 | "oxid:x%x SID:x%x\n", oxid, sid); | ||
14180 | return; | ||
14181 | } | ||
14182 | lpfc_nlp_init(vport, ndlp, sid); | ||
14183 | /* Put ndlp onto pport node list */ | ||
14184 | lpfc_enqueue_node(vport, ndlp); | ||
14185 | } else if (!NLP_CHK_NODE_ACT(ndlp)) { | ||
14186 | /* re-setup ndlp without removing from node list */ | ||
14187 | ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
14188 | if (!ndlp) { | ||
14189 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, | ||
14190 | "3275 Failed to active ndlp found " | ||
14191 | "for oxid:x%x SID:x%x\n", oxid, sid); | ||
14192 | return; | ||
14193 | } | ||
14144 | } | 14194 | } |
14145 | 14195 | ||
14146 | /* Allocate buffer for rsp iocb */ | 14196 | /* Allocate buffer for rsp iocb */ |
@@ -14164,7 +14214,7 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, | |||
14164 | icmd->ulpLe = 1; | 14214 | icmd->ulpLe = 1; |
14165 | icmd->ulpClass = CLASS3; | 14215 | icmd->ulpClass = CLASS3; |
14166 | icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | 14216 | icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; |
14167 | ctiocb->context1 = ndlp; | 14217 | ctiocb->context1 = lpfc_nlp_get(ndlp); |
14168 | 14218 | ||
14169 | ctiocb->iocb_cmpl = NULL; | 14219 | ctiocb->iocb_cmpl = NULL; |
14170 | ctiocb->vport = phba->pport; | 14220 | ctiocb->vport = phba->pport; |
@@ -14183,14 +14233,24 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, | |||
14183 | if (lxri != NO_XRI) | 14233 | if (lxri != NO_XRI) |
14184 | lpfc_set_rrq_active(phba, ndlp, lxri, | 14234 | lpfc_set_rrq_active(phba, ndlp, lxri, |
14185 | (xri == oxid) ? rxid : oxid, 0); | 14235 | (xri == oxid) ? rxid : oxid, 0); |
14186 | /* If the oxid maps to the FCP XRI range or if it is out of range, | 14236 | /* For BA_ABTS from exchange responder, if the logical xri with |
14187 | * send a BLS_RJT. The driver no longer has that exchange. | 14237 | * the oxid maps to the FCP XRI range, the port no longer has |
14188 | * Override the IOCB for a BA_RJT. | 14238 | * that exchange context, send a BLS_RJT. Override the IOCB for |
14239 | * a BA_RJT. | ||
14240 | */ | ||
14241 | if ((fctl & FC_FC_EX_CTX) && | ||
14242 | (lxri > lpfc_sli4_get_els_iocb_cnt(phba))) { | ||
14243 | icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT; | ||
14244 | bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0); | ||
14245 | bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID); | ||
14246 | bf_set(lpfc_rsn_code, &icmd->un.bls_rsp, FC_BA_RJT_UNABLE); | ||
14247 | } | ||
14248 | |||
14249 | /* If BA_ABTS failed to abort a partially assembled receive sequence, | ||
14250 | * the driver no longer has that exchange, send a BLS_RJT. Override | ||
14251 | * the IOCB for a BA_RJT. | ||
14189 | */ | 14252 | */ |
14190 | if (xri > (phba->sli4_hba.max_cfg_param.max_xri + | 14253 | if (aborted == false) { |
14191 | phba->sli4_hba.max_cfg_param.xri_base) || | ||
14192 | xri > (lpfc_sli4_get_els_iocb_cnt(phba) + | ||
14193 | phba->sli4_hba.max_cfg_param.xri_base)) { | ||
14194 | icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT; | 14254 | icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT; |
14195 | bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0); | 14255 | bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0); |
14196 | bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID); | 14256 | bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID); |
@@ -14214,17 +14274,19 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, | |||
14214 | bf_set(lpfc_abts_oxid, &icmd->un.bls_rsp, oxid); | 14274 | bf_set(lpfc_abts_oxid, &icmd->un.bls_rsp, oxid); |
14215 | 14275 | ||
14216 | /* Xmit CT abts response on exchange <xid> */ | 14276 | /* Xmit CT abts response on exchange <xid> */ |
14217 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 14277 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
14218 | "1200 Send BLS cmd x%x on oxid x%x Data: x%x\n", | 14278 | "1200 Send BLS cmd x%x on oxid x%x Data: x%x\n", |
14219 | icmd->un.xseq64.w5.hcsw.Rctl, oxid, phba->link_state); | 14279 | icmd->un.xseq64.w5.hcsw.Rctl, oxid, phba->link_state); |
14220 | 14280 | ||
14221 | rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0); | 14281 | rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0); |
14222 | if (rc == IOCB_ERROR) { | 14282 | if (rc == IOCB_ERROR) { |
14223 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | 14283 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
14224 | "2925 Failed to issue CT ABTS RSP x%x on " | 14284 | "2925 Failed to issue CT ABTS RSP x%x on " |
14225 | "xri x%x, Data x%x\n", | 14285 | "xri x%x, Data x%x\n", |
14226 | icmd->un.xseq64.w5.hcsw.Rctl, oxid, | 14286 | icmd->un.xseq64.w5.hcsw.Rctl, oxid, |
14227 | phba->link_state); | 14287 | phba->link_state); |
14288 | lpfc_nlp_put(ndlp); | ||
14289 | ctiocb->context1 = NULL; | ||
14228 | lpfc_sli_release_iocbq(phba, ctiocb); | 14290 | lpfc_sli_release_iocbq(phba, ctiocb); |
14229 | } | 14291 | } |
14230 | } | 14292 | } |
@@ -14249,32 +14311,25 @@ lpfc_sli4_handle_unsol_abort(struct lpfc_vport *vport, | |||
14249 | struct lpfc_hba *phba = vport->phba; | 14311 | struct lpfc_hba *phba = vport->phba; |
14250 | struct fc_frame_header fc_hdr; | 14312 | struct fc_frame_header fc_hdr; |
14251 | uint32_t fctl; | 14313 | uint32_t fctl; |
14252 | bool abts_par; | 14314 | bool aborted; |
14253 | 14315 | ||
14254 | /* Make a copy of fc_hdr before the dmabuf being released */ | 14316 | /* Make a copy of fc_hdr before the dmabuf being released */ |
14255 | memcpy(&fc_hdr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header)); | 14317 | memcpy(&fc_hdr, dmabuf->hbuf.virt, sizeof(struct fc_frame_header)); |
14256 | fctl = sli4_fctl_from_fc_hdr(&fc_hdr); | 14318 | fctl = sli4_fctl_from_fc_hdr(&fc_hdr); |
14257 | 14319 | ||
14258 | if (fctl & FC_FC_EX_CTX) { | 14320 | if (fctl & FC_FC_EX_CTX) { |
14259 | /* | 14321 | /* ABTS by responder to exchange, no cleanup needed */ |
14260 | * ABTS sent by responder to exchange, just free the buffer | 14322 | aborted = true; |
14261 | */ | ||
14262 | lpfc_in_buf_free(phba, &dmabuf->dbuf); | ||
14263 | } else { | 14323 | } else { |
14264 | /* | 14324 | /* ABTS by initiator to exchange, need to do cleanup */ |
14265 | * ABTS sent by initiator to exchange, need to do cleanup | 14325 | aborted = lpfc_sli4_abort_partial_seq(vport, dmabuf); |
14266 | */ | 14326 | if (aborted == false) |
14267 | /* Try to abort partially assembled seq */ | 14327 | aborted = lpfc_sli4_abort_ulp_seq(vport, dmabuf); |
14268 | abts_par = lpfc_sli4_abort_partial_seq(vport, dmabuf); | ||
14269 | |||
14270 | /* Send abort to ULP if partially seq abort failed */ | ||
14271 | if (abts_par == false) | ||
14272 | lpfc_sli4_send_seq_to_ulp(vport, dmabuf); | ||
14273 | else | ||
14274 | lpfc_in_buf_free(phba, &dmabuf->dbuf); | ||
14275 | } | 14328 | } |
14276 | /* Send basic accept (BA_ACC) to the abort requester */ | 14329 | lpfc_in_buf_free(phba, &dmabuf->dbuf); |
14277 | lpfc_sli4_seq_abort_rsp(phba, &fc_hdr); | 14330 | |
14331 | /* Respond with BA_ACC or BA_RJT accordingly */ | ||
14332 | lpfc_sli4_seq_abort_rsp(vport, &fc_hdr, aborted); | ||
14278 | } | 14333 | } |
14279 | 14334 | ||
14280 | /** | 14335 | /** |