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

Commit 1151e3ec authored by James Smart's avatar James Smart Committed by James Bottomley
Browse files

[SCSI] lpfc 8.3.21: RRQ Implementation fixes



RRQ Implementation fixes

- Added checks to prevent a call to findnode_did in clr_active_rrq
- Added the del_sync_timer call for the rrq_tmr to the stop_hba_timers routine.
- Added a check in __lpfc_set_active_rrq for the driver unloading to prevent
  adding an rrq when the driver is being removed.
- Add code to scsi_iocb_cmpl to check for the remote stop and add the rrq.
- Added the same check to els retry.
- Added code to compare the source did in the els rrq to the vports did and
  chose the right exchange ID.
- Initialize the start_cmd pointer to indicate when we have looped through
  all of the scsi buffers.
- Remove the need for the lock around the clearing of the active bit in the
  rrq.
- Added code to clean the els and fcp xri aborted list and remove the all of
  the RRQs for a deleted vport.

Signed-off-by: default avatarAlex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent fedd3b7b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -423,6 +423,6 @@ int lpfc_send_rrq(struct lpfc_hba *, struct lpfc_node_rrq *);
int lpfc_set_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *,
	uint16_t, uint16_t, uint16_t);
void lpfc_cleanup_wt_rrqs(struct lpfc_hba *);
void lpfc_cleanup_vports_rrqs(struct lpfc_vport *);
void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *);
struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t,
	uint32_t);
+46 −6
Original line number Diff line number Diff line
@@ -2816,9 +2816,17 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,

	switch (irsp->ulpStatus) {
	case IOSTAT_FCP_RSP_ERROR:
		break;
	case IOSTAT_REMOTE_STOP:
		if (phba->sli_rev == LPFC_SLI_REV4) {
			/* This IO was aborted by the target, we don't
			 * know the rxid and because we did not send the
			 * ABTS we cannot generate and RRQ.
			 */
			lpfc_set_rrq_active(phba, ndlp,
					 cmdiocb->sli4_xritag, 0, 0);
		}
		break;

	case IOSTAT_LOCAL_REJECT:
		switch ((irsp->un.ulpWord[4] & 0xff)) {
		case IOERR_LOOP_OPEN_FAILURE:
@@ -4014,28 +4022,34 @@ lpfc_els_clear_rrq(struct lpfc_vport *vport,
	uint8_t *pcmd;
	struct RRQ *rrq;
	uint16_t rxid;
	uint16_t xri;
	struct lpfc_node_rrq *prrq;


	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) iocb->context2)->virt);
	pcmd += sizeof(uint32_t);
	rrq = (struct RRQ *)pcmd;
	rxid = bf_get(rrq_oxid, rrq);
	rrq->rrq_exchg = be32_to_cpu(rrq->rrq_exchg);
	rxid = be16_to_cpu(bf_get(rrq_rxid, rrq));

	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
			"2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x"
			" x%x x%x\n",
			bf_get(rrq_did, rrq),
			bf_get(rrq_oxid, rrq),
			be32_to_cpu(bf_get(rrq_did, rrq)),
			be16_to_cpu(bf_get(rrq_oxid, rrq)),
			rxid,
			iocb->iotag, iocb->iocb.ulpContext);

	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
		"Clear RRQ:  did:x%x flg:x%x exchg:x%.08x",
		ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg);
	prrq = lpfc_get_active_rrq(vport, rxid, ndlp->nlp_DID);
	if (vport->fc_myDID == be32_to_cpu(bf_get(rrq_did, rrq)))
		xri = be16_to_cpu(bf_get(rrq_oxid, rrq));
	else
		xri = rxid;
	prrq = lpfc_get_active_rrq(vport, xri, ndlp->nlp_DID);
	if (prrq)
		lpfc_clr_rrq_active(phba, rxid, prrq);
		lpfc_clr_rrq_active(phba, xri, prrq);
	return;
}

@@ -7582,6 +7596,32 @@ void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
			      IOERR_SLI_ABORTED);
}

/**
 * lpfc_sli4_vport_delete_els_xri_aborted -Remove all ndlp references for vport
 * @vport: pointer to lpfc vport data structure.
 *
 * This routine is invoked by the vport cleanup for deletions and the cleanup
 * for an ndlp on removal.
 **/
void
lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *vport)
{
	struct lpfc_hba *phba = vport->phba;
	struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
	unsigned long iflag = 0;

	spin_lock_irqsave(&phba->hbalock, iflag);
	spin_lock(&phba->sli4_hba.abts_sgl_list_lock);
	list_for_each_entry_safe(sglq_entry, sglq_next,
			&phba->sli4_hba.lpfc_abts_els_sgl_list, list) {
		if (sglq_entry->ndlp && sglq_entry->ndlp->vport == vport)
			sglq_entry->ndlp = NULL;
	}
	spin_unlock(&phba->sli4_hba.abts_sgl_list_lock);
	spin_unlock_irqrestore(&phba->hbalock, iflag);
	return;
}

/**
 * lpfc_sli4_els_xri_aborted - Slow-path process of els xri abort
 * @phba: pointer to lpfc hba data structure.
+4 −2
Original line number Diff line number Diff line
@@ -3160,7 +3160,7 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
	spin_unlock_irq(shost->host_lock);
	vport->unreg_vpi_cmpl = VPORT_OK;
	mempool_free(pmb, phba->mbox_mem_pool);
	lpfc_cleanup_vports_rrqs(vport);
	lpfc_cleanup_vports_rrqs(vport, NULL);
	/*
	 * This shost reference might have been taken at the beginning of
	 * lpfc_vport_delete()
@@ -3900,6 +3900,8 @@ lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
	if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
		return;
	lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
	if (vport->phba->sli_rev == LPFC_SLI_REV4)
		lpfc_cleanup_vports_rrqs(vport, ndlp);
	lpfc_nlp_put(ndlp);
	return;
}
@@ -4289,7 +4291,7 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)

	list_del_init(&ndlp->els_retry_evt.evt_listp);
	list_del_init(&ndlp->dev_loss_evt.evt_listp);

	lpfc_cleanup_vports_rrqs(vport, ndlp);
	lpfc_unreg_rpi(vport, ndlp);

	return 0;
+7 −6
Original line number Diff line number Diff line
@@ -945,16 +945,12 @@ static void
lpfc_rrq_timeout(unsigned long ptr)
{
	struct lpfc_hba *phba;
	uint32_t tmo_posted;
	unsigned long iflag;

	phba = (struct lpfc_hba *)ptr;
	spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
	tmo_posted = phba->hba_flag & HBA_RRQ_ACTIVE;
	if (!tmo_posted)
	phba->hba_flag |= HBA_RRQ_ACTIVE;
	spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
	if (!tmo_posted)
	lpfc_worker_wake_up(phba);
}

@@ -2280,6 +2276,7 @@ lpfc_cleanup(struct lpfc_vport *vport)
		/* Wait for any activity on ndlps to settle */
		msleep(10);
	}
	lpfc_cleanup_vports_rrqs(vport, NULL);
}

/**
@@ -2355,6 +2352,10 @@ lpfc_stop_hba_timers(struct lpfc_hba *phba)
	del_timer_sync(&phba->fabric_block_timer);
	del_timer_sync(&phba->eratt_poll);
	del_timer_sync(&phba->hb_tmofunc);
	if (phba->sli_rev == LPFC_SLI_REV4) {
		del_timer_sync(&phba->rrq_tmr);
		phba->hba_flag &= ~HBA_RRQ_ACTIVE;
	}
	phba->hb_outstanding = 0;

	switch (phba->pci_dev_grp) {
+56 −21
Original line number Diff line number Diff line
@@ -608,6 +608,32 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc)
	return bcnt;
}

/**
 * lpfc_sli4_vport_delete_fcp_xri_aborted -Remove all ndlp references for vport
 * @vport: pointer to lpfc vport data structure.
 *
 * This routine is invoked by the vport cleanup for deletions and the cleanup
 * for an ndlp on removal.
 **/
void
lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport)
{
	struct lpfc_hba *phba = vport->phba;
	struct lpfc_scsi_buf *psb, *next_psb;
	unsigned long iflag = 0;

	spin_lock_irqsave(&phba->hbalock, iflag);
	spin_lock(&phba->sli4_hba.abts_scsi_buf_list_lock);
	list_for_each_entry_safe(psb, next_psb,
				&phba->sli4_hba.lpfc_abts_scsi_buf_list, list) {
		if (psb->rdata && psb->rdata->pnode
			&& psb->rdata->pnode->vport == vport)
			psb->rdata = NULL;
	}
	spin_unlock(&phba->sli4_hba.abts_scsi_buf_list_lock);
	spin_unlock_irqrestore(&phba->hbalock, iflag);
}

/**
 * lpfc_sli4_fcp_xri_aborted - Fast-path process of fcp xri abort
 * @phba: pointer to lpfc hba data structure.
@@ -640,7 +666,11 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
			psb->status = IOSTAT_SUCCESS;
			spin_unlock(
				&phba->sli4_hba.abts_scsi_buf_list_lock);
			if (psb->rdata && psb->rdata->pnode)
				ndlp = psb->rdata->pnode;
			else
				ndlp = NULL;

			rrq_empty = list_empty(&phba->active_rrq_list);
			spin_unlock_irqrestore(&phba->hbalock, iflag);
			if (ndlp)
@@ -964,35 +994,28 @@ lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
static struct lpfc_scsi_buf*
lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
	struct  lpfc_scsi_buf *lpfc_cmd = NULL;
	struct  lpfc_scsi_buf *start_lpfc_cmd = NULL;
	struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
	struct lpfc_scsi_buf *lpfc_cmd ;
	unsigned long iflag = 0;
	int found = 0;

	spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
	list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
	spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
	while (!found && lpfc_cmd) {
	list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list,
							list) {
		if (lpfc_test_rrq_active(phba, ndlp,
					 lpfc_cmd->cur_iocbq.sli4_xritag)) {
			lpfc_release_scsi_buf_s4(phba, lpfc_cmd);
			spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
			list_remove_head(scsi_buf_list, lpfc_cmd,
					 struct lpfc_scsi_buf, list);
			spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
						 iflag);
			if (lpfc_cmd == start_lpfc_cmd) {
				lpfc_cmd = NULL;
				break;
			} else
					 lpfc_cmd->cur_iocbq.sli4_xritag))
			continue;
		}
		list_del(&lpfc_cmd->list);
		found = 1;
		lpfc_cmd->seg_cnt = 0;
		lpfc_cmd->nonsg_phys = 0;
		lpfc_cmd->prot_seg_cnt = 0;
		break;
	}
	spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
						 iflag);
	if (!found)
		return NULL;
	else
		return  lpfc_cmd;
}
/**
@@ -2484,6 +2507,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
			lpfc_worker_wake_up(phba);
			break;
		case IOSTAT_LOCAL_REJECT:
		case IOSTAT_REMOTE_STOP:
			if (lpfc_cmd->result == IOERR_INVALID_RPI ||
			    lpfc_cmd->result == IOERR_NO_RESOURCES ||
			    lpfc_cmd->result == IOERR_ABORT_REQUESTED ||
@@ -2510,6 +2534,17 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
							"on unprotected cmd\n");
				}
			}
			if ((lpfc_cmd->status == IOSTAT_REMOTE_STOP)
				&& (phba->sli_rev == LPFC_SLI_REV4)
				&& (pnode && NLP_CHK_NODE_ACT(pnode))) {
				/* This IO was aborted by the target, we don't
				 * know the rxid and because we did not send the
				 * ABTS we cannot generate and RRQ.
				 */
				lpfc_set_rrq_active(phba, pnode,
						lpfc_cmd->cur_iocbq.sli4_xritag,
						0, 0);
			}

		/* else: fall through */
		default:
Loading