diff options
author | Prarit Bhargava <prarit@redhat.com> | 2017-03-14 07:36:02 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2017-03-16 05:43:11 -0400 |
commit | 8c75704ebcac2ffa31ee7bcc359baf701b52bf00 (patch) | |
tree | f114d4cd11eacd4426d46398589d5a5352dc5142 | |
parent | 69db7009318758769d625b023402161c750f7876 (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.c | 50 |
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 | ||
83 | static int __init mod_init(void) | 86 | static 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 | |||
102 | found: | ||
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 | } | ||
119 | out: | ||
120 | return err; | ||
121 | |||
122 | err_unmap: | ||
123 | iounmap(mem); | ||
124 | goto out; | ||
109 | } | 125 | } |
110 | 126 | ||
111 | static void __exit mod_exit(void) | 127 | static 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 | ||
115 | module_init(mod_init); | 135 | module_init(mod_init); |