Commit c30d8d01 authored by Asutosh Das's avatar Asutosh Das Committed by Martin K. Petersen
Browse files

scsi: ufs: core: Prepare for completion in MCQ



Modify completion path APIs and add completion queue entry.

Co-developed-by: default avatarCan Guo <quic_cang@quicinc.com>
Signed-off-by: default avatarCan Guo <quic_cang@quicinc.com>
Signed-off-by: default avatarAsutosh Das <quic_asutoshd@quicinc.com>
Reviewed-by: default avatarBart Van Assche <bvanassche@acm.org>
Reviewed-by: default avatarManivannan Sadhasivam <mani@kernel.org>
Reviewed-by: default avatarStanley Chu <stanley.chu@mediatek.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 854f84e7
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
	enum flag_idn idn, u8 index, bool *flag_res);
void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit);
void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag,
			  struct cq_entry *cqe);
int ufshcd_mcq_init(struct ufs_hba *hba);
int ufshcd_mcq_decide_queue_depth(struct ufs_hba *hba);
int ufshcd_mcq_memory_alloc(struct ufs_hba *hba);
+49 −31
Original line number Diff line number Diff line
@@ -776,12 +776,17 @@ static inline bool ufshcd_is_device_present(struct ufs_hba *hba)
/**
 * ufshcd_get_tr_ocs - Get the UTRD Overall Command Status
 * @lrbp: pointer to local command reference block
 * @cqe: pointer to the completion queue entry
 *
 * This function is used to get the OCS field from UTRD
 * Returns the OCS field in the UTRD
 */
static enum utp_ocs ufshcd_get_tr_ocs(struct ufshcd_lrb *lrbp)
static enum utp_ocs ufshcd_get_tr_ocs(struct ufshcd_lrb *lrbp,
				      struct cq_entry *cqe)
{
	if (cqe)
		return le32_to_cpu(cqe->status) & MASK_OCS;

	return le32_to_cpu(lrbp->utr_descriptor_ptr->header.dword_2) & MASK_OCS;
}

@@ -3068,7 +3073,7 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
		 * not trigger any race conditions.
		 */
		hba->dev_cmd.complete = NULL;
		err = ufshcd_get_tr_ocs(lrbp);
		err = ufshcd_get_tr_ocs(lrbp, hba->dev_cmd.cqe);
		if (!err)
			err = ufshcd_dev_cmd_completion(hba, lrbp);
	} else {
@@ -5202,18 +5207,20 @@ ufshcd_scsi_cmd_status(struct ufshcd_lrb *lrbp, int scsi_status)
 * ufshcd_transfer_rsp_status - Get overall status of the response
 * @hba: per adapter instance
 * @lrbp: pointer to local reference block of completed command
 * @cqe: pointer to the completion queue entry
 *
 * Returns result of the command to notify SCSI midlayer
 */
static inline int
ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp,
			   struct cq_entry *cqe)
{
	int result = 0;
	int scsi_status;
	enum utp_ocs ocs;

	/* overall command status of utrd */
	ocs = ufshcd_get_tr_ocs(lrbp);
	ocs = ufshcd_get_tr_ocs(lrbp, cqe);

	if (hba->quirks & UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR) {
		if (be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_1) &
@@ -5378,40 +5385,51 @@ static void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
}

/**
 * __ufshcd_transfer_req_compl - handle SCSI and query command completion
 * ufshcd_compl_one_cqe - handle a completion queue entry
 * @hba: per adapter instance
 * @completed_reqs: bitmask that indicates which requests to complete
 * @task_tag: the task tag of the request to be completed
 * @cqe: pointer to the completion queue entry
 */
static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
					unsigned long completed_reqs)
void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag,
			  struct cq_entry *cqe)
{
	struct ufshcd_lrb *lrbp;
	struct scsi_cmnd *cmd;
	int index;

	for_each_set_bit(index, &completed_reqs, hba->nutrs) {
		lrbp = &hba->lrb[index];
	lrbp = &hba->lrb[task_tag];
	lrbp->compl_time_stamp = ktime_get();
		lrbp->compl_time_stamp_local_clock = local_clock();
	cmd = lrbp->cmd;
	if (cmd) {
		if (unlikely(ufshcd_should_inform_monitor(hba, lrbp)))
			ufshcd_update_monitor(hba, lrbp);
			ufshcd_add_command_trace(hba, index, UFS_CMD_COMP);
			cmd->result = ufshcd_transfer_rsp_status(hba, lrbp);
		ufshcd_add_command_trace(hba, task_tag, UFS_CMD_COMP);
		cmd->result = ufshcd_transfer_rsp_status(hba, lrbp, cqe);
		ufshcd_release_scsi_cmd(hba, lrbp);
		/* Do not touch lrbp after scsi done */
		scsi_done(cmd);
	} else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE ||
		   lrbp->command_type == UTP_CMD_TYPE_UFS_STORAGE) {
		if (hba->dev_cmd.complete) {
				ufshcd_add_command_trace(hba, index,
							 UFS_DEV_COMP);
			hba->dev_cmd.cqe = cqe;
			ufshcd_add_command_trace(hba, task_tag, UFS_DEV_COMP);
			complete(hba->dev_cmd.complete);
			ufshcd_clk_scaling_update_busy(hba);
		}
	}
}

/**
 * __ufshcd_transfer_req_compl - handle SCSI and query command completion
 * @hba: per adapter instance
 * @completed_reqs: bitmask that indicates which requests to complete
 */
static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
					unsigned long completed_reqs)
{
	int tag;

	for_each_set_bit(tag, &completed_reqs, hba->nutrs)
		ufshcd_compl_one_cqe(hba, tag, NULL);
}

/* Any value that is not an existing queue number is fine for this constant. */