Commit 8653d71c authored by Davidlohr Bueso's avatar Davidlohr Bueso Committed by Greg Kroah-Hartman
Browse files

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: default avatarTakashi Iwai <tiwai@suse.de>
Acked-by: default avatarFelipe Balbi <balbi@kernel.org>
Signed-off-by: default avatarDavidlohr Bueso <dbueso@suse.de>
Link: https://lore.kernel.org/r/20210111042855.73289-1-dave@stgolabs.net


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0c0a20f6
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -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;