diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-11-02 16:15:30 -1000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-11-02 16:15:30 -1000 |
| commit | bc3012f4e3a9765de81f454cb8f9bb16aafc6ff5 (patch) | |
| tree | 2c127c669218b8c74c843331e455372f88a6a848 /drivers/crypto/qcom-rng.c | |
| parent | 6803bd7956ca8fc43069c2e42016f17f3c2fbf30 (diff) | |
| parent | a312e07a65fb598ed239b940434392721385c722 (diff) | |
Merge tag 'v6.7-p1' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto updates from Herbert Xu:
"API:
- Add virtual-address based lskcipher interface
- Optimise ahash/shash performance in light of costly indirect calls
- Remove ahash alignmask attribute
Algorithms:
- Improve AES/XTS performance of 6-way unrolling for ppc
- Remove some uses of obsolete algorithms (md4, md5, sha1)
- Add FIPS 202 SHA-3 support in pkcs1pad
- Add fast path for single-page messages in adiantum
- Remove zlib-deflate
Drivers:
- Add support for S4 in meson RNG driver
- Add STM32MP13x support in stm32
- Add hwrng interface support in qcom-rng
- Add support for deflate algorithm in hisilicon/zip"
* tag 'v6.7-p1' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (283 commits)
crypto: adiantum - flush destination page before unmapping
crypto: testmgr - move pkcs1pad(rsa,sha3-*) to correct place
Documentation/module-signing.txt: bring up to date
module: enable automatic module signing with FIPS 202 SHA-3
crypto: asymmetric_keys - allow FIPS 202 SHA-3 signatures
crypto: rsa-pkcs1pad - Add FIPS 202 SHA-3 support
crypto: FIPS 202 SHA-3 register in hash info for IMA
x509: Add OIDs for FIPS 202 SHA-3 hash and signatures
crypto: ahash - optimize performance when wrapping shash
crypto: ahash - check for shash type instead of not ahash type
crypto: hash - move "ahash wrapping shash" functions to ahash.c
crypto: talitos - stop using crypto_ahash::init
crypto: chelsio - stop using crypto_ahash::init
crypto: ahash - improve file comment
crypto: ahash - remove struct ahash_request_priv
crypto: ahash - remove crypto_ahash_alignmask
crypto: gcm - stop using alignmask of ahash
crypto: chacha20poly1305 - stop using alignmask of ahash
crypto: ccm - stop using alignmask of ahash
net: ipv6: stop checking crypto_ahash_alignmask
...
Diffstat (limited to 'drivers/crypto/qcom-rng.c')
| -rw-r--r-- | drivers/crypto/qcom-rng.c | 71 |
1 files changed, 60 insertions, 11 deletions
diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c index 825a729f205e..c670d7d0c11e 100644 --- a/drivers/crypto/qcom-rng.c +++ b/drivers/crypto/qcom-rng.c @@ -7,6 +7,7 @@ #include <linux/acpi.h> #include <linux/clk.h> #include <linux/crypto.h> +#include <linux/hw_random.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/kernel.h> @@ -28,17 +29,25 @@ #define WORD_SZ 4 +#define QCOM_TRNG_QUALITY 1024 + struct qcom_rng { struct mutex lock; void __iomem *base; struct clk *clk; - unsigned int skip_init; + struct hwrng hwrng; + struct qcom_rng_of_data *of_data; }; struct qcom_rng_ctx { struct qcom_rng *rng; }; +struct qcom_rng_of_data { + bool skip_init; + bool hwrng_support; +}; + static struct qcom_rng *qcom_rng_dev; static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max) @@ -66,11 +75,11 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max) } else { /* copy only remaining bytes */ memcpy(data, &val, max - currsize); - break; + currsize = max; } } while (currsize < max); - return 0; + return currsize; } static int qcom_rng_generate(struct crypto_rng *tfm, @@ -92,6 +101,9 @@ static int qcom_rng_generate(struct crypto_rng *tfm, mutex_unlock(&rng->lock); clk_disable_unprepare(rng->clk); + if (ret >= 0) + ret = 0; + return ret; } @@ -101,6 +113,13 @@ static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed, return 0; } +static int qcom_hwrng_read(struct hwrng *hwrng, void *data, size_t max, bool wait) +{ + struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng); + + return qcom_rng_read(qrng, data, max); +} + static int qcom_rng_enable(struct qcom_rng *rng) { u32 val; @@ -136,7 +155,7 @@ static int qcom_rng_init(struct crypto_tfm *tfm) ctx->rng = qcom_rng_dev; - if (!ctx->rng->skip_init) + if (!ctx->rng->of_data->skip_init) return qcom_rng_enable(ctx->rng); return 0; @@ -177,27 +196,56 @@ static int qcom_rng_probe(struct platform_device *pdev) if (IS_ERR(rng->clk)) return PTR_ERR(rng->clk); - rng->skip_init = (unsigned long)device_get_match_data(&pdev->dev); + rng->of_data = (struct qcom_rng_of_data *)of_device_get_match_data(&pdev->dev); qcom_rng_dev = rng; ret = crypto_register_rng(&qcom_rng_alg); if (ret) { dev_err(&pdev->dev, "Register crypto rng failed: %d\n", ret); qcom_rng_dev = NULL; + return ret; } + if (rng->of_data->hwrng_support) { + rng->hwrng.name = "qcom_hwrng"; + rng->hwrng.read = qcom_hwrng_read; + rng->hwrng.quality = QCOM_TRNG_QUALITY; + ret = devm_hwrng_register(&pdev->dev, &rng->hwrng); + if (ret) { + dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret); + qcom_rng_dev = NULL; + goto fail; + } + } + + return ret; +fail: + crypto_unregister_rng(&qcom_rng_alg); return ret; } -static int qcom_rng_remove(struct platform_device *pdev) +static void qcom_rng_remove(struct platform_device *pdev) { crypto_unregister_rng(&qcom_rng_alg); qcom_rng_dev = NULL; - - return 0; } +static struct qcom_rng_of_data qcom_prng_of_data = { + .skip_init = false, + .hwrng_support = false, +}; + +static struct qcom_rng_of_data qcom_prng_ee_of_data = { + .skip_init = true, + .hwrng_support = false, +}; + +static struct qcom_rng_of_data qcom_trng_of_data = { + .skip_init = true, + .hwrng_support = true, +}; + static const struct acpi_device_id __maybe_unused qcom_rng_acpi_match[] = { { .id = "QCOM8160", .driver_data = 1 }, {} @@ -205,15 +253,16 @@ static const struct acpi_device_id __maybe_unused qcom_rng_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, qcom_rng_acpi_match); static const struct of_device_id __maybe_unused qcom_rng_of_match[] = { - { .compatible = "qcom,prng", .data = (void *)0}, - { .compatible = "qcom,prng-ee", .data = (void *)1}, + { .compatible = "qcom,prng", .data = &qcom_prng_of_data }, + { .compatible = "qcom,prng-ee", .data = &qcom_prng_ee_of_data }, + { .compatible = "qcom,trng", .data = &qcom_trng_of_data }, {} }; MODULE_DEVICE_TABLE(of, qcom_rng_of_match); static struct platform_driver qcom_rng_driver = { .probe = qcom_rng_probe, - .remove = qcom_rng_remove, + .remove_new = qcom_rng_remove, .driver = { .name = KBUILD_MODNAME, .of_match_table = of_match_ptr(qcom_rng_of_match), |