codec->bus = bus;
        codec->addr = addr;
        codec->type = HDA_DEV_CORE;
+       mutex_init(&codec->widget_lock);
        pm_runtime_set_active(&codec->dev);
        pm_runtime_get_noresume(&codec->dev);
        atomic_set(&codec->in_pm, 0);
        err = device_add(&codec->dev);
        if (err < 0)
                return err;
+       mutex_lock(&codec->widget_lock);
        err = hda_widget_sysfs_init(codec);
+       mutex_unlock(&codec->widget_lock);
        if (err < 0) {
                device_del(&codec->dev);
                return err;
 void snd_hdac_device_unregister(struct hdac_device *codec)
 {
        if (device_is_registered(&codec->dev)) {
+               mutex_lock(&codec->widget_lock);
                hda_widget_sysfs_exit(codec);
+               mutex_unlock(&codec->widget_lock);
                device_del(&codec->dev);
                snd_hdac_bus_remove_device(codec->bus, codec);
        }
        }
 
        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;
        }
 
        return 0;
 }
 
+/* call with codec->widget_lock held */
 int hda_widget_sysfs_init(struct hdac_device *codec)
 {
        int err;
        return 0;
 }
 
+/* call with codec->widget_lock held */
 void hda_widget_sysfs_exit(struct hdac_device *codec)
 {
        widget_tree_free(codec);
 }
 
+/* call with codec->widget_lock held */
 int hda_widget_sysfs_reinit(struct hdac_device *codec,
                            hda_nid_t start_nid, int num_nodes)
 {