diff options
author | Tony Prisk <linux@prisktech.co.nz> | 2013-01-17 23:58:22 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2013-02-11 17:21:29 -0500 |
commit | 9f01d30ee191a74f1e7a2ac0710f064f472d000a (patch) | |
tree | 7be3599e3068977c27a1cb0052d38f0fdb895f2f /drivers/gpio | |
parent | 362432aed5e5b497a8cf7b20c268ba71df93c045 (diff) |
gpio/vt8500: memory cleanup missing
This driver is missing a .remove callback, and the fail path on
probe is incomplete.
If an error occurs in vt8500_add_chips, gpio_base is not unmapped.
The driver is also ignoring the return value from this function so
if a chip fails to register it completes as successful.
Replaced pr_err with dev_err in vt8500_add_chips since the device is
available.
There is also no .remove callback defined so the function is added.
Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-vt8500.c | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c index 9a7c434d2947..81683ca35ac1 100644 --- a/drivers/gpio/gpio-vt8500.c +++ b/drivers/gpio/gpio-vt8500.c | |||
@@ -127,6 +127,12 @@ struct vt8500_gpio_chip { | |||
127 | void __iomem *base; | 127 | void __iomem *base; |
128 | }; | 128 | }; |
129 | 129 | ||
130 | struct vt8500_data { | ||
131 | struct vt8500_gpio_chip *chip; | ||
132 | void __iomem *iobase; | ||
133 | int num_banks; | ||
134 | }; | ||
135 | |||
130 | 136 | ||
131 | #define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip) | 137 | #define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip) |
132 | 138 | ||
@@ -224,19 +230,32 @@ static int vt8500_of_xlate(struct gpio_chip *gc, | |||
224 | static int vt8500_add_chips(struct platform_device *pdev, void __iomem *base, | 230 | static int vt8500_add_chips(struct platform_device *pdev, void __iomem *base, |
225 | const struct vt8500_gpio_data *data) | 231 | const struct vt8500_gpio_data *data) |
226 | { | 232 | { |
233 | struct vt8500_data *priv; | ||
227 | struct vt8500_gpio_chip *vtchip; | 234 | struct vt8500_gpio_chip *vtchip; |
228 | struct gpio_chip *chip; | 235 | struct gpio_chip *chip; |
229 | int i; | 236 | int i; |
230 | int pin_cnt = 0; | 237 | int pin_cnt = 0; |
231 | 238 | ||
232 | vtchip = devm_kzalloc(&pdev->dev, | 239 | priv = devm_kzalloc(&pdev->dev, sizeof(struct vt8500_data), GFP_KERNEL); |
240 | if (!priv) { | ||
241 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
242 | return -ENOMEM; | ||
243 | } | ||
244 | |||
245 | priv->chip = devm_kzalloc(&pdev->dev, | ||
233 | sizeof(struct vt8500_gpio_chip) * data->num_banks, | 246 | sizeof(struct vt8500_gpio_chip) * data->num_banks, |
234 | GFP_KERNEL); | 247 | GFP_KERNEL); |
235 | if (!vtchip) { | 248 | if (!priv->chip) { |
236 | pr_err("%s: failed to allocate chip memory\n", __func__); | 249 | dev_err(&pdev->dev, "failed to allocate chip memory\n"); |
237 | return -ENOMEM; | 250 | return -ENOMEM; |
238 | } | 251 | } |
239 | 252 | ||
253 | priv->iobase = base; | ||
254 | priv->num_banks = data->num_banks; | ||
255 | platform_set_drvdata(pdev, priv); | ||
256 | |||
257 | vtchip = priv->chip; | ||
258 | |||
240 | for (i = 0; i < data->num_banks; i++) { | 259 | for (i = 0; i < data->num_banks; i++) { |
241 | vtchip[i].base = base; | 260 | vtchip[i].base = base; |
242 | vtchip[i].regs = &data->banks[i]; | 261 | vtchip[i].regs = &data->banks[i]; |
@@ -273,36 +292,54 @@ static struct of_device_id vt8500_gpio_dt_ids[] = { | |||
273 | 292 | ||
274 | static int vt8500_gpio_probe(struct platform_device *pdev) | 293 | static int vt8500_gpio_probe(struct platform_device *pdev) |
275 | { | 294 | { |
295 | int ret; | ||
276 | void __iomem *gpio_base; | 296 | void __iomem *gpio_base; |
277 | struct device_node *np; | 297 | struct resource *res; |
278 | const struct of_device_id *of_id = | 298 | const struct of_device_id *of_id = |
279 | of_match_device(vt8500_gpio_dt_ids, &pdev->dev); | 299 | of_match_device(vt8500_gpio_dt_ids, &pdev->dev); |
280 | 300 | ||
281 | if (!of_id) { | 301 | if (!of_id) { |
282 | dev_err(&pdev->dev, "Failed to find gpio controller\n"); | 302 | dev_err(&pdev->dev, "No matching driver data\n"); |
283 | return -ENODEV; | 303 | return -ENODEV; |
284 | } | 304 | } |
285 | 305 | ||
286 | np = pdev->dev.of_node; | 306 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
287 | if (!np) { | 307 | if (!res) { |
288 | dev_err(&pdev->dev, "Missing GPIO description in devicetree\n"); | 308 | dev_err(&pdev->dev, "Unable to get IO resource\n"); |
289 | return -EFAULT; | 309 | return -ENODEV; |
290 | } | 310 | } |
291 | 311 | ||
292 | gpio_base = of_iomap(np, 0); | 312 | gpio_base = devm_request_and_ioremap(&pdev->dev, res); |
293 | if (!gpio_base) { | 313 | if (!gpio_base) { |
294 | dev_err(&pdev->dev, "Unable to map GPIO registers\n"); | 314 | dev_err(&pdev->dev, "Unable to map GPIO registers\n"); |
295 | of_node_put(np); | ||
296 | return -ENOMEM; | 315 | return -ENOMEM; |
297 | } | 316 | } |
298 | 317 | ||
299 | vt8500_add_chips(pdev, gpio_base, of_id->data); | 318 | ret = vt8500_add_chips(pdev, gpio_base, of_id->data); |
319 | |||
320 | return ret; | ||
321 | } | ||
322 | |||
323 | static int vt8500_gpio_remove(struct platform_device *pdev) | ||
324 | { | ||
325 | int i; | ||
326 | int ret; | ||
327 | struct vt8500_data *priv = platform_get_drvdata(pdev); | ||
328 | struct vt8500_gpio_chip *vtchip = priv->chip; | ||
329 | |||
330 | for (i = 0; i < priv->num_banks; i++) { | ||
331 | ret = gpiochip_remove(&vtchip[i].chip); | ||
332 | if (ret) | ||
333 | dev_warn(&pdev->dev, "gpiochip_remove returned %d\n", | ||
334 | ret); | ||
335 | } | ||
300 | 336 | ||
301 | return 0; | 337 | return 0; |
302 | } | 338 | } |
303 | 339 | ||
304 | static struct platform_driver vt8500_gpio_driver = { | 340 | static struct platform_driver vt8500_gpio_driver = { |
305 | .probe = vt8500_gpio_probe, | 341 | .probe = vt8500_gpio_probe, |
342 | .remove = vt8500_gpio_remove, | ||
306 | .driver = { | 343 | .driver = { |
307 | .name = "vt8500-gpio", | 344 | .name = "vt8500-gpio", |
308 | .owner = THIS_MODULE, | 345 | .owner = THIS_MODULE, |