aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
authorMaximilain Schneider <max@schneidersoft.net>2016-02-22 20:17:28 -0500
committerMarc Kleine-Budde <mkl@pengutronix.de>2016-02-26 02:36:33 -0500
commite9a2d81b1761093386a0bb8a4f51642ac785ef63 (patch)
treefc98a26a18092acc4d2086fe0116accd10aa85a5 /drivers/net/can
parent4c0b6eaf373a5323f03a3a20c42fc435715b073d (diff)
can: gs_usb: fixed disconnect bug by removing erroneous use of kfree()
gs_destroy_candev() erroneously calls kfree() on a struct gs_can *, which is allocated through alloc_candev() and should instead be freed using free_candev() alone. The inappropriate use of kfree() causes the kernel to hang when gs_destroy_candev() is called. Only the struct gs_usb * which is allocated through kzalloc() should be freed using kfree() when the device is disconnected. Signed-off-by: Maximilian Schneider <max@schneidersoft.net> Cc: linux-stable <stable@vger.kernel.org> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can')
-rw-r--r--drivers/net/can/usb/gs_usb.c24
1 files changed, 11 insertions, 13 deletions
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 5eee62badf45..cbc99d5649af 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -826,9 +826,8 @@ static struct gs_can *gs_make_candev(unsigned int channel, struct usb_interface
826static void gs_destroy_candev(struct gs_can *dev) 826static void gs_destroy_candev(struct gs_can *dev)
827{ 827{
828 unregister_candev(dev->netdev); 828 unregister_candev(dev->netdev);
829 free_candev(dev->netdev);
830 usb_kill_anchored_urbs(&dev->tx_submitted); 829 usb_kill_anchored_urbs(&dev->tx_submitted);
831 kfree(dev); 830 free_candev(dev->netdev);
832} 831}
833 832
834static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) 833static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -913,12 +912,15 @@ static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *
913 for (i = 0; i < icount; i++) { 912 for (i = 0; i < icount; i++) {
914 dev->canch[i] = gs_make_candev(i, intf); 913 dev->canch[i] = gs_make_candev(i, intf);
915 if (IS_ERR_OR_NULL(dev->canch[i])) { 914 if (IS_ERR_OR_NULL(dev->canch[i])) {
915 /* save error code to return later */
916 rc = PTR_ERR(dev->canch[i]);
917
916 /* on failure destroy previously created candevs */ 918 /* on failure destroy previously created candevs */
917 icount = i; 919 icount = i;
918 for (i = 0; i < icount; i++) { 920 for (i = 0; i < icount; i++)
919 gs_destroy_candev(dev->canch[i]); 921 gs_destroy_candev(dev->canch[i]);
920 dev->canch[i] = NULL; 922
921 } 923 usb_kill_anchored_urbs(&dev->rx_submitted);
922 kfree(dev); 924 kfree(dev);
923 return rc; 925 return rc;
924 } 926 }
@@ -939,16 +941,12 @@ static void gs_usb_disconnect(struct usb_interface *intf)
939 return; 941 return;
940 } 942 }
941 943
942 for (i = 0; i < GS_MAX_INTF; i++) { 944 for (i = 0; i < GS_MAX_INTF; i++)
943 struct gs_can *can = dev->canch[i]; 945 if (dev->canch[i])
944 946 gs_destroy_candev(dev->canch[i]);
945 if (!can)
946 continue;
947
948 gs_destroy_candev(can);
949 }
950 947
951 usb_kill_anchored_urbs(&dev->rx_submitted); 948 usb_kill_anchored_urbs(&dev->rx_submitted);
949 kfree(dev);
952} 950}
953 951
954static const struct usb_device_id gs_usb_table[] = { 952static const struct usb_device_id gs_usb_table[] = {