Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 492d614a authored by Asutosh Das's avatar Asutosh Das Committed by Sayali Lokhande
Browse files

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: default avatarAsutosh Das <asutoshd@codeaurora.org>
Signed-off-by: default avatarSayali Lokhande <sayalil@codeaurora.org>
parent bd208931
Loading
Loading
Loading
Loading
+55 −2
Original line number Diff line number Diff line
@@ -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);
+3 −1
Original line number Diff line number Diff line
@@ -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)