diff options
Diffstat (limited to 'sound/hda')
-rw-r--r-- | sound/hda/hdac_controller.c | 7 | ||||
-rw-r--r-- | sound/hda/hdac_device.c | 29 | ||||
-rw-r--r-- | sound/hda/hdac_sysfs.c | 2 |
3 files changed, 21 insertions, 17 deletions
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index b02f74528b66..3b0110545070 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -79,6 +79,8 @@ void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus) snd_hdac_chip_writew(bus, RINTCNT, 1); /* enable rirb dma and response irq */ snd_hdac_chip_writeb(bus, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN); + /* Accept unsolicited responses */ + snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL); spin_unlock_irq(&bus->reg_lock); } EXPORT_SYMBOL_GPL(snd_hdac_bus_init_cmd_io); @@ -241,6 +243,8 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, for (loopcounter = 0;; loopcounter++) { spin_lock_irq(&bus->reg_lock); + if (bus->polling_mode) + snd_hdac_bus_update_rirb(bus); if (!bus->rirb.cmds[addr]) { if (res) *res = bus->rirb.res[addr]; /* the last value */ @@ -415,9 +419,6 @@ int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset) return -EBUSY; } - /* Accept unsolicited responses */ - snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL); - /* detect codecs */ if (!bus->codec_mask) { bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index 6907dbefd08c..b26cc93e7e10 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c @@ -90,7 +90,7 @@ int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus, fg = codec->afg ? codec->afg : codec->mfg; - err = snd_hdac_refresh_widgets(codec, false); + err = snd_hdac_refresh_widgets(codec); if (err < 0) goto error; @@ -395,32 +395,35 @@ static void setup_fg_nodes(struct hdac_device *codec) /** * snd_hdac_refresh_widgets - Reset the widget start/end nodes * @codec: the codec object - * @sysfs: re-initialize sysfs tree, too */ -int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs) +int snd_hdac_refresh_widgets(struct hdac_device *codec) { hda_nid_t start_nid; - int nums, err; + int nums, err = 0; + /* + * Serialize against multiple threads trying to update the sysfs + * widgets array. + */ + mutex_lock(&codec->widget_lock); nums = snd_hdac_get_sub_nodes(codec, codec->afg, &start_nid); if (!start_nid || nums <= 0 || nums >= 0xff) { dev_err(&codec->dev, "cannot read sub nodes for FG 0x%02x\n", codec->afg); - return -EINVAL; + err = -EINVAL; + goto unlock; } - if (sysfs) { - mutex_lock(&codec->widget_lock); - err = hda_widget_sysfs_reinit(codec, start_nid, nums); - mutex_unlock(&codec->widget_lock); - if (err < 0) - return err; - } + err = hda_widget_sysfs_reinit(codec, start_nid, nums); + if (err < 0) + goto unlock; codec->num_nodes = nums; codec->start_nid = start_nid; codec->end_nid = start_nid + nums; - return 0; +unlock: + mutex_unlock(&codec->widget_lock); + return err; } EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets); diff --git a/sound/hda/hdac_sysfs.c b/sound/hda/hdac_sysfs.c index 909d5ef1179c..e56e83325903 100644 --- a/sound/hda/hdac_sysfs.c +++ b/sound/hda/hdac_sysfs.c @@ -428,7 +428,7 @@ int hda_widget_sysfs_reinit(struct hdac_device *codec, int i; if (!codec->widgets) - return hda_widget_sysfs_init(codec); + return 0; tree = kmemdup(codec->widgets, sizeof(*tree), GFP_KERNEL); if (!tree) |