Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 32b9793f authored by James Smart's avatar James Smart Committed by James Bottomley
Browse files

[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: default avatarJames Smart <James.Smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 8568a4d2
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -526,6 +526,7 @@ struct lpfc_hba {
#define ELS_XRI_ABORT_EVENT	0x40
#define ASYNC_EVENT		0x80
#define LINK_DISABLED		0x100 /* Link disabled by user */
#define FCF_DISC_INPROGRESS	0x200 /* FCF discovery in progress */
	struct lpfc_dmabuf slim2p;

	MAILBOX_t *mbox;
@@ -767,6 +768,8 @@ struct lpfc_hba {
/* Maximum number of events that can be outstanding at any time*/
#define LPFC_MAX_EVT_COUNT 512
	atomic_t fast_event_count;
	uint32_t fcoe_eventtag;
	uint32_t fcoe_eventtag_at_fcf_scan;
	struct lpfc_fcf fcf;
	uint8_t fc_map[3];
	uint8_t valid_vlan;
+1 −0
Original line number Diff line number Diff line
@@ -189,6 +189,7 @@ void lpfc_unreg_vfi(struct lpfcMboxq *, uint16_t);
void lpfc_reg_fcfi(struct lpfc_hba *, struct lpfcMboxq *);
void lpfc_unreg_fcfi(struct lpfcMboxq *, uint16_t);
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 *,
	uint32_t , LPFC_MBOXQ_t *);
+76 −1
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ static uint8_t lpfcAlpaArray[] = {

static void lpfc_disc_timeout_handler(struct lpfc_vport *);
static void lpfc_disc_flush_list(struct lpfc_vport *vport);
static void lpfc_unregister_fcfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);

void
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);
	phba->fcf.fcf_flag |= FCF_REGISTERED;
	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) {
		spin_lock_irqsave(&phba->hbalock, flags);
		phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE);
		phba->hba_flag &= ~FCF_DISC_INPROGRESS;
		spin_unlock_irqrestore(&phba->hbalock, flags);
		lpfc_initial_flogi(vport);
	}
@@ -1199,6 +1206,7 @@ lpfc_register_fcf(struct lpfc_hba *phba)
	/* The FCF is already registered, start discovery */
	if (phba->fcf.fcf_flag & FCF_REGISTERED) {
		phba->fcf.fcf_flag |= (FCF_DISCOVERED | FCF_IN_USE);
		phba->hba_flag &= ~FCF_DISC_INPROGRESS;
		spin_unlock_irqrestore(&phba->hbalock, flags);
		if (phba->pport->port_state != LPFC_FLOGI)
			lpfc_initial_flogi(phba->pport);
@@ -1387,6 +1395,60 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba,
	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.
 * @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;
	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
	 * 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;
		}
	} else {
		vport->port_state = LPFC_VPORT_UNKNOWN;
		/*
		 * Add the driver's default FCF record at FCF index 0 now. This
		 * 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
		 * 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,
					LPFC_FCOE_FCF_GET_FIRST);
		if (rc)
@@ -4414,7 +4489,7 @@ lpfc_read_fcoe_param(struct lpfc_hba *phba,
	fcoe_param_hdr = (struct lpfc_fip_param_hdr *)
		buff;
	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) ||
		(fcoe_param_hdr->length != FCOE_PARAM_LENGTH))
+6 −3
Original line number Diff line number Diff line
@@ -2829,6 +2829,7 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
	att_type = lpfc_sli4_parse_latt_type(phba, acqe_link);
	if (att_type != AT_LINK_DOWN && att_type != AT_LINK_UP)
		return;
	phba->fcoe_eventtag = acqe_link->event_tag;
	pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
	if (!pmb) {
		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);
	int rc;

	phba->fcoe_eventtag = acqe_fcoe->event_tag;
	switch (event_type) {
	case LPFC_FCOE_EVENT_TYPE_NEW_FCF:
		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->event_tag);
		/*
		 * If the current FCF is in discovered state,
		 * do nothing.
		 * If the current FCF is in discovered state, or
		 * FCF discovery is in progress do nothing.
		 */
		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);
			break;
		}
+6 −1
Original line number Diff line number Diff line
@@ -11536,6 +11536,7 @@ lpfc_sli4_read_fcf_record(struct lpfc_hba *phba, uint16_t fcf_index)
	uint32_t alloc_len, req_len;
	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);
	if (!mboxq) {
		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) {
		lpfc_sli4_mbox_cmd_free(phba, mboxq);
		error = -EIO;
	} else
	} else {
		spin_lock_irq(&phba->hbalock);
		phba->hba_flag |= FCF_DISC_INPROGRESS;
		spin_unlock_irq(&phba->hbalock);
		error = 0;
	}
	return error;
}