scsi: ufs: Change power mode on line reset
Line reset can occur during hibernate enter, exit or during PA_INIT. In some cases, system slowness problem is observed when line reset happened during hibernate enter process in auto hibernate mode of operation as link remains in PWM-G1 mode. To fix this problem, read PA_PWRmode, PA_TxGear and PA_RxGear if line reset is detected and if link is in PWM-G1 mode, initiate power mode change to expected HS gear. Change-Id: Ic06a11c917e8954743c4dcf80b89fedeec4584ed Signed-off-by: Asutosh Das <asutoshd@codeaurora.org> Signed-off-by: Sayali Lokhande <sayalil@codeaurora.org>
This commit is contained in:
parent
bd20893138
commit
492d614a96
2 changed files with 58 additions and 3 deletions
|
@ -173,6 +173,9 @@ void ufshcd_update_query_stats(struct ufs_hba *hba,
|
|||
}
|
||||
#endif
|
||||
|
||||
#define PWR_INFO_MASK 0xF
|
||||
#define PWR_RX_OFFSET 4
|
||||
|
||||
#define UFSHCD_REQ_SENSE_SIZE 18
|
||||
|
||||
#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\
|
||||
|
@ -4653,7 +4656,8 @@ int ufshcd_change_power_mode(struct ufs_hba *hba,
|
|||
int ret = 0;
|
||||
|
||||
/* if already configured to the requested pwr_mode */
|
||||
if (pwr_mode->gear_rx == hba->pwr_info.gear_rx &&
|
||||
if (!hba->restore_needed &&
|
||||
pwr_mode->gear_rx == hba->pwr_info.gear_rx &&
|
||||
pwr_mode->gear_tx == hba->pwr_info.gear_tx &&
|
||||
pwr_mode->lane_rx == hba->pwr_info.lane_rx &&
|
||||
pwr_mode->lane_tx == hba->pwr_info.lane_tx &&
|
||||
|
@ -6275,6 +6279,52 @@ static void ufshcd_update_uic_reg_hist(struct ufs_uic_err_reg_hist *reg_hist,
|
|||
reg_hist->pos = (reg_hist->pos + 1) % UIC_ERR_REG_HIST_LENGTH;
|
||||
}
|
||||
|
||||
static void ufshcd_rls_handler(struct work_struct *work)
|
||||
{
|
||||
struct ufs_hba *hba;
|
||||
int ret = 0;
|
||||
u32 mode;
|
||||
|
||||
hba = container_of(work, struct ufs_hba, rls_work);
|
||||
ufshcd_scsi_block_requests(hba);
|
||||
pm_runtime_get_sync(hba->dev);
|
||||
ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX);
|
||||
if (ret) {
|
||||
dev_err(hba->dev,
|
||||
"Timed out (%d) waiting for DB to clear\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ufshcd_dme_get(hba, UIC_ARG_MIB(PA_PWRMODE), &mode);
|
||||
if (hba->pwr_info.pwr_rx != ((mode >> PWR_RX_OFFSET) & PWR_INFO_MASK))
|
||||
hba->restore_needed = true;
|
||||
|
||||
if (hba->pwr_info.pwr_tx != (mode & PWR_INFO_MASK))
|
||||
hba->restore_needed = true;
|
||||
|
||||
ufshcd_dme_get(hba, UIC_ARG_MIB(PA_RXGEAR), &mode);
|
||||
if (hba->pwr_info.gear_rx != mode)
|
||||
hba->restore_needed = true;
|
||||
|
||||
ufshcd_dme_get(hba, UIC_ARG_MIB(PA_TXGEAR), &mode);
|
||||
if (hba->pwr_info.gear_tx != mode)
|
||||
hba->restore_needed = true;
|
||||
|
||||
if (hba->restore_needed)
|
||||
ret = ufshcd_config_pwr_mode(hba, &(hba->pwr_info));
|
||||
|
||||
if (ret)
|
||||
dev_err(hba->dev, "%s: Failed setting power mode, err = %d\n",
|
||||
__func__, ret);
|
||||
else
|
||||
hba->restore_needed = false;
|
||||
|
||||
out:
|
||||
ufshcd_scsi_unblock_requests(hba);
|
||||
pm_runtime_put_sync(hba->dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_update_uic_error - check and set fatal UIC error flags.
|
||||
* @hba: per-adapter instance
|
||||
|
@ -6314,6 +6364,8 @@ static irqreturn_t ufshcd_update_uic_error(struct ufs_hba *hba)
|
|||
hba->full_init_linereset = true;
|
||||
}
|
||||
}
|
||||
if (!hba->full_init_linereset)
|
||||
schedule_work(&hba->rls_work);
|
||||
}
|
||||
retval |= IRQ_HANDLED;
|
||||
}
|
||||
|
@ -9922,6 +9974,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
|
|||
/* Initialize work queues */
|
||||
INIT_WORK(&hba->eh_work, ufshcd_err_handler);
|
||||
INIT_WORK(&hba->eeh_work, ufshcd_exception_event_handler);
|
||||
INIT_WORK(&hba->rls_work, ufshcd_rls_handler);
|
||||
|
||||
/* Initialize UIC command mutex */
|
||||
mutex_init(&hba->uic_cmd_mutex);
|
||||
|
|
|
@ -854,6 +854,7 @@ struct ufs_hba {
|
|||
/* Work Queues */
|
||||
struct work_struct eh_work;
|
||||
struct work_struct eeh_work;
|
||||
struct work_struct rls_work;
|
||||
|
||||
/* HBA Errors */
|
||||
u32 errors;
|
||||
|
@ -953,6 +954,7 @@ struct ufs_hba {
|
|||
|
||||
int latency_hist_enabled;
|
||||
struct io_latency_state io_lat_s;
|
||||
bool restore_needed;
|
||||
};
|
||||
|
||||
static inline void ufshcd_mark_shutdown_ongoing(struct ufs_hba *hba)
|
||||
|
|
Loading…
Add table
Reference in a new issue