At Tue, 26 Nov 2013 05:44:43 +0000, Lin, Mengdong wrote:
Hi Takashi,
-----Original Message----- From: Takashi Iwai [mailto:tiwai@suse.de] Sent: Monday, November 25, 2013 6:51 PM
int snd_hda_suspend(struct hda_bus *bus) { struct hda_codec *codec;
unsigned int mask = 0;
list_for_each_entry(codec, &bus->codec_list, list) { cancel_delayed_work_sync(&codec->jackpoll_work);
if (hda_codec_is_power_on(codec))
hda_call_codec_suspend(codec, false);
if (hda_codec_is_power_on(codec)) {
if (codec->epss || bus->num_codecs == 1)
hda_call_codec_suspend(codec, false);
What's the reason for codec->epss check exceptionally?
Check on codec->epss should be removed here. It's better to always parallel if there are multiple codecs. I had thought codec with EPSS support can change power state quickly and so we can tolerate not paralleling.
OK.
else {
mask |= 1 << codec->addr;
queue_work(codec->pm_wq, &codec->pm_work);
}
}
- }
- list_for_each_entry(codec, &bus->codec_list, list) {
if (mask & (1 << codec->addr))
flush_work(&codec->pm_work);
- }
I thought that the recent workqueue is performed asynchronously as default (unless an ordered workqueue is used), so it should be enough to have a single workqueue in the bus, and flush it.
If using the single work queue in the bus, I observe that the codecs are suspended one after one, not in parallel.
You need to increase the max active of the queue via workqueue_set_max_active(). Otherwise it's default to 1 when you created via create_workqueue(). Also, it'd be better with WQ_UNBOUND flag in this case, I guess.
Takashi