scsi :ufs: verify hba controller hce reg value
Sometimes due to hw issues it takes some time to the host controller register to update. In order to verify the register has updated, a polling is done until its value is set. In addition the functions ufshcd_hba_stop() and ufshcd_wait_for_register() was updated with an additional input parameter, indicating the timeout between reads will be done by sleeping or spinning the cpu. Change-Id: Id79d92a4a0bc05d385eb47c027fe19a765f71851 Signed-off-by: Raviv Shvili <rshvili@codeaurora.org> [subhashj@codeaurora.org: resolved merge conflicts, dropped the changes in drivers/scsi/ufs/ufshcd-pci.c] Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
parent
7e9e854fc3
commit
2069520a4c
2 changed files with 27 additions and 24 deletions
|
@ -318,11 +318,12 @@ static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap)
|
|||
* @val - wait condition
|
||||
* @interval_us - polling interval in microsecs
|
||||
* @timeout_ms - timeout in millisecs
|
||||
*
|
||||
* @can_sleep - perform sleep or just spin
|
||||
* Returns -ETIMEDOUT on error, zero on success
|
||||
*/
|
||||
static int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
|
||||
u32 val, unsigned long interval_us, unsigned long timeout_ms)
|
||||
int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
|
||||
u32 val, unsigned long interval_us,
|
||||
unsigned long timeout_ms, bool can_sleep)
|
||||
{
|
||||
int err = 0;
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
|
||||
|
@ -331,9 +332,10 @@ static int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
|
|||
val = val & mask;
|
||||
|
||||
while ((ufshcd_readl(hba, reg) & mask) != val) {
|
||||
/* wakeup within 50us of expiry */
|
||||
if (can_sleep)
|
||||
usleep_range(interval_us, interval_us + 50);
|
||||
|
||||
else
|
||||
udelay(interval_us);
|
||||
if (time_after(jiffies, timeout)) {
|
||||
if ((ufshcd_readl(hba, reg) & mask) != val)
|
||||
err = -ETIMEDOUT;
|
||||
|
@ -1504,7 +1506,7 @@ ufshcd_clear_cmd(struct ufs_hba *hba, int tag)
|
|||
*/
|
||||
err = ufshcd_wait_for_register(hba,
|
||||
REG_UTP_TRANSFER_REQ_DOOR_BELL,
|
||||
mask, ~mask, 1000, 1000);
|
||||
mask, ~mask, 1000, 1000, true);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -2757,18 +2759,9 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
|
|||
* development and testing of this driver. msleep can be changed to
|
||||
* mdelay and retry count can be reduced based on the controller.
|
||||
*/
|
||||
if (!ufshcd_is_hba_active(hba)) {
|
||||
|
||||
if (!ufshcd_is_hba_active(hba))
|
||||
/* change controller state to "reset state" */
|
||||
ufshcd_hba_stop(hba);
|
||||
|
||||
/*
|
||||
* This delay is based on the testing done with UFS host
|
||||
* controller FPGA. The delay can be changed based on the
|
||||
* host controller used.
|
||||
*/
|
||||
msleep(5);
|
||||
}
|
||||
ufshcd_hba_stop(hba, true);
|
||||
|
||||
/* UniPro link is disabled at this point */
|
||||
ufshcd_set_link_off(hba);
|
||||
|
@ -3856,7 +3849,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag)
|
|||
/* poll for max. 1 sec to clear door bell register by h/w */
|
||||
err = ufshcd_wait_for_register(hba,
|
||||
REG_UTP_TASK_REQ_DOOR_BELL,
|
||||
mask, 0, 1000, 1000);
|
||||
mask, 0, 1000, 1000, true);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
@ -4129,7 +4122,7 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
|
|||
|
||||
/* Reset the host controller */
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
ufshcd_hba_stop(hba);
|
||||
ufshcd_hba_stop(hba, false);
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
|
||||
err = ufshcd_hba_enable(hba);
|
||||
|
@ -5278,7 +5271,7 @@ static int ufshcd_link_state_transition(struct ufs_hba *hba,
|
|||
* Change controller state to "reset state" which
|
||||
* should also put the link in off/reset state
|
||||
*/
|
||||
ufshcd_hba_stop(hba);
|
||||
ufshcd_hba_stop(hba, true);
|
||||
/*
|
||||
* TODO: Check if we need any delay to make sure that
|
||||
* controller is reset
|
||||
|
@ -5754,7 +5747,7 @@ void ufshcd_remove(struct ufs_hba *hba)
|
|||
scsi_remove_host(hba->host);
|
||||
/* disable interrupts */
|
||||
ufshcd_disable_intr(hba, hba->intr_mask);
|
||||
ufshcd_hba_stop(hba);
|
||||
ufshcd_hba_stop(hba, true);
|
||||
|
||||
scsi_host_put(hba->host);
|
||||
|
||||
|
|
|
@ -633,14 +633,24 @@ int ufshcd_alloc_host(struct device *, struct ufs_hba **);
|
|||
void ufshcd_dealloc_host(struct ufs_hba *);
|
||||
int ufshcd_init(struct ufs_hba * , void __iomem * , unsigned int);
|
||||
void ufshcd_remove(struct ufs_hba *);
|
||||
|
||||
int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
|
||||
u32 val, unsigned long interval_us,
|
||||
unsigned long timeout_ms, bool can_sleep);
|
||||
/**
|
||||
* ufshcd_hba_stop - Send controller to reset state
|
||||
* @hba: per adapter instance
|
||||
* @can_sleep: perform sleep or just spin
|
||||
*/
|
||||
static inline void ufshcd_hba_stop(struct ufs_hba *hba)
|
||||
static inline void ufshcd_hba_stop(struct ufs_hba *hba, bool can_sleep)
|
||||
{
|
||||
int err;
|
||||
|
||||
ufshcd_writel(hba, CONTROLLER_DISABLE, REG_CONTROLLER_ENABLE);
|
||||
err = ufshcd_wait_for_register(hba, REG_CONTROLLER_ENABLE,
|
||||
CONTROLLER_ENABLE, CONTROLLER_DISABLE,
|
||||
10, 1, can_sleep);
|
||||
if (err)
|
||||
dev_err(hba->dev, "%s: Controller disable failed\n", __func__);
|
||||
}
|
||||
|
||||
static inline void check_upiu_size(void)
|
||||
|
|
Loading…
Add table
Reference in a new issue