From 1286c9b10f76b122ad1b328cc1bec17ac4d5908e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Horia=20Geant=C4=83?= <horia.geanta@nxp.com>
Date: Wed, 13 Nov 2019 09:42:34 +0200
Subject: [PATCH] LFV-26 crypto: caam - fix Secure Memory driver init
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

SM driver is buggy, since it runs irrespective of the presence of
the caam-sm DT node.
This causes issues on SoCs that have caam HW, but without support
for secure memory.

Let's transform the module in a library, in the same way (and for
the same reasons) we did for the other job ring-dependent drivers
(caamalg, caamhash etc.) in
commit 1b46c90c8e00 ("crypto: caam - convert top level drivers to libraries")

SM test module is also updated, to run only when needed.

Fixes: 54e3fcf89f97 ("MLKU-25-3 crypto: caam - add Secure Memory support")
Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
Reviewed-by: Iuliana Prodan <iuliana.prodan@nxp.com>
---
 drivers/crypto/caam/Kconfig    |  2 +-
 drivers/crypto/caam/ctrl.c     |  2 ++
 drivers/crypto/caam/intern.h   | 19 ++++++++++
 drivers/crypto/caam/jr.c       |  6 ++--
 drivers/crypto/caam/sm.h       |  1 -
 drivers/crypto/caam/sm_store.c | 80 +++++-------------------------------------
 drivers/crypto/caam/sm_test.c  |  7 ++++
 7 files changed, 42 insertions(+), 75 deletions(-)

--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -167,7 +167,7 @@ config CRYPTO_DEV_FSL_CAAM_RNG_TEST
 	  just before the RNG is registered with the hw_random API.
 
 config CRYPTO_DEV_FSL_CAAM_SM
-	tristate "CAAM Secure Memory / Keystore API (EXPERIMENTAL)"
+	bool "CAAM Secure Memory / Keystore API (EXPERIMENTAL)"
 	help
 	  Enables use of a prototype kernel-level Keystore API with CAAM
 	  Secure Memory for insertion/extraction of bus-protected secrets.
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -763,6 +763,8 @@ iomap_ctrl:
 		ctrlpriv->sm_size = resource_size(&res_regs);
 	else
 		ctrlpriv->sm_size = PG_SIZE_64K;
+
+	ctrlpriv->sm_present = 1;
 	of_node_put(np);
 
 	if (!reg_access)
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -86,6 +86,7 @@ struct caam_drv_private {
 	 */
 	u8 total_jobrs;		/* Total Job Rings in device */
 	u8 qi_present;		/* Nonzero if QI present in device */
+	u8 sm_present;		/* Nonzero if Secure Memory is supported */
 	u8 mc_en;		/* Nonzero if MC f/w is active */
 	u8 scu_en;		/* Nonzero if SCU f/w is active */
 	u8 optee_en;		/* Nonzero if OP-TEE f/w is active */
@@ -200,6 +201,24 @@ static inline void caam_qi_algapi_exit(v
 
 #endif /* CONFIG_CAAM_QI */
 
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_SM
+
+int caam_sm_startup(struct device *dev);
+void caam_sm_shutdown(struct device *dev);
+
+#else
+
+static inline int caam_sm_startup(struct device *dev)
+{
+	return 0;
+}
+
+static inline void caam_sm_shutdown(struct device *dev)
+{
+}
+
+#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_SM */
+
 #ifdef CONFIG_DEBUG_FS
 static int caam_debugfs_u64_get(void *data, u64 *val)
 {
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -34,6 +34,7 @@ static void register_algs(struct device
 	if (++active_devs != 1)
 		goto algs_unlock;
 
+	caam_sm_startup(dev);
 	caam_algapi_init(dev);
 	caam_algapi_hash_init(dev);
 	caam_pkc_init(dev);
@@ -44,7 +45,7 @@ algs_unlock:
 	mutex_unlock(&algs_lock);
 }
 
-static void unregister_algs(void)
+static void unregister_algs(struct device *dev)
 {
 	mutex_lock(&algs_lock);
 
@@ -57,6 +58,7 @@ static void unregister_algs(void)
 	caam_pkc_exit();
 	caam_algapi_hash_exit();
 	caam_algapi_exit();
+	caam_sm_shutdown(dev);
 
 algs_unlock:
 	mutex_unlock(&algs_lock);
@@ -143,7 +145,7 @@ static int caam_jr_remove(struct platfor
 	}
 
 	/* Unregister JR-based RNG & crypto algorithms */
-	unregister_algs();
+	unregister_algs(jrdev->parent);
 
 	/* Remove the node from Physical JobR list maintained by driver */
 	spin_lock(&driver_data.jr_alloc_lock);
--- a/drivers/crypto/caam/sm.h
+++ b/drivers/crypto/caam/sm.h
@@ -41,7 +41,6 @@ void sm_init_keystore(struct device *dev
 u32 sm_detect_keystore_units(struct device *dev);
 int sm_establish_keystore(struct device *dev, u32 unit);
 void sm_release_keystore(struct device *dev, u32 unit);
-void caam_sm_shutdown(struct platform_device *pdev);
 int caam_sm_example_init(struct platform_device *pdev);
 
 /* Keystore accessor functions */
--- a/drivers/crypto/caam/sm_store.c
+++ b/drivers/crypto/caam/sm_store.c
@@ -1053,9 +1053,9 @@ EXPORT_SYMBOL(sm_keystore_slot_import);
  * Also, simply uses ring 0 for execution at the present
  */
 
-int caam_sm_startup(struct platform_device *pdev)
+int caam_sm_startup(struct device *ctrldev)
 {
-	struct device *ctrldev, *smdev;
+	struct device *smdev;
 	struct caam_drv_private *ctrlpriv;
 	struct caam_drv_private_sm *smpriv;
 	struct caam_drv_private_jr *jrpriv;	/* need this for reg page */
@@ -1065,17 +1065,10 @@ int caam_sm_startup(struct platform_devi
 	int ret = 0;
 
 	struct device_node *np;
-	ctrldev = &pdev->dev;
 	ctrlpriv = dev_get_drvdata(ctrldev);
 
-	/*
-	 * If ctrlpriv is NULL, it's probably because the caam driver wasn't
-	 * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
-	 */
-	if (!ctrlpriv) {
-		ret = -ENODEV;
-		goto exit;
-	}
+	if (!ctrlpriv->sm_present)
+		return 0;
 
 	/*
 	 * Set up the private block for secure memory
@@ -1248,14 +1241,16 @@ exit:
 	return ret;
 }
 
-void caam_sm_shutdown(struct platform_device *pdev)
+void caam_sm_shutdown(struct device *ctrldev)
 {
-	struct device *ctrldev, *smdev;
+	struct device *smdev;
 	struct caam_drv_private *priv;
 	struct caam_drv_private_sm *smpriv;
 
-	ctrldev = &pdev->dev;
 	priv = dev_get_drvdata(ctrldev);
+	if (!priv->sm_present)
+		return;
+
 	smdev = priv->smdev;
 
 	/* Return if resource not initialized by startup */
@@ -1273,60 +1268,3 @@ void caam_sm_shutdown(struct platform_de
 	kfree(smpriv);
 }
 EXPORT_SYMBOL(caam_sm_shutdown);
-
-static void  __exit caam_sm_exit(void)
-{
-	struct device_node *dev_node;
-	struct platform_device *pdev;
-
-	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
-	if (!dev_node) {
-		dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
-		if (!dev_node)
-			return;
-	}
-
-	pdev = of_find_device_by_node(dev_node);
-	if (!pdev)
-		return;
-
-	of_node_put(dev_node);
-
-	caam_sm_shutdown(pdev);
-
-	return;
-}
-
-static int __init caam_sm_init(void)
-{
-	struct device_node *dev_node;
-	struct platform_device *pdev;
-
-	/*
-	 * Do of_find_compatible_node() then of_find_device_by_node()
-	 * once a functional device tree is available
-	 */
-	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
-	if (!dev_node) {
-		dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
-		if (!dev_node)
-			return -ENODEV;
-	}
-
-	pdev = of_find_device_by_node(dev_node);
-	if (!pdev)
-		return -ENODEV;
-
-	of_node_get(dev_node);
-
-	caam_sm_startup(pdev);
-
-	return 0;
-}
-
-module_init(caam_sm_init);
-module_exit(caam_sm_exit);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("FSL CAAM Secure Memory / Keystore");
-MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD");
--- a/drivers/crypto/caam/sm_test.c
+++ b/drivers/crypto/caam/sm_test.c
@@ -531,6 +531,7 @@ static int __init caam_sm_test_init(void
 {
 	struct device_node *dev_node;
 	struct platform_device *pdev;
+	struct caam_drv_private *priv;
 	int ret;
 
 	/*
@@ -550,6 +551,12 @@ static int __init caam_sm_test_init(void
 
 	of_node_put(dev_node);
 
+	priv = dev_get_drvdata(&pdev->dev);
+	if (!priv->sm_present) {
+		dev_info(&pdev->dev, "No SM support, skipping tests\n");
+		return -ENODEV;
+	}
+
 	ret = caam_sm_example_init(pdev);
 	if (ret)
 		dev_err(&pdev->dev, "SM test failed: %d\n", ret);
