]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/5.1.8/alsa-line6-assure-canceling-delayed-work-at-disconnection.patch
Linux 5.1.8
[thirdparty/kernel/stable-queue.git] / releases / 5.1.8 / alsa-line6-assure-canceling-delayed-work-at-disconnection.patch
CommitLineData
731fa5a3
GKH
1From 0b074ab7fc0d575247b9cc9f93bb7e007ca38840 Mon Sep 17 00:00:00 2001
2From: Takashi Iwai <tiwai@suse.de>
3Date: Tue, 28 May 2019 08:39:44 +0200
4Subject: ALSA: line6: Assure canceling delayed work at disconnection
5
6From: Takashi Iwai <tiwai@suse.de>
7
8commit 0b074ab7fc0d575247b9cc9f93bb7e007ca38840 upstream.
9
10The current code performs the cancel of a delayed work at the late
11stage of disconnection procedure, which may lead to the access to the
12already cleared state.
13
14This patch assures to call cancel_delayed_work_sync() at the beginning
15of the disconnection procedure for avoiding that race. The delayed
16work object is now assigned in the common line6 object instead of its
17derivative, so that we can call cancel_delayed_work_sync().
18
19Along with the change, the startup function is called via the new
20callback instead. This will make it easier to port other LINE6
21drivers to use the delayed work for startup in later patches.
22
23Reported-by: syzbot+5255458d5e0a2b10bbb9@syzkaller.appspotmail.com
24Fixes: 7f84ff68be05 ("ALSA: line6: toneport: Fix broken usage of timer for delayed execution")
25Cc: <stable@vger.kernel.org>
26Signed-off-by: Takashi Iwai <tiwai@suse.de>
27Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
28
29---
30 sound/usb/line6/driver.c | 12 ++++++++++++
31 sound/usb/line6/driver.h | 4 ++++
32 sound/usb/line6/toneport.c | 15 +++------------
33 3 files changed, 19 insertions(+), 12 deletions(-)
34
35--- a/sound/usb/line6/driver.c
36+++ b/sound/usb/line6/driver.c
37@@ -720,6 +720,15 @@ static int line6_init_cap_control(struct
38 return 0;
39 }
40
41+static void line6_startup_work(struct work_struct *work)
42+{
43+ struct usb_line6 *line6 =
44+ container_of(work, struct usb_line6, startup_work.work);
45+
46+ if (line6->startup)
47+ line6->startup(line6);
48+}
49+
50 /*
51 Probe USB device.
52 */
53@@ -755,6 +764,7 @@ int line6_probe(struct usb_interface *in
54 line6->properties = properties;
55 line6->usbdev = usbdev;
56 line6->ifcdev = &interface->dev;
57+ INIT_DELAYED_WORK(&line6->startup_work, line6_startup_work);
58
59 strcpy(card->id, properties->id);
60 strcpy(card->driver, driver_name);
61@@ -825,6 +835,8 @@ void line6_disconnect(struct usb_interfa
62 if (WARN_ON(usbdev != line6->usbdev))
63 return;
64
65+ cancel_delayed_work(&line6->startup_work);
66+
67 if (line6->urb_listen != NULL)
68 line6_stop_listen(line6);
69
70--- a/sound/usb/line6/driver.h
71+++ b/sound/usb/line6/driver.h
72@@ -178,11 +178,15 @@ struct usb_line6 {
73 fifo;
74 } messages;
75
76+ /* Work for delayed PCM startup */
77+ struct delayed_work startup_work;
78+
79 /* If MIDI is supported, buffer_message contains the pre-processed data;
80 * otherwise the data is only in urb_listen (buffer_incoming).
81 */
82 void (*process_message)(struct usb_line6 *);
83 void (*disconnect)(struct usb_line6 *line6);
84+ void (*startup)(struct usb_line6 *line6);
85 };
86
87 extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1,
88--- a/sound/usb/line6/toneport.c
89+++ b/sound/usb/line6/toneport.c
90@@ -54,9 +54,6 @@ struct usb_line6_toneport {
91 /* Firmware version (x 100) */
92 u8 firmware_version;
93
94- /* Work for delayed PCM startup */
95- struct delayed_work pcm_work;
96-
97 /* Device type */
98 enum line6_device_type type;
99
100@@ -241,12 +238,8 @@ static int snd_toneport_source_put(struc
101 return 1;
102 }
103
104-static void toneport_start_pcm(struct work_struct *work)
105+static void toneport_startup(struct usb_line6 *line6)
106 {
107- struct usb_line6_toneport *toneport =
108- container_of(work, struct usb_line6_toneport, pcm_work.work);
109- struct usb_line6 *line6 = &toneport->line6;
110-
111 line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR, true);
112 }
113
114@@ -394,7 +387,7 @@ static int toneport_setup(struct usb_lin
115 if (toneport_has_led(toneport))
116 toneport_update_led(toneport);
117
118- schedule_delayed_work(&toneport->pcm_work,
119+ schedule_delayed_work(&toneport->line6.startup_work,
120 msecs_to_jiffies(TONEPORT_PCM_DELAY * 1000));
121 return 0;
122 }
123@@ -407,8 +400,6 @@ static void line6_toneport_disconnect(st
124 struct usb_line6_toneport *toneport =
125 (struct usb_line6_toneport *)line6;
126
127- cancel_delayed_work_sync(&toneport->pcm_work);
128-
129 if (toneport_has_led(toneport))
130 toneport_remove_leds(toneport);
131 }
132@@ -424,9 +415,9 @@ static int toneport_init(struct usb_line
133 struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6;
134
135 toneport->type = id->driver_info;
136- INIT_DELAYED_WORK(&toneport->pcm_work, toneport_start_pcm);
137
138 line6->disconnect = line6_toneport_disconnect;
139+ line6->startup = toneport_startup;
140
141 /* initialize PCM subsystem: */
142 err = line6_init_pcm(line6, &toneport_pcm_properties);