All of lore.kernel.org
 help / color / mirror / Atom feed
From: b_lkasam@codeaurora.org
To: Takashi Iwai <tiwai@suse.de>
Cc: alsa-devel@alsa-project.org
Subject: Re: ALSA sound core device deinit crash
Date: Mon, 11 Jul 2016 12:15:20 +0530	[thread overview]
Message-ID: <42e44fd3c5bd0881dd36c79c7c00aa51@codeaurora.org> (raw)
In-Reply-To: <s5heg74llpq.wl-tiwai@suse.de>

On 2016-07-08 11:23, Takashi Iwai wrote:
> (Please don't drop Cc to ML)
> 
> On Fri, 08 Jul 2016 07:35:37 +0200,
> b_lkasam@codeaurora.org wrote:
>> 
>> On 2016-07-08 10:58, Takashi Iwai wrote:
>> > On Fri, 08 Jul 2016 07:19:05 +0200,
>> > b_lkasam@codeaurora.org wrote:
>> >>
>> >> Hi Alsa team,
>> >> There is kernel crash observed when soundcard register failure case as
>> >> below ->
>> >>
>> >> diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c old mode
>> >> 100644 new mode 100755 index 0495890..60a1eb0
>> >> --- a/sound/soc/soc-core.c
>> >> +++ b/sound/soc/soc-core.c
>> >> @@ -1382,6 +1382,7 @@ static int soc_probe_link_dais(struct
>> >> snd_soc_card *card, int num, int order)
>> >> /* do machine specific initialization */ if (dai_link->init) { ret =
>> >> dai_link->init(rtd);
>> >> + ret = -ENODEV; //  -> we can force error here to reproduce crash
>> >> easily.
>> >> if (ret < 0) {
>> >> dev_err(card->dev, "ASoC: failed to init %s: %d\n", dai_link->name,
>> >> ret);
>> >>
>> >> If sound card fails at initialize at above, it is crashing in
>> >> pcm_chmap_ctl_private_free().
>> >>
>> >> <1>[   40.646642] [01-01-2016 00:07:16 CPU:0x3] Unable to handle
>> >> kernel
>> >> paging request at virtual address ffffffc0da644b68
>> >> <1>[   40.646664] [01-01-2016 00:07:16 CPU:0x3] pgd = ffffffc001d28000
>> >> <1>[   40.646673] [01-01-2016 00:07:16 CPU:0x3] [ffffffc0da644b68]
>> >> *pgd=00000000857fc003, *pud=00000000857fc003, *pmd=000000017ddd8003,
>> >> *pte=00c000015a644793
>> >> <0>[   40.646697] [01-01-2016 00:07:16 CPU:0x3] Internal error: Oops:
>> >> 9600004f [#1] PREEMPT SMP
>> >> <6>[   40.646708] [01-01-2016 00:07:16 CPU:0x3] Modules linked in:
>> >> brcm_bt_drv fm_drv brcm_hci_ldisc texfat(PO)
>> >> <6>[   40.646735] [01-01-2016 00:07:16 CPU:0x3] CPU: 3 PID: 299 Comm:
>> >> kworker/u8:8 Tainted: P           O   3.18.24-g41b2dda2-00002-gbe25a74
>> >> #1
>> >> <6>[   40.646744] [01-01-2016 00:07:16 CPU:0x3] Hardware name:
>> >> Qualcomm
>> >> Technologies, Inc. MSM 8996 v3.x + PMI8996 MTP (DT)
>> >> <6>[   40.646763] [01-01-2016 00:07:16 CPU:0x3] Workqueue: deferwq
>> >> deferred_probe_work_func
>> >> <6>[   40.646773] [01-01-2016 00:07:16 CPU:0x3] task: ffffffc0e951c880
>> >> ti: ffffffc03368c000 task.ti: ffffffc03368c000
>> >> <6>[   40.646787] [01-01-2016 00:07:16 CPU:0x3] PC is at
>> >> pcm_chmap_ctl_private_free+0x1c/0x2c
>> >> <6>[   40.646798] [01-01-2016 00:07:16 CPU:0x3] LR is at
>> >> snd_ctl_free_one+0x20/0x34
>> >>
>> >>
>> >> FIX:
>> >>
>> >> Can you look at the change below and share your comments on this?
>> >> diff --git a/sound/core/device.c b/sound/core/device.c old mode 100644
>> >> new mode 100755 index 41bec30..eaffde1
>> >> --- a/sound/core/device.c
>> >> +++ b/sound/core/device.c
>> >> @@ -219,6 +219,7 @@ void snd_device_free_all(struct snd_card *card)
>> >>
>> >>           if (snd_BUG_ON(!card))
>> >>                   return;
>> >> -       list_for_each_entry_safe_reverse(dev, next, &card->devices,
>> >> list)
>> >> +               list_for_each_entry_safe(dev, next, &card->devices,
>> >> list)
>> >>                   __snd_device_free(dev); }
>> >>
>> >>
>> >> Since control sound device has the lowest type value
>> >> (SNDRV_DEV_CONTROL), it will be the first entry linked in the
>> >> card->devices linked list head and will be the last one to be freed.
>> >>
>> >> This issue seems to be resolved by modifying the sequence the sound
>> >> devices in the card->devices list are freed as shown below (from
>> >> “prev”
>> >> direction to “next” direction) but I’m not sure if this is a right
>> >> approach from ALSA perspective.
>> >
>> > This doesn't look correct.  The strange thing is that this error
>> > shouldn't happen no matter which free loop direction is.  The chmap
>> > ctl should have been already removed by the disconnection before
>> > freeing.  It means that either the disconnection isn't done properly
>> > or something else is missing.
>> >
>> > Could you give the full stack trace?  It's important to know which
>> > code path triggers it.
>> >
>> >
>> > thanks,
>> >
>> > Takashi
>> 
>> 
>> Hi Takashi,
>> 
>> Here is full stack trace -->
>> 
>> 
>> [Callstack]
>> : (struct snd_pcm_chmap *)info = 0xFFFFFFC0DA6A5200
>> : (struct snd_pcm *)pcm = 0xFFFFFFC0DA644A80 //part of buddy page,
>> read-only
>> : info->stream = 0
>> : snd_card_free() was called
>> 
>> -012|pcm_chmap_ctl_private_free()
>> //info->pcm->streams[info->stream].chmap_kctl = NULL
>> -013|snd_ctl_free_one()
>> -014|snd_ctl_remove()
>> -015|snd_ctl_dev_free()
>> -016|__snd_device_free()
>> -017|snd_device_free_all()
>> -018|snd_card_do_free(inline)
>> -018|release_card_device()
>> -019|device_release()
>> -020|kobject_cleanup(inline)
>> -020|kobject_release()
>> -021|kobject_put()
>> -022|put_device()
>> -023|snd_card_free_when_closed()
>> -024|snd_card_free()
>> -025|snd_soc_instantiate_card(inline) -> //Here instantiate card
>> failed for some reason, then triggers snd_card_free
>> -025|snd_soc_register_card()
>> -026|msm8996_asoc_machine_probe()
>> -027|platform_drv_probe()
>> -028|really_probe(inline)
>> -028|driver_probe_device()
>> -029|__device_attach()
>> -030|bus_for_each_drv()
>> -031|device_attach()
>> -032|bus_probe_device()
>> -033|deferred_probe_work_func()
>> -034|static_key_count(inline)
>> -034|static_key_false(inline)
>> -034|trace_workqueue_execute_end(inline)
>> -034|process_one_work()
>> -035|worker_thread()
>> -036|kthread()
>> -037|ret_from_fork(asm)
>> ---|end of frame
>> 
>> 
>> -----------------------
>> trigger point in soc-core.c
>> in API snd_soc_instantiate_card(),
>> 
>>         card_probe_error:
>>                  if (card->remove)
>>                         card->remove(card);
>> 
>>                  snd_card_free(card->snd_card); -> this is
>> snd_card_free which internally leads to above function call.
>> ------------------------------------------
> 
> OK, thanks.  So this is the case where it frees before registering,
> and indeed there is a bug in the PCM chmap code.  It's freed at
> disconnection but the disconnect is called only when it was
> registered.
> 
> Below is a quick fix.  Give it a try.
> 
> 
> thanks,
> 
> Takashi
> 
> ---
> diff --git a/sound/core/control.c b/sound/core/control.c
> index 9ff081cd03f4..fb096cb20a80 100644
> --- a/sound/core/control.c
> +++ b/sound/core/control.c
> @@ -160,6 +160,8 @@ void snd_ctl_notify(struct snd_card *card,
> unsigned int mask,
> 
>  	if (snd_BUG_ON(!card || !id))
>  		return;
> +	if (card->shutdown)
> +		return;
>  	read_lock(&card->ctl_files_rwlock);
>  #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
>  	card->mixer_oss_change_count++;
> diff --git a/sound/core/pcm.c b/sound/core/pcm.c
> index 308c9ecf73db..8e980aa678d0 100644
> --- a/sound/core/pcm.c
> +++ b/sound/core/pcm.c
> @@ -849,6 +849,14 @@ int snd_pcm_new_internal(struct snd_card *card,
> const char *id, int device,
>  }
>  EXPORT_SYMBOL(snd_pcm_new_internal);
> 
> +static void free_chmap(struct snd_pcm_str *pstr)
> +{
> +	if (pstr->chmap_kctl) {
> +		snd_ctl_remove(pstr->pcm->card, pstr->chmap_kctl);
> +		pstr->chmap_kctl = NULL;
> +	}
> +}
> +
>  static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
>  {
>  	struct snd_pcm_substream *substream, *substream_next;
> @@ -871,6 +879,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str 
> * pstr)
>  		kfree(setup);
>  	}
>  #endif
> +	free_chmap(pstr);
>  	if (pstr->substream_count)
>  		put_device(&pstr->dev);
>  }
> @@ -1135,10 +1144,7 @@ static int snd_pcm_dev_disconnect(struct
> snd_device *device)
>  	for (cidx = 0; cidx < 2; cidx++) {
>  		if (!pcm->internal)
>  			snd_unregister_device(&pcm->streams[cidx].dev);
> -		if (pcm->streams[cidx].chmap_kctl) {
> -			snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl);
> -			pcm->streams[cidx].chmap_kctl = NULL;
> -		}
> +		free_chmap(&pcm->streams[cidx]);
>  	}
>  	mutex_unlock(&pcm->open_mutex);
>  	mutex_unlock(&register_mutex);


hi Takashi,
Thanks for the patch.

It is working fine after above patch.

thanks
Kasam
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

  reply	other threads:[~2016-07-11  6:45 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-08  5:19 ALSA sound core device deinit crash b_lkasam
2016-07-08  5:28 ` Takashi Iwai
     [not found]   ` <075f5f6f919170ebb646d475a0e36f02@codeaurora.org>
2016-07-08  5:53     ` Takashi Iwai
2016-07-11  6:45       ` b_lkasam [this message]
2016-07-11 12:50         ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=42e44fd3c5bd0881dd36c79c7c00aa51@codeaurora.org \
    --to=b_lkasam@codeaurora.org \
    --cc=alsa-devel@alsa-project.org \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.