[PATCH] staging: axis-fifo: add error handling of class_create()

2018-09-28 Thread Alexey Khoroshilov
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()

2014-12-19 Thread Alexey Khoroshilov
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()

2014-12-26 Thread Alexey Khoroshilov
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

2013-12-20 Thread Alexey Khoroshilov
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()

2013-12-27 Thread Alexey Khoroshilov
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()

2014-01-10 Thread Alexey Khoroshilov
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()

2014-02-05 Thread Alexey Khoroshilov
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

2014-02-23 Thread Alexey Khoroshilov
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()

2014-02-23 Thread Alexey Khoroshilov
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()

2014-02-23 Thread Alexey Khoroshilov
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

2014-03-02 Thread Alexey Khoroshilov
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()

2014-03-02 Thread Alexey Khoroshilov
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()

2014-03-02 Thread Alexey Khoroshilov
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

2014-03-08 Thread Alexey Khoroshilov
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()

2014-03-08 Thread Alexey Khoroshilov
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()

2017-05-26 Thread Alexey Khoroshilov
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

2017-02-23 Thread Alexey Khoroshilov
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()

2015-10-30 Thread Alexey Khoroshilov
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

2015-11-14 Thread Alexey Khoroshilov
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()

2015-12-04 Thread Alexey Khoroshilov
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()

2015-03-13 Thread Alexey Khoroshilov
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()

2015-03-20 Thread Alexey Khoroshilov
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

2013-10-08 Thread Alexey Khoroshilov
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

2013-10-08 Thread Alexey Khoroshilov
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()

2013-11-15 Thread Alexey Khoroshilov
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()

2015-12-20 Thread Alexey Khoroshilov
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()

2015-12-22 Thread Alexey Khoroshilov
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()

2014-07-10 Thread Alexey Khoroshilov
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

2014-06-10 Thread Alexey Khoroshilov
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

2015-10-09 Thread Alexey Khoroshilov
_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

2015-10-17 Thread Alexey Khoroshilov
_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