Blob Blame History Raw
From: =?UTF-8?q?Antoine=20T=C3=A9nart?= <antoine.tenart@free-electrons.com>
Date: Thu, 14 Dec 2017 15:26:52 +0100
Subject: crypto: inside-secure - use threaded IRQs for result handling

Git-commit: 69ee4dd5ea8ce0b45d2fae03f6bda1044577705f
Patch-mainline: v4.16-rc1
References: fate#326470

This patch moves the result handling from an IRQ handler to a threaded
IRQ handler, to improve the number of complete requests being handled at
once.

Suggested-by: Ofer Heifetz <oferh@marvell.com>
Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
---
 drivers/crypto/inside-secure/safexcel.c | 41 ++++++++++++++++++---------------
 drivers/crypto/inside-secure/safexcel.h |  1 -
 2 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c
index f422af3eed2f..aa4943cad55e 100644
--- a/drivers/crypto/inside-secure/safexcel.c
+++ b/drivers/crypto/inside-secure/safexcel.c
@@ -618,15 +618,6 @@ static inline void safexcel_handle_result_descriptor(struct safexcel_crypto_priv
 	}
 }
 
-static void safexcel_handle_result_work(struct work_struct *work)
-{
-	struct safexcel_work_data *data =
-			container_of(work, struct safexcel_work_data, result_work);
-	struct safexcel_crypto_priv *priv = data->priv;
-
-	safexcel_handle_result_descriptor(priv, data->ring);
-}
-
 static void safexcel_dequeue_work(struct work_struct *work)
 {
 	struct safexcel_work_data *data =
@@ -644,12 +635,12 @@ static irqreturn_t safexcel_irq_ring(int irq, void *data)
 {
 	struct safexcel_ring_irq_data *irq_data = data;
 	struct safexcel_crypto_priv *priv = irq_data->priv;
-	int ring = irq_data->ring;
+	int ring = irq_data->ring, rc = IRQ_NONE;
 	u32 status, stat;
 
 	status = readl(priv->base + EIP197_HIA_AIC_R_ENABLED_STAT(ring));
 	if (!status)
-		return IRQ_NONE;
+		return rc;
 
 	/* RDR interrupts */
 	if (status & EIP197_RDR_IRQ(ring)) {
@@ -663,10 +654,7 @@ static irqreturn_t safexcel_irq_ring(int irq, void *data)
 			 */
 			dev_err(priv->dev, "RDR: fatal error.");
 		} else if (likely(stat & EIP197_xDR_THRESH)) {
-			queue_work(priv->ring[ring].workqueue,
-				   &priv->ring[ring].work_data.result_work);
-			queue_work(priv->ring[ring].workqueue,
-				   &priv->ring[ring].work_data.work);
+			rc = IRQ_WAKE_THREAD;
 		}
 
 		/* ACK the interrupts */
@@ -677,11 +665,26 @@ static irqreturn_t safexcel_irq_ring(int irq, void *data)
 	/* ACK the interrupts */
 	writel(status, priv->base + EIP197_HIA_AIC_R_ACK(ring));
 
+	return rc;
+}
+
+static irqreturn_t safexcel_irq_ring_thread(int irq, void *data)
+{
+	struct safexcel_ring_irq_data *irq_data = data;
+	struct safexcel_crypto_priv *priv = irq_data->priv;
+	int ring = irq_data->ring;
+
+	safexcel_handle_result_descriptor(priv, ring);
+
+	queue_work(priv->ring[ring].workqueue,
+		   &priv->ring[ring].work_data.work);
+
 	return IRQ_HANDLED;
 }
 
 static int safexcel_request_ring_irq(struct platform_device *pdev, const char *name,
 				     irq_handler_t handler,
+				     irq_handler_t threaded_handler,
 				     struct safexcel_ring_irq_data *ring_irq_priv)
 {
 	int ret, irq = platform_get_irq_byname(pdev, name);
@@ -691,8 +694,9 @@ static int safexcel_request_ring_irq(struct platform_device *pdev, const char *n
 		return irq;
 	}
 
-	ret = devm_request_irq(&pdev->dev, irq, handler, 0,
-			       dev_name(&pdev->dev), ring_irq_priv);
+	ret = devm_request_threaded_irq(&pdev->dev, irq, handler,
+					threaded_handler, IRQF_ONESHOT,
+					dev_name(&pdev->dev), ring_irq_priv);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to request IRQ %d\n", irq);
 		return ret;
@@ -839,6 +843,7 @@ static int safexcel_probe(struct platform_device *pdev)
 
 		snprintf(irq_name, 6, "ring%d", i);
 		irq = safexcel_request_ring_irq(pdev, irq_name, safexcel_irq_ring,
+						safexcel_irq_ring_thread,
 						ring_irq);
 		if (irq < 0) {
 			ret = irq;
@@ -847,8 +852,6 @@ static int safexcel_probe(struct platform_device *pdev)
 
 		priv->ring[i].work_data.priv = priv;
 		priv->ring[i].work_data.ring = i;
-		INIT_WORK(&priv->ring[i].work_data.result_work,
-			  safexcel_handle_result_work);
 		INIT_WORK(&priv->ring[i].work_data.work, safexcel_dequeue_work);
 
 		snprintf(wq_name, 9, "wq_ring%d", i);
diff --git a/drivers/crypto/inside-secure/safexcel.h b/drivers/crypto/inside-secure/safexcel.h
index 8e9c65183439..fffddefb0d9b 100644
--- a/drivers/crypto/inside-secure/safexcel.h
+++ b/drivers/crypto/inside-secure/safexcel.h
@@ -459,7 +459,6 @@ struct safexcel_config {
 
 struct safexcel_work_data {
 	struct work_struct work;
-	struct work_struct result_work;
 	struct safexcel_crypto_priv *priv;
 	int ring;
 };
-- 
2.11.0