[alsa-devel] ESI Juli@ crash with external clock switch - patch

Pavel Hofman pavel.hofman at ivitera.com
Thu Jan 15 22:15:46 CET 2015


Dne 12.1.2015 v 16:43 Takashi Iwai napsal(a):
> At Mon, 12 Jan 2015 09:34:52 +0100,
> Pavel Hofman wrote:
>>
>>
>> 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.

Hi,

Thanks a lot, the patch seems to run fine. Only ak4114_init_regs has to 
be called every samplerate change, otherwise the receiver does not 
re-run the samplerate detection and its register with detected 
samplerate does not update its value.

The following patch seems to run ok:

diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
index 52f02a6..796834b 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 c7f5633..6d643b7 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -152,10 +152,12 @@ static void ak4114_init_regs(struct ak4114 *chip)

  void snd_ak4114_reinit(struct ak4114 *chip)
  {
+       ak4114_init_regs(chip);
+       if (chip->in_workq)
+               return;
         chip->init = 1;
         mb();
-       flush_delayed_work(&chip->work);
-       ak4114_init_regs(chip);
+       cancel_delayed_work_sync(&chip->work);
         /* bring up statistics / event queing */
         chip->init = 0;
         if (chip->kctls[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);


>
>>> 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.

I am not sure users would want/need to disable a feature which detects 
incoming samplerate. IMO if the work thread is running only in the 
external clock mode, nothing more is needed.

Thanks a lot and regards,

Pavel.


More information about the Alsa-devel mailing list