]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.drivers/alsa-post-ga-hda-own-workq
Merge branch 'master' into next
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / alsa-post-ga-hda-own-workq
CommitLineData
2cb7cef9
BS
1From: Takashi Iwai <tiwai@suse.de>
2Subject: ALSA: hda - Use own workqueue
3Patch-mainline: 2.6.29-rc2
4References: bnc#502733
5
6snd-hda-intel driver used schedule_work() fot the delayed DMA pointer
7updates, but this has several potential problems:
8- it may block other eventsd works longer
9- it may deadlock when probing fails and flush_scheduled_work() is
10 called during probe callback (as probe callback itself could be
11 invoked from eventd)
12
13This patch adds an own workq for each driver instance to solve these
14problems.
15
16Signed-off-by: Takashi Iwai <tiwai@suse.de>
17
18---
19 sound/pci/hda/hda_beep.c | 1 -
20 sound/pci/hda/hda_codec.c | 24 ++++++++++++++++++------
21 sound/pci/hda/hda_codec.h | 2 ++
22 sound/pci/hda/hda_intel.c | 6 +++---
23 4 files changed, 23 insertions(+), 10 deletions(-)
24
25--- a/sound/pci/hda/hda_beep.c
26+++ b/sound/pci/hda/hda_beep.c
27@@ -134,7 +134,6 @@
28 struct hda_beep *beep = codec->beep;
29 if (beep) {
30 cancel_work_sync(&beep->beep_work);
31- flush_scheduled_work();
32
33 input_unregister_device(beep->dev);
34 kfree(beep);
35--- a/sound/pci/hda/hda_codec.c
36+++ b/sound/pci/hda/hda_codec.c
37@@ -310,7 +310,7 @@
38 unsol->queue[wp] = res;
39 unsol->queue[wp + 1] = res_ex;
40
41- schedule_work(&unsol->work);
42+ queue_work(bus->workq, &unsol->work);
43
44 return 0;
45 }
46@@ -373,15 +373,17 @@
47
48 if (!bus)
49 return 0;
50- if (bus->unsol) {
51- flush_scheduled_work();
52+ if (bus->workq)
53+ flush_workqueue(bus->workq);
54+ if (bus->unsol)
55 kfree(bus->unsol);
56- }
57 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
58 snd_hda_codec_free(codec);
59 }
60 if (bus->ops.private_free)
61 bus->ops.private_free(bus);
62+ if (bus->workq)
63+ destroy_workqueue(bus->workq);
64 kfree(bus);
65 return 0;
66 }
67@@ -431,6 +433,16 @@
68 mutex_init(&bus->cmd_mutex);
69 INIT_LIST_HEAD(&bus->codec_list);
70
71+ snprintf(bus->workq_name, sizeof(bus->workq_name),
72+ "hd-audio%d", card->number);
73+ bus->workq = create_singlethread_workqueue(bus->workq_name);
74+ if (!bus->workq) {
75+ snd_printk(KERN_ERR "cannot create workqueue %s\n",
76+ bus->workq_name);
77+ kfree(bus);
78+ return -ENOMEM;
79+ }
80+
81 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
82 if (err < 0) {
83 snd_hda_bus_free(bus);
84@@ -564,7 +576,7 @@
85 return;
86 #ifdef CONFIG_SND_HDA_POWER_SAVE
87 cancel_delayed_work(&codec->power_work);
88- flush_scheduled_work();
89+ flush_workqueue(codec->bus->workq);
90 #endif
91 list_del(&codec->list);
92 codec->bus->caddr_tbl[codec->addr] = NULL;
93@@ -2533,7 +2545,7 @@
94 return;
95 if (power_save) {
96 codec->power_transition = 1; /* avoid reentrance */
97- schedule_delayed_work(&codec->power_work,
98+ queue_delayed_work(codec->bus->workq, &codec->power_work,
99 msecs_to_jiffies(power_save * 1000));
100 }
101 }
102--- a/sound/pci/hda/hda_codec.h
103+++ b/sound/pci/hda/hda_codec.h
104@@ -580,6 +580,8 @@
105
106 /* unsolicited event queue */
107 struct hda_bus_unsolicited *unsol;
108+ char workq_name[16];
109+ struct workqueue_struct *workq; /* common workqueue for codecs */
110
111 struct snd_info_entry *proc;
112
113--- a/sound/pci/hda/hda_intel.c
114+++ b/sound/pci/hda/hda_intel.c
115@@ -986,10 +986,11 @@
116 spin_unlock(&chip->reg_lock);
117 snd_pcm_period_elapsed(azx_dev->substream);
118 spin_lock(&chip->reg_lock);
119- } else {
120+ } else if (chip->bus && chip->bus->workq) {
121 /* bogus IRQ, process it later */
122 azx_dev->irq_pending = 1;
123- schedule_work(&chip->irq_pending_work);
124+ queue_work(chip->bus->workq,
125+ &chip->irq_pending_work);
126 }
127 }
128 }
129@@ -1708,7 +1709,6 @@
130 for (i = 0; i < chip->num_streams; i++)
131 chip->azx_dev[i].irq_pending = 0;
132 spin_unlock_irq(&chip->reg_lock);
133- flush_scheduled_work();
134 }
135
136 static struct snd_pcm_ops azx_pcm_ops = {