From 9b12771ad243541ad28e651f40cc9c7905ee32c3 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 4 Feb 2011 12:23:13 +0000 Subject: mach-omap2: mux: world-writable debugfs files Do not create mux debugfs files as world-writable. Signed-off-by: Vasiliy Kulikov Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/mux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 98148b6c36e..6c84659cf84 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -605,7 +605,7 @@ static void __init omap_mux_dbg_create_entry( list_for_each_entry(e, &partition->muxmodes, node) { struct omap_mux *m = &e->mux; - (void)debugfs_create_file(m->muxnames[0], S_IWUGO, mux_dbg_dir, + (void)debugfs_create_file(m->muxnames[0], S_IWUSR, mux_dbg_dir, m, &omap_mux_dbg_signal_fops); } } -- cgit v1.2.3-18-g5258 From f9fbe47cc1487ba1a5f543a315f8a59bc77c1a68 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 4 Feb 2011 12:23:16 +0000 Subject: mach-omap2: pm: world-writable debugfs timer files Don't allow all users to change timer settings. Signed-off-by: Vasiliy Kulikov Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/pm-debug.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 125f56591fb..a5a83b358dd 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -637,14 +637,14 @@ static int __init pm_dbg_init(void) } - (void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUGO, d, + (void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d, &enable_off_mode, &pm_dbg_option_fops); - (void) debugfs_create_file("sleep_while_idle", S_IRUGO | S_IWUGO, d, + (void) debugfs_create_file("sleep_while_idle", S_IRUGO | S_IWUSR, d, &sleep_while_idle, &pm_dbg_option_fops); - (void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUGO, d, + (void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUSR, d, &wakeup_timer_seconds, &pm_dbg_option_fops); (void) debugfs_create_file("wakeup_timer_milliseconds", - S_IRUGO | S_IWUGO, d, &wakeup_timer_milliseconds, + S_IRUGO | S_IWUSR, d, &wakeup_timer_milliseconds, &pm_dbg_option_fops); pm_dbg_init_done = 1; -- cgit v1.2.3-18-g5258 From 1232a185ddd500b61b8dc389ad1a357e6b425548 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 4 Feb 2011 12:23:20 +0000 Subject: mach-omap2: smartreflex: world-writable debugfs voltage files Don't allow everybody to change voltage settings. Signed-off-by: Vasiliy Kulikov Acked-by: Kevin Hilman Acked-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/smartreflex.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index c37e823266d..95ac336fe3f 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -900,7 +900,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) return PTR_ERR(dbg_dir); } - (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUGO, dbg_dir, + (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, dbg_dir, (void *)sr_info, &pm_sr_fops); (void) debugfs_create_x32("errweight", S_IRUGO, dbg_dir, &sr_info->err_weight); @@ -939,7 +939,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) strcpy(name, "volt_"); sprintf(volt_name, "%d", volt_data[i].volt_nominal); strcat(name, volt_name); - (void) debugfs_create_x32(name, S_IRUGO | S_IWUGO, nvalue_dir, + (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir, &(sr_info->nvalue_table[i].nvalue)); } -- cgit v1.2.3-18-g5258 From b66a70d5e9929f3b0df5a7177bba75652d2f4c3e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 9 Feb 2011 18:04:11 +0000 Subject: ASoC: Sync initial widget state with hardware ASoC generally uses the register defaults for everything, but in some cases the hardware will default to enabling some of the DAPM widgets (clocks for example). Ensure that DAPM knows about the actual widget state at initialisation by reading the enable bits after instantiating the widgets so they don't get left enabled needlessly. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-dapm.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 8194f150bab..4df96ec9a81 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1627,6 +1627,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) { struct snd_soc_dapm_widget *w; + unsigned int val; list_for_each_entry(w, &dapm->card->widgets, list) { @@ -1675,6 +1676,18 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) case snd_soc_dapm_post: break; } + + /* Read the initial power state from the device */ + if (w->reg >= 0) { + val = snd_soc_read(w->codec, w->reg); + val &= 1 << w->shift; + if (w->invert) + val = !val; + + if (val) + w->power = 1; + } + w->new = 1; } -- cgit v1.2.3-18-g5258 From 8e6bfb9b1f79e07c18b0ae406c7c678fc54e4d8e Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Thu, 10 Feb 2011 13:24:32 +0100 Subject: ASoC: CX20442: fix wrong reg_cache_default content Content of the CX20442's snd_soc_codec_driver.reg_cache_default pointed area, introduced with my recent NULL pointer dereferece fix (commit f019ee5feb344ff0b22b58df4568676295aae14f), occured wrong after further testing, more thorough than just booting successfully. There are two problems with it: 1) It should read (1 << CX20442_TELOUT) | (1 << CX20442_MIC), not CX20442_TELOUT | CX20442_MIC. 2) While correctly matching actual codec hardware state on boot when fixed per 1), a few more code modifications would still be required to reflect that state not only into register cache, but also force them into DAPM pins state, otherwise an inconsitency occures which may prevent further codec state changes from being applied correctly. As a result, the phone stops ringing after reboot, until someone picks up the handset for the first time. Revert that reg_cache_default content to a working, previous de facto default value of 0, in hope this change can still be accepted as an rc cycle fix. Created and tested against linux-2.6.38-rc4 Signed-off-by: Janusz Krzysztofik Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/codecs/cx20442.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index bb4bf65b9e7..0bb424af956 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -367,7 +367,7 @@ static int cx20442_codec_remove(struct snd_soc_codec *codec) return 0; } -static const u8 cx20442_reg = CX20442_TELOUT | CX20442_MIC; +static const u8 cx20442_reg; static struct snd_soc_codec_driver cx20442_codec_dev = { .probe = cx20442_codec_probe, -- cgit v1.2.3-18-g5258 From 28d639f7bd2559e3d6dc10c0316d19154b28a2a4 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 10 Feb 2011 15:37:13 -0700 Subject: ASoC: WM8903: Fix mic detection register definitions * There is no hysteresis enable field in the current datasheet. * Mic detection threshold field is only 2 bits wide. Signed-off-by: Stephen Warren Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- include/sound/wm8903.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/include/sound/wm8903.h b/include/sound/wm8903.h index b4a0db2307e..1eeebd534f7 100644 --- a/include/sound/wm8903.h +++ b/include/sound/wm8903.h @@ -17,13 +17,9 @@ /* * R6 (0x06) - Mic Bias Control 0 */ -#define WM8903_MICDET_HYST_ENA 0x0080 /* MICDET_HYST_ENA */ -#define WM8903_MICDET_HYST_ENA_MASK 0x0080 /* MICDET_HYST_ENA */ -#define WM8903_MICDET_HYST_ENA_SHIFT 7 /* MICDET_HYST_ENA */ -#define WM8903_MICDET_HYST_ENA_WIDTH 1 /* MICDET_HYST_ENA */ -#define WM8903_MICDET_THR_MASK 0x0070 /* MICDET_THR - [6:4] */ -#define WM8903_MICDET_THR_SHIFT 4 /* MICDET_THR - [6:4] */ -#define WM8903_MICDET_THR_WIDTH 3 /* MICDET_THR - [6:4] */ +#define WM8903_MICDET_THR_MASK 0x0030 /* MICDET_THR - [5:4] */ +#define WM8903_MICDET_THR_SHIFT 4 /* MICDET_THR - [5:4] */ +#define WM8903_MICDET_THR_WIDTH 2 /* MICDET_THR - [5:4] */ #define WM8903_MICSHORT_THR_MASK 0x000C /* MICSHORT_THR - [3:2] */ #define WM8903_MICSHORT_THR_SHIFT 2 /* MICSHORT_THR - [3:2] */ #define WM8903_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [3:2] */ -- cgit v1.2.3-18-g5258 From 3088e3b4963d26d6f6f54987f595b974ed6d48d8 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 10 Feb 2011 15:37:14 -0700 Subject: ASoC: WM8903: Fix mic detection enable logic The mic detection HW should be enabled when either mic or short detection is required, not when only both are required. Signed-off-by: Stephen Warren Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/codecs/wm8903.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 987476a5895..017d99ceb42 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1482,7 +1482,7 @@ int wm8903_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, WM8903_MICDET_EINT | WM8903_MICSHRT_EINT, irq_mask); - if (det && shrt) { + if (det || shrt) { /* Enable mic detection, this may not have been set through * platform data (eg, if the defaults are OK). */ snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, -- cgit v1.2.3-18-g5258 From 173efa09e4c807a2a764509ddd593ad13a44d1df Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Fri, 11 Feb 2011 16:32:11 +0000 Subject: ASoC: WM8994: Improve robustness in some use cases Ensure that on disabling certain registers such as AIF1DAC1L, AIF1DAC1R etc. the AIF1CLK and AIF2CLK remain enabled. Similarly when enabling those registers, AIF1CLK and AIF2CLK will remain disabled. Signed-off-by: Dimitris Papastamos Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/codecs/wm8994.c | 142 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 133 insertions(+), 9 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 37b8aa8a680..bd0cfdd1386 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -107,6 +107,9 @@ struct wm8994_priv { int revision; struct wm8994_pdata *pdata; + + unsigned int aif1clk_enable:1; + unsigned int aif2clk_enable:1; }; static int wm8994_readable(unsigned int reg) @@ -1004,6 +1007,82 @@ static void wm8994_update_class_w(struct snd_soc_codec *codec) } } +static int late_enable_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (wm8994->aif1clk_enable) + snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, + WM8994_AIF1CLK_ENA_MASK, + WM8994_AIF1CLK_ENA); + if (wm8994->aif2clk_enable) + snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, + WM8994_AIF2CLK_ENA_MASK, + WM8994_AIF2CLK_ENA); + break; + } + + return 0; +} + +static int late_disable_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_POST_PMD: + if (wm8994->aif1clk_enable) { + snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, + WM8994_AIF1CLK_ENA_MASK, 0); + wm8994->aif1clk_enable = 0; + } + if (wm8994->aif2clk_enable) { + snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, + WM8994_AIF2CLK_ENA_MASK, 0); + wm8994->aif2clk_enable = 0; + } + break; + } + + return 0; +} + +static int aif1clk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + wm8994->aif1clk_enable = 1; + break; + } + + return 0; +} + +static int aif2clk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + wm8994->aif2clk_enable = 1; + break; + } + + return 0; +} + static const char *hp_mux_text[] = { "Mixer", "DAC", @@ -1272,6 +1351,29 @@ static const struct soc_enum aif2dacr_src_enum = static const struct snd_kcontrol_new aif2dacr_src_mux = SOC_DAPM_ENUM("AIF2DACR Mux", aif2dacr_src_enum); +static const struct snd_soc_dapm_widget wm8994_lateclk_revd_widgets[] = { +SND_SOC_DAPM_SUPPLY("AIF1CLK", SND_SOC_NOPM, 0, 0, aif1clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +SND_SOC_DAPM_SUPPLY("AIF2CLK", SND_SOC_NOPM, 0, 0, aif2clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + +SND_SOC_DAPM_PGA_E("Late DAC1L Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, + late_enable_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_PGA_E("Late DAC1R Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, + late_enable_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_PGA_E("Late DAC2L Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, + late_enable_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_PGA_E("Late DAC2R Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, + late_enable_ev, SND_SOC_DAPM_PRE_PMU), + +SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev) +}; + +static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { +SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0) +}; + static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { SND_SOC_DAPM_INPUT("DMIC1DAT"), SND_SOC_DAPM_INPUT("DMIC2DAT"), @@ -1284,9 +1386,6 @@ SND_SOC_DAPM_SUPPLY("DSP1CLK", WM8994_CLOCKING_1, 3, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("DSP2CLK", WM8994_CLOCKING_1, 2, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("DSPINTCLK", WM8994_CLOCKING_1, 1, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0), - SND_SOC_DAPM_AIF_OUT("AIF1ADC1L", NULL, 0, WM8994_POWER_MANAGEMENT_4, 9, 0), SND_SOC_DAPM_AIF_OUT("AIF1ADC1R", NULL, @@ -1516,14 +1615,12 @@ static const struct snd_soc_dapm_route intercon[] = { { "AIF2ADC Mux", "AIF3DACDAT", "AIF3ADCDAT" }, /* DAC1 inputs */ - { "DAC1L", NULL, "DAC1L Mixer" }, { "DAC1L Mixer", "AIF2 Switch", "AIF2DACL" }, { "DAC1L Mixer", "AIF1.2 Switch", "AIF1DAC2L" }, { "DAC1L Mixer", "AIF1.1 Switch", "AIF1DAC1L" }, { "DAC1L Mixer", "Left Sidetone Switch", "Left Sidetone" }, { "DAC1L Mixer", "Right Sidetone Switch", "Right Sidetone" }, - { "DAC1R", NULL, "DAC1R Mixer" }, { "DAC1R Mixer", "AIF2 Switch", "AIF2DACR" }, { "DAC1R Mixer", "AIF1.2 Switch", "AIF1DAC2R" }, { "DAC1R Mixer", "AIF1.1 Switch", "AIF1DAC1R" }, @@ -1532,7 +1629,6 @@ static const struct snd_soc_dapm_route intercon[] = { /* DAC2/AIF2 outputs */ { "AIF2ADCL", NULL, "AIF2DAC2L Mixer" }, - { "DAC2L", NULL, "AIF2DAC2L Mixer" }, { "AIF2DAC2L Mixer", "AIF2 Switch", "AIF2DACL" }, { "AIF2DAC2L Mixer", "AIF1.2 Switch", "AIF1DAC2L" }, { "AIF2DAC2L Mixer", "AIF1.1 Switch", "AIF1DAC1L" }, @@ -1540,7 +1636,6 @@ static const struct snd_soc_dapm_route intercon[] = { { "AIF2DAC2L Mixer", "Right Sidetone Switch", "Right Sidetone" }, { "AIF2ADCR", NULL, "AIF2DAC2R Mixer" }, - { "DAC2R", NULL, "AIF2DAC2R Mixer" }, { "AIF2DAC2R Mixer", "AIF2 Switch", "AIF2DACR" }, { "AIF2DAC2R Mixer", "AIF1.2 Switch", "AIF1DAC2R" }, { "AIF2DAC2R Mixer", "AIF1.1 Switch", "AIF1DAC1R" }, @@ -1584,6 +1679,24 @@ static const struct snd_soc_dapm_route intercon[] = { { "Right Headphone Mux", "DAC", "DAC1R" }, }; +static const struct snd_soc_dapm_route wm8994_lateclk_revd_intercon[] = { + { "DAC1L", NULL, "Late DAC1L Enable PGA" }, + { "Late DAC1L Enable PGA", NULL, "DAC1L Mixer" }, + { "DAC1R", NULL, "Late DAC1R Enable PGA" }, + { "Late DAC1R Enable PGA", NULL, "DAC1R Mixer" }, + { "DAC2L", NULL, "Late DAC2L Enable PGA" }, + { "Late DAC2L Enable PGA", NULL, "AIF2DAC2L Mixer" }, + { "DAC2R", NULL, "Late DAC2R Enable PGA" }, + { "Late DAC2R Enable PGA", NULL, "AIF2DAC2R Mixer" } +}; + +static const struct snd_soc_dapm_route wm8994_lateclk_intercon[] = { + { "DAC1L", NULL, "DAC1L Mixer" }, + { "DAC1R", NULL, "DAC1R Mixer" }, + { "DAC2L", NULL, "AIF2DAC2L Mixer" }, + { "DAC2R", NULL, "AIF2DAC2R Mixer" }, +}; + static const struct snd_soc_dapm_route wm8994_revd_intercon[] = { { "AIF1DACDAT", NULL, "AIF2DACDAT" }, { "AIF2DACDAT", NULL, "AIF1DACDAT" }, @@ -3125,6 +3238,12 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) case WM8994: snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets, ARRAY_SIZE(wm8994_specific_dapm_widgets)); + if (wm8994->revision < 4) + snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, + ARRAY_SIZE(wm8994_lateclk_revd_widgets)); + else + snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, + ARRAY_SIZE(wm8994_lateclk_widgets)); break; case WM8958: snd_soc_add_controls(codec, wm8958_snd_controls, @@ -3143,10 +3262,15 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) snd_soc_dapm_add_routes(dapm, wm8994_intercon, ARRAY_SIZE(wm8994_intercon)); - if (wm8994->revision < 4) + if (wm8994->revision < 4) { snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon, ARRAY_SIZE(wm8994_revd_intercon)); - + snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon, + ARRAY_SIZE(wm8994_lateclk_revd_intercon)); + } else { + snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon, + ARRAY_SIZE(wm8994_lateclk_intercon)); + } break; case WM8958: snd_soc_dapm_add_routes(dapm, wm8958_intercon, -- cgit v1.2.3-18-g5258 From c52fd021bc027a90a10782c0dcf667ac0135e478 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Fri, 11 Feb 2011 16:32:12 +0000 Subject: ASoC: WM8994: Improve playback robustness On WM8994 revision D and earlier ensure proper playback robustness as some rare use cases can trigger issues. Signed-off-by: Dimitris Papastamos Acked-by: Liam Girdwood Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/codecs/wm8994.c | 59 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index bd0cfdd1386..a60b5dbf015 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1083,6 +1083,17 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, return 0; } +static int dac_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + unsigned int mask = 1 << w->shift; + + snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, + mask, mask); + return 0; +} + static const char *hp_mux_text[] = { "Mixer", "DAC", @@ -1374,6 +1385,24 @@ SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0) }; +static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = { +SND_SOC_DAPM_DAC_E("DAC2L", NULL, SND_SOC_NOPM, 3, 0, + dac_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_DAC_E("DAC2R", NULL, SND_SOC_NOPM, 2, 0, + dac_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_DAC_E("DAC1L", NULL, SND_SOC_NOPM, 1, 0, + dac_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_DAC_E("DAC1R", NULL, SND_SOC_NOPM, 0, 0, + dac_ev, SND_SOC_DAPM_PRE_PMU), +}; + +static const struct snd_soc_dapm_widget wm8994_dac_widgets[] = { +SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0), +SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), +SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0), +SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), +}; + static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { SND_SOC_DAPM_INPUT("DMIC1DAT"), SND_SOC_DAPM_INPUT("DMIC2DAT"), @@ -1471,11 +1500,6 @@ SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), -SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0), -SND_SOC_DAPM_DAC("DAC2R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), -SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0), -SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), - SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), @@ -2627,6 +2651,22 @@ static int wm8994_resume(struct snd_soc_codec *codec) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); int i, ret; + unsigned int val, mask; + + if (wm8994->revision < 4) { + /* force a HW read */ + val = wm8994_reg_read(codec->control_data, + WM8994_POWER_MANAGEMENT_5); + + /* modify the cache only */ + codec->cache_only = 1; + mask = WM8994_DAC1R_ENA | WM8994_DAC1L_ENA | + WM8994_DAC2R_ENA | WM8994_DAC2L_ENA; + val &= mask; + snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, + mask, val); + codec->cache_only = 0; + } /* Restore the registers */ ret = snd_soc_cache_sync(codec); @@ -3238,12 +3278,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) case WM8994: snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets, ARRAY_SIZE(wm8994_specific_dapm_widgets)); - if (wm8994->revision < 4) + if (wm8994->revision < 4) { snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, ARRAY_SIZE(wm8994_lateclk_revd_widgets)); - else + snd_soc_dapm_new_controls(dapm, wm8994_dac_revd_widgets, + ARRAY_SIZE(wm8994_dac_revd_widgets)); + } else { snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, ARRAY_SIZE(wm8994_lateclk_widgets)); + snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets, + ARRAY_SIZE(wm8994_dac_widgets)); + } break; case WM8958: snd_soc_add_controls(codec, wm8958_snd_controls, -- cgit v1.2.3-18-g5258 From 3017358a75917b5ed5ad361c02ba2a7e257d3b2a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 11 Feb 2011 11:42:19 +0000 Subject: ASoC: Ensure supplies are maintained for force enabled widgets If a widget has been force enabled then not only do we need to keep the widget itself enabled, we also need to keep any supplies the widget requires enabled. The user could force all the individual widgets on but this requires too much knowledge of device internals. Signed-off-by: Mark Brown Tested-by: Stephen Warren Acked-by: Liam Girdwood --- sound/soc/soc-dapm.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 4df96ec9a81..25e54230cc6 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -712,7 +712,15 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) !path->connected(path->source, path->sink)) continue; - if (path->sink && path->sink->power_check && + if (!path->sink) + continue; + + if (path->sink->force) { + power = 1; + break; + } + + if (path->sink->power_check && path->sink->power_check(path->sink)) { power = 1; break; -- cgit v1.2.3-18-g5258 From f7bee80945155ad0326916486dabc38428c6cdef Mon Sep 17 00:00:00 2001 From: Krzysztof Wojcik Date: Mon, 14 Feb 2011 10:01:41 +1100 Subject: md: Fix raid1->raid0 takeover Takeover raid1->raid0 not succeded. Kernel message is shown: "md/raid0:md126: too few disks (1 of 2) - aborting!" Problem was that we weren't updating ->raid_disks for that takeover, unlike all the others. Signed-off-by: Krzysztof Wojcik Signed-off-by: NeilBrown --- drivers/md/raid0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 637a96855ed..75671dfee55 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -670,6 +670,7 @@ static void *raid0_takeover_raid1(mddev_t *mddev) mddev->new_layout = 0; mddev->new_chunk_sectors = 128; /* by default set chunk size to 64k */ mddev->delta_disks = 1 - mddev->raid_disks; + mddev->raid_disks = 1; /* make sure it will be not marked as dirty */ mddev->recovery_cp = MaxSector; -- cgit v1.2.3-18-g5258 From eca83258f1d81575576ca553075c641849150f23 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 11 Feb 2011 19:56:42 +0000 Subject: OMAP2420: mailbox: fix IVA vs DSP IRQ numbering The IRQ numbering for the IVA and DSP mailboxes was switched due to the wrong ordering in the OMAP2 mbox list. Switch the ordering so DSP is first and matches all the other SoCs. Tested on OMAP2420/n810. Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/mailbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index 394413dc7de..0a585dfa987 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/arch/arm/mach-omap2/mailbox.c @@ -334,7 +334,7 @@ static struct omap_mbox mbox_iva_info = { .priv = &omap2_mbox_iva_priv, }; -struct omap_mbox *omap2_mboxes[] = { &mbox_iva_info, &mbox_dsp_info, NULL }; +struct omap_mbox *omap2_mboxes[] = { &mbox_dsp_info, &mbox_iva_info, NULL }; #endif #if defined(CONFIG_ARCH_OMAP4) -- cgit v1.2.3-18-g5258 From c03773206bf2249a890c4d420ed32ef500630095 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 11 Feb 2011 19:56:43 +0000 Subject: OMAP2+: mailbox: fix lookups for multiple mailboxes The pointer math in omap_mbox_get() is not quite right, and leads to passing NULL to strcmp() when searching for an mbox that is not first in the list. Convert to using array indexing as is done in all the other functions which walk the mbox list. Tested on OMAP2420/n810, OMAP3630/zoom3, OMAP4430/Blaze Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/mailbox.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 459b319a9fa..49d3208793e 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -322,15 +322,18 @@ static void omap_mbox_fini(struct omap_mbox *mbox) struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) { - struct omap_mbox *mbox; - int ret; + struct omap_mbox *_mbox, *mbox = NULL; + int i, ret; if (!mboxes) return ERR_PTR(-EINVAL); - for (mbox = *mboxes; mbox; mbox++) - if (!strcmp(mbox->name, name)) + for (i = 0; (_mbox = mboxes[i]); i++) { + if (!strcmp(_mbox->name, name)) { + mbox = _mbox; break; + } + } if (!mbox) return ERR_PTR(-ENOENT); -- cgit v1.2.3-18-g5258 From 0f5cd45960173ba5b36727decbb4a241cbd35ef9 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 15 Feb 2011 21:29:32 +0530 Subject: ath9k: Fix ath9k prevents CPU to enter C3 states The DMA latency issue is observed only in Intel pinetrail platforms but in the driver we had a default PM-QOS value of 55. This caused unnecessary power consumption and battery drain in other platforms. Remove the pm-qos thing in the driver code and address the throughput issue in Intel pinetrail platfroms in user space using any one of the scripts in below links: http://www.kernel.org/pub/linux/kernel/people/mcgrof/scripts/cpudmalatency.c http://johannes.sipsolutions.net/files/netlatency.c.txt More details can be found in the following bugzilla link: https://bugzilla.kernel.org/show_bug.cgi?id=27532 This reverts the following commits: 98c316e348bedffa730e6f1e4baeb8a3c3e0f28b 4dc3530df7c0428b41c00399a7ee8c929406d181 10598c124ecabbbfd7522f74de19b8f7d52a1bee Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 6 ------ drivers/net/wireless/ath/ath9k/init.c | 8 -------- drivers/net/wireless/ath/ath9k/main.c | 8 -------- 3 files changed, 22 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 23838e37d45..1a7fa6ea4cf 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -21,7 +21,6 @@ #include #include #include -#include #include "debug.h" #include "common.h" @@ -57,8 +56,6 @@ struct ath_node; #define A_MAX(a, b) ((a) > (b) ? (a) : (b)) -#define ATH9K_PM_QOS_DEFAULT_VALUE 55 - #define TSF_TO_TU(_h,_l) \ ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) @@ -633,8 +630,6 @@ struct ath_softc { struct ath_descdma txsdma; struct ath_ant_comb ant_comb; - - struct pm_qos_request_list pm_qos_req; }; struct ath_wiphy { @@ -666,7 +661,6 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) extern struct ieee80211_ops ath9k_ops; extern int ath9k_modparam_nohwcrypt; extern int led_blink; -extern int ath9k_pm_qos_value; extern bool is_ath9k_unloaded; irqreturn_t ath_isr(int irq, void *dev); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 087a6a95edd..a033d01bf8a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -41,10 +41,6 @@ static int ath9k_btcoex_enable; module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444); MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); -int ath9k_pm_qos_value = ATH9K_PM_QOS_DEFAULT_VALUE; -module_param_named(pmqos, ath9k_pm_qos_value, int, S_IRUSR | S_IRGRP | S_IROTH); -MODULE_PARM_DESC(pmqos, "User specified PM-QOS value"); - bool is_ath9k_unloaded; /* We use the hw_value as an index into our private channel structure */ @@ -762,9 +758,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, ath_init_leds(sc); ath_start_rfkill_poll(sc); - pm_qos_add_request(&sc->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, - PM_QOS_DEFAULT_VALUE); - return 0; error_world: @@ -831,7 +824,6 @@ void ath9k_deinit_device(struct ath_softc *sc) } ieee80211_unregister_hw(hw); - pm_qos_remove_request(&sc->pm_qos_req); ath_rx_cleanup(sc); ath_tx_cleanup(sc); ath9k_deinit_softc(sc); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index da5c64597c1..a09d15f7aa6 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1173,12 +1173,6 @@ static int ath9k_start(struct ieee80211_hw *hw) ath9k_btcoex_timer_resume(sc); } - /* User has the option to provide pm-qos value as a module - * parameter rather than using the default value of - * 'ATH9K_PM_QOS_DEFAULT_VALUE'. - */ - pm_qos_update_request(&sc->pm_qos_req, ath9k_pm_qos_value); - if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en) common->bus_ops->extn_synch_en(common); @@ -1345,8 +1339,6 @@ static void ath9k_stop(struct ieee80211_hw *hw) sc->sc_flags |= SC_OP_INVALID; - pm_qos_update_request(&sc->pm_qos_req, PM_QOS_DEFAULT_VALUE); - mutex_unlock(&sc->mutex); ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n"); -- cgit v1.2.3-18-g5258 From cbe6ef1d2622e08e272600b3cb6040bed60f0450 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 16 Feb 2011 13:58:38 +1100 Subject: md: don't set_capacity before array is active. If the desired size of an array is set (via sysfs) before the array is active (which is the normal sequence), we currrently call set_capacity immediately. This means that a subsequent 'open' (as can be caused by some udev-triggers program) will notice the new size and try to probe for partitions. However as the array isn't quite ready yet the read will fail. Then when the array is read, as the size doesn't change again we don't try to re-probe. So when setting array size via sysfs, only call set_capacity if the array is already active. Signed-off-by: NeilBrown --- drivers/md/md.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 0cc30ecda4c..6818ff4aa8d 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4138,10 +4138,10 @@ array_size_store(mddev_t *mddev, const char *buf, size_t len) } mddev->array_sectors = sectors; - set_capacity(mddev->gendisk, mddev->array_sectors); - if (mddev->pers) + if (mddev->pers) { + set_capacity(mddev->gendisk, mddev->array_sectors); revalidate_disk(mddev->gendisk); - + } return len; } -- cgit v1.2.3-18-g5258 From 8f5f02c460b7ca74ce55ce126ce0c1e58a3f923d Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 16 Feb 2011 13:58:51 +1100 Subject: md: correctly handle probe of an 'mdp' device. 'mdp' devices are md devices with preallocated device numbers for partitions. As such it is possible to mknod and open a partition before opening the whole device. this causes md_probe() to be called with a device number of a partition, which in-turn calls mddev_find with such a number. However mddev_find expects the number of a 'whole device' and does the wrong thing with partition numbers. So add code to mddev_find to remove the 'partition' part of a device number and just work with the 'whole device'. This patch addresses https://bugzilla.kernel.org/show_bug.cgi?id=28652 Reported-by: hkmaly@bigfoot.com Signed-off-by: NeilBrown Cc: --- drivers/md/md.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index 6818ff4aa8d..330addfe9b7 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -553,6 +553,9 @@ static mddev_t * mddev_find(dev_t unit) { mddev_t *mddev, *new = NULL; + if (unit && MAJOR(unit) != MD_MAJOR) + unit &= ~((1< Date: Wed, 16 Feb 2011 14:08:02 +0300 Subject: perf, x86: P4 PMU: Fix spurious NMI messages Several people have reported spurious unknown NMI messages on some P4 CPUs. This patch fixes it by checking for an overflow (negative counter values) directly, instead of relying on the P4_CCCR_OVF bit. Reported-by: George Spelvin Reported-by: Meelis Roos Reported-by: Don Zickus Reported-by: Dave Airlie Signed-off-by: Cyrill Gorcunov Cc: Lin Ming Cc: Don Zickus Cc: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar --- arch/x86/include/asm/perf_event_p4.h | 1 + arch/x86/kernel/cpu/perf_event_p4.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h index e2f6a99f14a..cc29086e30c 100644 --- a/arch/x86/include/asm/perf_event_p4.h +++ b/arch/x86/include/asm/perf_event_p4.h @@ -22,6 +22,7 @@ #define ARCH_P4_CNTRVAL_BITS (40) #define ARCH_P4_CNTRVAL_MASK ((1ULL << ARCH_P4_CNTRVAL_BITS) - 1) +#define ARCH_P4_UNFLAGGED_BIT ((1ULL) << (ARCH_P4_CNTRVAL_BITS - 1)) #define P4_ESCR_EVENT_MASK 0x7e000000U #define P4_ESCR_EVENT_SHIFT 25 diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index f7a0993c1e7..ff751a9f182 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -770,9 +770,14 @@ static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc) return 1; } - /* it might be unflagged overflow */ - rdmsrl(hwc->event_base + hwc->idx, v); - if (!(v & ARCH_P4_CNTRVAL_MASK)) + /* + * In some circumstances the overflow might issue an NMI but did + * not set P4_CCCR_OVF bit. Because a counter holds a negative value + * we simply check for high bit being set, if it's cleared it means + * the counter has reached zero value and continued counting before + * real NMI signal was received: + */ + if (!(v & ARCH_P4_UNFLAGGED_BIT)) return 1; return 0; -- cgit v1.2.3-18-g5258 From 4fe757dd48a9e95e1a071291f15dda5421dacb66 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 15 Feb 2011 22:26:07 +0100 Subject: perf: Fix throttle logic It was possible to call pmu::start() on an already running event. In particular this lead so some wreckage as the hrtimer events would re-initialize active timers. This was due to throttled events being activated again by scheduling. Scheduling in a context would add and force start events, resulting in running events with a possible throttle status. The next tick to hit that task will then try to unthrottle the event and call ->start() on an already running event. Reported-by: Jeff Moyer Cc: Signed-off-by: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar --- kernel/perf_event.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 999835b6112..656222fcf76 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -782,6 +782,10 @@ retry: raw_spin_unlock_irq(&ctx->lock); } +#define MAX_INTERRUPTS (~0ULL) + +static void perf_log_throttle(struct perf_event *event, int enable); + static int event_sched_in(struct perf_event *event, struct perf_cpu_context *cpuctx, @@ -794,6 +798,17 @@ event_sched_in(struct perf_event *event, event->state = PERF_EVENT_STATE_ACTIVE; event->oncpu = smp_processor_id(); + + /* + * Unthrottle events, since we scheduled we might have missed several + * ticks already, also for a heavily scheduling task there is little + * guarantee it'll get a tick in a timely manner. + */ + if (unlikely(event->hw.interrupts == MAX_INTERRUPTS)) { + perf_log_throttle(event, 1); + event->hw.interrupts = 0; + } + /* * The new state must be visible before we turn it on in the hardware: */ @@ -1596,10 +1611,6 @@ void __perf_event_task_sched_in(struct task_struct *task) } } -#define MAX_INTERRUPTS (~0ULL) - -static void perf_log_throttle(struct perf_event *event, int enable); - static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count) { u64 frequency = event->attr.sample_freq; -- cgit v1.2.3-18-g5258 From 8efdd0cdc54f3bb5db464b3baf88f7441f54da47 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 11 Feb 2011 13:00:06 +0100 Subject: Bluetooth: fix crash with quirky dongles doing sound Quirky dongles sometimes do not use the iso interface which causes a crash with runtime PM Signed-off-by: Oliver Neukum Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/btusb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 4cefa91e6c3..664f1cc9f8d 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -829,7 +829,7 @@ static void btusb_work(struct work_struct *work) if (hdev->conn_hash.sco_num > 0) { if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) { - err = usb_autopm_get_interface(data->isoc); + err = usb_autopm_get_interface(data->isoc ? data->isoc : data->intf); if (err < 0) { clear_bit(BTUSB_ISOC_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->isoc_anchor); @@ -858,7 +858,7 @@ static void btusb_work(struct work_struct *work) __set_isoc_interface(hdev, 0); if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags)) - usb_autopm_put_interface(data->isoc); + usb_autopm_put_interface(data->isoc ? data->isoc : data->intf); } } -- cgit v1.2.3-18-g5258 From 840af824b2bf9194ea596e0ddc7aa05066794ca1 Mon Sep 17 00:00:00 2001 From: Vladislav P Date: Mon, 14 Feb 2011 15:21:50 -0200 Subject: Bluetooth: Release BTM while sleeping to avoid deadlock Signed-off-by: Vladislav P Signed-off-by: Gustavo F. Padovan --- net/bluetooth/rfcomm/tty.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 2575c2db640..d7b9af4703d 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -727,7 +727,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) break; } + tty_unlock(); schedule(); + tty_lock(); } set_current_state(TASK_RUNNING); remove_wait_queue(&dev->wait, &wait); -- cgit v1.2.3-18-g5258 From e9036e336a8e5640871e0006ea4a89982b25046f Mon Sep 17 00:00:00 2001 From: "Cho, Yu-Chen" Date: Tue, 15 Feb 2011 10:20:07 +0800 Subject: Bluetooth: Add Atheros BT AR5BBU12 fw supported Add the btusb.c blacklist [0489:e02c] for Atheros AR5BBU12 BT and add to ath3k.c supported this device. Signed-off-by: Cho, Yu-Chen Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/ath3k.c | 3 +++ drivers/bluetooth/btusb.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 333c21289d9..6dcd55a74c0 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -41,6 +41,9 @@ static struct usb_device_id ath3k_table[] = { /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03F0, 0x311D) }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xE02C) }, { } /* Terminating entry */ }; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 664f1cc9f8d..b7f2f373c63 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -105,6 +105,9 @@ static struct usb_device_id blacklist_table[] = { /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, + /* Broadcom BCM2035 */ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, -- cgit v1.2.3-18-g5258 From 91435650c233b93e0da389db74f4b2c11c5ad2d4 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Wed, 16 Feb 2011 13:10:41 -0500 Subject: Btrfs: put ENOSPC debugging under a mount option ENOSPC in btrfs is getting to the point where the extra debugging isn't required. I've put it under mount -o enospc_debug just in case someone is having difficult problems. Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 1 + fs/btrfs/extent-tree.c | 2 +- fs/btrfs/super.c | 7 ++++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 72195378bef..6297701bc19 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1254,6 +1254,7 @@ struct btrfs_root { #define BTRFS_MOUNT_SPACE_CACHE (1 << 12) #define BTRFS_MOUNT_CLEAR_CACHE (1 << 13) #define BTRFS_MOUNT_USER_SUBVOL_RM_ALLOWED (1 << 14) +#define BTRFS_MOUNT_ENOSPC_DEBUG (1 << 15) #define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) #define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a7aaa10c530..d375fc04a06 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -5377,7 +5377,7 @@ again: num_bytes, data, 1); goto again; } - if (ret == -ENOSPC) { + if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) { struct btrfs_space_info *sinfo; sinfo = __find_space_info(root->fs_info, data); diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 0209b5fc772..db0a827252b 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -155,7 +155,8 @@ enum { Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress, Opt_compress_type, Opt_compress_force, Opt_compress_force_type, Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, - Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, Opt_err, + Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, + Opt_enospc_debug, Opt_err, }; static match_table_t tokens = { @@ -184,6 +185,7 @@ static match_table_t tokens = { {Opt_space_cache, "space_cache"}, {Opt_clear_cache, "clear_cache"}, {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, + {Opt_enospc_debug, "enospc_debug"}, {Opt_err, NULL}, }; @@ -358,6 +360,9 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) case Opt_user_subvol_rm_allowed: btrfs_set_opt(info->mount_opt, USER_SUBVOL_RM_ALLOWED); break; + case Opt_enospc_debug: + btrfs_set_opt(info->mount_opt, ENOSPC_DEBUG); + break; case Opt_err: printk(KERN_INFO "btrfs: unrecognized mount option " "'%s'\n", p); -- cgit v1.2.3-18-g5258 From c87f08ca44e83b2c8d28f63f9c33f3a270a04bbe Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Wed, 16 Feb 2011 13:57:04 -0500 Subject: Btrfs: allow balance to explicitly allocate chunks as it relocates Btrfs device shrinking and balancing ends up reallocating all the blocks in order to allow COW to move them to new destinations. It is somewhat awkward in terms of ENOSPC because most of the enospc code is built around the idea that some operation on a reference counted tree triggers allocations in the non-reference counted trees. This commit changes the balancing code to deal with enospc by trying to allocate a new chunk. If that allocation succeeds, we go ahead and retry whatever failed due to enospc. Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 2 ++ fs/btrfs/extent-tree.c | 7 +++++++ fs/btrfs/relocation.c | 13 ++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 6297701bc19..28188a786da 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2219,6 +2219,8 @@ int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end); int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, u64 num_bytes); +int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, + struct btrfs_root *root, u64 type); /* ctree.c */ int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key, diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index d375fc04a06..100e409e905 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -8066,6 +8066,13 @@ out: return ret; } +int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, + struct btrfs_root *root, u64 type) +{ + u64 alloc_flags = get_alloc_profile(root, type); + return do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1); +} + /* * helper to account the unused space of all the readonly block group in the * list. takes mirrors into account. diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 0825e4ed944..31ade5802ae 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -3654,6 +3654,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) u32 item_size; int ret; int err = 0; + int progress = 0; path = btrfs_alloc_path(); if (!path) @@ -3666,9 +3667,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) } while (1) { + progress++; trans = btrfs_start_transaction(rc->extent_root, 0); BUG_ON(IS_ERR(trans)); - +restart: if (update_backref_cache(trans, &rc->backref_cache)) { btrfs_end_transaction(trans, rc->extent_root); continue; @@ -3781,6 +3783,15 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) } } } + if (trans && progress && err == -ENOSPC) { + ret = btrfs_force_chunk_alloc(trans, rc->extent_root, + rc->block_group->flags); + if (ret == 0) { + err = 0; + progress = 0; + goto restart; + } + } btrfs_release_path(rc->extent_root, path); clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY, -- cgit v1.2.3-18-g5258 From b4dc2b8c694ead005b828f5fb7fa1134db5b6275 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 16 Feb 2011 06:06:34 +0000 Subject: Btrfs: Fix BTRFS_IOC_SUBVOL_SETFLAGS ioctl - Check user-specified flags correctly - Check the inode owership - Search root item in root tree but not fs tree Reported-by: Dan Rosenberg Signed-off-by: Li Zefan Signed-off-by: Chris Mason --- fs/btrfs/ioctl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index be2d4f6aaa5..5fdb2abc4fa 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1071,12 +1071,15 @@ static noinline int btrfs_ioctl_subvol_setflags(struct file *file, if (copy_from_user(&flags, arg, sizeof(flags))) return -EFAULT; - if (flags & ~BTRFS_SUBVOL_CREATE_ASYNC) + if (flags & BTRFS_SUBVOL_CREATE_ASYNC) return -EINVAL; if (flags & ~BTRFS_SUBVOL_RDONLY) return -EOPNOTSUPP; + if (!is_owner_or_cap(inode)) + return -EACCES; + down_write(&root->fs_info->subvol_sem); /* nothing to do */ @@ -1097,7 +1100,7 @@ static noinline int btrfs_ioctl_subvol_setflags(struct file *file, goto out_reset; } - ret = btrfs_update_root(trans, root, + ret = btrfs_update_root(trans, root->fs_info->tree_root, &root->root_key, &root->root_item); btrfs_commit_transaction(trans, root); -- cgit v1.2.3-18-g5258 From ca9b688c1c9a21635cfc8af8b68565b154185196 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 16 Feb 2011 06:06:41 +0000 Subject: Btrfs: Avoid accessing unmapped kernel address When decompressing a chunk of data, we'll copy the data out to a working buffer if the data is stored in more than one page, otherwise we'll use the mapped page directly to avoid memory copy. In the latter case, we'll end up accessing the kernel address after we've unmapped the page in a corner case. Reported-by: Juan Francisco Cantero Hurtado Signed-off-by: Li Zefan Signed-off-by: Chris Mason --- fs/btrfs/lzo.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c index cc9b450399d..a178f5ebea7 100644 --- a/fs/btrfs/lzo.c +++ b/fs/btrfs/lzo.c @@ -280,6 +280,7 @@ static int lzo_decompress_biovec(struct list_head *ws, unsigned long tot_out; unsigned long tot_len; char *buf; + bool may_late_unmap, need_unmap; data_in = kmap(pages_in[0]); tot_len = read_compress_length(data_in); @@ -300,11 +301,13 @@ static int lzo_decompress_biovec(struct list_head *ws, tot_in += in_len; working_bytes = in_len; + may_late_unmap = need_unmap = false; /* fast path: avoid using the working buffer */ if (in_page_bytes_left >= in_len) { buf = data_in + in_offset; bytes = in_len; + may_late_unmap = true; goto cont; } @@ -329,14 +332,17 @@ cont: if (working_bytes == 0 && tot_in >= tot_len) break; - kunmap(pages_in[page_in_index]); - page_in_index++; - if (page_in_index >= total_pages_in) { + if (page_in_index + 1 >= total_pages_in) { ret = -1; - data_in = NULL; goto done; } - data_in = kmap(pages_in[page_in_index]); + + if (may_late_unmap) + need_unmap = true; + else + kunmap(pages_in[page_in_index]); + + data_in = kmap(pages_in[++page_in_index]); in_page_bytes_left = PAGE_CACHE_SIZE; in_offset = 0; @@ -346,6 +352,8 @@ cont: out_len = lzo1x_worst_compress(PAGE_CACHE_SIZE); ret = lzo1x_decompress_safe(buf, in_len, workspace->buf, &out_len); + if (need_unmap) + kunmap(pages_in[page_in_index - 1]); if (ret != LZO_E_OK) { printk(KERN_WARNING "btrfs decompress failed\n"); ret = -1; @@ -363,8 +371,7 @@ cont: break; } done: - if (data_in) - kunmap(pages_in[page_in_index]); + kunmap(pages_in[page_in_index]); return ret; } -- cgit v1.2.3-18-g5258 From 9b3517e9136824346227b7b04f8f7ea1f3a726cc Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Tue, 15 Feb 2011 18:14:25 +0000 Subject: Btrfs: make btrfs_rm_device() fail gracefully If shrinking done as part of the online device removal fails add that device back to the allocation list and increment the rw_devices counter. This fixes two bugs: 1) we could have a perfectly good device out of alloc list for no good reason; 2) in the btrfs consisting of two devices, failure in btrfs_rm_device() could lead to a situation where it was impossible to remove any of the devices because of the "unable to remove the only writeable device" error. Signed-off-by: Ilya Dryomov Signed-off-by: Chris Mason --- fs/btrfs/volumes.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index dadaaa8005c..f31c33119bb 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1337,11 +1337,11 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) ret = btrfs_shrink_device(device, 0); if (ret) - goto error_brelse; + goto error_undo; ret = btrfs_rm_dev_item(root->fs_info->chunk_root, device); if (ret) - goto error_brelse; + goto error_undo; device->in_fs_metadata = 0; @@ -1415,6 +1415,13 @@ out: mutex_unlock(&root->fs_info->volume_mutex); mutex_unlock(&uuid_mutex); return ret; +error_undo: + if (device->writeable) { + list_add(&device->dev_alloc_list, + &root->fs_info->fs_devices->alloc_list); + root->fs_info->fs_devices->rw_devices++; + } + goto error_brelse; } /* -- cgit v1.2.3-18-g5258 From fb01aa85b8b29c1a4e1f4a28ea54175de6bf7559 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Tue, 15 Feb 2011 18:12:57 +0000 Subject: Btrfs: set FMODE_EXCL in btrfs_device->mode This fixes a bug introduced in d4d77629, where the device added online (and therefore initialized via btrfs_init_new_device()) would be left with the positive bdev->bd_holders after unmount. Since d4d77629 we no longer OR FMODE_EXCL explicitly on blkdev_put(), set it in btrfs_device->mode. Signed-off-by: Ilya Dryomov Signed-off-by: Chris Mason --- fs/btrfs/volumes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index f31c33119bb..94334d95228 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1639,7 +1639,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) device->dev_root = root->fs_info->dev_root; device->bdev = bdev; device->in_fs_metadata = 1; - device->mode = 0; + device->mode = FMODE_EXCL; set_blocksize(device->bdev, 4096); if (seeding_dev) { -- cgit v1.2.3-18-g5258 From d503b30bd648b3cb4e5f50b65d27e389960cc6d9 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 17 Feb 2011 11:32:38 +0100 Subject: netfilter: tproxy: do not assign timewait sockets to skb->sk Assigning a socket in timewait state to skb->sk can trigger kernel oops, e.g. in nfnetlink_log, which does: if (skb->sk) { read_lock_bh(&skb->sk->sk_callback_lock); if (skb->sk->sk_socket && skb->sk->sk_socket->file) ... in the timewait case, accessing sk->sk_callback_lock and sk->sk_socket is invalid. Either all of these spots will need to add a test for sk->sk_state != TCP_TIME_WAIT, or xt_TPROXY must not assign a timewait socket to skb->sk. This does the latter. If a TW socket is found, assign the tproxy nfmark, but skip the skb->sk assignment, thus mimicking behaviour of a '-m socket .. -j MARK/ACCEPT' re-routing rule. The 'SYN to TW socket' case is left unchanged -- we try to redirect to the listener socket. Cc: Balazs Scheidler Cc: KOVACS Krisztian Signed-off-by: Florian Westphal Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_tproxy_core.h | 12 +----------- net/netfilter/nf_tproxy_core.c | 27 ++++++++++++--------------- net/netfilter/xt_TPROXY.c | 22 ++++++++++++++++++++-- net/netfilter/xt_socket.c | 13 +++++++++++-- 4 files changed, 44 insertions(+), 30 deletions(-) diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h index cd85b3bc832..e505358d899 100644 --- a/include/net/netfilter/nf_tproxy_core.h +++ b/include/net/netfilter/nf_tproxy_core.h @@ -201,18 +201,8 @@ nf_tproxy_get_sock_v6(struct net *net, const u8 protocol, } #endif -static inline void -nf_tproxy_put_sock(struct sock *sk) -{ - /* TIME_WAIT inet sockets have to be handled differently */ - if ((sk->sk_protocol == IPPROTO_TCP) && (sk->sk_state == TCP_TIME_WAIT)) - inet_twsk_put(inet_twsk(sk)); - else - sock_put(sk); -} - /* assign a socket to the skb -- consumes sk */ -int +void nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk); #endif diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c index 4d87befb04c..474d621cbc2 100644 --- a/net/netfilter/nf_tproxy_core.c +++ b/net/netfilter/nf_tproxy_core.c @@ -28,26 +28,23 @@ nf_tproxy_destructor(struct sk_buff *skb) skb->destructor = NULL; if (sk) - nf_tproxy_put_sock(sk); + sock_put(sk); } /* consumes sk */ -int +void nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk) { - bool transparent = (sk->sk_state == TCP_TIME_WAIT) ? - inet_twsk(sk)->tw_transparent : - inet_sk(sk)->transparent; - - if (transparent) { - skb_orphan(skb); - skb->sk = sk; - skb->destructor = nf_tproxy_destructor; - return 1; - } else - nf_tproxy_put_sock(sk); - - return 0; + /* assigning tw sockets complicates things; most + * skb->sk->X checks would have to test sk->sk_state first */ + if (sk->sk_state == TCP_TIME_WAIT) { + inet_twsk_put(inet_twsk(sk)); + return; + } + + skb_orphan(skb); + skb->sk = sk; + skb->destructor = nf_tproxy_destructor; } EXPORT_SYMBOL_GPL(nf_tproxy_assign_sock); diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c index 640678f47a2..dcfd57eb9d0 100644 --- a/net/netfilter/xt_TPROXY.c +++ b/net/netfilter/xt_TPROXY.c @@ -33,6 +33,20 @@ #include #include +static bool tproxy_sk_is_transparent(struct sock *sk) +{ + if (sk->sk_state != TCP_TIME_WAIT) { + if (inet_sk(sk)->transparent) + return true; + sock_put(sk); + } else { + if (inet_twsk(sk)->tw_transparent) + return true; + inet_twsk_put(inet_twsk(sk)); + } + return false; +} + static inline __be32 tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr) { @@ -141,7 +155,7 @@ tproxy_tg4(struct sk_buff *skb, __be32 laddr, __be16 lport, skb->dev, NFT_LOOKUP_LISTENER); /* NOTE: assign_sock consumes our sk reference */ - if (sk && nf_tproxy_assign_sock(skb, sk)) { + if (sk && tproxy_sk_is_transparent(sk)) { /* This should be in a separate target, but we don't do multiple targets on the same rule yet */ skb->mark = (skb->mark & ~mark_mask) ^ mark_value; @@ -149,6 +163,8 @@ tproxy_tg4(struct sk_buff *skb, __be32 laddr, __be16 lport, pr_debug("redirecting: proto %hhu %pI4:%hu -> %pI4:%hu, mark: %x\n", iph->protocol, &iph->daddr, ntohs(hp->dest), &laddr, ntohs(lport), skb->mark); + + nf_tproxy_assign_sock(skb, sk); return NF_ACCEPT; } @@ -306,7 +322,7 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par) par->in, NFT_LOOKUP_LISTENER); /* NOTE: assign_sock consumes our sk reference */ - if (sk && nf_tproxy_assign_sock(skb, sk)) { + if (sk && tproxy_sk_is_transparent(sk)) { /* This should be in a separate target, but we don't do multiple targets on the same rule yet */ skb->mark = (skb->mark & ~tgi->mark_mask) ^ tgi->mark_value; @@ -314,6 +330,8 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par) pr_debug("redirecting: proto %hhu %pI6:%hu -> %pI6:%hu, mark: %x\n", tproto, &iph->saddr, ntohs(hp->source), laddr, ntohs(lport), skb->mark); + + nf_tproxy_assign_sock(skb, sk); return NF_ACCEPT; } diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 00d6ae83830..9cc46356b57 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c @@ -35,6 +35,15 @@ #include #endif +static void +xt_socket_put_sk(struct sock *sk) +{ + if (sk->sk_state == TCP_TIME_WAIT) + inet_twsk_put(inet_twsk(sk)); + else + sock_put(sk); +} + static int extract_icmp4_fields(const struct sk_buff *skb, u8 *protocol, @@ -164,7 +173,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, (sk->sk_state == TCP_TIME_WAIT && inet_twsk(sk)->tw_transparent)); - nf_tproxy_put_sock(sk); + xt_socket_put_sk(sk); if (wildcard || !transparent) sk = NULL; @@ -298,7 +307,7 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) (sk->sk_state == TCP_TIME_WAIT && inet_twsk(sk)->tw_transparent)); - nf_tproxy_put_sock(sk); + xt_socket_put_sk(sk); if (wildcard || !transparent) sk = NULL; -- cgit v1.2.3-18-g5258 From 5990378b393429244559f4750f2ee3a50929b932 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 11 Feb 2011 10:00:02 +0200 Subject: usb: musb: fix build breakage commit 0662481855c389b75a0a54c32870cc90563d80a9 (usb: musb: disable double buffering when it's broken), introduced a compile error when gadget API is disabled. Fix it. Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index d74a8113ae7..e6400be8a0f 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -488,6 +488,15 @@ struct musb { unsigned set_address:1; unsigned test_mode:1; unsigned softconnect:1; + + u8 address; + u8 test_mode_nr; + u16 ackpend; /* ep0 */ + enum musb_g_ep0_state ep0_state; + struct usb_gadget g; /* the gadget */ + struct usb_gadget_driver *gadget_driver; /* its driver */ +#endif + /* * FIXME: Remove this flag. * @@ -501,14 +510,6 @@ struct musb { */ unsigned double_buffer_not_ok:1 __deprecated; - u8 address; - u8 test_mode_nr; - u16 ackpend; /* ep0 */ - enum musb_g_ep0_state ep0_state; - struct usb_gadget g; /* the gadget */ - struct usb_gadget_driver *gadget_driver; /* its driver */ -#endif - struct musb_hdrc_config *config; #ifdef MUSB_CONFIG_PROC_FS -- cgit v1.2.3-18-g5258 From b193b412e62b134adf69af286c7e7f8e99259350 Mon Sep 17 00:00:00 2001 From: Johan Hovold