From: Wang Xingchao <xingchao.wang@linux.intel.com>
To: tiwai@suse.de
Cc: alsa-devel@alsa-project.org, jocelyn.li@intel.com,
mengdong.lin@intel.com, intel-gfx@lists.freedesktop.org,
Wang Xingchao <xingchao.wang@linux.intel.com>,
xingchao.wang@intel.com, liam.r.girdwood@intel.com,
david.henningsson@canonical.com
Subject: [PATCH 4/4 V2] ALSA: hda - Continue probe in work context to avoid request_module deadlock
Date: Thu, 23 May 2013 09:51:07 +0800 [thread overview]
Message-ID: <1369273867-2067-1-git-send-email-xingchao.wang@linux.intel.com> (raw)
There's deadlock when request_module(i915) in azx_probe.
It looks like:
device_lock(audio pci device) -> azx_probe -> module_request
(or symbol_request) -> modprobe (userspace) -> i915 init ->
drm_pci_init -> pci_register_driver -> bus_add_driver -> driver_attach ->
which in turn tries all locks on pci bus, and when it tries the one on the
audio device, it will deadlock.
This patch introduce a work to store remaining probe stuff, and let
request_module run in safe work context.
Signed-off-by: Wang Xingchao <xingchao.wang@linux.intel.com>
---
sound/pci/hda/hda_i915.c | 13 ++++--
sound/pci/hda/hda_intel.c | 105 +++++++++++++++++++++++++++-------------------
2 files changed, 71 insertions(+), 47 deletions(-)
diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c
index 76c13d5..7547b20 100644
--- a/sound/pci/hda/hda_i915.c
+++ b/sound/pci/hda/hda_i915.c
@@ -42,13 +42,18 @@ int hda_i915_init(void)
{
int err = 0;
- get_power = symbol_request(i915_request_power_well);
+ get_power = symbol_get(i915_request_power_well);
if (!get_power) {
- snd_printk(KERN_WARNING "hda-i915: get_power symbol get fail\n");
- return -ENODEV;
+ request_module("i915");
+ get_power = symbol_get(i915_request_power_well);
+ if (!get_power) {
+ snd_printk(KERN_WARNING "hda-i915: get_power symbol get fail\n");
+ return -ENODEV;
+ }
+ snd_printdd("hda-i915: get_power symbol get successful\n");
}
- put_power = symbol_request(i915_release_power_well);
+ put_power = symbol_get(i915_release_power_well);
if (!put_power) {
symbol_put(i915_request_power_well);
get_power = NULL;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index f20a88c..1bc7c3b 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -76,6 +76,7 @@ static int probe_only[SNDRV_CARDS];
static int jackpoll_ms[SNDRV_CARDS];
static bool single_cmd;
static int enable_msi = -1;
+static int dev;
#ifdef CONFIG_SND_HDA_PATCH_LOADER
static char *patch[SNDRV_CARDS];
#endif
@@ -542,6 +543,8 @@ struct azx {
/* for pending irqs */
struct work_struct irq_pending_work;
+ struct delayed_work probe_work;
+
/* reboot notifier (for mysterious hangup problem at power-down) */
struct notifier_block reboot_notifier;
@@ -3670,58 +3673,22 @@ static void azx_firmware_cb(const struct firmware *fw, void *context)
}
#endif
-static int azx_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static void azx_probe_work(struct work_struct *work)
{
- static int dev;
- struct snd_card *card;
- struct azx *chip;
+ struct azx *chip =
+ container_of(work, struct azx, probe_work.work);
+ struct snd_card *card = chip->card;
+ struct pci_dev *pci = chip->pci;
bool probe_now;
int err;
- if (dev >= SNDRV_CARDS)
- return -ENODEV;
- if (!enable[dev]) {
- dev++;
- return -ENOENT;
- }
-
- err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
- if (err < 0) {
- snd_printk(KERN_ERR "hda-intel: Error creating card!\n");
- return err;
- }
-
- snd_card_set_dev(card, &pci->dev);
-
- err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
- if (err < 0)
- goto out_free;
- card->private_data = chip;
-
- pci_set_drvdata(pci, card);
-
- err = register_vga_switcheroo(chip);
- if (err < 0) {
- snd_printk(KERN_ERR SFX
- "%s: Error registering VGA-switcheroo client\n", pci_name(pci));
- goto out_free;
- }
-
- if (check_hdmi_disabled(pci)) {
- snd_printk(KERN_INFO SFX "%s: VGA controller is disabled\n",
- pci_name(pci));
- snd_printk(KERN_INFO SFX "%s: Delaying initialization\n", pci_name(pci));
- chip->disabled = true;
- }
-
/* Request power well for Haswell HDA controller and codec */
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
#ifdef CONFIG_SND_HDA_I915
err = hda_i915_init();
if (err < 0) {
snd_printk(KERN_ERR SFX "Error request power-well from i915\n");
- return err;
+ goto out_free;
}
hda_display_power(true);
#else
@@ -3760,7 +3727,7 @@ static int azx_probe(struct pci_dev *pci,
dev++;
complete_all(&chip->probe_wait);
- return 0;
+ return;
out_free_power:
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
hda_display_power(false);
@@ -3769,6 +3736,58 @@ out_free_power:
out_free:
snd_card_free(card);
pci_set_drvdata(pci, NULL);
+}
+
+static int azx_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ struct snd_card *card;
+ struct azx *chip;
+ int err;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+ if (err < 0) {
+ snd_printk(KERN_ERR "hda-intel: Error creating card!\n");
+ return err;
+ }
+
+ snd_card_set_dev(card, &pci->dev);
+
+ err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
+ if (err < 0)
+ goto out_free;
+ card->private_data = chip;
+
+ pci_set_drvdata(pci, card);
+
+ err = register_vga_switcheroo(chip);
+ if (err < 0) {
+ snd_printk(KERN_ERR SFX
+ "%s: Error registering VGA-switcheroo client\n", pci_name(pci));
+ goto out_free;
+ }
+
+ if (check_hdmi_disabled(pci)) {
+ snd_printk(KERN_INFO SFX "%s: VGA controller is disabled\n",
+ pci_name(pci));
+ snd_printk(KERN_INFO SFX "%s: Delaying initialization\n", pci_name(pci));
+ chip->disabled = true;
+ }
+
+ /* continue probing in work context as may trigger request module */
+ INIT_DELAYED_WORK(&chip->probe_work, azx_probe_work);
+ schedule_delayed_work(&chip->probe_work, 0);
+ return 0;
+out_free:
+ snd_card_free(card);
+ pci_set_drvdata(pci, NULL);
return err;
}
--
1.8.1.2
next reply other threads:[~2013-05-23 1:51 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-23 1:51 Wang Xingchao [this message]
2013-05-23 6:49 ` [PATCH 4/4 V2] ALSA: hda - Continue probe in work context to avoid request_module deadlock Takashi Iwai
2013-05-23 10:19 ` Wang, Xingchao
2013-05-23 10:26 ` Takashi Iwai
2013-05-23 10:29 ` Wang, Xingchao
2013-05-23 17:41 ` David Henningsson
2013-05-24 8:48 ` 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=1369273867-2067-1-git-send-email-xingchao.wang@linux.intel.com \
--to=xingchao.wang@linux.intel.com \
--cc=alsa-devel@alsa-project.org \
--cc=david.henningsson@canonical.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=jocelyn.li@intel.com \
--cc=liam.r.girdwood@intel.com \
--cc=mengdong.lin@intel.com \
--cc=tiwai@suse.de \
--cc=xingchao.wang@intel.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox