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 | |
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')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 77 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 9 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 7 |
5 files changed, 92 insertions, 5 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 8b69a110a305..d982ac78009e 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -526,6 +526,7 @@ struct lpfc_hba { | |||
526 | #define ELS_XRI_ABORT_EVENT 0x40 | 526 | #define ELS_XRI_ABORT_EVENT 0x40 |
527 | #define ASYNC_EVENT 0x80 | 527 | #define ASYNC_EVENT 0x80 |
528 | #define LINK_DISABLED 0x100 /* Link disabled by user */ | 528 | #define LINK_DISABLED 0x100 /* Link disabled by user */ |
529 | #define FCF_DISC_INPROGRESS 0x200 /* FCF discovery in progress */ | ||
529 | struct lpfc_dmabuf slim2p; | 530 | struct lpfc_dmabuf slim2p; |
530 | 531 | ||
531 | MAILBOX_t *mbox; | 532 | MAILBOX_t *mbox; |
@@ -767,6 +768,8 @@ struct lpfc_hba { | |||
767 | /* Maximum number of events that can be outstanding at any time*/ | 768 | /* Maximum number of events that can be outstanding at any time*/ |
768 | #define LPFC_MAX_EVT_COUNT 512 | 769 | #define LPFC_MAX_EVT_COUNT 512 |
769 | atomic_t fast_event_count; | 770 | atomic_t fast_event_count; |
771 | uint32_t fcoe_eventtag; | ||
772 | uint32_t fcoe_eventtag_at_fcf_scan; | ||
770 | struct lpfc_fcf fcf; | 773 | struct lpfc_fcf fcf; |
771 | uint8_t fc_map[3]; | 774 | uint8_t fc_map[3]; |
772 | uint8_t valid_vlan; | 775 | uint8_t valid_vlan; |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 84e53bb1daa3..d52aa3310551 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -189,6 +189,7 @@ void lpfc_unreg_vfi(struct lpfcMboxq *, uint16_t); | |||
189 | void lpfc_reg_fcfi(struct lpfc_hba *, struct lpfcMboxq *); | 189 | void lpfc_reg_fcfi(struct lpfc_hba *, struct lpfcMboxq *); |
190 | void lpfc_unreg_fcfi(struct lpfcMboxq *, uint16_t); | 190 | void lpfc_unreg_fcfi(struct lpfcMboxq *, uint16_t); |
191 | void lpfc_resume_rpi(struct lpfcMboxq *, struct lpfc_nodelist *); | 191 | void lpfc_resume_rpi(struct lpfcMboxq *, struct lpfc_nodelist *); |
192 | int lpfc_check_pending_fcoe_event(struct lpfc_hba *, uint8_t); | ||
192 | 193 | ||
193 | void lpfc_config_hbq(struct lpfc_hba *, uint32_t, struct lpfc_hbq_init *, | 194 | void lpfc_config_hbq(struct lpfc_hba *, uint32_t, struct lpfc_hbq_init *, |
194 | uint32_t , LPFC_MBOXQ_t *); | 195 | uint32_t , LPFC_MBOXQ_t *); |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 625b2ef3050f..cc4b6ba9e4d5 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)) |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index dc561e3c8b92..a7f32ed256bd 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -2829,6 +2829,7 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba, | |||
2829 | att_type = lpfc_sli4_parse_latt_type(phba, acqe_link); | 2829 | att_type = lpfc_sli4_parse_latt_type(phba, acqe_link); |
2830 | if (att_type != AT_LINK_DOWN && att_type != AT_LINK_UP) | 2830 | if (att_type != AT_LINK_DOWN && att_type != AT_LINK_UP) |
2831 | return; | 2831 | return; |
2832 | phba->fcoe_eventtag = acqe_link->event_tag; | ||
2832 | pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 2833 | pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
2833 | if (!pmb) { | 2834 | if (!pmb) { |
2834 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 2835 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
@@ -2916,6 +2917,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
2916 | uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe); | 2917 | uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe); |
2917 | int rc; | 2918 | int rc; |
2918 | 2919 | ||
2920 | phba->fcoe_eventtag = acqe_fcoe->event_tag; | ||
2919 | switch (event_type) { | 2921 | switch (event_type) { |
2920 | case LPFC_FCOE_EVENT_TYPE_NEW_FCF: | 2922 | case LPFC_FCOE_EVENT_TYPE_NEW_FCF: |
2921 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, | 2923 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, |
@@ -2923,11 +2925,12 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
2923 | acqe_fcoe->fcf_index, | 2925 | acqe_fcoe->fcf_index, |
2924 | acqe_fcoe->event_tag); | 2926 | acqe_fcoe->event_tag); |
2925 | /* | 2927 | /* |
2926 | * If the current FCF is in discovered state, | 2928 | * If the current FCF is in discovered state, or |
2927 | * do nothing. | 2929 | * FCF discovery is in progress do nothing. |
2928 | */ | 2930 | */ |
2929 | spin_lock_irq(&phba->hbalock); | 2931 | spin_lock_irq(&phba->hbalock); |
2930 | if (phba->fcf.fcf_flag & FCF_DISCOVERED) { | 2932 | if ((phba->fcf.fcf_flag & FCF_DISCOVERED) || |
2933 | (phba->hba_flag & FCF_DISC_INPROGRESS)) { | ||
2931 | spin_unlock_irq(&phba->hbalock); | 2934 | spin_unlock_irq(&phba->hbalock); |
2932 | break; | 2935 | break; |
2933 | } | 2936 | } |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 174a1b0d005d..a0f973e7acb3 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -11536,6 +11536,7 @@ lpfc_sli4_read_fcf_record(struct lpfc_hba *phba, uint16_t fcf_index) | |||
11536 | uint32_t alloc_len, req_len; | 11536 | uint32_t alloc_len, req_len; |
11537 | struct lpfc_mbx_read_fcf_tbl *read_fcf; | 11537 | struct lpfc_mbx_read_fcf_tbl *read_fcf; |
11538 | 11538 | ||
11539 | phba->fcoe_eventtag_at_fcf_scan = phba->fcoe_eventtag; | ||
11539 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 11540 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
11540 | if (!mboxq) { | 11541 | if (!mboxq) { |
11541 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 11542 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
@@ -11587,8 +11588,12 @@ lpfc_sli4_read_fcf_record(struct lpfc_hba *phba, uint16_t fcf_index) | |||
11587 | if (rc == MBX_NOT_FINISHED) { | 11588 | if (rc == MBX_NOT_FINISHED) { |
11588 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | 11589 | lpfc_sli4_mbox_cmd_free(phba, mboxq); |
11589 | error = -EIO; | 11590 | error = -EIO; |
11590 | } else | 11591 | } else { |
11592 | spin_lock_irq(&phba->hbalock); | ||
11593 | phba->hba_flag |= FCF_DISC_INPROGRESS; | ||
11594 | spin_unlock_irq(&phba->hbalock); | ||
11591 | error = 0; | 11595 | error = 0; |
11596 | } | ||
11592 | return error; | 11597 | return error; |
11593 | } | 11598 | } |
11594 | 11599 | ||