summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2018-06-24 18:08:35 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-06-28 06:36:07 -0400
commit579b9cca2bff170ac4c4487de6e8ebff7906b3a6 (patch)
treec9a7543b9a89e14fc130f3525e46ee3dda10966f
parent24b2068e26c6f24de05c81459553cbc6cf753708 (diff)
usb: cdc-wdm: use irqsave() in USB's complete callback
The USB completion callback does not disable interrupts while acquiring the lock. We want to remove the local_irq_disable() invocation from __usb_hcd_giveback_urb() and therefore it is required for the callback handler to disable the interrupts while acquiring the lock. The callback may be invoked either in IRQ or BH context depending on the USB host controller. Use the _irqsave() variant of the locking primitives. Cc: Oliver Neukum <oneukum@suse.com> Cc: "Bjørn Mork" <bjorn@mork.no> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/class/cdc-wdm.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 203bbd378858..bec581fb7c63 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -142,10 +142,12 @@ found:
142static void wdm_out_callback(struct urb *urb) 142static void wdm_out_callback(struct urb *urb)
143{ 143{
144 struct wdm_device *desc; 144 struct wdm_device *desc;
145 unsigned long flags;
146
145 desc = urb->context; 147 desc = urb->context;
146 spin_lock(&desc->iuspin); 148 spin_lock_irqsave(&desc->iuspin, flags);
147 desc->werr = urb->status; 149 desc->werr = urb->status;
148 spin_unlock(&desc->iuspin); 150 spin_unlock_irqrestore(&desc->iuspin, flags);
149 kfree(desc->outbuf); 151 kfree(desc->outbuf);
150 desc->outbuf = NULL; 152 desc->outbuf = NULL;
151 clear_bit(WDM_IN_USE, &desc->flags); 153 clear_bit(WDM_IN_USE, &desc->flags);
@@ -154,11 +156,12 @@ static void wdm_out_callback(struct urb *urb)
154 156
155static void wdm_in_callback(struct urb *urb) 157static void wdm_in_callback(struct urb *urb)
156{ 158{
159 unsigned long flags;
157 struct wdm_device *desc = urb->context; 160 struct wdm_device *desc = urb->context;
158 int status = urb->status; 161 int status = urb->status;
159 int length = urb->actual_length; 162 int length = urb->actual_length;
160 163
161 spin_lock(&desc->iuspin); 164 spin_lock_irqsave(&desc->iuspin, flags);
162 clear_bit(WDM_RESPONDING, &desc->flags); 165 clear_bit(WDM_RESPONDING, &desc->flags);
163 166
164 if (status) { 167 if (status) {
@@ -220,11 +223,12 @@ skip_error:
220 set_bit(WDM_READ, &desc->flags); 223 set_bit(WDM_READ, &desc->flags);
221 wake_up(&desc->wait); 224 wake_up(&desc->wait);
222 } 225 }
223 spin_unlock(&desc->iuspin); 226 spin_unlock_irqrestore(&desc->iuspin, flags);
224} 227}
225 228
226static void wdm_int_callback(struct urb *urb) 229static void wdm_int_callback(struct urb *urb)
227{ 230{
231 unsigned long flags;
228 int rv = 0; 232 int rv = 0;
229 int responding; 233 int responding;
230 int status = urb->status; 234 int status = urb->status;
@@ -284,7 +288,7 @@ static void wdm_int_callback(struct urb *urb)
284 goto exit; 288 goto exit;
285 } 289 }
286 290
287 spin_lock(&desc->iuspin); 291 spin_lock_irqsave(&desc->iuspin, flags);
288 responding = test_and_set_bit(WDM_RESPONDING, &desc->flags); 292 responding = test_and_set_bit(WDM_RESPONDING, &desc->flags);
289 if (!desc->resp_count++ && !responding 293 if (!desc->resp_count++ && !responding
290 && !test_bit(WDM_DISCONNECTING, &desc->flags) 294 && !test_bit(WDM_DISCONNECTING, &desc->flags)
@@ -292,7 +296,7 @@ static void wdm_int_callback(struct urb *urb)
292 rv = usb_submit_urb(desc->response, GFP_ATOMIC); 296 rv = usb_submit_urb(desc->response, GFP_ATOMIC);
293 dev_dbg(&desc->intf->dev, "submit response URB %d\n", rv); 297 dev_dbg(&desc->intf->dev, "submit response URB %d\n", rv);
294 } 298 }
295 spin_unlock(&desc->iuspin); 299 spin_unlock_irqrestore(&desc->iuspin, flags);
296 if (rv < 0) { 300 if (rv < 0) {
297 clear_bit(WDM_RESPONDING, &desc->flags); 301 clear_bit(WDM_RESPONDING, &desc->flags);
298 if (rv == -EPERM) 302 if (rv == -EPERM)