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

Commit 341af102 authored by James Smart's avatar James Smart Committed by James Bottomley
Browse files

[SCSI] lpfc 8.3.8: BugFixes: SLI relates changes



Fix hardware/SLI relates issues:
- Handle XB bit so that ELS XRIs are not prematurely released.
- Handle XB bit so that FCP XRIs are not prematurely released.
- Define new security SLI Commands.
- Remove unused security SLI commands
- Skip receive data size parameter check on received FLOGI.
- Added LPFC_USE_FCPWQIDX flag to iocb to force SLI layer
  to submit abort WQE on same WQ as the command WQE.

Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 2cec8029
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -99,7 +99,7 @@ int lpfc_disc_state_machine(struct lpfc_vport *, struct lpfc_nodelist *, void *,

void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *);
int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *,
		     struct serv_parm *, uint32_t);
		     struct serv_parm *, uint32_t, int);
int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
void lpfc_more_plogi(struct lpfc_vport *);
void lpfc_more_adisc(struct lpfc_vport *);
+1 −1
Original line number Diff line number Diff line
@@ -4385,7 +4385,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,

	did = Fabric_DID;

	if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3))) {
	if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1))) {
		/* For a FLOGI we accept, then if our portname is greater
		 * then the remote portname we initiate Nport login.
		 */
+7 −11
Original line number Diff line number Diff line
@@ -1465,17 +1465,13 @@ typedef struct { /* FireFly BIU registers */
#define CMD_IOCB_LOGENTRY_CN		0x94
#define CMD_IOCB_LOGENTRY_ASYNC_CN	0x96

/* Unhandled Data Security SLI Commands */
#define DSSCMD_IWRITE64_CR 		0xD8
#define DSSCMD_IWRITE64_CX		0xD9
#define DSSCMD_IREAD64_CR		0xDA
#define DSSCMD_IREAD64_CX		0xDB
#define DSSCMD_INVALIDATE_DEK		0xDC
#define DSSCMD_SET_KEK			0xDD
#define DSSCMD_GET_KEK_ID		0xDE
#define DSSCMD_GEN_XFER			0xDF

#define CMD_MAX_IOCB_CMD        0xE6
/* Data Security SLI Commands */
#define DSSCMD_IWRITE64_CR		0xF8
#define DSSCMD_IWRITE64_CX		0xF9
#define DSSCMD_IREAD64_CR		0xFA
#define DSSCMD_IREAD64_CX		0xFB

#define CMD_MAX_IOCB_CMD        0xFB
#define CMD_IOCB_MASK           0xff

#define MAX_MSG_DATA            28	/* max msg data in CMD_ADAPTER_MSG
+45 −38
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,

int
lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
		 struct serv_parm * sp, uint32_t class)
		 struct serv_parm *sp, uint32_t class, int flogi)
{
	volatile struct serv_parm *hsp = &vport->fc_sparam;
	uint16_t hsp_value, ssp_value = 0;
@@ -75,49 +75,56 @@ lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
	 * correcting the byte values.
	 */
	if (sp->cls1.classValid) {
		hsp_value = (hsp->cls1.rcvDataSizeMsb << 8) |
				hsp->cls1.rcvDataSizeLsb;
		ssp_value = (sp->cls1.rcvDataSizeMsb << 8) |
				sp->cls1.rcvDataSizeLsb;
		if (!flogi) {
			hsp_value = ((hsp->cls1.rcvDataSizeMsb << 8) |
				     hsp->cls1.rcvDataSizeLsb);
			ssp_value = ((sp->cls1.rcvDataSizeMsb << 8) |
				     sp->cls1.rcvDataSizeLsb);
			if (!ssp_value)
				goto bad_service_param;
			if (ssp_value > hsp_value) {
			sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb;
			sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
				sp->cls1.rcvDataSizeLsb =
					hsp->cls1.rcvDataSizeLsb;
				sp->cls1.rcvDataSizeMsb =
					hsp->cls1.rcvDataSizeMsb;
			}
	} else if (class == CLASS1) {
		goto bad_service_param;
		}

	} else if (class == CLASS1)
		goto bad_service_param;
	if (sp->cls2.classValid) {
		hsp_value = (hsp->cls2.rcvDataSizeMsb << 8) |
				hsp->cls2.rcvDataSizeLsb;
		ssp_value = (sp->cls2.rcvDataSizeMsb << 8) |
				sp->cls2.rcvDataSizeLsb;
		if (!flogi) {
			hsp_value = ((hsp->cls2.rcvDataSizeMsb << 8) |
				     hsp->cls2.rcvDataSizeLsb);
			ssp_value = ((sp->cls2.rcvDataSizeMsb << 8) |
				     sp->cls2.rcvDataSizeLsb);
			if (!ssp_value)
				goto bad_service_param;
			if (ssp_value > hsp_value) {
			sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb;
			sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
				sp->cls2.rcvDataSizeLsb =
					hsp->cls2.rcvDataSizeLsb;
				sp->cls2.rcvDataSizeMsb =
					hsp->cls2.rcvDataSizeMsb;
			}
	} else if (class == CLASS2) {
		goto bad_service_param;
		}

	} else if (class == CLASS2)
		goto bad_service_param;
	if (sp->cls3.classValid) {
		hsp_value = (hsp->cls3.rcvDataSizeMsb << 8) |
				hsp->cls3.rcvDataSizeLsb;
		ssp_value = (sp->cls3.rcvDataSizeMsb << 8) |
				sp->cls3.rcvDataSizeLsb;
		if (!flogi) {
			hsp_value = ((hsp->cls3.rcvDataSizeMsb << 8) |
				     hsp->cls3.rcvDataSizeLsb);
			ssp_value = ((sp->cls3.rcvDataSizeMsb << 8) |
				     sp->cls3.rcvDataSizeLsb);
			if (!ssp_value)
				goto bad_service_param;
			if (ssp_value > hsp_value) {
			sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb;
			sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
				sp->cls3.rcvDataSizeLsb =
					hsp->cls3.rcvDataSizeLsb;
				sp->cls3.rcvDataSizeMsb =
					hsp->cls3.rcvDataSizeMsb;
			}
	} else if (class == CLASS3) {
		goto bad_service_param;
		}
	} else if (class == CLASS3)
		goto bad_service_param;

	/*
	 * Preserve the upper four bits of the MSB from the PLOGI response.
@@ -295,7 +302,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
			NULL);
		return 0;
	}
	if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) {
	if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0) == 0)) {
		/* Reject this request because invalid parameters */
		stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
		stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
@@ -831,7 +838,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
				 "0142 PLOGI RSP: Invalid WWN.\n");
		goto out;
	}
	if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3))
	if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0))
		goto out;
	/* PLOGI chkparm OK */
	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+18 −11
Original line number Diff line number Diff line
@@ -626,6 +626,7 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
		&phba->sli4_hba.lpfc_abts_scsi_buf_list, list) {
		if (psb->cur_iocbq.sli4_xritag == xri) {
			list_del(&psb->list);
			psb->exch_busy = 0;
			psb->status = IOSTAT_SUCCESS;
			spin_unlock_irqrestore(
				&phba->sli4_hba.abts_scsi_buf_list_lock,
@@ -688,11 +689,12 @@ lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
					 list);
			if (status) {
				/* Put this back on the abort scsi list */
				psb->status = IOSTAT_LOCAL_REJECT;
				psb->result = IOERR_ABORT_REQUESTED;
				psb->exch_busy = 1;
				rc++;
			} else
			} else {
				psb->exch_busy = 0;
				psb->status = IOSTAT_SUCCESS;
			}
			/* Put it back into the SCSI buffer list */
			lpfc_release_scsi_buf_s4(phba, psb);
		}
@@ -839,11 +841,12 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
						psb->cur_iocbq.sli4_xritag);
			if (status) {
				/* Put this back on the abort scsi list */
				psb->status = IOSTAT_LOCAL_REJECT;
				psb->result = IOERR_ABORT_REQUESTED;
				psb->exch_busy = 1;
				rc++;
			} else
			} else {
				psb->exch_busy = 0;
				psb->status = IOSTAT_SUCCESS;
			}
			/* Put it back into the SCSI buffer list */
			lpfc_release_scsi_buf_s4(phba, psb);
			break;
@@ -857,11 +860,12 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
				 list);
			if (status) {
				/* Put this back on the abort scsi list */
				psb->status = IOSTAT_LOCAL_REJECT;
				psb->result = IOERR_ABORT_REQUESTED;
				psb->exch_busy = 1;
				rc++;
			} else
			} else {
				psb->exch_busy = 0;
				psb->status = IOSTAT_SUCCESS;
			}
			/* Put it back into the SCSI buffer list */
			lpfc_release_scsi_buf_s4(phba, psb);
		}
@@ -951,8 +955,7 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
{
	unsigned long iflag = 0;

	if (psb->status == IOSTAT_LOCAL_REJECT
		&& psb->result == IOERR_ABORT_REQUESTED) {
	if (psb->exch_busy) {
		spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock,
					iflag);
		psb->pCmd = NULL;
@@ -2221,6 +2224,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,

	lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
	lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
	/* pick up SLI4 exhange busy status from HBA */
	lpfc_cmd->exch_busy = pIocbOut->iocb_flag & LPFC_EXCHANGE_BUSY;

	if (pnode && NLP_CHK_NODE_ACT(pnode))
		atomic_dec(&pnode->cmd_pending);

@@ -2990,6 +2996,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)

	/* ABTS WQE must go to the same WQ as the WQE to be aborted */
	abtsiocb->fcp_wqidx = iocb->fcp_wqidx;
	abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX;

	if (lpfc_is_link_up(phba))
		icmd->ulpCommand = CMD_ABORT_XRI_CN;
Loading