|
@@ -4339,6 +4339,11 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
|
|
|
phba->sli.sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK;
|
|
|
spin_unlock_irq(&phba->hbalock);
|
|
|
done = 1;
|
|
|
+
|
|
|
+ if ((pmb->u.mb.un.varCfgPort.casabt == 1) &&
|
|
|
+ (pmb->u.mb.un.varCfgPort.gasabt == 0))
|
|
|
+ lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
|
|
|
+ "3110 Port did not grant ASABT\n");
|
|
|
}
|
|
|
}
|
|
|
if (!done) {
|
|
@@ -7704,6 +7709,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
|
|
iocbq->context2)->virt);
|
|
|
if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
|
|
|
if (pcmd && (*pcmd == ELS_CMD_FLOGI ||
|
|
|
+ *pcmd == ELS_CMD_SCR ||
|
|
|
*pcmd == ELS_CMD_PLOGI)) {
|
|
|
bf_set(els_req64_sp, &wqe->els_req, 1);
|
|
|
bf_set(els_req64_sid, &wqe->els_req,
|
|
@@ -8213,6 +8219,137 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/* lpfc_sli_abts_recover_port - Recover a port that failed an ABTS.
|
|
|
+ * @vport: pointer to virtual port object.
|
|
|
+ * @ndlp: nodelist pointer for the impacted rport.
|
|
|
+ *
|
|
|
+ * The driver calls this routine in response to a XRI ABORT CQE
|
|
|
+ * event from the port. In this event, the driver is required to
|
|
|
+ * recover its login to the rport even though its login may be valid
|
|
|
+ * from the driver's perspective. The failed ABTS notice from the
|
|
|
+ * port indicates the rport is not responding.
|
|
|
+ */
|
|
|
+static void
|
|
|
+lpfc_sli_abts_recover_port(struct lpfc_vport *vport,
|
|
|
+ struct lpfc_nodelist *ndlp)
|
|
|
+{
|
|
|
+ struct Scsi_Host *shost;
|
|
|
+ struct lpfc_hba *phba;
|
|
|
+ unsigned long flags = 0;
|
|
|
+
|
|
|
+ shost = lpfc_shost_from_vport(vport);
|
|
|
+ phba = vport->phba;
|
|
|
+ if (ndlp->nlp_state != NLP_STE_MAPPED_NODE) {
|
|
|
+ lpfc_printf_log(phba, KERN_INFO,
|
|
|
+ LOG_SLI, "3093 No rport recovery needed. "
|
|
|
+ "rport in state 0x%x\n",
|
|
|
+ ndlp->nlp_state);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
|
|
+ "3094 Start rport recovery on shost id 0x%x "
|
|
|
+ "fc_id 0x%06x vpi 0x%x rpi 0x%x state 0x%x "
|
|
|
+ "flags 0x%x\n",
|
|
|
+ shost->host_no, ndlp->nlp_DID,
|
|
|
+ vport->vpi, ndlp->nlp_rpi, ndlp->nlp_state,
|
|
|
+ ndlp->nlp_flag);
|
|
|
+ /*
|
|
|
+ * The rport is not responding. Don't attempt ADISC recovery.
|
|
|
+ * Remove the FCP-2 flag to force a PLOGI.
|
|
|
+ */
|
|
|
+ spin_lock_irqsave(shost->host_lock, flags);
|
|
|
+ ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
|
|
|
+ spin_unlock_irqrestore(shost->host_lock, flags);
|
|
|
+ lpfc_disc_state_machine(vport, ndlp, NULL,
|
|
|
+ NLP_EVT_DEVICE_RECOVERY);
|
|
|
+ lpfc_cancel_retry_delay_tmo(vport, ndlp);
|
|
|
+ spin_lock_irqsave(shost->host_lock, flags);
|
|
|
+ ndlp->nlp_flag |= NLP_NPR_2B_DISC;
|
|
|
+ spin_unlock_irqrestore(shost->host_lock, flags);
|
|
|
+ lpfc_disc_start(vport);
|
|
|
+}
|
|
|
+
|
|
|
+/* lpfc_sli_abts_err_handler - handle a failed ABTS request from an SLI3 port.
|
|
|
+ * @phba: Pointer to HBA context object.
|
|
|
+ * @iocbq: Pointer to iocb object.
|
|
|
+ *
|
|
|
+ * The async_event handler calls this routine when it receives
|
|
|
+ * an ASYNC_STATUS_CN event from the port. The port generates
|
|
|
+ * this event when an Abort Sequence request to an rport fails
|
|
|
+ * twice in succession. The abort could be originated by the
|
|
|
+ * driver or by the port. The ABTS could have been for an ELS
|
|
|
+ * or FCP IO. The port only generates this event when an ABTS
|
|
|
+ * fails to complete after one retry.
|
|
|
+ */
|
|
|
+static void
|
|
|
+lpfc_sli_abts_err_handler(struct lpfc_hba *phba,
|
|
|
+ struct lpfc_iocbq *iocbq)
|
|
|
+{
|
|
|
+ struct lpfc_nodelist *ndlp = NULL;
|
|
|
+ uint16_t rpi = 0, vpi = 0;
|
|
|
+ struct lpfc_vport *vport = NULL;
|
|
|
+
|
|
|
+ /* The rpi in the ulpContext is vport-sensitive. */
|
|
|
+ vpi = iocbq->iocb.un.asyncstat.sub_ctxt_tag;
|
|
|
+ rpi = iocbq->iocb.ulpContext;
|
|
|
+
|
|
|
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
|
|
|
+ "3092 Port generated ABTS async event "
|
|
|
+ "on vpi %d rpi %d status 0x%x\n",
|
|
|
+ vpi, rpi, iocbq->iocb.ulpStatus);
|
|
|
+
|
|
|
+ vport = lpfc_find_vport_by_vpid(phba, vpi);
|
|
|
+ if (!vport)
|
|
|
+ goto err_exit;
|
|
|
+ ndlp = lpfc_findnode_rpi(vport, rpi);
|
|
|
+ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
|
|
|
+ goto err_exit;
|
|
|
+
|
|
|
+ if (iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT)
|
|
|
+ lpfc_sli_abts_recover_port(vport, ndlp);
|
|
|
+ return;
|
|
|
+
|
|
|
+ err_exit:
|
|
|
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
|
|
+ "3095 Event Context not found, no "
|
|
|
+ "action on vpi %d rpi %d status 0x%x, reason 0x%x\n",
|
|
|
+ iocbq->iocb.ulpContext, iocbq->iocb.ulpStatus,
|
|
|
+ vpi, rpi);
|
|
|
+}
|
|
|
+
|
|
|
+/* lpfc_sli4_abts_err_handler - handle a failed ABTS request from an SLI4 port.
|
|
|
+ * @phba: pointer to HBA context object.
|
|
|
+ * @ndlp: nodelist pointer for the impacted rport.
|
|
|
+ * @axri: pointer to the wcqe containing the failed exchange.
|
|
|
+ *
|
|
|
+ * The driver calls this routine when it receives an ABORT_XRI_FCP CQE from the
|
|
|
+ * port. The port generates this event when an abort exchange request to an
|
|
|
+ * rport fails twice in succession with no reply. The abort could be originated
|
|
|
+ * by the driver or by the port. The ABTS could have been for an ELS or FCP IO.
|
|
|
+ */
|
|
|
+void
|
|
|
+lpfc_sli4_abts_err_handler(struct lpfc_hba *phba,
|
|
|
+ struct lpfc_nodelist *ndlp,
|
|
|
+ struct sli4_wcqe_xri_aborted *axri)
|
|
|
+{
|
|
|
+ struct lpfc_vport *vport;
|
|
|
+
|
|
|
+ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
|
|
|
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
|
|
+ "3115 Node Context not found, driver "
|
|
|
+ "ignoring abts err event\n");
|
|
|
+ vport = ndlp->vport;
|
|
|
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
|
|
|
+ "3116 Port generated FCP XRI ABORT event on "
|
|
|
+ "vpi %d rpi %d xri x%x status 0x%x\n",
|
|
|
+ ndlp->vport->vpi, ndlp->nlp_rpi,
|
|
|
+ bf_get(lpfc_wcqe_xa_xri, axri),
|
|
|
+ bf_get(lpfc_wcqe_xa_status, axri));
|
|
|
+
|
|
|
+ if (bf_get(lpfc_wcqe_xa_status, axri) == IOSTAT_LOCAL_REJECT)
|
|
|
+ lpfc_sli_abts_recover_port(vport, ndlp);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* lpfc_sli_async_event_handler - ASYNC iocb handler function
|
|
|
* @phba: Pointer to HBA context object.
|
|
@@ -8232,63 +8369,58 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba,
|
|
|
{
|
|
|
IOCB_t *icmd;
|
|
|
uint16_t evt_code;
|
|
|
- uint16_t temp;
|
|
|
struct temp_event temp_event_data;
|
|
|
struct Scsi_Host *shost;
|
|
|
uint32_t *iocb_w;
|
|
|
|
|
|
icmd = &iocbq->iocb;
|
|
|
evt_code = icmd->un.asyncstat.evt_code;
|
|
|
- temp = icmd->ulpContext;
|
|
|
|
|
|
- if ((evt_code != ASYNC_TEMP_WARN) &&
|
|
|
- (evt_code != ASYNC_TEMP_SAFE)) {
|
|
|
+ switch (evt_code) {
|
|
|
+ case ASYNC_TEMP_WARN:
|
|
|
+ case ASYNC_TEMP_SAFE:
|
|
|
+ temp_event_data.data = (uint32_t) icmd->ulpContext;
|
|
|
+ temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT;
|
|
|
+ if (evt_code == ASYNC_TEMP_WARN) {
|
|
|
+ temp_event_data.event_code = LPFC_THRESHOLD_TEMP;
|
|
|
+ lpfc_printf_log(phba, KERN_ERR, LOG_TEMP,
|
|
|
+ "0347 Adapter is very hot, please take "
|
|
|
+ "corrective action. temperature : %d Celsius\n",
|
|
|
+ (uint32_t) icmd->ulpContext);
|
|
|
+ } else {
|
|
|
+ temp_event_data.event_code = LPFC_NORMAL_TEMP;
|
|
|
+ lpfc_printf_log(phba, KERN_ERR, LOG_TEMP,
|
|
|
+ "0340 Adapter temperature is OK now. "
|
|
|
+ "temperature : %d Celsius\n",
|
|
|
+ (uint32_t) icmd->ulpContext);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Send temperature change event to applications */
|
|
|
+ shost = lpfc_shost_from_vport(phba->pport);
|
|
|
+ fc_host_post_vendor_event(shost, fc_get_event_number(),
|
|
|
+ sizeof(temp_event_data), (char *) &temp_event_data,
|
|
|
+ LPFC_NL_VENDOR_ID);
|
|
|
+ break;
|
|
|
+ case ASYNC_STATUS_CN:
|
|
|
+ lpfc_sli_abts_err_handler(phba, iocbq);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
iocb_w = (uint32_t *) icmd;
|
|
|
- lpfc_printf_log(phba,
|
|
|
- KERN_ERR,
|
|
|
- LOG_SLI,
|
|
|
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
|
|
"0346 Ring %d handler: unexpected ASYNC_STATUS"
|
|
|
" evt_code 0x%x\n"
|
|
|
"W0 0x%08x W1 0x%08x W2 0x%08x W3 0x%08x\n"
|
|
|
"W4 0x%08x W5 0x%08x W6 0x%08x W7 0x%08x\n"
|
|
|
"W8 0x%08x W9 0x%08x W10 0x%08x W11 0x%08x\n"
|
|
|
"W12 0x%08x W13 0x%08x W14 0x%08x W15 0x%08x\n",
|
|
|
- pring->ringno,
|
|
|
- icmd->un.asyncstat.evt_code,
|
|
|
+ pring->ringno, icmd->un.asyncstat.evt_code,
|
|
|
iocb_w[0], iocb_w[1], iocb_w[2], iocb_w[3],
|
|
|
iocb_w[4], iocb_w[5], iocb_w[6], iocb_w[7],
|
|
|
iocb_w[8], iocb_w[9], iocb_w[10], iocb_w[11],
|
|
|
iocb_w[12], iocb_w[13], iocb_w[14], iocb_w[15]);
|
|
|
|
|
|
- return;
|
|
|
- }
|
|
|
- temp_event_data.data = (uint32_t)temp;
|
|
|
- temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT;
|
|
|
- if (evt_code == ASYNC_TEMP_WARN) {
|
|
|
- temp_event_data.event_code = LPFC_THRESHOLD_TEMP;
|
|
|
- lpfc_printf_log(phba,
|
|
|
- KERN_ERR,
|
|
|
- LOG_TEMP,
|
|
|
- "0347 Adapter is very hot, please take "
|
|
|
- "corrective action. temperature : %d Celsius\n",
|
|
|
- temp);
|
|
|
- }
|
|
|
- if (evt_code == ASYNC_TEMP_SAFE) {
|
|
|
- temp_event_data.event_code = LPFC_NORMAL_TEMP;
|
|
|
- lpfc_printf_log(phba,
|
|
|
- KERN_ERR,
|
|
|
- LOG_TEMP,
|
|
|
- "0340 Adapter temperature is OK now. "
|
|
|
- "temperature : %d Celsius\n",
|
|
|
- temp);
|
|
|
+ break;
|
|
|
}
|
|
|
-
|
|
|
- /* Send temperature change event to applications */
|
|
|
- shost = lpfc_shost_from_vport(phba->pport);
|
|
|
- fc_host_post_vendor_event(shost, fc_get_event_number(),
|
|
|
- sizeof(temp_event_data), (char *) &temp_event_data,
|
|
|
- LPFC_NL_VENDOR_ID);
|
|
|
-
|
|
|
}
|
|
|
|
|
|
|
|
@@ -9247,6 +9379,14 @@ void
|
|
|
lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|
|
struct lpfc_iocbq *rspiocb)
|
|
|
{
|
|
|
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
|
|
+ "3096 ABORT_XRI_CN completing on xri x%x "
|
|
|
+ "original iotag x%x, abort cmd iotag x%x "
|
|
|
+ "status 0x%x, reason 0x%x\n",
|
|
|
+ cmdiocb->iocb.un.acxri.abortContextTag,
|
|
|
+ cmdiocb->iocb.un.acxri.abortIoTag,
|
|
|
+ cmdiocb->iotag, rspiocb->iocb.ulpStatus,
|
|
|
+ rspiocb->iocb.un.ulpWord[4]);
|
|
|
lpfc_sli_release_iocbq(phba, cmdiocb);
|
|
|
return;
|
|
|
}
|