diff options
Diffstat (limited to 'drivers/char/hw_random')
-rw-r--r-- | drivers/char/hw_random/Kconfig | 13 | ||||
-rw-r--r-- | drivers/char/hw_random/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/hw_random/amd-rng.c | 140 | ||||
-rw-r--r-- | drivers/char/hw_random/bcm2835-rng.c | 5 | ||||
-rw-r--r-- | drivers/char/hw_random/cavium-rng-vf.c | 99 | ||||
-rw-r--r-- | drivers/char/hw_random/cavium-rng.c | 94 | ||||
-rw-r--r-- | drivers/char/hw_random/core.c | 37 | ||||
-rw-r--r-- | drivers/char/hw_random/geode-rng.c | 58 | ||||
-rw-r--r-- | drivers/char/hw_random/meson-rng.c | 3 | ||||
-rw-r--r-- | drivers/char/hw_random/omap-rng.c | 4 | ||||
-rw-r--r-- | drivers/char/hw_random/omap3-rom-rng.c | 10 | ||||
-rw-r--r-- | drivers/char/hw_random/pasemi-rng.c | 39 | ||||
-rw-r--r-- | drivers/char/hw_random/pic32-rng.c | 1 | ||||
-rw-r--r-- | drivers/char/hw_random/st-rng.c | 4 | ||||
-rw-r--r-- | drivers/char/hw_random/tx4939-rng.c | 11 |
15 files changed, 341 insertions, 178 deletions
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 8c0770bf8881..200dab5136a7 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -410,6 +410,19 @@ config HW_RANDOM_MESON If unsure, say Y. +config HW_RANDOM_CAVIUM + tristate "Cavium ThunderX Random Number Generator support" + depends on HW_RANDOM && PCI && (ARM64 || (COMPILE_TEST && 64BIT)) + default HW_RANDOM + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on Cavium SoCs. + + To compile this driver as a module, choose M here: the + module will be called cavium_rng. + + If unsure, say Y. + endif # HW_RANDOM config UML_RANDOM diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 04bb0b03356f..5f52b1e4e7be 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -35,3 +35,4 @@ obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o +obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c index 48f6a83cdd61..4a99ac756f08 100644 --- a/drivers/char/hw_random/amd-rng.c +++ b/drivers/char/hw_random/amd-rng.c @@ -24,16 +24,18 @@ * warranty of any kind, whether express or implied. */ -#include <linux/module.h> +#include <linux/delay.h> +#include <linux/hw_random.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/pci.h> -#include <linux/hw_random.h> -#include <linux/delay.h> -#include <asm/io.h> +#define DRV_NAME "AMD768-HWRNG" -#define PFX KBUILD_MODNAME ": " - +#define RNGDATA 0x00 +#define RNGDONE 0x04 +#define PMBASE_OFFSET 0xF0 +#define PMBASE_SIZE 8 /* * Data for PCI driver interface @@ -50,72 +52,84 @@ static const struct pci_device_id pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, pci_tbl); -static struct pci_dev *amd_pdev; - +struct amd768_priv { + void __iomem *iobase; + struct pci_dev *pcidev; +}; -static int amd_rng_data_present(struct hwrng *rng, int wait) +static int amd_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) { - u32 pmbase = (u32)rng->priv; - int data, i; - - for (i = 0; i < 20; i++) { - data = !!(inl(pmbase + 0xF4) & 1); - if (data || !wait) - break; - udelay(10); + u32 *data = buf; + struct amd768_priv *priv = (struct amd768_priv *)rng->priv; + size_t read = 0; + /* We will wait at maximum one time per read */ + int timeout = max / 4 + 1; + + /* + * RNG data is available when RNGDONE is set to 1 + * New random numbers are generated approximately 128 microseconds + * after RNGDATA is read + */ + while (read < max) { + if (ioread32(priv->iobase + RNGDONE) == 0) { + if (wait) { + /* Delay given by datasheet */ + usleep_range(128, 196); + if (timeout-- == 0) + return read; + } else { + return 0; + } + } else { + *data = ioread32(priv->iobase + RNGDATA); + data++; + read += 4; + } } - return data; -} -static int amd_rng_data_read(struct hwrng *rng, u32 *data) -{ - u32 pmbase = (u32)rng->priv; - - *data = inl(pmbase + 0xF0); - - return 4; + return read; } static int amd_rng_init(struct hwrng *rng) { + struct amd768_priv *priv = (struct amd768_priv *)rng->priv; u8 rnen; - pci_read_config_byte(amd_pdev, 0x40, &rnen); - rnen |= (1 << 7); /* RNG on */ - pci_write_config_byte(amd_pdev, 0x40, rnen); + pci_read_config_byte(priv->pcidev, 0x40, &rnen); + rnen |= BIT(7); /* RNG on */ + pci_write_config_byte(priv->pcidev, 0x40, rnen); - pci_read_config_byte(amd_pdev, 0x41, &rnen); - rnen |= (1 << 7); /* PMIO enable */ - pci_write_config_byte(amd_pdev, 0x41, rnen); + pci_read_config_byte(priv->pcidev, 0x41, &rnen); + rnen |= BIT(7); /* PMIO enable */ + pci_write_config_byte(priv->pcidev, 0x41, rnen); return 0; } static void amd_rng_cleanup(struct hwrng *rng) { + struct amd768_priv *priv = (struct amd768_priv *)rng->priv; u8 rnen; - pci_read_config_byte(amd_pdev, 0x40, &rnen); - rnen &= ~(1 << 7); /* RNG off */ - pci_write_config_byte(amd_pdev, 0x40, rnen); + pci_read_config_byte(priv->pcidev, 0x40, &rnen); + rnen &= ~BIT(7); /* RNG off */ + pci_write_config_byte(priv->pcidev, 0x40, rnen); } - static struct hwrng amd_rng = { .name = "amd", .init = amd_rng_init, .cleanup = amd_rng_cleanup, - .data_present = amd_rng_data_present, - .data_read = amd_rng_data_read, + .read = amd_rng_read, }; - static int __init mod_init(void) { int err = -ENODEV; struct pci_dev *pdev = NULL; const struct pci_device_id *ent; u32 pmbase; + struct amd768_priv *priv; for_each_pci_dev(pdev) { ent = pci_match_id(pci_tbl, pdev); @@ -123,42 +137,44 @@ static int __init mod_init(void) goto found; } /* Device not found. */ - goto out; + return -ENODEV; found: err = pci_read_config_dword(pdev, 0x58, &pmbase); if (err) - goto out; - err = -EIO; + return err; + pmbase &= 0x0000FF00; if (pmbase == 0) - goto out; - if (!request_region(pmbase + 0xF0, 8, "AMD HWRNG")) { - dev_err(&pdev->dev, "AMD HWRNG region 0x%x already in use!\n", + return -EIO; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + if (!devm_request_region(&pdev->dev, pmbase + PMBASE_OFFSET, + PMBASE_SIZE, DRV_NAME)) { + dev_err(&pdev->dev, DRV_NAME " region 0x%x already in use!\n", pmbase + 0xF0); - err = -EBUSY; - goto out; + return -EBUSY; } - amd_rng.priv = (unsigned long)pmbase; - amd_pdev = pdev; - - pr_info("AMD768 RNG detected\n"); - err = hwrng_register(&amd_rng); - if (err) { - pr_err(PFX "RNG registering failed (%d)\n", - err); - release_region(pmbase + 0xF0, 8); - goto out; + + priv->iobase = devm_ioport_map(&pdev->dev, pmbase + PMBASE_OFFSET, + PMBASE_SIZE); + if (!priv->iobase) { + pr_err(DRV_NAME "Cannot map ioport\n"); + return -ENOMEM; } -out: - return err; + + amd_rng.priv = (unsigned long)priv; + priv->pcidev = pdev; + + pr_info(DRV_NAME " detected\n"); + return devm_hwrng_register(&pdev->dev, &amd_rng); } static void __exit mod_exit(void) { - u32 pmbase = (unsigned long)amd_rng.priv; - release_region(pmbase + 0xF0, 8); - hwrng_unregister(&amd_rng); } module_init(mod_init); diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c index af2149273fe0..574211a49549 100644 --- a/drivers/char/hw_random/bcm2835-rng.c +++ b/drivers/char/hw_random/bcm2835-rng.c @@ -92,9 +92,10 @@ static int bcm2835_rng_probe(struct platform_device *pdev) bcm2835_rng_ops.priv = (unsigned long)rng_base; rng_id = of_match_node(bcm2835_rng_of_match, np); - if (!rng_id) + if (!rng_id) { + iounmap(rng_base); return -EINVAL; - + } /* Check for rng init function, execute it */ rng_setup = rng_id->data; if (rng_setup) diff --git a/drivers/char/hw_random/cavium-rng-vf.c b/drivers/char/hw_random/cavium-rng-vf.c new file mode 100644 index 000000000000..066ae0e78d63 --- /dev/null +++ b/drivers/char/hw_random/cavium-rng-vf.c @@ -0,0 +1,99 @@ +/* + * Hardware Random Number Generator support for Cavium, Inc. + * Thunder processor family. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2016 Cavium, Inc. + */ + +#include <linux/hw_random.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> + +struct cavium_rng { + struct hwrng ops; + void __iomem *result; +}; + +/* Read data from the RNG unit */ +static int cavium_rng_read(struct hwrng *rng, void *dat, size_t max, bool wait) +{ + struct cavium_rng *p = container_of(rng, struct cavium_rng, ops); + unsigned int size = max; + + while (size >= 8) { + *((u64 *)dat) = readq(p->result); + size -= 8; + dat += 8; + } + while (size > 0) { + *((u8 *)dat) = readb(p->result); + size--; + dat++; + } + return max; +} + +/* Map Cavium RNG to an HWRNG object */ +static int cavium_rng_probe_vf(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct cavium_rng *rng; + int ret; + + rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); + if (!rng) + return -ENOMEM; + + /* Map the RNG result */ + rng->result = pcim_iomap(pdev, 0, 0); + if (!rng->result) { + dev_err(&pdev->dev, "Error iomap failed retrieving result.\n"); + return -ENOMEM; + } + + rng->ops.name = "cavium rng"; + rng->ops.read = cavium_rng_read; + rng->ops.quality = 1000; + + pci_set_drvdata(pdev, rng); + + ret = hwrng_register(&rng->ops); + if (ret) { + dev_err(&pdev->dev, "Error registering device as HWRNG.\n"); + return ret; + } + + return 0; +} + +/* Remove the VF */ +void cavium_rng_remove_vf(struct pci_dev *pdev) +{ + struct cavium_rng *rng; + + rng = pci_get_drvdata(pdev); + hwrng_unregister(&rng->ops); +} + +static const struct pci_device_id cavium_rng_vf_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa033), 0, 0, 0}, + {0,}, +}; +MODULE_DEVICE_TABLE(pci, cavium_rng_vf_id_table); + +static struct pci_driver cavium_rng_vf_driver = { + .name = "cavium_rng_vf", + .id_table = cavium_rng_vf_id_table, + .probe = cavium_rng_probe_vf, + .remove = cavium_rng_remove_vf, +}; +module_pci_driver(cavium_rng_vf_driver); + +MODULE_AUTHOR("Omer Khaliq <okhaliq@caviumnetworks.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/cavium-rng.c b/drivers/char/hw_random/cavium-rng.c new file mode 100644 index 000000000000..a944e0a47f42 --- /dev/null +++ b/drivers/char/hw_random/cavium-rng.c @@ -0,0 +1,94 @@ +/* + * Hardware Random Number Generator support for Cavium Inc. + * Thunder processor family. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2016 Cavium, Inc. + */ + +#include <linux/hw_random.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> + +#define THUNDERX_RNM_ENT_EN 0x1 +#define THUNDERX_RNM_RNG_EN 0x2 + +struct cavium_rng_pf { + void __iomem *control_status; +}; + +/* Enable the RNG hardware and activate the VF */ +static int cavium_rng_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct cavium_rng_pf *rng; + int iov_err; + + rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); + if (!rng) + return -ENOMEM; + + /*Map the RNG control */ + rng->control_status = pcim_iomap(pdev, 0, 0); + if (!rng->control_status) { + dev_err(&pdev->dev, + "Error iomap failed retrieving control_status.\n"); + return -ENOMEM; + } + + /* Enable the RNG hardware and entropy source */ + writeq(THUNDERX_RNM_RNG_EN | THUNDERX_RNM_ENT_EN, + rng->control_status); + + pci_set_drvdata(pdev, rng); + + /* Enable the Cavium RNG as a VF */ + iov_err = pci_enable_sriov(pdev, 1); + if (iov_err != 0) { + /* Disable the RNG hardware and entropy source */ + writeq(0, rng->control_status); + dev_err(&pdev->dev, + "Error initializing RNG virtual function,(%i).\n", + iov_err); + return iov_err; + } + + return 0; +} + +/* Disable VF and RNG Hardware */ +void cavium_rng_remove(struct pci_dev *pdev) +{ + struct cavium_rng_pf *rng; + + rng = pci_get_drvdata(pdev); + + /* Remove the VF */ + pci_disable_sriov(pdev); + + /* Disable the RNG hardware and entropy source */ + writeq(0, rng->control_status); +} + +static const struct pci_device_id cavium_rng_pf_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa018), 0, 0, 0}, /* Thunder RNM */ + {0,}, +}; + +MODULE_DEVICE_TABLE(pci, cavium_rng_pf_id_table); + +static struct pci_driver cavium_rng_pf_driver = { + .name = "cavium_rng_pf", + .id_table = cavium_rng_pf_id_table, + .probe = cavium_rng_probe, + .remove = cavium_rng_remove, +}; + +module_pci_driver(cavium_rng_pf_driver); +MODULE_AUTHOR("Omer Khaliq <okhaliq@caviumnetworks.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 9203f2d130c0..482794526e8c 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -449,22 +449,6 @@ int hwrng_register(struct hwrng *rng) goto out; mutex_lock(&rng_mutex); - - /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */ - err = -ENOMEM; - if (!rng_buffer) { - rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL); - if (!rng_buffer) - goto out_unlock; - } - if (!rng_fillbuf) { - rng_fillbuf = kmalloc(rng_buffer_size(), GFP_KERNEL); - if (!rng_fillbuf) { - kfree(rng_buffer); - goto out_unlock; - } - } - /* Must not register two RNGs with the same name. */ err = -EEXIST; list_for_each_entry(tmp, &rng_list, list) { @@ -573,7 +557,26 @@ EXPORT_SYMBOL_GPL(devm_hwrng_unregister); static int __init hwrng_modinit(void) { - return register_miscdev(); + int ret = -ENOMEM; + + /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */ + rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL); + if (!rng_buffer) + return -ENOMEM; + + rng_fillbuf = kmalloc(rng_buffer_size(), GFP_KERNEL); + if (!rng_fillbuf) { + kfree(rng_buffer); + return -ENOMEM; + } + + ret = register_miscdev(); + if (ret) { + kfree(rng_fillbuf); + kfree(rng_buffer); + } + + return ret; } static void __exit hwrng_modexit(void) diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c index 0d0579fe465e..e7a245942029 100644 --- a/drivers/char/hw_random/geode-rng.c +++ b/drivers/char/hw_random/geode-rng.c @@ -24,15 +24,12 @@ * warranty of any kind, whether express or implied. */ -#include <linux/module.h> +#include <linux/delay.h> +#include <linux/hw_random.h> +#include <linux/io.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/pci.h> -#include <linux/hw_random.h> -#include <linux/delay.h> -#include <asm/io.h> - - -#define PFX KBUILD_MODNAME ": " #define GEODE_RNG_DATA_REG 0x50 #define GEODE_RNG_STATUS_REG 0x54 @@ -85,7 +82,6 @@ static struct hwrng geode_rng = { static int __init mod_init(void) { - int err = -ENODEV; struct pci_dev *pdev = NULL; const struct pci_device_id *ent; void __iomem *mem; @@ -93,43 +89,27 @@ static int __init mod_init(void) for_each_pci_dev(pdev) { ent = pci_match_id(pci_tbl, pdev); - if (ent) - goto found; - } - /* Device not found. */ - goto out; - -found: - rng_base = pci_resource_start(pdev, 0); - if (rng_base == 0) - goto out; - err = -ENOMEM; - mem = ioremap(rng_base, 0x58); - if (!mem) - goto out; - geode_rng.priv = (unsigned long)mem; - - pr_info("AMD Geode RNG detected\n"); - err = hwrng_register(&geode_rng); - if (err) { - pr_err(PFX "RNG registering failed (%d)\n", - err); - goto err_unmap; + if (ent) { + rng_base = pci_resource_start(pdev, 0); + if (rng_base == 0) + return -ENODEV; + + mem = devm_ioremap(&pdev->dev, rng_base, 0x58); + if (!mem) + return -ENOMEM; + geode_rng.priv = (unsigned long)mem; + + pr_info("AMD Geode RNG detected\n"); + return devm_hwrng_register(&pdev->dev, &geode_rng); + } } -out: - return err; -err_unmap: - iounmap(mem); - goto out; + /* Device not found. */ + return -ENODEV; } static void __exit mod_exit(void) { - void __iomem *mem = (void __iomem *)geode_rng.priv; - - hwrng_unregister(&geode_rng); - iounmap(mem); } module_init(mod_init); diff --git a/drivers/char/hw_random/meson-rng.c b/drivers/char/hw_random/meson-rng.c index 0cfd81bcaeac..58bef39f7286 100644 --- a/drivers/char/hw_random/meson-rng.c +++ b/drivers/char/hw_random/meson-rng.c @@ -76,9 +76,6 @@ static int meson_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) struct meson_rng_data *data = container_of(rng, struct meson_rng_data, rng); - if (max < sizeof(u32)) - return 0; - *(u32 *)buf = readl_relaxed(data->base + RNG_DATA); return sizeof(u32); diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index 01d4be2c354b..f5c26a5f6875 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -385,7 +385,7 @@ static int omap_rng_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); - if (ret) { + if (ret < 0) { dev_err(&pdev->dev, "Failed to runtime_get device: %d\n", ret); pm_runtime_put_noidle(&pdev->dev); goto err_ioremap; @@ -443,7 +443,7 @@ static int __maybe_unused omap_rng_resume(struct device *dev) int ret; ret = pm_runtime_get_sync(dev); - if (ret) { + if (ret < 0) { dev_err(dev, "Failed to runtime_get device: %d\n", ret); pm_runtime_put_noidle(dev); return ret; diff --git a/drivers/char/hw_random/omap3-rom-rng.c b/drivers/char/hw_random/omap3-rom-rng.c index 8da14f1a1f56..37a58d78aab3 100644 --- a/drivers/char/hw_random/omap3-rom-rng.c +++ b/drivers/char/hw_random/omap3-rom-rng.c @@ -71,12 +71,7 @@ static int omap3_rom_rng_get_random(void *buf, unsigned int count) return 0; } -static int omap3_rom_rng_data_present(struct hwrng *rng, int wait) -{ - return 1; -} - -static int omap3_rom_rng_data_read(struct hwrng *rng, u32 *data) +static int omap3_rom_rng_read(struct hwrng *rng, void *data, size_t max, bool w) { int r; @@ -88,8 +83,7 @@ static int omap3_rom_rng_data_read(struct hwrng *rng, u32 *data) static struct hwrng omap3_rom_rng_ops = { .name = "omap3-rom", - .data_present = omap3_rom_rng_data_present, - .data_read = omap3_rom_rng_data_read, + .read = omap3_rom_rng_read, }; static int omap3_rom_rng_probe(struct platform_device *pdev) diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c index 699b7259f5d7..545df485bcc4 100644 --- a/drivers/char/hw_random/pasemi-rng.c +++ b/drivers/char/hw_random/pasemi-rng.c @@ -26,7 +26,7 @@ #include <linux/delay.h> #include <linux/of_address.h> #include <linux/of_platform.h> -#include <asm/io.h> +#include <linux/io.h> #define SDCRNG_CTL_REG 0x00 #define SDCRNG_CTL_FVLD_M 0x0000f000 @@ -95,42 +95,20 @@ static struct hwrng pasemi_rng = { .data_read = pasemi_rng_data_read, }; -static int rng_probe(struct platform_device *ofdev) +static int rng_probe(struct platform_device *pdev) { void __iomem *rng_regs; - struct device_node *rng_np = ofdev->dev.of_node; - struct resource res; - int err = 0; + struct resource *res; - err = of_address_to_resource(rng_np, 0, &res); - if (err) - return -ENODEV; - - rng_regs = ioremap(res.start, 0x100); - - if (!rng_regs) - return -ENOMEM; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rng_regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(rng_regs)) + return PTR_ERR(rng_regs); pasemi_rng.priv = (unsigned long)rng_regs; pr_info("Registering PA Semi RNG\n"); - - err = hwrng_register(&pasemi_rng); - - if (err) - iounmap(rng_regs); - - return err; -} - -static int rng_remove(struct platform_device *dev) -{ - void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; - - hwrng_unregister(&pasemi_rng); - iounmap(rng_regs); - - return 0; + return devm_hwrng_register(&pdev->dev, &pasemi_rng); } static const struct of_device_id rng_match[] = { @@ -146,7 +124,6 @@ static struct platform_driver rng_driver = { .of_match_table = rng_match, }, .probe = rng_probe, - .remove = rng_remove, }; module_platform_driver(rng_driver); diff --git a/drivers/char/hw_random/pic32-rng.c b/drivers/char/hw_random/pic32-rng.c index 108897bea2d0..11dc9b7c09ce 100644 --- a/drivers/char/hw_random/pic32-rng.c +++ b/drivers/char/hw_random/pic32-rng.c @@ -143,7 +143,6 @@ static struct platform_driver pic32_rng_driver = { .remove = pic32_rng_remove, .driver = { .name = "pic32-rng", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(pic32_rng_of_match), }, }; diff --git a/drivers/char/hw_random/st-rng.c b/drivers/char/hw_random/st-rng.c index 1d35363d23c5..938ec10e733d 100644 --- a/drivers/char/hw_random/st-rng.c +++ b/drivers/char/hw_random/st-rng.c @@ -54,9 +54,6 @@ static int st_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) u32 status; int i; - if (max < sizeof(u16)) - return -EINVAL; - /* Wait until FIFO is full - max 4uS*/ for (i = 0; i < ST_RNG_FILL_FIFO_TIMEOUT; i++) { status = readl_relaxed(ddata->base + ST_RNG_STATUS_REG); @@ -111,6 +108,7 @@ static int st_rng_probe(struct platform_device *pdev) ret = hwrng_register(&ddata->ops); if (ret) { dev_err(&pdev->dev, "Failed to register HW RNG\n"); + clk_disable_unprepare(clk); return ret; } diff --git a/drivers/char/hw_random/tx4939-rng.c b/drivers/char/hw_random/tx4939-rng.c index a7b694913416..1093583b579c 100644 --- a/drivers/char/hw_random/tx4939-rng.c +++ b/drivers/char/hw_random/tx4939-rng.c @@ -144,22 +144,13 @@ static int __init tx4939_rng_probe(struct platform_device *dev) } platform_set_drvdata(dev, rngdev); - return hwrng_register(&rngdev->rng); -} - -static int __exit tx4939_rng_remove(struct platform_device *dev) -{ - struct tx4939_rng *rngdev = platform_get_drvdata(dev); - - hwrng_unregister(&rngdev->rng); - return 0; + return devm_hwrng_register(&dev->dev, &rngdev->rng); } static struct platform_driver tx4939_rng_driver = { .driver = { .name = "tx4939-rng", }, - .remove = tx4939_rng_remove, }; module_platform_driver_probe(tx4939_rng_driver, tx4939_rng_probe); |