ice: fix issue with losing ICE key configuration during reset

TZ is called to restore key configuration in case of UFS reset

Change-Id: Id434e7f9ec6befdce97f52fd350957b66adcb15f
Signed-off-by: Andrey Markovytch <andreym@codeaurora.org>
This commit is contained in:
Andrey Markovytch 2017-02-08 14:32:22 +02:00 committed by Gerrit - the friendly Code Review server
parent 2aa89ab3ff
commit a1cd6239e4
5 changed files with 86 additions and 3 deletions

View file

@ -24,6 +24,7 @@
#include <linux/pfk.h>
#include <crypto/ice.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/qseecomi.h>
#include "iceregs.h"
#define TZ_SYSCALL_CREATE_SMC_ID(o, s, f) \
@ -40,6 +41,13 @@
#define TZ_OS_KS_RESTORE_KEY_ID_PARAM_ID \
TZ_SYSCALL_CREATE_PARAM_ID_0
#define TZ_OS_KS_RESTORE_KEY_CONFIG_ID \
TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_KEYSTORE, 0x06)
#define TZ_OS_KS_RESTORE_KEY_CONFIG_ID_PARAM_ID \
TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL)
#define ICE_REV(x, y) (((x) & ICE_CORE_##y##_REV_MASK) >> ICE_CORE_##y##_REV)
#define QCOM_UFS_ICE_DEV "iceufs"
#define QCOM_SDCC_ICE_DEV "icesdcc"
@ -830,6 +838,24 @@ static int qcom_ice_restore_config(void)
return ret;
}
static int qcom_ice_restore_key_config(void)
{
struct scm_desc desc = {0};
int ret = -1;
/* For ice 3, key configuration needs to be restored in case of reset */
desc.arginfo = TZ_OS_KS_RESTORE_KEY_CONFIG_ID_PARAM_ID;
desc.args[0] = 10; /* UFS_ICE */
ret = scm_call2(TZ_OS_KS_RESTORE_KEY_CONFIG_ID, &desc);
if (ret)
pr_err("%s: Error: 0x%x\n", __func__, ret);
return ret;
}
static int qcom_ice_init_clocks(struct ice_device *ice)
{
int ret = -EINVAL;
@ -1103,6 +1129,22 @@ static int qcom_ice_finish_power_collapse(struct ice_device *ice_dev)
err = -EFAULT;
goto out;
}
/*
* ICE looses its key configuration when UFS is reset,
* restore it
*/
} else if (ICE_REV(ice_dev->ice_hw_version, MAJOR) > 2) {
err = qcom_ice_restore_key_config();
if (err)
goto out;
/*
* for PFE case, clear the cached ICE key table,
* this will force keys to be reconfigured
* per each next transaction
*/
pfk_clear_on_reset();
}
}

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2017, 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
@ -24,6 +24,7 @@ int pfk_load_key_start(const struct bio *bio,
int pfk_load_key_end(const struct bio *bio, bool *is_pfe);
int pfk_remove_key(const unsigned char *key, size_t key_size);
bool pfk_allow_merge_bio(const struct bio *bio1, const struct bio *bio2);
void pfk_clear_on_reset(void);
#else
static inline int pfk_load_key_start(const struct bio *bio,
@ -48,6 +49,9 @@ static inline bool pfk_allow_merge_bio(const struct bio *bio1,
return true;
}
static inline void pfk_clear_on_reset(void)
{}
#endif /* CONFIG_PFK */
#endif /* PFK_H */

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2017, 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
@ -476,6 +476,18 @@ bool pfk_allow_merge_bio(const struct bio *bio1, const struct bio *bio2)
return (*(pfk_allow_merge_bio_ftable[which_pfe1]))(bio1, bio2,
inode1, inode2);
}
/**
* Flush key table on storage core reset. During core reset key configuration
* is lost in ICE. We need to flash the cache, so that the keys will be
* reconfigured again for every subsequent transaction
*/
void pfk_clear_on_reset(void)
{
if (!pfk_is_ready())
return;
pfk_kc_clear_on_reset();
}
module_init(pfk_init);
module_exit(pfk_exit);

View file

@ -826,3 +826,27 @@ out:
return res;
}
/**
* pfk_kc_clear_on_reset() - clear the table and remove all keys from ICE
* The assumption is that at this point we don't have any pending transactions
* Also, there is no need to clear keys from ICE
*
* Return 0 on success, error otherwise
*
*/
void pfk_kc_clear_on_reset(void)
{
struct kc_entry *entry = NULL;
int i = 0;
if (!kc_is_ready())
return;
kc_spin_lock();
for (i = 0; i < PFK_KC_TABLE_SIZE; i++) {
entry = kc_entry_at_index(i);
kc_clear_entry(entry);
}
kc_spin_unlock();
}

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2017, 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
@ -26,6 +26,7 @@ int pfk_kc_remove_key_with_salt(const unsigned char *key, size_t key_size,
const unsigned char *salt, size_t salt_size);
int pfk_kc_remove_key(const unsigned char *key, size_t key_size);
int pfk_kc_clear(void);
void pfk_kc_clear_on_reset(void);