Commit aad730d0 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Always do delayed probes for HD-audio devices

HD-audio devices tend to take long time for finishing the whole
probing procedure.  In this patch, the time-consuming part of the
probing procedure, the codec probe and the rest initializations, are
moved in the work, so that they can be done asynchronously in parallel
with probes of other devices.

Since we already have this mechanism in the driver code for the
firmware and i915 request_symbol() stuff, we just need to enable it
always; the resultant patch even reduces more lines, which is an
additional bonus.

Credit goes to David Henningsson, who suggested this workaround.
Reported-by: default avatarMengdong Lin <mengdong.lin@intel.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent b95ff8e6
...@@ -543,9 +543,7 @@ struct azx { ...@@ -543,9 +543,7 @@ struct azx {
/* for pending irqs */ /* for pending irqs */
struct work_struct irq_pending_work; struct work_struct irq_pending_work;
#ifdef CONFIG_SND_HDA_I915
struct work_struct probe_work; struct work_struct probe_work;
#endif
/* reboot notifier (for mysterious hangup problem at power-down) */ /* reboot notifier (for mysterious hangup problem at power-down) */
struct notifier_block reboot_notifier; struct notifier_block reboot_notifier;
...@@ -3500,12 +3498,10 @@ static void azx_check_snoop_available(struct azx *chip) ...@@ -3500,12 +3498,10 @@ static void azx_check_snoop_available(struct azx *chip)
} }
} }
#ifdef CONFIG_SND_HDA_I915
static void azx_probe_work(struct work_struct *work) static void azx_probe_work(struct work_struct *work)
{ {
azx_probe_continue(container_of(work, struct azx, probe_work)); azx_probe_continue(container_of(work, struct azx, probe_work));
} }
#endif
/* /*
* constructor * constructor
...@@ -3582,10 +3578,8 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, ...@@ -3582,10 +3578,8 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
return err; return err;
} }
#ifdef CONFIG_SND_HDA_I915
/* continue probing in work context as may trigger request module */ /* continue probing in work context as may trigger request module */
INIT_WORK(&chip->probe_work, azx_probe_work); INIT_WORK(&chip->probe_work, azx_probe_work);
#endif
*rchip = chip; *rchip = chip;
...@@ -3805,7 +3799,7 @@ static int azx_probe(struct pci_dev *pci, ...@@ -3805,7 +3799,7 @@ static int azx_probe(struct pci_dev *pci,
static int dev; static int dev;
struct snd_card *card; struct snd_card *card;
struct azx *chip; struct azx *chip;
bool probe_now; bool schedule_probe;
int err; int err;
if (dev >= SNDRV_CARDS) if (dev >= SNDRV_CARDS)
...@@ -3844,7 +3838,7 @@ static int azx_probe(struct pci_dev *pci, ...@@ -3844,7 +3838,7 @@ static int azx_probe(struct pci_dev *pci,
chip->disabled = true; chip->disabled = true;
} }
probe_now = !chip->disabled; schedule_probe = !chip->disabled;
#ifdef CONFIG_SND_HDA_PATCH_LOADER #ifdef CONFIG_SND_HDA_PATCH_LOADER
if (patch[dev] && *patch[dev]) { if (patch[dev] && *patch[dev]) {
...@@ -3855,25 +3849,17 @@ static int azx_probe(struct pci_dev *pci, ...@@ -3855,25 +3849,17 @@ static int azx_probe(struct pci_dev *pci,
azx_firmware_cb); azx_firmware_cb);
if (err < 0) if (err < 0)
goto out_free; goto out_free;
probe_now = false; /* continued in azx_firmware_cb() */ schedule_probe = false; /* continued in azx_firmware_cb() */
} }
#endif /* CONFIG_SND_HDA_PATCH_LOADER */ #endif /* CONFIG_SND_HDA_PATCH_LOADER */
/* continue probing in work context, avoid request_module deadlock */ #ifndef CONFIG_SND_HDA_I915
if (probe_now && (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)) { if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
#ifdef CONFIG_SND_HDA_I915
probe_now = false;
schedule_work(&chip->probe_work);
#else
snd_printk(KERN_ERR SFX "Haswell must build in CONFIG_SND_HDA_I915\n"); snd_printk(KERN_ERR SFX "Haswell must build in CONFIG_SND_HDA_I915\n");
#endif #endif
}
if (probe_now) { if (schedule_probe)
err = azx_probe_continue(chip); schedule_work(&chip->probe_work);
if (err < 0)
goto out_free;
}
dev++; dev++;
if (chip->disabled) if (chip->disabled)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment