diff options
author | James Smart <james.smart@emulex.com> | 2011-12-13 13:21:57 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-12-15 01:57:44 -0500 |
commit | cb69f7decc3777822b240c46890a209df288c7bb (patch) | |
tree | 8ae647f9d3d50452fc0bc684a8b4108a4f94a65e /drivers/scsi | |
parent | ff78d8f97c85a568c0799b06137a4171db45b923 (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')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 50 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 67 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 13 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 214 |
7 files changed, 263 insertions, 93 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 9237ff154234..bcc021f3c8eb 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -106,7 +106,7 @@ void lpfc_cleanup(struct lpfc_vport *); | |||
106 | void lpfc_disc_timeout(unsigned long); | 106 | void lpfc_disc_timeout(unsigned long); |
107 | 107 | ||
108 | struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t); | 108 | struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t); |
109 | 109 | struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_vport *, uint16_t); | |
110 | void lpfc_worker_wake_up(struct lpfc_hba *); | 110 | void lpfc_worker_wake_up(struct lpfc_hba *); |
111 | int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t); | 111 | int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t); |
112 | int lpfc_do_work(void *); | 112 | int lpfc_do_work(void *); |
@@ -455,3 +455,5 @@ int lpfc_sli4_queue_create(struct lpfc_hba *); | |||
455 | void lpfc_sli4_queue_destroy(struct lpfc_hba *); | 455 | void lpfc_sli4_queue_destroy(struct lpfc_hba *); |
456 | int lpfc_sli4_read_config(struct lpfc_hba *phba); | 456 | int lpfc_sli4_read_config(struct lpfc_hba *phba); |
457 | int lpfc_scsi_buf_update(struct lpfc_hba *phba); | 457 | int lpfc_scsi_buf_update(struct lpfc_hba *phba); |
458 | void lpfc_sli4_abts_err_handler(struct lpfc_hba *, struct lpfc_nodelist *, | ||
459 | struct sli4_wcqe_xri_aborted *); | ||
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 846ebfd37b5e..46876941bac6 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -6596,56 +6596,6 @@ dropit: | |||
6596 | } | 6596 | } |
6597 | 6597 | ||
6598 | /** | 6598 | /** |
6599 | * lpfc_find_vport_by_vpid - Find a vport on a HBA through vport identifier | ||
6600 | * @phba: pointer to lpfc hba data structure. | ||
6601 | * @vpi: host virtual N_Port identifier. | ||
6602 | * | ||
6603 | * This routine finds a vport on a HBA (referred by @phba) through a | ||
6604 | * @vpi. The function walks the HBA's vport list and returns the address | ||
6605 | * of the vport with the matching @vpi. | ||
6606 | * | ||
6607 | * Return code | ||
6608 | * NULL - No vport with the matching @vpi found | ||
6609 | * Otherwise - Address to the vport with the matching @vpi. | ||
6610 | **/ | ||
6611 | struct lpfc_vport * | ||
6612 | lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) | ||
6613 | { | ||
6614 | struct lpfc_vport *vport; | ||
6615 | unsigned long flags; | ||
6616 | int i = 0; | ||
6617 | |||
6618 | /* The physical ports are always vpi 0 - translate is unnecessary. */ | ||
6619 | if (vpi > 0) { | ||
6620 | /* | ||
6621 | * Translate the physical vpi to the logical vpi. The | ||
6622 | * vport stores the logical vpi. | ||
6623 | */ | ||
6624 | for (i = 0; i < phba->max_vpi; i++) { | ||
6625 | if (vpi == phba->vpi_ids[i]) | ||
6626 | break; | ||
6627 | } | ||
6628 | |||
6629 | if (i >= phba->max_vpi) { | ||
6630 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
6631 | "2936 Could not find Vport mapped " | ||
6632 | "to vpi %d\n", vpi); | ||
6633 | return NULL; | ||
6634 | } | ||
6635 | } | ||
6636 | |||
6637 | spin_lock_irqsave(&phba->hbalock, flags); | ||
6638 | list_for_each_entry(vport, &phba->port_list, listentry) { | ||
6639 | if (vport->vpi == i) { | ||
6640 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
6641 | return vport; | ||
6642 | } | ||
6643 | } | ||
6644 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
6645 | return NULL; | ||
6646 | } | ||
6647 | |||
6648 | /** | ||
6649 | * lpfc_els_unsol_event - Process an unsolicited event from an els sli ring | 6599 | * lpfc_els_unsol_event - Process an unsolicited event from an els sli ring |
6650 | * @phba: pointer to lpfc hba data structure. | 6600 | * @phba: pointer to lpfc hba data structure. |
6651 | * @pring: pointer to a SLI ring. | 6601 | * @pring: pointer to a SLI ring. |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index cf4408f9a2cb..99c76677e394 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -5352,6 +5352,73 @@ lpfc_findnode_wwpn(struct lpfc_vport *vport, struct lpfc_name *wwpn) | |||
5352 | return ndlp; | 5352 | return ndlp; |
5353 | } | 5353 | } |
5354 | 5354 | ||
5355 | /* | ||
5356 | * This routine looks up the ndlp lists for the given RPI. If the rpi | ||
5357 | * is found, the routine returns the node element list pointer else | ||
5358 | * return NULL. | ||
5359 | */ | ||
5360 | struct lpfc_nodelist * | ||
5361 | lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi) | ||
5362 | { | ||
5363 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
5364 | struct lpfc_nodelist *ndlp; | ||
5365 | |||
5366 | spin_lock_irq(shost->host_lock); | ||
5367 | ndlp = __lpfc_findnode_rpi(vport, rpi); | ||
5368 | spin_unlock_irq(shost->host_lock); | ||
5369 | return ndlp; | ||
5370 | } | ||
5371 | |||
5372 | /** | ||
5373 | * lpfc_find_vport_by_vpid - Find a vport on a HBA through vport identifier | ||
5374 | * @phba: pointer to lpfc hba data structure. | ||
5375 | * @vpi: the physical host virtual N_Port identifier. | ||
5376 | * | ||
5377 | * This routine finds a vport on a HBA (referred by @phba) through a | ||
5378 | * @vpi. The function walks the HBA's vport list and returns the address | ||
5379 | * of the vport with the matching @vpi. | ||
5380 | * | ||
5381 | * Return code | ||
5382 | * NULL - No vport with the matching @vpi found | ||
5383 | * Otherwise - Address to the vport with the matching @vpi. | ||
5384 | **/ | ||
5385 | struct lpfc_vport * | ||
5386 | lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) | ||
5387 | { | ||
5388 | struct lpfc_vport *vport; | ||
5389 | unsigned long flags; | ||
5390 | int i = 0; | ||
5391 | |||
5392 | /* The physical ports are always vpi 0 - translate is unnecessary. */ | ||
5393 | if (vpi > 0) { | ||
5394 | /* | ||
5395 | * Translate the physical vpi to the logical vpi. The | ||
5396 | * vport stores the logical vpi. | ||
5397 | */ | ||
5398 | for (i = 0; i < phba->max_vpi; i++) { | ||
5399 | if (vpi == phba->vpi_ids[i]) | ||
5400 | break; | ||
5401 | } | ||
5402 | |||
5403 | if (i >= phba->max_vpi) { | ||
5404 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
5405 | "2936 Could not find Vport mapped " | ||
5406 | "to vpi %d\n", vpi); | ||
5407 | return NULL; | ||
5408 | } | ||
5409 | } | ||
5410 | |||
5411 | spin_lock_irqsave(&phba->hbalock, flags); | ||
5412 | list_for_each_entry(vport, &phba->port_list, listentry) { | ||
5413 | if (vport->vpi == i) { | ||
5414 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
5415 | return vport; | ||
5416 | } | ||
5417 | } | ||
5418 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
5419 | return NULL; | ||
5420 | } | ||
5421 | |||
5355 | void | 5422 | void |
5356 | lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 5423 | lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
5357 | uint32_t did) | 5424 | uint32_t did) |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 046edc4ab35f..2dd464b0f29e 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -2819,7 +2819,8 @@ typedef struct { | |||
2819 | #ifdef __BIG_ENDIAN_BITFIELD | 2819 | #ifdef __BIG_ENDIAN_BITFIELD |
2820 | uint32_t rsvd1 : 19; /* Reserved */ | 2820 | uint32_t rsvd1 : 19; /* Reserved */ |
2821 | uint32_t cdss : 1; /* Configure Data Security SLI */ | 2821 | uint32_t cdss : 1; /* Configure Data Security SLI */ |
2822 | uint32_t rsvd2 : 3; /* Reserved */ | 2822 | uint32_t casabt : 1; /* Configure async abts status notice */ |
2823 | uint32_t rsvd2 : 2; /* Reserved */ | ||
2823 | uint32_t cbg : 1; /* Configure BlockGuard */ | 2824 | uint32_t cbg : 1; /* Configure BlockGuard */ |
2824 | uint32_t cmv : 1; /* Configure Max VPIs */ | 2825 | uint32_t cmv : 1; /* Configure Max VPIs */ |
2825 | uint32_t ccrp : 1; /* Config Command Ring Polling */ | 2826 | uint32_t ccrp : 1; /* Config Command Ring Polling */ |
@@ -2839,14 +2840,16 @@ typedef struct { | |||
2839 | uint32_t ccrp : 1; /* Config Command Ring Polling */ | 2840 | uint32_t ccrp : 1; /* Config Command Ring Polling */ |
2840 | uint32_t cmv : 1; /* Configure Max VPIs */ | 2841 | uint32_t cmv : 1; /* Configure Max VPIs */ |
2841 | uint32_t cbg : 1; /* Configure BlockGuard */ | 2842 | uint32_t cbg : 1; /* Configure BlockGuard */ |
2842 | uint32_t rsvd2 : 3; /* Reserved */ | 2843 | uint32_t rsvd2 : 2; /* Reserved */ |
2844 | uint32_t casabt : 1; /* Configure async abts status notice */ | ||
2843 | uint32_t cdss : 1; /* Configure Data Security SLI */ | 2845 | uint32_t cdss : 1; /* Configure Data Security SLI */ |
2844 | uint32_t rsvd1 : 19; /* Reserved */ | 2846 | uint32_t rsvd1 : 19; /* Reserved */ |
2845 | #endif | 2847 | #endif |
2846 | #ifdef __BIG_ENDIAN_BITFIELD | 2848 | #ifdef __BIG_ENDIAN_BITFIELD |
2847 | uint32_t rsvd3 : 19; /* Reserved */ | 2849 | uint32_t rsvd3 : 19; /* Reserved */ |
2848 | uint32_t gdss : 1; /* Configure Data Security SLI */ | 2850 | uint32_t gdss : 1; /* Configure Data Security SLI */ |
2849 | uint32_t rsvd4 : 3; /* Reserved */ | 2851 | uint32_t gasabt : 1; /* Grant async abts status notice */ |
2852 | uint32_t rsvd4 : 2; /* Reserved */ | ||
2850 | uint32_t gbg : 1; /* Grant BlockGuard */ | 2853 | uint32_t gbg : 1; /* Grant BlockGuard */ |
2851 | uint32_t gmv : 1; /* Grant Max VPIs */ | 2854 | uint32_t gmv : 1; /* Grant Max VPIs */ |
2852 | uint32_t gcrp : 1; /* Grant Command Ring Polling */ | 2855 | uint32_t gcrp : 1; /* Grant Command Ring Polling */ |
@@ -2866,7 +2869,8 @@ typedef struct { | |||
2866 | uint32_t gcrp : 1; /* Grant Command Ring Polling */ | 2869 | uint32_t gcrp : 1; /* Grant Command Ring Polling */ |
2867 | uint32_t gmv : 1; /* Grant Max VPIs */ | 2870 | uint32_t gmv : 1; /* Grant Max VPIs */ |
2868 | uint32_t gbg : 1; /* Grant BlockGuard */ | 2871 | uint32_t gbg : 1; /* Grant BlockGuard */ |
2869 | uint32_t rsvd4 : 3; /* Reserved */ | 2872 | uint32_t rsvd4 : 2; /* Reserved */ |
2873 | uint32_t gasabt : 1; /* Grant async abts status notice */ | ||
2870 | uint32_t gdss : 1; /* Configure Data Security SLI */ | 2874 | uint32_t gdss : 1; /* Configure Data Security SLI */ |
2871 | uint32_t rsvd3 : 19; /* Reserved */ | 2875 | uint32_t rsvd3 : 19; /* Reserved */ |
2872 | #endif | 2876 | #endif |
@@ -3465,6 +3469,7 @@ typedef struct { | |||
3465 | } ASYNCSTAT_FIELDS; | 3469 | } ASYNCSTAT_FIELDS; |
3466 | #define ASYNC_TEMP_WARN 0x100 | 3470 | #define ASYNC_TEMP_WARN 0x100 |
3467 | #define ASYNC_TEMP_SAFE 0x101 | 3471 | #define ASYNC_TEMP_SAFE 0x101 |
3472 | #define ASYNC_STATUS_CN 0x102 | ||
3468 | 3473 | ||
3469 | /* IOCB Command template for CMD_IOCB_RCV_ELS64_CX (0xB7) | 3474 | /* IOCB Command template for CMD_IOCB_RCV_ELS64_CX (0xB7) |
3470 | or CMD_IOCB_RCV_SEQ64_CX (0xB5) */ | 3475 | or CMD_IOCB_RCV_SEQ64_CX (0xB5) */ |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 0228f04061da..328782efc839 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -1293,6 +1293,10 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1293 | phba->sli_rev = LPFC_SLI_REV2; | 1293 | phba->sli_rev = LPFC_SLI_REV2; |
1294 | mb->un.varCfgPort.sli_mode = phba->sli_rev; | 1294 | mb->un.varCfgPort.sli_mode = phba->sli_rev; |
1295 | 1295 | ||
1296 | /* If this is an SLI3 port, configure async status notification. */ | ||
1297 | if (phba->sli_rev == LPFC_SLI_REV3) | ||
1298 | mb->un.varCfgPort.casabt = 1; | ||
1299 | |||
1296 | /* Now setup pcb */ | 1300 | /* Now setup pcb */ |
1297 | phba->pcb->type = TYPE_NATIVE_SLI2; | 1301 | phba->pcb->type = TYPE_NATIVE_SLI2; |
1298 | phba->pcb->feature = FEATURE_INITIAL_SLI2; | 1302 | phba->pcb->feature = FEATURE_INITIAL_SLI2; |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 2e1e54e5c3ae..f1af3f9dead4 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -681,8 +681,10 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, | |||
681 | 681 | ||
682 | rrq_empty = list_empty(&phba->active_rrq_list); | 682 | rrq_empty = list_empty(&phba->active_rrq_list); |
683 | spin_unlock_irqrestore(&phba->hbalock, iflag); | 683 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
684 | if (ndlp) | 684 | if (ndlp) { |
685 | lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1); | 685 | lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1); |
686 | lpfc_sli4_abts_err_handler(phba, ndlp, axri); | ||
687 | } | ||
686 | lpfc_release_scsi_buf_s4(phba, psb); | 688 | lpfc_release_scsi_buf_s4(phba, psb); |
687 | if (rrq_empty) | 689 | if (rrq_empty) |
688 | lpfc_worker_wake_up(phba); | 690 | lpfc_worker_wake_up(phba); |
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 | */ | ||
8232 | static void | ||
8233 | lpfc_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 | */ | ||
8284 | static void | ||
8285 | lpfc_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 | */ | ||
8330 | void | ||
8331 | lpfc_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 | |||
9247 | lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | 9379 | lpfc_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 | } |