ANDROID: scsi: ufs: vendor check response and recovery addition

As per Vendor HW design consideration,
added Vendor specific error handling flow
Under the error checking flow, Vendor can check errors as per their HW design/arch and recover
them accordingly.

Added vendor hook for completion response check
- trace_android_vh_ufs_compl_rsp_check_done
Added vendor hook for vendor specific error handling
- trace_android_vh_ufs_err_handler
Added vendor hook for err logs printing control
- trace_android_vh_ufs_err_print_ctrl
Added vendor hook for error checking flow trigger
- trace_android_vh_ufs_err_check_ctrl

Bug: 312806167
Change-Id: I614737218537f197c68780f5b528b1948d5e29ea
Signed-off-by: Sanjeev Yadav <sanjeev.y@mediatek.com>
Signed-off-by: Browse Zhang <browse.zhang@mediatek.com>
This commit is contained in:
Browse Zhang
2023-12-08 09:20:43 +08:00
committed by Todd Kjos
parent 4246d242fa
commit b39b9bde93
2 changed files with 50 additions and 17 deletions

View File

@@ -145,10 +145,7 @@ enum {
UFSHCD_STATE_EH_SCHEDULED_NON_FATAL,
};
/* UFSHCD error handling flags */
enum {
UFSHCD_EH_IN_PROGRESS = (1 << 0),
};
/* UFSHCD UIC layer error flags */
enum {
@@ -161,12 +158,6 @@ enum {
UFSHCD_UIC_PA_GENERIC_ERROR = (1 << 6), /* Generic PA error */
};
#define ufshcd_set_eh_in_progress(h) \
((h)->eh_flags |= UFSHCD_EH_IN_PROGRESS)
#define ufshcd_eh_in_progress(h) \
((h)->eh_flags & UFSHCD_EH_IN_PROGRESS)
#define ufshcd_clear_eh_in_progress(h) \
((h)->eh_flags &= ~UFSHCD_EH_IN_PROGRESS)
struct ufs_pm_lvl_states ufs_pm_lvl_states[] = {
{UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE},
@@ -5207,7 +5198,7 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
}
/* Release the resources allocated for processing a SCSI command. */
static void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
struct ufshcd_lrb *lrbp)
{
struct scsi_cmnd *cmd = lrbp->cmd;
@@ -5218,6 +5209,7 @@ static void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
ufshcd_release(hba);
ufshcd_clk_scaling_update_busy(hba);
}
EXPORT_SYMBOL_GPL(ufshcd_release_scsi_cmd);
/**
* __ufshcd_transfer_req_compl - handle SCSI and query command completion
@@ -5238,9 +5230,13 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
lrbp->compl_time_stamp = ktime_get();
cmd = lrbp->cmd;
if (cmd) {
bool done = false;
if (unlikely(ufshcd_should_inform_monitor(hba, lrbp)))
ufshcd_update_monitor(hba, lrbp);
trace_android_vh_ufs_compl_command(hba, lrbp);
trace_android_vh_ufs_compl_rsp_check_done(hba, lrbp, &done);
if (done)
return;
ufshcd_add_command_trace(hba, index, "complete");
cmd->result = ufshcd_transfer_rsp_status(hba, lrbp);
ufshcd_release_scsi_cmd(hba, lrbp);
@@ -5807,11 +5803,13 @@ out:
}
/* Complete requests that have door-bell cleared */
static void ufshcd_complete_requests(struct ufs_hba *hba)
void ufshcd_complete_requests(struct ufs_hba *hba)
{
ufshcd_trc_handler(hba, false);
ufshcd_tmc_handler(hba);
}
EXPORT_SYMBOL_GPL(ufshcd_complete_requests);
/**
* ufshcd_quirk_dl_nac_errors - This function checks if error handling is
@@ -5925,7 +5923,7 @@ static void ufshcd_clk_scaling_suspend(struct ufs_hba *hba, bool suspend)
}
}
static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
void ufshcd_err_handling_prepare(struct ufs_hba *hba)
{
pm_runtime_get_sync(hba->dev);
if (pm_runtime_status_suspended(hba->dev) || hba->is_sys_suspended) {
@@ -5960,8 +5958,9 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
up_write(&hba->clk_scaling_lock);
cancel_work_sync(&hba->eeh_work);
}
EXPORT_SYMBOL_GPL(ufshcd_err_handling_prepare);
static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)
void ufshcd_err_handling_unprepare(struct ufs_hba *hba)
{
ufshcd_scsi_unblock_requests(hba);
ufshcd_release(hba);
@@ -5969,6 +5968,7 @@ static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)
ufshcd_clk_scaling_suspend(hba, false);
pm_runtime_put(hba->dev);
}
EXPORT_SYMBOL_GPL(ufshcd_err_handling_unprepare);
static inline bool ufshcd_err_handling_should_stop(struct ufs_hba *hba)
{
@@ -6041,10 +6041,16 @@ static void ufshcd_err_handler(struct work_struct *work)
bool err_tm = false;
int err = 0, pmc_err;
int tag;
bool err_handled = false;
bool needs_reset = false, needs_restore = false;
hba = container_of(work, struct ufs_hba, eh_work);
trace_android_vh_ufs_err_handler(hba, &err_handled);
if (err_handled)
return;
down(&hba->host_sem);
spin_lock_irqsave(hba->host->host_lock, flags);
if (ufshcd_err_handling_should_stop(hba)) {
@@ -6350,14 +6356,16 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status)
* update the transfer error masks to sticky bits, let's do this
* irrespective of current ufshcd_state.
*/
bool skip = false;
hba->saved_err |= hba->errors;
hba->saved_uic_err |= hba->uic_error;
trace_android_vh_ufs_err_print_ctrl(hba, &skip);
/* dump controller state before resetting */
if ((hba->saved_err &
if (!skip &&((hba->saved_err &
(INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK)) ||
(hba->saved_uic_err &&
(hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR))) {
(hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR)))) {
dev_err(hba->dev, "%s: saved_err 0x%x saved_uic_err 0x%x\n",
__func__, hba->saved_err,
hba->saved_uic_err);
@@ -6422,6 +6430,7 @@ static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba)
static irqreturn_t ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)
{
irqreturn_t retval = IRQ_NONE;
bool err_check = false;
if (intr_status & UFSHCD_UIC_MASK)
retval |= ufshcd_uic_cmd_compl(hba, intr_status);
@@ -6432,9 +6441,14 @@ static irqreturn_t ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)
if (intr_status & UTP_TASK_REQ_COMPL)
retval |= ufshcd_tmc_handler(hba);
if (intr_status & UTP_TRANSFER_REQ_COMPL)
if (intr_status & UTP_TRANSFER_REQ_COMPL) {
retval |= ufshcd_trc_handler(hba, ufshcd_has_utrlcnr(hba));
trace_android_vh_ufs_err_check_ctrl(hba, &err_check);
if (err_check)
ufshcd_check_errors(hba, hba->errors);
}
return retval;
}

View File

@@ -82,6 +82,19 @@ enum ufs_event_type {
UFS_EVT_CNT,
};
/* UFSHCD error handling flags */
enum {
UFSHCD_EH_IN_PROGRESS = (1 << 0),
};
#define ufshcd_set_eh_in_progress(h) \
((h)->eh_flags |= UFSHCD_EH_IN_PROGRESS)
#define ufshcd_eh_in_progress(h) \
((h)->eh_flags & UFSHCD_EH_IN_PROGRESS)
#define ufshcd_clear_eh_in_progress(h) \
((h)->eh_flags &= ~UFSHCD_EH_IN_PROGRESS)
/**
* struct uic_command - UIC command structure
* @command: UIC command
@@ -1048,6 +1061,12 @@ int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk);
void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val);
void ufshcd_hba_stop(struct ufs_hba *hba);
void ufshcd_complete_requests(struct ufs_hba *hba);
void ufshcd_release_scsi_cmd(struct ufs_hba *hba,
struct ufshcd_lrb *lrbp);
void ufshcd_err_handling_prepare(struct ufs_hba *hba);
void ufshcd_err_handling_unprepare(struct ufs_hba *hba);
static inline void check_upiu_size(void)
{