diff options
Diffstat (limited to 'drivers/usb/gadget/function/f_midi.c')
-rw-r--r-- | drivers/usb/gadget/function/f_midi.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 84c0ee5ebd1e..58fc199a18ec 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/device.h> | 25 | #include <linux/device.h> |
26 | #include <linux/kfifo.h> | 26 | #include <linux/kfifo.h> |
27 | #include <linux/spinlock.h> | ||
27 | 28 | ||
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
29 | #include <sound/initval.h> | 30 | #include <sound/initval.h> |
@@ -89,6 +90,7 @@ struct f_midi { | |||
89 | unsigned int buflen, qlen; | 90 | unsigned int buflen, qlen; |
90 | /* This fifo is used as a buffer ring for pre-allocated IN usb_requests */ | 91 | /* This fifo is used as a buffer ring for pre-allocated IN usb_requests */ |
91 | DECLARE_KFIFO_PTR(in_req_fifo, struct usb_request *); | 92 | DECLARE_KFIFO_PTR(in_req_fifo, struct usb_request *); |
93 | spinlock_t transmit_lock; | ||
92 | unsigned int in_last_port; | 94 | unsigned int in_last_port; |
93 | 95 | ||
94 | struct gmidi_in_port in_ports_array[/* in_ports */]; | 96 | struct gmidi_in_port in_ports_array[/* in_ports */]; |
@@ -358,7 +360,9 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | |||
358 | /* allocate a bunch of read buffers and queue them all at once. */ | 360 | /* allocate a bunch of read buffers and queue them all at once. */ |
359 | for (i = 0; i < midi->qlen && err == 0; i++) { | 361 | for (i = 0; i < midi->qlen && err == 0; i++) { |
360 | struct usb_request *req = | 362 | struct usb_request *req = |
361 | midi_alloc_ep_req(midi->out_ep, midi->buflen); | 363 | midi_alloc_ep_req(midi->out_ep, |
364 | max_t(unsigned, midi->buflen, | ||
365 | bulk_out_desc.wMaxPacketSize)); | ||
362 | if (req == NULL) | 366 | if (req == NULL) |
363 | return -ENOMEM; | 367 | return -ENOMEM; |
364 | 368 | ||
@@ -597,17 +601,24 @@ static void f_midi_transmit(struct f_midi *midi) | |||
597 | { | 601 | { |
598 | struct usb_ep *ep = midi->in_ep; | 602 | struct usb_ep *ep = midi->in_ep; |
599 | int ret; | 603 | int ret; |
604 | unsigned long flags; | ||
600 | 605 | ||
601 | /* We only care about USB requests if IN endpoint is enabled */ | 606 | /* We only care about USB requests if IN endpoint is enabled */ |
602 | if (!ep || !ep->enabled) | 607 | if (!ep || !ep->enabled) |
603 | goto drop_out; | 608 | goto drop_out; |
604 | 609 | ||
610 | spin_lock_irqsave(&midi->transmit_lock, flags); | ||
611 | |||
605 | do { | 612 | do { |
606 | ret = f_midi_do_transmit(midi, ep); | 613 | ret = f_midi_do_transmit(midi, ep); |
607 | if (ret < 0) | 614 | if (ret < 0) { |
615 | spin_unlock_irqrestore(&midi->transmit_lock, flags); | ||
608 | goto drop_out; | 616 | goto drop_out; |
617 | } | ||
609 | } while (ret); | 618 | } while (ret); |
610 | 619 | ||
620 | spin_unlock_irqrestore(&midi->transmit_lock, flags); | ||
621 | |||
611 | return; | 622 | return; |
612 | 623 | ||
613 | drop_out: | 624 | drop_out: |
@@ -1201,6 +1212,8 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) | |||
1201 | if (status) | 1212 | if (status) |
1202 | goto setup_fail; | 1213 | goto setup_fail; |
1203 | 1214 | ||
1215 | spin_lock_init(&midi->transmit_lock); | ||
1216 | |||
1204 | ++opts->refcnt; | 1217 | ++opts->refcnt; |
1205 | mutex_unlock(&opts->lock); | 1218 | mutex_unlock(&opts->lock); |
1206 | 1219 | ||