usb/gadget: f_midi: Replace tasklet with work

Currently a tasklet is used to transmit input substream buffer
data. However, tasklets have long been deprecated as being too
heavy on the system by running in irq context - and this is not
a performance critical path. If a higher priority process wants
to run, it must wait for the tasklet to finish before doing so.

Deferring work to a workqueue and executing in process context
should be fine considering the callback already does
f_midi_do_transmit() under the transmit_lock and thus changes in
semantics are ok regarding concurrency - tasklets being serialized
against itself.

Cc: Takashi Iwai <tiwai@suse.de>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Acked-by: Felipe Balbi <balbi@kernel.org>
Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
Link: https://lore.kernel.org/r/20210111042855.73289-1-dave@stgolabs.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Davidlohr Bueso 2021-01-10 20:28:55 -08:00 committed by Greg Kroah-Hartman
parent 0c0a20f6da
commit 8653d71ce3
1 changed files with 7 additions and 5 deletions

View File

@ -87,7 +87,7 @@ struct f_midi {
struct snd_rawmidi_substream *out_substream[MAX_PORTS];
unsigned long out_triggered;
struct tasklet_struct tasklet;
struct work_struct work;
unsigned int in_ports;
unsigned int out_ports;
int index;
@ -698,9 +698,11 @@ static void f_midi_transmit(struct f_midi *midi)
f_midi_drop_out_substreams(midi);
}
static void f_midi_in_tasklet(struct tasklet_struct *t)
static void f_midi_in_work(struct work_struct *work)
{
struct f_midi *midi = from_tasklet(midi, t, tasklet);
struct f_midi *midi;
midi = container_of(work, struct f_midi, work);
f_midi_transmit(midi);
}
@ -737,7 +739,7 @@ static void f_midi_in_trigger(struct snd_rawmidi_substream *substream, int up)
VDBG(midi, "%s() %d\n", __func__, up);
midi->in_ports_array[substream->number].active = up;
if (up)
tasklet_hi_schedule(&midi->tasklet);
queue_work(system_highpri_wq, &midi->work);
}
static int f_midi_out_open(struct snd_rawmidi_substream *substream)
@ -875,7 +877,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0;
midi->gadget = cdev->gadget;
tasklet_setup(&midi->tasklet, f_midi_in_tasklet);
INIT_WORK(&midi->work, f_midi_in_work);
status = f_midi_register_card(midi);
if (status < 0)
goto fail_register;