Loading sound/drivers/pcsp/pcsp.c +1 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) return -EINVAL; hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE; pcsp_chip.timer.cb_mode = HRTIMER_CB_SOFTIRQ; pcsp_chip.timer.function = pcsp_do_timer; card = snd_card_new(index, id, THIS_MODULE, 0); Loading sound/drivers/pcsp/pcsp_lib.c +4 −33 Original line number Diff line number Diff line Loading @@ -9,7 +9,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <sound/pcm.h> #include <linux/interrupt.h> #include <asm/io.h> #include "pcsp.h" Loading @@ -20,34 +19,8 @@ MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround " #define DMIX_WANTS_S16 1 static void pcsp_start_timer(unsigned long dummy) { hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); } /* * We need the hrtimer_start as a tasklet to avoid * the nasty locking problem. :( * The problem: * - The timer handler is called with the cpu_base->lock * already held by hrtimer code. * - snd_pcm_period_elapsed() takes the * substream->self_group.lock. * So far so good. * But the snd_pcsp_trigger() is called with the * substream->self_group.lock held, and it calls * hrtimer_start(), which takes the cpu_base->lock. * You see the problem. We have the code pathes * which take two locks in a reverse order. This * can deadlock and the lock validator complains. * The only solution I could find was to move the * hrtimer_start() into a tasklet. -stsp */ static DECLARE_TASKLET(pcsp_start_timer_tasklet, pcsp_start_timer, 0); enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) { unsigned long flags; unsigned char timer_cnt, val; int fmt_size, periods_elapsed; u64 ns; Loading @@ -66,9 +39,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) return HRTIMER_RESTART; } /* hrtimer calls us from both hardirq and softirq contexts, * so irqsave :( */ spin_lock_irqsave(&chip->substream_lock, flags); spin_lock_irq(&chip->substream_lock); /* Takashi Iwai says regarding this extra lock: If the irq handler handles some data on the DMA buffer, it should Loading Loading @@ -139,7 +110,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) chip->period_ptr %= buffer_bytes; } spin_unlock_irqrestore(&chip->substream_lock, flags); spin_unlock_irq(&chip->substream_lock); if (!atomic_read(&chip->timer_active)) return HRTIMER_NORESTART; Loading @@ -153,7 +124,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) exit_nr_unlock2: snd_pcm_stream_unlock(substream); exit_nr_unlock1: spin_unlock_irqrestore(&chip->substream_lock, flags); spin_unlock_irq(&chip->substream_lock); return HRTIMER_NORESTART; } Loading @@ -174,7 +145,7 @@ static void pcsp_start_playing(struct snd_pcsp *chip) atomic_set(&chip->timer_active, 1); chip->thalf = 0; tasklet_schedule(&pcsp_start_timer_tasklet); hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); } static void pcsp_stop_playing(struct snd_pcsp *chip) Loading sound/pci/hda/patch_realtek.c +29 −19 Original line number Diff line number Diff line Loading @@ -2981,7 +2981,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */ SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x814e, "ASUS", ALC880_ASUS), SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG), SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), Loading Loading @@ -8757,36 +8757,40 @@ static struct hda_input_mux alc262_HP_D7000_capture_source = { }, }; /* mute/unmute internal speaker according to the hp jack and mute state */ /* mute/unmute internal speaker according to the hp jacks and mute state */ static void alc262_fujitsu_automute(struct hda_codec *codec, int force) { struct alc_spec *spec = codec->spec; unsigned int mute; if (force || !spec->sense_updated) { unsigned int present_int_hp, present_dock_hp; unsigned int present; /* need to execute and sync at first */ snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); present_int_hp = snd_hda_codec_read(codec, 0x14, 0, /* check laptop HP jack */ present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0); snd_hda_codec_read(codec, 0x1B, 0, AC_VERB_SET_PIN_SENSE, 0); present_dock_hp = snd_hda_codec_read(codec, 0x1b, 0, /* need to execute and sync at first */ snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); /* check docking HP jack */ present |= snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_GET_PIN_SENSE, 0); spec->jack_present = (present_int_hp & 0x80000000) != 0; spec->jack_present |= (present_dock_hp & 0x80000000) != 0; if (present & AC_PINSENSE_PRESENCE) spec->jack_present = 1; else spec->jack_present = 0; spec->sense_updated = 1; } if (spec->jack_present) { /* mute internal speaker */ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, HDA_AMP_MUTE, HDA_AMP_MUTE); } else { /* unmute internal speaker if necessary */ /* unmute internal speaker only if both HPs are unplugged and * master switch is on */ if (spec->jack_present) mute = HDA_AMP_MUTE; else mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, HDA_AMP_MUTE, mute); } } /* unsolicited event for HP jack sensing */ static void alc262_fujitsu_unsol_event(struct hda_codec *codec, Loading @@ -8797,6 +8801,11 @@ static void alc262_fujitsu_unsol_event(struct hda_codec *codec, alc262_fujitsu_automute(codec, 1); } static void alc262_fujitsu_init_hook(struct hda_codec *codec) { alc262_fujitsu_automute(codec, 1); } /* bind volumes of both NID 0x0c and 0x0d */ static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = { .ops = &snd_hda_bind_vol, Loading Loading @@ -9570,6 +9579,7 @@ static struct alc_config_preset alc262_presets[] = { .channel_mode = alc262_modes, .input_mux = &alc262_fujitsu_capture_source, .unsol_event = alc262_fujitsu_unsol_event, .init_hook = alc262_fujitsu_init_hook, }, [ALC262_HP_BPC] = { .mixers = { alc262_HP_BPC_mixer }, Loading Loading
sound/drivers/pcsp/pcsp.c +1 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) return -EINVAL; hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE; pcsp_chip.timer.cb_mode = HRTIMER_CB_SOFTIRQ; pcsp_chip.timer.function = pcsp_do_timer; card = snd_card_new(index, id, THIS_MODULE, 0); Loading
sound/drivers/pcsp/pcsp_lib.c +4 −33 Original line number Diff line number Diff line Loading @@ -9,7 +9,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <sound/pcm.h> #include <linux/interrupt.h> #include <asm/io.h> #include "pcsp.h" Loading @@ -20,34 +19,8 @@ MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround " #define DMIX_WANTS_S16 1 static void pcsp_start_timer(unsigned long dummy) { hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); } /* * We need the hrtimer_start as a tasklet to avoid * the nasty locking problem. :( * The problem: * - The timer handler is called with the cpu_base->lock * already held by hrtimer code. * - snd_pcm_period_elapsed() takes the * substream->self_group.lock. * So far so good. * But the snd_pcsp_trigger() is called with the * substream->self_group.lock held, and it calls * hrtimer_start(), which takes the cpu_base->lock. * You see the problem. We have the code pathes * which take two locks in a reverse order. This * can deadlock and the lock validator complains. * The only solution I could find was to move the * hrtimer_start() into a tasklet. -stsp */ static DECLARE_TASKLET(pcsp_start_timer_tasklet, pcsp_start_timer, 0); enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) { unsigned long flags; unsigned char timer_cnt, val; int fmt_size, periods_elapsed; u64 ns; Loading @@ -66,9 +39,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) return HRTIMER_RESTART; } /* hrtimer calls us from both hardirq and softirq contexts, * so irqsave :( */ spin_lock_irqsave(&chip->substream_lock, flags); spin_lock_irq(&chip->substream_lock); /* Takashi Iwai says regarding this extra lock: If the irq handler handles some data on the DMA buffer, it should Loading Loading @@ -139,7 +110,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) chip->period_ptr %= buffer_bytes; } spin_unlock_irqrestore(&chip->substream_lock, flags); spin_unlock_irq(&chip->substream_lock); if (!atomic_read(&chip->timer_active)) return HRTIMER_NORESTART; Loading @@ -153,7 +124,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) exit_nr_unlock2: snd_pcm_stream_unlock(substream); exit_nr_unlock1: spin_unlock_irqrestore(&chip->substream_lock, flags); spin_unlock_irq(&chip->substream_lock); return HRTIMER_NORESTART; } Loading @@ -174,7 +145,7 @@ static void pcsp_start_playing(struct snd_pcsp *chip) atomic_set(&chip->timer_active, 1); chip->thalf = 0; tasklet_schedule(&pcsp_start_timer_tasklet); hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); } static void pcsp_stop_playing(struct snd_pcsp *chip) Loading
sound/pci/hda/patch_realtek.c +29 −19 Original line number Diff line number Diff line Loading @@ -2981,7 +2981,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */ SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x814e, "ASUS", ALC880_ASUS), SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG), SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), Loading Loading @@ -8757,36 +8757,40 @@ static struct hda_input_mux alc262_HP_D7000_capture_source = { }, }; /* mute/unmute internal speaker according to the hp jack and mute state */ /* mute/unmute internal speaker according to the hp jacks and mute state */ static void alc262_fujitsu_automute(struct hda_codec *codec, int force) { struct alc_spec *spec = codec->spec; unsigned int mute; if (force || !spec->sense_updated) { unsigned int present_int_hp, present_dock_hp; unsigned int present; /* need to execute and sync at first */ snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); present_int_hp = snd_hda_codec_read(codec, 0x14, 0, /* check laptop HP jack */ present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0); snd_hda_codec_read(codec, 0x1B, 0, AC_VERB_SET_PIN_SENSE, 0); present_dock_hp = snd_hda_codec_read(codec, 0x1b, 0, /* need to execute and sync at first */ snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); /* check docking HP jack */ present |= snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_GET_PIN_SENSE, 0); spec->jack_present = (present_int_hp & 0x80000000) != 0; spec->jack_present |= (present_dock_hp & 0x80000000) != 0; if (present & AC_PINSENSE_PRESENCE) spec->jack_present = 1; else spec->jack_present = 0; spec->sense_updated = 1; } if (spec->jack_present) { /* mute internal speaker */ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, HDA_AMP_MUTE, HDA_AMP_MUTE); } else { /* unmute internal speaker if necessary */ /* unmute internal speaker only if both HPs are unplugged and * master switch is on */ if (spec->jack_present) mute = HDA_AMP_MUTE; else mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, HDA_AMP_MUTE, mute); } } /* unsolicited event for HP jack sensing */ static void alc262_fujitsu_unsol_event(struct hda_codec *codec, Loading @@ -8797,6 +8801,11 @@ static void alc262_fujitsu_unsol_event(struct hda_codec *codec, alc262_fujitsu_automute(codec, 1); } static void alc262_fujitsu_init_hook(struct hda_codec *codec) { alc262_fujitsu_automute(codec, 1); } /* bind volumes of both NID 0x0c and 0x0d */ static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = { .ops = &snd_hda_bind_vol, Loading Loading @@ -9570,6 +9579,7 @@ static struct alc_config_preset alc262_presets[] = { .channel_mode = alc262_modes, .input_mux = &alc262_fujitsu_capture_source, .unsol_event = alc262_fujitsu_unsol_event, .init_hook = alc262_fujitsu_init_hook, }, [ALC262_HP_BPC] = { .mixers = { alc262_HP_BPC_mixer }, Loading