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

Commit 0ff10d46 authored by James Smart's avatar James Smart Committed by James Bottomley
Browse files

[SCSI] lpfc 8.2.4 : Miscellaneous Discovery/ELS Fixes



Miscellaneous Discovery/ELS Fixes:
- Delay free's of ELS requests if adapter reject conditions
- Fix concurrent PLOGI vs ADISC state handling
- Add retry mechanism for GFF_ID
- Correct some illegal state transitions around RSCN timeouts
- Fix missing return in FAN handling

Signed-off-by: default avatarJames Smart <James.Smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent b18268fc
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -583,6 +583,11 @@ struct lpfc_hba {
	atomic_t slow_ring_trc_cnt;
#endif

	/* Used for deferred freeing of ELS data buffers */
	struct list_head elsbuf;
	int elsbuf_cnt;
	int elsbuf_prev_cnt;

	uint8_t temp_sensor_support;
	/* Fields used for heart beat. */
	unsigned long last_completion_time;
+1 −0
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *,
		     struct serv_parm *, uint32_t);
int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
void lpfc_more_plogi(struct lpfc_vport *);
void lpfc_more_adisc(struct lpfc_vport *);
void lpfc_end_rscn(struct lpfc_vport *);
int lpfc_els_chk_latt(struct lpfc_vport *);
int lpfc_els_abort_flogi(struct lpfc_hba *);
+74 −9
Original line number Diff line number Diff line
@@ -426,6 +426,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)

	lpfc_set_disctmo(vport);
	vport->num_disc_nodes = 0;
	vport->fc_ns_retry = 0;


	list_add_tail(&head, &mp->list);
@@ -506,7 +507,17 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
						Did, vport->fc_flag,
						vport->fc_rscn_id_cnt);

						if (lpfc_ns_cmd(vport,
						/* This NPortID was previously
						 * a FCP target, * Don't even
						 * bother to send GFF_ID.
						 */
						ndlp = lpfc_findnode_did(vport,
							Did);
						if (ndlp && (ndlp->nlp_type &
							NLP_FCP_TARGET))
							lpfc_setup_disc_node
								(vport, Did);
						else if (lpfc_ns_cmd(vport,
							SLI_CTNS_GFF_ID,
							0, Did) == 0)
							vport->num_disc_nodes++;
@@ -554,7 +565,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
	struct lpfc_dmabuf *outp;
	struct lpfc_sli_ct_request *CTrsp;
	struct lpfc_nodelist *ndlp;
	int rc;
	int rc, retry;

	/* First save ndlp, before we overwrite it */
	ndlp = cmdiocb->context_un.ndlp;
@@ -585,15 +596,36 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
	if (irsp->ulpStatus) {
		/* Check for retry */
		if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
			if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
				(irsp->un.ulpWord[4] != IOERR_NO_RESOURCES))
			retry = 1;
			if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
				switch (irsp->un.ulpWord[4]) {
				case IOERR_NO_RESOURCES:
					/* We don't increment the retry
					 * count for this case.
					 */
					break;
				case IOERR_LINK_DOWN:
				case IOERR_SLI_ABORTED:
				case IOERR_SLI_DOWN:
					retry = 0;
					break;
				default:
					vport->fc_ns_retry++;
				}
			}
			else
				vport->fc_ns_retry++;

			if (retry) {
				/* CT command is being retried */
				rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
					 vport->fc_ns_retry, 0);
			if (rc == 0)
				if (rc == 0) {
					/* success */
					goto out;
				}
			}
		}
		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
				 "0257 GID_FT Query error: 0x%x 0x%x\n",
@@ -698,7 +730,7 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
	struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1;
	struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2;
	struct lpfc_sli_ct_request *CTrsp;
	int did;
	int did, rc, retry;
	uint8_t fbits;
	struct lpfc_nodelist *ndlp;

@@ -729,6 +761,39 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
		}
	}
	else {
		/* Check for retry */
		if (cmdiocb->retry < LPFC_MAX_NS_RETRY) {
			retry = 1;
			if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
				switch (irsp->un.ulpWord[4]) {
				case IOERR_NO_RESOURCES:
					/* We don't increment the retry
					 * count for this case.
					 */
					break;
				case IOERR_LINK_DOWN:
				case IOERR_SLI_ABORTED:
				case IOERR_SLI_DOWN:
					retry = 0;
					break;
				default:
					cmdiocb->retry++;
				}
			}
			else
				cmdiocb->retry++;

			if (retry) {
				/* CT command is being retried */
				rc = lpfc_ns_cmd(vport, SLI_CTNS_GFF_ID,
					 cmdiocb->retry, did);
				if (rc == 0) {
					/* success */
					lpfc_ct_free_iocb(phba, cmdiocb);
					return;
				}
			}
		}
		lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
				 "0267 NameServer GFF Rsp "
				 "x%x Error (%d %d) Data: x%x x%x\n",
+53 −3
Original line number Diff line number Diff line
@@ -783,6 +783,8 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
{
	struct lpfc_vport    *vport = ndlp->vport;
	struct lpfc_nodelist *new_ndlp;
	struct lpfc_rport_data *rdata;
	struct fc_rport *rport;
	struct serv_parm *sp;
	uint8_t  name[sizeof(struct lpfc_name)];
	uint32_t rc;
@@ -819,6 +821,11 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
	lpfc_unreg_rpi(vport, new_ndlp);
	new_ndlp->nlp_DID = ndlp->nlp_DID;
	new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;

	if (ndlp->nlp_flag & NLP_NPR_2B_DISC)
		new_ndlp->nlp_flag |= NLP_NPR_2B_DISC;
	ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;

	lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state);

	/* Move this back to NPR state */
@@ -826,6 +833,20 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
		/* The new_ndlp is replacing ndlp totally, so we need
		 * to put ndlp on UNUSED list and try to free it.
		 */

		/* Fix up the rport accordingly */
		rport =  ndlp->rport;
		if (rport) {
			rdata = rport->dd_data;
			if (rdata->pnode == ndlp) {
				lpfc_nlp_put(ndlp);
				ndlp->rport = NULL;
				rdata->pnode = lpfc_nlp_get(new_ndlp);
				new_ndlp->rport = rport;
			}
			new_ndlp->nlp_type = ndlp->nlp_type;
		}

		lpfc_drop_node(vport, ndlp);
	}
	else {
@@ -1149,7 +1170,7 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
	return 0;
}

static void
void
lpfc_more_adisc(struct lpfc_vport *vport)
{
	int sentadisc;
@@ -2100,9 +2121,36 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
	}
	/* context2  = cmd,  context2->next = rsp, context3 = bpl */
	if (elsiocb->context2) {
		if (elsiocb->iocb_flag & LPFC_DELAY_MEM_FREE) {
			/* Firmware could still be in progress of DMAing
			 * payload, so don't free data buffer till after
			 * a hbeat.
			 */
			elsiocb->iocb_flag &= ~LPFC_DELAY_MEM_FREE;
			buf_ptr = elsiocb->context2;
			elsiocb->context2 = NULL;
			if (buf_ptr) {
				buf_ptr1 = NULL;
				spin_lock_irq(&phba->hbalock);
				if (!list_empty(&buf_ptr->list)) {
					list_remove_head(&buf_ptr->list,
						buf_ptr1, struct lpfc_dmabuf,
						list);
					INIT_LIST_HEAD(&buf_ptr1->list);
					list_add_tail(&buf_ptr1->list,
						&phba->elsbuf);
					phba->elsbuf_cnt++;
				}
				INIT_LIST_HEAD(&buf_ptr->list);
				list_add_tail(&buf_ptr->list, &phba->elsbuf);
				phba->elsbuf_cnt++;
				spin_unlock_irq(&phba->hbalock);
			}
		} else {
			buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
			lpfc_els_free_data(phba, buf_ptr1);
		}
	}

	if (elsiocb->context3) {
		buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3;
@@ -3027,6 +3075,8 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport)

	/* To process RSCN, first compare RSCN data with NameServer */
	vport->fc_ns_retry = 0;
	vport->num_disc_nodes = 0;

	ndlp = lpfc_findnode_did(vport, NameServer_DID);
	if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
		/* Good ndlp, issue CT Request to NameServer */
+1 −0
Original line number Diff line number Diff line
@@ -2564,6 +2564,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
		}
		if (vport->port_state != LPFC_FLOGI) {
			lpfc_initial_flogi(vport);
			return;
		}
		break;

Loading