Re: Adding movable PCIe BARs support in snd_hda_intel

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 2021-03-25 2:58 a.m., Takashi Iwai wrote:
On Wed, 24 Mar 2021 22:43:24 +0100,
Andrey Grodzovsky wrote:

Few comments -

1) Why we don't use snd_power_wait_and_ref in patch 3 in the common
handler ?
Don't we want the PCI rescan sequence to 'wait for' any in flight
taks that might be accessing registers and not only read/write/tlv
accesses ?

Right, we don't need to block all ioctls, but only the ones that may
access the hardware.  So basically the patches 3-5 can be dropped if
we take the patch 6.  The current patch was written on top of the
previous series, that's why it has both.

2) Possible deadlock -
In azx_rescan_prepare - you put the card into SNDRV_CTL_POWER_D3hot
first and then 'wait for' all in flight tasks with the refcount.
The in flight tasks on the other hand, using snd_power_wait_and_ref,
may have already bumped up the refcount and now 'wait for' the card
to go into SNDRV_CTL_POWER_D0 which can't happen since PCI rescan
waits for the refocunt to drop to 0 before proceeding.

Instead of snd_power_wait_and_ref can't we just call snd_power_ref
in common IOCTL before checking for power_state != SNDRV_CTL_POWER_D0 ?
Or is it because you don't want to fail IOCTLs ?

No, this is the intended behavior and should work as-is because
snd_power_wait_and_ref() drops the refcount in the loop before
sleeping.  The inc before the state check is a must for covering the
possible race, and ditto for changing the power_state to D3hot before
syncing.

Ohh, missed the refcount dec in the wait loop... My bad.

On boot the latest patch-set was throwing refcount warnings since
u are not supposed to inc from zerro count and so I fixed
with the attached patch. That way seems to work fine.

Andrey



Takashi

>From 96c05549bb01697b97204dfd51f8f917ab11a178 Mon Sep 17 00:00:00 2001
From: Andrey Grodzovsky <andrey.grodzovsky@xxxxxxx>
Date: Thu, 25 Mar 2021 12:07:38 -0400
Subject: FIX refcount splat

Righ on boot bellow WARN observed

Fix by setting refcount to 1 and also
drop the optimization in snd_power_unref
since I can't rely on atomic refcount_sub_and_test
anymore.

[   41.710577 <    0.000078>] ------------[ cut here ]------------
[   41.710580 <    0.000003>] refcount_t: addition on 0; use-after-free.
[   41.710603 <    0.000023>] WARNING: CPU: 10 PID: 2781 at lib/refcount.c:25 refcount_warn_saturate+0x86/0x110
[   41.710614 <    0.000011>] Modules linked in: snd_hda_codec_hdmi(OE) snd_hda_intel(OE) snd_intel_dspcfg(OE) snd_hda_codec(OE) snd_hda_core(OE) snd_pcm(OE) snd_seq_midi(OE) snd_seq_midi_event(OE) snd_rawmidi(OE) snd_seq(OE) snd_seq_device(OE) snd_timer(OE) snd(OE) input_leds led_class joydev kvm k10temp drm(OE) drm_panel_orientation_quirks(OE) igb i2c_algo_bit pinctrl_amd
[   41.710679 <    0.000065>] CPU: 10 PID: 2781 Comm: alsactl Tainted: G           OE     5.11.0-rc3-pci-bars+ #7
[   41.710685 <    0.000006>] Hardware name: System manufacturer System Product Name/PRIME X470-PRO, BIOS 4406 02/28/2019
[   41.710689 <    0.000004>] RIP: 0010:refcount_warn_saturate+0x86/0x110
[   41.710696 <    0.000007>] Code: dc dd 27 02 01 e8 22 92 9f 00 0f 0b eb d9 80 3d cb dd 27 02 00 75 d0 48 c7 c7 40 f0 d9 83 c6 05 bb dd 27 02 01 e8 02 92 9f 00 <0f> 0b eb b9 80 3d ad dd 27 02 00 75 b0 48 c7 c7 a0 ef d9 83 c6 05
[   41.710701 <    0.000005>] RSP: 0018:ffff888259bcfb98 EFLAGS: 00010286
[   41.710707 <    0.000006>] RAX: 0000000000000000 RBX: 0000000000000002 RCX: 0000000000000000
[   41.710711 <    0.000004>] RDX: 0000000000000027 RSI: 0000000000000004 RDI: ffffed104b379f65
[   41.710715 <    0.000004>] RBP: ffff88816a60ef40 R08: ffffffff822b270e R09: ffffed10df33e014
[   41.710719 <    0.000004>] R10: ffff8886f99f009b R11: ffffed10df33e013 R12: 0000000000000001
[   41.710723 <    0.000004>] R13: 1ffff1104b379f79 R14: ffff88816a60ef40 R15: 0000000000000000
[   41.710728 <    0.000005>] FS:  00007f0e1817e440(0000) GS:ffff8886f9800000(0000) knlGS:0000000000000000
[   41.710732 <    0.000004>] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   41.710736 <    0.000004>] CR2: 00007f0e185f7000 CR3: 00000001532fa000 CR4: 00000000003506e0
[   41.710740 <    0.000004>] Call Trace:
[   41.710744 <    0.000004>]  snd_power_wait_and_ref+0x315/0x320 [snd]
[   41.710768 <    0.000024>]  ? snd_card_new+0x5e0/0x5e0 [snd]
[   41.710790 <    0.000022>]  ? lock_acquire+0xee/0x570
[   41.710797 <    0.000007>]  ? lock_acquire+0xee/0x570
[   41.710804 <    0.000007>]  ? lock_acquired+0xb4/0x5a0
[   41.710810 <    0.000006>]  ? snd_ctl_ioctl+0x240/0xb60 [snd]
[   41.710832 <    0.000022>]  ? snd_ctl_find_id+0x161/0x180 [snd]
[   41.710855 <    0.000023>]  snd_ctl_elem_write+0x1c4/0x350 [snd]
[   41.710878 <    0.000023>]  ? copy_ctl_value_from_user+0x2f0/0x2f0 [snd]
[   41.710901 <    0.000023>]  ? down_write+0x16c/0x2e0
[   41.710907 <    0.000006>]  ? snd_ctl_ioctl+0x240/0xb60 [snd]
[   41.710929 <    0.000022>]  ? rwsem_down_read_slowpath+0x5f0/0x5f0
[   41.710935 <    0.000006>]  ? _copy_from_user+0xa0/0xf0
[   41.710942 <    0.000007>]  snd_ctl_ioctl+0x24e/0xb60 [snd]
[   41.710965 <    0.000023>]  ? snd_ctl_elem_add_user+0x150/0x150 [snd]
[   41.710988 <    0.000023>]  ? selinux_capable+0x20/0x20
[   41.710995 <    0.000007>]  ? kmem_cache_free+0x145/0x390
[   41.711001 <    0.000006>]  ? lockdep_hardirqs_on_prepare+0xe/0x210
[   41.711007 <    0.000006>]  ? blkcg_maybe_throttle_current+0x7f/0x7f0
[   41.711014 <    0.000007>]  ? call_rcu+0x20b/0x3a0
[   41.711024 <    0.000010>]  __x64_sys_ioctl+0xe0/0x120
[   41.711029 <    0.000005>]  ? syscall_trace_enter.isra.0+0xc9/0x270
[   41.711036 <    0.000007>]  do_syscall_64+0x33/0x80
[   41.711042 <    0.000006>]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[   41.711048 <    0.000006>] RIP: 0033:0x7f0e183eb50b

Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@xxxxxxx>
---
 include/sound/core.h      | 4 ++--
 sound/core/init.c         | 3 ++-
 sound/pci/hda/hda_intel.c | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/include/sound/core.h b/include/sound/core.h
index 0b220bfe001b..d5d5053e743e 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -157,8 +157,8 @@ static inline void snd_power_ref(struct snd_card *card)
 
 static inline void snd_power_unref(struct snd_card *card)
 {
-	if (refcount_dec_and_test(&card->power_ref))
-		wake_up(&card->power_ref_sleep);
+	refcount_dec(&card->power_ref);
+	wake_up(&card->power_ref_sleep);
 }
 
 /* init.c */
diff --git a/sound/core/init.c b/sound/core/init.c
index cb0ad0883329..31cd6830557d 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -215,8 +215,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
 	mutex_init(&card->memory_mutex);
 #ifdef CONFIG_PM
 	init_waitqueue_head(&card->power_sleep);
-	refcount_set(&card->power_ref, 0);
 	init_waitqueue_head(&card->power_ref_sleep);
+	refcount_set(&card->power_ref, 1);
 #endif
 	init_waitqueue_head(&card->remove_sleep);
 	card->sync_irq = -1;
@@ -1007,6 +1007,7 @@ int snd_power_wait_and_ref(struct snd_card *card, bool ref)
 	/* fastpath */
 	if (ref)
 		snd_power_ref(card);
+
 	if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0)
 		return 0;
 	init_waitqueue_entry(&wait, current);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index b6d118c2b75b..10189d90416a 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2457,7 +2457,7 @@ static void azx_rescan_prepare(struct pci_dev *pdev)
 		azx_prepare(&pdev->dev);
 		azx_suspend_streams(chip);
 		wait_event(card->power_ref_sleep,
-			   !refcount_read(&card->power_ref));
+			   refcount_read(&card->power_ref) == 1);
 		list_for_each_codec(codec, &chip->bus) {
 			pm_runtime_suspend(hda_codec_dev(codec));
 			pm_runtime_disable(hda_codec_dev(codec));
-- 
2.25.1


[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux