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

Commit b9fca76e authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "scsi: ufs-ice: fix ICE error handler"

parents 55461996 f8435977
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -1532,11 +1532,7 @@ static int qcom_ice_status(struct platform_device *pdev)
	test_bus_reg_status = qcom_ice_readl(ice_dev,
					QCOM_ICE_REGS_TEST_BUS_REG);

	if ((test_bus_reg_status & QCOM_ICE_TEST_BUS_REG_NON_SECURE_INTR) ||
	    (test_bus_reg_status & QCOM_ICE_TEST_BUS_REG_NON_SECURE_INTR))
		return 1;
	else
		return 0;
	return !!(test_bus_reg_status & QCOM_ICE_TEST_BUS_REG_NON_SECURE_INTR);

}
EXPORT_SYMBOL(qcom_ice_status);
+7 −48
Original line number Diff line number Diff line
@@ -707,53 +707,14 @@ out:
	return err;
}

static int ufs_qcom_crypto_engine_eh(struct ufs_hba *hba)
static int ufs_qcom_crypto_engine_get_status(struct ufs_hba *hba, u32 *status)
{
	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
	int ice_status = 0;
	int err = 0;

	host->ice.crypto_engine_err = 0;

	if (host->ice.quirks &
	    UFS_QCOM_ICE_QUIRK_HANDLE_CRYPTO_ENGINE_ERRORS) {
		err = ufs_qcom_ice_get_status(host, &ice_status);
		if (!err)
			host->ice.crypto_engine_err = ice_status;

		if (host->ice.crypto_engine_err) {
			dev_err(hba->dev, "%s handling crypto engine error\n",
					__func__);
			/*
			 * block commands from scsi mid-layer.
			 * As crypto error is a fatal error and will result in
			 * a host reset we should leave scsi mid layer blocked
			 * until host reset is completed.
			 * Host reset will be handled in a seperate workqueue
			 * and will be triggered from ufshcd_check_errors.
			 */
			ufshcd_scsi_block_requests(hba);

			ufshcd_abort_outstanding_transfer_requests(hba,
					DID_TARGET_FAILURE);
		}
	}

	return host->ice.crypto_engine_err;
}

static int ufs_qcom_crypto_engine_get_err(struct ufs_hba *hba)
{
	struct ufs_qcom_host *host = ufshcd_get_variant(hba);

	return host->ice.crypto_engine_err;
}

static void ufs_qcom_crypto_engine_reset_err(struct ufs_hba *hba)
{
	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
	if (!status)
		return -EINVAL;

	host->ice.crypto_engine_err = 0;
	return ufs_qcom_ice_get_status(host, status);
}

struct ufs_qcom_dev_params {
@@ -2286,9 +2247,7 @@ static struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
static struct ufs_hba_crypto_variant_ops ufs_hba_crypto_variant_ops = {
	.crypto_engine_cfg	  = ufs_qcom_crytpo_engine_cfg,
	.crypto_engine_reset	  = ufs_qcom_crytpo_engine_reset,
	.crypto_engine_eh	= ufs_qcom_crypto_engine_eh,
	.crypto_engine_get_err	= ufs_qcom_crypto_engine_get_err,
	.crypto_engine_reset_err = ufs_qcom_crypto_engine_reset_err,
	.crypto_engine_get_status = ufs_qcom_crypto_engine_get_status,
};

static struct ufs_hba_pm_qos_variant_ops ufs_hba_pm_qos_variant_ops = {
+0 −6
Original line number Diff line number Diff line
@@ -212,12 +212,6 @@ struct ufs_qcom_ice_data {
	struct platform_device *pdev;
	int state;

	/*
	 * If UFS host controller should handle cryptographic engine's
	 * errors, enables this quirk.
	 */
	#define UFS_QCOM_ICE_QUIRK_HANDLE_CRYPTO_ENGINE_ERRORS	UFS_BIT(0)

	u16 quirks;

	bool crypto_engine_err;
+11 −16
Original line number Diff line number Diff line
@@ -629,8 +629,8 @@ static void ufshcd_print_host_state(struct ufs_hba *hba)
	dev_err(hba->dev, "UFS Host state=%d\n", hba->ufshcd_state);
	dev_err(hba->dev, "lrb in use=0x%lx, outstanding reqs=0x%lx tasks=0x%lx\n",
		hba->lrb_in_use, hba->outstanding_tasks, hba->outstanding_reqs);
	dev_err(hba->dev, "saved_err=0x%x, saved_uic_err=0x%x\n",
		hba->saved_err, hba->saved_uic_err);
	dev_err(hba->dev, "saved_err=0x%x, saved_uic_err=0x%x, saved_ce_err=0x%x\n",
		hba->saved_err, hba->saved_uic_err, hba->saved_ce_err);
	dev_err(hba->dev, "Device power mode=%d, UIC link state=%d\n",
		hba->curr_dev_pwr_mode, hba->uic_link_state);
	dev_err(hba->dev, "PM in progress=%d, sys. suspended=%d\n",
@@ -5421,7 +5421,6 @@ static void ufshcd_err_handler(struct work_struct *work)
	bool err_xfer = false, err_tm = false;
	int err = 0;
	int tag;
	int crypto_engine_err = 0;
	bool needs_reset = false;

	hba = container_of(work, struct ufs_hba, eh_work);
@@ -5465,9 +5464,7 @@ static void ufshcd_err_handler(struct work_struct *work)
		}
	}

	crypto_engine_err = ufshcd_vops_crypto_engine_get_err(hba);

	if ((hba->saved_err & INT_FATAL_ERRORS) || crypto_engine_err ||
	if ((hba->saved_err & INT_FATAL_ERRORS) || hba->saved_ce_err ||
	    ((hba->saved_err & UIC_ERROR) &&
	    (hba->saved_uic_err & (UFSHCD_UIC_DL_PA_INIT_ERROR |
				   UFSHCD_UIC_DL_NAC_RECEIVED_ERROR |
@@ -5514,9 +5511,11 @@ skip_pending_xfer_clear:
	if (needs_reset) {
		unsigned long max_doorbells = (1UL << hba->nutrs) - 1;

		if (hba->saved_err & INT_FATAL_ERRORS || crypto_engine_err)
		if (hba->saved_err & INT_FATAL_ERRORS)
			ufshcd_update_error_stats(hba,
						  UFS_ERR_INT_FATAL_ERRORS);
		if (hba->saved_ce_err)
			ufshcd_update_error_stats(hba, UFS_ERR_CRYPTO_ENGINE);

		if (hba->saved_err & UIC_ERROR)
			ufshcd_update_error_stats(hba,
@@ -5552,7 +5551,7 @@ skip_pending_xfer_clear:
		scsi_report_bus_reset(hba->host, 0);
		hba->saved_err = 0;
		hba->saved_uic_err = 0;
		ufshcd_vops_crypto_engine_reset_err(hba);
		hba->saved_ce_err = 0;
	}

skip_err_handling:
@@ -5648,11 +5647,8 @@ static void ufshcd_update_uic_error(struct ufs_hba *hba)
static void ufshcd_check_errors(struct ufs_hba *hba)
{
	bool queue_eh_work = false;
	int crypto_engine_err = 0;

	crypto_engine_err = ufshcd_vops_crypto_engine_get_err(hba);

	if (hba->errors & INT_FATAL_ERRORS || crypto_engine_err)
	if (hba->errors & INT_FATAL_ERRORS || hba->ce_error)
		queue_eh_work = true;

	if (hba->errors & UIC_ERROR) {
@@ -5669,6 +5665,7 @@ static void ufshcd_check_errors(struct ufs_hba *hba)
		 */
		hba->saved_err |= hba->errors;
		hba->saved_uic_err |= hba->uic_error;
		hba->saved_ce_err |= hba->ce_error;

		/* handle fatal errors only when link is functional */
		if (hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL) {
@@ -5707,15 +5704,13 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba)
 */
static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)
{
	bool crypto_engine_err = false;

	ufsdbg_error_inject_dispatcher(hba,
		ERR_INJECT_INTR, intr_status, &intr_status);

	ufshcd_vops_crypto_engine_eh(hba);
	ufshcd_vops_crypto_engine_get_status(hba, &hba->ce_error);

	hba->errors = UFSHCD_ERROR_MASK & intr_status;
	if (hba->errors || crypto_engine_err)
	if (hba->errors || hba->ce_error)
		ufshcd_check_errors(hba);

	if (intr_status & UFSHCD_UIC_MASK)
+9 −21
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ enum {
	UFS_ERR_CLEAR_PEND_XFER_TM,
	UFS_ERR_INT_FATAL_ERRORS,
	UFS_ERR_INT_UIC_ERROR,
	UFS_ERR_CRYPTO_ENGINE,

	/* other errors */
	UFS_ERR_HIBERN8_ENTER,
@@ -351,9 +352,7 @@ struct ufs_hba_variant_ops {
struct ufs_hba_crypto_variant_ops {
	int	(*crypto_engine_cfg)(struct ufs_hba *, unsigned int);
	int	(*crypto_engine_reset)(struct ufs_hba *);
	int	(*crypto_engine_eh)(struct ufs_hba *);
	int	(*crypto_engine_get_err)(struct ufs_hba *);
	void	(*crypto_engine_reset_err)(struct ufs_hba *);
	int	(*crypto_engine_get_status)(struct ufs_hba *, u32 *);
};

/**
@@ -797,8 +796,10 @@ struct ufs_hba {
	/* HBA Errors */
	u32 errors;
	u32 uic_error;
	u32 ce_error;	/* crypto engine errors */
	u32 saved_err;
	u32 saved_uic_err;
	u32 saved_ce_err;
	bool silence_err_logs;

	/* Device management request data */
@@ -1229,29 +1230,16 @@ static inline int ufshcd_vops_crypto_engine_reset(struct ufs_hba *hba)
	return 0;
}

static inline int ufshcd_vops_crypto_engine_eh(struct ufs_hba *hba)
static inline int ufshcd_vops_crypto_engine_get_status(struct ufs_hba *hba,
		u32 *status)
{
	if (hba->var && hba->var->crypto_vops &&
	    hba->var->crypto_vops->crypto_engine_eh)
		return hba->var->crypto_vops->crypto_engine_eh(hba);
	    hba->var->crypto_vops->crypto_engine_get_status)
		return hba->var->crypto_vops->crypto_engine_get_status(hba,
			status);
	return 0;
}

static inline int ufshcd_vops_crypto_engine_get_err(struct ufs_hba *hba)
{
	if (hba->var && hba->var->crypto_vops &&
	    hba->var->crypto_vops->crypto_engine_get_err)
		return hba->var->crypto_vops->crypto_engine_get_err(hba);
	return 0;
}

static inline void ufshcd_vops_crypto_engine_reset_err(struct ufs_hba *hba)
{
	if (hba->var && hba->var->crypto_vops &&
	    hba->var->crypto_vops->crypto_engine_reset_err)
		hba->var->crypto_vops->crypto_engine_reset_err(hba);
}

static inline void ufshcd_vops_pm_qos_req_start(struct ufs_hba *hba,
		struct request *req)
{