aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2011-12-13 13:21:57 -0500
committerJames Bottomley <JBottomley@Parallels.com>2011-12-15 01:57:44 -0500
commitcb69f7decc3777822b240c46890a209df288c7bb (patch)
tree8ae647f9d3d50452fc0bc684a8b4108a4f94a65e /drivers/scsi/lpfc/lpfc_sli.c
parentff78d8f97c85a568c0799b06137a4171db45b923 (diff)
[SCSI] lpfc 8.3.28: Add support for ABTS failure handling
Add support for ABTS failure handling: - Add asynchronous ABTS notification event feature to driver (CR 124578) - Change driver message 3092 and 3116 to KERN_WARNING (CR 124768) - Alter the SCR ELS command to use the temporary RPI and the Destination DID for SLI4-FC (CR 126070) Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com> Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c214
1 files changed, 177 insertions, 37 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 4c4d77356bb2..97bbafb21bc2 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -4339,6 +4339,11 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
4339 phba->sli.sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK; 4339 phba->sli.sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK;
4340 spin_unlock_irq(&phba->hbalock); 4340 spin_unlock_irq(&phba->hbalock);
4341 done = 1; 4341 done = 1;
4342
4343 if ((pmb->u.mb.un.varCfgPort.casabt == 1) &&
4344 (pmb->u.mb.un.varCfgPort.gasabt == 0))
4345 lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
4346 "3110 Port did not grant ASABT\n");
4342 } 4347 }
4343 } 4348 }
4344 if (!done) { 4349 if (!done) {
@@ -7704,6 +7709,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
7704 iocbq->context2)->virt); 7709 iocbq->context2)->virt);
7705 if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { 7710 if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
7706 if (pcmd && (*pcmd == ELS_CMD_FLOGI || 7711 if (pcmd && (*pcmd == ELS_CMD_FLOGI ||
7712 *pcmd == ELS_CMD_SCR ||
7707 *pcmd == ELS_CMD_PLOGI)) { 7713 *pcmd == ELS_CMD_PLOGI)) {
7708 bf_set(els_req64_sp, &wqe->els_req, 1); 7714 bf_set(els_req64_sp, &wqe->els_req, 1);
7709 bf_set(els_req64_sid, &wqe->els_req, 7715 bf_set(els_req64_sid, &wqe->els_req,
@@ -8213,6 +8219,137 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba)
8213 return 0; 8219 return 0;
8214} 8220}
8215 8221
8222/* lpfc_sli_abts_recover_port - Recover a port that failed an ABTS.
8223 * @vport: pointer to virtual port object.
8224 * @ndlp: nodelist pointer for the impacted rport.
8225 *
8226 * The driver calls this routine in response to a XRI ABORT CQE
8227 * event from the port. In this event, the driver is required to
8228 * recover its login to the rport even though its login may be valid
8229 * from the driver's perspective. The failed ABTS notice from the
8230 * port indicates the rport is not responding.
8231 */
8232static void
8233lpfc_sli_abts_recover_port(struct lpfc_vport *vport,
8234 struct lpfc_nodelist *ndlp)
8235{
8236 struct Scsi_Host *shost;
8237 struct lpfc_hba *phba;
8238 unsigned long flags = 0;
8239
8240 shost = lpfc_shost_from_vport(vport);
8241 phba = vport->phba;
8242 if (ndlp->nlp_state != NLP_STE_MAPPED_NODE) {
8243 lpfc_printf_log(phba, KERN_INFO,
8244 LOG_SLI, "3093 No rport recovery needed. "
8245 "rport in state 0x%x\n",
8246 ndlp->nlp_state);
8247 return;
8248 }
8249 lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
8250 "3094 Start rport recovery on shost id 0x%x "
8251 "fc_id 0x%06x vpi 0x%x rpi 0x%x state 0x%x "
8252 "flags 0x%x\n",
8253 shost->host_no, ndlp->nlp_DID,
8254 vport->vpi, ndlp->nlp_rpi, ndlp->nlp_state,
8255 ndlp->nlp_flag);
8256 /*
8257 * The rport is not responding. Don't attempt ADISC recovery.
8258 * Remove the FCP-2 flag to force a PLOGI.
8259 */
8260 spin_lock_irqsave(shost->host_lock, flags);
8261 ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
8262 spin_unlock_irqrestore(shost->host_lock, flags);
8263 lpfc_disc_state_machine(vport, ndlp, NULL,
8264 NLP_EVT_DEVICE_RECOVERY);
8265 lpfc_cancel_retry_delay_tmo(vport, ndlp);
8266 spin_lock_irqsave(shost->host_lock, flags);
8267 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
8268 spin_unlock_irqrestore(shost->host_lock, flags);
8269 lpfc_disc_start(vport);
8270}
8271
8272/* lpfc_sli_abts_err_handler - handle a failed ABTS request from an SLI3 port.
8273 * @phba: Pointer to HBA context object.
8274 * @iocbq: Pointer to iocb object.
8275 *
8276 * The async_event handler calls this routine when it receives
8277 * an ASYNC_STATUS_CN event from the port. The port generates
8278 * this event when an Abort Sequence request to an rport fails
8279 * twice in succession. The abort could be originated by the
8280 * driver or by the port. The ABTS could have been for an ELS
8281 * or FCP IO. The port only generates this event when an ABTS
8282 * fails to complete after one retry.
8283 */
8284static void
8285lpfc_sli_abts_err_handler(struct lpfc_hba *phba,
8286 struct lpfc_iocbq *iocbq)
8287{
8288 struct lpfc_nodelist *ndlp = NULL;
8289 uint16_t rpi = 0, vpi = 0;
8290 struct lpfc_vport *vport = NULL;
8291
8292 /* The rpi in the ulpContext is vport-sensitive. */
8293 vpi = iocbq->iocb.un.asyncstat.sub_ctxt_tag;
8294 rpi = iocbq->iocb.ulpContext;
8295
8296 lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
8297 "3092 Port generated ABTS async event "
8298 "on vpi %d rpi %d status 0x%x\n",
8299 vpi, rpi, iocbq->iocb.ulpStatus);
8300
8301 vport = lpfc_find_vport_by_vpid(phba, vpi);
8302 if (!vport)
8303 goto err_exit;
8304 ndlp = lpfc_findnode_rpi(vport, rpi);
8305 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
8306 goto err_exit;
8307
8308 if (iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT)
8309 lpfc_sli_abts_recover_port(vport, ndlp);
8310 return;
8311
8312 err_exit:
8313 lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
8314 "3095 Event Context not found, no "
8315 "action on vpi %d rpi %d status 0x%x, reason 0x%x\n",
8316 iocbq->iocb.ulpContext, iocbq->iocb.ulpStatus,
8317 vpi, rpi);
8318}
8319
8320/* lpfc_sli4_abts_err_handler - handle a failed ABTS request from an SLI4 port.
8321 * @phba: pointer to HBA context object.
8322 * @ndlp: nodelist pointer for the impacted rport.
8323 * @axri: pointer to the wcqe containing the failed exchange.
8324 *
8325 * The driver calls this routine when it receives an ABORT_XRI_FCP CQE from the
8326 * port. The port generates this event when an abort exchange request to an
8327 * rport fails twice in succession with no reply. The abort could be originated
8328 * by the driver or by the port. The ABTS could have been for an ELS or FCP IO.
8329 */
8330void
8331lpfc_sli4_abts_err_handler(struct lpfc_hba *phba,
8332 struct lpfc_nodelist *ndlp,
8333 struct sli4_wcqe_xri_aborted *axri)
8334{
8335 struct lpfc_vport *vport;
8336
8337 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
8338 lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
8339 "3115 Node Context not found, driver "
8340 "ignoring abts err event\n");
8341 vport = ndlp->vport;
8342 lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
8343 "3116 Port generated FCP XRI ABORT event on "
8344 "vpi %d rpi %d xri x%x status 0x%x\n",
8345 ndlp->vport->vpi, ndlp->nlp_rpi,
8346 bf_get(lpfc_wcqe_xa_xri, axri),
8347 bf_get(lpfc_wcqe_xa_status, axri));
8348
8349 if (bf_get(lpfc_wcqe_xa_status, axri) == IOSTAT_LOCAL_REJECT)
8350 lpfc_sli_abts_recover_port(vport, ndlp);
8351}
8352
8216/** 8353/**
8217 * lpfc_sli_async_event_handler - ASYNC iocb handler function 8354 * lpfc_sli_async_event_handler - ASYNC iocb handler function
8218 * @phba: Pointer to HBA context object. 8355 * @phba: Pointer to HBA context object.
@@ -8232,63 +8369,58 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba,
8232{ 8369{
8233 IOCB_t *icmd; 8370 IOCB_t *icmd;
8234 uint16_t evt_code; 8371 uint16_t evt_code;
8235 uint16_t temp;
8236 struct temp_event temp_event_data; 8372 struct temp_event temp_event_data;
8237 struct Scsi_Host *shost; 8373 struct Scsi_Host *shost;
8238 uint32_t *iocb_w; 8374 uint32_t *iocb_w;
8239 8375
8240 icmd = &iocbq->iocb; 8376 icmd = &iocbq->iocb;
8241 evt_code = icmd->un.asyncstat.evt_code; 8377 evt_code = icmd->un.asyncstat.evt_code;
8242 temp = icmd->ulpContext;
8243 8378
8244 if ((evt_code != ASYNC_TEMP_WARN) && 8379 switch (evt_code) {
8245 (evt_code != ASYNC_TEMP_SAFE)) { 8380 case ASYNC_TEMP_WARN:
8381 case ASYNC_TEMP_SAFE:
8382 temp_event_data.data = (uint32_t) icmd->ulpContext;
8383 temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT;
8384 if (evt_code == ASYNC_TEMP_WARN) {
8385 temp_event_data.event_code = LPFC_THRESHOLD_TEMP;
8386 lpfc_printf_log(phba, KERN_ERR, LOG_TEMP,
8387 "0347 Adapter is very hot, please take "
8388 "corrective action. temperature : %d Celsius\n",
8389 (uint32_t) icmd->ulpContext);
8390 } else {
8391 temp_event_data.event_code = LPFC_NORMAL_TEMP;
8392 lpfc_printf_log(phba, KERN_ERR, LOG_TEMP,
8393 "0340 Adapter temperature is OK now. "
8394 "temperature : %d Celsius\n",
8395 (uint32_t) icmd->ulpContext);
8396 }
8397
8398 /* Send temperature change event to applications */
8399 shost = lpfc_shost_from_vport(phba->pport);
8400 fc_host_post_vendor_event(shost, fc_get_event_number(),
8401 sizeof(temp_event_data), (char *) &temp_event_data,
8402 LPFC_NL_VENDOR_ID);
8403 break;
8404 case ASYNC_STATUS_CN:
8405 lpfc_sli_abts_err_handler(phba, iocbq);
8406 break;
8407 default:
8246 iocb_w = (uint32_t *) icmd; 8408 iocb_w = (uint32_t *) icmd;
8247 lpfc_printf_log(phba, 8409 lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
8248 KERN_ERR,
8249 LOG_SLI,
8250 "0346 Ring %d handler: unexpected ASYNC_STATUS" 8410 "0346 Ring %d handler: unexpected ASYNC_STATUS"
8251 " evt_code 0x%x\n" 8411 " evt_code 0x%x\n"
8252 "W0 0x%08x W1 0x%08x W2 0x%08x W3 0x%08x\n" 8412 "W0 0x%08x W1 0x%08x W2 0x%08x W3 0x%08x\n"
8253 "W4 0x%08x W5 0x%08x W6 0x%08x W7 0x%08x\n" 8413 "W4 0x%08x W5 0x%08x W6 0x%08x W7 0x%08x\n"
8254 "W8 0x%08x W9 0x%08x W10 0x%08x W11 0x%08x\n" 8414 "W8 0x%08x W9 0x%08x W10 0x%08x W11 0x%08x\n"
8255 "W12 0x%08x W13 0x%08x W14 0x%08x W15 0x%08x\n", 8415 "W12 0x%08x W13 0x%08x W14 0x%08x W15 0x%08x\n",
8256 pring->ringno, 8416 pring->ringno, icmd->un.asyncstat.evt_code,
8257 icmd->un.asyncstat.evt_code,
8258 iocb_w[0], iocb_w[1], iocb_w[2], iocb_w[3], 8417 iocb_w[0], iocb_w[1], iocb_w[2], iocb_w[3],
8259 iocb_w[4], iocb_w[5], iocb_w[6], iocb_w[7], 8418 iocb_w[4], iocb_w[5], iocb_w[6], iocb_w[7],
8260 iocb_w[8], iocb_w[9], iocb_w[10], iocb_w[11], 8419 iocb_w[8], iocb_w[9], iocb_w[10], iocb_w[11],
8261 iocb_w[12], iocb_w[13], iocb_w[14], iocb_w[15]); 8420 iocb_w[12], iocb_w[13], iocb_w[14], iocb_w[15]);
8262 8421
8263 return; 8422 break;
8264 }
8265 temp_event_data.data = (uint32_t)temp;
8266 temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT;
8267 if (evt_code == ASYNC_TEMP_WARN) {
8268 temp_event_data.event_code = LPFC_THRESHOLD_TEMP;
8269 lpfc_printf_log(phba,
8270 KERN_ERR,
8271 LOG_TEMP,
8272 "0347 Adapter is very hot, please take "
8273 "corrective action. temperature : %d Celsius\n",
8274 temp);
8275 }
8276 if (evt_code == ASYNC_TEMP_SAFE) {
8277 temp_event_data.event_code = LPFC_NORMAL_TEMP;
8278 lpfc_printf_log(phba,
8279 KERN_ERR,
8280 LOG_TEMP,
8281 "0340 Adapter temperature is OK now. "
8282 "temperature : %d Celsius\n",
8283 temp);
8284 } 8423 }
8285
8286 /* Send temperature change event to applications */
8287 shost = lpfc_shost_from_vport(phba->pport);
8288 fc_host_post_vendor_event(shost, fc_get_event_number(),
8289 sizeof(temp_event_data), (char *) &temp_event_data,
8290 LPFC_NL_VENDOR_ID);
8291
8292} 8424}
8293 8425
8294 8426
@@ -9247,6 +9379,14 @@ void
9247lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, 9379lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
9248 struct lpfc_iocbq *rspiocb) 9380 struct lpfc_iocbq *rspiocb)
9249{ 9381{
9382 lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
9383 "3096 ABORT_XRI_CN completing on xri x%x "
9384 "original iotag x%x, abort cmd iotag x%x "
9385 "status 0x%x, reason 0x%x\n",
9386 cmdiocb->iocb.un.acxri.abortContextTag,
9387 cmdiocb->iocb.un.acxri.abortIoTag,
9388 cmdiocb->iotag, rspiocb->iocb.ulpStatus,
9389 rspiocb->iocb.un.ulpWord[4]);
9250 lpfc_sli_release_iocbq(phba, cmdiocb); 9390 lpfc_sli_release_iocbq(phba, cmdiocb);
9251 return; 9391 return;
9252} 9392}