aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-09-06 18:17:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-06 18:17:17 -0400
commit80cee03bf1d626db0278271b505d7f5febb37bba (patch)
tree6fc86272106f526a9d07343c524612aa493539e6 /drivers/char
parentaae3dbb4776e7916b6cd442d00159bea27a695c1 (diff)
parent2d45a7e89833f88b38112292ff227af437f81f2f (diff)
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto updates from Herbert Xu: "Here is the crypto update for 4.14: API: - Defer scompress scratch buffer allocation to first use. - Add __crypto_xor that takes separte src and dst operands. - Add ahash multiple registration interface. - Revamped aead/skcipher algif code to fix async IO properly. Drivers: - Add non-SIMD fallback code path on ARM for SVE. - Add AMD Security Processor framework for ccp. - Add support for RSA in ccp. - Add XTS-AES-256 support for CCP version 5. - Add support for PRNG in sun4i-ss. - Add support for DPAA2 in caam. - Add ARTPEC crypto support. - Add Freescale RNGC hwrng support. - Add Microchip / Atmel ECC driver. - Add support for STM32 HASH module" * 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (116 commits) crypto: af_alg - get_page upon reassignment to TX SGL crypto: cavium/nitrox - Fix an error handling path in 'nitrox_probe()' crypto: inside-secure - fix an error handling path in safexcel_probe() crypto: rockchip - Don't dequeue the request when device is busy crypto: cavium - add release_firmware to all return case crypto: sahara - constify platform_device_id MAINTAINERS: Add ARTPEC crypto maintainer crypto: axis - add ARTPEC-6/7 crypto accelerator driver crypto: hash - add crypto_(un)register_ahashes() dt-bindings: crypto: add ARTPEC crypto crypto: algif_aead - fix comment regarding memory layout crypto: ccp - use dma_mapping_error to check map error lib/mpi: fix build with clang crypto: sahara - Remove leftover from previous used spinlock crypto: sahara - Fix dma unmap direction crypto: af_alg - consolidation of duplicate code crypto: caam - Remove unused dentry members crypto: ccp - select CONFIG_CRYPTO_RSA crypto: ccp - avoid uninitialized variable warning crypto: serpent - improve __serpent_setkey with UBSAN ...
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/hw_random/Kconfig20
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/core.c42
-rw-r--r--drivers/char/hw_random/imx-rngc.c331
4 files changed, 384 insertions, 10 deletions
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 1b223c32a8ae..95a031e9eced 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -13,10 +13,8 @@ menuconfig HW_RANDOM
13 that's usually called /dev/hwrng, and which exposes one 13 that's usually called /dev/hwrng, and which exposes one
14 of possibly several hardware random number generators. 14 of possibly several hardware random number generators.
15 15
16 These hardware random number generators do not feed directly 16 These hardware random number generators do feed into the
17 into the kernel's random number generator. That is usually 17 kernel's random number generator entropy pool.
18 handled by the "rngd" daemon. Documentation/hw_random.txt
19 has more information.
20 18
21 If unsure, say Y. 19 If unsure, say Y.
22 20
@@ -255,6 +253,20 @@ config HW_RANDOM_MXC_RNGA
255 253
256 If unsure, say Y. 254 If unsure, say Y.
257 255
256config HW_RANDOM_IMX_RNGC
257 tristate "Freescale i.MX RNGC Random Number Generator"
258 depends on ARCH_MXC
259 default HW_RANDOM
260 ---help---
261 This driver provides kernel-side support for the Random Number
262 Generator Version C hardware found on some Freescale i.MX
263 processors. Version B is also supported by this driver.
264
265 To compile this driver as a module, choose M here: the
266 module will be called imx-rngc.
267
268 If unsure, say Y.
269
258config HW_RANDOM_NOMADIK 270config HW_RANDOM_NOMADIK
259 tristate "ST-Ericsson Nomadik Random Number Generator support" 271 tristate "ST-Ericsson Nomadik Random Number Generator support"
260 depends on ARCH_NOMADIK 272 depends on ARCH_NOMADIK
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index b085975ec1d2..39a67defac67 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
20obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o 20obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
21obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o 21obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o
22obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o 22obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
23obj-$(CONFIG_HW_RANDOM_IMX_RNGC) += imx-rngc.o
23obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o 24obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
24obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o 25obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
25obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o 26obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 503a41dfa193..9701ac7d8b47 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -28,7 +28,10 @@
28#define RNG_MODULE_NAME "hw_random" 28#define RNG_MODULE_NAME "hw_random"
29 29
30static struct hwrng *current_rng; 30static struct hwrng *current_rng;
31/* the current rng has been explicitly chosen by user via sysfs */
32static int cur_rng_set_by_user;
31static struct task_struct *hwrng_fill; 33static struct task_struct *hwrng_fill;
34/* list of registered rngs, sorted decending by quality */
32static LIST_HEAD(rng_list); 35static LIST_HEAD(rng_list);
33/* Protects rng_list and current_rng */ 36/* Protects rng_list and current_rng */
34static DEFINE_MUTEX(rng_mutex); 37static DEFINE_MUTEX(rng_mutex);
@@ -303,6 +306,7 @@ static ssize_t hwrng_attr_current_store(struct device *dev,
303 list_for_each_entry(rng, &rng_list, list) { 306 list_for_each_entry(rng, &rng_list, list) {
304 if (sysfs_streq(rng->name, buf)) { 307 if (sysfs_streq(rng->name, buf)) {
305 err = 0; 308 err = 0;
309 cur_rng_set_by_user = 1;
306 if (rng != current_rng) 310 if (rng != current_rng)
307 err = set_current_rng(rng); 311 err = set_current_rng(rng);
308 break; 312 break;
@@ -351,16 +355,27 @@ static ssize_t hwrng_attr_available_show(struct device *dev,
351 return strlen(buf); 355 return strlen(buf);
352} 356}
353 357
358static ssize_t hwrng_attr_selected_show(struct device *dev,
359 struct device_attribute *attr,
360 char *buf)
361{
362 return snprintf(buf, PAGE_SIZE, "%d\n", cur_rng_set_by_user);
363}
364
354static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR, 365static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
355 hwrng_attr_current_show, 366 hwrng_attr_current_show,
356 hwrng_attr_current_store); 367 hwrng_attr_current_store);
357static DEVICE_ATTR(rng_available, S_IRUGO, 368static DEVICE_ATTR(rng_available, S_IRUGO,
358 hwrng_attr_available_show, 369 hwrng_attr_available_show,
359 NULL); 370 NULL);
371static DEVICE_ATTR(rng_selected, S_IRUGO,
372 hwrng_attr_selected_show,
373 NULL);
360 374
361static struct attribute *rng_dev_attrs[] = { 375static struct attribute *rng_dev_attrs[] = {
362 &dev_attr_rng_current.attr, 376 &dev_attr_rng_current.attr,
363 &dev_attr_rng_available.attr, 377 &dev_attr_rng_available.attr,
378 &dev_attr_rng_selected.attr,
364 NULL 379 NULL
365}; 380};
366 381
@@ -417,6 +432,7 @@ int hwrng_register(struct hwrng *rng)
417{ 432{
418 int err = -EINVAL; 433 int err = -EINVAL;
419 struct hwrng *old_rng, *tmp; 434 struct hwrng *old_rng, *tmp;
435 struct list_head *rng_list_ptr;
420 436
421 if (!rng->name || (!rng->data_read && !rng->read)) 437 if (!rng->name || (!rng->data_read && !rng->read))
422 goto out; 438 goto out;
@@ -432,14 +448,27 @@ int hwrng_register(struct hwrng *rng)
432 init_completion(&rng->cleanup_done); 448 init_completion(&rng->cleanup_done);
433 complete(&rng->cleanup_done); 449 complete(&rng->cleanup_done);
434 450
451 /* rng_list is sorted by decreasing quality */
452 list_for_each(rng_list_ptr, &rng_list) {
453 tmp = list_entry(rng_list_ptr, struct hwrng, list);
454 if (tmp->quality < rng->quality)
455 break;
456 }
457 list_add_tail(&rng->list, rng_list_ptr);
458
435 old_rng = current_rng; 459 old_rng = current_rng;
436 err = 0; 460 err = 0;
437 if (!old_rng) { 461 if (!old_rng ||
462 (!cur_rng_set_by_user && rng->quality > old_rng->quality)) {
463 /*
464 * Set new rng as current as the new rng source
465 * provides better entropy quality and was not
466 * chosen by userspace.
467 */
438 err = set_current_rng(rng); 468 err = set_current_rng(rng);
439 if (err) 469 if (err)
440 goto out_unlock; 470 goto out_unlock;
441 } 471 }
442 list_add_tail(&rng->list, &rng_list);
443 472
444 if (old_rng && !rng->init) { 473 if (old_rng && !rng->init) {
445 /* 474 /*
@@ -466,12 +495,13 @@ void hwrng_unregister(struct hwrng *rng)
466 list_del(&rng->list); 495 list_del(&rng->list);
467 if (current_rng == rng) { 496 if (current_rng == rng) {
468 drop_current_rng(); 497 drop_current_rng();
498 cur_rng_set_by_user = 0;
499 /* rng_list is sorted by quality, use the best (=first) one */
469 if (!list_empty(&rng_list)) { 500 if (!list_empty(&rng_list)) {
470 struct hwrng *tail; 501 struct hwrng *new_rng;
471
472 tail = list_entry(rng_list.prev, struct hwrng, list);
473 502
474 set_current_rng(tail); 503 new_rng = list_entry(rng_list.next, struct hwrng, list);
504 set_current_rng(new_rng);
475 } 505 }
476 } 506 }
477 507
diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c
new file mode 100644
index 000000000000..88db42d30760
--- /dev/null
+++ b/drivers/char/hw_random/imx-rngc.c
@@ -0,0 +1,331 @@
1/*
2 * RNG driver for Freescale RNGC
3 *
4 * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
5 * Copyright (C) 2017 Martin Kaiser <martin@kaiser.cx>
6 *
7 * The code contained herein is licensed under the GNU General Public
8 * License. You may obtain a copy of the GNU General Public License
9 * Version 2 or later at the following locations:
10 *
11 * http://www.opensource.org/licenses/gpl-license.html
12 * http://www.gnu.org/copyleft/gpl.html
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/clk.h>
19#include <linux/err.h>
20#include <linux/platform_device.h>
21#include <linux/interrupt.h>
22#include <linux/hw_random.h>
23#include <linux/completion.h>
24#include <linux/io.h>
25
26#define RNGC_COMMAND 0x0004
27#define RNGC_CONTROL 0x0008
28#define RNGC_STATUS 0x000C
29#define RNGC_ERROR 0x0010
30#define RNGC_FIFO 0x0014
31
32#define RNGC_CMD_CLR_ERR 0x00000020
33#define RNGC_CMD_CLR_INT 0x00000010
34#define RNGC_CMD_SEED 0x00000002
35#define RNGC_CMD_SELF_TEST 0x00000001
36
37#define RNGC_CTRL_MASK_ERROR 0x00000040
38#define RNGC_CTRL_MASK_DONE 0x00000020
39
40#define RNGC_STATUS_ERROR 0x00010000
41#define RNGC_STATUS_FIFO_LEVEL_MASK 0x00000f00
42#define RNGC_STATUS_FIFO_LEVEL_SHIFT 8
43#define RNGC_STATUS_SEED_DONE 0x00000020
44#define RNGC_STATUS_ST_DONE 0x00000010
45
46#define RNGC_ERROR_STATUS_STAT_ERR 0x00000008
47
48#define RNGC_TIMEOUT 3000 /* 3 sec */
49
50
51static bool self_test = true;
52module_param(self_test, bool, 0);
53
54struct imx_rngc {
55 struct device *dev;
56 struct clk *clk;
57 void __iomem *base;
58 struct hwrng rng;
59 struct completion rng_op_done;
60 /*
61 * err_reg is written only by the irq handler and read only
62 * when interrupts are masked, we need no spinlock
63 */
64 u32 err_reg;
65};
66
67
68static inline void imx_rngc_irq_mask_clear(struct imx_rngc *rngc)
69{
70 u32 ctrl, cmd;
71
72 /* mask interrupts */
73 ctrl = readl(rngc->base + RNGC_CONTROL);
74 ctrl |= RNGC_CTRL_MASK_DONE | RNGC_CTRL_MASK_ERROR;
75 writel(ctrl, rngc->base + RNGC_CONTROL);
76
77 /*
78 * CLR_INT clears the interrupt only if there's no error
79 * CLR_ERR clear the interrupt and the error register if there
80 * is an error
81 */
82 cmd = readl(rngc->base + RNGC_COMMAND);
83 cmd |= RNGC_CMD_CLR_INT | RNGC_CMD_CLR_ERR;
84 writel(cmd, rngc->base + RNGC_COMMAND);
85}
86
87static inline void imx_rngc_irq_unmask(struct imx_rngc *rngc)
88{
89 u32 ctrl;
90
91 ctrl = readl(rngc->base + RNGC_CONTROL);
92 ctrl &= ~(RNGC_CTRL_MASK_DONE | RNGC_CTRL_MASK_ERROR);
93 writel(ctrl, rngc->base + RNGC_CONTROL);
94}
95
96static int imx_rngc_self_test(struct imx_rngc *rngc)
97{
98 u32 cmd;
99 int ret;
100
101 imx_rngc_irq_unmask(rngc);
102
103 /* run self test */
104 cmd = readl(rngc->base + RNGC_COMMAND);
105 writel(cmd | RNGC_CMD_SELF_TEST, rngc->base + RNGC_COMMAND);
106
107 ret = wait_for_completion_timeout(&rngc->rng_op_done, RNGC_TIMEOUT);
108 if (!ret) {
109 imx_rngc_irq_mask_clear(rngc);
110 return -ETIMEDOUT;
111 }
112
113 if (rngc->err_reg != 0)
114 return -EIO;
115
116 return 0;
117}
118
119static int imx_rngc_read(struct hwrng *rng, void *data, size_t max, bool wait)
120{
121 struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng);
122 unsigned int status;
123 unsigned int level;
124 int retval = 0;
125
126 while (max >= sizeof(u32)) {
127 status = readl(rngc->base + RNGC_STATUS);
128
129 /* is there some error while reading this random number? */
130 if (status & RNGC_STATUS_ERROR)
131 break;
132
133 /* how many random numbers are in FIFO? [0-16] */
134 level = (status & RNGC_STATUS_FIFO_LEVEL_MASK) >>
135 RNGC_STATUS_FIFO_LEVEL_SHIFT;
136
137 if (level) {
138 /* retrieve a random number from FIFO */
139 *(u32 *)data = readl(rngc->base + RNGC_FIFO);
140
141 retval += sizeof(u32);
142 data += sizeof(u32);
143 max -= sizeof(u32);
144 }
145 }
146
147 return retval ? retval : -EIO;
148}
149
150static irqreturn_t imx_rngc_irq(int irq, void *priv)
151{
152 struct imx_rngc *rngc = (struct imx_rngc *)priv;
153 u32 status;
154
155 /*
156 * clearing the interrupt will also clear the error register
157 * read error and status before clearing
158 */
159 status = readl(rngc->base + RNGC_STATUS);
160 rngc->err_reg = readl(rngc->base + RNGC_ERROR);
161
162 imx_rngc_irq_mask_clear(rngc);
163
164 if (status & (RNGC_STATUS_SEED_DONE | RNGC_STATUS_ST_DONE))
165 complete(&rngc->rng_op_done);
166
167 return IRQ_HANDLED;
168}
169
170static int imx_rngc_init(struct hwrng *rng)
171{
172 struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng);
173 u32 cmd;
174 int ret;
175
176 /* clear error */
177 cmd = readl(rngc->base + RNGC_COMMAND);
178 writel(cmd | RNGC_CMD_CLR_ERR, rngc->base + RNGC_COMMAND);
179
180 /* create seed, repeat while there is some statistical error */
181 do {
182 imx_rngc_irq_unmask(rngc);
183
184 /* seed creation */
185 cmd = readl(rngc->base + RNGC_COMMAND);
186 writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND);
187
188 ret = wait_for_completion_timeout(&rngc->rng_op_done,
189 RNGC_TIMEOUT);
190
191 if (!ret) {
192 imx_rngc_irq_mask_clear(rngc);
193 return -ETIMEDOUT;
194 }
195
196 } while (rngc->err_reg == RNGC_ERROR_STATUS_STAT_ERR);
197
198 return rngc->err_reg ? -EIO : 0;
199}
200
201static int imx_rngc_probe(struct platform_device *pdev)
202{
203 struct imx_rngc *rngc;
204 struct resource *res;
205 int ret;
206 int irq;
207
208 rngc = devm_kzalloc(&pdev->dev, sizeof(*rngc), GFP_KERNEL);
209 if (!rngc)
210 return -ENOMEM;
211
212 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
213 rngc->base = devm_ioremap_resource(&pdev->dev, res);
214 if (IS_ERR(rngc->base))
215 return PTR_ERR(rngc->base);
216
217 rngc->clk = devm_clk_get(&pdev->dev, NULL);
218 if (IS_ERR(rngc->clk)) {
219 dev_err(&pdev->dev, "Can not get rng_clk\n");
220 return PTR_ERR(rngc->clk);
221 }
222
223 irq = platform_get_irq(pdev, 0);
224 if (irq <= 0) {
225 dev_err(&pdev->dev, "Couldn't get irq %d\n", irq);
226 return irq;
227 }
228
229 ret = clk_prepare_enable(rngc->clk);
230 if (ret)
231 return ret;
232
233 ret = devm_request_irq(&pdev->dev,
234 irq, imx_rngc_irq, 0, pdev->name, (void *)rngc);
235 if (ret) {
236 dev_err(rngc->dev, "Can't get interrupt working.\n");
237 goto err;
238 }
239
240 init_completion(&rngc->rng_op_done);
241
242 rngc->rng.name = pdev->name;
243 rngc->rng.init = imx_rngc_init;
244 rngc->rng.read = imx_rngc_read;
245
246 rngc->dev = &pdev->dev;
247 platform_set_drvdata(pdev, rngc);
248
249 imx_rngc_irq_mask_clear(rngc);
250
251 if (self_test) {
252 ret = imx_rngc_self_test(rngc);
253 if (ret) {
254 dev_err(rngc->dev, "FSL RNGC self test failed.\n");
255 goto err;
256 }
257 }
258
259 ret = hwrng_register(&rngc->rng);
260 if (ret) {
261 dev_err(&pdev->dev, "FSL RNGC registering failed (%d)\n", ret);
262 goto err;
263 }
264
265 dev_info(&pdev->dev, "Freescale RNGC registered.\n");
266 return 0;
267
268err:
269 clk_disable_unprepare(rngc->clk);
270
271 return ret;
272}
273
274static int __exit imx_rngc_remove(struct platform_device *pdev)
275{
276 struct imx_rngc *rngc = platform_get_drvdata(pdev);
277
278 hwrng_unregister(&rngc->rng);
279
280 clk_disable_unprepare(rngc->clk);
281
282 return 0;
283}
284
285#ifdef CONFIG_PM
286static int imx_rngc_suspend(struct device *dev)
287{
288 struct imx_rngc *rngc = dev_get_drvdata(dev);
289
290 clk_disable_unprepare(rngc->clk);
291
292 return 0;
293}
294
295static int imx_rngc_resume(struct device *dev)
296{
297 struct imx_rngc *rngc = dev_get_drvdata(dev);
298
299 clk_prepare_enable(rngc->clk);
300
301 return 0;
302}
303
304static const struct dev_pm_ops imx_rngc_pm_ops = {
305 .suspend = imx_rngc_suspend,
306 .resume = imx_rngc_resume,
307};
308#endif
309
310static const struct of_device_id imx_rngc_dt_ids[] = {
311 { .compatible = "fsl,imx25-rngb", .data = NULL, },
312 { /* sentinel */ }
313};
314MODULE_DEVICE_TABLE(of, imx_rngc_dt_ids);
315
316static struct platform_driver imx_rngc_driver = {
317 .driver = {
318 .name = "imx_rngc",
319#ifdef CONFIG_PM
320 .pm = &imx_rngc_pm_ops,
321#endif
322 .of_match_table = imx_rngc_dt_ids,
323 },
324 .remove = __exit_p(imx_rngc_remove),
325};
326
327module_platform_driver_probe(imx_rngc_driver, imx_rngc_probe);
328
329MODULE_AUTHOR("Freescale Semiconductor, Inc.");
330MODULE_DESCRIPTION("H/W RNGC driver for i.MX");
331MODULE_LICENSE("GPL");