Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Prarit Bhargava and committed by
Herbert Xu
8c75704e 69db7009

+35 -15
+35 -15
drivers/char/hw_random/geode-rng.c
··· 31 31 #include <linux/module.h> 32 32 #include <linux/pci.h> 33 33 34 + 35 + #define PFX KBUILD_MODNAME ": " 36 + 34 37 #define GEODE_RNG_DATA_REG 0x50 35 38 #define GEODE_RNG_STATUS_REG 0x54 36 39 ··· 85 82 86 83 static int __init mod_init(void) 87 84 { 85 + int err = -ENODEV; 88 86 struct pci_dev *pdev = NULL; 89 87 const struct pci_device_id *ent; 90 88 void __iomem *mem; ··· 93 89 94 90 for_each_pci_dev(pdev) { 95 91 ent = pci_match_id(pci_tbl, pdev); 96 - if (ent) { 97 - rng_base = pci_resource_start(pdev, 0); 98 - if (rng_base == 0) 99 - return -ENODEV; 100 - 101 - mem = devm_ioremap(&pdev->dev, rng_base, 0x58); 102 - if (!mem) 103 - return -ENOMEM; 104 - geode_rng.priv = (unsigned long)mem; 105 - 106 - pr_info("AMD Geode RNG detected\n"); 107 - return devm_hwrng_register(&pdev->dev, &geode_rng); 108 - } 92 + if (ent) 93 + goto found; 109 94 } 110 - 111 95 /* Device not found. */ 112 - return -ENODEV; 96 + goto out; 97 + 98 + found: 99 + rng_base = pci_resource_start(pdev, 0); 100 + if (rng_base == 0) 101 + goto out; 102 + err = -ENOMEM; 103 + mem = ioremap(rng_base, 0x58); 104 + if (!mem) 105 + goto out; 106 + geode_rng.priv = (unsigned long)mem; 107 + 108 + pr_info("AMD Geode RNG detected\n"); 109 + err = hwrng_register(&geode_rng); 110 + if (err) { 111 + pr_err(PFX "RNG registering failed (%d)\n", 112 + err); 113 + goto err_unmap; 114 + } 115 + out: 116 + return err; 117 + 118 + err_unmap: 119 + iounmap(mem); 120 + goto out; 113 121 } 114 122 115 123 static void __exit mod_exit(void) 116 124 { 125 + void __iomem *mem = (void __iomem *)geode_rng.priv; 126 + 127 + hwrng_unregister(&geode_rng); 128 + iounmap(mem); 117 129 } 118 130 119 131 module_init(mod_init);