aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPrarit Bhargava <prarit@redhat.com>2017-03-14 07:36:02 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2017-03-16 05:43:11 -0400
commit8c75704ebcac2ffa31ee7bcc359baf701b52bf00 (patch)
treef114d4cd11eacd4426d46398589d5a5352dc5142
parent69db7009318758769d625b023402161c750f7876 (diff)
hwrng: geode - Revert managed API changes
After commit e9afc746299d ("hwrng: geode - Use linux/io.h instead of asm/io.h") the geode-rng driver uses devres with pci_dev->dev to keep track of resources, but does not actually register a PCI driver. This results in the following issues: 1. The driver leaks memory because the driver does not attach to a device. The driver only uses the PCI device as a reference. devm_*() functions will release resources on driver detach, which the geode-rng driver will never do. As a result, 2. The driver cannot be reloaded because there is always a use of the ioport and region after the first load of the driver. Revert the changes made by e9afc746299d ("hwrng: geode - Use linux/io.h instead of asm/io.h"). Cc: <stable@vger.kernel.org> Signed-off-by: Prarit Bhargava <prarit@redhat.com> Fixes: 6e9b5e76882c ("hwrng: geode - Migrate to managed API") Cc: Matt Mackall <mpm@selenic.com> Cc: Corentin LABBE <clabbe.montjoie@gmail.com> Cc: PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com> Cc: Wei Yongjun <weiyongjun1@huawei.com> Cc: linux-crypto@vger.kernel.org Cc: linux-geode@lists.infradead.org Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--drivers/char/hw_random/geode-rng.c50
1 files changed, 35 insertions, 15 deletions
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
index e7a245942029..e1d421a36a13 100644
--- a/drivers/char/hw_random/geode-rng.c
+++ b/drivers/char/hw_random/geode-rng.c
@@ -31,6 +31,9 @@
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/pci.h> 32#include <linux/pci.h>
33 33
34
35#define PFX KBUILD_MODNAME ": "
36
34#define GEODE_RNG_DATA_REG 0x50 37#define GEODE_RNG_DATA_REG 0x50
35#define GEODE_RNG_STATUS_REG 0x54 38#define GEODE_RNG_STATUS_REG 0x54
36 39
@@ -82,6 +85,7 @@ static struct hwrng geode_rng = {
82 85
83static int __init mod_init(void) 86static int __init mod_init(void)
84{ 87{
88 int err = -ENODEV;
85 struct pci_dev *pdev = NULL; 89 struct pci_dev *pdev = NULL;
86 const struct pci_device_id *ent; 90 const struct pci_device_id *ent;
87 void __iomem *mem; 91 void __iomem *mem;
@@ -89,27 +93,43 @@ static int __init mod_init(void)
89 93
90 for_each_pci_dev(pdev) { 94 for_each_pci_dev(pdev) {
91 ent = pci_match_id(pci_tbl, pdev); 95 ent = pci_match_id(pci_tbl, pdev);
92 if (ent) { 96 if (ent)
93 rng_base = pci_resource_start(pdev, 0); 97 goto found;
94 if (rng_base == 0)
95 return -ENODEV;
96
97 mem = devm_ioremap(&pdev->dev, rng_base, 0x58);
98 if (!mem)
99 return -ENOMEM;
100 geode_rng.priv = (unsigned long)mem;
101
102 pr_info("AMD Geode RNG detected\n");
103 return devm_hwrng_register(&pdev->dev, &geode_rng);
104 }
105 } 98 }
106
107 /* Device not found. */ 99 /* Device not found. */
108 return -ENODEV; 100 goto out;
101
102found:
103 rng_base = pci_resource_start(pdev, 0);
104 if (rng_base == 0)
105 goto out;
106 err = -ENOMEM;
107 mem = ioremap(rng_base, 0x58);
108 if (!mem)
109 goto out;
110 geode_rng.priv = (unsigned long)mem;
111
112 pr_info("AMD Geode RNG detected\n");
113 err = hwrng_register(&geode_rng);
114 if (err) {
115 pr_err(PFX "RNG registering failed (%d)\n",
116 err);
117 goto err_unmap;
118 }
119out:
120 return err;
121
122err_unmap:
123 iounmap(mem);
124 goto out;
109} 125}
110 126
111static void __exit mod_exit(void) 127static void __exit mod_exit(void)
112{ 128{
129 void __iomem *mem = (void __iomem *)geode_rng.priv;
130
131 hwrng_unregister(&geode_rng);
132 iounmap(mem);
113} 133}
114 134
115module_init(mod_init); 135module_init(mod_init);