msm: ice: check for crypto engine state before processing request
Crypto engine can be put to suspend by host controller after workqueue is scheduled. Also shutdown sequence can be ongoing while workqueue is scheduled/executing. The request passed to crypto driver in these cases can be invalidated by host device driver. So check for crypto engine state before processing the pending requests. Change-Id: I4aa2a211e439a876c8525ab062a7cb917b4e2d7e Signed-off-by: Prerna Kalla <prernak@codeaurora.org>
This commit is contained in:
@@ -20,7 +20,8 @@
|
||||
#include <soc/qcom/qseecomi.h>
|
||||
#include "iceregs.h"
|
||||
#include <linux/pfk.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#define TZ_SYSCALL_CREATE_SMC_ID(o, s, f) \
|
||||
((uint32_t)((((o & 0x3f) << 24) | (s & 0xff) << 8) | (f & 0xff)))
|
||||
@@ -800,6 +801,28 @@ static int qcom_ice_remove(struct platform_device *pdev)
|
||||
|
||||
static int qcom_ice_suspend(struct platform_device *pdev)
|
||||
{
|
||||
struct ice_device *ice_dev;
|
||||
int ret;
|
||||
|
||||
ice_dev = (struct ice_device *)platform_get_drvdata(pdev);
|
||||
|
||||
if (!ice_dev)
|
||||
return -EINVAL;
|
||||
if (atomic_read(&ice_dev->is_ice_busy) != 0) {
|
||||
ret = wait_event_interruptible_timeout(
|
||||
ice_dev->block_suspend_ice_queue,
|
||||
atomic_read(&ice_dev->is_ice_busy) == 0,
|
||||
msecs_to_jiffies(1000));
|
||||
|
||||
if (!ret) {
|
||||
pr_err("%s: Suspend ICE during an ongoing operation\n",
|
||||
__func__);
|
||||
atomic_set(&ice_dev->is_ice_suspended, 0);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
atomic_set(&ice_dev->is_ice_suspended, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1030,7 +1053,7 @@ static int qcom_ice_finish_init(struct ice_device *ice_dev)
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&ice_dev->block_suspend_ice_queue);
|
||||
qcom_ice_low_power_mode_enable(ice_dev);
|
||||
qcom_ice_optimization_enable(ice_dev);
|
||||
qcom_ice_config_proc_ignore(ice_dev);
|
||||
@@ -1038,7 +1061,8 @@ static int qcom_ice_finish_init(struct ice_device *ice_dev)
|
||||
qcom_ice_enable(ice_dev);
|
||||
ice_dev->is_ice_enabled = true;
|
||||
qcom_ice_enable_intr(ice_dev);
|
||||
|
||||
atomic_set(&ice_dev->is_ice_suspended, 0);
|
||||
atomic_set(&ice_dev->is_ice_busy, 0);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
@@ -1145,7 +1169,7 @@ static int qcom_ice_resume(struct platform_device *pdev)
|
||||
*/
|
||||
qcom_ice_enable(ice_dev);
|
||||
}
|
||||
|
||||
atomic_set(&ice_dev->is_ice_suspended, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1415,8 +1439,20 @@ static int qcom_ice_config_start(struct platform_device *pdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (atomic_read(&ice_dev->is_ice_suspended) == 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (async)
|
||||
atomic_set(&ice_dev->is_ice_busy, 1);
|
||||
|
||||
ret = pfk_load_key_start(req->bio, ice_dev, &pfk_crypto_data,
|
||||
&is_pfe, async);
|
||||
|
||||
if (async) {
|
||||
atomic_set(&ice_dev->is_ice_busy, 0);
|
||||
wake_up_interruptible(&ice_dev->block_suspend_ice_queue);
|
||||
}
|
||||
|
||||
if (is_pfe) {
|
||||
if (ret) {
|
||||
if (ret != -EBUSY && ret != -EAGAIN)
|
||||
|
||||
@@ -180,7 +180,8 @@ static void ufs_qcom_ice_cfg_work(struct work_struct *work)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&qcom_host->ice_work_lock, flags);
|
||||
if (!qcom_host->req_pending) {
|
||||
if (!qcom_host->req_pending ||
|
||||
ufshcd_is_shutdown_ongoing(qcom_host->hba)) {
|
||||
qcom_host->work_pending = false;
|
||||
spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags);
|
||||
return;
|
||||
@@ -228,7 +229,7 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *qcom_host)
|
||||
qcom_host->dbg_print_en |= UFS_QCOM_ICE_DEFAULT_DBG_PRINT_EN;
|
||||
if (!ice_workqueue) {
|
||||
ice_workqueue = alloc_workqueue("ice-set-key",
|
||||
WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
|
||||
WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_FREEZABLE, 0);
|
||||
if (!ice_workqueue) {
|
||||
dev_err(ufs_dev, "%s: workqueue allocation failed.\n",
|
||||
__func__);
|
||||
@@ -659,6 +660,28 @@ int ufs_qcom_ice_resume(struct ufs_qcom_host *qcom_host)
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufs_qcom_is_ice_busy() - lets the caller of the function know if
|
||||
* there is any ongoing operation in ICE in workqueue context.
|
||||
* @qcom_host: Pointer to a UFS QCom internal host structure.
|
||||
* qcom_host should be a valid pointer.
|
||||
*
|
||||
* Return: 1 if ICE is busy, 0 if it is free.
|
||||
* -EINVAL in case of error.
|
||||
*/
|
||||
int ufs_qcom_is_ice_busy(struct ufs_qcom_host *qcom_host)
|
||||
{
|
||||
if (!qcom_host) {
|
||||
pr_err("%s: invalid qcom_host\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (qcom_host->req_pending)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufs_qcom_ice_suspend() - suspends UFS-ICE interface and ICE device
|
||||
* @qcom_host: Pointer to a UFS QCom internal host structure.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2014-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
|
||||
@@ -84,6 +84,7 @@ int ufs_qcom_ice_resume(struct ufs_qcom_host *qcom_host);
|
||||
int ufs_qcom_ice_suspend(struct ufs_qcom_host *qcom_host);
|
||||
int ufs_qcom_ice_get_status(struct ufs_qcom_host *qcom_host, int *ice_status);
|
||||
void ufs_qcom_ice_print_regs(struct ufs_qcom_host *qcom_host);
|
||||
int ufs_qcom_is_ice_busy(struct ufs_qcom_host *qcom_host);
|
||||
#else
|
||||
inline int ufs_qcom_ice_get_dev(struct ufs_qcom_host *qcom_host)
|
||||
{
|
||||
@@ -127,6 +128,10 @@ inline int ufs_qcom_ice_get_status(struct ufs_qcom_host *qcom_host,
|
||||
inline void ufs_qcom_ice_print_regs(struct ufs_qcom_host *qcom_host)
|
||||
{
|
||||
}
|
||||
static inline int ufs_qcom_is_ice_busy(struct ufs_qcom_host *qcom_host)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_SCSI_UFS_QCOM_ICE */
|
||||
|
||||
#endif /* UFS_QCOM_ICE_H_ */
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
struct request;
|
||||
|
||||
@@ -68,6 +70,9 @@ struct ice_device {
|
||||
ktime_t ice_reset_start_time;
|
||||
ktime_t ice_reset_complete_time;
|
||||
void *key_table;
|
||||
atomic_t is_ice_suspended;
|
||||
atomic_t is_ice_busy;
|
||||
wait_queue_head_t block_suspend_ice_queue;
|
||||
};
|
||||
|
||||
struct ice_crypto_setting {
|
||||
|
||||
Reference in New Issue
Block a user