]>
Commit | Line | Data |
---|---|---|
7a8521b4 GKH |
1 | From e99ddfde6ae0dd2662bb40435696002b590e4057 Mon Sep 17 00:00:00 2001 |
2 | From: Clemens Ladisch <clemens@ladisch.de> | |
3 | Date: Wed, 31 Oct 2012 16:35:30 +0100 | |
4 | Subject: ALSA: ua101, usx2y: fix broken MIDI output | |
5 | ||
6 | From: Clemens Ladisch <clemens@ladisch.de> | |
7 | ||
8 | commit e99ddfde6ae0dd2662bb40435696002b590e4057 upstream. | |
9 | ||
10 | Commit 88a8516a2128 (ALSA: usbaudio: implement USB autosuspend) added | |
11 | autosuspend code to all files making up the snd-usb-audio driver. | |
12 | However, midi.c is part of snd-usb-lib and is also used by other | |
13 | drivers, not all of which support autosuspend. Thus, calls to | |
14 | usb_autopm_get_interface() could fail, and this unexpected error would | |
15 | result in the MIDI output being completely unusable. | |
16 | ||
17 | Make it work by ignoring the error that is expected with drivers that do | |
18 | not support autosuspend. | |
19 | ||
20 | Reported-by: Colin Fletcher <colin.m.fletcher@googlemail.com> | |
21 | Reported-by: Devin Venable <venable.devin@gmail.com> | |
22 | Reported-by: Dr Nick Bailey <nicholas.bailey@glasgow.ac.uk> | |
23 | Reported-by: Jannis Achstetter <jannis_achstetter@web.de> | |
24 | Reported-by: Rui Nuno Capela <rncbc@rncbc.org> | |
25 | Cc: Oliver Neukum <oliver@neukum.org> | |
26 | Signed-off-by: Clemens Ladisch <clemens@ladisch.de> | |
27 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
28 | ||
29 | --- | |
30 | sound/usb/midi.c | 8 ++++++-- | |
31 | 1 file changed, 6 insertions(+), 2 deletions(-) | |
32 | ||
33 | --- a/sound/usb/midi.c | |
34 | +++ b/sound/usb/midi.c | |
35 | @@ -148,6 +148,7 @@ struct snd_usb_midi_out_endpoint { | |
36 | struct snd_usb_midi_out_endpoint* ep; | |
37 | struct snd_rawmidi_substream *substream; | |
38 | int active; | |
39 | + bool autopm_reference; | |
40 | uint8_t cable; /* cable number << 4 */ | |
41 | uint8_t state; | |
42 | #define STATE_UNKNOWN 0 | |
43 | @@ -1076,7 +1077,8 @@ static int snd_usbmidi_output_open(struc | |
44 | return -ENXIO; | |
45 | } | |
46 | err = usb_autopm_get_interface(umidi->iface); | |
47 | - if (err < 0) | |
48 | + port->autopm_reference = err >= 0; | |
49 | + if (err < 0 && err != -EACCES) | |
50 | return -EIO; | |
51 | substream->runtime->private_data = port; | |
52 | port->state = STATE_UNKNOWN; | |
53 | @@ -1087,9 +1089,11 @@ static int snd_usbmidi_output_open(struc | |
54 | static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) | |
55 | { | |
56 | struct snd_usb_midi* umidi = substream->rmidi->private_data; | |
57 | + struct usbmidi_out_port *port = substream->runtime->private_data; | |
58 | ||
59 | substream_open(substream, 0); | |
60 | - usb_autopm_put_interface(umidi->iface); | |
61 | + if (port->autopm_reference) | |
62 | + usb_autopm_put_interface(umidi->iface); | |
63 | return 0; | |
64 | } | |
65 |