diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-10-02 15:16:39 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:01:39 -0500 |
commit | 4d9ab994e214d35107017c342aca42477b137316 (patch) | |
tree | 0ee7dd76ce9938eceeac20e4dab287194dc42c41 /drivers/scsi/lpfc/lpfc_hbadisc.c | |
parent | 1796e72291b2b6aafaec5954e666d0b5a95da935 (diff) |
[SCSI] lpfc 8.3.5: fix reset path, ELS ordering and discovery issues
This patch includes the following fixes:
- Fixed panic during HBA reset.
- Fixed FCoE event tag passed in resume_rpi.
- Fix out of order ELS commands
- Fixed discovery issues found during VLAN testing.
- Fix UNREG_VPI failure on extended link pull
- Fixed crash while processing unsolicited FC frames.
- Clear retry count in the delayed ELS handler
- Fixed discovery failure during quick link bounce.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 67 |
1 files changed, 56 insertions, 11 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index e6a47e25b218..5073c127bfe1 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -525,8 +525,6 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
525 | spin_unlock_irq(&phba->hbalock); | 525 | spin_unlock_irq(&phba->hbalock); |
526 | lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ); | 526 | lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ); |
527 | } | 527 | } |
528 | if (phba->hba_flag & HBA_RECEIVE_BUFFER) | ||
529 | lpfc_sli4_handle_received_buffer(phba); | ||
530 | } | 528 | } |
531 | 529 | ||
532 | vports = lpfc_create_vport_work_array(phba); | 530 | vports = lpfc_create_vport_work_array(phba); |
@@ -568,8 +566,9 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
568 | pring = &phba->sli.ring[LPFC_ELS_RING]; | 566 | pring = &phba->sli.ring[LPFC_ELS_RING]; |
569 | status = (ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING))); | 567 | status = (ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING))); |
570 | status >>= (4*LPFC_ELS_RING); | 568 | status >>= (4*LPFC_ELS_RING); |
571 | if ((status & HA_RXMASK) | 569 | if ((status & HA_RXMASK) || |
572 | || (pring->flag & LPFC_DEFERRED_RING_EVENT)) { | 570 | (pring->flag & LPFC_DEFERRED_RING_EVENT) || |
571 | (phba->hba_flag & HBA_RECEIVE_BUFFER)) { | ||
573 | if (pring->flag & LPFC_STOP_IOCB_EVENT) { | 572 | if (pring->flag & LPFC_STOP_IOCB_EVENT) { |
574 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 573 | pring->flag |= LPFC_DEFERRED_RING_EVENT; |
575 | /* Set the lpfc data pending flag */ | 574 | /* Set the lpfc data pending flag */ |
@@ -688,7 +687,8 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) | |||
688 | lpfc_unreg_rpi(vport, ndlp); | 687 | lpfc_unreg_rpi(vport, ndlp); |
689 | 688 | ||
690 | /* Leave Fabric nodes alone on link down */ | 689 | /* Leave Fabric nodes alone on link down */ |
691 | if (!remove && ndlp->nlp_type & NLP_FABRIC) | 690 | if ((phba->sli_rev < LPFC_SLI_REV4) && |
691 | (!remove && ndlp->nlp_type & NLP_FABRIC)) | ||
692 | continue; | 692 | continue; |
693 | rc = lpfc_disc_state_machine(vport, ndlp, NULL, | 693 | rc = lpfc_disc_state_machine(vport, ndlp, NULL, |
694 | remove | 694 | remove |
@@ -1015,10 +1015,10 @@ lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
1015 | mempool_free(mboxq, phba->mbox_mem_pool); | 1015 | mempool_free(mboxq, phba->mbox_mem_pool); |
1016 | return; | 1016 | return; |
1017 | } | 1017 | } |
1018 | phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE); | ||
1019 | phba->hba_flag &= ~FCF_DISC_INPROGRESS; | ||
1018 | if (vport->port_state != LPFC_FLOGI) { | 1020 | if (vport->port_state != LPFC_FLOGI) { |
1019 | spin_lock_irqsave(&phba->hbalock, flags); | 1021 | spin_lock_irqsave(&phba->hbalock, flags); |
1020 | phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE); | ||
1021 | phba->hba_flag &= ~FCF_DISC_INPROGRESS; | ||
1022 | spin_unlock_irqrestore(&phba->hbalock, flags); | 1022 | spin_unlock_irqrestore(&phba->hbalock, flags); |
1023 | lpfc_initial_flogi(vport); | 1023 | lpfc_initial_flogi(vport); |
1024 | } | 1024 | } |
@@ -1199,6 +1199,7 @@ lpfc_register_fcf(struct lpfc_hba *phba) | |||
1199 | 1199 | ||
1200 | /* If the FCF is not availabe do nothing. */ | 1200 | /* If the FCF is not availabe do nothing. */ |
1201 | if (!(phba->fcf.fcf_flag & FCF_AVAILABLE)) { | 1201 | if (!(phba->fcf.fcf_flag & FCF_AVAILABLE)) { |
1202 | phba->hba_flag &= ~FCF_DISC_INPROGRESS; | ||
1202 | spin_unlock_irqrestore(&phba->hbalock, flags); | 1203 | spin_unlock_irqrestore(&phba->hbalock, flags); |
1203 | return; | 1204 | return; |
1204 | } | 1205 | } |
@@ -1216,15 +1217,23 @@ lpfc_register_fcf(struct lpfc_hba *phba) | |||
1216 | 1217 | ||
1217 | fcf_mbxq = mempool_alloc(phba->mbox_mem_pool, | 1218 | fcf_mbxq = mempool_alloc(phba->mbox_mem_pool, |
1218 | GFP_KERNEL); | 1219 | GFP_KERNEL); |
1219 | if (!fcf_mbxq) | 1220 | if (!fcf_mbxq) { |
1221 | spin_lock_irqsave(&phba->hbalock, flags); | ||
1222 | phba->hba_flag &= ~FCF_DISC_INPROGRESS; | ||
1223 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
1220 | return; | 1224 | return; |
1225 | } | ||
1221 | 1226 | ||
1222 | lpfc_reg_fcfi(phba, fcf_mbxq); | 1227 | lpfc_reg_fcfi(phba, fcf_mbxq); |
1223 | fcf_mbxq->vport = phba->pport; | 1228 | fcf_mbxq->vport = phba->pport; |
1224 | fcf_mbxq->mbox_cmpl = lpfc_mbx_cmpl_reg_fcfi; | 1229 | fcf_mbxq->mbox_cmpl = lpfc_mbx_cmpl_reg_fcfi; |
1225 | rc = lpfc_sli_issue_mbox(phba, fcf_mbxq, MBX_NOWAIT); | 1230 | rc = lpfc_sli_issue_mbox(phba, fcf_mbxq, MBX_NOWAIT); |
1226 | if (rc == MBX_NOT_FINISHED) | 1231 | if (rc == MBX_NOT_FINISHED) { |
1232 | spin_lock_irqsave(&phba->hbalock, flags); | ||
1233 | phba->hba_flag &= ~FCF_DISC_INPROGRESS; | ||
1234 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
1227 | mempool_free(fcf_mbxq, phba->mbox_mem_pool); | 1235 | mempool_free(fcf_mbxq, phba->mbox_mem_pool); |
1236 | } | ||
1228 | 1237 | ||
1229 | return; | 1238 | return; |
1230 | } | 1239 | } |
@@ -1253,6 +1262,20 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, | |||
1253 | uint16_t *vlan_id) | 1262 | uint16_t *vlan_id) |
1254 | { | 1263 | { |
1255 | struct lpfc_fcf_conn_entry *conn_entry; | 1264 | struct lpfc_fcf_conn_entry *conn_entry; |
1265 | int i, j, fcf_vlan_id = 0; | ||
1266 | |||
1267 | /* Find the lowest VLAN id in the FCF record */ | ||
1268 | for (i = 0; i < 512; i++) { | ||
1269 | if (new_fcf_record->vlan_bitmap[i]) { | ||
1270 | fcf_vlan_id = i * 8; | ||
1271 | j = 0; | ||
1272 | while (!((new_fcf_record->vlan_bitmap[i] >> j) & 1)) { | ||
1273 | j++; | ||
1274 | fcf_vlan_id++; | ||
1275 | } | ||
1276 | break; | ||
1277 | } | ||
1278 | } | ||
1256 | 1279 | ||
1257 | /* If FCF not available return 0 */ | 1280 | /* If FCF not available return 0 */ |
1258 | if (!bf_get(lpfc_fcf_record_fcf_avail, new_fcf_record) || | 1281 | if (!bf_get(lpfc_fcf_record_fcf_avail, new_fcf_record) || |
@@ -1286,7 +1309,11 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, | |||
1286 | if (*addr_mode & LPFC_FCF_FPMA) | 1309 | if (*addr_mode & LPFC_FCF_FPMA) |
1287 | *addr_mode = LPFC_FCF_FPMA; | 1310 | *addr_mode = LPFC_FCF_FPMA; |
1288 | 1311 | ||
1289 | *vlan_id = 0xFFFF; | 1312 | /* If FCF record report a vlan id use that vlan id */ |
1313 | if (fcf_vlan_id) | ||
1314 | *vlan_id = fcf_vlan_id; | ||
1315 | else | ||
1316 | *vlan_id = 0xFFFF; | ||
1290 | return 1; | 1317 | return 1; |
1291 | } | 1318 | } |
1292 | 1319 | ||
@@ -1384,8 +1411,15 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, | |||
1384 | (*addr_mode & LPFC_FCF_FPMA)) | 1411 | (*addr_mode & LPFC_FCF_FPMA)) |
1385 | *addr_mode = LPFC_FCF_FPMA; | 1412 | *addr_mode = LPFC_FCF_FPMA; |
1386 | 1413 | ||
1414 | /* If matching connect list has a vlan id, use it */ | ||
1387 | if (conn_entry->conn_rec.flags & FCFCNCT_VLAN_VALID) | 1415 | if (conn_entry->conn_rec.flags & FCFCNCT_VLAN_VALID) |
1388 | *vlan_id = conn_entry->conn_rec.vlan_tag; | 1416 | *vlan_id = conn_entry->conn_rec.vlan_tag; |
1417 | /* | ||
1418 | * If no vlan id is specified in connect list, use the vlan id | ||
1419 | * in the FCF record | ||
1420 | */ | ||
1421 | else if (fcf_vlan_id) | ||
1422 | *vlan_id = fcf_vlan_id; | ||
1389 | else | 1423 | else |
1390 | *vlan_id = 0xFFFF; | 1424 | *vlan_id = 0xFFFF; |
1391 | 1425 | ||
@@ -1423,6 +1457,12 @@ lpfc_check_pending_fcoe_event(struct lpfc_hba *phba, uint8_t unreg_fcf) | |||
1423 | 1457 | ||
1424 | if (phba->link_state >= LPFC_LINK_UP) | 1458 | if (phba->link_state >= LPFC_LINK_UP) |
1425 | lpfc_sli4_read_fcf_record(phba, LPFC_FCOE_FCF_GET_FIRST); | 1459 | lpfc_sli4_read_fcf_record(phba, LPFC_FCOE_FCF_GET_FIRST); |
1460 | else | ||
1461 | /* | ||
1462 | * Do not continue FCF discovery and clear FCF_DISC_INPROGRESS | ||
1463 | * flag | ||
1464 | */ | ||
1465 | phba->hba_flag &= ~FCF_DISC_INPROGRESS; | ||
1426 | 1466 | ||
1427 | if (unreg_fcf) { | 1467 | if (unreg_fcf) { |
1428 | spin_lock_irq(&phba->hbalock); | 1468 | spin_lock_irq(&phba->hbalock); |
@@ -2085,6 +2125,7 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2085 | else | 2125 | else |
2086 | phba->sli.sli_flag &= ~LPFC_MENLO_MAINT; | 2126 | phba->sli.sli_flag &= ~LPFC_MENLO_MAINT; |
2087 | 2127 | ||
2128 | phba->link_events++; | ||
2088 | if (la->attType == AT_LINK_UP && (!la->mm)) { | 2129 | if (la->attType == AT_LINK_UP && (!la->mm)) { |
2089 | phba->fc_stat.LinkUp++; | 2130 | phba->fc_stat.LinkUp++; |
2090 | if (phba->link_flag & LS_LOOPBACK_MODE) { | 2131 | if (phba->link_flag & LS_LOOPBACK_MODE) { |
@@ -4409,6 +4450,8 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba) | |||
4409 | if (lpfc_fcf_inuse(phba)) | 4450 | if (lpfc_fcf_inuse(phba)) |
4410 | return; | 4451 | return; |
4411 | 4452 | ||
4453 | /* At this point, all discovery is aborted */ | ||
4454 | phba->pport->port_state = LPFC_VPORT_UNKNOWN; | ||
4412 | 4455 | ||
4413 | /* Unregister VPIs */ | 4456 | /* Unregister VPIs */ |
4414 | vports = lpfc_create_vport_work_array(phba); | 4457 | vports = lpfc_create_vport_work_array(phba); |
@@ -4512,8 +4555,10 @@ lpfc_read_fcf_conn_tbl(struct lpfc_hba *phba, | |||
4512 | 4555 | ||
4513 | /* Free the current connect table */ | 4556 | /* Free the current connect table */ |
4514 | list_for_each_entry_safe(conn_entry, next_conn_entry, | 4557 | list_for_each_entry_safe(conn_entry, next_conn_entry, |
4515 | &phba->fcf_conn_rec_list, list) | 4558 | &phba->fcf_conn_rec_list, list) { |
4559 | list_del_init(&conn_entry->list); | ||
4516 | kfree(conn_entry); | 4560 | kfree(conn_entry); |
4561 | } | ||
4517 | 4562 | ||
4518 | conn_hdr = (struct lpfc_fcf_conn_hdr *) buff; | 4563 | conn_hdr = (struct lpfc_fcf_conn_hdr *) buff; |
4519 | record_count = conn_hdr->length * sizeof(uint32_t)/ | 4564 | record_count = conn_hdr->length * sizeof(uint32_t)/ |