Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: usbtest: 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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Sebastian Andrzej Siewior and committed by
Greg Kroah-Hartman
6f3fde68 399111aa

+6 -4
+6 -4
drivers/usb/misc/usbtest.c
··· 1082 1082 struct usb_ctrlrequest *reqp; 1083 1083 struct subcase *subcase; 1084 1084 int status = urb->status; 1085 + unsigned long flags; 1085 1086 1086 1087 reqp = (struct usb_ctrlrequest *)urb->setup_packet; 1087 1088 subcase = container_of(reqp, struct subcase, setup); 1088 1089 1089 - spin_lock(&ctx->lock); 1090 + spin_lock_irqsave(&ctx->lock, flags); 1090 1091 ctx->count--; 1091 1092 ctx->pending--; 1092 1093 ··· 1186 1185 /* signal completion when nothing's queued */ 1187 1186 if (ctx->pending == 0) 1188 1187 complete(&ctx->complete); 1189 - spin_unlock(&ctx->lock); 1188 + spin_unlock_irqrestore(&ctx->lock, flags); 1190 1189 } 1191 1190 1192 1191 static int ··· 1918 1917 static void complicated_callback(struct urb *urb) 1919 1918 { 1920 1919 struct transfer_context *ctx = urb->context; 1920 + unsigned long flags; 1921 1921 1922 - spin_lock(&ctx->lock); 1922 + spin_lock_irqsave(&ctx->lock, flags); 1923 1923 ctx->count--; 1924 1924 1925 1925 ctx->packet_count += urb->number_of_packets; ··· 1960 1958 complete(&ctx->done); 1961 1959 } 1962 1960 done: 1963 - spin_unlock(&ctx->lock); 1961 + spin_unlock_irqrestore(&ctx->lock, flags); 1964 1962 } 1965 1963 1966 1964 static struct urb *iso_alloc_urb(