mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
[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>
This commit is contained in:
parent
8568a4d249
commit
32b9793fe6
5 changed files with 92 additions and 5 deletions
|
@ -526,6 +526,7 @@ struct lpfc_hba {
|
||||||
#define ELS_XRI_ABORT_EVENT 0x40
|
#define ELS_XRI_ABORT_EVENT 0x40
|
||||||
#define ASYNC_EVENT 0x80
|
#define ASYNC_EVENT 0x80
|
||||||
#define LINK_DISABLED 0x100 /* Link disabled by user */
|
#define LINK_DISABLED 0x100 /* Link disabled by user */
|
||||||
|
#define FCF_DISC_INPROGRESS 0x200 /* FCF discovery in progress */
|
||||||
struct lpfc_dmabuf slim2p;
|
struct lpfc_dmabuf slim2p;
|
||||||
|
|
||||||
MAILBOX_t *mbox;
|
MAILBOX_t *mbox;
|
||||||
|
@ -767,6 +768,8 @@ struct lpfc_hba {
|
||||||
/* Maximum number of events that can be outstanding at any time*/
|
/* Maximum number of events that can be outstanding at any time*/
|
||||||
#define LPFC_MAX_EVT_COUNT 512
|
#define LPFC_MAX_EVT_COUNT 512
|
||||||
atomic_t fast_event_count;
|
atomic_t fast_event_count;
|
||||||
|
uint32_t fcoe_eventtag;
|
||||||
|
uint32_t fcoe_eventtag_at_fcf_scan;
|
||||||
struct lpfc_fcf fcf;
|
struct lpfc_fcf fcf;
|
||||||
uint8_t fc_map[3];
|
uint8_t fc_map[3];
|
||||||
uint8_t valid_vlan;
|
uint8_t valid_vlan;
|
||||||
|
|
|
@ -189,6 +189,7 @@ void lpfc_unreg_vfi(struct lpfcMboxq *, uint16_t);
|
||||||
void lpfc_reg_fcfi(struct lpfc_hba *, struct lpfcMboxq *);
|
void lpfc_reg_fcfi(struct lpfc_hba *, struct lpfcMboxq *);
|
||||||
void lpfc_unreg_fcfi(struct lpfcMboxq *, uint16_t);
|
void lpfc_unreg_fcfi(struct lpfcMboxq *, uint16_t);
|
||||||
void lpfc_resume_rpi(struct lpfcMboxq *, struct lpfc_nodelist *);
|
void lpfc_resume_rpi(struct lpfcMboxq *, struct lpfc_nodelist *);
|
||||||
|
int lpfc_check_pending_fcoe_event(struct lpfc_hba *, uint8_t);
|
||||||
|
|
||||||
void lpfc_config_hbq(struct lpfc_hba *, uint32_t, struct lpfc_hbq_init *,
|
void lpfc_config_hbq(struct lpfc_hba *, uint32_t, struct lpfc_hbq_init *,
|
||||||
uint32_t , LPFC_MBOXQ_t *);
|
uint32_t , LPFC_MBOXQ_t *);
|
||||||
|
|
|
@ -61,6 +61,7 @@ static uint8_t lpfcAlpaArray[] = {
|
||||||
|
|
||||||
static void lpfc_disc_timeout_handler(struct lpfc_vport *);
|
static void lpfc_disc_timeout_handler(struct lpfc_vport *);
|
||||||
static void lpfc_disc_flush_list(struct lpfc_vport *vport);
|
static void lpfc_disc_flush_list(struct lpfc_vport *vport);
|
||||||
|
static void lpfc_unregister_fcfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||||
|
|
||||||
void
|
void
|
||||||
lpfc_terminate_rport_io(struct fc_rport *rport)
|
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)
|
||||||
spin_lock_irqsave(&phba->hbalock, flags);
|
spin_lock_irqsave(&phba->hbalock, flags);
|
||||||
phba->fcf.fcf_flag |= FCF_REGISTERED;
|
phba->fcf.fcf_flag |= FCF_REGISTERED;
|
||||||
spin_unlock_irqrestore(&phba->hbalock, flags);
|
spin_unlock_irqrestore(&phba->hbalock, flags);
|
||||||
|
/* If there is a pending FCoE event, restart FCF table scan. */
|
||||||
|
if (lpfc_check_pending_fcoe_event(phba, 1)) {
|
||||||
|
mempool_free(mboxq, phba->mbox_mem_pool);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (vport->port_state != LPFC_FLOGI) {
|
if (vport->port_state != LPFC_FLOGI) {
|
||||||
spin_lock_irqsave(&phba->hbalock, flags);
|
spin_lock_irqsave(&phba->hbalock, flags);
|
||||||
phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE);
|
phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE);
|
||||||
|
phba->hba_flag &= ~FCF_DISC_INPROGRESS;
|
||||||
spin_unlock_irqrestore(&phba->hbalock, flags);
|
spin_unlock_irqrestore(&phba->hbalock, flags);
|
||||||
lpfc_initial_flogi(vport);
|
lpfc_initial_flogi(vport);
|
||||||
}
|
}
|
||||||
|
@ -1199,6 +1206,7 @@ lpfc_register_fcf(struct lpfc_hba *phba)
|
||||||
/* The FCF is already registered, start discovery */
|
/* The FCF is already registered, start discovery */
|
||||||
if (phba->fcf.fcf_flag & FCF_REGISTERED) {
|
if (phba->fcf.fcf_flag & FCF_REGISTERED) {
|
||||||
phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE);
|
phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE);
|
||||||
|
phba->hba_flag &= ~FCF_DISC_INPROGRESS;
|
||||||
spin_unlock_irqrestore(&phba->hbalock, flags);
|
spin_unlock_irqrestore(&phba->hbalock, flags);
|
||||||
if (phba->pport->port_state != LPFC_FLOGI)
|
if (phba->pport->port_state != LPFC_FLOGI)
|
||||||
lpfc_initial_flogi(phba->pport);
|
lpfc_initial_flogi(phba->pport);
|
||||||
|
@ -1387,6 +1395,60 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lpfc_check_pending_fcoe_event - Check if there is pending fcoe event.
|
||||||
|
* @phba: pointer to lpfc hba data structure.
|
||||||
|
* @unreg_fcf: Unregister FCF if FCF table need to be re-scaned.
|
||||||
|
*
|
||||||
|
* This function check if there is any fcoe event pending while driver
|
||||||
|
* scan FCF entries. If there is any pending event, it will restart the
|
||||||
|
* FCF saning and return 1 else return 0.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
lpfc_check_pending_fcoe_event(struct lpfc_hba *phba, uint8_t unreg_fcf)
|
||||||
|
{
|
||||||
|
LPFC_MBOXQ_t *mbox;
|
||||||
|
int rc;
|
||||||
|
/*
|
||||||
|
* If the Link is up and no FCoE events while in the
|
||||||
|
* FCF discovery, no need to restart FCF discovery.
|
||||||
|
*/
|
||||||
|
if ((phba->link_state >= LPFC_LINK_UP) &&
|
||||||
|
(phba->fcoe_eventtag == phba->fcoe_eventtag_at_fcf_scan))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
spin_lock_irq(&phba->hbalock);
|
||||||
|
phba->fcf.fcf_flag &= ~FCF_AVAILABLE;
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
|
||||||
|
if (phba->link_state >= LPFC_LINK_UP)
|
||||||
|
lpfc_sli4_read_fcf_record(phba, LPFC_FCOE_FCF_GET_FIRST);
|
||||||
|
|
||||||
|
if (unreg_fcf) {
|
||||||
|
spin_lock_irq(&phba->hbalock);
|
||||||
|
phba->fcf.fcf_flag &= ~FCF_REGISTERED;
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||||
|
if (!mbox) {
|
||||||
|
lpfc_printf_log(phba, KERN_ERR,
|
||||||
|
LOG_DISCOVERY|LOG_MBOX,
|
||||||
|
"2610 UNREG_FCFI mbox allocation failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
lpfc_unreg_fcfi(mbox, phba->fcf.fcfi);
|
||||||
|
mbox->vport = phba->pport;
|
||||||
|
mbox->mbox_cmpl = lpfc_unregister_fcfi_cmpl;
|
||||||
|
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
|
||||||
|
if (rc == MBX_NOT_FINISHED) {
|
||||||
|
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
|
||||||
|
"2611 UNREG_FCFI issue mbox failed\n");
|
||||||
|
mempool_free(mbox, phba->mbox_mem_pool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lpfc_mbx_cmpl_read_fcf_record - Completion handler for read_fcf mbox.
|
* lpfc_mbx_cmpl_read_fcf_record - Completion handler for read_fcf mbox.
|
||||||
* @phba: pointer to lpfc hba data structure.
|
* @phba: pointer to lpfc hba data structure.
|
||||||
|
@ -1419,6 +1481,12 @@ lpfc_mbx_cmpl_read_fcf_record(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
uint16_t vlan_id;
|
uint16_t vlan_id;
|
||||||
|
|
||||||
|
/* If there is pending FCoE event restart FCF table scan */
|
||||||
|
if (lpfc_check_pending_fcoe_event(phba, 0)) {
|
||||||
|
lpfc_sli4_mbox_cmd_free(phba, mboxq);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the first SGE entry from the non-embedded DMA memory. This
|
/* Get the first SGE entry from the non-embedded DMA memory. This
|
||||||
* routine only uses a single SGE.
|
* routine only uses a single SGE.
|
||||||
*/
|
*/
|
||||||
|
@ -1823,6 +1891,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
vport->port_state = LPFC_VPORT_UNKNOWN;
|
||||||
/*
|
/*
|
||||||
* Add the driver's default FCF record at FCF index 0 now. This
|
* Add the driver's default FCF record at FCF index 0 now. This
|
||||||
* is phase 1 implementation that support FCF index 0 and driver
|
* 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)
|
||||||
* The driver is expected to do FIP/FCF. Call the port
|
* The driver is expected to do FIP/FCF. Call the port
|
||||||
* and get the FCF Table.
|
* and get the FCF Table.
|
||||||
*/
|
*/
|
||||||
|
spin_lock_irq(&phba->hbalock);
|
||||||
|
if (phba->hba_flag & FCF_DISC_INPROGRESS) {
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
rc = lpfc_sli4_read_fcf_record(phba,
|
rc = lpfc_sli4_read_fcf_record(phba,
|
||||||
LPFC_FCOE_FCF_GET_FIRST);
|
LPFC_FCOE_FCF_GET_FIRST);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -4414,7 +4489,7 @@ lpfc_read_fcoe_param(struct lpfc_hba *phba,
|
||||||
fcoe_param_hdr = (struct lpfc_fip_param_hdr *)
|
fcoe_param_hdr = (struct lpfc_fip_param_hdr *)
|
||||||
buff;
|
buff;
|
||||||
fcoe_param = (struct lpfc_fcoe_params *)
|
fcoe_param = (struct lpfc_fcoe_params *)
|
||||||
buff + sizeof(struct lpfc_fip_param_hdr);
|
(buff + sizeof(struct lpfc_fip_param_hdr));
|
||||||
|
|
||||||
if ((fcoe_param_hdr->parm_version != FIPP_VERSION) ||
|
if ((fcoe_param_hdr->parm_version != FIPP_VERSION) ||
|
||||||
(fcoe_param_hdr->length != FCOE_PARAM_LENGTH))
|
(fcoe_param_hdr->length != FCOE_PARAM_LENGTH))
|
||||||
|
|
|
@ -2829,6 +2829,7 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
|
||||||
att_type = lpfc_sli4_parse_latt_type(phba, acqe_link);
|
att_type = lpfc_sli4_parse_latt_type(phba, acqe_link);
|
||||||
if (att_type != AT_LINK_DOWN && att_type != AT_LINK_UP)
|
if (att_type != AT_LINK_DOWN && att_type != AT_LINK_UP)
|
||||||
return;
|
return;
|
||||||
|
phba->fcoe_eventtag = acqe_link->event_tag;
|
||||||
pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||||
if (!pmb) {
|
if (!pmb) {
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||||
|
@ -2916,6 +2917,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
|
||||||
uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe);
|
uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
phba->fcoe_eventtag = acqe_fcoe->event_tag;
|
||||||
switch (event_type) {
|
switch (event_type) {
|
||||||
case LPFC_FCOE_EVENT_TYPE_NEW_FCF:
|
case LPFC_FCOE_EVENT_TYPE_NEW_FCF:
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
|
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
|
||||||
|
@ -2923,11 +2925,12 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
|
||||||
acqe_fcoe->fcf_index,
|
acqe_fcoe->fcf_index,
|
||||||
acqe_fcoe->event_tag);
|
acqe_fcoe->event_tag);
|
||||||
/*
|
/*
|
||||||
* If the current FCF is in discovered state,
|
* If the current FCF is in discovered state, or
|
||||||
* do nothing.
|
* FCF discovery is in progress do nothing.
|
||||||
*/
|
*/
|
||||||
spin_lock_irq(&phba->hbalock);
|
spin_lock_irq(&phba->hbalock);
|
||||||
if (phba->fcf.fcf_flag & FCF_DISCOVERED) {
|
if ((phba->fcf.fcf_flag & FCF_DISCOVERED) ||
|
||||||
|
(phba->hba_flag & FCF_DISC_INPROGRESS)) {
|
||||||
spin_unlock_irq(&phba->hbalock);
|
spin_unlock_irq(&phba->hbalock);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11536,6 +11536,7 @@ lpfc_sli4_read_fcf_record(struct lpfc_hba *phba, uint16_t fcf_index)
|
||||||
uint32_t alloc_len, req_len;
|
uint32_t alloc_len, req_len;
|
||||||
struct lpfc_mbx_read_fcf_tbl *read_fcf;
|
struct lpfc_mbx_read_fcf_tbl *read_fcf;
|
||||||
|
|
||||||
|
phba->fcoe_eventtag_at_fcf_scan = phba->fcoe_eventtag;
|
||||||
mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||||
if (!mboxq) {
|
if (!mboxq) {
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
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)
|
||||||
if (rc == MBX_NOT_FINISHED) {
|
if (rc == MBX_NOT_FINISHED) {
|
||||||
lpfc_sli4_mbox_cmd_free(phba, mboxq);
|
lpfc_sli4_mbox_cmd_free(phba, mboxq);
|
||||||
error = -EIO;
|
error = -EIO;
|
||||||
} else
|
} else {
|
||||||
|
spin_lock_irq(&phba->hbalock);
|
||||||
|
phba->hba_flag |= FCF_DISC_INPROGRESS;
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
error = 0;
|
error = 0;
|
||||||
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue