[PATCH] staging: axis-fifo: add error handling of class_create()
Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/axis-fifo/axis-fifo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c index abeee0ecc122..63c8efd1b8db 100644 --- a/drivers/staging/axis-fifo/axis-fifo.c +++ b/drivers/staging/axis-fifo/axis-fifo.c @@ -1089,6 +1089,8 @@ static int __init axis_fifo_init(void) pr_info("axis-fifo driver loaded with parameters read_timeout = %i, write_timeout = %i\n", read_timeout, write_timeout); axis_fifo_driver_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(axis_fifo_driver_class)) + return PTR_ERR(axis_fifo_driver_class); return platform_driver_register(&axis_fifo_driver); } -- 2.7.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: dgnc: implement proper error handling in dgnc_start()
dgnc_start() ignores errors in class_create() and device_create() and it does not deallocate resources if dgnc_tty_preinit() fails. The patch implements proper error handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/dgnc/dgnc_driver.c | 28 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index ba98ff348112..f610ae1f3a9f 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -238,6 +238,7 @@ static int dgnc_start(void) { int rc = 0; unsigned long flags; + struct device *dev; /* make sure that the globals are init'd before we do anything else */ dgnc_init_globals(); @@ -257,9 +258,20 @@ static int dgnc_start(void) dgnc_Major = rc; dgnc_class = class_create(THIS_MODULE, "dgnc_mgmt"); - device_create(dgnc_class, NULL, - MKDEV(dgnc_Major, 0), - NULL, "dgnc_mgmt"); + if (IS_ERR(dgnc_class)) { + rc = PTR_ERR(dgnc_class); + pr_err(DRVSTR ": Can't create dgnc_mgmt class (%d)\n", rc); + goto failed_class; + } + + dev = device_create(dgnc_class, NULL, + MKDEV(dgnc_Major, 0), + NULL, "dgnc_mgmt"); + if (IS_ERR(dev)) { + rc = PTR_ERR(dev); + pr_err(DRVSTR ": Can't create device (%d)\n", rc); + goto failed_device; + } /* * Init any global tty stuff. @@ -268,7 +280,7 @@ static int dgnc_start(void) if (rc < 0) { pr_err(DRVSTR ": tty preinit - not enough memory (%d)\n", rc); - return rc; + goto failed_tty; } /* Start the poller */ @@ -282,6 +294,14 @@ static int dgnc_start(void) add_timer(&dgnc_poll_timer); + return 0; + +failed_tty: + device_destroy(dgnc_class, MKDEV(dgnc_Major, 0)); +failed_device: + class_destroy(dgnc_class); +failed_class: + unregister_chrdev(dgnc_Major, "dgnc"); return rc; } -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: lustre: do not ignore try_module_get() fail in obd_class_open()
obd_class_open() ignores error code of try_module_get(), while it can lead to race with module unload. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/lustre/lustre/obdclass/linux/linux-module.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index 66ceab20c743..bb4bc72ddac7 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -168,8 +168,7 @@ EXPORT_SYMBOL(obd_ioctl_popdata); /* opening /dev/obd */ static int obd_class_open(struct inode *inode, struct file *file) { - try_module_get(THIS_MODULE); - return 0; + return try_module_get(THIS_MODULE); } /* closing /dev/obd */ -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] [media] go7007-loader: fix usb_dev leak
There is usb_get_dev() in go7007_loader_probe(), but there is no usb_put_dev() anywhere. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/media/go7007/go7007-loader.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/go7007/go7007-loader.c b/drivers/staging/media/go7007/go7007-loader.c index f846ad5819dc..2b15952e4c18 100644 --- a/drivers/staging/media/go7007/go7007-loader.c +++ b/drivers/staging/media/go7007/go7007-loader.c @@ -60,7 +60,7 @@ static int go7007_loader_probe(struct usb_interface *interface, if (usbdev->descriptor.bNumConfigurations != 1) { dev_err(&interface->dev, "can't handle multiple config\n"); - return -ENODEV; + goto failed2; } vendor = le16_to_cpu(usbdev->descriptor.idVendor); @@ -109,6 +109,7 @@ static int go7007_loader_probe(struct usb_interface *interface, return 0; failed2: + usb_put_dev(usbdev); dev_err(&interface->dev, "probe failed\n"); return -ENODEV; } @@ -116,6 +117,7 @@ failed2: static void go7007_loader_disconnect(struct usb_interface *interface) { dev_info(&interface->dev, "disconnect\n"); + usb_put_dev(interface_to_usbdev(interface)); usb_set_intfdata(interface, NULL); } -- 1.8.3.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] [media] as102: fix leaks at failure paths in as102_usb_probe()
Failure handling is incomplete in as102_usb_probe(). The patch implements proper resource deallocations. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/media/as102/as102_usb_drv.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c index 9f275f020150..c1c6152d1ab4 100644 --- a/drivers/staging/media/as102/as102_usb_drv.c +++ b/drivers/staging/media/as102/as102_usb_drv.c @@ -419,15 +419,22 @@ static int as102_usb_probe(struct usb_interface *intf, /* request buffer allocation for streaming */ ret = as102_alloc_usb_stream_buffer(as102_dev); if (ret != 0) - goto failed; + goto failed_stream; /* register dvb layer */ ret = as102_dvb_register(as102_dev); + if (ret != 0) + goto failed_dvb; LEAVE(); return ret; +failed_dvb: + as102_free_usb_stream_buffer(as102_dev); +failed_stream: + usb_deregister_dev(intf, &as102_usb_class_driver); failed: + usb_put_dev(as102_dev->bus_adap.usb_dev); usb_set_intfdata(intf, NULL); kfree(as102_dev); return ret; -- 1.8.3.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: wlan-ng: fix leaks on failure paths in prism2sta_probe_usb()
There are leaks of resources allocated by wlan_setup() and usb_dev refcnt on failure paths in prism2sta_probe_usb(). The patch adds appropriate deallocations and removes invalid code from hfa384x_corereset() failure handling. unregister_wlandev() is wrong because it is not registered yet. hfa384x_destroy() is just noop in init state. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/wlan-ng/prism2usb.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index b401974fb282..4739c14d8359 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -140,11 +140,9 @@ static int prism2sta_probe_usb(struct usb_interface *interface, prism2_reset_holdtime, prism2_reset_settletime, 0); if (result != 0) { - unregister_wlandev(wlandev); - hfa384x_destroy(hw); result = -EIO; dev_err(&interface->dev, "hfa384x_corereset() failed.\n"); - goto failed; + goto failed_reset; } } @@ -159,11 +157,15 @@ static int prism2sta_probe_usb(struct usb_interface *interface, if (register_wlandev(wlandev) != 0) { dev_err(&interface->dev, "register_wlandev() failed.\n"); result = -EIO; - goto failed; + goto failed_register; } goto done; +failed_register: + usb_put_dev(dev); +failed_reset: + wlan_unsetup(wlandev); failed: kfree(wlandev); kfree(hw); -- 1.8.3.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: gdm72xx: fix leaks at failure path in gdm_usb_probe()
Error handling code in gdm_usb_probe() misses to deallocate tx_ and rx_structs and to do usb_put_dev(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/gdm72xx/gdm_usb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/gdm72xx/gdm_usb.c b/drivers/staging/gdm72xx/gdm_usb.c index f8788bf0a7d3..cdeffe75496b 100644 --- a/drivers/staging/gdm72xx/gdm_usb.c +++ b/drivers/staging/gdm72xx/gdm_usb.c @@ -635,11 +635,14 @@ static int gdm_usb_probe(struct usb_interface *intf, #endif /* CONFIG_WIMAX_GDM72XX_USB_PM */ ret = register_wimax_device(phy_dev, &intf->dev); + if (ret) + release_usb(udev); out: if (ret) { kfree(phy_dev); kfree(udev); + usb_put_dev(usbdev); } else { usb_set_intfdata(intf, phy_dev); } -- 1.8.3.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/3] staging: dgap: remove unneeded status variables
dgap_driver_start and dgap_Major_Control_Registered are used to keep status of initialization of the driver as a whole and its "Major Control". But the code that checks them is executed once on module init/unload. That makes no sense in these variables as far as their values are predictable at any time. Signed-off-by: Alexey Khoroshilov --- drivers/staging/dgap/dgap_driver.c | 105 - 1 file changed, 46 insertions(+), 59 deletions(-) diff --git a/drivers/staging/dgap/dgap_driver.c b/drivers/staging/dgap/dgap_driver.c index 089d017fc291..d7f1e999aaa4 100644 --- a/drivers/staging/dgap/dgap_driver.c +++ b/drivers/staging/dgap/dgap_driver.c @@ -117,9 +117,6 @@ int dgap_poll_tick = 20;/* Poll interval - 20 ms */ /* * Static vars. */ -static int dgap_Major_Control_Registered = FALSE; -static uintdgap_driver_start = FALSE; - static struct class * dgap_class; /* @@ -283,65 +280,57 @@ static int dgap_start(void) int rc = 0; unsigned long flags; - if (dgap_driver_start == FALSE) { - - dgap_driver_start = TRUE; + /* make sure that the globals are init'd before we do anything else */ + dgap_init_globals(); - /* make sure that the globals are init'd before we do anything else */ - dgap_init_globals(); + dgap_NumBoards = 0; - dgap_NumBoards = 0; + APR(("For the tools package or updated drivers please visit http://www.digi.com\n";)); - APR(("For the tools package or updated drivers please visit http://www.digi.com\n";)); - - /* -* Register our base character device into the kernel. -* This allows the download daemon to connect to the downld device -* before any of the boards are init'ed. -*/ - if (!dgap_Major_Control_Registered) { - /* -* Register management/dpa devices -*/ - rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &DgapBoardFops); - if (rc < 0) { - APR(("Can't register dgap driver device (%d)\n", rc)); - return (rc); - } + /* +* Register our base character device into the kernel. +* This allows the download daemon to connect to the downld device +* before any of the boards are init'ed. +*/ - dgap_class = class_create(THIS_MODULE, "dgap_mgmt"); - device_create(dgap_class, NULL, - MKDEV(DIGI_DGAP_MAJOR, 0), - NULL, "dgap_mgmt"); - device_create(dgap_class, NULL, - MKDEV(DIGI_DGAP_MAJOR, 1), - NULL, "dgap_downld"); - dgap_Major_Control_Registered = TRUE; - } + /* +* Register management/dpa devices +*/ + rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &DgapBoardFops); + if (rc < 0) { + APR(("Can't register dgap driver device (%d)\n", rc)); + return (rc); + } - /* -* Init any global tty stuff. -*/ - rc = dgap_tty_preinit(); + dgap_class = class_create(THIS_MODULE, "dgap_mgmt"); + device_create(dgap_class, NULL, + MKDEV(DIGI_DGAP_MAJOR, 0), + NULL, "dgap_mgmt"); + device_create(dgap_class, NULL, + MKDEV(DIGI_DGAP_MAJOR, 1), + NULL, "dgap_downld"); - if (rc < 0) { - APR(("tty preinit - not enough memory (%d)\n", rc)); - return(rc); - } + /* +* Init any global tty stuff. +*/ + rc = dgap_tty_preinit(); + if (rc < 0) { + APR(("tty preinit - not enough memory (%d)\n", rc)); + return(rc); + } - /* Start the poller */ - DGAP_LOCK(dgap_poll_lock, flags); - init_timer(&dgap_poll_timer); - dgap_poll_timer.function = dgap_poll_handler; - dgap_poll_timer.data = 0; - dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick); - dgap_poll_timer.expires = dgap_poll_time; - DGAP_UNLOCK(dgap_poll_lock, flags); + /* Start the poller */ + DGAP_LOCK(dgap_poll_lock, flags); + init_timer(&dgap_poll_timer); + dgap_poll_timer.function = dgap_poll_handler; + dgap_poll_timer.data = 0; +
[PATCH 2/3] staging: dgap: implement proper error handling in dgap_start()
dgap_start() ignored errors in class_create() and device_create(). The patch implements proper error handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/dgap/dgap_driver.c | 42 +++--- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/drivers/staging/dgap/dgap_driver.c b/drivers/staging/dgap/dgap_driver.c index d7f1e999aaa4..136c879b560c 100644 --- a/drivers/staging/dgap/dgap_driver.c +++ b/drivers/staging/dgap/dgap_driver.c @@ -279,6 +279,7 @@ static int dgap_start(void) { int rc = 0; unsigned long flags; + struct device *device; /* make sure that the globals are init'd before we do anything else */ dgap_init_globals(); @@ -303,12 +304,29 @@ static int dgap_start(void) } dgap_class = class_create(THIS_MODULE, "dgap_mgmt"); - device_create(dgap_class, NULL, - MKDEV(DIGI_DGAP_MAJOR, 0), - NULL, "dgap_mgmt"); - device_create(dgap_class, NULL, - MKDEV(DIGI_DGAP_MAJOR, 1), - NULL, "dgap_downld"); + if (IS_ERR(dgap_class)) { + rc = PTR_ERR(dgap_class); + APR(("Can't create dgap_mgmt class (%d)\n", rc)); + goto failed_class; + } + + device = device_create(dgap_class, NULL, + MKDEV(DIGI_DGAP_MAJOR, 0), + NULL, "dgap_mgmt"); + if (IS_ERR(device)) { + rc = PTR_ERR(device); + APR(("Can't create device (%d)\n", rc)); + goto failed_device0; + } + + device = device_create(dgap_class, NULL, + MKDEV(DIGI_DGAP_MAJOR, 1), + NULL, "dgap_downld"); + if (IS_ERR(device)) { + rc = PTR_ERR(device); + APR(("Can't create device (%d)\n", rc)); + goto failed_device1; + } /* * Init any global tty stuff. @@ -316,7 +334,7 @@ static int dgap_start(void) rc = dgap_tty_preinit(); if (rc < 0) { APR(("tty preinit - not enough memory (%d)\n", rc)); - return(rc); + goto failed_tty; } /* Start the poller */ @@ -333,6 +351,16 @@ static int dgap_start(void) dgap_driver_state = DRIVER_NEED_CONFIG_LOAD; return (rc); + +failed_tty: + device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 1)); +failed_device1: + device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0)); +failed_device0: + class_destroy(dgap_class); +failed_class: + unregister_chrdev(DIGI_DGAP_MAJOR, "dgap"); + return (rc); } -- 1.8.3.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 3/3] staging: dgap: fix error handling in dgap_init_module()
No need to call pci_unregister_driver() if pci_register_driver() failed. Signed-off-by: Alexey Khoroshilov --- drivers/staging/dgap/dgap_driver.c | 12 ++-- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/staging/dgap/dgap_driver.c b/drivers/staging/dgap/dgap_driver.c index 136c879b560c..cc6933db6feb 100644 --- a/drivers/staging/dgap/dgap_driver.c +++ b/drivers/staging/dgap/dgap_driver.c @@ -254,18 +254,10 @@ int dgap_init_module(void) /* * If something went wrong in the scan, bail out of driver. */ - if (rc < 0) { - /* Only unregister the pci driver if it was actually registered. */ - if (dgap_NumBoards) - pci_unregister_driver(&dgap_driver); - else - printk("WARNING: dgap driver load failed. No DGAP boards found.\n"); - + if (rc < 0) dgap_cleanup_module(); - } - else { + else dgap_create_driver_sysfiles(&dgap_driver); - } DPR_INIT(("Finished init_module. Returning %d\n", rc)); return (rc); -- 1.8.3.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/3] staging: dgap: remove unneeded status variables
dgap_driver_start and dgap_Major_Control_Registered are used to keep status of initialization of the driver as a whole and its "Major Control". But the code that checks them is executed once on module init/unload. That makes no sense in these variables as far as their values are predictable at any time. Signed-off-by: Alexey Khoroshilov --- drivers/staging/dgap/dgap.c | 97 - 1 file changed, 42 insertions(+), 55 deletions(-) diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index cbce457..5271856 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -254,9 +254,6 @@ static int dgap_poll_tick = 20; /* Poll interval - 20 ms */ /* * Static vars. */ -static int dgap_Major_Control_Registered = FALSE; -static uint dgap_driver_start = FALSE; - static struct class *dgap_class; static struct board_t *dgap_BoardsByMajor[256]; @@ -561,61 +558,54 @@ static int dgap_start(void) int rc = 0; unsigned long flags; - if (dgap_driver_start == FALSE) { + /* +* make sure that the globals are +* init'd before we do anything else +*/ + dgap_init_globals(); - dgap_driver_start = TRUE; + dgap_NumBoards = 0; - /* -* make sure that the globals are -* init'd before we do anything else -*/ - dgap_init_globals(); + pr_info("For the tools package please visit http://www.digi.com\n";); - dgap_NumBoards = 0; + /* +* Register our base character device into the kernel. +* This allows the download daemon to connect to the downld device +* before any of the boards are init'ed. +*/ - pr_info("For the tools package please visit http://www.digi.com\n";); + /* +* Register management/dpa devices +*/ + rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &DgapBoardFops); + if (rc < 0) + return rc; - /* -* Register our base character device into the kernel. -* This allows the download daemon to connect to the downld device -* before any of the boards are init'ed. -*/ - if (!dgap_Major_Control_Registered) { - /* -* Register management/dpa devices -*/ - rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &DgapBoardFops); - if (rc < 0) - return rc; - - dgap_class = class_create(THIS_MODULE, "dgap_mgmt"); - device_create(dgap_class, NULL, - MKDEV(DIGI_DGAP_MAJOR, 0), - NULL, "dgap_mgmt"); - dgap_Major_Control_Registered = TRUE; - } + dgap_class = class_create(THIS_MODULE, "dgap_mgmt"); + device_create(dgap_class, NULL, + MKDEV(DIGI_DGAP_MAJOR, 0), + NULL, "dgap_mgmt"); - /* -* Init any global tty stuff. -*/ - rc = dgap_tty_preinit(); + /* +* Init any global tty stuff. +*/ + rc = dgap_tty_preinit(); - if (rc < 0) - return rc; + if (rc < 0) + return rc; - /* Start the poller */ - DGAP_LOCK(dgap_poll_lock, flags); - init_timer(&dgap_poll_timer); - dgap_poll_timer.function = dgap_poll_handler; - dgap_poll_timer.data = 0; - dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick); - dgap_poll_timer.expires = dgap_poll_time; - DGAP_UNLOCK(dgap_poll_lock, flags); + /* Start the poller */ + DGAP_LOCK(dgap_poll_lock, flags); + init_timer(&dgap_poll_timer); + dgap_poll_timer.function = dgap_poll_handler; + dgap_poll_timer.data = 0; + dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick); + dgap_poll_timer.expires = dgap_poll_time; + DGAP_UNLOCK(dgap_poll_lock, flags); - add_timer(&dgap_poll_timer); + add_timer(&dgap_poll_timer); - dgap_driver_state = DRIVER_NEED_CONFIG_LOAD; - } + dgap_driver_state = DRIVER_NEED_CONFIG_LOAD; return rc; } @@ -677,13 +667,10 @@ void dgap_cleanup_module(void) dgap_remove_driver_sysfiles(&dgap_driver); - - if (dgap_Major_Control_Registered) { - device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0)); - device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 1)); - cla
[PATCH 3/3] staging: dgap: fix error handling in dgap_init_module()
No need to call pci_unregister_driver() if pci_register_driver() failed. Signed-off-by: Alexey Khoroshilov --- drivers/staging/dgap/dgap.c | 13 - 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index b4157d7..510e8b3 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -535,18 +535,13 @@ int dgap_init_module(void) * If something went wrong in the scan, bail out of driver. */ if (rc < 0) { - /* Only unregister the pci driver if it was actually registered. */ - if (dgap_NumBoards) - pci_unregister_driver(&dgap_driver); - else - printk("WARNING: dgap driver load failed. No DGAP boards found.\n"); - dgap_cleanup_module(); - } else { - dgap_create_driver_sysfiles(&dgap_driver); - dgap_driver_state = DRIVER_READY; + return rc; } + dgap_create_driver_sysfiles(&dgap_driver); + dgap_driver_state = DRIVER_READY; + return rc; } -- 1.8.3.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/3] staging: dgap: implement proper error handling in dgap_start()
dgap_start() ignored errors in class_create() and device_create(). The patch implements proper error handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/dgap/dgap.c | 22 -- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index 5271856..b4157d7 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -557,6 +557,7 @@ static int dgap_start(void) { int rc = 0; unsigned long flags; + struct device *device; /* * make sure that the globals are @@ -582,9 +583,18 @@ static int dgap_start(void) return rc; dgap_class = class_create(THIS_MODULE, "dgap_mgmt"); - device_create(dgap_class, NULL, + if (IS_ERR(dgap_class)) { + rc = PTR_ERR(dgap_class); + goto failed_class; + } + + device = device_create(dgap_class, NULL, MKDEV(DIGI_DGAP_MAJOR, 0), NULL, "dgap_mgmt"); + if (IS_ERR(device)) { + rc = PTR_ERR(device); + goto failed_device; + } /* * Init any global tty stuff. @@ -592,7 +602,7 @@ static int dgap_start(void) rc = dgap_tty_preinit(); if (rc < 0) - return rc; + goto failed_tty; /* Start the poller */ DGAP_LOCK(dgap_poll_lock, flags); @@ -608,6 +618,14 @@ static int dgap_start(void) dgap_driver_state = DRIVER_NEED_CONFIG_LOAD; return rc; + +failed_tty: + device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0)); +failed_device: + class_destroy(dgap_class); +failed_class: + unregister_chrdev(DIGI_DGAP_MAJOR, "dgap"); + return rc; } /* -- 1.8.3.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/2] staging: dgap: remove unneeded status variables
dgap_driver_start and dgap_Major_Control_Registered are used to keep status of initialization of the driver as a whole and its "Major Control". But the code that checks them is executed once on module init/unload. That makes no sense in these variables as far as their values are predictable at any time. Also "dgap_downld" device was removed, while device_destroy(MKDEV(DIGI_DGAP_MAJOR, 1)) is still in dgap_cleanup_module(). The patch removes it by the way. Signed-off-by: Alexey Khoroshilov --- drivers/staging/dgap/dgap.c | 81 ++--- 1 file changed, 33 insertions(+), 48 deletions(-) diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index d00283a..ad5afbc 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -254,9 +254,6 @@ static int dgap_poll_tick = 20; /* Poll interval - 20 ms */ /* * Static vars. */ -static int dgap_Major_Control_Registered = FALSE; -static uint dgap_driver_start = FALSE; - static struct class *dgap_class; static struct board_t *dgap_BoardsByMajor[256]; @@ -551,52 +548,44 @@ static int dgap_start(void) int rc = 0; unsigned long flags; - if (dgap_driver_start == FALSE) { + /* +* make sure that the globals are +* init'd before we do anything else +*/ + dgap_init_globals(); - dgap_driver_start = TRUE; + dgap_NumBoards = 0; - /* -* make sure that the globals are -* init'd before we do anything else -*/ - dgap_init_globals(); + pr_info("For the tools package please visit http://www.digi.com\n";); - dgap_NumBoards = 0; + /* +* Register our base character device into the kernel. +*/ - pr_info("For the tools package please visit http://www.digi.com\n";); + /* +* Register management/dpa devices +*/ + rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &DgapBoardFops); + if (rc < 0) + return rc; - /* -* Register our base character device into the kernel. -*/ - if (!dgap_Major_Control_Registered) { - /* -* Register management/dpa devices -*/ - rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", -&DgapBoardFops); - if (rc < 0) - return rc; - - dgap_class = class_create(THIS_MODULE, "dgap_mgmt"); - device_create(dgap_class, NULL, - MKDEV(DIGI_DGAP_MAJOR, 0), - NULL, "dgap_mgmt"); - dgap_Major_Control_Registered = TRUE; - } + dgap_class = class_create(THIS_MODULE, "dgap_mgmt"); + device_create(dgap_class, NULL, + MKDEV(DIGI_DGAP_MAJOR, 0), + NULL, "dgap_mgmt"); - /* Start the poller */ - DGAP_LOCK(dgap_poll_lock, flags); - init_timer(&dgap_poll_timer); - dgap_poll_timer.function = dgap_poll_handler; - dgap_poll_timer.data = 0; - dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick); - dgap_poll_timer.expires = dgap_poll_time; - DGAP_UNLOCK(dgap_poll_lock, flags); + /* Start the poller */ + DGAP_LOCK(dgap_poll_lock, flags); + init_timer(&dgap_poll_timer); + dgap_poll_timer.function = dgap_poll_handler; + dgap_poll_timer.data = 0; + dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick); + dgap_poll_timer.expires = dgap_poll_time; + DGAP_UNLOCK(dgap_poll_lock, flags); - add_timer(&dgap_poll_timer); + add_timer(&dgap_poll_timer); - dgap_driver_state = DRIVER_NEED_CONFIG_LOAD; - } + dgap_driver_state = DRIVER_NEED_CONFIG_LOAD; return rc; } @@ -658,13 +647,9 @@ static void dgap_cleanup_module(void) dgap_remove_driver_sysfiles(&dgap_driver); - - if (dgap_Major_Control_Registered) { - device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0)); - device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 1)); - class_destroy(dgap_class); - unregister_chrdev(DIGI_DGAP_MAJOR, "dgap"); - } + device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0)); + class_destroy(dgap_class); + unregister_chrdev(DIGI_DGAP_MAJOR, "dgap"); kfree(dgap_config_buf); -- 1.8.3.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/2] staging: dgap: implement proper error handling in dgap_start()
dgap_start() ignored errors in class_create() and device_create(). The patch implements proper error handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/dgap/dgap.c | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index ad5afbc..bfafe7e 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -547,6 +547,7 @@ static int dgap_start(void) { int rc = 0; unsigned long flags; + struct device *device; /* * make sure that the globals are @@ -570,9 +571,18 @@ static int dgap_start(void) return rc; dgap_class = class_create(THIS_MODULE, "dgap_mgmt"); - device_create(dgap_class, NULL, + if (IS_ERR(dgap_class)) { + rc = PTR_ERR(dgap_class); + goto failed_class; + } + + device = device_create(dgap_class, NULL, MKDEV(DIGI_DGAP_MAJOR, 0), NULL, "dgap_mgmt"); + if (IS_ERR(device)) { + rc = PTR_ERR(device); + goto failed_device; + } /* Start the poller */ DGAP_LOCK(dgap_poll_lock, flags); @@ -588,6 +598,12 @@ static int dgap_start(void) dgap_driver_state = DRIVER_NEED_CONFIG_LOAD; return rc; + +failed_device: + class_destroy(dgap_class); +failed_class: + unregister_chrdev(DIGI_DGAP_MAJOR, "dgap"); + return rc; } /* -- 1.8.3.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: iio: ad7152: Fix deadlock in ad7152_write_raw_samp_freq()
ad7152_write_raw_samp_freq() is called by ad7152_write_raw() with chip->state_lock held. So, there is unavoidable deadlock when ad7152_write_raw_samp_freq() locks the mutex itself. The patch removes unneeded locking. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/iio/cdc/ad7152.c | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c index dc6ecd824365..ff10d1f0a7e4 100644 --- a/drivers/staging/iio/cdc/ad7152.c +++ b/drivers/staging/iio/cdc/ad7152.c @@ -231,16 +231,12 @@ static int ad7152_write_raw_samp_freq(struct device *dev, int val) if (i >= ARRAY_SIZE(ad7152_filter_rate_table)) i = ARRAY_SIZE(ad7152_filter_rate_table) - 1; - mutex_lock(&chip->state_lock); ret = i2c_smbus_write_byte_data(chip->client, AD7152_REG_CFG2, AD7152_CFG2_OSR(i)); - if (ret < 0) { - mutex_unlock(&chip->state_lock); + if (ret < 0) return ret; - } chip->filter_rate_setup = i; - mutex_unlock(&chip->state_lock); return ret; } -- 2.7.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[media] s5p-cec: strange clk enabling pattern
The s5p-cec driver has a few places that touch hdmicec clk: static int s5p_cec_probe(struct platform_device *pdev) { ... cec->clk = devm_clk_get(dev, "hdmicec"); if (IS_ERR(cec->clk)) return PTR_ERR(cec->clk); ... } static int __maybe_unused s5p_cec_runtime_suspend(struct device *dev) { struct s5p_cec_dev *cec = dev_get_drvdata(dev); clk_disable_unprepare(cec->clk); return 0; } static int __maybe_unused s5p_cec_runtime_resume(struct device *dev) { struct s5p_cec_dev *cec = dev_get_drvdata(dev); int ret; ret = clk_prepare_enable(cec->clk); if (ret < 0) return ret; return 0; } Is it ok to enable/disable clock in rusume/suspend only? Or have I missed anything? -- Thank you, Alexey Khoroshilov Linux Verification Center, ISPRAS web: http://linuxtesting.org ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[BUG] IB/hfi1: might sleep under spinlock in hfi1_ioctl()
Hello, hfi1_ioctl() contains many calls to might sleep functions with dd->hfi1_snoop.snoop_lock spinlock held (for example, access_ok, copy_from_user, kzalloc(GFP_KERNEL), etc.). Should dd->hfi1_snoop.snoop_lock be acquired just before updating state? Found by Linux Driver Verification project (linuxtesting.org). -- Alexey Khoroshilov Linux Verification Center, ISPRAS web: http://linuxtesting.org ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] [media] lirc_imon: do not leave imon_probe() with mutex held
Commit af8a819a2513 ("[media] lirc_imon: simplify error handling code") lost mutex_unlock(&context->ctx_lock), so imon_probe() exits with the context->ctx_lock mutex acquired. The patch adds mutex_unlock(&context->ctx_lock) back. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Fixes: af8a819a2513 ("[media] lirc_imon: simplify error handling code") --- drivers/staging/media/lirc/lirc_imon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index 534b8103ae80..ff1926ca1f96 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -885,12 +885,14 @@ static int imon_probe(struct usb_interface *interface, vendor, product, ifnum, usbdev->bus->busnum, usbdev->devnum); /* Everything went fine. Just unlock and return retval (with is 0) */ + mutex_unlock(&context->ctx_lock); goto driver_unlock; unregister_lirc: lirc_unregister_driver(driver->minor); free_tx_urb: + mutex_unlock(&context->ctx_lock); usb_free_urb(tx_urb); free_rx_urb: -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: wilc1000: fix double mutex_unlock on failure path in wilc_wlan_cleanup()
If hif_read_reg() or hif_write_reg() fail in wilc_wlan_cleanup(), it calls release_bus() and continues execution. But it leads to double release_bus() call that means double unlock of g_linux_wlan->hif_cs mutex. The patch adds return in case of failure. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/wilc1000/wilc_wlan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index c02665747705..cd7f52a51173 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1703,12 +1703,14 @@ void wilc_wlan_cleanup(struct net_device *dev) if (!ret) { PRINT_ER("Error while reading reg\n"); release_bus(RELEASE_ALLOW_SLEEP); + return; } PRINT_ER("Writing ABORT reg\n"); ret = p->hif_func.hif_write_reg(WILC_GP_REG_0, (reg | ABORT_INT)); if (!ret) { PRINT_ER("Error while writing reg\n"); release_bus(RELEASE_ALLOW_SLEEP); + return; } release_bus(RELEASE_ALLOW_SLEEP); /** -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: vt6656: don't return zero on failure path in vt6656_probe()
If ieee80211_alloc_hw() fails in vt6656_probe(), it breaks off initialization, but returns zero. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/vt6656/main_usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 71adc1f61838..ab3ab84cb0a7 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -963,6 +963,7 @@ vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id) hw = ieee80211_alloc_hw(sizeof(struct vnt_private), &vnt_mac_ops); if (!hw) { dev_err(&udev->dev, "could not register ieee80211_hw\n"); + rc = -ENOMEM; goto err_nomem; } -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: ozwpan: implement error handling in ozwpan_init()
Errors are correctly handled in oz_cdev_register() and oz_protocol_init(), but then they are ignored in ozwpan_init(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/ozwpan/ozmain.c | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/staging/ozwpan/ozmain.c b/drivers/staging/ozwpan/ozmain.c index 7d6ef4cadf1a..74ef34815b98 100644 --- a/drivers/staging/ozwpan/ozmain.c +++ b/drivers/staging/ozwpan/ozmain.c @@ -34,11 +34,21 @@ MODULE_PARM_DESC(g_net_dev, "The device(s) to bind to; " */ static int __init ozwpan_init(void) { - oz_cdev_register(); - oz_protocol_init(g_net_dev); + int err; + + err = oz_cdev_register(); + if (err) + return err; + err = oz_protocol_init(g_net_dev); + if (err) + goto err_protocol; oz_app_enable(OZ_APPID_USB, 1); oz_apps_init(); return 0; + +err_protocol: + oz_cdev_deregister(); + return err; } /* -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/2] staging: gdm7240: alloc_mux_rx() does not need GFP_ATOMIC
As far as alloc_mux_rx() is called from probe() only there is no need in GFP_ATOMIC here. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/gdm724x/gdm_mux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c index 5b1ef40..5221cf9 100644 --- a/drivers/staging/gdm724x/gdm_mux.c +++ b/drivers/staging/gdm724x/gdm_mux.c @@ -96,12 +96,12 @@ static struct mux_rx *alloc_mux_rx(void) { struct mux_rx *r = NULL; - r = kzalloc(sizeof(struct mux_rx), GFP_ATOMIC); + r = kzalloc(sizeof(struct mux_rx), GFP_KERNEL); if (!r) return NULL; - r->urb = usb_alloc_urb(0, GFP_ATOMIC); - r->buf = kmalloc(MUX_RX_MAX_SIZE, GFP_ATOMIC); + r->urb = usb_alloc_urb(0, GFP_KERNEL); + r->buf = kmalloc(MUX_RX_MAX_SIZE, GFP_KERNEL); if (!r->urb || !r->buf) { usb_free_urb(r->urb); kfree(r->buf); -- 1.8.1.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/2] staging: gdm7240: fix memory leak on failure path
init_usb() may fail after some of mux_rxes already allocated. So we need to release them on the failure path. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/gdm724x/gdm_mux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c index 5221cf9..69813c7 100644 --- a/drivers/staging/gdm724x/gdm_mux.c +++ b/drivers/staging/gdm724x/gdm_mux.c @@ -541,7 +541,7 @@ static int gdm_mux_probe(struct usb_interface *intf, const struct usb_device_id ret = init_usb(mux_dev); if (ret) - goto err_free_tty; + goto err_free_usb; tty_dev->priv_dev = (void *)mux_dev; tty_dev->send_func = gdm_mux_send; @@ -565,8 +565,8 @@ static int gdm_mux_probe(struct usb_interface *intf, const struct usb_device_id err_unregister_tty: unregister_lte_tty_device(tty_dev); +err_free_usb: release_usb(mux_dev); -err_free_tty: kfree(tty_dev); err_free_mux: kfree(mux_dev); -- 1.8.1.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: gdm724x: fix leak at failure path in gdm_usb_probe()
Error handling code in gdm_usb_probe() deallocates all resources, but calls usb_get_dev(usbdev) and returns error code after that. The patch fixes it and, by the way, several other issues: - no need to use GFP_ATOMIC in probe(); - return -ENODEV instead of -1; - kmalloc+memset -> kzalloc Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/gdm724x/gdm_usb.c | 40 +-- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c index 781134af69d1..33458a583142 100644 --- a/drivers/staging/gdm724x/gdm_usb.c +++ b/drivers/staging/gdm724x/gdm_usb.c @@ -830,24 +830,19 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id if (bInterfaceNumber > NETWORK_INTERFACE) { pr_info("not a network device\n"); - return -1; + return -ENODEV; } - phy_dev = kmalloc(sizeof(struct phy_dev), GFP_ATOMIC); - if (!phy_dev) { - ret = -ENOMEM; - goto out; - } + phy_dev = kzalloc(sizeof(struct phy_dev), GFP_KERNEL); + if (!phy_dev) + return -ENOMEM; - udev = kmalloc(sizeof(struct lte_udev), GFP_ATOMIC); + udev = kzalloc(sizeof(struct lte_udev), GFP_KERNEL); if (!udev) { ret = -ENOMEM; - goto out; + goto err_udev; } - memset(phy_dev, 0, sizeof(struct phy_dev)); - memset(udev, 0, sizeof(struct lte_udev)); - phy_dev->priv_dev = (void *)udev; phy_dev->send_hci_func = gdm_usb_hci_send; phy_dev->send_sdu_func = gdm_usb_sdu_send; @@ -858,7 +853,7 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id ret = init_usb(udev); if (ret < 0) { pr_err("init_usb func failed\n"); - goto out; + goto err_init_usb; } udev->intf = intf; @@ -875,23 +870,22 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id ret = request_mac_address(udev); if (ret < 0) { pr_err("request Mac address failed\n"); - goto out; + goto err_mac_address; } start_rx_proc(phy_dev); -out: - - if (ret < 0) { - kfree(phy_dev); - if (udev) { - release_usb(udev); - kfree(udev); - } - } - usb_get_dev(usbdev); usb_set_intfdata(intf, phy_dev); + return 0; + +err_mac_address: + release_usb(udev); +err_init_usb: + kfree(udev); +err_udev: + kfree(phy_dev); + return ret; } -- 1.8.1.2 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: wilc1000: fix double mutex_unlock on failure path in wilc_wlan_cleanup()
If hif_read_reg() or hif_write_reg() fail in wilc_wlan_cleanup(), it calls release_bus() and continues execution. But it leads to double release_bus() call that means double unlock of g_linux_wlan->hif_cs mutex. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/wilc1000/wilc_wlan.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index a73e99f..4b7c8e9 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1459,15 +1459,16 @@ void wilc_wlan_cleanup(struct net_device *dev) ret = p->hif_func.hif_read_reg(wilc, WILC_GP_REG_0, ®); if (!ret) { PRINT_ER("Error while reading reg\n"); - release_bus(wilc, RELEASE_ALLOW_SLEEP); + goto _unlock; } PRINT_ER("Writing ABORT reg\n"); ret = p->hif_func.hif_write_reg(wilc, WILC_GP_REG_0, (reg | ABORT_INT)); if (!ret) { PRINT_ER("Error while writing reg\n"); - release_bus(wilc, RELEASE_ALLOW_SLEEP); + goto _unlock; } +_unlock: release_bus(wilc, RELEASE_ALLOW_SLEEP); p->hif_func.hif_deinit(NULL); } -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH v3] staging: wilc1000: fix double mutex_unlock on failure path in wilc_wlan_cleanup()
If hif_read_reg() or hif_write_reg() fail in wilc_wlan_cleanup(), it calls release_bus() and continues execution. But it leads to double release_bus() call that means double unlock of g_linux_wlan->hif_cs mutex. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/wilc1000/wilc_wlan.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 83af51b..b8c4a63 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1381,15 +1381,16 @@ void wilc_wlan_cleanup(struct net_device *dev) ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®); if (!ret) { PRINT_ER("Error while reading reg\n"); - release_bus(wilc, RELEASE_ALLOW_SLEEP); + goto unlock; } PRINT_ER("Writing ABORT reg\n"); ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, (reg | ABORT_INT)); if (!ret) { PRINT_ER("Error while writing reg\n"); - release_bus(wilc, RELEASE_ALLOW_SLEEP); + goto unlock; } +unlock: release_bus(wilc, RELEASE_ALLOW_SLEEP); wilc->hif_func->hif_deinit(NULL); } -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: gdm724x: fix leak at failure path in init_usb()
If an allocation in init_usb() failed, it returns without deallocation of already allocated resources. The patch fix it and replaces GFP_ATOMIC by GFP_KERNEL in alloc_tx_sdu_struct() and alloc_rx_struct() as long as they are called from probe only. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/gdm724x/gdm_usb.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c index ee6e40facca7..ea89d530ff3f 100644 --- a/drivers/staging/gdm724x/gdm_usb.c +++ b/drivers/staging/gdm724x/gdm_usb.c @@ -125,11 +125,11 @@ static struct usb_tx_sdu *alloc_tx_sdu_struct(void) { struct usb_tx_sdu *t_sdu; - t_sdu = kzalloc(sizeof(struct usb_tx_sdu), GFP_ATOMIC); + t_sdu = kzalloc(sizeof(struct usb_tx_sdu), GFP_KERNEL); if (!t_sdu) return NULL; - t_sdu->buf = kmalloc(SDU_BUF_SIZE, GFP_ATOMIC); + t_sdu->buf = kmalloc(SDU_BUF_SIZE, GFP_KERNEL); if (!t_sdu->buf) { kfree(t_sdu); return NULL; @@ -183,14 +183,14 @@ static struct usb_rx *alloc_rx_struct(void) struct usb_rx *r = NULL; int ret = 0; - r = kmalloc(sizeof(struct usb_rx), GFP_ATOMIC); + r = kmalloc(sizeof(struct usb_rx), GFP_KERNEL); if (!r) { ret = -ENOMEM; goto out; } - r->urb = usb_alloc_urb(0, GFP_ATOMIC); - r->buf = kmalloc(RX_BUF_SIZE, GFP_ATOMIC); + r->urb = usb_alloc_urb(0, GFP_KERNEL); + r->buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); if (!r->urb || !r->buf) { ret = -ENOMEM; goto out; @@ -366,6 +366,7 @@ static int init_usb(struct lte_udev *udev) INIT_DELAYED_WORK(&udev->work_rx, do_rx); return 0; fail: + release_usb(udev); return ret; } -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: line6: do not return 0 from probe if no initialization done
There is a strange "return 0" in line6_probe() before any initialization of the module is done. It can lead to NULL pointer dereference in other functions. The patch proposes to return -ENODEV in this case. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/line6/driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c index ef511c76a6e3..503b2d763595 100644 --- a/drivers/staging/line6/driver.c +++ b/drivers/staging/line6/driver.c @@ -663,7 +663,7 @@ static int line6_probe(struct usb_interface *interface, case LINE6_DEVID_POCKETPOD: switch (interface_number) { case 0: - return 0; /* this interface has no endpoints */ + return -ENODEV; /* this interface has no endpoints */ case 1: alternate = 0; break; -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: r8188eu: Add _enter_critical_mutex() error handling
_enter_critical_mutex() is a simple call to mutex_lock_interruptible(), but there is no error handling code for it. The patch removes wrapper _enter_critical_mutex() and adds error handling for mutex_lock_interruptible(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 5 +++-- drivers/staging/rtl8188eu/include/osdep_service.h | 9 - drivers/staging/rtl8188eu/os_dep/os_intfs.c | 3 ++- drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 5 - 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 935b48eef8b1..4e9312f0e902 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -271,7 +271,8 @@ static s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, if (padapter->bSurpriseRemoved || padapter->bDriverStopped) return -1; - _enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL); + if (!mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex)) + return _FAIL; pxmitpriv->ack_tx = true; pmgntframe->ack_report = 1; @@ -282,7 +283,7 @@ static s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, pxmitpriv->ack_tx = false; mutex_unlock(&pxmitpriv->ack_tx_mutex); -return ret; + return ret; } static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index cf9ca685eb77..96505a6dbe2c 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -67,15 +67,6 @@ static inline struct list_head *get_list_head(struct __queue *queue) return &(queue->queue); } -static inline int _enter_critical_mutex(struct mutex *pmutex, - unsigned long *pirqL) -{ - int ret; - - ret = mutex_lock_interruptible(pmutex); - return ret; -} - static inline int rtw_netif_queue_stopped(struct net_device *pnetdev) { return netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 0)) && diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 2361bce480c3..9a3425a7110d 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -1053,7 +1053,8 @@ static int netdev_open(struct net_device *pnetdev) int ret; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); - _enter_critical_mutex(&padapter->hw_init_mutex, NULL); + if (mutex_lock_interruptible(&padapter->hw_init_mutex)) + return -ERESTARTSYS; ret = _netdev_open(pnetdev); mutex_unlock(&padapter->hw_init_mutex); return ret; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index 7e599bc5b2d3..0fea338d7313 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -249,7 +249,10 @@ static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 i goto exit; } - _enter_critical_mutex(&dvobjpriv->usb_vendor_req_mutex, NULL); + if (mutex_lock_interruptible(&dvobjpriv->usb_vendor_req_mutex)) { + status = -ERESTARTSYS; + goto exit; + } /* Acquire IO memory for vendorreq */ pIo_buf = dvobjpriv->usb_vendor_req_buf; -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH v2] staging: r8188eu: Add _enter_critical_mutex() error handling
_enter_critical_mutex() is a simple call to mutex_lock_interruptible(), but there is no error handling code for it. The patch removes wrapper _enter_critical_mutex() and adds error handling for mutex_lock_interruptible(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 5 +++-- drivers/staging/rtl8188eu/include/osdep_service.h | 9 - drivers/staging/rtl8188eu/os_dep/os_intfs.c | 3 ++- drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 5 - 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 935b48eef8b1..4e9312f0e902 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -271,7 +271,8 @@ static s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, if (padapter->bSurpriseRemoved || padapter->bDriverStopped) return -1; - _enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL); + if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex)) + return _FAIL; pxmitpriv->ack_tx = true; pmgntframe->ack_report = 1; @@ -282,7 +283,7 @@ static s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, pxmitpriv->ack_tx = false; mutex_unlock(&pxmitpriv->ack_tx_mutex); -return ret; + return ret; } static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index cf9ca685eb77..96505a6dbe2c 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -67,15 +67,6 @@ static inline struct list_head *get_list_head(struct __queue *queue) return &(queue->queue); } -static inline int _enter_critical_mutex(struct mutex *pmutex, - unsigned long *pirqL) -{ - int ret; - - ret = mutex_lock_interruptible(pmutex); - return ret; -} - static inline int rtw_netif_queue_stopped(struct net_device *pnetdev) { return netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 0)) && diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 2361bce480c3..9a3425a7110d 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -1053,7 +1053,8 @@ static int netdev_open(struct net_device *pnetdev) int ret; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); - _enter_critical_mutex(&padapter->hw_init_mutex, NULL); + if (mutex_lock_interruptible(&padapter->hw_init_mutex)) + return -ERESTARTSYS; ret = _netdev_open(pnetdev); mutex_unlock(&padapter->hw_init_mutex); return ret; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index 7e599bc5b2d3..0fea338d7313 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -249,7 +249,10 @@ static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 i goto exit; } - _enter_critical_mutex(&dvobjpriv->usb_vendor_req_mutex, NULL); + if (mutex_lock_interruptible(&dvobjpriv->usb_vendor_req_mutex)) { + status = -ERESTARTSYS; + goto exit; + } /* Acquire IO memory for vendorreq */ pIo_buf = dvobjpriv->usb_vendor_req_buf; -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel