1
0
Fork 0

ALSA: line6: variax: Rewrite complex timer & work combo with a delayed work

Variax driver had a very complex and staged startup sequence using
multiple timers and a work.  This patch simplifies the procedure to a
single delayed work.

Now the startup stage consists of:
- VARIAX_STARTUP_VERSIONREQ:
  requesting the version and the message handler raises up to the next
  stage upon receiving the reply.  The request is repeated until a
  reply arrives.
- VARIAX_STARTUP_ACTIVATE:
  does activation, and queue for the next stage.
- VARIAX_STARTUP_SETUP:
  registers the card.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
alistair/sunxi64-5.4-dsi
Takashi Iwai 2019-05-08 15:55:36 +02:00
parent a91c1da77c
commit 6ea53391c0
1 changed files with 35 additions and 93 deletions

View File

@ -26,13 +26,9 @@
Stages of Variax startup procedure Stages of Variax startup procedure
*/ */
enum { enum {
VARIAX_STARTUP_INIT = 1,
VARIAX_STARTUP_VERSIONREQ, VARIAX_STARTUP_VERSIONREQ,
VARIAX_STARTUP_WAIT,
VARIAX_STARTUP_ACTIVATE, VARIAX_STARTUP_ACTIVATE,
VARIAX_STARTUP_WORKQUEUE,
VARIAX_STARTUP_SETUP, VARIAX_STARTUP_SETUP,
VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
}; };
enum { enum {
@ -47,13 +43,6 @@ struct usb_line6_variax {
/* Buffer for activation code */ /* Buffer for activation code */
unsigned char *buffer_activate; 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 */ /* Current progress in startup procedure */
int startup_progress; int startup_progress;
}; };
@ -81,11 +70,6 @@ static const char variax_activate[] = {
0xf7 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) static void variax_activate_async(struct usb_line6_variax *variax, int a)
{ {
variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a; variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
@ -100,74 +84,30 @@ static void variax_activate_async(struct usb_line6_variax *variax, int a)
context). After the last one has finished, the device is ready to use. 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 = (struct usb_line6_variax *)line6;
/* delay startup procedure: */ switch (variax->startup_progress) {
line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1, case VARIAX_STARTUP_VERSIONREQ:
variax_startup2); /* repeat request until getting the response */
} schedule_delayed_work(&line6->startup_work,
msecs_to_jiffies(VARIAX_STARTUP_DELAY1));
static void variax_startup2(struct timer_list *t) /* request firmware version: */
{ line6_version_request_async(line6);
struct usb_line6_variax *variax = from_timer(variax, t, startup_timer1); break;
struct usb_line6 *line6 = &variax->line6; case VARIAX_STARTUP_ACTIVATE:
/* activate device: */
/* schedule another startup procedure until startup is complete: */ variax_activate_async(variax, 1);
if (variax->startup_progress >= VARIAX_STARTUP_LAST) variax->startup_progress = VARIAX_STARTUP_SETUP;
return; schedule_delayed_work(&line6->startup_work,
msecs_to_jiffies(VARIAX_STARTUP_DELAY4));
variax->startup_progress = VARIAX_STARTUP_VERSIONREQ; break;
line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1, case VARIAX_STARTUP_SETUP:
variax_startup2); /* ALSA audio interface: */
snd_card_register(variax->line6.card);
/* request firmware version: */ break;
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);
} }
/* /*
@ -186,11 +126,19 @@ static void line6_variax_process_message(struct usb_line6 *line6)
case LINE6_SYSEX_BEGIN: case LINE6_SYSEX_BEGIN:
if (memcmp(buf + 1, variax_init_version + 1, if (memcmp(buf + 1, variax_init_version + 1,
sizeof(variax_init_version) - 1) == 0) { 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, } else if (memcmp(buf + 1, variax_init_done + 1,
sizeof(variax_init_done) - 1) == 0) { sizeof(variax_init_done) - 1) == 0) {
/* notify of complete initialization: */ /* 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; break;
} }
@ -203,10 +151,6 @@ static void line6_variax_disconnect(struct usb_line6 *line6)
{ {
struct usb_line6_variax *variax = (struct usb_line6_variax *)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);
kfree(variax->buffer_activate); kfree(variax->buffer_activate);
} }
@ -221,10 +165,7 @@ static int variax_init(struct usb_line6 *line6,
line6->process_message = line6_variax_process_message; line6->process_message = line6_variax_process_message;
line6->disconnect = line6_variax_disconnect; line6->disconnect = line6_variax_disconnect;
line6->startup = variax_startup;
timer_setup(&variax->startup_timer1, NULL, 0);
timer_setup(&variax->startup_timer2, NULL, 0);
INIT_WORK(&variax->startup_work, variax_startup6);
/* initialize USB buffers: */ /* initialize USB buffers: */
variax->buffer_activate = kmemdup(variax_activate, variax->buffer_activate = kmemdup(variax_activate,
@ -239,7 +180,8 @@ static int variax_init(struct usb_line6 *line6,
return err; return err;
/* initiate startup procedure: */ /* initiate startup procedure: */
variax_startup1(variax); schedule_delayed_work(&line6->startup_work,
msecs_to_jiffies(VARIAX_STARTUP_DELAY1));
return 0; return 0;
} }