Loading drivers/scsi/ufs/ufshcd.c +55 −2 Original line number Diff line number Diff line Loading @@ -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 |\ Loading Loading @@ -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 && Loading Loading @@ -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 Loading Loading @@ -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; } Loading Loading @@ -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); Loading drivers/scsi/ufs/ufshcd.h +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading
drivers/scsi/ufs/ufshcd.c +55 −2 Original line number Diff line number Diff line Loading @@ -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 |\ Loading Loading @@ -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 && Loading Loading @@ -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 Loading Loading @@ -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; } Loading Loading @@ -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); Loading
drivers/scsi/ufs/ufshcd.h +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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