mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +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,
|
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
|
||||||
enum flag_idn idn, u8 index, bool *flag_res);
|
enum flag_idn idn, u8 index, bool *flag_res);
|
||||||
void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit);
|
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_init(struct ufs_hba *hba);
|
||||||
int ufshcd_mcq_decide_queue_depth(struct ufs_hba *hba);
|
int ufshcd_mcq_decide_queue_depth(struct ufs_hba *hba);
|
||||||
int ufshcd_mcq_memory_alloc(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
|
* ufshcd_get_tr_ocs - Get the UTRD Overall Command Status
|
||||||
* @lrbp: pointer to local command reference block
|
* @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
|
* This function is used to get the OCS field from UTRD
|
||||||
* Returns the OCS field in the 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;
|
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.
|
* not trigger any race conditions.
|
||||||
*/
|
*/
|
||||||
hba->dev_cmd.complete = NULL;
|
hba->dev_cmd.complete = NULL;
|
||||||
err = ufshcd_get_tr_ocs(lrbp);
|
err = ufshcd_get_tr_ocs(lrbp, hba->dev_cmd.cqe);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = ufshcd_dev_cmd_completion(hba, lrbp);
|
err = ufshcd_dev_cmd_completion(hba, lrbp);
|
||||||
} else {
|
} 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
|
* ufshcd_transfer_rsp_status - Get overall status of the response
|
||||||
* @hba: per adapter instance
|
* @hba: per adapter instance
|
||||||
* @lrbp: pointer to local reference block of completed command
|
* @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
|
* Returns result of the command to notify SCSI midlayer
|
||||||
*/
|
*/
|
||||||
static inline int
|
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 result = 0;
|
||||||
int scsi_status;
|
int scsi_status;
|
||||||
enum utp_ocs ocs;
|
enum utp_ocs ocs;
|
||||||
|
|
||||||
/* overall command status of utrd */
|
/* 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 (hba->quirks & UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR) {
|
||||||
if (be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_1) &
|
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_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
|
* __ufshcd_transfer_req_compl - handle SCSI and query command completion
|
||||||
* @hba: per adapter instance
|
* @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,
|
static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
|
||||||
unsigned long completed_reqs)
|
unsigned long completed_reqs)
|
||||||
{
|
{
|
||||||
struct ufshcd_lrb *lrbp;
|
int tag;
|
||||||
struct scsi_cmnd *cmd;
|
|
||||||
int index;
|
|
||||||
|
|
||||||
for_each_set_bit(index, &completed_reqs, hba->nutrs) {
|
for_each_set_bit(tag, &completed_reqs, hba->nutrs)
|
||||||
lrbp = &hba->lrb[index];
|
ufshcd_compl_one_cqe(hba, tag, NULL);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Any value that is not an existing queue number is fine for this constant. */
|
/* Any value that is not an existing queue number is fine for this constant. */
|
||||||
|
Loading…
Reference in New Issue
Block a user