diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-07-19 10:01:21 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-08-22 18:51:58 -0400 |
commit | 32b9793fe6ff09a85f36b8bd7d6ff214653a7497 (patch) | |
tree | e4bfaf3c28982f9e9b2555ba06dc780e7cb70dca /drivers/scsi/lpfc/lpfc_hbadisc.c | |
parent | 8568a4d2495ebcf5da38a2141c7633399143b1a5 (diff) |
[SCSI] lpfc 8.3.4: Fix a pair of FCoE issues
Fix a pair of FCoE issues
- Fix Region 23 FCoE Parameters not being read correctly
- Fix race condition when there are FCoE events during FCF table read
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.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 | 77 |
1 files changed, 76 insertions, 1 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 625b2ef3050..cc4b6ba9e4d 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -61,6 +61,7 @@ static uint8_t lpfcAlpaArray[] = { | |||
61 | 61 | ||
62 | static void lpfc_disc_timeout_handler(struct lpfc_vport *); | 62 | static void lpfc_disc_timeout_handler(struct lpfc_vport *); |
63 | static void lpfc_disc_flush_list(struct lpfc_vport *vport); | 63 | static void lpfc_disc_flush_list(struct lpfc_vport *vport); |
64 | static void lpfc_unregister_fcfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); | ||
64 | 65 | ||
65 | void | 66 | void |
66 | lpfc_terminate_rport_io(struct fc_rport *rport) | 67 | lpfc_terminate_rport_io(struct fc_rport *rport) |
@@ -1009,9 +1010,15 @@ lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
1009 | spin_lock_irqsave(&phba->hbalock, flags); | 1010 | spin_lock_irqsave(&phba->hbalock, flags); |
1010 | phba->fcf.fcf_flag |= FCF_REGISTERED; | 1011 | phba->fcf.fcf_flag |= FCF_REGISTERED; |
1011 | spin_unlock_irqrestore(&phba->hbalock, flags); | 1012 | spin_unlock_irqrestore(&phba->hbalock, flags); |
1013 | /* If there is a pending FCoE event, restart FCF table scan. */ | ||
1014 | if (lpfc_check_pending_fcoe_event(phba, 1)) { | ||
1015 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
1016 | return; | ||
1017 | } | ||
1012 | if (vport->port_state != LPFC_FLOGI) { | 1018 | if (vport->port_state != LPFC_FLOGI) { |
1013 | spin_lock_irqsave(&phba->hbalock, flags); | 1019 | spin_lock_irqsave(&phba->hbalock, flags); |
1014 | phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE); | 1020 | phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE); |
1021 | phba->hba_flag &= ~FCF_DISC_INPROGRESS; | ||
1015 | spin_unlock_irqrestore(&phba->hbalock, flags); | 1022 | spin_unlock_irqrestore(&phba->hbalock, flags); |
1016 | lpfc_initial_flogi(vport); | 1023 | lpfc_initial_flogi(vport); |
1017 | } | 1024 | } |
@@ -1199,6 +1206,7 @@ lpfc_register_fcf(struct lpfc_hba *phba) | |||
1199 | /* The FCF is already registered, start discovery */ | 1206 | /* The FCF is already registered, start discovery */ |
1200 | if (phba->fcf.fcf_flag & FCF_REGISTERED) { | 1207 | if (phba->fcf.fcf_flag & FCF_REGISTERED) { |
1201 | phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE); | 1208 | phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE); |
1209 | phba->hba_flag &= ~FCF_DISC_INPROGRESS; | ||
1202 | spin_unlock_irqrestore(&phba->hbalock, flags); | 1210 | spin_unlock_irqrestore(&phba->hbalock, flags); |
1203 | if (phba->pport->port_state != LPFC_FLOGI) | 1211 | if (phba->pport->port_state != LPFC_FLOGI) |
1204 | lpfc_initial_flogi(phba->pport); | 1212 | lpfc_initial_flogi(phba->pport); |
@@ -1388,6 +1396,60 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, | |||
1388 | } | 1396 | } |
1389 | 1397 | ||
1390 | /** | 1398 | /** |
1399 | * lpfc_check_pending_fcoe_event - Check if there is pending fcoe event. | ||
1400 | * @phba: pointer to lpfc hba data structure. | ||
1401 | * @unreg_fcf: Unregister FCF if FCF table need to be re-scaned. | ||
1402 | * | ||
1403 | * This function check if there is any fcoe event pending while driver | ||
1404 | * scan FCF entries. If there is any pending event, it will restart the | ||
1405 | * FCF saning and return 1 else return 0. | ||
1406 | */ | ||
1407 | int | ||
1408 | lpfc_check_pending_fcoe_event(struct lpfc_hba *phba, uint8_t unreg_fcf) | ||
1409 | { | ||
1410 | LPFC_MBOXQ_t *mbox; | ||
1411 | int rc; | ||
1412 | /* | ||
1413 | * If the Link is up and no FCoE events while in the | ||
1414 | * FCF discovery, no need to restart FCF discovery. | ||
1415 | */ | ||
1416 | if ((phba->link_state >= LPFC_LINK_UP) && | ||
1417 | (phba->fcoe_eventtag == phba->fcoe_eventtag_at_fcf_scan)) | ||
1418 | return 0; | ||
1419 | |||
1420 | spin_lock_irq(&phba->hbalock); | ||
1421 | phba->fcf.fcf_flag &= ~FCF_AVAILABLE; | ||
1422 | spin_unlock_irq(&phba->hbalock); | ||
1423 | |||
1424 | if (phba->link_state >= LPFC_LINK_UP) | ||
1425 | lpfc_sli4_read_fcf_record(phba, LPFC_FCOE_FCF_GET_FIRST); | ||
1426 | |||
1427 | if (unreg_fcf) { | ||
1428 | spin_lock_irq(&phba->hbalock); | ||
1429 | phba->fcf.fcf_flag &= ~FCF_REGISTERED; | ||
1430 | spin_unlock_irq(&phba->hbalock); | ||
1431 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
1432 | if (!mbox) { | ||
1433 | lpfc_printf_log(phba, KERN_ERR, | ||
1434 | LOG_DISCOVERY|LOG_MBOX, | ||
1435 | "2610 UNREG_FCFI mbox allocation failed\n"); | ||
1436 | return 1; | ||
1437 | } | ||
1438 | lpfc_unreg_fcfi(mbox, phba->fcf.fcfi); | ||
1439 | mbox->vport = phba->pport; | ||
1440 | mbox->mbox_cmpl = lpfc_unregister_fcfi_cmpl; | ||
1441 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); | ||
1442 | if (rc == MBX_NOT_FINISHED) { | ||
1443 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, | ||
1444 | "2611 UNREG_FCFI issue mbox failed\n"); | ||
1445 | mempool_free(mbox, phba->mbox_mem_pool); | ||
1446 | } | ||
1447 | } | ||
1448 | |||
1449 | return 1; | ||
1450 | } | ||
1451 | |||
1452 | /** | ||
1391 | * lpfc_mbx_cmpl_read_fcf_record - Completion handler for read_fcf mbox. | 1453 | * lpfc_mbx_cmpl_read_fcf_record - Completion handler for read_fcf mbox. |
1392 | * @phba: pointer to lpfc hba data structure. | 1454 | * @phba: pointer to lpfc hba data structure. |
1393 | * @mboxq: pointer to mailbox object. | 1455 | * @mboxq: pointer to mailbox object. |
@@ -1419,6 +1481,12 @@ lpfc_mbx_cmpl_read_fcf_record(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
1419 | unsigned long flags; | 1481 | unsigned long flags; |
1420 | uint16_t vlan_id; | 1482 | uint16_t vlan_id; |
1421 | 1483 | ||
1484 | /* If there is pending FCoE event restart FCF table scan */ | ||
1485 | if (lpfc_check_pending_fcoe_event(phba, 0)) { | ||
1486 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | ||
1487 | return; | ||
1488 | } | ||
1489 | |||
1422 | /* Get the first SGE entry from the non-embedded DMA memory. This | 1490 | /* Get the first SGE entry from the non-embedded DMA memory. This |
1423 | * routine only uses a single SGE. | 1491 | * routine only uses a single SGE. |
1424 | */ | 1492 | */ |
@@ -1823,6 +1891,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) | |||
1823 | goto out; | 1891 | goto out; |
1824 | } | 1892 | } |
1825 | } else { | 1893 | } else { |
1894 | vport->port_state = LPFC_VPORT_UNKNOWN; | ||
1826 | /* | 1895 | /* |
1827 | * Add the driver's default FCF record at FCF index 0 now. This | 1896 | * Add the driver's default FCF record at FCF index 0 now. This |
1828 | * is phase 1 implementation that support FCF index 0 and driver | 1897 | * is phase 1 implementation that support FCF index 0 and driver |
@@ -1858,6 +1927,12 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) | |||
1858 | * The driver is expected to do FIP/FCF. Call the port | 1927 | * The driver is expected to do FIP/FCF. Call the port |
1859 | * and get the FCF Table. | 1928 | * and get the FCF Table. |
1860 | */ | 1929 | */ |
1930 | spin_lock_irq(&phba->hbalock); | ||
1931 | if (phba->hba_flag & FCF_DISC_INPROGRESS) { | ||
1932 | spin_unlock_irq(&phba->hbalock); | ||
1933 | return; | ||
1934 | } | ||
1935 | spin_unlock_irq(&phba->hbalock); | ||
1861 | rc = lpfc_sli4_read_fcf_record(phba, | 1936 | rc = lpfc_sli4_read_fcf_record(phba, |
1862 | LPFC_FCOE_FCF_GET_FIRST); | 1937 | LPFC_FCOE_FCF_GET_FIRST); |
1863 | if (rc) | 1938 | if (rc) |
@@ -4414,7 +4489,7 @@ lpfc_read_fcoe_param(struct lpfc_hba *phba, | |||
4414 | fcoe_param_hdr = (struct lpfc_fip_param_hdr *) | 4489 | fcoe_param_hdr = (struct lpfc_fip_param_hdr *) |
4415 | buff; | 4490 | buff; |
4416 | fcoe_param = (struct lpfc_fcoe_params *) | 4491 | fcoe_param = (struct lpfc_fcoe_params *) |
4417 | buff + sizeof(struct lpfc_fip_param_hdr); | 4492 | (buff + sizeof(struct lpfc_fip_param_hdr)); |
4418 | 4493 | ||
4419 | if ((fcoe_param_hdr->parm_version != FIPP_VERSION) || | 4494 | if ((fcoe_param_hdr->parm_version != FIPP_VERSION) || |
4420 | (fcoe_param_hdr->length != FCOE_PARAM_LENGTH)) | 4495 | (fcoe_param_hdr->length != FCOE_PARAM_LENGTH)) |