diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/usb/sipc_hsic.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/net/usb/sipc_hsic.c b/drivers/net/usb/sipc_hsic.c index 1809480cd5dd..e32acb07f1c0 100644 --- a/drivers/net/usb/sipc_hsic.c +++ b/drivers/net/usb/sipc_hsic.c @@ -32,6 +32,9 @@ struct sipc_usb_ep { struct sipc_link_callback *cb; struct usb_device *udev; struct usb_interface *data_intf; + + spinlock_t rx_lock; /* Protects disconnects */ + bool disconnected; }; #define linkops_to_ep(ops) container_of(ops, struct sipc_usb_ep, link_ops) @@ -73,8 +76,16 @@ static void sipc_rx_complete(struct urb *urb) static int sipc_start_rx(struct sipc_usb_ep *ep) { struct urb *urb; + unsigned long flags; int ret; + spin_lock_irqsave(&ep->rx_lock, flags); + + if (ep->disconnected) { + spin_unlock_irqrestore(&ep->rx_lock, flags); + return -ENODEV; + } + urb = ep->in_urb; urb->transfer_flags = 0; usb_fill_bulk_urb(urb, ep->udev, @@ -83,6 +94,8 @@ static int sipc_start_rx(struct sipc_usb_ep *ep) ep); ret = usb_submit_urb(urb, GFP_ATOMIC); + spin_unlock_irqrestore(&ep->rx_lock, flags); + if (ret) dev_err(&ep->udev->dev, "Failed to submit rx urb: %d\n", ret); @@ -259,6 +272,8 @@ static int sipc_probe(struct usb_interface *intf, } } + spin_lock_init(&ep->rx_lock); + sipc_start_rx(ep); return 0; @@ -273,6 +288,8 @@ static void sipc_disconnect(struct usb_interface *intf) struct sipc_usb_ep *ep = usb_get_intfdata(intf); int fmt; + ep->disconnected = true; + fmt = usb_to_sipc_format(ep->ep); if (fmt < 0) goto invalid_format; |