Skip to content

Commit 495000a

Browse files
committed
ALSA: core: Remove debugfs at disconnection
The card-specific debugfs entries are removed at the last stage of card free phase, and it's performed after synchronization of the closes of all opened fds. This works fine for most cases, but it can be potentially problematic for a hotplug device like USB-audio. Due to the nature of snd_card_free_when_closed(), the card free isn't called immediately after the driver removal for a hotplug device, but it's left until the last fd is closed. It implies that the card debugfs entries also remain. Meanwhile, when a new device is inserted before the last close and the very same card slot is assigned, the driver tries to create the card debugfs root again on the very same path. This conflicts with the remaining entry, and results in the kernel warning such as: debugfs: Directory 'card0' with parent 'sound' already present! with the missing debugfs entry afterwards. For avoiding such conflicts, remove debugfs entries at the device disconnection phase instead. The jack kctl debugfs entries get removed in snd_jack_dev_disconnect() instead of each kctl private_free. Fixes: 2d670ea ("ALSA: jack: implement software jack injection via debugfs") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent 1613e60 commit 495000a

File tree

2 files changed

+19
-11
lines changed

2 files changed

+19
-11
lines changed

sound/core/init.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,11 @@ void snd_card_disconnect(struct snd_card *card)
537537
synchronize_irq(card->sync_irq);
538538

539539
snd_info_card_disconnect(card);
540+
#ifdef CONFIG_SND_DEBUG
541+
debugfs_remove(card->debugfs_root);
542+
card->debugfs_root = NULL;
543+
#endif
544+
540545
if (card->registered) {
541546
device_del(&card->card_dev);
542547
card->registered = false;
@@ -586,10 +591,6 @@ static int snd_card_do_free(struct snd_card *card)
586591
dev_warn(card->dev, "unable to free card info\n");
587592
/* Not fatal error */
588593
}
589-
#ifdef CONFIG_SND_DEBUG
590-
debugfs_remove(card->debugfs_root);
591-
card->debugfs_root = NULL;
592-
#endif
593594
if (card->release_completion)
594595
complete(card->release_completion);
595596
if (!card->managed)

sound/core/jack.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,15 @@ static const int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
3737
};
3838
#endif /* CONFIG_SND_JACK_INPUT_DEV */
3939

40+
static void snd_jack_remove_debugfs(struct snd_jack *jack);
41+
4042
static int snd_jack_dev_disconnect(struct snd_device *device)
4143
{
42-
#ifdef CONFIG_SND_JACK_INPUT_DEV
4344
struct snd_jack *jack = device->device_data;
4445

46+
snd_jack_remove_debugfs(jack);
47+
48+
#ifdef CONFIG_SND_JACK_INPUT_DEV
4549
guard(mutex)(&jack->input_dev_lock);
4650
if (!jack->input_dev)
4751
return 0;
@@ -381,10 +385,14 @@ static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
381385
return 0;
382386
}
383387

384-
static void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl)
388+
static void snd_jack_remove_debugfs(struct snd_jack *jack)
385389
{
386-
debugfs_remove(jack_kctl->jack_debugfs_root);
387-
jack_kctl->jack_debugfs_root = NULL;
390+
struct snd_jack_kctl *jack_kctl;
391+
392+
list_for_each_entry(jack_kctl, &jack->kctl_list, list) {
393+
debugfs_remove(jack_kctl->jack_debugfs_root);
394+
jack_kctl->jack_debugfs_root = NULL;
395+
}
388396
}
389397
#else /* CONFIG_SND_JACK_INJECTION_DEBUG */
390398
static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
@@ -393,7 +401,7 @@ static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
393401
return 0;
394402
}
395403

396-
static void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl)
404+
static void snd_jack_remove_debugfs(struct snd_jack *jack)
397405
{
398406
}
399407
#endif /* CONFIG_SND_JACK_INJECTION_DEBUG */
@@ -404,7 +412,6 @@ static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl)
404412

405413
jack_kctl = kctl->private_data;
406414
if (jack_kctl) {
407-
snd_jack_debugfs_clear_inject_node(jack_kctl);
408415
list_del(&jack_kctl->list);
409416
kfree(jack_kctl);
410417
}
@@ -497,8 +504,8 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
497504
.dev_free = snd_jack_dev_free,
498505
#ifdef CONFIG_SND_JACK_INPUT_DEV
499506
.dev_register = snd_jack_dev_register,
500-
.dev_disconnect = snd_jack_dev_disconnect,
501507
#endif /* CONFIG_SND_JACK_INPUT_DEV */
508+
.dev_disconnect = snd_jack_dev_disconnect,
502509
};
503510

504511
if (initial_kctl) {

0 commit comments

Comments
 (0)