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

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

[SCSI] lpfc 8.3.23: BSG additions and fixes



- Fixed the mixed declarations and codes which violate ISO C90
   (declarations in subsections that assign at declaration)
- Add BSG data transfer size protection in mailbox command pass-through path
- Invoke BSG job_done while holding spinlock to fix deadlock
- Added support for checking SLI_CONFIG subcommands
- Fixed bug in BSG mailbox size check to non-embedded external buffer

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 c31098ce
Loading
Loading
Loading
Loading
+34 −25
Original line number Diff line number Diff line
@@ -2426,6 +2426,7 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
{
	struct bsg_job_data *dd_data;
	struct fc_bsg_job *job;
	struct lpfc_mbx_nembed_cmd *nembed_sge;
	uint32_t size;
	unsigned long flags;
	uint8_t *to;
@@ -2469,8 +2470,7 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
			memcpy(to, from, size);
		} else if ((phba->sli_rev == LPFC_SLI_REV4) &&
			(pmboxq->u.mb.mbxCommand == MBX_SLI4_CONFIG)) {
			struct lpfc_mbx_nembed_cmd *nembed_sge =
				(struct lpfc_mbx_nembed_cmd *)
			nembed_sge = (struct lpfc_mbx_nembed_cmd *)
					&pmboxq->u.mb.un.varWords[0];

			from = (uint8_t *)dd_data->context_un.mbox.dmp->dma.
@@ -2496,16 +2496,18 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
					job->reply_payload.sg_cnt,
					from, size);
		job->reply->result = 0;

		/* need to hold the lock until we set job->dd_data to NULL
		 * to hold off the timeout handler returning to the mid-layer
		 * while we are still processing the job.
		 */
		job->dd_data = NULL;
		dd_data->context_un.mbox.set_job = NULL;
		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
		job->job_done(job);
	}
	} else {
		dd_data->context_un.mbox.set_job = NULL;
	/* need to hold the lock until we call job done to hold off
	 * the timeout handler returning to the midlayer while
	 * we are stillprocessing the job
	 */
		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
	}

	kfree(dd_data->context_un.mbox.mb);
	mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool);
@@ -2644,6 +2646,11 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
	struct ulp_bde64 *rxbpl = NULL;
	struct dfc_mbox_req *mbox_req = (struct dfc_mbox_req *)
		job->request->rqst_data.h_vendor.vendor_cmd;
	struct READ_EVENT_LOG_VAR *rdEventLog;
	uint32_t transmit_length, receive_length, mode;
	struct lpfc_mbx_nembed_cmd *nembed_sge;
	struct mbox_header *header;
	struct ulp_bde64 *bde;
	uint8_t *ext = NULL;
	int rc = 0;
	uint8_t *from;
@@ -2651,9 +2658,16 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
	/* in case no data is transferred */
	job->reply->reply_payload_rcv_len = 0;

	/* sanity check to protect driver */
	if (job->reply_payload.payload_len > BSG_MBOX_SIZE ||
	    job->request_payload.payload_len > BSG_MBOX_SIZE) {
		rc = -ERANGE;
		goto job_done;
	}

	/* check if requested extended data lengths are valid */
	if ((mbox_req->inExtWLen > MAILBOX_EXT_SIZE) ||
		(mbox_req->outExtWLen > MAILBOX_EXT_SIZE)) {
	if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) ||
	    (mbox_req->outExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t))) {
		rc = -ERANGE;
		goto job_done;
	}
@@ -2744,8 +2758,8 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
	 * use ours
	 */
	if (pmb->mbxCommand == MBX_RUN_BIU_DIAG64) {
		uint32_t transmit_length = pmb->un.varWords[1];
		uint32_t receive_length = pmb->un.varWords[4];
		transmit_length = pmb->un.varWords[1];
		receive_length = pmb->un.varWords[4];
		/* transmit length cannot be greater than receive length or
		 * mailbox extension size
		 */
@@ -2795,10 +2809,9 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
		from += sizeof(MAILBOX_t);
		memcpy((uint8_t *)dmp->dma.virt, from, transmit_length);
	} else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) {
		struct READ_EVENT_LOG_VAR *rdEventLog =
			&pmb->un.varRdEventLog ;
		uint32_t receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize;
		uint32_t mode =	 bf_get(lpfc_event_log, rdEventLog);
		rdEventLog = &pmb->un.varRdEventLog;
		receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize;
		mode = bf_get(lpfc_event_log, rdEventLog);

		/* receive length cannot be greater than mailbox
		 * extension size
@@ -2843,7 +2856,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
			/* rebuild the command for sli4 using our own buffers
			* like we do for biu diags
			*/
			uint32_t receive_length = pmb->un.varWords[2];
			receive_length = pmb->un.varWords[2];
			/* receive length cannot be greater than mailbox
			 * extension size
			 */
@@ -2879,8 +2892,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
			pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys);
		} else if ((pmb->mbxCommand == MBX_UPDATE_CFG) &&
			pmb->un.varUpdateCfg.co) {
			struct ulp_bde64 *bde =
				(struct ulp_bde64 *)&pmb->un.varWords[4];
			bde = (struct ulp_bde64 *)&pmb->un.varWords[4];

			/* bde size cannot be greater than mailbox ext size */
			if (bde->tus.f.bdeSize > MAILBOX_EXT_SIZE) {
@@ -2921,10 +2933,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
			memcpy((uint8_t *)dmp->dma.virt, from,
				bde->tus.f.bdeSize);
		} else if (pmb->mbxCommand == MBX_SLI4_CONFIG) {
			struct lpfc_mbx_nembed_cmd *nembed_sge;
			struct mbox_header *header;
			uint32_t receive_length;

			/* rebuild the command for sli4 using our own buffers
			* like we do for biu diags
			*/
@@ -3386,6 +3394,7 @@ lpfc_menlo_cmd(struct fc_bsg_job *job)
	job->dd_data = NULL;
	return rc;
}

/**
 * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job
 * @job: fc_bsg_job to handle
+130 −0
Original line number Diff line number Diff line
@@ -109,3 +109,133 @@ struct menlo_response {
	uint32_t xri; /* return the xri of the iocb exchange */
};

/*
 * macros and data structures for handling sli-config mailbox command
 * pass-through support, this header file is shared between user and
 * kernel spaces, note the set of macros are duplicates from lpfc_hw4.h,
 * with macro names prefixed with bsg_, as the macros defined in
 * lpfc_hw4.h are not accessible from user space.
 */

/* Macros to deal with bit fields. Each bit field must have 3 #defines
 * associated with it (_SHIFT, _MASK, and _WORD).
 * EG. For a bit field that is in the 7th bit of the "field4" field of a
 * structure and is 2 bits in size the following #defines must exist:
 *      struct temp {
 *              uint32_t        field1;
 *              uint32_t        field2;
 *              uint32_t        field3;
 *              uint32_t        field4;
 *      #define example_bit_field_SHIFT         7
 *      #define example_bit_field_MASK          0x03
 *      #define example_bit_field_WORD          field4
 *              uint32_t        field5;
 *      };
 * Then the macros below may be used to get or set the value of that field.
 * EG. To get the value of the bit field from the above example:
 *      struct temp t1;
 *      value = bsg_bf_get(example_bit_field, &t1);
 * And then to set that bit field:
 *      bsg_bf_set(example_bit_field, &t1, 2);
 * Or clear that bit field:
 *      bsg_bf_set(example_bit_field, &t1, 0);
 */
#define bsg_bf_get_le32(name, ptr) \
	((le32_to_cpu((ptr)->name##_WORD) >> name##_SHIFT) & name##_MASK)
#define bsg_bf_get(name, ptr) \
	(((ptr)->name##_WORD >> name##_SHIFT) & name##_MASK)
#define bsg_bf_set_le32(name, ptr, value) \
	((ptr)->name##_WORD = cpu_to_le32(((((value) & \
	name##_MASK) << name##_SHIFT) | (le32_to_cpu((ptr)->name##_WORD) & \
	~(name##_MASK << name##_SHIFT)))))
#define bsg_bf_set(name, ptr, value) \
	((ptr)->name##_WORD = ((((value) & name##_MASK) << name##_SHIFT) | \
	((ptr)->name##_WORD & ~(name##_MASK << name##_SHIFT))))

/*
 * The sli_config structure specified here is based on the following
 * restriction:
 *
 * -- SLI_CONFIG EMB=0, carrying MSEs, will carry subcommands without
 *    carrying HBD.
 * -- SLI_CONFIG EMB=1, not carrying MSE, will carry subcommands with or
 *    without carrying HBDs.
 */

struct lpfc_sli_config_mse {
	uint32_t pa_lo;
	uint32_t pa_hi;
	uint32_t buf_len;
#define lpfc_mbox_sli_config_mse_len_SHIFT	0
#define lpfc_mbox_sli_config_mse_len_MASK	0xffffff
#define lpfc_mbox_sli_config_mse_len_WORD	buf_len
};

struct lpfc_sli_config_subcmd_hbd {
	uint32_t buf_len;
#define lpfc_mbox_sli_config_ecmn_hbd_len_SHIFT	0
#define lpfc_mbox_sli_config_ecmn_hbd_len_MASK	0xffffff
#define lpfc_mbox_sli_config_ecmn_hbd_len_WORD	buf_len
	uint32_t pa_lo;
	uint32_t pa_hi;
};

struct lpfc_sli_config_hdr {
	uint32_t word1;
#define lpfc_mbox_hdr_emb_SHIFT		0
#define lpfc_mbox_hdr_emb_MASK		0x00000001
#define lpfc_mbox_hdr_emb_WORD		word1
#define lpfc_mbox_hdr_mse_cnt_SHIFT	3
#define lpfc_mbox_hdr_mse_cnt_MASK	0x0000001f
#define lpfc_mbox_hdr_mse_cnt_WORD	word1
	uint32_t payload_length;
	uint32_t tag_lo;
	uint32_t tag_hi;
	uint32_t reserved5;
};

struct lpfc_sli_config_generic {
	struct lpfc_sli_config_hdr	sli_config_hdr;
#define LPFC_MBX_SLI_CONFIG_MAX_MSE     19
	struct lpfc_sli_config_mse	mse[LPFC_MBX_SLI_CONFIG_MAX_MSE];
};

struct lpfc_sli_config_subcmnd {
	struct lpfc_sli_config_hdr	sli_config_hdr;
	uint32_t word6;
#define lpfc_subcmnd_opcode_SHIFT	0
#define lpfc_subcmnd_opcode_MASK	0xff
#define lpfc_subcmnd_opcode_WORD	word6
#define lpfc_subcmnd_subsys_SHIFT	8
#define lpfc_subcmnd_subsys_MASK	0xff
#define lpfc_subcmnd_subsys_WORD	word6
	uint32_t timeout;
	uint32_t request_length;
	uint32_t word9;
#define lpfc_subcmnd_version_SHIFT	0
#define lpfc_subcmnd_version_MASK	0xff
#define lpfc_subcmnd_version_WORD	word9
	uint32_t word10;
#define lpfc_subcmnd_ask_rd_len_SHIFT	0
#define lpfc_subcmnd_ask_rd_len_MASK	0xffffff
#define lpfc_subcmnd_ask_rd_len_WORD	word10
	uint32_t rd_offset;
	uint32_t obj_name[26];
	uint32_t hbd_count;
#define LPFC_MBX_SLI_CONFIG_MAX_HBD	10
	struct lpfc_sli_config_subcmd_hbd   hbd[LPFC_MBX_SLI_CONFIG_MAX_HBD];
};

struct lpfc_sli_config_mbox {
	uint32_t word0;
#define lpfc_mqe_status_SHIFT		16
#define lpfc_mqe_status_MASK		0x0000FFFF
#define lpfc_mqe_status_WORD		word0
#define lpfc_mqe_command_SHIFT		8
#define lpfc_mqe_command_MASK		0x000000FF
#define lpfc_mqe_command_WORD		word0
	union {
		struct lpfc_sli_config_generic	sli_config_generic;
		struct lpfc_sli_config_subcmnd	sli_config_subcmnd;
	} un;
};