[alsa-devel] ESI Juli@ crash with external clock switch - patch
Takashi Iwai
tiwai at suse.de
Mon Jan 12 16:43:51 CET 2015
At Mon, 12 Jan 2015 09:34:52 +0100,
Pavel Hofman wrote:
>
> On 12.1.2015 09:21, Takashi Iwai wrote:
> > Yeah, restart is necessary only in a certain situation, and is a bug
> > that is done through work itself. This was the cause. I'll prepare
> > fix patches later.
>
> I wish I could help but unfortunately my practical knowledge of kernel
> workqueues is close to zero :-( Of course I will test the patches and
> will extend them for quartet with testing too.
How about the patch below? This is a quick fix for 3.19 (and
stable). More better fixes will follow later once after it's
confirmed to work.
> > The HZ/10 isn't that bad, but the problem is that it's unconditionally
> > running even if user doesn't need/want.
>
> It is useful only for the external clock mode. In fact the detection of
> incoming SPDIF rate is not reliable for internal clock in Juli (while it
> works just fine in Quartet, its FPGA pins configure the SPDIF receiver
> differently). IMO the thread could be running only when clock is
> switched to external.
Yeah, we can do some smart task change in addition to manual on/off.
Maybe it's good to have an enum control for that.
Takashi
--
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
index 52f02a60dba7..796834b7790c 100644
--- a/include/sound/ak4114.h
+++ b/include/sound/ak4114.h
@@ -169,6 +169,7 @@ struct ak4114 {
ak4114_read_t * read;
void * private_data;
unsigned int init: 1;
+ bool in_workq;
spinlock_t lock;
unsigned char regmap[6];
unsigned char txcsb[5];
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index c7f56339415d..0f923809522c 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -152,9 +152,11 @@ static void ak4114_init_regs(struct ak4114 *chip)
void snd_ak4114_reinit(struct ak4114 *chip)
{
+ if (chip->in_workq)
+ return;
chip->init = 1;
mb();
- flush_delayed_work(&chip->work);
+ cancel_delayed_work_sync(&chip->work);
ak4114_init_regs(chip);
/* bring up statistics / event queing */
chip->init = 0;
@@ -612,10 +614,12 @@ static void ak4114_stats(struct work_struct *work)
{
struct ak4114 *chip = container_of(work, struct ak4114, work.work);
- if (!chip->init)
+ chip->in_workq = true;
+ if (!chip->init) {
snd_ak4114_check_rate_and_errors(chip, chip->check_flags);
-
- schedule_delayed_work(&chip->work, HZ / 10);
+ schedule_delayed_work(&chip->work, HZ / 10);
+ }
+ chip->in_workq = false;
}
EXPORT_SYMBOL(snd_ak4114_create);
More information about the Alsa-devel
mailing list