.. | .. |
---|
51 | 51 | }; |
---|
52 | 52 | MODULE_DEVICE_TABLE(pci, pci_tbl); |
---|
53 | 53 | |
---|
| 54 | +struct amd_geode_priv { |
---|
| 55 | + struct pci_dev *pcidev; |
---|
| 56 | + void __iomem *membase; |
---|
| 57 | +}; |
---|
54 | 58 | |
---|
55 | 59 | static int geode_rng_data_read(struct hwrng *rng, u32 *data) |
---|
56 | 60 | { |
---|
.. | .. |
---|
90 | 94 | const struct pci_device_id *ent; |
---|
91 | 95 | void __iomem *mem; |
---|
92 | 96 | unsigned long rng_base; |
---|
| 97 | + struct amd_geode_priv *priv; |
---|
93 | 98 | |
---|
94 | 99 | for_each_pci_dev(pdev) { |
---|
95 | 100 | ent = pci_match_id(pci_tbl, pdev); |
---|
.. | .. |
---|
97 | 102 | goto found; |
---|
98 | 103 | } |
---|
99 | 104 | /* Device not found. */ |
---|
100 | | - goto out; |
---|
| 105 | + return err; |
---|
101 | 106 | |
---|
102 | 107 | found: |
---|
| 108 | + priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
---|
| 109 | + if (!priv) { |
---|
| 110 | + err = -ENOMEM; |
---|
| 111 | + goto put_dev; |
---|
| 112 | + } |
---|
| 113 | + |
---|
103 | 114 | rng_base = pci_resource_start(pdev, 0); |
---|
104 | 115 | if (rng_base == 0) |
---|
105 | | - goto out; |
---|
| 116 | + goto free_priv; |
---|
106 | 117 | err = -ENOMEM; |
---|
107 | 118 | mem = ioremap(rng_base, 0x58); |
---|
108 | 119 | if (!mem) |
---|
109 | | - goto out; |
---|
110 | | - geode_rng.priv = (unsigned long)mem; |
---|
| 120 | + goto free_priv; |
---|
| 121 | + |
---|
| 122 | + geode_rng.priv = (unsigned long)priv; |
---|
| 123 | + priv->membase = mem; |
---|
| 124 | + priv->pcidev = pdev; |
---|
111 | 125 | |
---|
112 | 126 | pr_info("AMD Geode RNG detected\n"); |
---|
113 | 127 | err = hwrng_register(&geode_rng); |
---|
.. | .. |
---|
116 | 130 | err); |
---|
117 | 131 | goto err_unmap; |
---|
118 | 132 | } |
---|
119 | | -out: |
---|
120 | 133 | return err; |
---|
121 | 134 | |
---|
122 | 135 | err_unmap: |
---|
123 | 136 | iounmap(mem); |
---|
124 | | - goto out; |
---|
| 137 | +free_priv: |
---|
| 138 | + kfree(priv); |
---|
| 139 | +put_dev: |
---|
| 140 | + pci_dev_put(pdev); |
---|
| 141 | + return err; |
---|
125 | 142 | } |
---|
126 | 143 | |
---|
127 | 144 | static void __exit mod_exit(void) |
---|
128 | 145 | { |
---|
129 | | - void __iomem *mem = (void __iomem *)geode_rng.priv; |
---|
| 146 | + struct amd_geode_priv *priv; |
---|
130 | 147 | |
---|
| 148 | + priv = (struct amd_geode_priv *)geode_rng.priv; |
---|
131 | 149 | hwrng_unregister(&geode_rng); |
---|
132 | | - iounmap(mem); |
---|
| 150 | + iounmap(priv->membase); |
---|
| 151 | + pci_dev_put(priv->pcidev); |
---|
| 152 | + kfree(priv); |
---|
133 | 153 | } |
---|
134 | 154 | |
---|
135 | 155 | module_init(mod_init); |
---|