From patchwork Thu May 23 01:51:07 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Xingchao X-Patchwork-Id: 2604461 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id C4F3FDF215 for ; Thu, 23 May 2013 02:31:26 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B7184E6325 for ; Wed, 22 May 2013 19:31:26 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga14.intel.com (mga14.intel.com [143.182.124.37]) by gabe.freedesktop.org (Postfix) with ESMTP id 89044E6172 for ; Wed, 22 May 2013 19:18:05 -0700 (PDT) Received: from azsmga002.ch.intel.com ([10.2.17.35]) by azsmga102.ch.intel.com with ESMTP; 22 May 2013 19:18:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.87,725,1363158000"; d="scan'208";a="245450254" Received: from wxc-intel.bj.intel.com ([10.238.144.103]) by AZSMGA002.ch.intel.com with ESMTP; 22 May 2013 19:18:02 -0700 From: Wang Xingchao To: tiwai@suse.de Date: Thu, 23 May 2013 09:51:07 +0800 Message-Id: <1369273867-2067-1-git-send-email-xingchao.wang@linux.intel.com> X-Mailer: git-send-email 1.7.9.5 Cc: alsa-devel@alsa-project.org, jocelyn.li@intel.com, mengdong.lin@intel.com, intel-gfx@lists.freedesktop.org, Wang Xingchao , liam.r.girdwood@intel.com, david.henningsson@canonical.com Subject: [Intel-gfx] [PATCH 4/4 V2] ALSA: hda - Continue probe in work context to avoid request_module deadlock X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org 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 --- 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; }