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

Commit 0a4e7663 authored by Asutosh Das's avatar Asutosh Das Committed by Anjana
Browse files

scsi: ufs: Add freeze and restore callbacks



Adds freeze, thaw and restore callbacks for hibernate and restore
functionality.

Change-Id: I5db830d4d7b29d54043eb80cbc5e8684b95a82e6
Signed-off-by: default avatarAsutosh Das <asutoshd@codeaurora.org>
Signed-off-by: default avatarAnjana <ahari@codeaurora.org>
parent 2537e5e5
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -370,6 +370,45 @@ static void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba)
}

#ifdef CONFIG_SMP
/**
 * ufshcd_pltfrm_restore - restore power management function
 * @dev: pointer to device handle
 *
 * Returns 0 if successful
 * Returns non-zero otherwise
 */
int ufshcd_pltfrm_restore(struct device *dev)
{
	return ufshcd_system_restore(dev_get_drvdata(dev));
}
EXPORT_SYMBOL(ufshcd_pltfrm_restore);

/**
 * ufshcd_pltfrm_freeze - freeze power management function
 * @dev: pointer to device handle
 *
 * Returns 0 if successful
 * Returns non-zero otherwise
 */
int ufshcd_pltfrm_freeze(struct device *dev)
{
	return ufshcd_system_freeze(dev_get_drvdata(dev));
}
EXPORT_SYMBOL(ufshcd_pltfrm_freeze);

/**
 * ufshcd_pltfrm_thaw - freeze power management function
 * @dev: pointer to device handle
 *
 * Returns 0 if successful
 * Returns non-zero otherwise
 */
int ufshcd_pltfrm_thaw(struct device *dev)
{
	return ufshcd_system_thaw(dev_get_drvdata(dev));
}
EXPORT_SYMBOL(ufshcd_pltfrm_thaw);

/**
 * ufshcd_pltfrm_suspend - suspend power management function
 * @dev: pointer to device handle
+4 −1
Original line number Diff line number Diff line
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,9 @@ int ufshcd_pltfrm_resume(struct device *dev);
int ufshcd_pltfrm_runtime_suspend(struct device *dev);
int ufshcd_pltfrm_runtime_resume(struct device *dev);
int ufshcd_pltfrm_runtime_idle(struct device *dev);
int ufshcd_pltfrm_freeze(struct device *dev);
int ufshcd_pltfrm_restore(struct device *dev);
int ufshcd_pltfrm_thaw(struct device *dev);

#else /* !CONFIG_PM */

+41 −3
Original line number Diff line number Diff line
@@ -3817,8 +3817,8 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
	if (err) {
		if (err != -EAGAIN)
			dev_err(hba->dev,
				"%s: failed to compose upiu %d\n",
				__func__, err);
				"%s: failed to compose upiu %d cmd:0x%08x lun:%d\n",
				__func__, err, cmd, lrbp->lun);

		lrbp->cmd = NULL;
		clear_bit_unlock(tag, &hba->lrb_in_use);
@@ -10254,7 +10254,19 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
	ret = ufshcd_vreg_set_hpm(hba);
	if (ret)
		goto disable_irq_and_vops_clks;

	if (hba->restore) {
		/* Configure UTRL and UTMRL base address registers */
		ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr),
			      REG_UTP_TRANSFER_REQ_LIST_BASE_L);
		ufshcd_writel(hba, upper_32_bits(hba->utrdl_dma_addr),
			      REG_UTP_TRANSFER_REQ_LIST_BASE_H);
		ufshcd_writel(hba, lower_32_bits(hba->utmrdl_dma_addr),
			      REG_UTP_TASK_REQ_LIST_BASE_L);
		ufshcd_writel(hba, upper_32_bits(hba->utmrdl_dma_addr),
			      REG_UTP_TASK_REQ_LIST_BASE_H);
		/* Commit the registers */
		mb();
	}
	/*
	 * Call vendor specific resume callback. As these callbacks may access
	 * vendor specific host controller register space call them when the
@@ -10269,6 +10281,10 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
	     (ufshcd_is_card_online(hba) && !hba->sdev_ufs_device)))
		goto skip_dev_ops;

	/* Resuming from hibernate, assume that link was OFF */
	if (hba->restore)
		ufshcd_set_link_off(hba);

	if (ufshcd_is_link_hibern8(hba)) {
		ret = ufshcd_uic_hibern8_exit(hba);
		if (!ret) {
@@ -10340,6 +10356,9 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
out:
	hba->pm_op_in_progress = 0;

	if (hba->restore)
		hba->restore = false;

	if (ret)
		ufshcd_update_error_stats(hba, UFS_ERR_RESUME);

@@ -10502,6 +10521,25 @@ int ufshcd_runtime_idle(struct ufs_hba *hba)
}
EXPORT_SYMBOL(ufshcd_runtime_idle);

int ufshcd_system_freeze(struct ufs_hba *hba)
{
	return ufshcd_system_suspend(hba);
}
EXPORT_SYMBOL(ufshcd_system_freeze);

int ufshcd_system_restore(struct ufs_hba *hba)
{
	hba->restore = true;
	return ufshcd_system_resume(hba);
}
EXPORT_SYMBOL(ufshcd_system_restore);

int ufshcd_system_thaw(struct ufs_hba *hba)
{
	return ufshcd_system_resume(hba);
}
EXPORT_SYMBOL(ufshcd_system_thaw);

static inline ssize_t ufshcd_pm_lvl_store(struct device *dev,
					   struct device_attribute *attr,
					   const char *buf, size_t count,
+8 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
 *
 * This code is based on drivers/scsi/ufs/ufshcd.h
 * Copyright (C) 2011-2013 Samsung India Software Operations
 * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
 *
 * Authors:
 *	Santosh Yaraganavi <santosh.sy@samsung.com>
@@ -112,11 +112,13 @@ enum ufs_pm_op {
	UFS_RUNTIME_PM,
	UFS_SYSTEM_PM,
	UFS_SHUTDOWN_PM,
	UFS_SYSTEM_RESTORE,
};

#define ufshcd_is_runtime_pm(op) ((op) == UFS_RUNTIME_PM)
#define ufshcd_is_system_pm(op) ((op) == UFS_SYSTEM_PM)
#define ufshcd_is_shutdown_pm(op) ((op) == UFS_SHUTDOWN_PM)
#define ufshcd_is_restore(op) ((op) == UFS_SYSTEM_RESTORE)

/* Host <-> Device UniPro Link state */
enum uic_link_state {
@@ -1042,6 +1044,8 @@ struct ufs_hba {

	bool reinit_g4_rate_A;
	bool force_g4;
	/* distinguish between resume and restore */
	bool restore;
};

static inline void ufshcd_mark_shutdown_ongoing(struct ufs_hba *hba)
@@ -1171,6 +1175,9 @@ static inline bool ufshcd_keep_autobkops_enabled_except_suspend(
	return hba->caps & UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND;
}

extern int ufshcd_system_thaw(struct ufs_hba *hba);
extern int ufshcd_system_restore(struct ufs_hba *hba);
extern int ufshcd_system_freeze(struct ufs_hba *hba);
extern int ufshcd_runtime_suspend(struct ufs_hba *hba);
extern int ufshcd_runtime_resume(struct ufs_hba *hba);
extern int ufshcd_runtime_idle(struct ufs_hba *hba);