diff options
author | Takeshi Yoshimura <yos@sslab.ics.keio.ac.jp> | 2015-06-15 02:43:59 +0900 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2015-06-14 21:35:45 +0200 |
commit | d19319affb6c84ef45185588f63dc28f8ff95ea3 (patch) | |
tree | 6419375f21500c0125d8f9de33ecdf2d6ebbe17f /drivers/pcmcia/yenta_socket.c | |
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>
Diffstat (limited to 'drivers/pcmcia/yenta_socket.c')
-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) else del_timer_sync(&sock->poll_timer); - if (sock->base) - iounmap(sock->base); + iounmap(sock->base); yenta_free_resources(sock); pci_release_regions(dev); pci_disable_device(dev); pci_set_drvdata(dev, NULL); + kfree(sock); } @@ -1254,25 +1254,34 @@ static int yenta_probe(struct pci_dev *dev, const struct pci_device_id *id) /* Register it with the pcmcia layer.. */ ret = pcmcia_register_socket(&socket->socket); - if (ret == 0) { - /* Add the yenta register attributes */ - ret = device_create_file(&dev->dev, &dev_attr_yenta_registers); - if (ret == 0) - goto out; - - /* error path... */ - pcmcia_unregister_socket(&socket->socket); - } + if (ret) + goto free_irq; + + /* Add the yenta register attributes */ + ret = device_create_file(&dev->dev, &dev_attr_yenta_registers); + if (ret) + goto unregister_socket; + return ret; + + /* error path... */ + unregister_socket: + pcmcia_unregister_socket(&socket->socket); + free_irq: + if (socket->cb_irq) + free_irq(socket->cb_irq, socket); + else + del_timer_sync(&socket->poll_timer); unmap: iounmap(socket->base); + yenta_free_resources(socket); release: pci_release_regions(dev); disable: pci_disable_device(dev); free: + pci_set_drvdata(dev, NULL); kfree(socket); - out: return ret; } |