diff options
Diffstat (limited to 'drivers/char/hw_random/geode-rng.c')
| -rw-r--r-- | drivers/char/hw_random/geode-rng.c | 36 | 
1 files changed, 28 insertions, 8 deletions
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c index 138ce434f86b..12fbe8091831 100644 --- a/drivers/char/hw_random/geode-rng.c +++ b/drivers/char/hw_random/geode-rng.c @@ -51,6 +51,10 @@ static const struct pci_device_id pci_tbl[] = {  };  MODULE_DEVICE_TABLE(pci, pci_tbl); +struct amd_geode_priv { +	struct pci_dev *pcidev; +	void __iomem *membase; +};  static int geode_rng_data_read(struct hwrng *rng, u32 *data)  { @@ -90,6 +94,7 @@ static int __init geode_rng_init(void)  	const struct pci_device_id *ent;  	void __iomem *mem;  	unsigned long rng_base; +	struct amd_geode_priv *priv;  	for_each_pci_dev(pdev) {  		ent = pci_match_id(pci_tbl, pdev); @@ -97,17 +102,26 @@ static int __init geode_rng_init(void)  			goto found;  	}  	/* Device not found. */ -	goto out; +	return err;  found: +	priv = kzalloc(sizeof(*priv), GFP_KERNEL); +	if (!priv) { +		err = -ENOMEM; +		goto put_dev; +	} +  	rng_base = pci_resource_start(pdev, 0);  	if (rng_base == 0) -		goto out; +		goto free_priv;  	err = -ENOMEM;  	mem = ioremap(rng_base, 0x58);  	if (!mem) -		goto out; -	geode_rng.priv = (unsigned long)mem; +		goto free_priv; + +	geode_rng.priv = (unsigned long)priv; +	priv->membase = mem; +	priv->pcidev = pdev;  	pr_info("AMD Geode RNG detected\n");  	err = hwrng_register(&geode_rng); @@ -116,20 +130,26 @@ found:  		       err);  		goto err_unmap;  	} -out:  	return err;  err_unmap:  	iounmap(mem); -	goto out; +free_priv: +	kfree(priv); +put_dev: +	pci_dev_put(pdev); +	return err;  }  static void __exit geode_rng_exit(void)  { -	void __iomem *mem = (void __iomem *)geode_rng.priv; +	struct amd_geode_priv *priv; +	priv = (struct amd_geode_priv *)geode_rng.priv;  	hwrng_unregister(&geode_rng); -	iounmap(mem); +	iounmap(priv->membase); +	pci_dev_put(priv->pcidev); +	kfree(priv);  }  module_init(geode_rng_init);  | 
