Update Linux to v5.4.2
Change-Id: Idf6911045d9d382da2cfe01b1edff026404ac8fd
diff --git a/sound/usb/line6/Kconfig b/sound/usb/line6/Kconfig
index 39b4003..ab557e5 100644
--- a/sound/usb/line6/Kconfig
+++ b/sound/usb/line6/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
config SND_USB_LINE6
tristate
select SND_RAWMIDI
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
index d8a14d7..82abef3 100644
--- a/sound/usb/line6/capture.c
+++ b/sound/usb/line6/capture.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#include <linux/slab.h>
diff --git a/sound/usb/line6/capture.h b/sound/usb/line6/capture.h
index b67ccc3..20e05a5 100644
--- a/sound/usb/line6/capture.h
+++ b/sound/usb/line6/capture.h
@@ -1,12 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#ifndef CAPTURE_H
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index c1376bf..b5a3f75 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#include <linux/kernel.h>
@@ -196,17 +192,6 @@
}
/*
- Setup and start timer.
-*/
-void line6_start_timer(struct timer_list *timer, unsigned long msecs,
- void (*function)(struct timer_list *t))
-{
- timer->function = function;
- mod_timer(timer, jiffies + msecs_to_jiffies(msecs));
-}
-EXPORT_SYMBOL_GPL(line6_start_timer);
-
-/*
Asynchronously send raw message.
*/
int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer,
@@ -351,12 +336,16 @@
{
struct usb_device *usbdev = line6->usbdev;
int ret;
- unsigned char len;
+ unsigned char *len;
unsigned count;
if (address > 0xffff || datalen > 0xff)
return -EINVAL;
+ len = kmalloc(1, GFP_KERNEL);
+ if (!len)
+ return -ENOMEM;
+
/* query the serial number: */
ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
@@ -365,7 +354,7 @@
if (ret < 0) {
dev_err(line6->ifcdev, "read request failed (error %d)\n", ret);
- return ret;
+ goto exit;
}
/* Wait for data length. We'll get 0xff until length arrives. */
@@ -375,28 +364,29 @@
ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_DIR_IN,
- 0x0012, 0x0000, &len, 1,
+ 0x0012, 0x0000, len, 1,
LINE6_TIMEOUT * HZ);
if (ret < 0) {
dev_err(line6->ifcdev,
"receive length failed (error %d)\n", ret);
- return ret;
+ goto exit;
}
- if (len != 0xff)
+ if (*len != 0xff)
break;
}
- if (len == 0xff) {
+ ret = -EIO;
+ if (*len == 0xff) {
dev_err(line6->ifcdev, "read failed after %d retries\n",
count);
- return -EIO;
- } else if (len != datalen) {
+ goto exit;
+ } else if (*len != datalen) {
/* should be equal or something went wrong */
dev_err(line6->ifcdev,
"length mismatch (expected %d, got %d)\n",
- (int)datalen, (int)len);
- return -EIO;
+ (int)datalen, (int)*len);
+ goto exit;
}
/* receive the result: */
@@ -405,12 +395,12 @@
0x0013, 0x0000, data, datalen,
LINE6_TIMEOUT * HZ);
- if (ret < 0) {
+ if (ret < 0)
dev_err(line6->ifcdev, "read failed (error %d)\n", ret);
- return ret;
- }
- return 0;
+exit:
+ kfree(len);
+ return ret;
}
EXPORT_SYMBOL_GPL(line6_read_data);
@@ -422,12 +412,16 @@
{
struct usb_device *usbdev = line6->usbdev;
int ret;
- unsigned char status;
+ unsigned char *status;
int count;
if (address > 0xffff || datalen > 0xffff)
return -EINVAL;
+ status = kmalloc(1, GFP_KERNEL);
+ if (!status)
+ return -ENOMEM;
+
ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0x0022, address, data, datalen,
@@ -436,7 +430,7 @@
if (ret < 0) {
dev_err(line6->ifcdev,
"write request failed (error %d)\n", ret);
- return ret;
+ goto exit;
}
for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) {
@@ -447,28 +441,29 @@
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_DIR_IN,
0x0012, 0x0000,
- &status, 1, LINE6_TIMEOUT * HZ);
+ status, 1, LINE6_TIMEOUT * HZ);
if (ret < 0) {
dev_err(line6->ifcdev,
"receiving status failed (error %d)\n", ret);
- return ret;
+ goto exit;
}
- if (status != 0xff)
+ if (*status != 0xff)
break;
}
- if (status == 0xff) {
+ if (*status == 0xff) {
dev_err(line6->ifcdev, "write failed after %d retries\n",
count);
- return -EIO;
- } else if (status != 0) {
+ ret = -EIO;
+ } else if (*status != 0) {
dev_err(line6->ifcdev, "write failed (error %d)\n", ret);
- return -EIO;
+ ret = -EIO;
}
-
- return 0;
+exit:
+ kfree(status);
+ return ret;
}
EXPORT_SYMBOL_GPL(line6_write_data);
@@ -710,6 +705,15 @@
return 0;
}
+static void line6_startup_work(struct work_struct *work)
+{
+ struct usb_line6 *line6 =
+ container_of(work, struct usb_line6, startup_work.work);
+
+ if (line6->startup)
+ line6->startup(line6);
+}
+
/*
Probe USB device.
*/
@@ -745,6 +749,7 @@
line6->properties = properties;
line6->usbdev = usbdev;
line6->ifcdev = &interface->dev;
+ INIT_DELAYED_WORK(&line6->startup_work, line6_startup_work);
strcpy(card->id, properties->id);
strcpy(card->driver, driver_name);
@@ -815,6 +820,8 @@
if (WARN_ON(usbdev != line6->usbdev))
return;
+ cancel_delayed_work(&line6->startup_work);
+
if (line6->urb_listen != NULL)
line6_stop_listen(line6);
@@ -849,10 +856,8 @@
if (line6->properties->capabilities & LINE6_CAP_CONTROL)
line6_stop_listen(line6);
- if (line6pcm != NULL) {
- snd_pcm_suspend_all(line6pcm->pcm);
+ if (line6pcm != NULL)
line6pcm->flags = 0;
- }
return 0;
}
diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h
index 6142559..e5e572e 100644
--- a/sound/usb/line6/driver.h
+++ b/sound/usb/line6/driver.h
@@ -1,12 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#ifndef DRIVER_H
@@ -68,13 +64,6 @@
#define LINE6_CHANNEL_MASK 0x0f
-#define CHECK_STARTUP_PROGRESS(x, n) \
-do { \
- if ((x) >= (n)) \
- return; \
- x = (n); \
-} while (0)
-
extern const unsigned char line6_midi_id[3];
static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;
@@ -178,11 +167,15 @@
fifo;
} messages;
+ /* Work for delayed PCM startup */
+ struct delayed_work startup_work;
+
/* If MIDI is supported, buffer_message contains the pre-processed data;
* otherwise the data is only in urb_listen (buffer_incoming).
*/
void (*process_message)(struct usb_line6 *);
void (*disconnect)(struct usb_line6 *line6);
+ void (*startup)(struct usb_line6 *line6);
};
extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1,
@@ -197,8 +190,6 @@
const char *buffer, int size);
extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
-extern void line6_start_timer(struct timer_list *timer, unsigned long msecs,
- void (*function)(struct timer_list *t));
extern int line6_version_request_async(struct usb_line6 *line6);
extern int line6_write_data(struct usb_line6 *line6, unsigned address,
void *data, unsigned datalen);
diff --git a/sound/usb/line6/midi.c b/sound/usb/line6/midi.c
index e2cf55c..ba0e2b7 100644
--- a/sound/usb/line6/midi.c
+++ b/sound/usb/line6/midi.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#include <linux/slab.h>
diff --git a/sound/usb/line6/midi.h b/sound/usb/line6/midi.h
index cf82d69..918754e 100644
--- a/sound/usb/line6/midi.h
+++ b/sound/usb/line6/midi.h
@@ -1,12 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#ifndef MIDI_H
diff --git a/sound/usb/line6/midibuf.c b/sound/usb/line6/midibuf.c
index 36a610b..8d6eefa 100644
--- a/sound/usb/line6/midibuf.c
+++ b/sound/usb/line6/midibuf.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#include <linux/slab.h>
diff --git a/sound/usb/line6/midibuf.h b/sound/usb/line6/midibuf.h
index 6ea21ff..124a8f9 100644
--- a/sound/usb/line6/midibuf.h
+++ b/sound/usb/line6/midibuf.h
@@ -1,12 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#ifndef MIDIBUF_H
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
index 72c6f8e..f70211e 100644
--- a/sound/usb/line6/pcm.c
+++ b/sound/usb/line6/pcm.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#include <linux/slab.h>
@@ -554,13 +550,6 @@
line6pcm->volume_monitor = 255;
line6pcm->line6 = line6;
- line6pcm->max_packet_size_in =
- usb_maxpacket(line6->usbdev,
- usb_rcvisocpipe(line6->usbdev, ep_read), 0);
- line6pcm->max_packet_size_out =
- usb_maxpacket(line6->usbdev,
- usb_sndisocpipe(line6->usbdev, ep_write), 1);
-
spin_lock_init(&line6pcm->out.lock);
spin_lock_init(&line6pcm->in.lock);
line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
@@ -570,6 +559,18 @@
pcm->private_data = line6pcm;
pcm->private_free = line6_cleanup_pcm;
+ line6pcm->max_packet_size_in =
+ usb_maxpacket(line6->usbdev,
+ usb_rcvisocpipe(line6->usbdev, ep_read), 0);
+ line6pcm->max_packet_size_out =
+ usb_maxpacket(line6->usbdev,
+ usb_sndisocpipe(line6->usbdev, ep_write), 1);
+ if (!line6pcm->max_packet_size_in || !line6pcm->max_packet_size_out) {
+ dev_err(line6pcm->line6->ifcdev,
+ "cannot get proper max packet size\n");
+ return -EINVAL;
+ }
+
err = line6_create_audio_out_urbs(line6pcm);
if (err < 0)
return err;
diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h
index bb0c9cb..9c68304 100644
--- a/sound/usb/line6/pcm.h
+++ b/sound/usb/line6/pcm.h
@@ -1,12 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
/*
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
index dec89d2..2e8ead3 100644
--- a/sound/usb/line6/playback.c
+++ b/sound/usb/line6/playback.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#include <linux/slab.h>
diff --git a/sound/usb/line6/playback.h b/sound/usb/line6/playback.h
index d8d3b8a..2ca832c 100644
--- a/sound/usb/line6/playback.h
+++ b/sound/usb/line6/playback.h
@@ -1,12 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#ifndef PLAYBACK_H
diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c
index 020c818..ee4c9d2 100644
--- a/sound/usb/line6/pod.c
+++ b/sound/usb/line6/pod.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#include <linux/slab.h>
@@ -39,11 +35,9 @@
Stages of POD startup procedure
*/
enum {
- POD_STARTUP_INIT = 1,
POD_STARTUP_VERSIONREQ,
- POD_STARTUP_WORKQUEUE,
POD_STARTUP_SETUP,
- POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
+ POD_STARTUP_DONE,
};
enum {
@@ -63,12 +57,6 @@
/* Instrument monitor level */
int monitor_level;
- /* Timer for device initialization */
- struct timer_list startup_timer;
-
- /* Work handler for device initialization */
- struct work_struct startup_work;
-
/* Current progress in startup procedure */
int startup_progress;
@@ -82,6 +70,8 @@
int device_id;
};
+#define line6_to_pod(x) container_of(x, struct usb_line6_pod, line6)
+
#define POD_SYSEX_CODE 3
/* *INDENT-OFF* */
@@ -173,10 +163,6 @@
0xf2, 0x7e, 0x7f, 0x06, 0x02
};
-/* forward declarations: */
-static void pod_startup2(struct timer_list *t);
-static void pod_startup3(struct usb_line6_pod *pod);
-
static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
int size)
{
@@ -189,14 +175,17 @@
*/
static void line6_pod_process_message(struct usb_line6 *line6)
{
- struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
+ struct usb_line6_pod *pod = line6_to_pod(line6);
const unsigned char *buf = pod->line6.buffer_message;
if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
(int) buf[10];
- pod_startup3(pod);
+ if (pod->startup_progress == POD_STARTUP_VERSIONREQ) {
+ pod->startup_progress = POD_STARTUP_SETUP;
+ schedule_delayed_work(&line6->startup_work, 0);
+ }
return;
}
@@ -281,46 +270,27 @@
context). After the last one has finished, the device is ready to use.
*/
-static void pod_startup1(struct usb_line6_pod *pod)
+static void pod_startup(struct usb_line6 *line6)
{
- CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
+ struct usb_line6_pod *pod = line6_to_pod(line6);
- /* delay startup procedure: */
- line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2);
-}
+ switch (pod->startup_progress) {
+ case POD_STARTUP_VERSIONREQ:
+ /* request firmware version: */
+ line6_version_request_async(line6);
+ break;
+ case POD_STARTUP_SETUP:
+ /* serial number: */
+ line6_read_serial_number(&pod->line6, &pod->serial_number);
-static void pod_startup2(struct timer_list *t)
-{
- struct usb_line6_pod *pod = from_timer(pod, t, startup_timer);
- struct usb_line6 *line6 = &pod->line6;
-
- CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
-
- /* request firmware version: */
- line6_version_request_async(line6);
-}
-
-static void pod_startup3(struct usb_line6_pod *pod)
-{
- CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
-
- /* schedule work for global work queue: */
- schedule_work(&pod->startup_work);
-}
-
-static void pod_startup4(struct work_struct *work)
-{
- struct usb_line6_pod *pod =
- container_of(work, struct usb_line6_pod, startup_work);
- struct usb_line6 *line6 = &pod->line6;
-
- CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
-
- /* serial number: */
- line6_read_serial_number(&pod->line6, &pod->serial_number);
-
- /* ALSA audio interface: */
- snd_card_register(line6->card);
+ /* ALSA audio interface: */
+ if (snd_card_register(line6->card))
+ dev_err(line6->ifcdev, "Failed to register POD card.\n");
+ pod->startup_progress = POD_STARTUP_DONE;
+ break;
+ default:
+ break;
+ }
}
/* POD special files: */
@@ -356,7 +326,7 @@
struct snd_ctl_elem_value *ucontrol)
{
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
- struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
+ struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6);
ucontrol->value.integer.value[0] = pod->monitor_level;
return 0;
@@ -367,7 +337,7 @@
struct snd_ctl_elem_value *ucontrol)
{
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
- struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
+ struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6);
if (ucontrol->value.integer.value[0] == pod->monitor_level)
return 0;
@@ -390,30 +360,16 @@
};
/*
- POD device disconnected.
-*/
-static void line6_pod_disconnect(struct usb_line6 *line6)
-{
- struct usb_line6_pod *pod = (struct usb_line6_pod *)line6;
-
- del_timer_sync(&pod->startup_timer);
- cancel_work_sync(&pod->startup_work);
-}
-
-/*
Try to init POD device.
*/
static int pod_init(struct usb_line6 *line6,
const struct usb_device_id *id)
{
int err;
- struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
+ struct usb_line6_pod *pod = line6_to_pod(line6);
line6->process_message = line6_pod_process_message;
- line6->disconnect = line6_pod_disconnect;
-
- timer_setup(&pod->startup_timer, NULL, 0);
- INIT_WORK(&pod->startup_work, pod_startup4);
+ line6->startup = pod_startup;
/* create sysfs entries: */
err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group);
@@ -446,7 +402,8 @@
pod->monitor_level = POD_SYSTEM_INVALID;
/* initiate startup procedure: */
- pod_startup1(pod);
+ schedule_delayed_work(&line6->startup_work,
+ msecs_to_jiffies(POD_STARTUP_DELAY));
}
return 0;
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c
index 36ed9c8..27bf61c 100644
--- a/sound/usb/line6/podhd.c
+++ b/sound/usb/line6/podhd.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Line 6 Pod HD
*
* Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
* Copyright (C) 2015 Andrej Krutak <dev@andree.sk>
* Copyright (C) 2017 Hans P. Moller <hmoller@uc.cl>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#include <linux/usb.h>
@@ -22,16 +18,6 @@
#define PODHD_STARTUP_DELAY 500
-/*
- * Stages of POD startup procedure
- */
-enum {
- PODHD_STARTUP_INIT = 1,
- PODHD_STARTUP_SCHEDULE_WORKQUEUE,
- PODHD_STARTUP_SETUP,
- PODHD_STARTUP_LAST = PODHD_STARTUP_SETUP - 1
-};
-
enum {
LINE6_PODHD300,
LINE6_PODHD400,
@@ -47,15 +33,6 @@
/* Generic Line 6 USB data */
struct usb_line6 line6;
- /* Timer for device initialization */
- struct timer_list startup_timer;
-
- /* Work handler for device initialization */
- struct work_struct startup_work;
-
- /* Current progress in startup procedure */
- int startup_progress;
-
/* Serial number of device */
u32 serial_number;
@@ -63,6 +40,8 @@
int firmware_version;
};
+#define line6_to_podhd(x) container_of(x, struct usb_line6_podhd, line6)
+
static struct snd_ratden podhd_ratden = {
.num_min = 48000,
.num_max = 48000,
@@ -158,10 +137,6 @@
};
static struct usb_driver podhd_driver;
-static void podhd_startup_start_workqueue(struct timer_list *t);
-static void podhd_startup_workqueue(struct work_struct *work);
-static int podhd_startup_finalize(struct usb_line6_podhd *pod);
-
static ssize_t serial_number_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -202,51 +177,35 @@
* audio nor bulk interfaces to work.
*/
-static void podhd_startup(struct usb_line6_podhd *pod)
-{
- CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_INIT);
-
- /* delay startup procedure: */
- line6_start_timer(&pod->startup_timer, PODHD_STARTUP_DELAY,
- podhd_startup_start_workqueue);
-}
-
-static void podhd_startup_start_workqueue(struct timer_list *t)
-{
- struct usb_line6_podhd *pod = from_timer(pod, t, startup_timer);
-
- CHECK_STARTUP_PROGRESS(pod->startup_progress,
- PODHD_STARTUP_SCHEDULE_WORKQUEUE);
-
- /* schedule work for global work queue: */
- schedule_work(&pod->startup_work);
-}
-
static int podhd_dev_start(struct usb_line6_podhd *pod)
{
int ret;
- u8 init_bytes[8];
+ u8 *init_bytes;
int i;
struct usb_device *usbdev = pod->line6.usbdev;
+ init_bytes = kmalloc(8, GFP_KERNEL);
+ if (!init_bytes)
+ return -ENOMEM;
+
ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0x11, 0,
NULL, 0, LINE6_TIMEOUT * HZ);
if (ret < 0) {
dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret);
- return ret;
+ goto exit;
}
/* NOTE: looks like some kind of ping message */
ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x11, 0x0,
- &init_bytes, 3, LINE6_TIMEOUT * HZ);
+ init_bytes, 3, LINE6_TIMEOUT * HZ);
if (ret < 0) {
dev_err(pod->line6.ifcdev,
"receive length failed (error %d)\n", ret);
- return ret;
+ goto exit;
}
pod->firmware_version =
@@ -255,7 +214,7 @@
for (i = 0; i <= 16; i++) {
ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8);
if (ret < 0)
- return ret;
+ goto exit;
}
ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
@@ -263,43 +222,28 @@
USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT,
1, 0,
NULL, 0, LINE6_TIMEOUT * HZ);
- if (ret < 0)
- return ret;
-
- return 0;
+exit:
+ kfree(init_bytes);
+ return ret;
}
-static void podhd_startup_workqueue(struct work_struct *work)
+static void podhd_startup(struct usb_line6 *line6)
{
- struct usb_line6_podhd *pod =
- container_of(work, struct usb_line6_podhd, startup_work);
-
- CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_SETUP);
+ struct usb_line6_podhd *pod = line6_to_podhd(line6);
podhd_dev_start(pod);
line6_read_serial_number(&pod->line6, &pod->serial_number);
-
- podhd_startup_finalize(pod);
-}
-
-static int podhd_startup_finalize(struct usb_line6_podhd *pod)
-{
- struct usb_line6 *line6 = &pod->line6;
-
- /* ALSA audio interface: */
- return snd_card_register(line6->card);
+ if (snd_card_register(line6->card))
+ dev_err(line6->ifcdev, "Failed to register POD HD card.\n");
}
static void podhd_disconnect(struct usb_line6 *line6)
{
- struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6;
+ struct usb_line6_podhd *pod = line6_to_podhd(line6);
if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) {
struct usb_interface *intf;
- del_timer_sync(&pod->startup_timer);
- cancel_work_sync(&pod->startup_work);
-
intf = usb_ifnum_to_if(line6->usbdev,
pod->line6.properties->ctrl_if);
if (intf)
@@ -314,13 +258,11 @@
const struct usb_device_id *id)
{
int err;
- struct usb_line6_podhd *pod = (struct usb_line6_podhd *) line6;
+ struct usb_line6_podhd *pod = line6_to_podhd(line6);
struct usb_interface *intf;
line6->disconnect = podhd_disconnect;
-
- timer_setup(&pod->startup_timer, NULL, 0);
- INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
+ line6->startup = podhd_startup;
if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
/* claim the data interface */
@@ -359,11 +301,12 @@
if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) {
/* register USB audio system directly */
- return podhd_startup_finalize(pod);
+ return snd_card_register(line6->card);
}
/* init device and delay registering */
- podhd_startup(pod);
+ schedule_delayed_work(&line6->startup_work,
+ msecs_to_jiffies(PODHD_STARTUP_DELAY));
return 0;
}
@@ -425,7 +368,7 @@
.name = "POD HD500",
.capabilities = LINE6_CAP_PCM
| LINE6_CAP_HWMON,
- .altsetting = 1,
+ .altsetting = 0,
.ep_ctrl_r = 0x81,
.ep_ctrl_w = 0x01,
.ep_audio_r = 0x86,
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
index f47ba94..d0a555d 100644
--- a/sound/usb/line6/toneport.c
+++ b/sound/usb/line6/toneport.c
@@ -1,13 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* Emil Myhrman (emil.myhrman@gmail.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#include <linux/wait.h>
@@ -54,9 +50,6 @@
/* Firmware version (x 100) */
u8 firmware_version;
- /* Timer for delayed PCM startup */
- struct timer_list timer;
-
/* Device type */
enum line6_device_type type;
@@ -64,6 +57,8 @@
struct toneport_led leds[2];
};
+#define line6_to_toneport(x) container_of(x, struct usb_line6_toneport, line6)
+
static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2);
#define TONEPORT_PCM_DELAY 1
@@ -214,8 +209,8 @@
struct snd_ctl_elem_value *ucontrol)
{
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
- struct usb_line6_toneport *toneport =
- (struct usb_line6_toneport *)line6pcm->line6;
+ struct usb_line6_toneport *toneport = line6_to_toneport(line6pcm->line6);
+
ucontrol->value.enumerated.item[0] = toneport->source;
return 0;
}
@@ -225,8 +220,7 @@
struct snd_ctl_elem_value *ucontrol)
{
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
- struct usb_line6_toneport *toneport =
- (struct usb_line6_toneport *)line6pcm->line6;
+ struct usb_line6_toneport *toneport = line6_to_toneport(line6pcm->line6);
unsigned int source;
source = ucontrol->value.enumerated.item[0];
@@ -241,11 +235,8 @@
return 1;
}
-static void toneport_start_pcm(struct timer_list *t)
+static void toneport_startup(struct usb_line6 *line6)
{
- struct usb_line6_toneport *toneport = from_timer(toneport, t, timer);
- struct usb_line6 *line6 = &toneport->line6;
-
line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR, true);
}
@@ -291,8 +282,8 @@
}
}
-static const char * const led_colors[2] = { "red", "green" };
-static const int led_init_vals[2] = { 0x00, 0x26 };
+static const char * const toneport_led_colors[2] = { "red", "green" };
+static const int toneport_led_init_vals[2] = { 0x00, 0x26 };
static void toneport_update_led(struct usb_line6_toneport *toneport)
{
@@ -320,9 +311,9 @@
led->toneport = toneport;
snprintf(led->name, sizeof(led->name), "%s::%s",
- dev_name(dev), led_colors[i]);
+ dev_name(dev), toneport_led_colors[i]);
leddev->name = led->name;
- leddev->brightness = led_init_vals[i];
+ leddev->brightness = toneport_led_init_vals[i];
leddev->max_brightness = 0x26;
leddev->brightness_set = toneport_led_brightness_set;
err = led_classdev_register(dev, leddev);
@@ -365,16 +356,21 @@
/*
Setup Toneport device.
*/
-static void toneport_setup(struct usb_line6_toneport *toneport)
+static int toneport_setup(struct usb_line6_toneport *toneport)
{
- u32 ticks;
+ u32 *ticks;
struct usb_line6 *line6 = &toneport->line6;
struct usb_device *usbdev = line6->usbdev;
+ ticks = kmalloc(sizeof(*ticks), GFP_KERNEL);
+ if (!ticks)
+ return -ENOMEM;
+
/* sync time on device with host: */
/* note: 32-bit timestamps overflow in year 2106 */
- ticks = (u32)ktime_get_real_seconds();
- line6_write_data(line6, 0x80c6, &ticks, 4);
+ *ticks = (u32)ktime_get_real_seconds();
+ line6_write_data(line6, 0x80c6, ticks, 4);
+ kfree(ticks);
/* enable device: */
toneport_send_cmd(usbdev, 0x0301, 0x0000);
@@ -388,7 +384,9 @@
if (toneport_has_led(toneport))
toneport_update_led(toneport);
- mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ);
+ schedule_delayed_work(&toneport->line6.startup_work,
+ msecs_to_jiffies(TONEPORT_PCM_DELAY * 1000));
+ return 0;
}
/*
@@ -396,10 +394,7 @@
*/
static void line6_toneport_disconnect(struct usb_line6 *line6)
{
- struct usb_line6_toneport *toneport =
- (struct usb_line6_toneport *)line6;
-
- del_timer_sync(&toneport->timer);
+ struct usb_line6_toneport *toneport = line6_to_toneport(line6);
if (toneport_has_led(toneport))
toneport_remove_leds(toneport);
@@ -413,12 +408,12 @@
const struct usb_device_id *id)
{
int err;
- struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6;
+ struct usb_line6_toneport *toneport = line6_to_toneport(line6);
toneport->type = id->driver_info;
- timer_setup(&toneport->timer, toneport_start_pcm, 0);
line6->disconnect = line6_toneport_disconnect;
+ line6->startup = toneport_startup;
/* initialize PCM subsystem: */
err = line6_init_pcm(line6, &toneport_pcm_properties);
@@ -451,7 +446,9 @@
return err;
}
- toneport_setup(toneport);
+ err = toneport_setup(toneport);
+ if (err)
+ return err;
/* register audio system: */
return snd_card_register(line6->card);
@@ -463,7 +460,11 @@
*/
static int toneport_reset_resume(struct usb_interface *interface)
{
- toneport_setup(usb_get_intfdata(interface));
+ int err;
+
+ err = toneport_setup(usb_get_intfdata(interface));
+ if (err)
+ return err;
return line6_resume(interface);
}
#endif
diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c
index e8c852b..ed158f0 100644
--- a/sound/usb/line6/variax.c
+++ b/sound/usb/line6/variax.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Line 6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
*/
#include <linux/slab.h>
@@ -26,13 +22,9 @@
Stages of Variax startup procedure
*/
enum {
- VARIAX_STARTUP_INIT = 1,
VARIAX_STARTUP_VERSIONREQ,
- VARIAX_STARTUP_WAIT,
VARIAX_STARTUP_ACTIVATE,
- VARIAX_STARTUP_WORKQUEUE,
VARIAX_STARTUP_SETUP,
- VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
};
enum {
@@ -47,17 +39,12 @@
/* Buffer for activation code */
unsigned char *buffer_activate;
- /* Handler for device initialization */
- struct work_struct startup_work;
-
- /* Timers for device initialization */
- struct timer_list startup_timer1;
- struct timer_list startup_timer2;
-
/* Current progress in startup procedure */
int startup_progress;
};
+#define line6_to_variax(x) container_of(x, struct usb_line6_variax, line6)
+
#define VARIAX_OFFSET_ACTIVATE 7
/*
@@ -81,11 +68,6 @@
0xf7
};
-/* forward declarations: */
-static void variax_startup2(struct timer_list *t);
-static void variax_startup4(struct timer_list *t);
-static void variax_startup5(struct timer_list *t);
-
static void variax_activate_async(struct usb_line6_variax *variax, int a)
{
variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
@@ -100,74 +82,30 @@
context). After the last one has finished, the device is ready to use.
*/
-static void variax_startup1(struct usb_line6_variax *variax)
+static void variax_startup(struct usb_line6 *line6)
{
- CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT);
+ struct usb_line6_variax *variax = line6_to_variax(line6);
- /* delay startup procedure: */
- line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
- variax_startup2);
-}
-
-static void variax_startup2(struct timer_list *t)
-{
- struct usb_line6_variax *variax = from_timer(variax, t, startup_timer1);
- struct usb_line6 *line6 = &variax->line6;
-
- /* schedule another startup procedure until startup is complete: */
- if (variax->startup_progress >= VARIAX_STARTUP_LAST)
- return;
-
- variax->startup_progress = VARIAX_STARTUP_VERSIONREQ;
- line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
- variax_startup2);
-
- /* request firmware version: */
- line6_version_request_async(line6);
-}
-
-static void variax_startup3(struct usb_line6_variax *variax)
-{
- CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT);
-
- /* delay startup procedure: */
- line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
- variax_startup4);
-}
-
-static void variax_startup4(struct timer_list *t)
-{
- struct usb_line6_variax *variax = from_timer(variax, t, startup_timer2);
-
- CHECK_STARTUP_PROGRESS(variax->startup_progress,
- VARIAX_STARTUP_ACTIVATE);
-
- /* activate device: */
- variax_activate_async(variax, 1);
- line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4,
- variax_startup5);
-}
-
-static void variax_startup5(struct timer_list *t)
-{
- struct usb_line6_variax *variax = from_timer(variax, t, startup_timer2);
-
- CHECK_STARTUP_PROGRESS(variax->startup_progress,
- VARIAX_STARTUP_WORKQUEUE);
-
- /* schedule work for global work queue: */
- schedule_work(&variax->startup_work);
-}
-
-static void variax_startup6(struct work_struct *work)
-{
- struct usb_line6_variax *variax =
- container_of(work, struct usb_line6_variax, startup_work);
-
- CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
-
- /* ALSA audio interface: */
- snd_card_register(variax->line6.card);
+ switch (variax->startup_progress) {
+ case VARIAX_STARTUP_VERSIONREQ:
+ /* repeat request until getting the response */
+ schedule_delayed_work(&line6->startup_work,
+ msecs_to_jiffies(VARIAX_STARTUP_DELAY1));
+ /* request firmware version: */
+ line6_version_request_async(line6);
+ break;
+ case VARIAX_STARTUP_ACTIVATE:
+ /* activate device: */
+ variax_activate_async(variax, 1);
+ variax->startup_progress = VARIAX_STARTUP_SETUP;
+ schedule_delayed_work(&line6->startup_work,
+ msecs_to_jiffies(VARIAX_STARTUP_DELAY4));
+ break;
+ case VARIAX_STARTUP_SETUP:
+ /* ALSA audio interface: */
+ snd_card_register(variax->line6.card);
+ break;
+ }
}
/*
@@ -175,7 +113,7 @@
*/
static void line6_variax_process_message(struct usb_line6 *line6)
{
- struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
+ struct usb_line6_variax *variax = line6_to_variax(line6);
const unsigned char *buf = variax->line6.buffer_message;
switch (buf[0]) {
@@ -186,11 +124,19 @@
case LINE6_SYSEX_BEGIN:
if (memcmp(buf + 1, variax_init_version + 1,
sizeof(variax_init_version) - 1) == 0) {
- variax_startup3(variax);
+ if (variax->startup_progress >= VARIAX_STARTUP_ACTIVATE)
+ break;
+ variax->startup_progress = VARIAX_STARTUP_ACTIVATE;
+ cancel_delayed_work(&line6->startup_work);
+ schedule_delayed_work(&line6->startup_work,
+ msecs_to_jiffies(VARIAX_STARTUP_DELAY3));
} else if (memcmp(buf + 1, variax_init_done + 1,
sizeof(variax_init_done) - 1) == 0) {
/* notify of complete initialization: */
- variax_startup4(&variax->startup_timer2);
+ if (variax->startup_progress >= VARIAX_STARTUP_SETUP)
+ break;
+ cancel_delayed_work(&line6->startup_work);
+ schedule_delayed_work(&line6->startup_work, 0);
}
break;
}
@@ -201,11 +147,7 @@
*/
static void line6_variax_disconnect(struct usb_line6 *line6)
{
- struct usb_line6_variax *variax = (struct usb_line6_variax *)line6;
-
- del_timer(&variax->startup_timer1);
- del_timer(&variax->startup_timer2);
- cancel_work_sync(&variax->startup_work);
+ struct usb_line6_variax *variax = line6_to_variax(line6);
kfree(variax->buffer_activate);
}
@@ -216,15 +158,12 @@
static int variax_init(struct usb_line6 *line6,
const struct usb_device_id *id)
{
- struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
+ struct usb_line6_variax *variax = line6_to_variax(line6);
int err;
line6->process_message = line6_variax_process_message;
line6->disconnect = line6_variax_disconnect;
-
- timer_setup(&variax->startup_timer1, NULL, 0);
- timer_setup(&variax->startup_timer2, NULL, 0);
- INIT_WORK(&variax->startup_work, variax_startup6);
+ line6->startup = variax_startup;
/* initialize USB buffers: */
variax->buffer_activate = kmemdup(variax_activate,
@@ -239,7 +178,8 @@
return err;
/* initiate startup procedure: */
- variax_startup1(variax);
+ schedule_delayed_work(&line6->startup_work,
+ msecs_to_jiffies(VARIAX_STARTUP_DELAY1));
return 0;
}
@@ -304,5 +244,5 @@
module_usb_driver(variax_driver);
-MODULE_DESCRIPTION("Vairax Workbench USB driver");
+MODULE_DESCRIPTION("Variax Workbench USB driver");
MODULE_LICENSE("GPL");