* [RFC PATCH v2 1/9] crypto: qce: Add core driver implementation
2014-04-14 12:48 [RFC PATCH v2 0/9] Add Qualcomm crypto driver Stanimir Varbanov
@ 2014-04-14 12:48 ` Stanimir Varbanov
2014-04-28 8:50 ` Herbert Xu
2014-04-28 8:59 ` Herbert Xu
2014-04-14 12:48 ` [RFC PATCH v2 9/9] ARM: DT: qcom: Add Qualcomm crypto driver binding document Stanimir Varbanov
2014-04-16 15:10 ` [RFC PATCH v2 0/9] Add Qualcomm crypto driver Stanimir Varbanov
2 siblings, 2 replies; 11+ messages in thread
From: Stanimir Varbanov @ 2014-04-14 12:48 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Grant Likely, Rob Herring
Cc: Stanimir Varbanov, linux-arm-msm, Mona Hossain,
Hariprasad Dhalinarasimha, Zhen Kong, Niranjana Vishwanathapura,
Rohit Vaswani, linux-kernel, linux-crypto, devicetree
This adds core driver files. The core part is implementing a
platform driver probe and remove callbaks, the probe enables
clocks, checks crypto version, initialize and request dma
channels, create done tasklet and work queue and finally
register the algorithms into crypto subsystem.
Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
---
drivers/crypto/qce/core.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/crypto/qce/core.h | 73 ++++++++++++
2 files changed, 368 insertions(+)
create mode 100644 drivers/crypto/qce/core.c
create mode 100644 drivers/crypto/qce/core.h
diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c
new file mode 100644
index 000000000000..61d08c5ff5b9
--- /dev/null
+++ b/drivers/crypto/qce/core.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2010-2014, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+#include <crypto/internal/hash.h>
+#include <crypto/sha.h>
+
+#include "core.h"
+#include "cipher.h"
+#include "sha.h"
+
+#define QCE_MAJOR_VERSION5 0x05
+#define QCE_QUEUE_LENGTH 50
+
+static int qce_async_request_queue(struct qce_device *qce,
+ struct crypto_async_request *req)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&qce->lock, flags);
+ ret = crypto_enqueue_request(&qce->queue, req);
+ spin_unlock_irqrestore(&qce->lock, flags);
+
+ queue_work(qce->queue_wq, &qce->queue_work);
+
+ return ret;
+}
+
+static void qce_async_request_done(struct qce_device *qce, int ret)
+{
+ qce->result = ret;
+ tasklet_schedule(&qce->done_tasklet);
+}
+
+static struct qce_algo_ops *qce_ops[] = {
+ &ablkcipher_ops,
+ &ahash_ops,
+};
+
+static void qce_unregister_algs(struct qce_device *qce)
+{
+ struct qce_algo_ops *ops;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
+ ops = qce_ops[i];
+ ops->unregister_algs(qce);
+ }
+}
+
+static int qce_register_algs(struct qce_device *qce)
+{
+ struct qce_algo_ops *ops;
+ int i, ret = -ENODEV;
+
+ qce->async_req_queue = qce_async_request_queue;
+ qce->async_req_done = qce_async_request_done;
+
+ for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
+ ops = qce_ops[i];
+ ret = ops->register_algs(qce);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static int qce_handle_request(struct crypto_async_request *async_req)
+{
+ int ret = -EINVAL, i;
+ struct qce_algo_ops *ops;
+ u32 type = crypto_tfm_alg_type(async_req->tfm);
+
+ for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
+ ops = qce_ops[i];
+ if (type != ops->type)
+ continue;
+ ret = ops->async_req_handle(async_req);
+ break;
+ }
+
+ return ret;
+}
+
+static void qce_reqqueue_handler(struct work_struct *work)
+{
+ struct qce_device *qce =
+ container_of(work, struct qce_device, queue_work);
+ struct crypto_async_request *async_req = NULL, *backlog = NULL;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&qce->lock, flags);
+ if (!qce->req) {
+ backlog = crypto_get_backlog(&qce->queue);
+ async_req = crypto_dequeue_request(&qce->queue);
+ qce->req = async_req;
+ }
+ spin_unlock_irqrestore(&qce->lock, flags);
+
+ if (!async_req)
+ return;
+
+ if (backlog)
+ backlog->complete(backlog, -EINPROGRESS);
+
+ ret = qce_handle_request(async_req);
+ if (ret) {
+ spin_lock_irqsave(&qce->lock, flags);
+ qce->req = NULL;
+ spin_unlock_irqrestore(&qce->lock, flags);
+
+ async_req->complete(async_req, ret);
+ }
+}
+
+static void qce_tasklet_req_done(unsigned long data)
+{
+ struct qce_device *qce = (struct qce_device *)data;
+ struct crypto_async_request *areq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&qce->lock, flags);
+ areq = qce->req;
+ qce->req = NULL;
+ spin_unlock_irqrestore(&qce->lock, flags);
+
+ if (areq)
+ areq->complete(areq, qce->result);
+
+ queue_work(qce->queue_wq, &qce->queue_work);
+}
+
+static int qce_check_version(struct qce_device *qce)
+{
+ u32 major, minor, step;
+
+ qce_get_version(qce, &major, &minor, &step);
+
+ /*
+ * the driver does not support v5 with minor 0 because it has special
+ * alignment requirements.
+ */
+ if (major != QCE_MAJOR_VERSION5 || minor == 0)
+ return -ENODEV;
+
+ qce->burst_size = QCE_BAM_BURST_SIZE;
+ qce->pipe_pair_index = 1;
+
+ dev_dbg(qce->dev, "Crypto device found, version %d.%d.%d\n",
+ major, minor, step);
+
+ return 0;
+}
+
+static int qce_crypto_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct qce_device *qce;
+ struct resource *res;
+ int ret;
+
+ qce = devm_kzalloc(dev, sizeof(*qce), GFP_KERNEL);
+ if (!qce)
+ return -ENOMEM;
+
+ qce->dev = dev;
+ platform_set_drvdata(pdev, qce);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ qce->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(qce->base))
+ return PTR_ERR(qce->base);
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (ret < 0)
+ return ret;
+
+ qce->core = devm_clk_get(qce->dev, "core");
+ if (IS_ERR(qce->core))
+ return PTR_ERR(qce->core);
+
+ qce->iface = devm_clk_get(qce->dev, "iface");
+ if (IS_ERR(qce->iface))
+ return PTR_ERR(qce->iface);
+
+ qce->bus = devm_clk_get(qce->dev, "bus");
+ if (IS_ERR(qce->bus))
+ return PTR_ERR(qce->bus);
+
+ ret = clk_prepare_enable(qce->core);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(qce->iface);
+ if (ret)
+ goto err_clks_core;
+
+ ret = clk_prepare_enable(qce->bus);
+ if (ret)
+ goto err_clks_iface;
+
+ ret = qce_dma_request(qce->dev, &qce->dma);
+ if (ret)
+ goto err_clks;
+
+ ret = qce_check_version(qce);
+ if (ret)
+ goto err_clks;
+
+ spin_lock_init(&qce->lock);
+ tasklet_init(&qce->done_tasklet, qce_tasklet_req_done,
+ (unsigned long)qce);
+
+ qce->queue_wq = alloc_workqueue("qce_wq", WQ_HIGHPRI | WQ_UNBOUND, 1);
+ if (!qce->queue_wq) {
+ ret = -ENOMEM;
+ goto err_dma;
+ }
+
+ INIT_WORK(&qce->queue_work, qce_reqqueue_handler);
+ crypto_init_queue(&qce->queue, QCE_QUEUE_LENGTH);
+
+ ret = qce_register_algs(qce);
+ if (ret)
+ goto err_wq;
+
+ return 0;
+err_wq:
+ destroy_workqueue(qce->queue_wq);
+err_dma:
+ qce_dma_release(&qce->dma);
+err_clks:
+ clk_disable_unprepare(qce->bus);
+err_clks_iface:
+ clk_disable_unprepare(qce->iface);
+err_clks_core:
+ clk_disable_unprepare(qce->core);
+ return ret;
+}
+
+static int qce_crypto_remove(struct platform_device *pdev)
+{
+ struct qce_device *qce = platform_get_drvdata(pdev);
+
+ cancel_work_sync(&qce->queue_work);
+ destroy_workqueue(qce->queue_wq);
+ tasklet_kill(&qce->done_tasklet);
+ qce_unregister_algs(qce);
+ qce_dma_release(&qce->dma);
+ clk_disable_unprepare(qce->bus);
+ clk_disable_unprepare(qce->iface);
+ clk_disable_unprepare(qce->core);
+ return 0;
+}
+
+static const struct of_device_id qce_crypto_of_match[] = {
+ { .compatible = "qcom,crypto-v5.1", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, qce_crypto_of_match);
+
+static struct platform_driver qce_crypto_driver = {
+ .probe = qce_crypto_probe,
+ .remove = qce_crypto_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = KBUILD_MODNAME,
+ .of_match_table = qce_crypto_of_match,
+ },
+};
+module_platform_driver(qce_crypto_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm crypto engine driver");
+MODULE_ALIAS("platform:" KBUILD_MODNAME);
+MODULE_AUTHOR("The Linux Foundation");
diff --git a/drivers/crypto/qce/core.h b/drivers/crypto/qce/core.h
new file mode 100644
index 000000000000..49107e894a35
--- /dev/null
+++ b/drivers/crypto/qce/core.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2010-2014, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CORE_H_
+#define _CORE_H_
+
+#include "dma.h"
+
+/**
+ * struct qce_device - crypto engine device structure
+ * @alg_list: list of registered algorithms
+ * @queue: request queue
+ * @lock: the lock protects queue and req
+ * @done_tasklet: done tasklet object
+ * @queue_wq: queue workqueue
+ * @queue_work: queue work
+ * @req: current active request
+ * @result: result of transform
+ * @base: virtual IO base
+ * @dev: pointer to device
+ * @core: core device clock
+ * @iface: interface clock
+ * @bus: bus clock
+ * @dma: pointer to dma data
+ * @burst_size: the crypto burst size
+ * @pipe_pair_index: which pipe pair the device using
+ * @async_req_queue: invoked by every algorithm to enqueue a request
+ * @async_req_done: invoked by every algorithm to finish its request
+ */
+struct qce_device {
+ struct crypto_queue queue;
+ spinlock_t lock;
+ struct tasklet_struct done_tasklet;
+ struct workqueue_struct *queue_wq;
+ struct work_struct queue_work;
+ struct crypto_async_request *req;
+ int result;
+ void __iomem *base;
+ struct device *dev;
+ struct clk *core, *iface, *bus;
+ struct qce_dma_data dma;
+ int burst_size;
+ unsigned int pipe_pair_index;
+ int (*async_req_queue)(struct qce_device *qce,
+ struct crypto_async_request *req);
+ void (*async_req_done)(struct qce_device *qce, int ret);
+};
+
+/**
+ * struct qce_algo_ops - algorithm operations per crypto type
+ * @type: should be CRYPTO_ALG_TYPE_XXX
+ * @register_algs: invoked by core to register the algorithms
+ * @unregister_algs: invoked by core to unregister the algorithms
+ * @async_req_handle: invoked by core to handle enqueued request
+ */
+struct qce_algo_ops {
+ u32 type;
+ int (*register_algs)(struct qce_device *qce);
+ void (*unregister_algs)(struct qce_device *qce);
+ int (*async_req_handle)(struct crypto_async_request *async_req);
+};
+
+#endif /* _CORE_H_ */
--
1.8.4.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v2 9/9] ARM: DT: qcom: Add Qualcomm crypto driver binding document
2014-04-14 12:48 [RFC PATCH v2 0/9] Add Qualcomm crypto driver Stanimir Varbanov
2014-04-14 12:48 ` [RFC PATCH v2 1/9] crypto: qce: Add core driver implementation Stanimir Varbanov
@ 2014-04-14 12:48 ` Stanimir Varbanov
2014-04-16 15:10 ` [RFC PATCH v2 0/9] Add Qualcomm crypto driver Stanimir Varbanov
2 siblings, 0 replies; 11+ messages in thread
From: Stanimir Varbanov @ 2014-04-14 12:48 UTC (permalink / raw)
To: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
Rob Landley
Cc: Stanimir Varbanov, linux-arm-msm, Mona Hossain,
Hariprasad Dhalinarasimha, Zhen Kong, Niranjana Vishwanathapura,
Rohit Vaswani, devicetree, linux-doc, linux-kernel
Here is Qualcomm crypto driver device tree binding documentation
to be used as a reference example.
Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
---
.../devicetree/bindings/crypto/qcom-qce.txt | 25 ++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 Documentation/devicetree/bindings/crypto/qcom-qce.txt
diff --git a/Documentation/devicetree/bindings/crypto/qcom-qce.txt b/Documentation/devicetree/bindings/crypto/qcom-qce.txt
new file mode 100644
index 000000000000..fdd53b184ba8
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/qcom-qce.txt
@@ -0,0 +1,25 @@
+Qualcomm crypto engine driver
+
+Required properties:
+
+- compatible : should be "qcom,crypto-v5.1"
+- reg : specifies base physical address and size of the registers map
+- clocks : phandle to clock-controller plus clock-specifier pair
+- clock-names : "iface" clocks register interface
+ "bus" clocks data transfer interface
+ "core" clocks rest of the crypto block
+- dmas : DMA specifiers for tx and rx dma channels. For more see
+ Documentation/devicetree/bindings/dma/dma.txt
+- dma-names : DMA request names should be "rx" and "tx"
+
+Example:
+ crypto@fd45a000 {
+ compatible = "qcom,crypto-v5.1";
+ reg = <0xfd45a000 0x6000>;
+ clocks = <&gcc GCC_CE2_AHB_CLK>,
+ <&gcc GCC_CE2_AXI_CLK>,
+ <&gcc GCC_CE2_CLK>;
+ clock-names = "iface", "bus", "core";
+ dmas = <&cryptobam 2>, <&cryptobam 3>;
+ dma-names = "rx", "tx";
+ };
--
1.8.4.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v2 0/9] Add Qualcomm crypto driver
2014-04-14 12:48 [RFC PATCH v2 0/9] Add Qualcomm crypto driver Stanimir Varbanov
2014-04-14 12:48 ` [RFC PATCH v2 1/9] crypto: qce: Add core driver implementation Stanimir Varbanov
2014-04-14 12:48 ` [RFC PATCH v2 9/9] ARM: DT: qcom: Add Qualcomm crypto driver binding document Stanimir Varbanov
@ 2014-04-16 15:10 ` Stanimir Varbanov
2 siblings, 0 replies; 11+ messages in thread
From: Stanimir Varbanov @ 2014-04-16 15:10 UTC (permalink / raw)
To: Herbert Xu
Cc: Stanimir Varbanov, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Rob Landley, David S. Miller,
Grant Likely, linux-arm-msm, Mona Hossain,
Hariprasad Dhalinarasimha, Zhen Kong, Niranjana Vishwanathapura,
Rohit Vaswani, devicetree, linux-doc, linux-kernel, linux-crypto
Hi Herbert, crypto folks
I would like to know your opinions on the state of this driver. How far
it is from the others crypto drivers in kernel. If you have some
comments, criticisms etc. I will be glad to hear them and correct the
potential issues.
Thanks for your time.
regards,
Stan
On 04/14/2014 03:48 PM, Stanimir Varbanov wrote:
> Hi,
>
> Here is the second version of the patch set. This time tagged
> as an RFC to avoid confusions. The driver is splitted by files
> and is buildable at the last patch. When the review has finished
> 1/9 to 7/9 could be squashed in one patch.
>
> Any comments appreciated!
>
> Changes since v1:
>
> core
> - added MODULE_DEVICE_TABLE
> - reorganise includes
> - kernel doc comments
> - fix probe error path, forgot to destroy workqueue
> - rework clocks and kill loops for enabling
> - restructure the interfaces between core part of the driver
> and crypto type algorithms. Now struct qce_algo_ops has
> .unregister_algs operation and it is implemented by every
> algorithm type (unregister_algs was common in v1).
> Also async_req_queue/done are now part of core structure
> qce_device
>
> regs-v5
> - use GENMASK and include bitops.h
>
> dma-sg helpers
> - do not check !IS_ERR on error path
> - various fixes as per review comments
> - reorganise includes
> - return error on qce_dma_terminate_all
>
> ablkcipher
> - use queue and done callbacks from struct qce_device
> - reorganise includes
> - kernel doc notation
>
> sha-hmac
> - use queue and done callbacks from struct qce_device
> - make byte_count __be32
> - kernel doc notation
> - make rctx flags member unsigned long
> - cleanup qce_ahash_update function
> - make const * input args of qce_import_common
>
> common
> - rename bits/masks to use _SHIFT suffix
> - reorganise includes and add qce_get_version function
> - make rctx flags unsigned long
> - move blocksize boundary check on function begging and
> clear BYTECOUNT registers on first processing block
>
> This driver is based on Codeaurora's driver found at [1]
>
> regards,
> Stan
>
> [1] https://www.codeaurora.org/cgit/quic/la/kernel/msm-3.10/tree/drivers
> /crypto/msm?h=msm-3.10
> ------------------------------------------------------------
> v1.
>
> The following patch set implements support for Qualcomm
> crypto hardware accelerator driver. It registers itself
> to the crypto subsystem and adds the following operations
> for encryption/decription - AES with ECB CBC CTR XTS modes,
> DES with ECB CBC modes, and 3DES ECB CBC modes.
> For hashing and MAC it adds support for sha1 sha256,
> hmac(sha1) hmac(sha256).
>
> The version of the driver is reworked by me and it is based
> on Codeaurora's qcrypto driver. The proposed version has many
> coding style fixes, re-factored files, separated by
> functionality. I wanted to make the driver more readable and
> easier for review, hope I done well. I'll appreciate any review
> comments which will help me to make this code clear and ready
> for mainline kernel.
>
> Stanimir Varbanov (9):
> crypto: qce: Add core driver implementation
> crypto: qce: Add register defines
> crypto: qce: Add dma and sg helpers
> crypto: qce: Add ablkcipher algorithms
> crypto: qce: Adds sha and hmac transforms
> crypto: qce: Adds infrastructure to setup the crypto block
> crypto: qce: Adds Makefile to build the driver
> crypto: qce: Build Qualcomm qce driver
> ARM: DT: qcom: Add Qualcomm crypto driver binding document
>
> .../devicetree/bindings/crypto/qcom-qce.txt | 25 +
> drivers/crypto/Kconfig | 10 +
> drivers/crypto/Makefile | 1 +
> drivers/crypto/qce/Makefile | 6 +
> drivers/crypto/qce/ablkcipher.c | 403 ++++++++++++++
> drivers/crypto/qce/cipher.h | 67 +++
> drivers/crypto/qce/common.c | 438 +++++++++++++++
> drivers/crypto/qce/common.h | 104 ++++
> drivers/crypto/qce/core.c | 295 ++++++++++
> drivers/crypto/qce/core.h | 73 +++
> drivers/crypto/qce/dma.c | 188 +++++++
> drivers/crypto/qce/dma.h | 58 ++
> drivers/crypto/qce/regs-v5.h | 331 ++++++++++++
> drivers/crypto/qce/sha.c | 591 +++++++++++++++++++++
> drivers/crypto/qce/sha.h | 81 +++
> 15 files changed, 2671 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/crypto/qcom-qce.txt
> create mode 100644 drivers/crypto/qce/Makefile
> create mode 100644 drivers/crypto/qce/ablkcipher.c
> create mode 100644 drivers/crypto/qce/cipher.h
> create mode 100644 drivers/crypto/qce/common.c
> create mode 100644 drivers/crypto/qce/common.h
> create mode 100644 drivers/crypto/qce/core.c
> create mode 100644 drivers/crypto/qce/core.h
> create mode 100644 drivers/crypto/qce/dma.c
> create mode 100644 drivers/crypto/qce/dma.h
> create mode 100644 drivers/crypto/qce/regs-v5.h
> create mode 100644 drivers/crypto/qce/sha.c
> create mode 100644 drivers/crypto/qce/sha.h
>
--
regards,
Stan
^ permalink raw reply [flat|nested] 11+ messages in thread