diff options
author | Takeshi Yoshimura <yos@sslab.ics.keio.ac.jp> | 2015-06-14 13:43:59 -0400 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2015-06-14 15:35:45 -0400 |
commit | d19319affb6c84ef45185588f63dc28f8ff95ea3 (patch) | |
tree | 6419375f21500c0125d8f9de33ecdf2d6ebbe17f | |
parent | 2fb22a8042fe96b4220843f79241c116d90922c4 (diff) |
pcmcia: Fix resource leaks in yenta_probe() and _close()
There are some resource leaks in yenta_probe() and _close(). I fixed
the following issues with some code cleanups. Thanks to Dominik's
suggestions.
On the error path in yenta_probe():
- a requested irq is not released
- yenta_free_resources() and pci_set_drvdata(dev, NULL) are not called
In yenta_close():
- kfree(sock) is not called
- sock->base is always set to non-NULL when yenta_close() is called,
therefore the check in yenta_close() is not necessary.
Signed-off-by: Takeshi Yoshimura <yos@sslab.ics.keio.ac.jp>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r-- | drivers/pcmcia/yenta_socket.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 56c83437271c..5d6d9b1549bc 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -801,13 +801,13 @@ static void yenta_close(struct pci_dev *dev) | |||
801 | else | 801 | else |
802 | del_timer_sync(&sock->poll_timer); | 802 | del_timer_sync(&sock->poll_timer); |
803 | 803 | ||
804 | if (sock->base) | 804 | iounmap(sock->base); |
805 | iounmap(sock->base); | ||
806 | yenta_free_resources(sock); | 805 | yenta_free_resources(sock); |
807 | 806 | ||
808 | pci_release_regions(dev); | 807 | pci_release_regions(dev); |
809 | pci_disable_device(dev); | 808 | pci_disable_device(dev); |
810 | pci_set_drvdata(dev, NULL); | 809 | pci_set_drvdata(dev, NULL); |
810 | kfree(sock); | ||
811 | } | 811 | } |
812 | 812 | ||
813 | 813 | ||
@@ -1254,25 +1254,34 @@ static int yenta_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1254 | 1254 | ||
1255 | /* Register it with the pcmcia layer.. */ | 1255 | /* Register it with the pcmcia layer.. */ |
1256 | ret = pcmcia_register_socket(&socket->socket); | 1256 | ret = pcmcia_register_socket(&socket->socket); |
1257 | if (ret == 0) { | 1257 | if (ret) |
1258 | /* Add the yenta register attributes */ | 1258 | goto free_irq; |
1259 | ret = device_create_file(&dev->dev, &dev_attr_yenta_registers); | 1259 | |
1260 | if (ret == 0) | 1260 | /* Add the yenta register attributes */ |
1261 | goto out; | 1261 | ret = device_create_file(&dev->dev, &dev_attr_yenta_registers); |
1262 | 1262 | if (ret) | |
1263 | /* error path... */ | 1263 | goto unregister_socket; |
1264 | pcmcia_unregister_socket(&socket->socket); | ||
1265 | } | ||
1266 | 1264 | ||
1265 | return ret; | ||
1266 | |||
1267 | /* error path... */ | ||
1268 | unregister_socket: | ||
1269 | pcmcia_unregister_socket(&socket->socket); | ||
1270 | free_irq: | ||
1271 | if (socket->cb_irq) | ||
1272 | free_irq(socket->cb_irq, socket); | ||
1273 | else | ||
1274 | del_timer_sync(&socket->poll_timer); | ||
1267 | unmap: | 1275 | unmap: |
1268 | iounmap(socket->base); | 1276 | iounmap(socket->base); |
1277 | yenta_free_resources(socket); | ||
1269 | release: | 1278 | release: |
1270 | pci_release_regions(dev); | 1279 | pci_release_regions(dev); |
1271 | disable: | 1280 | disable: |
1272 | pci_disable_device(dev); | 1281 | pci_disable_device(dev); |
1273 | free: | 1282 | free: |
1283 | pci_set_drvdata(dev, NULL); | ||
1274 | kfree(socket); | 1284 | kfree(socket); |
1275 | out: | ||
1276 | return ret; | 1285 | return ret; |
1277 | } | 1286 | } |
1278 | 1287 | ||