mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +00:00
scsi: ufs: core: Prepare for completion in MCQ
Modify completion path APIs and add completion queue entry. Co-developed-by: Can Guo <quic_cang@quicinc.com> Signed-off-by: Can Guo <quic_cang@quicinc.com> Signed-off-by: Asutosh Das <quic_asutoshd@quicinc.com> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Manivannan Sadhasivam <mani@kernel.org> Reviewed-by: Stanley Chu <stanley.chu@mediatek.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
854f84e7fe
commit
c30d8d010b
@ -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);
|
||||
|
@ -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) &
|
||||
@ -5377,6 +5384,40 @@ static void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
|
||||
ufshcd_clk_scaling_update_busy(hba);
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_compl_one_cqe - handle a completion queue entry
|
||||
* @hba: per adapter instance
|
||||
* @task_tag: the task tag of the request to be completed
|
||||
* @cqe: pointer to the completion queue entry
|
||||
*/
|
||||
void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag,
|
||||
struct cq_entry *cqe)
|
||||
{
|
||||
struct ufshcd_lrb *lrbp;
|
||||
struct scsi_cmnd *cmd;
|
||||
|
||||
lrbp = &hba->lrb[task_tag];
|
||||
lrbp->compl_time_stamp = ktime_get();
|
||||
cmd = lrbp->cmd;
|
||||
if (cmd) {
|
||||
if (unlikely(ufshcd_should_inform_monitor(hba, lrbp)))
|
||||
ufshcd_update_monitor(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) {
|
||||
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
|
||||
@ -5385,33 +5426,10 @@ static void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
|
||||
static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
|
||||
unsigned long completed_reqs)
|
||||
{
|
||||
struct ufshcd_lrb *lrbp;
|
||||
struct scsi_cmnd *cmd;
|
||||
int index;
|
||||
int tag;
|
||||
|
||||
for_each_set_bit(index, &completed_reqs, hba->nutrs) {
|
||||
lrbp = &hba->lrb[index];
|
||||
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_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);
|
||||
complete(hba->dev_cmd.complete);
|
||||
ufshcd_clk_scaling_update_busy(hba);
|
||||
}
|
||||
}
|
||||
}
|
||||
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. */
|
||||
|
Loading…
Reference in New Issue
Block a user