diff options
Diffstat (limited to 'drivers/bluetooth/bcm203x.c')
| -rw-r--r-- | drivers/bluetooth/bcm203x.c | 12 | 
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index 8b1b643a519..54952ab800b 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -24,6 +24,7 @@  #include <linux/module.h> +#include <linux/atomic.h>  #include <linux/kernel.h>  #include <linux/init.h>  #include <linux/slab.h> @@ -65,6 +66,7 @@ struct bcm203x_data {  	unsigned long		state;  	struct work_struct	work; +	atomic_t		shutdown;  	struct urb		*urb;  	unsigned char		*buffer; @@ -97,6 +99,7 @@ static void bcm203x_complete(struct urb *urb)  		data->state = BCM203X_SELECT_MEMORY; +		/* use workqueue to have a small delay */  		schedule_work(&data->work);  		break; @@ -155,7 +158,10 @@ static void bcm203x_work(struct work_struct *work)  	struct bcm203x_data *data =  		container_of(work, struct bcm203x_data, work); -	if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) +	if (atomic_read(&data->shutdown)) +		return; + +	if (usb_submit_urb(data->urb, GFP_KERNEL) < 0)  		BT_ERR("Can't submit URB");  } @@ -243,6 +249,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id  	usb_set_intfdata(intf, data); +	/* use workqueue to have a small delay */  	schedule_work(&data->work);  	return 0; @@ -254,6 +261,9 @@ static void bcm203x_disconnect(struct usb_interface *intf)  	BT_DBG("intf %p", intf); +	atomic_inc(&data->shutdown); +	cancel_work_sync(&data->work); +  	usb_kill_urb(data->urb);  	usb_set_intfdata(intf, NULL);  |