diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-02-25 22:10:38 +0000 | 
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-02-25 22:10:38 +0000 | 
| commit | 9f33be2c3a80bdc2cc08342dd77fac87652e0548 (patch) | |
| tree | 7ad6e825427a15c5ec0fc15540abc0429d7f4bce | |
| parent | 2741ecb4ce5c2d430b5c44b0a169038338c21df5 (diff) | |
| parent | eed18b5fa4d297c681b00144e8c6942dd35d39a7 (diff) | |
| download | olio-linux-3.10-9f33be2c3a80bdc2cc08342dd77fac87652e0548.tar.xz olio-linux-3.10-9f33be2c3a80bdc2cc08342dd77fac87652e0548.zip  | |
Merge branches 'clks' and 'pnx' into devel
146 files changed, 1464 insertions, 1154 deletions
@@ -1,7 +1,7 @@  VERSION = 2  PATCHLEVEL = 6  SUBLEVEL = 33 -EXTRAVERSION = -rc4 +EXTRAVERSION = -rc5  NAME = Man-Eating Seals of Antiquity  # *DOCUMENTATION* diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e932da03349..e4a765438ee 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -574,6 +574,7 @@ config ARCH_PNX4008  	bool "Philips Nexperia PNX4008 Mobile"  	select CPU_ARM926T  	select HAVE_CLK +	select COMMON_CLKDEV  	help  	  This enables support for Philips PNX4008 mobile platform. diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c index aae5bc01acc..446b696196e 100644 --- a/arch/arm/common/clkdev.c +++ b/arch/arm/common/clkdev.c @@ -99,6 +99,16 @@ void clkdev_add(struct clk_lookup *cl)  }  EXPORT_SYMBOL(clkdev_add); +void __init clkdev_add_table(struct clk_lookup *cl, size_t num) +{ +	mutex_lock(&clocks_mutex); +	while (num--) { +		list_add_tail(&cl->node, &clocks); +		cl++; +	} +	mutex_unlock(&clocks_mutex); +} +  #define MAX_DEV_ID	20  #define MAX_CON_ID	16 diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index be8b4d79cf4..8148a009273 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -154,16 +154,16 @@   *	Please note that the implementation of these, and the required   *	effects are cache-type (VIVT/VIPT/PIPT) specific.   * - *	flush_cache_kern_all() + *	flush_kern_all()   *   *		Unconditionally clean and invalidate the entire cache.   * - *	flush_cache_user_mm(mm) + *	flush_user_all()   *   *		Clean and invalidate all user space cache entries   *		before a change of page tables.   * - *	flush_cache_user_range(start, end, flags) + *	flush_user_range(start, end, flags)   *   *		Clean and invalidate a range of cache entries in the   *		specified address space before a change of page tables. @@ -179,6 +179,20 @@   *		- start  - virtual start address   *		- end    - virtual end address   * + *	coherent_user_range(start, end) + * + *		Ensure coherency between the Icache and the Dcache in the + *		region described by start, end.  If you have non-snooping + *		Harvard caches, you need to implement this function. + *		- start  - virtual start address + *		- end    - virtual end address + * + *	flush_kern_dcache_area(kaddr, size) + * + *		Ensure that the data held in page is written back. + *		- kaddr  - page address + *		- size   - region size + *   *	DMA Cache Coherency   *	===================   * diff --git a/arch/arm/include/asm/clkdev.h b/arch/arm/include/asm/clkdev.h index b6ec7c627b3..7a0690da5e6 100644 --- a/arch/arm/include/asm/clkdev.h +++ b/arch/arm/include/asm/clkdev.h @@ -27,4 +27,7 @@ struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,  void clkdev_add(struct clk_lookup *cl);  void clkdev_drop(struct clk_lookup *cl); +void clkdev_add_table(struct clk_lookup *, size_t); +int clk_add_alias(const char *, const char *, char *, struct device *); +  #endif diff --git a/arch/arm/mach-bcmring/core.c b/arch/arm/mach-bcmring/core.c index e590bbe0a7b..72e405df0fb 100644 --- a/arch/arm/mach-bcmring/core.c +++ b/arch/arm/mach-bcmring/core.c @@ -142,8 +142,7 @@ void __init bcmring_amba_init(void)  	chipcHw_busInterfaceClockEnable(bus_clock); -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {  		struct amba_device *d = amba_devs[i]; diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 49fa9f8fef4..5f80092b6ac 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -447,7 +447,6 @@ static void __init ep93xx_dma_clock_init(void)  static int __init ep93xx_clock_init(void)  {  	u32 value; -	int i;  	/* Determine the bootloader configured pll1 rate */  	value = __raw_readl(EP93XX_SYSCON_CLKSET1); @@ -480,8 +479,7 @@ static int __init ep93xx_clock_init(void)  		clk_f.rate / 1000000, clk_h.rate / 1000000,  		clk_p.rate / 1000000); -	for (i = 0; i < ARRAY_SIZE(clocks); i++) -		clkdev_add(&clocks[i]); +	clkdev_add_table(clocks, ARRAY_SIZE(clocks));  	return 0;  }  arch_initcall(ep93xx_clock_init); diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index a0f60e55da6..8b390e36ba6 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -144,8 +144,7 @@ static int __init integrator_init(void)  {  	int i; -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {  		struct amba_device *d = amba_devs[i]; diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 3f35293d457..66ef86d6d9e 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -558,9 +558,7 @@ static void __init intcp_init(void)  {  	int i; -	for (i = 0; i < ARRAY_SIZE(cp_lookups); i++) -		clkdev_add(&cp_lookups[i]); - +	clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));  	platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));  	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { diff --git a/arch/arm/mach-mmp/clock.c b/arch/arm/mach-mmp/clock.c index 2a46ed5cc2a..886e05648f0 100644 --- a/arch/arm/mach-mmp/clock.c +++ b/arch/arm/mach-mmp/clock.c @@ -88,11 +88,3 @@ unsigned long clk_get_rate(struct clk *clk)  	return rate;  }  EXPORT_SYMBOL(clk_get_rate); - -void clks_register(struct clk_lookup *clks, size_t num) -{ -	int i; - -	for (i = 0; i < num; i++) -		clkdev_add(&clks[i]); -} diff --git a/arch/arm/mach-mmp/clock.h b/arch/arm/mach-mmp/clock.h index eefffbe683b..016ae94691c 100644 --- a/arch/arm/mach-mmp/clock.h +++ b/arch/arm/mach-mmp/clock.h @@ -68,5 +68,3 @@ struct clk clk_##_name = {					\  extern struct clk clk_pxa168_gpio;  extern struct clk clk_pxa168_timers; - -extern void clks_register(struct clk_lookup *, size_t); diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 37dbdde17fa..1873c821df9 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -94,7 +94,7 @@ static int __init pxa168_init(void)  		mfp_init_base(MFPR_VIRT_BASE);  		mfp_init_addr(pxa168_mfp_addr_map);  		pxa_init_dma(IRQ_PXA168_DMA_INT0, 32); -		clks_register(ARRAY_AND_SIZE(pxa168_clkregs)); +		clkdev_add_table(ARRAY_AND_SIZE(pxa168_clkregs));  	}  	return 0; diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c index d4049508a4d..46f2d69bef3 100644 --- a/arch/arm/mach-mmp/pxa910.c +++ b/arch/arm/mach-mmp/pxa910.c @@ -131,7 +131,7 @@ static int __init pxa910_init(void)  		mfp_init_base(MFPR_VIRT_BASE);  		mfp_init_addr(pxa910_mfp_addr_map);  		pxa_init_dma(IRQ_PXA910_DMA_INT0, 32); -		clks_register(ARRAY_AND_SIZE(pxa910_clkregs)); +		clkdev_add_table(ARRAY_AND_SIZE(pxa910_clkregs));  	}  	return 0; diff --git a/arch/arm/mach-mx1/clock.c b/arch/arm/mach-mx1/clock.c index d1b588519ad..6cf2d4a7511 100644 --- a/arch/arm/mach-mx1/clock.c +++ b/arch/arm/mach-mx1/clock.c @@ -570,7 +570,6 @@ static struct clk_lookup lookups[] __initdata = {  int __init mx1_clocks_init(unsigned long fref)  {  	unsigned int reg; -	int i;  	/* disable clocks we are able to */  	__raw_writel(0, SCM_GCCR); @@ -592,8 +591,7 @@ int __init mx1_clocks_init(unsigned long fref)  	reg = (reg & CCM_CSCR_CLKO_MASK) >> CCM_CSCR_CLKO_OFFSET;  	clko_clk.parent = (struct clk *)clko_clocks[reg]; -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  	clk_enable(&hclk);  	clk_enable(&fclk); diff --git a/arch/arm/mach-mx2/clock_imx21.c b/arch/arm/mach-mx2/clock_imx21.c index 91901b5d56c..e82b489d121 100644 --- a/arch/arm/mach-mx2/clock_imx21.c +++ b/arch/arm/mach-mx2/clock_imx21.c @@ -968,7 +968,6 @@ static struct clk_lookup lookups[] = {   */  int __init mx21_clocks_init(unsigned long lref, unsigned long href)  { -	int i;  	u32 cscr;  	external_low_reference = lref; @@ -986,8 +985,7 @@ int __init mx21_clocks_init(unsigned long lref, unsigned long href)  	else  		spll_clk.parent = &fpm_clk; -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  	/* Turn off all clock gates */  	__raw_writel(0, CCM_PCCR0); diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c index b010bf9ceaa..18c53a6487f 100644 --- a/arch/arm/mach-mx2/clock_imx27.c +++ b/arch/arm/mach-mx2/clock_imx27.c @@ -719,7 +719,6 @@ static void __init to2_adjust_clocks(void)  int __init mx27_clocks_init(unsigned long fref)  {  	u32 cscr = __raw_readl(CCM_CSCR); -	int i;  	external_high_reference = fref; @@ -736,8 +735,7 @@ int __init mx27_clocks_init(unsigned long fref)  	to2_adjust_clocks(); -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  	/* Turn off all clocks we do not need */  	__raw_writel(0, CCM_PCCR0); diff --git a/arch/arm/mach-mx25/clock.c b/arch/arm/mach-mx25/clock.c index 6e838b85771..66916f10481 100644 --- a/arch/arm/mach-mx25/clock.c +++ b/arch/arm/mach-mx25/clock.c @@ -210,11 +210,7 @@ static struct clk_lookup lookups[] = {  int __init mx25_clocks_init(unsigned long fref)  { -	int i; - -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); - +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  	mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);  	return 0; diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index 7584b4c6c55..f3f41fa4f21 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -485,15 +485,13 @@ static struct clk_lookup lookups[] = {  int __init mx35_clocks_init()  { -	int i;  	unsigned int ll = 0;  #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)  	ll = (3 << 16);  #endif -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  	/* Turn off all clocks except the ones we need to survive, namely:  	 * EMI, GPIO1/2/3, GPT, IOMUX, MAX and eventually uart diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c index 27a318af0d2..b5c39a016db 100644 --- a/arch/arm/mach-mx3/clock.c +++ b/arch/arm/mach-mx3/clock.c @@ -578,12 +578,10 @@ static struct clk_lookup lookups[] = {  int __init mx31_clocks_init(unsigned long fref)  {  	u32 reg; -	int i;  	ckih_rate = fref; -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  	/* change the csi_clk parent if necessary */  	reg = __raw_readl(MXC_CCM_CCMR); diff --git a/arch/arm/mach-mxc91231/clock.c b/arch/arm/mach-mxc91231/clock.c index ecfa37fef8a..5c85075d8a5 100644 --- a/arch/arm/mach-mxc91231/clock.c +++ b/arch/arm/mach-mxc91231/clock.c @@ -624,7 +624,6 @@ static struct clk_lookup lookups[] = {  int __init mxc91231_clocks_init(unsigned long fref)  {  	void __iomem *gpt_base; -	int i;  	ckih_rate = fref; @@ -632,8 +631,7 @@ int __init mxc91231_clocks_init(unsigned long fref)  	sdhc_clk[0].parent = clk_sdhc_parent(&sdhc_clk[0]);  	sdhc_clk[1].parent = clk_sdhc_parent(&sdhc_clk[1]); -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  	gpt_base = MXC91231_IO_ADDRESS(MXC91231_GPT1_BASE_ADDR);  	mxc_timer_init(&gpt_clk, gpt_base, MXC91231_INT_GPT); diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c index 898c0e88acb..9d1975fa4d9 100644 --- a/arch/arm/mach-pnx4008/clock.c +++ b/arch/arm/mach-pnx4008/clock.c @@ -22,8 +22,9 @@  #include <linux/delay.h>  #include <linux/io.h> -#include <mach/hardware.h> +#include <asm/clkdev.h> +#include <mach/hardware.h>  #include <mach/clock.h>  #include "clock.h" @@ -56,18 +57,19 @@ static void propagate_rate(struct clk *clk)  	}  } -static inline void clk_reg_disable(struct clk *clk) +static void clk_reg_disable(struct clk *clk)  {  	if (clk->enable_reg)  		__raw_writel(__raw_readl(clk->enable_reg) &  			     ~(1 << clk->enable_shift), clk->enable_reg);  } -static inline void clk_reg_enable(struct clk *clk) +static int clk_reg_enable(struct clk *clk)  {  	if (clk->enable_reg)  		__raw_writel(__raw_readl(clk->enable_reg) |  			     (1 << clk->enable_shift), clk->enable_reg); +	return 0;  }  static inline void clk_reg_disable1(struct clk *clk) @@ -636,31 +638,34 @@ static struct clk flash_ck = {  static struct clk i2c0_ck = {  	.name = "i2c0_ck",  	.parent = &per_ck, -	.flags = NEEDS_INITIALIZATION, -	.round_rate = &on_off_round_rate, -	.set_rate = &on_off_set_rate, +	.flags = NEEDS_INITIALIZATION | FIXED_RATE,  	.enable_shift = 0,  	.enable_reg = I2CCLKCTRL_REG, +	.rate = 13000000, +	.enable = clk_reg_enable, +	.disable = clk_reg_disable,  };  static struct clk i2c1_ck = {  	.name = "i2c1_ck",  	.parent = &per_ck, -	.flags = NEEDS_INITIALIZATION, -	.round_rate = &on_off_round_rate, -	.set_rate = &on_off_set_rate, +	.flags = NEEDS_INITIALIZATION | FIXED_RATE,  	.enable_shift = 1,  	.enable_reg = I2CCLKCTRL_REG, +	.rate = 13000000, +	.enable = clk_reg_enable, +	.disable = clk_reg_disable,  };  static struct clk i2c2_ck = {  	.name = "i2c2_ck",  	.parent = &per_ck, -	.flags = NEEDS_INITIALIZATION, -	.round_rate = &on_off_round_rate, -	.set_rate = &on_off_set_rate, +	.flags = NEEDS_INITIALIZATION | FIXED_RATE,  	.enable_shift = 2,  	.enable_reg = USB_OTG_CLKCTRL_REG, +	.rate = 13000000, +	.enable = clk_reg_enable, +	.disable = clk_reg_disable,  };  static struct clk spi0_ck = { @@ -738,16 +743,16 @@ static struct clk wdt_ck = {  	.name = "wdt_ck",  	.parent = &per_ck,  	.flags = NEEDS_INITIALIZATION, -	.round_rate = &on_off_round_rate, -	.set_rate = &on_off_set_rate,  	.enable_shift = 0,  	.enable_reg = TIMCLKCTRL_REG, +	.enable = clk_reg_enable, +	.disable = clk_reg_disable,  };  /* These clocks are visible outside this module   * and can be initialized   */ -static struct clk *onchip_clks[] = { +static struct clk *onchip_clks[] __initdata = {  	&ck_13MHz,  	&ck_pll1,  	&ck_pll4, @@ -777,49 +782,74 @@ static struct clk *onchip_clks[] = {  	&wdt_ck,  }; -static int local_clk_enable(struct clk *clk) -{ -	int ret = 0; - -	if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate -	    && clk->user_rate) -		ret = clk->set_rate(clk, clk->user_rate); -	return ret; -} +static struct clk_lookup onchip_clkreg[] = { +	{ .clk = &ck_13MHz,	.con_id = "ck_13MHz"	}, +	{ .clk = &ck_pll1,	.con_id = "ck_pll1"	}, +	{ .clk = &ck_pll4,	.con_id = "ck_pll4"	}, +	{ .clk = &ck_pll5,	.con_id = "ck_pll5"	}, +	{ .clk = &ck_pll3,	.con_id = "ck_pll3"	}, +	{ .clk = &vfp9_ck,	.con_id = "vfp9_ck"	}, +	{ .clk = &m2hclk_ck,	.con_id = "m2hclk_ck"	}, +	{ .clk = &hclk_ck,	.con_id = "hclk_ck"	}, +	{ .clk = &dma_ck,	.con_id = "dma_ck"	}, +	{ .clk = &flash_ck,	.con_id = "flash_ck"	}, +	{ .clk = &dum_ck,	.con_id = "dum_ck"	}, +	{ .clk = &keyscan_ck,	.con_id = "keyscan_ck"	}, +	{ .clk = &pwm1_ck,	.con_id = "pwm1_ck"	}, +	{ .clk = &pwm2_ck,	.con_id = "pwm2_ck"	}, +	{ .clk = &jpeg_ck,	.con_id = "jpeg_ck"	}, +	{ .clk = &ms_ck,	.con_id = "ms_ck"	}, +	{ .clk = &touch_ck,	.con_id = "touch_ck"	}, +	{ .clk = &i2c0_ck,	.dev_id = "pnx-i2c.0"	}, +	{ .clk = &i2c1_ck,	.dev_id = "pnx-i2c.1"	}, +	{ .clk = &i2c2_ck,	.dev_id = "pnx-i2c.2"	}, +	{ .clk = &spi0_ck,	.con_id = "spi0_ck"	}, +	{ .clk = &spi1_ck,	.con_id = "spi1_ck"	}, +	{ .clk = &uart3_ck,	.con_id = "uart3_ck"	}, +	{ .clk = &uart4_ck,	.con_id = "uart4_ck"	}, +	{ .clk = &uart5_ck,	.con_id = "uart5_ck"	}, +	{ .clk = &uart6_ck,	.con_id = "uart6_ck"	}, +	{ .clk = &wdt_ck,	.dev_id = "pnx4008-watchdog" }, +};  static void local_clk_disable(struct clk *clk)  { -	if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate) -		clk->set_rate(clk, 0); -} +	if (WARN_ON(clk->usecount == 0)) +		return; -static void local_clk_unuse(struct clk *clk) -{ -	if (clk->usecount > 0 && !(--clk->usecount)) { -		local_clk_disable(clk); +	if (!(--clk->usecount)) { +		if (clk->disable) +			clk->disable(clk); +		else if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate) +			clk->set_rate(clk, 0);  		if (clk->parent) -			local_clk_unuse(clk->parent); +			local_clk_disable(clk->parent);  	}  } -static int local_clk_use(struct clk *clk) +static int local_clk_enable(struct clk *clk)  {  	int ret = 0; -	if (clk->usecount++ == 0) { -		if (clk->parent) -			ret = local_clk_use(clk->parent); -		if (ret != 0) { -			clk->usecount--; -			goto out; +	if (clk->usecount == 0) { +		if (clk->parent) { +			ret = local_clk_enable(clk->parent); +			if (ret != 0) +				goto out;  		} -		ret = local_clk_enable(clk); +		if (clk->enable) +			ret = clk->enable(clk); +		else if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate +			    && clk->user_rate) +			ret = clk->set_rate(clk, clk->user_rate);  		if (ret != 0 && clk->parent) { -			local_clk_unuse(clk->parent); -			clk->usecount--; +			local_clk_disable(clk->parent); +			goto out;  		} + +		clk->usecount++;  	}  out:  	return ret; @@ -866,35 +896,6 @@ out:  EXPORT_SYMBOL(clk_set_rate); -struct clk *clk_get(struct device *dev, const char *id) -{ -	struct clk *clk = ERR_PTR(-ENOENT); -	struct clk **clkp; - -	clock_lock(); -	for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks); -	     clkp++) { -		if (strcmp(id, (*clkp)->name) == 0 -		    && try_module_get((*clkp)->owner)) { -			clk = (*clkp); -			break; -		} -	} -	clock_unlock(); - -	return clk; -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ -	clock_lock(); -	if (clk && !IS_ERR(clk)) -		module_put(clk->owner); -	clock_unlock(); -} -EXPORT_SYMBOL(clk_put); -  unsigned long clk_get_rate(struct clk *clk)  {  	unsigned long ret; @@ -907,10 +908,10 @@ EXPORT_SYMBOL(clk_get_rate);  int clk_enable(struct clk *clk)  { -	int ret = 0; +	int ret;  	clock_lock(); -	ret = local_clk_use(clk); +	ret = local_clk_enable(clk);  	clock_unlock();  	return ret;  } @@ -920,7 +921,7 @@ EXPORT_SYMBOL(clk_enable);  void clk_disable(struct clk *clk)  {  	clock_lock(); -	local_clk_unuse(clk); +	local_clk_disable(clk);  	clock_unlock();  } @@ -967,18 +968,24 @@ static int __init clk_init(void)  	for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);  	     clkp++) { -		if (((*clkp)->flags & NEEDS_INITIALIZATION) -		    && ((*clkp)->set_rate)) { -			(*clkp)->user_rate = (*clkp)->rate; -			local_set_rate((*clkp), (*clkp)->user_rate); -			if ((*clkp)->set_parent) -				(*clkp)->set_parent((*clkp), (*clkp)->parent); +		struct clk *clk = *clkp; +		if (clk->flags & NEEDS_INITIALIZATION) { +			if (clk->set_rate) { +				clk->user_rate = clk->rate; +				local_set_rate(clk, clk->user_rate); +				if (clk->set_parent) +					clk->set_parent(clk, clk->parent); +			} +			if (clk->enable && clk->usecount) +				clk->enable(clk); +			if (clk->disable && !clk->usecount) +				clk->disable(clk);  		}  		pr_debug("%s: clock %s, rate %ld\n", -			__func__, (*clkp)->name, (*clkp)->rate); +			__func__, clk->name, clk->rate);  	} -	local_clk_use(&ck_pll4); +	local_clk_enable(&ck_pll4);  	/* if ck_13MHz is not used, disable it. */  	if (ck_13MHz.usecount == 0) @@ -987,6 +994,8 @@ static int __init clk_init(void)  	/* Disable autoclocking */  	__raw_writeb(0xff, AUTOCLK_CTRL); +	clkdev_add_table(onchip_clkreg, ARRAY_SIZE(onchip_clkreg)); +  	return 0;  } diff --git a/arch/arm/mach-pnx4008/clock.h b/arch/arm/mach-pnx4008/clock.h index cd58f372cfd..39720d6c0d0 100644 --- a/arch/arm/mach-pnx4008/clock.h +++ b/arch/arm/mach-pnx4008/clock.h @@ -14,8 +14,6 @@  #define __ARCH_ARM_PNX4008_CLOCK_H__  struct clk { -	struct list_head node; -	struct module *owner;  	const char *name;  	struct clk *parent;  	struct clk *propagate_next; @@ -29,9 +27,11 @@ struct clk {  	u8 enable_shift1;  	u32 enable_reg1;  	u32 parent_switch_reg; -	 u32(*round_rate) (struct clk *, u32); +	u32(*round_rate) (struct clk *, u32);  	int (*set_rate) (struct clk *, u32);  	int (*set_parent) (struct clk * clk, struct clk * parent); +	int (*enable)(struct clk *); +	void (*disable)(struct clk *);  };  /* Flags */ diff --git a/arch/arm/mach-pnx4008/i2c.c b/arch/arm/mach-pnx4008/i2c.c index f3fea29c00d..8103f9644e2 100644 --- a/arch/arm/mach-pnx4008/i2c.c +++ b/arch/arm/mach-pnx4008/i2c.c @@ -18,120 +18,24 @@  #include <mach/irqs.h>  #include <mach/i2c.h> -static int set_clock_run(struct platform_device *pdev) -{ -	struct clk *clk; -	char name[10]; -	int retval = 0; - -	snprintf(name, 10, "i2c%d_ck", pdev->id); -	clk = clk_get(&pdev->dev, name); -	if (!IS_ERR(clk)) { -		clk_set_rate(clk, 1); -		clk_put(clk); -	} else -		retval = -ENOENT; - -	return retval; -} - -static int set_clock_stop(struct platform_device *pdev) -{ -	struct clk *clk; -	char name[10]; -	int retval = 0; - -	snprintf(name, 10, "i2c%d_ck", pdev->id); -	clk = clk_get(&pdev->dev, name); -	if (!IS_ERR(clk)) { -		clk_set_rate(clk, 0); -		clk_put(clk); -	} else -		retval = -ENOENT; - -	return retval; -} - -static int i2c_pnx_suspend(struct platform_device *pdev, pm_message_t state) -{ -	int retval = 0; -#ifdef CONFIG_PM -	retval = set_clock_run(pdev); -#endif -	return retval; -} - -static int i2c_pnx_resume(struct platform_device *pdev) -{ -	int retval = 0; -#ifdef CONFIG_PM -	retval = set_clock_run(pdev); -#endif -	return retval; -} - -static u32 calculate_input_freq(struct platform_device *pdev) -{ -	return HCLK_MHZ; -} - - -static struct i2c_pnx_algo_data pnx_algo_data0 = { +static struct i2c_pnx_data i2c0_data = { +	.name = I2C_CHIP_NAME "0",  	.base = PNX4008_I2C1_BASE,  	.irq = I2C_1_INT,  }; -static struct i2c_pnx_algo_data pnx_algo_data1 = { +static struct i2c_pnx_data i2c1_data = { +	.name = I2C_CHIP_NAME "1",  	.base = PNX4008_I2C2_BASE,  	.irq = I2C_2_INT,  }; -static struct i2c_pnx_algo_data pnx_algo_data2 = { +static struct i2c_pnx_data i2c2_data = { +	.name = "USB-I2C",  	.base = (PNX4008_USB_CONFIG_BASE + 0x300),  	.irq = USB_I2C_INT,  }; -static struct i2c_adapter pnx_adapter0 = { -	.name = I2C_CHIP_NAME "0", -	.algo_data = &pnx_algo_data0, -}; -static struct i2c_adapter pnx_adapter1 = { -	.name = I2C_CHIP_NAME "1", -	.algo_data = &pnx_algo_data1, -}; - -static struct i2c_adapter pnx_adapter2 = { -	.name = "USB-I2C", -	.algo_data = &pnx_algo_data2, -}; - -static struct i2c_pnx_data i2c0_data = { -	.suspend = i2c_pnx_suspend, -	.resume = i2c_pnx_resume, -	.calculate_input_freq = calculate_input_freq, -	.set_clock_run = set_clock_run, -	.set_clock_stop = set_clock_stop, -	.adapter = &pnx_adapter0, -}; - -static struct i2c_pnx_data i2c1_data = { -	.suspend = i2c_pnx_suspend, -	.resume = i2c_pnx_resume, -	.calculate_input_freq = calculate_input_freq, -	.set_clock_run = set_clock_run, -	.set_clock_stop = set_clock_stop, -	.adapter = &pnx_adapter1, -}; - -static struct i2c_pnx_data i2c2_data = { -	.suspend = i2c_pnx_suspend, -	.resume = i2c_pnx_resume, -	.calculate_input_freq = calculate_input_freq, -	.set_clock_run = set_clock_run, -	.set_clock_stop = set_clock_stop, -	.adapter = &pnx_adapter2, -}; -  static struct platform_device i2c0_device = {  	.name = "pnx-i2c",  	.id = 0, diff --git a/arch/arm/mach-pnx4008/include/mach/clkdev.h b/arch/arm/mach-pnx4008/include/mach/clkdev.h new file mode 100644 index 00000000000..04b37a89801 --- /dev/null +++ b/arch/arm/mach-pnx4008/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/mach-pnx4008/include/mach/timex.h b/arch/arm/mach-pnx4008/include/mach/timex.h index 5ff0196c0f1..b383c7de7ab 100644 --- a/arch/arm/mach-pnx4008/include/mach/timex.h +++ b/arch/arm/mach-pnx4008/include/mach/timex.h @@ -14,60 +14,6 @@  #ifndef __PNX4008_TIMEX_H  #define __PNX4008_TIMEX_H -#include <linux/io.h> -#include <mach/hardware.h> -  #define CLOCK_TICK_RATE		1000000 -#define TICKS2USECS(x)	(x) - -/* MilliSecond Timer - Chapter 21 Page 202 */ - -#define MSTIM_INT     IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x0)) -#define MSTIM_CTRL    IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x4)) -#define MSTIM_COUNTER IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x8)) -#define MSTIM_MCTRL   IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x14)) -#define MSTIM_MATCH0  IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x18)) -#define MSTIM_MATCH1  IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x1c)) - -/* High Speed Timer - Chpater 22, Page 205 */ - -#define HSTIM_INT     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x0)) -#define HSTIM_CTRL    IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x4)) -#define HSTIM_COUNTER IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x8)) -#define HSTIM_PMATCH  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0xC)) -#define HSTIM_PCOUNT  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x10)) -#define HSTIM_MCTRL   IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x14)) -#define HSTIM_MATCH0  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x18)) -#define HSTIM_MATCH1  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x1c)) -#define HSTIM_MATCH2  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x20)) -#define HSTIM_CCR     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x28)) -#define HSTIM_CR0     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x2C)) -#define HSTIM_CR1     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x30)) - -/* IMPORTANT: both timers are UPCOUNTING */ - -/* xSTIM_MCTRL bit definitions */ -#define MR0_INT        1 -#define RESET_COUNT0   (1<<1) -#define STOP_COUNT0    (1<<2) -#define MR1_INT        (1<<3) -#define RESET_COUNT1   (1<<4) -#define STOP_COUNT1    (1<<5) -#define MR2_INT        (1<<6) -#define RESET_COUNT2   (1<<7) -#define STOP_COUNT2    (1<<8) - -/* xSTIM_CTRL bit definitions */ -#define COUNT_ENAB     1 -#define RESET_COUNT    (1<<1) -#define DEBUG_EN       (1<<2) - -/* xSTIM_INT bit definitions */ -#define MATCH0_INT     1 -#define MATCH1_INT     (1<<1) -#define MATCH2_INT     (1<<2) -#define RTC_TICK0      (1<<4) -#define RTC_TICK1      (1<<5) -  #endif diff --git a/arch/arm/mach-pnx4008/pm.c b/arch/arm/mach-pnx4008/pm.c index b3d8d53e32e..1f0585329be 100644 --- a/arch/arm/mach-pnx4008/pm.c +++ b/arch/arm/mach-pnx4008/pm.c @@ -21,6 +21,8 @@  #include <linux/io.h>  #include <asm/cacheflush.h> + +#include <mach/hardware.h>  #include <mach/pm.h>  #include <mach/clock.h> diff --git a/arch/arm/mach-pnx4008/time.c b/arch/arm/mach-pnx4008/time.c index fc0ba183fe1..0c8aad4bb0d 100644 --- a/arch/arm/mach-pnx4008/time.c +++ b/arch/arm/mach-pnx4008/time.c @@ -30,6 +30,8 @@  #include <asm/mach/time.h>  #include <asm/errno.h> +#include "time.h" +  /*! Note: all timers are UPCOUNTING */  /*! diff --git a/arch/arm/mach-pnx4008/time.h b/arch/arm/mach-pnx4008/time.h new file mode 100644 index 00000000000..75e88c570aa --- /dev/null +++ b/arch/arm/mach-pnx4008/time.h @@ -0,0 +1,70 @@ +/* + * arch/arm/mach-pnx4008/include/mach/timex.h + * + * PNX4008 timers header file + * + * Author: Dmitry Chigirev <source@mvista.com> + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef PNX_TIME_H +#define PNX_TIME_H + +#include <linux/io.h> +#include <mach/hardware.h> + +#define TICKS2USECS(x)	(x) + +/* MilliSecond Timer - Chapter 21 Page 202 */ + +#define MSTIM_INT     IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x0)) +#define MSTIM_CTRL    IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x4)) +#define MSTIM_COUNTER IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x8)) +#define MSTIM_MCTRL   IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x14)) +#define MSTIM_MATCH0  IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x18)) +#define MSTIM_MATCH1  IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x1c)) + +/* High Speed Timer - Chpater 22, Page 205 */ + +#define HSTIM_INT     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x0)) +#define HSTIM_CTRL    IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x4)) +#define HSTIM_COUNTER IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x8)) +#define HSTIM_PMATCH  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0xC)) +#define HSTIM_PCOUNT  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x10)) +#define HSTIM_MCTRL   IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x14)) +#define HSTIM_MATCH0  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x18)) +#define HSTIM_MATCH1  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x1c)) +#define HSTIM_MATCH2  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x20)) +#define HSTIM_CCR     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x28)) +#define HSTIM_CR0     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x2C)) +#define HSTIM_CR1     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x30)) + +/* IMPORTANT: both timers are UPCOUNTING */ + +/* xSTIM_MCTRL bit definitions */ +#define MR0_INT        1 +#define RESET_COUNT0   (1<<1) +#define STOP_COUNT0    (1<<2) +#define MR1_INT        (1<<3) +#define RESET_COUNT1   (1<<4) +#define STOP_COUNT1    (1<<5) +#define MR2_INT        (1<<6) +#define RESET_COUNT2   (1<<7) +#define STOP_COUNT2    (1<<8) + +/* xSTIM_CTRL bit definitions */ +#define COUNT_ENAB     1 +#define RESET_COUNT    (1<<1) +#define DEBUG_EN       (1<<2) + +/* xSTIM_INT bit definitions */ +#define MATCH0_INT     1 +#define MATCH1_INT     (1<<1) +#define MATCH2_INT     (1<<2) +#define RTC_TICK0      (1<<4) +#define RTC_TICK1      (1<<5) + +#endif diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c index 49ae3829231..abba0089a2a 100644 --- a/arch/arm/mach-pxa/clock.c +++ b/arch/arm/mach-pxa/clock.c @@ -78,11 +78,3 @@ const struct clkops clk_cken_ops = {  	.enable		= clk_cken_enable,  	.disable	= clk_cken_disable,  }; - -void clks_register(struct clk_lookup *clks, size_t num) -{ -	int i; - -	for (i = 0; i < num; i++) -		clkdev_add(&clks[i]); -} diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h index 978a3667e90..d8488742b80 100644 --- a/arch/arm/mach-pxa/clock.h +++ b/arch/arm/mach-pxa/clock.h @@ -67,7 +67,3 @@ extern void clk_pxa3xx_cken_enable(struct clk *);  extern void clk_pxa3xx_cken_disable(struct clk *);  #endif -void clks_register(struct clk_lookup *clks, size_t num); -int clk_add_alias(const char *alias, const char *alias_name, char *id, -	struct device *dev); - diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c index 91417f03506..96ed1308163 100644 --- a/arch/arm/mach-pxa/eseries.c +++ b/arch/arm/mach-pxa/eseries.c @@ -128,6 +128,6 @@ static struct clk_lookup eseries_clkregs[] = {  void eseries_register_clks(void)  { -	clks_register(eseries_clkregs, ARRAY_SIZE(eseries_clkregs)); +	clkdev_add_table(eseries_clkregs, ARRAY_SIZE(eseries_clkregs));  } diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 2c1b0b70d01..0b9ad30bfd5 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -349,7 +349,7 @@ static int __init pxa25x_init(void)  		reset_status = RCSR; -		clks_register(pxa25x_clkregs, ARRAY_SIZE(pxa25x_clkregs)); +		clkdev_add_table(pxa25x_clkregs, ARRAY_SIZE(pxa25x_clkregs));  		if ((ret = pxa_init_dma(IRQ_DMA, 16)))  			return ret; @@ -370,7 +370,7 @@ static int __init pxa25x_init(void)  	/* Only add HWUART for PXA255/26x; PXA210/250 do not have it. */  	if (cpu_is_pxa255()) -		clks_register(&pxa25x_hwuart_clkreg, 1); +		clkdev_add(&pxa25x_hwuart_clkreg);  	return ret;  } diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 6a0b73167e0..d783123e2d4 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -392,7 +392,7 @@ static int __init pxa27x_init(void)  		reset_status = RCSR; -		clks_register(pxa27x_clkregs, ARRAY_SIZE(pxa27x_clkregs)); +		clkdev_add_table(pxa27x_clkregs, ARRAY_SIZE(pxa27x_clkregs));  		if ((ret = pxa_init_dma(IRQ_DMA, 32)))  			return ret; diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c index f4af6e2bef8..40bb16501d8 100644 --- a/arch/arm/mach-pxa/pxa300.c +++ b/arch/arm/mach-pxa/pxa300.c @@ -102,12 +102,12 @@ static int __init pxa300_init(void)  	if (cpu_is_pxa300() || cpu_is_pxa310()) {  		mfp_init_base(io_p2v(MFPR_BASE));  		mfp_init_addr(pxa300_mfp_addr_map); -		clks_register(ARRAY_AND_SIZE(common_clkregs)); +		clkdev_add_table(ARRAY_AND_SIZE(common_clkregs));  	}  	if (cpu_is_pxa310()) {  		mfp_init_addr(pxa310_mfp_addr_map); -		clks_register(ARRAY_AND_SIZE(pxa310_clkregs)); +		clkdev_add_table(ARRAY_AND_SIZE(pxa310_clkregs));  	}  	return 0; diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c index c7373e74a10..8d614ecd8e9 100644 --- a/arch/arm/mach-pxa/pxa320.c +++ b/arch/arm/mach-pxa/pxa320.c @@ -90,7 +90,7 @@ static int __init pxa320_init(void)  	if (cpu_is_pxa320()) {  		mfp_init_base(io_p2v(MFPR_BASE));  		mfp_init_addr(pxa320_mfp_addr_map); -		clks_register(ARRAY_AND_SIZE(pxa320_clkregs)); +		clkdev_add_table(ARRAY_AND_SIZE(pxa320_clkregs));  	}  	return 0; diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index fcb0721f466..4d7c03e7250 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -634,7 +634,7 @@ static int __init pxa3xx_init(void)  		 */  		ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S); -		clks_register(pxa3xx_clkregs, ARRAY_SIZE(pxa3xx_clkregs)); +		clkdev_add_table(pxa3xx_clkregs, ARRAY_SIZE(pxa3xx_clkregs));  		if ((ret = pxa_init_dma(IRQ_DMA, 32)))  			return ret; diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 9f293438e02..90bd4ef71b2 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -346,10 +346,7 @@ static struct clk_lookup lookups[] = {  static int __init clk_init(void)  { -	int i; - -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  	return 0;  }  arch_initcall(clk_init); diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c index 36ffd6a8b34..5af71d5ba66 100644 --- a/arch/arm/mach-u300/clock.c +++ b/arch/arm/mach-u300/clock.c @@ -1276,11 +1276,8 @@ static struct clk_lookup lookups[] = {  static void __init clk_register(void)  { -	int i; -  	/* Register the lookups */ -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  }  /* diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 20b6ebb6783..8359a73d004 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -85,11 +85,8 @@ static struct clk_lookup lookups[] = {  static int __init clk_init(void)  { -	int i; -  	/* register the clock lookups */ -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  	return 0;  }  arch_initcall(clk_init); diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index e13be7c444c..9ddb49b1cb7 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -851,8 +851,7 @@ void __init versatile_init(void)  {  	int i; -	for (i = 0; i < ARRAY_SIZE(lookups); i++) -		clkdev_add(&lookups[i]); +	clkdev_add_table(lookups, ARRAY_SIZE(lookups));  	platform_device_register(&versatile_flash_device);  	platform_device_register(&versatile_i2c_device); diff --git a/arch/arm/mach-w90x900/clock.c b/arch/arm/mach-w90x900/clock.c index b785994bab0..2c371ff22e5 100644 --- a/arch/arm/mach-w90x900/clock.c +++ b/arch/arm/mach-w90x900/clock.c @@ -90,12 +90,3 @@ void nuc900_subclk_enable(struct clk *clk, int enable)  	__raw_writel(clken, W90X900_VA_CLKPWR + SUBCLK);  } - - -void clks_register(struct clk_lookup *clks, size_t num) -{ -	int i; - -	for (i = 0; i < num; i++) -		clkdev_add(&clks[i]); -} diff --git a/arch/arm/mach-w90x900/clock.h b/arch/arm/mach-w90x900/clock.h index f5816a06eed..c56ddab3d91 100644 --- a/arch/arm/mach-w90x900/clock.h +++ b/arch/arm/mach-w90x900/clock.h @@ -14,7 +14,6 @@  void nuc900_clk_enable(struct clk *clk, int enable);  void nuc900_subclk_enable(struct clk *clk, int enable); -void clks_register(struct clk_lookup *clks, size_t num);  struct clk {  	unsigned long		cken; diff --git a/arch/arm/mach-w90x900/cpu.c b/arch/arm/mach-w90x900/cpu.c index e44b0a0ecf4..642207e1819 100644 --- a/arch/arm/mach-w90x900/cpu.c +++ b/arch/arm/mach-w90x900/cpu.c @@ -219,6 +219,6 @@ void __init nuc900_map_io(struct map_desc *mach_desc, int mach_size)  void __init nuc900_init_clocks(void)  { -	clks_register(nuc900_clkregs, ARRAY_SIZE(nuc900_clkregs)); +	clkdev_add_table(nuc900_clkregs, ARRAY_SIZE(nuc900_clkregs));  } diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 88f5d71248d..9d4da6ac28e 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1068,4 +1068,6 @@ void setup_mm_for_reboot(char mode)  		pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));  		flush_pmd_entry(pmd);  	} + +	local_flush_tlb_all();  } diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 395cc90c661..7a5337ed7d6 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -59,8 +59,6 @@ ENTRY(cpu_v6_proc_fin)   *	to what would be the reset vector.   *   *	- loc   - location to jump to for soft reset - * - *	It is assumed that:   */  	.align	5  ENTRY(cpu_v6_reset) diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 3a285218fd1..7aaf88a3b7a 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -45,7 +45,14 @@ ENTRY(cpu_v7_proc_init)  ENDPROC(cpu_v7_proc_init)  ENTRY(cpu_v7_proc_fin) -	mov	pc, lr +	stmfd	sp!, {lr} +	cpsid	if				@ disable interrupts +	bl	v7_flush_kern_cache_all +	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register +	bic	r0, r0, #0x1000			@ ...i............ +	bic	r0, r0, #0x0006			@ .............ca. +	mcr	p15, 0, r0, c1, c0, 0		@ disable caches +	ldmfd	sp!, {pc}  ENDPROC(cpu_v7_proc_fin)  /* @@ -56,8 +63,6 @@ ENDPROC(cpu_v7_proc_fin)   *	to what would be the reset vector.   *   *	- loc   - location to jump to for soft reset - * - *	It is assumed that:   */  	.align	5  ENTRY(cpu_v7_reset) diff --git a/arch/arm/plat-stmp3xxx/clock.c b/arch/arm/plat-stmp3xxx/clock.c index 5d2f19a09e4..e593a2a801c 100644 --- a/arch/arm/plat-stmp3xxx/clock.c +++ b/arch/arm/plat-stmp3xxx/clock.c @@ -1126,9 +1126,8 @@ static int __init clk_init(void)  			if (ops && ops->set_parent)  				ops->set_parent(cl->clk, cl->clk->parent);  		} - -		clkdev_add(cl);  	} +	clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks));  	return 0;  } diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 5d0f70b46c9..858ecb25d46 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -533,7 +533,7 @@ static int __init sh_eth_is_eeprom_ready(void)  	while (t--) {  		if (!ctrl_inw(EEPROM_STAT))  			return 1; -		cpu_relax(); +		udelay(1);  	}  	printk(KERN_ERR "ms7724se can not access to eeprom\n"); diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h index f18c4f9baf2..365744b0526 100644 --- a/arch/sh/include/asm/unistd_32.h +++ b/arch/sh/include/asm/unistd_32.h @@ -345,12 +345,13 @@  #define __NR_pwritev		334  #define __NR_rt_tgsigqueueinfo	335  #define __NR_perf_event_open	336 -#define __NR_recvmmsg		337 -#define NR_syscalls 338 +#define NR_syscalls 337  #ifdef __KERNEL__ +#define __IGNORE_recvmmsg +  #define __ARCH_WANT_IPC_PARSE_VERSION  #define __ARCH_WANT_OLD_READDIR  #define __ARCH_WANT_OLD_STAT diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h index 3e7645d1113..25de158aac3 100644 --- a/arch/sh/include/asm/unistd_64.h +++ b/arch/sh/include/asm/unistd_64.h @@ -386,10 +386,11 @@  #define __NR_rt_tgsigqueueinfo	363  #define __NR_perf_event_open	364  #define __NR_recvmmsg		365 +#define __NR_accept4		366  #ifdef __KERNEL__ -#define NR_syscalls 366 +#define NR_syscalls 367  #define __ARCH_WANT_IPC_PARSE_VERSION  #define __ARCH_WANT_OLD_READDIR diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index 4bd5a114695..19fd11dd987 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S @@ -353,4 +353,3 @@ ENTRY(sys_call_table)  	.long sys_pwritev  	.long sys_rt_tgsigqueueinfo	/* 335 */  	.long sys_perf_event_open -	.long sys_recvmmsg diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 07d2aaea9ae..2048a20d7c8 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S @@ -392,3 +392,4 @@ sys_call_table:  	.long sys_rt_tgsigqueueinfo  	.long sys_perf_event_open  	.long sys_recvmmsg		/* 365 */ +	.long sys_accept4 diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index 8d9f8548a87..1380367dabd 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -19,6 +19,7 @@  #define MSR_ARCH_PERFMON_EVENTSEL1			     0x187  #define ARCH_PERFMON_EVENTSEL0_ENABLE			  (1 << 22) +#define ARCH_PERFMON_EVENTSEL_ANY			  (1 << 21)  #define ARCH_PERFMON_EVENTSEL_INT			  (1 << 20)  #define ARCH_PERFMON_EVENTSEL_OS			  (1 << 17)  #define ARCH_PERFMON_EVENTSEL_USR			  (1 << 16) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index fb1035cd9a6..036d28adf59 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1529,16 +1529,10 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = {   *	if acpi_blacklisted() acpi_disabled = 1;   *	acpi_irq_model=...   *	... - * - * return value: (currently ignored) - *	0: success - *	!0: failure   */ -int __init acpi_boot_table_init(void) +void __init acpi_boot_table_init(void)  { -	int error; -  	dmi_check_system(acpi_dmi_table);  	/* @@ -1546,15 +1540,14 @@ int __init acpi_boot_table_init(void)  	 * One exception: acpi=ht continues far enough to enumerate LAPICs  	 */  	if (acpi_disabled && !acpi_ht) -		return 1; +		return;   	/*  	 * Initialize the ACPI boot-time table parser.  	 */ -	error = acpi_table_init(); -	if (error) { +	if (acpi_table_init()) {  		disable_acpi(); -		return error; +		return;  	}  	acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); @@ -1562,18 +1555,15 @@ int __init acpi_boot_table_init(void)  	/*  	 * blacklist may disable ACPI entirely  	 */ -	error = acpi_blacklisted(); -	if (error) { +	if (acpi_blacklisted()) {  		if (acpi_force) {  			printk(KERN_WARNING PREFIX "acpi=force override\n");  		} else {  			printk(KERN_WARNING PREFIX "Disabling ACPI support\n");  			disable_acpi(); -			return error; +			return;  		}  	} - -	return 0;  }  int __init early_acpi_boot_init(void) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index d616c06e99b..8c1c07073cc 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1343,6 +1343,13 @@ intel_pmu_enable_fixed(struct hw_perf_event *hwc, int __idx)  		bits |= 0x2;  	if (hwc->config & ARCH_PERFMON_EVENTSEL_OS)  		bits |= 0x1; + +	/* +	 * ANY bit is supported in v3 and up +	 */ +	if (x86_pmu.version > 2 && hwc->config & ARCH_PERFMON_EVENTSEL_ANY) +		bits |= 0x4; +  	bits <<= (idx * 4);  	mask = 0xfULL << (idx * 4); diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c index c0f6198565e..536fb682336 100644 --- a/arch/x86/mm/kmmio.c +++ b/arch/x86/mm/kmmio.c @@ -538,14 +538,15 @@ static int  kmmio_die_notifier(struct notifier_block *nb, unsigned long val, void *args)  {  	struct die_args *arg = args; +	unsigned long* dr6_p = (unsigned long *)ERR_PTR(arg->err); -	if (val == DIE_DEBUG && (arg->err & DR_STEP)) -		if (post_kmmio_handler(arg->err, arg->regs) == 1) { +	if (val == DIE_DEBUG && (*dr6_p & DR_STEP)) +		if (post_kmmio_handler(*dr6_p, arg->regs) == 1) {  			/*  			 * Reset the BS bit in dr6 (pointed by args->err) to  			 * denote completion of processing  			 */ -			(*(unsigned long *)ERR_PTR(arg->err)) &= ~DR_STEP; +			*dr6_p &= ~DR_STEP;  			return NOTIFY_STOP;  		} diff --git a/block/blk-ioc.c b/block/blk-ioc.c index cbdabb0dd6d..98e6bf61b0a 100644 --- a/block/blk-ioc.c +++ b/block/blk-ioc.c @@ -39,8 +39,6 @@ int put_io_context(struct io_context *ioc)  	if (atomic_long_dec_and_test(&ioc->refcount)) {  		rcu_read_lock(); -		if (ioc->aic && ioc->aic->dtor) -			ioc->aic->dtor(ioc->aic);  		cfq_dtor(ioc);  		rcu_read_unlock(); @@ -76,8 +74,6 @@ void exit_io_context(struct task_struct *task)  	task_unlock(task);  	if (atomic_dec_and_test(&ioc->nr_tasks)) { -		if (ioc->aic && ioc->aic->exit) -			ioc->aic->exit(ioc->aic);  		cfq_exit(ioc);  	} @@ -97,7 +93,6 @@ struct io_context *alloc_io_context(gfp_t gfp_flags, int node)  		ret->ioprio = 0;  		ret->last_waited = jiffies; /* doesn't matter... */  		ret->nr_batch_requests = 0; /* because this is 0 */ -		ret->aic = NULL;  		INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH);  		INIT_HLIST_HEAD(&ret->cic_list);  		ret->ioc_data = NULL; diff --git a/block/blk-settings.c b/block/blk-settings.c index d52d4adc440..5eeb9e0d256 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -528,7 +528,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,  		     sector_t offset)  {  	sector_t alignment; -	unsigned int top, bottom; +	unsigned int top, bottom, ret = 0;  	t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);  	t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors); @@ -546,6 +546,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,  	t->max_segment_size = min_not_zero(t->max_segment_size,  					   b->max_segment_size); +	t->misaligned |= b->misaligned; +  	alignment = queue_limit_alignment_offset(b, offset);  	/* Bottom device has different alignment.  Check that it is @@ -558,8 +560,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,  		bottom = max(b->physical_block_size, b->io_min) + alignment;  		/* Verify that top and bottom intervals line up */ -		if (max(top, bottom) & (min(top, bottom) - 1)) +		if (max(top, bottom) & (min(top, bottom) - 1)) {  			t->misaligned = 1; +			ret = -1; +		}  	}  	t->logical_block_size = max(t->logical_block_size, @@ -578,18 +582,21 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,  	if (t->physical_block_size & (t->logical_block_size - 1)) {  		t->physical_block_size = t->logical_block_size;  		t->misaligned = 1; +		ret = -1;  	}  	/* Minimum I/O a multiple of the physical block size? */  	if (t->io_min & (t->physical_block_size - 1)) {  		t->io_min = t->physical_block_size;  		t->misaligned = 1; +		ret = -1;  	}  	/* Optimal I/O a multiple of the physical block size? */  	if (t->io_opt & (t->physical_block_size - 1)) {  		t->io_opt = 0;  		t->misaligned = 1; +		ret = -1;  	}  	/* Find lowest common alignment_offset */ @@ -597,8 +604,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,  		& (max(t->physical_block_size, t->io_min) - 1);  	/* Verify that new alignment_offset is on a logical block boundary */ -	if (t->alignment_offset & (t->logical_block_size - 1)) +	if (t->alignment_offset & (t->logical_block_size - 1)) {  		t->misaligned = 1; +		ret = -1; +	}  	/* Discard alignment and granularity */  	if (b->discard_granularity) { @@ -626,11 +635,33 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,  			(t->discard_granularity - 1);  	} -	return t->misaligned ? -1 : 0; +	return ret;  }  EXPORT_SYMBOL(blk_stack_limits);  /** + * bdev_stack_limits - adjust queue limits for stacked drivers + * @t:	the stacking driver limits (top device) + * @bdev:  the component block_device (bottom) + * @start:  first data sector within component device + * + * Description: + *    Merges queue limits for a top device and a block_device.  Returns + *    0 if alignment didn't change.  Returns -1 if adding the bottom + *    device caused misalignment. + */ +int bdev_stack_limits(struct queue_limits *t, struct block_device *bdev, +		      sector_t start) +{ +	struct request_queue *bq = bdev_get_queue(bdev); + +	start += get_start_sect(bdev); + +	return blk_stack_limits(t, &bq->limits, start << 9); +} +EXPORT_SYMBOL(bdev_stack_limits); + +/**   * disk_stack_limits - adjust queue limits for stacked drivers   * @disk:  MD/DM gendisk (top)   * @bdev:  the underlying block device (bottom) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 918c7fd9aeb..ee130f14d1f 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -3077,6 +3077,12 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,  		return true;  	/* +	 * Don't allow a non-RT request to preempt an ongoing RT cfqq timeslice. +	 */ +	if (cfq_class_rt(cfqq) && !cfq_class_rt(new_cfqq)) +		return false; + +	/*  	 * if the new request is sync, but the currently running queue is  	 * not, let the sync request have priority.  	 */ diff --git a/block/genhd.c b/block/genhd.c index b11a4ad7d57..d13ba76a169 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -867,7 +867,7 @@ static ssize_t disk_discard_alignment_show(struct device *dev,  {  	struct gendisk *disk = dev_to_disk(dev); -	return sprintf(buf, "%u\n", queue_discard_alignment(disk->queue)); +	return sprintf(buf, "%d\n", queue_discard_alignment(disk->queue));  }  static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 97991ac6f5f..7e52295f1ec 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -208,7 +208,7 @@ static int power_saving_thread(void *data)  		 * the mechanism only works when all CPUs have RT task running,  		 * as if one CPU hasn't RT task, RT task from other CPUs will  		 * borrow CPU time from this CPU and cause RT task use > 95% -		 * CPU time. To make 'avoid staration' work, takes a nap here. +		 * CPU time. To make 'avoid starvation' work, takes a nap here.  		 */  		if (do_sleep)  			schedule_timeout_killable(HZ * idle_pct / 100); @@ -222,14 +222,18 @@ static struct task_struct *ps_tsks[NR_CPUS];  static unsigned int ps_tsk_num;  static int create_power_saving_task(void)  { +	int rc = -ENOMEM; +  	ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread,  		(void *)(unsigned long)ps_tsk_num,  		"power_saving/%d", ps_tsk_num); -	if (ps_tsks[ps_tsk_num]) { +	rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0; +	if (!rc)  		ps_tsk_num++; -		return 0; -	} -	return -EINVAL; +	else +		ps_tsks[ps_tsk_num] = NULL; + +	return rc;  }  static void destroy_power_saving_task(void) @@ -237,6 +241,7 @@ static void destroy_power_saving_task(void)  	if (ps_tsk_num > 0) {  		ps_tsk_num--;  		kthread_stop(ps_tsks[ps_tsk_num]); +		ps_tsks[ps_tsk_num] = NULL;  	}  } @@ -253,7 +258,7 @@ static void set_power_saving_task_num(unsigned int num)  	}  } -static int acpi_pad_idle_cpus(unsigned int num_cpus) +static void acpi_pad_idle_cpus(unsigned int num_cpus)  {  	get_online_cpus(); @@ -261,7 +266,6 @@ static int acpi_pad_idle_cpus(unsigned int num_cpus)  	set_power_saving_task_num(num_cpus);  	put_online_cpus(); -	return 0;  }  static uint32_t acpi_pad_idle_cpus_num(void) @@ -369,19 +373,21 @@ static void acpi_pad_remove_sysfs(struct acpi_device *device)  static int acpi_pad_pur(acpi_handle handle, int *num_cpus)  {  	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; -	acpi_status status;  	union acpi_object *package;  	int rev, num, ret = -EINVAL; -	status = acpi_evaluate_object(handle, "_PUR", NULL, &buffer); -	if (ACPI_FAILURE(status)) +	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer))) +		return -EINVAL; + +	if (!buffer.length || !buffer.pointer)  		return -EINVAL; +  	package = buffer.pointer;  	if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2)  		goto out;  	rev = package->package.elements[0].integer.value;  	num = package->package.elements[1].integer.value; -	if (rev != 1) +	if (rev != 1 || num < 0)  		goto out;  	*num_cpus = num;  	ret = 0; @@ -410,7 +416,7 @@ static void acpi_pad_ost(acpi_handle handle, int stat,  static void acpi_pad_handle_notify(acpi_handle handle)  { -	int num_cpus, ret; +	int num_cpus;  	uint32_t idle_cpus;  	mutex_lock(&isolated_cpus_lock); @@ -418,12 +424,9 @@ static void acpi_pad_handle_notify(acpi_handle handle)  		mutex_unlock(&isolated_cpus_lock);  		return;  	} -	ret = acpi_pad_idle_cpus(num_cpus); +	acpi_pad_idle_cpus(num_cpus);  	idle_cpus = acpi_pad_idle_cpus_num(); -	if (!ret) -		acpi_pad_ost(handle, 0, idle_cpus); -	else -		acpi_pad_ost(handle, 1, 0); +	acpi_pad_ost(handle, 0, idle_cpus);  	mutex_unlock(&isolated_cpus_lock);  } diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index cf761b904e4..a52126e4630 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -490,9 +490,14 @@ static void acpi_bus_osc_support(void)  	capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;  	capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ -#ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR +#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ +			defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)  	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT;  #endif + +#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) +	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; +#endif  	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))  		return;  	if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index fd1801bdee6..d6471bb6852 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -201,14 +201,13 @@ unlock:  	spin_unlock_irqrestore(&ec->curr_lock, flags);  } -static void acpi_ec_gpe_query(void *ec_cxt); +static int acpi_ec_sync_query(struct acpi_ec *ec); -static int ec_check_sci(struct acpi_ec *ec, u8 state) +static int ec_check_sci_sync(struct acpi_ec *ec, u8 state)  {  	if (state & ACPI_EC_FLAG_SCI) {  		if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) -			return acpi_os_execute(OSL_EC_BURST_HANDLER, -				acpi_ec_gpe_query, ec); +			return acpi_ec_sync_query(ec);  	}  	return 0;  } @@ -249,11 +248,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,  {  	unsigned long tmp;  	int ret = 0; -	pr_debug(PREFIX "transaction start\n"); -	/* disable GPE during transaction if storm is detected */ -	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { -		acpi_disable_gpe(NULL, ec->gpe); -	}  	if (EC_FLAGS_MSI)  		udelay(ACPI_EC_MSI_UDELAY);  	/* start transaction */ @@ -265,20 +259,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,  		clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);  	spin_unlock_irqrestore(&ec->curr_lock, tmp);  	ret = ec_poll(ec); -	pr_debug(PREFIX "transaction end\n");  	spin_lock_irqsave(&ec->curr_lock, tmp);  	ec->curr = NULL;  	spin_unlock_irqrestore(&ec->curr_lock, tmp); -	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { -		/* check if we received SCI during transaction */ -		ec_check_sci(ec, acpi_ec_read_status(ec)); -		/* it is safe to enable GPE outside of transaction */ -		acpi_enable_gpe(NULL, ec->gpe); -	} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { -		pr_info(PREFIX "GPE storm detected, " -			"transactions will use polling mode\n"); -		set_bit(EC_FLAGS_GPE_STORM, &ec->flags); -	}  	return ret;  } @@ -321,7 +304,26 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)  		status = -ETIME;  		goto end;  	} +	pr_debug(PREFIX "transaction start\n"); +	/* disable GPE during transaction if storm is detected */ +	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { +		acpi_disable_gpe(NULL, ec->gpe); +	} +  	status = acpi_ec_transaction_unlocked(ec, t); + +	/* check if we received SCI during transaction */ +	ec_check_sci_sync(ec, acpi_ec_read_status(ec)); +	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { +		msleep(1); +		/* it is safe to enable GPE outside of transaction */ +		acpi_enable_gpe(NULL, ec->gpe); +	} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { +		pr_info(PREFIX "GPE storm detected, " +			"transactions will use polling mode\n"); +		set_bit(EC_FLAGS_GPE_STORM, &ec->flags); +	} +	pr_debug(PREFIX "transaction end\n");  end:  	if (ec->global_lock)  		acpi_release_global_lock(glk); @@ -443,7 +445,7 @@ int ec_transaction(u8 command,  EXPORT_SYMBOL(ec_transaction); -static int acpi_ec_query(struct acpi_ec *ec, u8 * data) +static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)  {  	int result;  	u8 d; @@ -452,20 +454,16 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)  				.wlen = 0, .rlen = 1};  	if (!ec || !data)  		return -EINVAL; -  	/*  	 * Query the EC to find out which _Qxx method we need to evaluate.  	 * Note that successful completion of the query causes the ACPI_EC_SCI  	 * bit to be cleared (and thus clearing the interrupt source).  	 */ - -	result = acpi_ec_transaction(ec, &t); +	result = acpi_ec_transaction_unlocked(ec, &t);  	if (result)  		return result; -  	if (!d)  		return -ENODATA; -  	*data = d;  	return 0;  } @@ -509,43 +507,79 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)  EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); -static void acpi_ec_gpe_query(void *ec_cxt) +static void acpi_ec_run(void *cxt)  { -	struct acpi_ec *ec = ec_cxt; -	u8 value = 0; -	struct acpi_ec_query_handler *handler, copy; - -	if (!ec || acpi_ec_query(ec, &value)) +	struct acpi_ec_query_handler *handler = cxt; +	if (!handler)  		return; -	mutex_lock(&ec->lock); +	pr_debug(PREFIX "start query execution\n"); +	if (handler->func) +		handler->func(handler->data); +	else if (handler->handle) +		acpi_evaluate_object(handler->handle, NULL, NULL, NULL); +	pr_debug(PREFIX "stop query execution\n"); +	kfree(handler); +} + +static int acpi_ec_sync_query(struct acpi_ec *ec) +{ +	u8 value = 0; +	int status; +	struct acpi_ec_query_handler *handler, *copy; +	if ((status = acpi_ec_query_unlocked(ec, &value))) +		return status;  	list_for_each_entry(handler, &ec->list, node) {  		if (value == handler->query_bit) {  			/* have custom handler for this bit */ -			memcpy(©, handler, sizeof(copy)); -			mutex_unlock(&ec->lock); -			if (copy.func) { -				copy.func(copy.data); -			} else if (copy.handle) { -				acpi_evaluate_object(copy.handle, NULL, NULL, NULL); -			} -			return; +			copy = kmalloc(sizeof(*handler), GFP_KERNEL); +			if (!copy) +				return -ENOMEM; +			memcpy(copy, handler, sizeof(*copy)); +			pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); +			return acpi_os_execute((copy->func) ? +				OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, +				acpi_ec_run, copy);  		}  	} +	return 0; +} + +static void acpi_ec_gpe_query(void *ec_cxt) +{ +	struct acpi_ec *ec = ec_cxt; +	if (!ec) +		return; +	mutex_lock(&ec->lock); +	acpi_ec_sync_query(ec);  	mutex_unlock(&ec->lock);  } +static void acpi_ec_gpe_query(void *ec_cxt); + +static int ec_check_sci(struct acpi_ec *ec, u8 state) +{ +	if (state & ACPI_EC_FLAG_SCI) { +		if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { +			pr_debug(PREFIX "push gpe query to the queue\n"); +			return acpi_os_execute(OSL_NOTIFY_HANDLER, +				acpi_ec_gpe_query, ec); +		} +	} +	return 0; +} +  static u32 acpi_ec_gpe_handler(void *data)  {  	struct acpi_ec *ec = data; -	u8 status;  	pr_debug(PREFIX "~~~> interrupt\n"); -	status = acpi_ec_read_status(ec); -	advance_transaction(ec, status); -	if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) +	advance_transaction(ec, acpi_ec_read_status(ec)); +	if (ec_transaction_done(ec) && +	    (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {  		wake_up(&ec->wait); -	ec_check_sci(ec, status); +		ec_check_sci(ec, acpi_ec_read_status(ec)); +	}  	return ACPI_INTERRUPT_HANDLED;  } diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 394ae89409c..04b0f007c9b 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -56,7 +56,7 @@ ACPI_MODULE_NAME("pci_link");  static int acpi_pci_link_add(struct acpi_device *device);  static int acpi_pci_link_remove(struct acpi_device *device, int type); -static struct acpi_device_id link_device_ids[] = { +static const struct acpi_device_id link_device_ids[] = {  	{"PNP0C0F", 0},  	{"", 0},  }; diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 101cce3681d..64f55b6db73 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -46,7 +46,7 @@ static int acpi_pci_root_add(struct acpi_device *device);  static int acpi_pci_root_remove(struct acpi_device *device, int type);  static int acpi_pci_root_start(struct acpi_device *device); -static struct acpi_device_id root_device_ids[] = { +static const struct acpi_device_id root_device_ids[] = {  	{"PNP0A03", 0},  	{"", 0},  }; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 22b29791651..0f30c3c1eea 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -65,7 +65,7 @@ static int acpi_power_remove(struct acpi_device *device, int type);  static int acpi_power_resume(struct acpi_device *device);  static int acpi_power_open_fs(struct inode *inode, struct file *file); -static struct acpi_device_id power_device_ids[] = { +static const struct acpi_device_id power_device_ids[] = {  	{ACPI_POWER_HID, 0},  	{"", 0},  }; diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index 2ef7030a0c2..dc4ffadf812 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c @@ -64,7 +64,7 @@ static int can_cap_in_hardware(void)  	return force_cap_on || cap_in_hardware;  } -static struct acpi_device_id power_meter_ids[] = { +static const struct acpi_device_id power_meter_ids[] = {  	{"ACPI000D", 0},  	{"", 0},  }; @@ -534,6 +534,7 @@ static void remove_domain_devices(struct acpi_power_meter_resource *resource)  	kfree(resource->domain_devices);  	kobject_put(resource->holders_dir); +	resource->num_domain_devices = 0;  }  static int read_domain_devices(struct acpi_power_meter_resource *resource) @@ -740,7 +741,6 @@ skip_unsafe_cap:  	return res;  error: -	remove_domain_devices(resource);  	remove_attrs(resource);  	return res;  } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d1676b1754d..7c0441f63b3 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -305,6 +305,28 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)  	pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency;  	pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; +	/* +	 * FADT specified C2 latency must be less than or equal to +	 * 100 microseconds. +	 */ +	if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { +		ACPI_DEBUG_PRINT((ACPI_DB_INFO, +			"C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency)); +		/* invalidate C2 */ +		pr->power.states[ACPI_STATE_C2].address = 0; +	} + +	/* +	 * FADT supplied C3 latency must be less than or equal to +	 * 1000 microseconds. +	 */ +	if (acpi_gbl_FADT.C3latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { +		ACPI_DEBUG_PRINT((ACPI_DB_INFO, +			"C3 latency too large [%d]\n", acpi_gbl_FADT.C3latency)); +		/* invalidate C3 */ +		pr->power.states[ACPI_STATE_C3].address = 0; +	} +  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,  			  "lvl2[0x%08x] lvl3[0x%08x]\n",  			  pr->power.states[ACPI_STATE_C2].address, @@ -494,33 +516,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)  	return status;  } -static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) -{ - -	if (!cx->address) -		return; - -	/* -	 * C2 latency must be less than or equal to 100 -	 * microseconds. -	 */ -	else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { -		ACPI_DEBUG_PRINT((ACPI_DB_INFO, -				  "latency too large [%d]\n", cx->latency)); -		return; -	} - -	/* -	 * Otherwise we've met all of our C2 requirements. -	 * Normalize the C2 latency to expidite policy -	 */ -	cx->valid = 1; - -	cx->latency_ticks = cx->latency; - -	return; -} -  static void acpi_processor_power_verify_c3(struct acpi_processor *pr,  					   struct acpi_processor_cx *cx)  { @@ -532,16 +527,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,  		return;  	/* -	 * C3 latency must be less than or equal to 1000 -	 * microseconds. -	 */ -	else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { -		ACPI_DEBUG_PRINT((ACPI_DB_INFO, -				  "latency too large [%d]\n", cx->latency)); -		return; -	} - -	/*  	 * PIIX4 Erratum #18: We don't support C3 when Type-F (fast)  	 * DMA transfers are used by any ISA device to avoid livelock.  	 * Note that we could disable Type-F DMA (as recommended by @@ -629,7 +614,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)  			break;  		case ACPI_STATE_C2: -			acpi_processor_power_verify_c2(cx); +			if (!cx->address) +				break; +			cx->valid = 1;  +			cx->latency_ticks = cx->latency; /* Normalize latency */  			break;  		case ACPI_STATE_C3: diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 30e4dc0cdf3..7247819dbd8 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -144,6 +144,29 @@ void acpi_processor_set_pdc(acpi_handle handle)  }  EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); +static int early_pdc_optin; +static int set_early_pdc_optin(const struct dmi_system_id *id) +{ +	early_pdc_optin = 1; +	return 0; +} + +static struct dmi_system_id __cpuinitdata early_pdc_optin_table[] = { +	{ +	set_early_pdc_optin, "HP Envy", { +	DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), +	DMI_MATCH(DMI_PRODUCT_NAME, "HP Envy") }, NULL}, +	{ +	set_early_pdc_optin, "HP Pavilion dv6", { +	DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), +	DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6") }, NULL}, +	{ +	set_early_pdc_optin, "HP Pavilion dv7", { +	DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), +	DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7") }, NULL}, +	{}, +}; +  static acpi_status  early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)  { @@ -151,7 +174,7 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)  	return AE_OK;  } -void acpi_early_processor_set_pdc(void) +void __init acpi_early_processor_set_pdc(void)  {  	/*  	 * Check whether the system is DMI table. If yes, OSPM @@ -159,6 +182,13 @@ void acpi_early_processor_set_pdc(void)  	 */  	dmi_check_system(processor_idle_dmi_table); +	/* +	 * Allow systems to opt-in to early _PDC evaluation. +	 */ +	dmi_check_system(early_pdc_optin_table); +	if (!early_pdc_optin) +		return; +  	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,  			    ACPI_UINT32_MAX,  			    early_init_pdc, NULL, NULL, NULL); diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 140c5c5b423..6deafb4aa0d 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -443,8 +443,7 @@ struct thermal_cooling_device_ops processor_cooling_ops = {  #ifdef CONFIG_ACPI_PROCFS  static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)  { -	struct acpi_processor *pr = (struct acpi_processor *)seq->private; - +	struct acpi_processor *pr = seq->private;  	if (!pr)  		goto end; diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 52b9db8afc2..b16ddbf23a9 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -822,7 +822,10 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)  static void acpi_battery_remove(struct acpi_sbs *sbs, int id)  { +#if defined(CONFIG_ACPI_SYSFS_POWER) || defined(CONFIG_ACPI_PROCFS_POWER)  	struct acpi_battery *battery = &sbs->battery[id]; +#endif +  #ifdef CONFIG_ACPI_SYSFS_POWER  	if (battery->bat.dev) {  		if (battery->have_sysfs_alarm) diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index d9339806df4..fd09229282e 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -242,7 +242,7 @@ static int smbus_alarm(void *context)  		case ACPI_SBS_CHARGER:  		case ACPI_SBS_MANAGER:  		case ACPI_SBS_BATTERY: -			acpi_os_execute(OSL_GPE_HANDLER, +			acpi_os_execute(OSL_NOTIFY_HANDLER,  					acpi_smbus_callback, hc);  		default:;  	} diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 72e76b4b653..b765790b32b 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -78,6 +78,13 @@ MODULE_LICENSE("GPL");  static int brightness_switch_enabled = 1;  module_param(brightness_switch_enabled, bool, 0644); +/* + * By default, we don't allow duplicate ACPI video bus devices + * under the same VGA controller + */ +static int allow_duplicates; +module_param(allow_duplicates, bool, 0644); +  static int register_count = 0;  static int acpi_video_bus_add(struct acpi_device *device);  static int acpi_video_bus_remove(struct acpi_device *device, int type); @@ -2239,11 +2246,47 @@ static int acpi_video_resume(struct acpi_device *device)  	return AE_OK;  } +static acpi_status +acpi_video_bus_match(acpi_handle handle, u32 level, void *context, +			void **return_value) +{ +	struct acpi_device *device = context; +	struct acpi_device *sibling; +	int result; + +	if (handle == device->handle) +		return AE_CTRL_TERMINATE; + +	result = acpi_bus_get_device(handle, &sibling); +	if (result) +		return AE_OK; + +	if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME)) +			return AE_ALREADY_EXISTS; + +	return AE_OK; +} +  static int acpi_video_bus_add(struct acpi_device *device)  {  	struct acpi_video_bus *video;  	struct input_dev *input;  	int error; +	acpi_status status; + +	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, +				device->parent->handle, 1, +				acpi_video_bus_match, NULL, +				device, NULL); +	if (status == AE_ALREADY_EXISTS) { +		printk(KERN_WARNING FW_BUG +			"Duplicate ACPI video bus devices for the" +			" same VGA controller, please try module " +			"parameter \"video.allow_duplicates=1\"" +			"if the current driver doesn't work.\n"); +		if (!allow_duplicates) +			return -ENODEV; +	}  	video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);  	if (!video) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 0ea97c942ce..9f6cfac0f2c 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2028,8 +2028,9 @@ static void ata_eh_link_autopsy(struct ata_link *link)  			qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);  		/* determine whether the command is worth retrying */ -		if (!(qc->err_mask & AC_ERR_INVALID) && -		    ((qc->flags & ATA_QCFLAG_IO) || qc->err_mask != AC_ERR_DEV)) +		if (qc->flags & ATA_QCFLAG_IO || +		    (!(qc->err_mask & AC_ERR_INVALID) && +		     qc->err_mask != AC_ERR_DEV))  			qc->flags |= ATA_QCFLAG_RETRY;  		/* accumulate error info */ diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 090dd485130..42ae452b36b 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -354,6 +354,7 @@ int __init devtmpfs_init(void)  {  	int err;  	struct vfsmount *mnt; +	char options[] = "mode=0755";  	err = register_filesystem(&dev_fs_type);  	if (err) { @@ -362,7 +363,7 @@ int __init devtmpfs_init(void)  		return err;  	} -	mnt = kern_mount_data(&dev_fs_type, "mode=0755"); +	mnt = kern_mount_data(&dev_fs_type, options);  	if (IS_ERR(mnt)) {  		err = PTR_ERR(mnt);  		printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err); diff --git a/drivers/base/memory.c b/drivers/base/memory.c index ae6b6c43cff..bd025059711 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -309,19 +309,17 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);   * Block size attribute stuff   */  static ssize_t -print_block_size(struct sysdev_class *class, -		 struct sysdev_class_attribute *class_attr, -		 char *buf) +print_block_size(struct class *class, char *buf)  {  	return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE);  } -static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); +static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);  static int block_size_init(void)  {  	return sysfs_create_file(&memory_sysdev_class.kset.kobj, -				&attr_block_size_bytes.attr); +				&class_attr_block_size_bytes.attr);  }  /* @@ -332,9 +330,7 @@ static int block_size_init(void)   */  #ifdef CONFIG_ARCH_MEMORY_PROBE  static ssize_t -memory_probe_store(struct sysdev_class *class, -		   struct sysdev_class_attribute *class_attr, -		   const char *buf, size_t count) +memory_probe_store(struct class *class, const char *buf, size_t count)  {  	u64 phys_addr;  	int nid; @@ -350,12 +346,12 @@ memory_probe_store(struct sysdev_class *class,  	return count;  } -static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store); +static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store);  static int memory_probe_init(void)  {  	return sysfs_create_file(&memory_sysdev_class.kset.kobj, -				&attr_probe.attr); +				&class_attr_probe.attr);  }  #else  static inline int memory_probe_init(void) @@ -371,9 +367,7 @@ static inline int memory_probe_init(void)  /* Soft offline a page */  static ssize_t -store_soft_offline_page(struct sysdev_class *class, -			struct sysdev_class_attribute *class_attr, -			const char *buf, size_t count) +store_soft_offline_page(struct class *class, const char *buf, size_t count)  {  	int ret;  	u64 pfn; @@ -390,9 +384,7 @@ store_soft_offline_page(struct sysdev_class *class,  /* Forcibly offline a page, including killing processes. */  static ssize_t -store_hard_offline_page(struct sysdev_class *class, -			struct sysdev_class_attribute *class_attr, -			const char *buf, size_t count) +store_hard_offline_page(struct class *class, const char *buf, size_t count)  {  	int ret;  	u64 pfn; @@ -405,18 +397,18 @@ store_hard_offline_page(struct sysdev_class *class,  	return ret ? ret : count;  } -static SYSDEV_CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page); -static SYSDEV_CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page); +static CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page); +static CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page);  static __init int memory_fail_init(void)  {  	int err;  	err = sysfs_create_file(&memory_sysdev_class.kset.kobj, -				&attr_soft_offline_page.attr); +				&class_attr_soft_offline_page.attr);  	if (!err)  		err = sysfs_create_file(&memory_sysdev_class.kset.kobj, -				&attr_hard_offline_page.attr); +				&class_attr_hard_offline_page.attr);  	return err;  }  #else diff --git a/drivers/block/drbd/Kconfig b/drivers/block/drbd/Kconfig index f4acd04ebee..df098378739 100644 --- a/drivers/block/drbd/Kconfig +++ b/drivers/block/drbd/Kconfig @@ -3,7 +3,7 @@  #  comment "DRBD disabled because PROC_FS, INET or CONNECTOR not selected" -	depends on !PROC_FS || !INET || !CONNECTOR +	depends on PROC_FS='n' || INET='n' || CONNECTOR='n'  config BLK_DEV_DRBD  	tristate "DRBD Distributed Replicated Block Device support" diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index c9755876343..2bf3a6ef368 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1275,7 +1275,7 @@ struct bm_extent {  #if DRBD_MAX_SECTORS_BM < DRBD_MAX_SECTORS_32  #define DRBD_MAX_SECTORS      DRBD_MAX_SECTORS_BM  #define DRBD_MAX_SECTORS_FLEX DRBD_MAX_SECTORS_BM -#elif !defined(CONFIG_LBD) && BITS_PER_LONG == 32 +#elif !defined(CONFIG_LBDAF) && BITS_PER_LONG == 32  #define DRBD_MAX_SECTORS      DRBD_MAX_SECTORS_32  #define DRBD_MAX_SECTORS_FLEX DRBD_MAX_SECTORS_32  #else @@ -1371,10 +1371,9 @@ extern int is_valid_ar_handle(struct drbd_request *, sector_t);  extern void drbd_suspend_io(struct drbd_conf *mdev);  extern void drbd_resume_io(struct drbd_conf *mdev);  extern char *ppsize(char *buf, unsigned long long size); -extern sector_t drbd_new_dev_size(struct drbd_conf *, -		struct drbd_backing_dev *); +extern sector_t drbd_new_dev_size(struct drbd_conf *, struct drbd_backing_dev *, int);  enum determine_dev_size { dev_size_error = -1, unchanged = 0, shrunk = 1, grew = 2 }; -extern enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *) __must_hold(local); +extern enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *, int force) __must_hold(local);  extern void resync_after_online_grow(struct drbd_conf *);  extern void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int) __must_hold(local);  extern int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 9348f33f624..e898ad9eb1c 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1298,6 +1298,7 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,  				dev_err(DEV, "Sending state in drbd_io_error() failed\n");  		} +		wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt));  		lc_destroy(mdev->resync);  		mdev->resync = NULL;  		lc_destroy(mdev->act_log); diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 4e0726aa53b..1292e062066 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -510,7 +510,7 @@ void drbd_resume_io(struct drbd_conf *mdev)   * Returns 0 on success, negative return values indicate errors.   * You should call drbd_md_sync() after calling this function.   */ -enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev) __must_hold(local) +enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, int force) __must_hold(local)  {  	sector_t prev_first_sect, prev_size; /* previous meta location */  	sector_t la_size; @@ -541,7 +541,7 @@ enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev) __must_ho  	/* TODO: should only be some assert here, not (re)init... */  	drbd_md_set_sector_offsets(mdev, mdev->ldev); -	size = drbd_new_dev_size(mdev, mdev->ldev); +	size = drbd_new_dev_size(mdev, mdev->ldev, force);  	if (drbd_get_capacity(mdev->this_bdev) != size ||  	    drbd_bm_capacity(mdev) != size) { @@ -596,7 +596,7 @@ out:  }  sector_t -drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) +drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, int assume_peer_has_space)  {  	sector_t p_size = mdev->p_size;   /* partner's disk size. */  	sector_t la_size = bdev->md.la_size_sect; /* last agreed size. */ @@ -606,6 +606,11 @@ drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)  	m_size = drbd_get_max_capacity(bdev); +	if (mdev->state.conn < C_CONNECTED && assume_peer_has_space) { +		dev_warn(DEV, "Resize while not connected was forced by the user!\n"); +		p_size = m_size; +	} +  	if (p_size && m_size) {  		size = min_t(sector_t, p_size, m_size);  	} else { @@ -965,7 +970,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp  	/* Prevent shrinking of consistent devices ! */  	if (drbd_md_test_flag(nbc, MDF_CONSISTENT) && -	   drbd_new_dev_size(mdev, nbc) < nbc->md.la_size_sect) { +	    drbd_new_dev_size(mdev, nbc, 0) < nbc->md.la_size_sect) {  		dev_warn(DEV, "refusing to truncate a consistent device\n");  		retcode = ERR_DISK_TO_SMALL;  		goto force_diskless_dec; @@ -1052,7 +1057,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp  	    !drbd_md_test_flag(mdev->ldev, MDF_CONNECTED_IND))  		set_bit(USE_DEGR_WFC_T, &mdev->flags); -	dd = drbd_determin_dev_size(mdev); +	dd = drbd_determin_dev_size(mdev, 0);  	if (dd == dev_size_error) {  		retcode = ERR_NOMEM_BITMAP;  		goto force_diskless_dec; @@ -1271,7 +1276,7 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,  			goto fail;  		} -		if (crypto_tfm_alg_type(crypto_hash_tfm(tfm)) != CRYPTO_ALG_TYPE_SHASH) { +		if (!drbd_crypto_is_hash(crypto_hash_tfm(tfm))) {  			retcode = ERR_AUTH_ALG_ND;  			goto fail;  		} @@ -1504,7 +1509,7 @@ static int drbd_nl_resize(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,  	}  	mdev->ldev->dc.disk_size = (sector_t)rs.resize_size; -	dd = drbd_determin_dev_size(mdev); +	dd = drbd_determin_dev_size(mdev, rs.resize_force);  	drbd_md_sync(mdev);  	put_ldev(mdev);  	if (dd == dev_size_error) { diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 259c1351b15..f22a5283128 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -878,9 +878,13 @@ retry:  	if (mdev->cram_hmac_tfm) {  		/* drbd_request_state(mdev, NS(conn, WFAuth)); */ -		if (!drbd_do_auth(mdev)) { +		switch (drbd_do_auth(mdev)) { +		case -1:  			dev_err(DEV, "Authentication of peer failed\n");  			return -1; +		case 0: +			dev_err(DEV, "Authentication of peer failed, trying again.\n"); +			return 0;  		}  	} @@ -1201,10 +1205,11 @@ static int receive_Barrier(struct drbd_conf *mdev, struct p_header *h)  	case WO_bdev_flush:  	case WO_drain_io: -		D_ASSERT(rv == FE_STILL_LIVE); -		set_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &mdev->current_epoch->flags); -		drbd_wait_ee_list_empty(mdev, &mdev->active_ee); -		rv = drbd_flush_after_epoch(mdev, mdev->current_epoch); +		if (rv == FE_STILL_LIVE) { +			set_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &mdev->current_epoch->flags); +			drbd_wait_ee_list_empty(mdev, &mdev->active_ee); +			rv = drbd_flush_after_epoch(mdev, mdev->current_epoch); +		}  		if (rv == FE_RECYCLED)  			return TRUE; @@ -2865,7 +2870,7 @@ static int receive_sizes(struct drbd_conf *mdev, struct p_header *h)  		/* Never shrink a device with usable data during connect.  		   But allow online shrinking if we are connected. */ -		if (drbd_new_dev_size(mdev, mdev->ldev) < +		if (drbd_new_dev_size(mdev, mdev->ldev, 0) <  		   drbd_get_capacity(mdev->this_bdev) &&  		   mdev->state.disk >= D_OUTDATED &&  		   mdev->state.conn < C_CONNECTED) { @@ -2880,7 +2885,7 @@ static int receive_sizes(struct drbd_conf *mdev, struct p_header *h)  #undef min_not_zero  	if (get_ldev(mdev)) { -		dd = drbd_determin_dev_size(mdev); +	  dd = drbd_determin_dev_size(mdev, 0);  		put_ldev(mdev);  		if (dd == dev_size_error)  			return FALSE; @@ -3830,10 +3835,17 @@ static int drbd_do_auth(struct drbd_conf *mdev)  {  	dev_err(DEV, "This kernel was build without CONFIG_CRYPTO_HMAC.\n");  	dev_err(DEV, "You need to disable 'cram-hmac-alg' in drbd.conf.\n"); -	return 0; +	return -1;  }  #else  #define CHALLENGE_LEN 64 + +/* Return value: +	1 - auth succeeded, +	0 - failed, try again (network error), +	-1 - auth failed, don't try again. +*/ +  static int drbd_do_auth(struct drbd_conf *mdev)  {  	char my_challenge[CHALLENGE_LEN];  /* 64 Bytes... */ @@ -3854,7 +3866,7 @@ static int drbd_do_auth(struct drbd_conf *mdev)  				(u8 *)mdev->net_conf->shared_secret, key_len);  	if (rv) {  		dev_err(DEV, "crypto_hash_setkey() failed with %d\n", rv); -		rv = 0; +		rv = -1;  		goto fail;  	} @@ -3877,14 +3889,14 @@ static int drbd_do_auth(struct drbd_conf *mdev)  	if (p.length > CHALLENGE_LEN*2) {  		dev_err(DEV, "expected AuthChallenge payload too big.\n"); -		rv = 0; +		rv = -1;  		goto fail;  	}  	peers_ch = kmalloc(p.length, GFP_NOIO);  	if (peers_ch == NULL) {  		dev_err(DEV, "kmalloc of peers_ch failed\n"); -		rv = 0; +		rv = -1;  		goto fail;  	} @@ -3900,7 +3912,7 @@ static int drbd_do_auth(struct drbd_conf *mdev)  	response = kmalloc(resp_size, GFP_NOIO);  	if (response == NULL) {  		dev_err(DEV, "kmalloc of response failed\n"); -		rv = 0; +		rv = -1;  		goto fail;  	} @@ -3910,7 +3922,7 @@ static int drbd_do_auth(struct drbd_conf *mdev)  	rv = crypto_hash_digest(&desc, &sg, sg.length, response);  	if (rv) {  		dev_err(DEV, "crypto_hash_digest() failed with %d\n", rv); -		rv = 0; +		rv = -1;  		goto fail;  	} @@ -3944,9 +3956,9 @@ static int drbd_do_auth(struct drbd_conf *mdev)  	}  	right_response = kmalloc(resp_size, GFP_NOIO); -	if (response == NULL) { +	if (right_response == NULL) {  		dev_err(DEV, "kmalloc of right_response failed\n"); -		rv = 0; +		rv = -1;  		goto fail;  	} @@ -3955,7 +3967,7 @@ static int drbd_do_auth(struct drbd_conf *mdev)  	rv = crypto_hash_digest(&desc, &sg, sg.length, right_response);  	if (rv) {  		dev_err(DEV, "crypto_hash_digest() failed with %d\n", rv); -		rv = 0; +		rv = -1;  		goto fail;  	} @@ -3964,6 +3976,8 @@ static int drbd_do_auth(struct drbd_conf *mdev)  	if (rv)  		dev_info(DEV, "Peer authenticated using %d bytes of '%s' HMAC\n",  		     resp_size, mdev->net_conf->cram_hmac_alg); +	else +		rv = -1;   fail:  	kfree(peers_ch); diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 7d73cd43034..2ad7d37afbd 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -1651,10 +1651,10 @@ static void ntty_close(struct tty_struct *tty, struct file *file)  	dc->open_ttys--;  	port->count--; -	tty_port_tty_set(port, NULL);  	if (port->count == 0) {  		DBG1("close: %d", nport->token_dl); +		tty_port_tty_set(port, NULL);  		spin_lock_irqsave(&dc->spin_mutex, flags);  		dc->last_ier &= ~(nport->token_dl);  		writew(dc->last_ier, dc->reg_ier); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index f15df40bc31..c6f3b48be9d 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1951,8 +1951,8 @@ static int tty_fasync(int fd, struct file *filp, int on)  			pid = task_pid(current);  			type = PIDTYPE_PID;  		} -		spin_unlock_irqrestore(&tty->ctrl_lock, flags);  		retval = __f_setown(filp, pid, type, 0); +		spin_unlock_irqrestore(&tty->ctrl_lock, flags);  		if (retval)  			goto out;  	} else { diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 5d1c2603a13..2b0bd0b042d 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -20,15 +20,15 @@  #include <linux/platform_device.h>  #include <linux/i2c-pnx.h>  #include <linux/io.h> +#include <linux/err.h> +#include <linux/clk.h> +  #include <mach/hardware.h>  #include <mach/i2c.h> -#include <asm/irq.h> -#include <asm/uaccess.h>  #define I2C_PNX_TIMEOUT		10 /* msec */  #define I2C_PNX_SPEED_KHZ	100  #define I2C_PNX_REGION_SIZE	0x100 -#define PNX_DEFAULT_FREQ	13 /* MHz */  static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)  { @@ -50,22 +50,21 @@ static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)  	return (timeout <= 0);  } -static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap) +static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)  { -	struct i2c_pnx_algo_data *data = adap->algo_data; -	struct timer_list *timer = &data->mif.timer; -	int expires = I2C_PNX_TIMEOUT / (1000 / HZ); +	struct timer_list *timer = &alg_data->mif.timer; +	unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT);  	if (expires <= 1)  		expires = 2;  	del_timer_sync(timer); -	dev_dbg(&adap->dev, "Timer armed at %lu plus %u jiffies.\n", +	dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n",  		jiffies, expires);  	timer->expires = jiffies + expires; -	timer->data = (unsigned long)adap; +	timer->data = (unsigned long)&alg_data;  	add_timer(timer);  } @@ -77,34 +76,34 @@ static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap)   *   * Generate a START signal in the desired mode.   */ -static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap) +static int i2c_pnx_start(unsigned char slave_addr, +	struct i2c_pnx_algo_data *alg_data)  { -	struct i2c_pnx_algo_data *alg_data = adap->algo_data; - -	dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __func__, +	dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__,  		slave_addr, alg_data->mif.mode);  	/* Check for 7 bit slave addresses only */  	if (slave_addr & ~0x7f) { -		dev_err(&adap->dev, "%s: Invalid slave address %x. " -		       "Only 7-bit addresses are supported\n", -		       adap->name, slave_addr); +		dev_err(&alg_data->adapter.dev, +			"%s: Invalid slave address %x. Only 7-bit addresses are supported\n", +			alg_data->adapter.name, slave_addr);  		return -EINVAL;  	}  	/* First, make sure bus is idle */  	if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {  		/* Somebody else is monopolizing the bus */ -		dev_err(&adap->dev, "%s: Bus busy. Slave addr = %02x, " -		       "cntrl = %x, stat = %x\n", -		       adap->name, slave_addr, -		       ioread32(I2C_REG_CTL(alg_data)), -		       ioread32(I2C_REG_STS(alg_data))); +		dev_err(&alg_data->adapter.dev, +			"%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n", +			alg_data->adapter.name, slave_addr, +			ioread32(I2C_REG_CTL(alg_data)), +			ioread32(I2C_REG_STS(alg_data)));  		return -EBUSY;  	} else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {  		/* Sorry, we lost the bus */ -		dev_err(&adap->dev, "%s: Arbitration failure. " -		       "Slave addr = %02x\n", adap->name, slave_addr); +		dev_err(&alg_data->adapter.dev, +		        "%s: Arbitration failure. Slave addr = %02x\n", +			alg_data->adapter.name, slave_addr);  		return -EIO;  	} @@ -115,14 +114,14 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)  	iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,  		  I2C_REG_STS(alg_data)); -	dev_dbg(&adap->dev, "%s(): sending %#x\n", __func__, +	dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__,  		(slave_addr << 1) | start_bit | alg_data->mif.mode);  	/* Write the slave address, START bit and R/W bit */  	iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,  		  I2C_REG_TX(alg_data)); -	dev_dbg(&adap->dev, "%s(): exit\n", __func__); +	dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__);  	return 0;  } @@ -133,13 +132,12 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)   *   * Generate a STOP signal to terminate the master transaction.   */ -static void i2c_pnx_stop(struct i2c_adapter *adap) +static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data)  { -	struct i2c_pnx_algo_data *alg_data = adap->algo_data;  	/* Only 1 msec max timeout due to interrupt context */  	long timeout = 1000; -	dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", +	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",  		__func__, ioread32(I2C_REG_STS(alg_data)));  	/* Write a STOP bit to TX FIFO */ @@ -153,7 +151,7 @@ static void i2c_pnx_stop(struct i2c_adapter *adap)  		timeout--;  	} -	dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", +	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",  		__func__, ioread32(I2C_REG_STS(alg_data)));  } @@ -163,12 +161,11 @@ static void i2c_pnx_stop(struct i2c_adapter *adap)   *   * Sends one byte of data to the slave   */ -static int i2c_pnx_master_xmit(struct i2c_adapter *adap) +static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)  { -	struct i2c_pnx_algo_data *alg_data = adap->algo_data;  	u32 val; -	dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", +	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",  		__func__, ioread32(I2C_REG_STS(alg_data)));  	if (alg_data->mif.len > 0) { @@ -184,15 +181,15 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)  		alg_data->mif.len--;  		iowrite32(val, I2C_REG_TX(alg_data)); -		dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __func__, -			val, alg_data->mif.len + 1); +		dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n", +			__func__, val, alg_data->mif.len + 1);  		if (alg_data->mif.len == 0) {  			if (alg_data->last) {  				/* Wait until the STOP is seen. */  				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) -					dev_err(&adap->dev, "The bus is still " -						"active after timeout\n"); +					dev_err(&alg_data->adapter.dev, +						"The bus is still active after timeout\n");  			}  			/* Disable master interrupts */  			iowrite32(ioread32(I2C_REG_CTL(alg_data)) & @@ -201,14 +198,15 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)  			del_timer_sync(&alg_data->mif.timer); -			dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n", +			dev_dbg(&alg_data->adapter.dev, +				"%s(): Waking up xfer routine.\n",  				__func__);  			complete(&alg_data->mif.complete);  		}  	} else if (alg_data->mif.len == 0) {  		/* zero-sized transfer */ -		i2c_pnx_stop(adap); +		i2c_pnx_stop(alg_data);  		/* Disable master interrupts. */  		iowrite32(ioread32(I2C_REG_CTL(alg_data)) & @@ -217,13 +215,14 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)  		/* Stop timer. */  		del_timer_sync(&alg_data->mif.timer); -		dev_dbg(&adap->dev, "%s(): Waking up xfer routine after " -			"zero-xfer.\n", __func__); +		dev_dbg(&alg_data->adapter.dev, +			"%s(): Waking up xfer routine after zero-xfer.\n", +			__func__);  		complete(&alg_data->mif.complete);  	} -	dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", +	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",  		__func__, ioread32(I2C_REG_STS(alg_data)));  	return 0; @@ -235,21 +234,21 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)   *   * Reads one byte data from the slave   */ -static int i2c_pnx_master_rcv(struct i2c_adapter *adap) +static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)  { -	struct i2c_pnx_algo_data *alg_data = adap->algo_data;  	unsigned int val = 0;  	u32 ctl = 0; -	dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", +	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",  		__func__, ioread32(I2C_REG_STS(alg_data)));  	/* Check, whether there is already data,  	 * or we didn't 'ask' for it yet.  	 */  	if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) { -		dev_dbg(&adap->dev, "%s(): Write dummy data to fill " -			"Rx-fifo...\n", __func__); +		dev_dbg(&alg_data->adapter.dev, +			"%s(): Write dummy data to fill Rx-fifo...\n", +			__func__);  		if (alg_data->mif.len == 1) {  			/* Last byte, do not acknowledge next rcv. */ @@ -281,16 +280,16 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)  	if (alg_data->mif.len > 0) {  		val = ioread32(I2C_REG_RX(alg_data));  		*alg_data->mif.buf++ = (u8) (val & 0xff); -		dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __func__, val, -			alg_data->mif.len); +		dev_dbg(&alg_data->adapter.dev, "%s(): rcv 0x%x [%d]\n", +			__func__, val, alg_data->mif.len);  		alg_data->mif.len--;  		if (alg_data->mif.len == 0) {  			if (alg_data->last)  				/* Wait until the STOP is seen. */  				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) -					dev_err(&adap->dev, "The bus is still " -						"active after timeout\n"); +					dev_err(&alg_data->adapter.dev, +						"The bus is still active after timeout\n");  			/* Disable master interrupts */  			ctl = ioread32(I2C_REG_CTL(alg_data)); @@ -304,7 +303,7 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)  		}  	} -	dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", +	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",  		__func__, ioread32(I2C_REG_STS(alg_data)));  	return 0; @@ -312,11 +311,11 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)  static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)  { +	struct i2c_pnx_algo_data *alg_data = dev_id;  	u32 stat, ctl; -	struct i2c_adapter *adap = dev_id; -	struct i2c_pnx_algo_data *alg_data = adap->algo_data; -	dev_dbg(&adap->dev, "%s(): mstat = %x mctrl = %x, mode = %d\n", +	dev_dbg(&alg_data->adapter.dev, +		"%s(): mstat = %x mctrl = %x, mode = %d\n",  		__func__,  		ioread32(I2C_REG_STS(alg_data)),  		ioread32(I2C_REG_CTL(alg_data)), @@ -339,10 +338,10 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)  		complete(&alg_data->mif.complete);  	} else if (stat & mstatus_nai) {  		/* Slave did not acknowledge, generate a STOP */ -		dev_dbg(&adap->dev, "%s(): " -			"Slave did not acknowledge, generating a STOP.\n", +		dev_dbg(&alg_data->adapter.dev, +			"%s(): Slave did not acknowledge, generating a STOP.\n",  			__func__); -		i2c_pnx_stop(adap); +		i2c_pnx_stop(alg_data);  		/* Disable master interrupts. */  		ctl = ioread32(I2C_REG_CTL(alg_data)); @@ -368,9 +367,9 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)  		 */  		if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {  			if (alg_data->mif.mode == I2C_SMBUS_WRITE) { -				i2c_pnx_master_xmit(adap); +				i2c_pnx_master_xmit(alg_data);  			} else if (alg_data->mif.mode == I2C_SMBUS_READ) { -				i2c_pnx_master_rcv(adap); +				i2c_pnx_master_rcv(alg_data);  			}  		}  	} @@ -379,7 +378,8 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)  	stat = ioread32(I2C_REG_STS(alg_data));  	iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data)); -	dev_dbg(&adap->dev, "%s(): exiting, stat = %x ctrl = %x.\n", +	dev_dbg(&alg_data->adapter.dev, +		"%s(): exiting, stat = %x ctrl = %x.\n",  		 __func__, ioread32(I2C_REG_STS(alg_data)),  		 ioread32(I2C_REG_CTL(alg_data))); @@ -388,14 +388,13 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)  static void i2c_pnx_timeout(unsigned long data)  { -	struct i2c_adapter *adap = (struct i2c_adapter *)data; -	struct i2c_pnx_algo_data *alg_data = adap->algo_data; +	struct i2c_pnx_algo_data *alg_data = (struct i2c_pnx_algo_data *)data;  	u32 ctl; -	dev_err(&adap->dev, "Master timed out. stat = %04x, cntrl = %04x. " -	       "Resetting master...\n", -	       ioread32(I2C_REG_STS(alg_data)), -	       ioread32(I2C_REG_CTL(alg_data))); +	dev_err(&alg_data->adapter.dev, +		"Master timed out. stat = %04x, cntrl = %04x. Resetting master...\n", +		ioread32(I2C_REG_STS(alg_data)), +		ioread32(I2C_REG_CTL(alg_data)));  	/* Reset master and disable interrupts */  	ctl = ioread32(I2C_REG_CTL(alg_data)); @@ -409,15 +408,14 @@ static void i2c_pnx_timeout(unsigned long data)  	complete(&alg_data->mif.complete);  } -static inline void bus_reset_if_active(struct i2c_adapter *adap) +static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data)  { -	struct i2c_pnx_algo_data *alg_data = adap->algo_data;  	u32 stat;  	if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) { -		dev_err(&adap->dev, +		dev_err(&alg_data->adapter.dev,  			"%s: Bus is still active after xfer. Reset it...\n", -		       adap->name); +			alg_data->adapter.name);  		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,  			  I2C_REG_CTL(alg_data));  		wait_reset(I2C_PNX_TIMEOUT, alg_data); @@ -451,10 +449,11 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  	struct i2c_pnx_algo_data *alg_data = adap->algo_data;  	u32 stat = ioread32(I2C_REG_STS(alg_data)); -	dev_dbg(&adap->dev, "%s(): entering: %d messages, stat = %04x.\n", +	dev_dbg(&alg_data->adapter.dev, +		"%s(): entering: %d messages, stat = %04x.\n",  		__func__, num, ioread32(I2C_REG_STS(alg_data))); -	bus_reset_if_active(adap); +	bus_reset_if_active(alg_data);  	/* Process transactions in a loop. */  	for (i = 0; rc >= 0 && i < num; i++) { @@ -464,9 +463,9 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  		addr = pmsg->addr;  		if (pmsg->flags & I2C_M_TEN) { -			dev_err(&adap->dev, +			dev_err(&alg_data->adapter.dev,  				"%s: 10 bits addr not supported!\n", -				adap->name); +				alg_data->adapter.name);  			rc = -EINVAL;  			break;  		} @@ -478,11 +477,10 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  		alg_data->mif.ret = 0;  		alg_data->last = (i == num - 1); -		dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __func__, -			alg_data->mif.mode, -			alg_data->mif.len); +		dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n", +			__func__, alg_data->mif.mode, alg_data->mif.len); -		i2c_pnx_arm_timer(adap); +		i2c_pnx_arm_timer(alg_data);  		/* initialize the completion var */  		init_completion(&alg_data->mif.complete); @@ -493,7 +491,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  			  I2C_REG_CTL(alg_data));  		/* Put start-code and slave-address on the bus. */ -		rc = i2c_pnx_start(addr, adap); +		rc = i2c_pnx_start(addr, alg_data);  		if (rc < 0)  			break; @@ -502,31 +500,32 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  		if (!(rc = alg_data->mif.ret))  			completed++; -		dev_dbg(&adap->dev, "%s(): Complete, return code = %d.\n", +		dev_dbg(&alg_data->adapter.dev, +			"%s(): Complete, return code = %d.\n",  			__func__, rc);  		/* Clear TDI and AFI bits in case they are set. */  		if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) { -			dev_dbg(&adap->dev, +			dev_dbg(&alg_data->adapter.dev,  				"%s: TDI still set... clearing now.\n", -			       adap->name); +				alg_data->adapter.name);  			iowrite32(stat, I2C_REG_STS(alg_data));  		}  		if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) { -			dev_dbg(&adap->dev, +			dev_dbg(&alg_data->adapter.dev,  				"%s: AFI still set... clearing now.\n", -			       adap->name); +				alg_data->adapter.name);  			iowrite32(stat, I2C_REG_STS(alg_data));  		}  	} -	bus_reset_if_active(adap); +	bus_reset_if_active(alg_data);  	/* Cleanup to be sure... */  	alg_data->mif.buf = NULL;  	alg_data->mif.len = 0; -	dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n", +	dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n",  		__func__, ioread32(I2C_REG_STS(alg_data)));  	if (completed != num) @@ -545,69 +544,92 @@ static struct i2c_algorithm pnx_algorithm = {  	.functionality = i2c_pnx_func,  }; +#ifdef CONFIG_PM  static int i2c_pnx_controller_suspend(struct platform_device *pdev,  				      pm_message_t state)  { -	struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); -	return i2c_pnx->suspend(pdev, state); +	struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); + +	/* FIXME: shouldn't this be clk_disable? */ +	clk_enable(alg_data->clk); + +	return 0;  }  static int i2c_pnx_controller_resume(struct platform_device *pdev)  { -	struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); -	return i2c_pnx->resume(pdev); +	struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); + +	return clk_enable(alg_data->clk);  } +#else +#define i2c_pnx_controller_suspend	NULL +#define i2c_pnx_controller_resume	NULL +#endif  static int __devinit i2c_pnx_probe(struct platform_device *pdev)  {  	unsigned long tmp;  	int ret = 0;  	struct i2c_pnx_algo_data *alg_data; -	int freq_mhz; +	unsigned long freq;  	struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data; -	if (!i2c_pnx || !i2c_pnx->adapter) { +	if (!i2c_pnx || !i2c_pnx->name) {  		dev_err(&pdev->dev, "%s: no platform data supplied\n",  		       __func__);  		ret = -EINVAL;  		goto out;  	} -	platform_set_drvdata(pdev, i2c_pnx); - -	if (i2c_pnx->calculate_input_freq) -		freq_mhz = i2c_pnx->calculate_input_freq(pdev); -	else { -		freq_mhz = PNX_DEFAULT_FREQ; -		dev_info(&pdev->dev, "Setting bus frequency to default value: " -		       "%d MHz\n", freq_mhz); +	alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL); +	if (!alg_data) { +		ret = -ENOMEM; +		goto err_kzalloc;  	} -	i2c_pnx->adapter->algo = &pnx_algorithm; +	platform_set_drvdata(pdev, alg_data); + +	strlcpy(alg_data->adapter.name, i2c_pnx->name, +		sizeof(alg_data->adapter.name)); +	alg_data->adapter.dev.parent = &pdev->dev; +	alg_data->adapter.algo = &pnx_algorithm; +	alg_data->adapter.algo_data = alg_data; +	alg_data->adapter.nr = pdev->id; +	alg_data->i2c_pnx = i2c_pnx; + +	alg_data->clk = clk_get(&pdev->dev, NULL); +	if (IS_ERR(alg_data->clk)) { +		ret = PTR_ERR(alg_data->clk); +		goto out_drvdata; +	} -	alg_data = i2c_pnx->adapter->algo_data;  	init_timer(&alg_data->mif.timer);  	alg_data->mif.timer.function = i2c_pnx_timeout; -	alg_data->mif.timer.data = (unsigned long)i2c_pnx->adapter; +	alg_data->mif.timer.data = (unsigned long)alg_data;  	/* Register I/O resource */ -	if (!request_mem_region(alg_data->base, I2C_PNX_REGION_SIZE, +	if (!request_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE,  				pdev->name)) {  		dev_err(&pdev->dev,  		       "I/O region 0x%08x for I2C already in use.\n", -		       alg_data->base); +		       i2c_pnx->base);  		ret = -ENODEV; -		goto out_drvdata; +		goto out_clkget;  	} -	if (!(alg_data->ioaddr = -			(u32)ioremap(alg_data->base, I2C_PNX_REGION_SIZE))) { +	alg_data->ioaddr = ioremap(i2c_pnx->base, I2C_PNX_REGION_SIZE); +	if (!alg_data->ioaddr) {  		dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n");  		ret = -ENOMEM;  		goto out_release;  	} -	i2c_pnx->set_clock_run(pdev); +	ret = clk_enable(alg_data->clk); +	if (ret) +		goto out_unmap; + +	freq = clk_get_rate(alg_data->clk);  	/*  	 * Clock Divisor High This value is the number of system clocks @@ -620,45 +642,47 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)  	 * the deglitching filter length.  	 */ -	tmp = ((freq_mhz * 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2; +	tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;  	iowrite32(tmp, I2C_REG_CKH(alg_data));  	iowrite32(tmp, I2C_REG_CKL(alg_data));  	iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));  	if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {  		ret = -ENODEV; -		goto out_unmap; +		goto out_clock;  	}  	init_completion(&alg_data->mif.complete); -	ret = request_irq(alg_data->irq, i2c_pnx_interrupt, -			0, pdev->name, i2c_pnx->adapter); +	ret = request_irq(i2c_pnx->irq, i2c_pnx_interrupt, +			0, pdev->name, alg_data);  	if (ret)  		goto out_clock;  	/* Register this adapter with the I2C subsystem */ -	i2c_pnx->adapter->dev.parent = &pdev->dev; -	i2c_pnx->adapter->nr = pdev->id; -	ret = i2c_add_numbered_adapter(i2c_pnx->adapter); +	ret = i2c_add_numbered_adapter(&alg_data->adapter);  	if (ret < 0) {  		dev_err(&pdev->dev, "I2C: Failed to add bus\n");  		goto out_irq;  	}  	dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n", -	       i2c_pnx->adapter->name, alg_data->base, alg_data->irq); +	       alg_data->adapter.name, i2c_pnx->base, i2c_pnx->irq);  	return 0;  out_irq: -	free_irq(alg_data->irq, i2c_pnx->adapter); +	free_irq(i2c_pnx->irq, alg_data);  out_clock: -	i2c_pnx->set_clock_stop(pdev); +	clk_disable(alg_data->clk);  out_unmap: -	iounmap((void *)alg_data->ioaddr); +	iounmap(alg_data->ioaddr);  out_release: -	release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE); +	release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE); +out_clkget: +	clk_put(alg_data->clk);  out_drvdata: +	kfree(alg_data); +err_kzalloc:  	platform_set_drvdata(pdev, NULL);  out:  	return ret; @@ -666,15 +690,16 @@ out:  static int __devexit i2c_pnx_remove(struct platform_device *pdev)  { -	struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); -	struct i2c_adapter *adap = i2c_pnx->adapter; -	struct i2c_pnx_algo_data *alg_data = adap->algo_data; +	struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); +	struct i2c_pnx_data *i2c_pnx = alg_data->i2c_pnx; -	free_irq(alg_data->irq, i2c_pnx->adapter); -	i2c_del_adapter(adap); -	i2c_pnx->set_clock_stop(pdev); -	iounmap((void *)alg_data->ioaddr); -	release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE); +	free_irq(i2c_pnx->irq, alg_data); +	i2c_del_adapter(&alg_data->adapter); +	clk_disable(alg_data->clk); +	iounmap(alg_data->ioaddr); +	release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE); +	clk_put(alg_data->clk); +	kfree(alg_data);  	platform_set_drvdata(pdev, NULL);  	return 0; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index be625475cf6..4b22feb01a0 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -503,16 +503,15 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,  		return 0;  	} -	if (blk_stack_limits(limits, &q->limits, start << 9) < 0) -		DMWARN("%s: target device %s is misaligned: " +	if (bdev_stack_limits(limits, bdev, start) < 0) +		DMWARN("%s: adding target device %s caused an alignment inconsistency: "  		       "physical_block_size=%u, logical_block_size=%u, "  		       "alignment_offset=%u, start=%llu",  		       dm_device_name(ti->table->md), bdevname(bdev, b),  		       q->limits.physical_block_size,  		       q->limits.logical_block_size,  		       q->limits.alignment_offset, -		       (unsigned long long) start << 9); - +		       (unsigned long long) start << SECTOR_SHIFT);  	/*  	 * Check if merge fn is supported. @@ -1026,9 +1025,9 @@ combine_limits:  		 * for the table.  		 */  		if (blk_stack_limits(limits, &ti_limits, 0) < 0) -			DMWARN("%s: target device " +			DMWARN("%s: adding target device "  			       "(start sect %llu len %llu) " -			       "is misaligned", +			       "caused an alignment inconsistency",  			       dm_device_name(table->md),  			       (unsigned long long) ti->begin,  			       (unsigned long long) ti->len); @@ -1080,15 +1079,6 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,  			       struct queue_limits *limits)  {  	/* -	 * Each target device in the table has a data area that should normally -	 * be aligned such that the DM device's alignment_offset is 0. -	 * FIXME: Propagate alignment_offsets up the stack and warn of -	 *	  sub-optimal or inconsistent settings. -	 */ -	limits->alignment_offset = 0; -	limits->misaligned = 0; - -	/*  	 * Copy table's limits to the DM device's request_queue  	 */  	q->limits = *limits; diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index db32c25e360..f526e735c5a 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -364,6 +364,7 @@ config EEEPC_LAPTOP  	select HWMON  	select LEDS_CLASS  	select NEW_LEDS +	select INPUT_SPARSEKMAP  	---help---  	  This driver supports the Fn-Fx keys on Eee PC laptops. diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 5838c69b2fb..e2be6bb33d9 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -31,10 +31,12 @@  #include <acpi/acpi_bus.h>  #include <linux/uaccess.h>  #include <linux/input.h> +#include <linux/input/sparse-keymap.h>  #include <linux/rfkill.h>  #include <linux/pci.h>  #include <linux/pci_hotplug.h>  #include <linux/leds.h> +#include <linux/dmi.h>  #define EEEPC_LAPTOP_VERSION	"0.1"  #define EEEPC_LAPTOP_NAME	"Eee PC Hotkey Driver" @@ -48,6 +50,14 @@ MODULE_AUTHOR("Corentin Chary, Eric Cooper");  MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME);  MODULE_LICENSE("GPL"); +static bool hotplug_disabled; + +module_param(hotplug_disabled, bool, 0644); +MODULE_PARM_DESC(hotplug_disabled, +		 "Disable hotplug for wireless device. " +		 "If your laptop need that, please report to " +		 "acpi4asus-user@lists.sourceforge.net."); +  /*   * Definitions for Asus EeePC   */ @@ -120,38 +130,28 @@ static const char *cm_setv[] = {  	NULL, NULL, "PBPS", "TPDS"  }; -struct key_entry { -	char type; -	u8 code; -	u16 keycode; -}; - -enum { KE_KEY, KE_END }; -  static const struct key_entry eeepc_keymap[] = { -	/* Sleep already handled via generic ACPI code */ -	{KE_KEY, 0x10, KEY_WLAN }, -	{KE_KEY, 0x11, KEY_WLAN }, -	{KE_KEY, 0x12, KEY_PROG1 }, -	{KE_KEY, 0x13, KEY_MUTE }, -	{KE_KEY, 0x14, KEY_VOLUMEDOWN }, -	{KE_KEY, 0x15, KEY_VOLUMEUP }, -	{KE_KEY, 0x16, KEY_DISPLAY_OFF }, -	{KE_KEY, 0x1a, KEY_COFFEE }, -	{KE_KEY, 0x1b, KEY_ZOOM }, -	{KE_KEY, 0x1c, KEY_PROG2 }, -	{KE_KEY, 0x1d, KEY_PROG3 }, -	{KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, -	{KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP }, -	{KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, -	{KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, -	{KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, -	{KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */ -	{KE_KEY, 0x38, KEY_F14 }, -	{KE_END, 0}, +	{ KE_KEY, 0x10, { KEY_WLAN } }, +	{ KE_KEY, 0x11, { KEY_WLAN } }, +	{ KE_KEY, 0x12, { KEY_PROG1 } }, +	{ KE_KEY, 0x13, { KEY_MUTE } }, +	{ KE_KEY, 0x14, { KEY_VOLUMEDOWN } }, +	{ KE_KEY, 0x15, { KEY_VOLUMEUP } }, +	{ KE_KEY, 0x16, { KEY_DISPLAY_OFF } }, +	{ KE_KEY, 0x1a, { KEY_COFFEE } }, +	{ KE_KEY, 0x1b, { KEY_ZOOM } }, +	{ KE_KEY, 0x1c, { KEY_PROG2 } }, +	{ KE_KEY, 0x1d, { KEY_PROG3 } }, +	{ KE_KEY, NOTIFY_BRN_MIN, { KEY_BRIGHTNESSDOWN } }, +	{ KE_KEY, NOTIFY_BRN_MAX, { KEY_BRIGHTNESSUP } }, +	{ KE_KEY, 0x30, { KEY_SWITCHVIDEOMODE } }, +	{ KE_KEY, 0x31, { KEY_SWITCHVIDEOMODE } }, +	{ KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } }, +	{ KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */ +	{ KE_KEY, 0x38, { KEY_F14 } }, +	{ KE_END, 0 },  }; -  /*   * This is the main structure, we can use it to store useful information   */ @@ -159,6 +159,8 @@ struct eeepc_laptop {  	acpi_handle handle;		/* the handle of the acpi device */  	u32 cm_supported;		/* the control methods supported  					   by this BIOS */ +	bool cpufv_disabled; +	bool hotplug_disabled;  	u16 event_count[128];		/* count for each event */  	struct platform_device *platform_device; @@ -378,6 +380,8 @@ static ssize_t store_cpufv(struct device *dev,  	struct eeepc_cpufv c;  	int rv, value; +	if (eeepc->cpufv_disabled) +		return -EPERM;  	if (get_cpufv(eeepc, &c))  		return -ENODEV;  	rv = parse_arg(buf, count, &value); @@ -389,6 +393,41 @@ static ssize_t store_cpufv(struct device *dev,  	return rv;  } +static ssize_t show_cpufv_disabled(struct device *dev, +			  struct device_attribute *attr, +			  char *buf) +{ +	struct eeepc_laptop *eeepc = dev_get_drvdata(dev); + +	return sprintf(buf, "%d\n", eeepc->cpufv_disabled); +} + +static ssize_t store_cpufv_disabled(struct device *dev, +			   struct device_attribute *attr, +			   const char *buf, size_t count) +{ +	struct eeepc_laptop *eeepc = dev_get_drvdata(dev); +	int rv, value; + +	rv = parse_arg(buf, count, &value); +	if (rv < 0) +		return rv; + +	switch (value) { +	case 0: +		if (eeepc->cpufv_disabled) +			pr_warning("cpufv enabled (not officially supported " +				"on this model)\n"); +		eeepc->cpufv_disabled = false; +		return rv; +	case 1: +		return -EPERM; +	default: +		return -EINVAL; +	} +} + +  static struct device_attribute dev_attr_cpufv = {  	.attr = {  		.name = "cpufv", @@ -404,12 +443,22 @@ static struct device_attribute dev_attr_available_cpufv = {  	.show   = show_available_cpufv  }; +static struct device_attribute dev_attr_cpufv_disabled = { +	.attr = { +		.name = "cpufv_disabled", +		.mode = 0644 }, +	.show   = show_cpufv_disabled, +	.store  = store_cpufv_disabled +}; + +  static struct attribute *platform_attributes[] = {  	&dev_attr_camera.attr,  	&dev_attr_cardr.attr,  	&dev_attr_disp.attr,  	&dev_attr_cpufv.attr,  	&dev_attr_available_cpufv.attr, +	&dev_attr_cpufv_disabled.attr,  	NULL  }; @@ -796,6 +845,9 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)  	if (result && result != -ENODEV)  		goto exit; +	if (eeepc->hotplug_disabled) +		return 0; +  	result = eeepc_setup_pci_hotplug(eeepc);  	/*  	 * If we get -EBUSY then something else is handling the PCI hotplug - @@ -1090,120 +1142,42 @@ static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)  /*   * Input device (i.e. hotkeys)   */ -static struct key_entry *eeepc_get_entry_by_scancode( -	struct eeepc_laptop *eeepc, -	int code) -{ -	struct key_entry *key; - -	for (key = eeepc->keymap; key->type != KE_END; key++) -		if (code == key->code) -			return key; - -	return NULL; -} - -static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event) -{ -	static struct key_entry *key; - -	key = eeepc_get_entry_by_scancode(eeepc, event); -	if (key) { -		switch (key->type) { -		case KE_KEY: -			input_report_key(eeepc->inputdev, key->keycode, -						1); -			input_sync(eeepc->inputdev); -			input_report_key(eeepc->inputdev, key->keycode, -						0); -			input_sync(eeepc->inputdev); -			break; -		} -	} -} - -static struct key_entry *eeepc_get_entry_by_keycode( -	struct eeepc_laptop *eeepc, int code) -{ -	struct key_entry *key; - -	for (key = eeepc->keymap; key->type != KE_END; key++) -		if (code == key->keycode && key->type == KE_KEY) -			return key; - -	return NULL; -} - -static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) -{ -	struct eeepc_laptop *eeepc = input_get_drvdata(dev); -	struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode); - -	if (key && key->type == KE_KEY) { -		*keycode = key->keycode; -		return 0; -	} - -	return -EINVAL; -} - -static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) -{ -	struct eeepc_laptop *eeepc = input_get_drvdata(dev); -	struct key_entry *key; -	int old_keycode; - -	if (keycode < 0 || keycode > KEY_MAX) -		return -EINVAL; - -	key = eeepc_get_entry_by_scancode(eeepc, scancode); -	if (key && key->type == KE_KEY) { -		old_keycode = key->keycode; -		key->keycode = keycode; -		set_bit(keycode, dev->keybit); -		if (!eeepc_get_entry_by_keycode(eeepc, old_keycode)) -			clear_bit(old_keycode, dev->keybit); -		return 0; -	} - -	return -EINVAL; -} -  static int eeepc_input_init(struct eeepc_laptop *eeepc)  { -	const struct key_entry *key; -	int result; +	struct input_dev *input; +	int error; -	eeepc->inputdev = input_allocate_device(); -	if (!eeepc->inputdev) { +	input = input_allocate_device(); +	if (!input) {  		pr_info("Unable to allocate input device\n");  		return -ENOMEM;  	} -	eeepc->inputdev->name = "Asus EeePC extra buttons"; -	eeepc->inputdev->dev.parent = &eeepc->platform_device->dev; -	eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0"; -	eeepc->inputdev->id.bustype = BUS_HOST; -	eeepc->inputdev->getkeycode = eeepc_getkeycode; -	eeepc->inputdev->setkeycode = eeepc_setkeycode; -	input_set_drvdata(eeepc->inputdev, eeepc); -	eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap), -				GFP_KERNEL); -	for (key = eeepc_keymap; key->type != KE_END; key++) { -		switch (key->type) { -		case KE_KEY: -			set_bit(EV_KEY, eeepc->inputdev->evbit); -			set_bit(key->keycode, eeepc->inputdev->keybit); -			break; -		} +	input->name = "Asus EeePC extra buttons"; +	input->phys = EEEPC_LAPTOP_FILE "/input0"; +	input->id.bustype = BUS_HOST; +	input->dev.parent = &eeepc->platform_device->dev; + +	error = sparse_keymap_setup(input, eeepc_keymap, NULL); +	if (error) { +		pr_err("Unable to setup input device keymap\n"); +		goto err_free_dev;  	} -	result = input_register_device(eeepc->inputdev); -	if (result) { -		pr_info("Unable to register input device\n"); -		input_free_device(eeepc->inputdev); -		return result; + +	error = input_register_device(input); +	if (error) { +		pr_err("Unable to register input device\n"); +		goto err_free_keymap;  	} + +	eeepc->inputdev = input;  	return 0; + + err_free_keymap: +	sparse_keymap_free(input); + err_free_dev: +	input_free_device(input); +	return error;  }  static void eeepc_input_exit(struct eeepc_laptop *eeepc) @@ -1253,11 +1227,59 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event)  				* event will be desired value (or else ignored)  				*/  			} -			eeepc_input_notify(eeepc, event); +			sparse_keymap_report_event(eeepc->inputdev, event, +						   1, true);  		}  	} else {  		/* Everything else is a bona-fide keypress event */ -		eeepc_input_notify(eeepc, event); +		sparse_keymap_report_event(eeepc->inputdev, event, 1, true); +	} +} + +static void eeepc_dmi_check(struct eeepc_laptop *eeepc) +{ +	const char *model; + +	model = dmi_get_system_info(DMI_PRODUCT_NAME); +	if (!model) +		return; + +	/* +	 * Blacklist for setting cpufv (cpu speed). +	 * +	 * EeePC 4G ("701") implements CFVS, but it is not supported +	 * by the pre-installed OS, and the original option to change it +	 * in the BIOS setup screen was removed in later versions. +	 * +	 * Judging by the lack of "Super Hybrid Engine" on Asus product pages, +	 * this applies to all "701" models (4G/4G Surf/2G Surf). +	 * +	 * So Asus made a deliberate decision not to support it on this model. +	 * We have several reports that using it can cause the system to hang +	 * +	 * The hang has also been reported on a "702" (Model name "8G"?). +	 * +	 * We avoid dmi_check_system() / dmi_match(), because they use +	 * substring matching.  We don't want to affect the "701SD" +	 * and "701SDX" models, because they do support S.H.E. +	 */ +	if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { +		eeepc->cpufv_disabled = true; +		pr_info("model %s does not officially support setting cpu " +			"speed\n", model); +		pr_info("cpufv disabled to avoid instability\n"); +	} + +	/* +	 * Blacklist for wlan hotplug +	 * +	 * Eeepc 1005HA doesn't work like others models and don't need the +	 * hotplug code. In fact, current hotplug code seems to unplug another +	 * device... +	 */ +	if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) { +		eeepc->hotplug_disabled = true; +		pr_info("wlan hotplug disabled\n");  	}  } @@ -1342,6 +1364,10 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device)  	strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);  	device->driver_data = eeepc; +	eeepc->hotplug_disabled = hotplug_disabled; + +	eeepc_dmi_check(eeepc); +  	result = eeepc_acpi_init(eeepc, device);  	if (result)  		goto fail_platform; @@ -1452,10 +1478,12 @@ static int __init eeepc_laptop_init(void)  	result = acpi_bus_register_driver(&eeepc_acpi_driver);  	if (result < 0)  		goto fail_acpi_driver; +  	if (!eeepc_device_present) {  		result = -ENODEV;  		goto fail_no_device;  	} +  	return 0;  fail_no_device: diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 5af53340da6..3f71a605a49 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1201,9 +1201,12 @@ static void sony_nc_rfkill_setup(struct acpi_device *device)  	/* the buffer is filled with magic numbers describing the devices  	 * available, 0xff terminates the enumeration  	 */ -	while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff && -			i < device_enum->buffer.length) { -		i++; +	for (i = 0; i < device_enum->buffer.length; i++) { + +		dev_code = *(device_enum->buffer.pointer + i); +		if (dev_code == 0xff) +			break; +  		dprintk("Radio devices, looking at 0x%.2x\n", dev_code);  		if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index b5496a19d96..24485cc62ff 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -328,15 +328,7 @@ static const struct pnp_device_id pnp_dev_table[] = {  	/* U.S. Robotics 56K Voice INT PnP*/  	{	"USR9190",		0	},  	/* Wacom tablets */ -	{	"WACF004",		0	}, -	{	"WACF005",		0	}, -	{       "WACF006",              0       }, -	{       "WACF007",              0       }, -	{       "WACF008",              0       }, -	{       "WACF009",              0       }, -	{       "WACF00A",              0       }, -	{       "WACF00B",              0       }, -	{       "WACF00C",              0       }, +	{	"WACFXXX",		0	},  	/* Compaq touchscreen */  	{       "FPI2002",              0 },  	/* Fujitsu Stylistic touchscreens */ diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 18130f11238..60d665a17a8 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -1088,7 +1088,7 @@ imx_console_get_options(struct imx_port *sport, int *baud,  			   int *parity, int *bits)  { -	if ( readl(sport->port.membase + UCR1) | UCR1_UARTEN ) { +	if (readl(sport->port.membase + UCR1) & UCR1_UARTEN) {  		/* ok, the port was enabled */  		unsigned int ucr2, ubir,ubmr, uartclk;  		unsigned int baud_raw; diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 047530b285b..7f283070951 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -385,13 +385,20 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,  		}  		/* -		 * As a last resort, if the quotient is zero, -		 * default to 9600 bps +		 * As a last resort, if the range cannot be met then clip to +		 * the nearest chip supported rate.  		 */ -		if (!hung_up) -			tty_termios_encode_baud_rate(termios, 9600, 9600); +		if (!hung_up) { +			if (baud <= min) +				tty_termios_encode_baud_rate(termios, +							min + 1, min + 1); +			else +				tty_termios_encode_baud_rate(termios, +							max - 1, max - 1); +		}  	} - +	/* Should never happen */ +	WARN_ON(1);  	return 0;  } @@ -2006,12 +2013,6 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)  	mutex_lock(&port->mutex); -	if (!console_suspend_enabled && uart_console(uport)) { -		/* we're going to avoid suspending serial console */ -		mutex_unlock(&port->mutex); -		return 0; -	} -  	tty_dev = device_find_child(uport->dev, &match, serial_match_port);  	if (device_may_wakeup(tty_dev)) {  		enable_irq_wake(uport->irq); @@ -2019,20 +2020,23 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)  		mutex_unlock(&port->mutex);  		return 0;  	} -	uport->suspended = 1; +	if (console_suspend_enabled || !uart_console(uport)) +		uport->suspended = 1;  	if (port->flags & ASYNC_INITIALIZED) {  		const struct uart_ops *ops = uport->ops;  		int tries; -		set_bit(ASYNCB_SUSPENDED, &port->flags); -		clear_bit(ASYNCB_INITIALIZED, &port->flags); +		if (console_suspend_enabled || !uart_console(uport)) { +			set_bit(ASYNCB_SUSPENDED, &port->flags); +			clear_bit(ASYNCB_INITIALIZED, &port->flags); -		spin_lock_irq(&uport->lock); -		ops->stop_tx(uport); -		ops->set_mctrl(uport, 0); -		ops->stop_rx(uport); -		spin_unlock_irq(&uport->lock); +			spin_lock_irq(&uport->lock); +			ops->stop_tx(uport); +			ops->set_mctrl(uport, 0); +			ops->stop_rx(uport); +			spin_unlock_irq(&uport->lock); +		}  		/*  		 * Wait for the transmitter to empty. @@ -2047,16 +2051,18 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)  			       drv->dev_name,  			       drv->tty_driver->name_base + uport->line); -		ops->shutdown(uport); +		if (console_suspend_enabled || !uart_console(uport)) +			ops->shutdown(uport);  	}  	/*  	 * Disable the console device before suspending.  	 */ -	if (uart_console(uport)) +	if (console_suspend_enabled && uart_console(uport))  		console_stop(uport->cons); -	uart_change_pm(state, 3); +	if (console_suspend_enabled || !uart_console(uport)) +		uart_change_pm(state, 3);  	mutex_unlock(&port->mutex); @@ -2073,29 +2079,6 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)  	mutex_lock(&port->mutex); -	if (!console_suspend_enabled && uart_console(uport)) { -		/* no need to resume serial console, it wasn't suspended */ -		/* -		 * First try to use the console cflag setting. -		 */ -		memset(&termios, 0, sizeof(struct ktermios)); -		termios.c_cflag = uport->cons->cflag; -		/* -		 * If that's unset, use the tty termios setting. -		 */ -		if (termios.c_cflag == 0) -			termios = *state->port.tty->termios; -		else { -			termios.c_ispeed = termios.c_ospeed = -				tty_termios_input_baud_rate(&termios); -			termios.c_ispeed = termios.c_ospeed = -				tty_termios_baud_rate(&termios); -		} -		uport->ops->set_termios(uport, &termios, NULL); -		mutex_unlock(&port->mutex); -		return 0; -	} -  	tty_dev = device_find_child(uport->dev, &match, serial_match_port);  	if (!uport->suspended && device_may_wakeup(tty_dev)) {  		disable_irq_wake(uport->irq); @@ -2121,21 +2104,23 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)  		spin_lock_irq(&uport->lock);  		ops->set_mctrl(uport, 0);  		spin_unlock_irq(&uport->lock); -		ret = ops->startup(uport); -		if (ret == 0) { -			uart_change_speed(state, NULL); -			spin_lock_irq(&uport->lock); -			ops->set_mctrl(uport, uport->mctrl); -			ops->start_tx(uport); -			spin_unlock_irq(&uport->lock); -			set_bit(ASYNCB_INITIALIZED, &port->flags); -		} else { -			/* -			 * Failed to resume - maybe hardware went away? -			 * Clear the "initialized" flag so we won't try -			 * to call the low level drivers shutdown method. -			 */ -			uart_shutdown(state); +		if (console_suspend_enabled || !uart_console(uport)) { +			ret = ops->startup(uport); +			if (ret == 0) { +				uart_change_speed(state, NULL); +				spin_lock_irq(&uport->lock); +				ops->set_mctrl(uport, uport->mctrl); +				ops->start_tx(uport); +				spin_unlock_irq(&uport->lock); +				set_bit(ASYNCB_INITIALIZED, &port->flags); +			} else { +				/* +				 * Failed to resume - maybe hardware went away? +				 * Clear the "initialized" flag so we won't try +				 * to call the low level drivers shutdown method. +				 */ +				uart_shutdown(state); +			}  		}  		clear_bit(ASYNCB_SUSPENDED, &port->flags); diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 0ee7239c5d6..df854401af2 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -146,7 +146,8 @@ static void quirk_wakeup_oxsemi(struct pcmcia_device *link)  {  	struct serial_info *info = link->priv; -	outb(12, info->c950ctrl + 1); +	if (info->c950ctrl) +		outb(12, info->c950ctrl + 1);  }  /* request_region? oxsemi branch does no request_region too... */ diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c index f4c26572c7d..43c57b7688a 100644 --- a/drivers/staging/asus_oled/asus_oled.c +++ b/drivers/staging/asus_oled/asus_oled.c @@ -194,9 +194,11 @@ static ssize_t set_enabled(struct device *dev, struct device_attribute *attr,  {  	struct usb_interface *intf = to_usb_interface(dev);  	struct asus_oled_dev *odev = usb_get_intfdata(intf); -	int temp = strict_strtoul(buf, 10, NULL); +	unsigned long value; +	if (strict_strtoul(buf, 10, &value)) +		return -EINVAL; -	enable_oled(odev, temp); +	enable_oled(odev, value);  	return count;  } @@ -207,10 +209,12 @@ static ssize_t class_set_enabled(struct device *device,  {  	struct asus_oled_dev *odev =  		(struct asus_oled_dev *) dev_get_drvdata(device); +	unsigned long value; -	int temp = strict_strtoul(buf, 10, NULL); +	if (strict_strtoul(buf, 10, &value)) +		return -EINVAL; -	enable_oled(odev, temp); +	enable_oled(odev, value);  	return count;  } diff --git a/drivers/staging/et131x/et1310_address_map.h b/drivers/staging/et131x/et1310_address_map.h index 6da843cc343..e715e4dcb52 100644 --- a/drivers/staging/et131x/et1310_address_map.h +++ b/drivers/staging/et131x/et1310_address_map.h @@ -203,11 +203,14 @@ typedef struct _GLOBAL_t {			/* Location: */   * 9-0: pr ndes   */ -#define ET_DMA10_MASK		0x3FF	/* 10 bit mask for DMA10W types */ -#define ET_DMA10_WRAP		0x400 -#define ET_DMA4_MASK		0x00F	/* 4 bit mask for DMA4W types */ -#define ET_DMA4_WRAP		0x010 +#define ET_DMA12_MASK		0x0FFF	/* 12 bit mask for DMA12W types */ +#define ET_DMA12_WRAP		0x1000 +#define ET_DMA10_MASK		0x03FF	/* 10 bit mask for DMA10W types */ +#define ET_DMA10_WRAP		0x0400 +#define ET_DMA4_MASK		0x000F	/* 4 bit mask for DMA4W types */ +#define ET_DMA4_WRAP		0x0010 +#define INDEX12(x)	((x) & ET_DMA12_MASK)  #define INDEX10(x)	((x) & ET_DMA10_MASK)  #define INDEX4(x)	((x) & ET_DMA4_MASK) @@ -216,6 +219,11 @@ extern inline void add_10bit(u32 *v, int n)  	*v = INDEX10(*v + n) | (*v & ET_DMA10_WRAP);  } +extern inline void add_12bit(u32 *v, int n) +{ +	*v = INDEX12(*v + n) | (*v & ET_DMA12_WRAP); +} +  /*   * 10bit DMA with wrap   * txdma tx queue write address reg in txdma address map at 0x1010 diff --git a/drivers/staging/et131x/et1310_rx.c b/drivers/staging/et131x/et1310_rx.c index 3ddc9b12b8d..81c1a7478ad 100644 --- a/drivers/staging/et131x/et1310_rx.c +++ b/drivers/staging/et131x/et1310_rx.c @@ -831,10 +831,10 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)  	/* Indicate that we have used this PSR entry. */  	/* FIXME wrap 12 */ -	rx_local->local_psr_full = (rx_local->local_psr_full + 1) & 0xFFF; -	if (rx_local->local_psr_full  > rx_local->PsrNumEntries - 1) { +	add_12bit(&rx_local->local_psr_full, 1); +	if ((rx_local->local_psr_full & 0xFFF)  > rx_local->PsrNumEntries - 1) {  		/* Clear psr full and toggle the wrap bit */ -		rx_local->local_psr_full &=  0xFFF; +		rx_local->local_psr_full &=  ~0xFFF;  		rx_local->local_psr_full ^= 0x1000;  	} diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c index c5b6613f2f2..c2809f2a2ce 100644 --- a/drivers/staging/hv/Hv.c +++ b/drivers/staging/hv/Hv.c @@ -386,7 +386,7 @@ u16 HvSignalEvent(void)   * retrieve the initialized message and event pages.  Otherwise, we create and   * initialize the message and event pages.   */ -int HvSynicInit(u32 irqVector) +void HvSynicInit(void *irqarg)  {  	u64 version;  	union hv_synic_simp simp; @@ -394,13 +394,14 @@ int HvSynicInit(u32 irqVector)  	union hv_synic_sint sharedSint;  	union hv_synic_scontrol sctrl;  	u64 guestID; -	int ret = 0; +	u32 irqVector = *((u32 *)(irqarg)); +	int cpu = smp_processor_id();  	DPRINT_ENTER(VMBUS);  	if (!gHvContext.HypercallPage) {  		DPRINT_EXIT(VMBUS); -		return ret; +		return;  	}  	/* Check the version */ @@ -425,27 +426,27 @@ int HvSynicInit(u32 irqVector)  		 */  		rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID);  		if (guestID == HV_LINUX_GUEST_ID) { -			gHvContext.synICMessagePage[0] = +			gHvContext.synICMessagePage[cpu] =  				phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT); -			gHvContext.synICEventPage[0] = +			gHvContext.synICEventPage[cpu] =  				phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT);  		} else {  			DPRINT_ERR(VMBUS, "unknown guest id!!");  			goto Cleanup;  		}  		DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p", -			   gHvContext.synICMessagePage[0], -			   gHvContext.synICEventPage[0]); +			   gHvContext.synICMessagePage[cpu], +			   gHvContext.synICEventPage[cpu]);  	} else { -		gHvContext.synICMessagePage[0] = osd_PageAlloc(1); -		if (gHvContext.synICMessagePage[0] == NULL) { +		gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC); +		if (gHvContext.synICMessagePage[cpu] == NULL) {  			DPRINT_ERR(VMBUS,  				   "unable to allocate SYNIC message page!!");  			goto Cleanup;  		} -		gHvContext.synICEventPage[0] = osd_PageAlloc(1); -		if (gHvContext.synICEventPage[0] == NULL) { +		gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC); +		if (gHvContext.synICEventPage[cpu] == NULL) {  			DPRINT_ERR(VMBUS,  				   "unable to allocate SYNIC event page!!");  			goto Cleanup; @@ -454,7 +455,7 @@ int HvSynicInit(u32 irqVector)  		/* Setup the Synic's message page */  		rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);  		simp.SimpEnabled = 1; -		simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[0]) +		simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu])  					>> PAGE_SHIFT;  		DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", @@ -465,7 +466,7 @@ int HvSynicInit(u32 irqVector)  		/* Setup the Synic's event page */  		rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);  		siefp.SiefpEnabled = 1; -		siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[0]) +		siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu])  					>> PAGE_SHIFT;  		DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", @@ -501,32 +502,30 @@ int HvSynicInit(u32 irqVector)  	DPRINT_EXIT(VMBUS); -	return ret; +	return;  Cleanup: -	ret = -1; -  	if (gHvContext.GuestId == HV_LINUX_GUEST_ID) { -		if (gHvContext.synICEventPage[0]) -			osd_PageFree(gHvContext.synICEventPage[0], 1); +		if (gHvContext.synICEventPage[cpu]) +			osd_PageFree(gHvContext.synICEventPage[cpu], 1); -		if (gHvContext.synICMessagePage[0]) -			osd_PageFree(gHvContext.synICMessagePage[0], 1); +		if (gHvContext.synICMessagePage[cpu]) +			osd_PageFree(gHvContext.synICMessagePage[cpu], 1);  	}  	DPRINT_EXIT(VMBUS); - -	return ret; +	return;  }  /**   * HvSynicCleanup - Cleanup routine for HvSynicInit().   */ -void HvSynicCleanup(void) +void HvSynicCleanup(void *arg)  {  	union hv_synic_sint sharedSint;  	union hv_synic_simp simp;  	union hv_synic_siefp siefp; +	int cpu = smp_processor_id();  	DPRINT_ENTER(VMBUS); @@ -539,6 +538,7 @@ void HvSynicCleanup(void)  	sharedSint.Masked = 1; +	/* Need to correctly cleanup in the case of SMP!!! */  	/* Disable the interrupt */  	wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64); @@ -560,8 +560,8 @@ void HvSynicCleanup(void)  		wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); -		osd_PageFree(gHvContext.synICMessagePage[0], 1); -		osd_PageFree(gHvContext.synICEventPage[0], 1); +		osd_PageFree(gHvContext.synICMessagePage[cpu], 1); +		osd_PageFree(gHvContext.synICEventPage[cpu], 1);  	}  	DPRINT_EXIT(VMBUS); diff --git a/drivers/staging/hv/Hv.h b/drivers/staging/hv/Hv.h index 5379e4bfc56..fce4b5cdac3 100644 --- a/drivers/staging/hv/Hv.h +++ b/drivers/staging/hv/Hv.h @@ -93,7 +93,7 @@ static const struct hv_guid VMBUS_SERVICE_ID = {  	},  }; -#define MAX_NUM_CPUS	1 +#define MAX_NUM_CPUS	32  struct hv_input_signal_event_buffer { @@ -137,8 +137,8 @@ extern u16 HvPostMessage(union hv_connection_id connectionId,  extern u16 HvSignalEvent(void); -extern int HvSynicInit(u32 irqVector); +extern void HvSynicInit(void *irqarg); -extern void HvSynicCleanup(void); +extern void HvSynicCleanup(void *arg);  #endif /* __HV_H__ */ diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c index a4dd06f6d45..35a023e9f9d 100644 --- a/drivers/staging/hv/Vmbus.c +++ b/drivers/staging/hv/Vmbus.c @@ -129,7 +129,7 @@ static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo)  	/* strcpy(dev->name, "vmbus"); */  	/* SynIC setup... */ -	ret = HvSynicInit(*irqvector); +	on_each_cpu(HvSynicInit, (void *)irqvector, 1);  	/* Connect to VMBus in the root partition */  	ret = VmbusConnect(); @@ -150,7 +150,7 @@ static int VmbusOnDeviceRemove(struct hv_device *dev)  	DPRINT_ENTER(VMBUS);  	VmbusChannelReleaseUnattachedChannels();  	VmbusDisconnect(); -	HvSynicCleanup(); +	on_each_cpu(HvSynicCleanup, NULL, 1);  	DPRINT_EXIT(VMBUS);  	return ret; @@ -173,7 +173,8 @@ static void VmbusOnCleanup(struct hv_driver *drv)   */  static void VmbusOnMsgDPC(struct hv_driver *drv)  { -	void *page_addr = gHvContext.synICMessagePage[0]; +	int cpu = smp_processor_id(); +	void *page_addr = gHvContext.synICMessagePage[cpu];  	struct hv_message *msg = (struct hv_message *)page_addr +  				  VMBUS_MESSAGE_SINT;  	struct hv_message *copied; @@ -230,11 +231,12 @@ static void VmbusOnEventDPC(struct hv_driver *drv)  static int VmbusOnISR(struct hv_driver *drv)  {  	int ret = 0; +	int cpu = smp_processor_id();  	void *page_addr;  	struct hv_message *msg;  	union hv_synic_event_flags *event; -	page_addr = gHvContext.synICMessagePage[0]; +	page_addr = gHvContext.synICMessagePage[cpu];  	msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;  	DPRINT_ENTER(VMBUS); @@ -248,7 +250,7 @@ static int VmbusOnISR(struct hv_driver *drv)  	}  	/* TODO: Check if there are events to be process */ -	page_addr = gHvContext.synICEventPage[0]; +	page_addr = gHvContext.synICEventPage[cpu];  	event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;  	/* Since we are a child, we only need to check bit 0 */ diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 96f11715cd2..355dffcc23b 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -494,7 +494,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,  		return 0;  	/* allocate 2^1 pages = 8K (on i386);  	 * should be more than enough for one device */ -	pages_start = (char *)__get_free_pages(GFP_KERNEL, 1); +	pages_start = (char *)__get_free_pages(GFP_NOIO, 1);  	if (!pages_start)  		return -ENOMEM; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0495fa65122..80995ef0868 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1684,6 +1684,24 @@ int usb_hcd_alloc_bandwidth(struct usb_device *udev,  		}  	}  	if (cur_alt && new_alt) { +		struct usb_interface *iface = usb_ifnum_to_if(udev, +				cur_alt->desc.bInterfaceNumber); + +		if (iface->resetting_device) { +			/* +			 * The USB core just reset the device, so the xHCI host +			 * and the device will think alt setting 0 is installed. +			 * However, the USB core will pass in the alternate +			 * setting installed before the reset as cur_alt.  Dig +			 * out the alternate setting 0 structure, or the first +			 * alternate setting if a broken device doesn't have alt +			 * setting 0. +			 */ +			cur_alt = usb_altnum_to_altsetting(iface, 0); +			if (!cur_alt) +				cur_alt = &iface->altsetting[0]; +		} +  		/* Drop all the endpoints in the current alt setting */  		for (i = 0; i < cur_alt->desc.bNumEndpoints; i++) {  			ret = hcd->driver->drop_endpoint(hcd, udev, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0cec6caf6e9..35cc8b9ba1f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3347,6 +3347,9 @@ static void hub_events(void)  					USB_PORT_FEAT_C_SUSPEND);  				udev = hdev->children[i-1];  				if (udev) { +					/* TRSMRCY = 10 msec */ +					msleep(10); +  					usb_lock_device(udev);  					ret = remote_wakeup(hdev->  							children[i-1]); @@ -3692,19 +3695,14 @@ static int usb_reset_and_verify_device(struct usb_device *udev)  			usb_enable_interface(udev, intf, true);  			ret = 0;  		} else { -			/* We've just reset the device, so it will think alt -			 * setting 0 is installed.  For usb_set_interface() to -			 * work properly, we need to set the current alternate -			 * interface setting to 0 (or the first alt setting, if -			 * the device doesn't have alt setting 0). +			/* Let the bandwidth allocation function know that this +			 * device has been reset, and it will have to use +			 * alternate setting 0 as the current alternate setting.  			 */ -			intf->cur_altsetting = -				usb_find_alt_setting(config, i, 0); -			if (!intf->cur_altsetting) -				intf->cur_altsetting = -					&config->intf_cache[i]->altsetting[0]; +			intf->resetting_device = 1;  			ret = usb_set_interface(udev, desc->bInterfaceNumber,  					desc->bAlternateSetting); +			intf->resetting_device = 0;  		}  		if (ret < 0) {  			dev_err(&udev->dev, "failed to restore interface %d " diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 1b994846e8e..9bc95fec793 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -906,11 +906,11 @@ char *usb_cache_string(struct usb_device *udev, int index)  	if (index <= 0)  		return NULL; -	buf = kmalloc(MAX_USB_STRING_SIZE, GFP_KERNEL); +	buf = kmalloc(MAX_USB_STRING_SIZE, GFP_NOIO);  	if (buf) {  		len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE);  		if (len > 0) { -			smallbuf = kmalloc(++len, GFP_KERNEL); +			smallbuf = kmalloc(++len, GFP_NOIO);  			if (!smallbuf)  				return buf;  			memcpy(smallbuf, buf, len); @@ -1731,7 +1731,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)  	if (cp) {  		nintf = cp->desc.bNumInterfaces;  		new_interfaces = kmalloc(nintf * sizeof(*new_interfaces), -				GFP_KERNEL); +				GFP_NOIO);  		if (!new_interfaces) {  			dev_err(&dev->dev, "Out of memory\n");  			return -ENOMEM; @@ -1740,7 +1740,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)  		for (; n < nintf; ++n) {  			new_interfaces[n] = kzalloc(  					sizeof(struct usb_interface), -					GFP_KERNEL); +					GFP_NOIO);  			if (!new_interfaces[n]) {  				dev_err(&dev->dev, "Out of memory\n");  				ret = -ENOMEM; diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 485edf937f2..5f3908f6e2d 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -115,6 +115,12 @@ show_speed(struct device *dev, struct device_attribute *attr, char *buf)  	case USB_SPEED_HIGH:  		speed = "480";  		break; +	case USB_SPEED_VARIABLE: +		speed = "480"; +		break; +	case USB_SPEED_SUPER: +		speed = "5000"; +		break;  	default:  		speed = "unknown";  	} diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 5859522d6ed..1ec3857f22e 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -787,9 +787,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  			/* start 20 msec resume signaling from this port,  			 * and make khubd collect PORT_STAT_C_SUSPEND to -			 * stop that signaling. +			 * stop that signaling.  Use 5 ms extra for safety, +			 * like usb_port_resume() does.  			 */ -			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); +			ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);  			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);  			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);  		} diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 2c6571c05f3..c75d9270c75 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -120,9 +120,26 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)  	del_timer_sync(&ehci->watchdog);  	del_timer_sync(&ehci->iaa_watchdog); -	port = HCS_N_PORTS (ehci->hcs_params);  	spin_lock_irq (&ehci->lock); +	/* Once the controller is stopped, port resumes that are already +	 * in progress won't complete.  Hence if remote wakeup is enabled +	 * for the root hub and any ports are in the middle of a resume or +	 * remote wakeup, we must fail the suspend. +	 */ +	if (hcd->self.root_hub->do_remote_wakeup) { +		port = HCS_N_PORTS(ehci->hcs_params); +		while (port--) { +			if (ehci->reset_done[port] != 0) { +				spin_unlock_irq(&ehci->lock); +				ehci_dbg(ehci, "suspend failed because " +						"port %d is resuming\n", +						port + 1); +				return -EBUSY; +			} +		} +	} +  	/* stop schedules, clean any completed work */  	if (HC_IS_RUNNING(hcd->state)) {  		ehci_quiesce (ehci); @@ -138,6 +155,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)  	 */  	ehci->bus_suspended = 0;  	ehci->owned_ports = 0; +	port = HCS_N_PORTS(ehci->hcs_params);  	while (port--) {  		u32 __iomem	*reg = &ehci->regs->port_status [port];  		u32		t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index a427d3b0063..89521775c56 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -849,9 +849,10 @@ qh_make (  				 * But interval 1 scheduling is simpler, and  				 * includes high bandwidth.  				 */ -				dbg ("intr period %d uframes, NYET!", -						urb->interval); -				goto done; +				urb->interval = 1; +			} else if (qh->period > ehci->periodic_size) { +				qh->period = ehci->periodic_size; +				urb->interval = qh->period << 3;  			}  		} else {  			int		think_time; @@ -874,6 +875,10 @@ qh_make (  					usb_calc_bus_time (urb->dev->speed,  					is_input, 0, max_packet (maxp)));  			qh->period = urb->interval; +			if (qh->period > ehci->periodic_size) { +				qh->period = ehci->periodic_size; +				urb->interval = qh->period; +			}  		}  	} diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index 0951818ef93..78e7c3cfcb7 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -242,9 +242,10 @@ err:  static void fhci_usb_free(void *lld)  {  	struct fhci_usb *usb = lld; -	struct fhci_hcd *fhci = usb->fhci; +	struct fhci_hcd *fhci;  	if (usb) { +		fhci = usb->fhci;  		fhci_config_transceiver(fhci, FHCI_PORT_POWER_OFF);  		fhci_ep0_free(usb);  		kfree(usb->actual_frame); diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 73352f3739b..42971657fde 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2270,10 +2270,10 @@ static int isp1362_mem_config(struct usb_hcd *hcd)  	dev_info(hcd->self.controller, "ISP1362 Memory usage:\n");  	dev_info(hcd->self.controller, "  ISTL:    2 * %4d:     %4d @ $%04x:$%04x\n",  		 istl_size / 2, istl_size, 0, istl_size / 2); -	dev_info(hcd->self.controller, "  INTL: %4d * (%3lu+8):  %4d @ $%04x\n", +	dev_info(hcd->self.controller, "  INTL: %4d * (%3zu+8):  %4d @ $%04x\n",  		 ISP1362_INTL_BUFFERS, intl_blksize - PTD_HEADER_SIZE,  		 intl_size, istl_size); -	dev_info(hcd->self.controller, "  ATL : %4d * (%3lu+8):  %4d @ $%04x\n", +	dev_info(hcd->self.controller, "  ATL : %4d * (%3zu+8):  %4d @ $%04x\n",  		 atl_buffers, atl_blksize - PTD_HEADER_SIZE,  		 atl_size, istl_size + intl_size);  	dev_info(hcd->self.controller, "  USED/FREE:   %4d      %4d\n", total, @@ -2697,6 +2697,8 @@ static int __init isp1362_probe(struct platform_device *pdev)  	void __iomem *data_reg;  	int irq;  	int retval = 0; +	struct resource *irq_res; +	unsigned int irq_flags = 0;  	/* basic sanity checks first.  board-specific init logic should  	 * have initialized this the three resources and probably board @@ -2710,11 +2712,12 @@ static int __init isp1362_probe(struct platform_device *pdev)  	data = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	addr = platform_get_resource(pdev, IORESOURCE_MEM, 1); -	irq = platform_get_irq(pdev, 0); -	if (!addr || !data || irq < 0) { +	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); +	if (!addr || !data || !irq_res) {  		retval = -ENODEV;  		goto err1;  	} +	irq = irq_res->start;  #ifdef CONFIG_USB_HCD_DMA  	if (pdev->dev.dma_mask) { @@ -2781,12 +2784,16 @@ static int __init isp1362_probe(struct platform_device *pdev)  	}  #endif -#ifdef CONFIG_ARM -	if (isp1362_hcd->board) -		set_irq_type(irq, isp1362_hcd->board->int_act_high ? IRQT_RISING : IRQT_FALLING); -#endif +	if (irq_res->flags & IORESOURCE_IRQ_HIGHEDGE) +		irq_flags |= IRQF_TRIGGER_RISING; +	if (irq_res->flags & IORESOURCE_IRQ_LOWEDGE) +		irq_flags |= IRQF_TRIGGER_FALLING; +	if (irq_res->flags & IORESOURCE_IRQ_HIGHLEVEL) +		irq_flags |= IRQF_TRIGGER_HIGH; +	if (irq_res->flags & IORESOURCE_IRQ_LOWLEVEL) +		irq_flags |= IRQF_TRIGGER_LOW; -	retval = usb_add_hcd(hcd, irq, IRQF_TRIGGER_LOW | IRQF_DISABLED | IRQF_SHARED); +	retval = usb_add_hcd(hcd, irq, irq_flags | IRQF_DISABLED | IRQF_SHARED);  	if (retval != 0)  		goto err6;  	pr_info("%s, irq %d\n", hcd->product_desc, irq); diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 9600a58299d..27b8f7cb447 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -1039,12 +1039,12 @@ static void do_atl_int(struct usb_hcd *usb_hcd)  		if (!nakcount && (dw3 & DW3_QTD_ACTIVE)) {  			u32 buffstatus; -			/* XXX +			/*  			 * NAKs are handled in HW by the chip. Usually if the  			 * device is not able to send data fast enough. -			 * This did not trigger for a long time now. +			 * This happens mostly on slower hardware.  			 */ -			printk(KERN_ERR "Reloading ptd %p/%p... qh %p readed: " +			printk(KERN_NOTICE "Reloading ptd %p/%p... qh %p read: "  					"%d of %zu done: %08x cur: %08x\n", qtd,  					urb, qh, PTD_XFERRED_LENGTH(dw3),  					qtd->length, done_map, diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 5cd0e48f67f..99cd00fd351 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -749,7 +749,20 @@ static int uhci_rh_suspend(struct usb_hcd *hcd)  	spin_lock_irq(&uhci->lock);  	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))  		rc = -ESHUTDOWN; -	else if (!uhci->dead) +	else if (uhci->dead) +		;		/* Dead controllers tell no tales */ + +	/* Once the controller is stopped, port resumes that are already +	 * in progress won't complete.  Hence if remote wakeup is enabled +	 * for the root hub and any ports are in the middle of a resume or +	 * remote wakeup, we must fail the suspend. +	 */ +	else if (hcd->self.root_hub->do_remote_wakeup && +			uhci->resuming_ports) { +		dev_dbg(uhci_dev(uhci), "suspend failed because a port " +				"is resuming\n"); +		rc = -EBUSY; +	} else  		suspend_rh(uhci, UHCI_RH_SUSPENDED);  	spin_unlock_irq(&uhci->lock);  	return rc; diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 885b585360b..8270055848c 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -167,7 +167,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci)  				/* Port received a wakeup request */  				set_bit(port, &uhci->resuming_ports);  				uhci->ports_timeout = jiffies + -						msecs_to_jiffies(20); +						msecs_to_jiffies(25);  				/* Make sure we see the port again  				 * after the resuming period is over. */ diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index f1ea3a33b6e..83443d6306d 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -386,12 +386,12 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)  	dbg("%s - port %d", __func__, port->number); -	if (serial->type->max_in_flight_urbs) { -		spin_lock_irqsave(&port->lock, flags); +	spin_lock_irqsave(&port->lock, flags); +	if (serial->type->max_in_flight_urbs)  		chars = port->tx_bytes_flight; -		spin_unlock_irqrestore(&port->lock, flags); -	} else if (serial->num_bulk_out) +	else if (serial->num_bulk_out)  		chars = kfifo_len(&port->write_fifo); +	spin_unlock_irqrestore(&port->lock, flags);  	dbg("%s - returns %d", __func__, chars);  	return chars; @@ -489,6 +489,8 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)  	dbg("%s - port %d", __func__, port->number);  	if (port->serial->type->max_in_flight_urbs) { +		kfree(urb->transfer_buffer); +  		spin_lock_irqsave(&port->lock, flags);  		--port->urbs_in_flight;  		port->tx_bytes_flight -= urb->transfer_buffer_length; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 64a0a2c27e1..c932f905318 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1807,13 +1807,6 @@ UNUSUAL_DEV(  0x2735, 0x100b, 0x0000, 0x9999,  		US_SC_DEVICE, US_PR_DEVICE, NULL,  		US_FL_GO_SLOW ), -/* Reported by Rohan Hart <rohan.hart17@gmail.com> */ -UNUSUAL_DEV(  0x2770, 0x915d, 0x0010, 0x0010, -		"INTOVA", -		"Pixtreme", -		US_SC_DEVICE, US_PR_DEVICE, NULL, -		US_FL_FIX_CAPACITY ), -  /* Reported by Frederic Marchal <frederic.marchal@wowcompany.com>   * Mio Moov 330   */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 5a53d4f0dd1..e9f995486ec 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -434,7 +434,8 @@ static void adjust_quirks(struct us_data *us)  	u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor);  	u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct);  	unsigned f = 0; -	unsigned int mask = (US_FL_SANE_SENSE | US_FL_FIX_CAPACITY | +	unsigned int mask = (US_FL_SANE_SENSE | US_FL_BAD_SENSE | +			US_FL_FIX_CAPACITY |  			US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE |  			US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |  			US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE | diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 430a5848a9a..c7a9479934a 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -96,9 +96,6 @@ static void wdt_enable(void)  {  	spin_lock(&io_lock); -	if (wdt_clk) -		clk_set_rate(wdt_clk, 1); -  	/* stop counter, initiate counter reset */  	__raw_writel(RESET_COUNT, WDTIM_CTRL(wdt_base));  	/*wait for reset to complete. 100% guarantee event */ @@ -125,19 +122,25 @@ static void wdt_disable(void)  	spin_lock(&io_lock);  	__raw_writel(0, WDTIM_CTRL(wdt_base));	/*stop counter */ -	if (wdt_clk) -		clk_set_rate(wdt_clk, 0);  	spin_unlock(&io_lock);  }  static int pnx4008_wdt_open(struct inode *inode, struct file *file)  { +	int ret; +  	if (test_and_set_bit(WDT_IN_USE, &wdt_status))  		return -EBUSY;  	clear_bit(WDT_OK_TO_CLOSE, &wdt_status); +	ret = clk_enable(wdt_clk); +	if (ret) { +		clear_bit(WDT_IN_USE, &wdt_status); +		return ret; +	} +  	wdt_enable();  	return nonseekable_open(inode, file); @@ -225,6 +228,7 @@ static int pnx4008_wdt_release(struct inode *inode, struct file *file)  		printk(KERN_WARNING "WATCHDOG: Device closed unexpectdly\n");  	wdt_disable(); +	clk_disable(wdt_clk);  	clear_bit(WDT_IN_USE, &wdt_status);  	clear_bit(WDT_OK_TO_CLOSE, &wdt_status); @@ -273,25 +277,33 @@ static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)  	}  	wdt_base = (void __iomem *)IO_ADDRESS(res->start); -	wdt_clk = clk_get(&pdev->dev, "wdt_ck"); +	wdt_clk = clk_get(&pdev->dev, NULL);  	if (IS_ERR(wdt_clk)) {  		ret = PTR_ERR(wdt_clk);  		release_resource(wdt_mem);  		kfree(wdt_mem);  		goto out; -	} else -		clk_set_rate(wdt_clk, 1); +	} + +	ret = clk_enable(wdt_clk); +	if (ret) { +		release_resource(wdt_mem); +		kfree(wdt_mem); +		goto out; +	}  	ret = misc_register(&pnx4008_wdt_miscdev);  	if (ret < 0) {  		printk(KERN_ERR MODULE_NAME "cannot register misc device\n");  		release_resource(wdt_mem);  		kfree(wdt_mem); -		clk_set_rate(wdt_clk, 0); +		clk_disable(wdt_clk); +		clk_put(wdt_clk);  	} else {  		boot_status = (__raw_readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ?  		    WDIOF_CARDRESET : 0;  		wdt_disable();		/*disable for now */ +		clk_disable(wdt_clk);  		set_bit(WDT_DEVICE_INITED, &wdt_status);  	} @@ -302,11 +314,10 @@ out:  static int __devexit pnx4008_wdt_remove(struct platform_device *pdev)  {  	misc_deregister(&pnx4008_wdt_miscdev); -	if (wdt_clk) { -		clk_set_rate(wdt_clk, 0); -		clk_put(wdt_clk); -		wdt_clk = NULL; -	} + +	clk_disable(wdt_clk); +	clk_put(wdt_clk); +  	if (wdt_mem) {  		release_resource(wdt_mem);  		kfree(wdt_mem); @@ -78,7 +78,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)  	i = 0;  	while (i < bio_slab_nr) { -		struct bio_slab *bslab = &bio_slabs[i]; +		bslab = &bio_slabs[i];  		if (!bslab->slab && entry == -1)  			entry = i; diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 2e9e69987a8..54f4798ab46 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -112,12 +112,14 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans,  	switch (type) {  	case ACL_TYPE_ACCESS:  		mode = inode->i_mode; -		ret = posix_acl_equiv_mode(acl, &mode); -		if (ret < 0) -			return ret; -		ret = 0; -		inode->i_mode = mode;  		name = POSIX_ACL_XATTR_ACCESS; +		if (acl) { +			ret = posix_acl_equiv_mode(acl, &mode); +			if (ret < 0) +				return ret; +			inode->i_mode = mode; +		} +		ret = 0;  		break;  	case ACL_TYPE_DEFAULT:  		if (!S_ISDIR(inode->i_mode)) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 56e50137d0e..432a2da4641 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -83,6 +83,17 @@ static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits)  	return (cache->flags & bits) == bits;  } +void btrfs_get_block_group(struct btrfs_block_group_cache *cache) +{ +	atomic_inc(&cache->count); +} + +void btrfs_put_block_group(struct btrfs_block_group_cache *cache) +{ +	if (atomic_dec_and_test(&cache->count)) +		kfree(cache); +} +  /*   * this adds the block group to the fs_info rb tree for the block group   * cache @@ -156,7 +167,7 @@ block_group_cache_tree_search(struct btrfs_fs_info *info, u64 bytenr,  		}  	}  	if (ret) -		atomic_inc(&ret->count); +		btrfs_get_block_group(ret);  	spin_unlock(&info->block_group_cache_lock);  	return ret; @@ -407,6 +418,8 @@ err:  	put_caching_control(caching_ctl);  	atomic_dec(&block_group->space_info->caching_threads); +	btrfs_put_block_group(block_group); +  	return 0;  } @@ -447,6 +460,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache)  	up_write(&fs_info->extent_commit_sem);  	atomic_inc(&cache->space_info->caching_threads); +	btrfs_get_block_group(cache);  	tsk = kthread_run(caching_kthread, cache, "btrfs-cache-%llu\n",  			  cache->key.objectid); @@ -486,12 +500,6 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(  	return cache;  } -void btrfs_put_block_group(struct btrfs_block_group_cache *cache) -{ -	if (atomic_dec_and_test(&cache->count)) -		kfree(cache); -} -  static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,  						  u64 flags)  { @@ -2582,7 +2590,7 @@ next_block_group(struct btrfs_root *root,  	if (node) {  		cache = rb_entry(node, struct btrfs_block_group_cache,  				 cache_node); -		atomic_inc(&cache->count); +		btrfs_get_block_group(cache);  	} else  		cache = NULL;  	spin_unlock(&root->fs_info->block_group_cache_lock); @@ -4227,7 +4235,7 @@ search:  		u64 offset;  		int cached; -		atomic_inc(&block_group->count); +		btrfs_get_block_group(block_group);  		search_start = block_group->key.objectid;  have_block_group: @@ -4315,7 +4323,7 @@ have_block_group:  				btrfs_put_block_group(block_group);  				block_group = last_ptr->block_group; -				atomic_inc(&block_group->count); +				btrfs_get_block_group(block_group);  				spin_unlock(&last_ptr->lock);  				spin_unlock(&last_ptr->refill_lock); @@ -7395,9 +7403,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)  			wait_block_group_cache_done(block_group);  		btrfs_remove_free_space_cache(block_group); - -		WARN_ON(atomic_read(&block_group->count) != 1); -		kfree(block_group); +		btrfs_put_block_group(block_group);  		spin_lock(&info->block_group_cache_lock);  	} diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index feaa13b105d..c02033596f0 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -506,7 +506,8 @@ next_slot:  }  static int extent_mergeable(struct extent_buffer *leaf, int slot, -			    u64 objectid, u64 bytenr, u64 *start, u64 *end) +			    u64 objectid, u64 bytenr, u64 orig_offset, +			    u64 *start, u64 *end)  {  	struct btrfs_file_extent_item *fi;  	struct btrfs_key key; @@ -522,6 +523,7 @@ static int extent_mergeable(struct extent_buffer *leaf, int slot,  	fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);  	if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG ||  	    btrfs_file_extent_disk_bytenr(leaf, fi) != bytenr || +	    btrfs_file_extent_offset(leaf, fi) != key.offset - orig_offset ||  	    btrfs_file_extent_compression(leaf, fi) ||  	    btrfs_file_extent_encryption(leaf, fi) ||  	    btrfs_file_extent_other_encoding(leaf, fi)) @@ -561,6 +563,7 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,  	u64 split;  	int del_nr = 0;  	int del_slot = 0; +	int recow;  	int ret;  	btrfs_drop_extent_cache(inode, start, end - 1, 0); @@ -568,6 +571,7 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,  	path = btrfs_alloc_path();  	BUG_ON(!path);  again: +	recow = 0;  	split = start;  	key.objectid = inode->i_ino;  	key.type = BTRFS_EXTENT_DATA_KEY; @@ -591,12 +595,60 @@ again:  	bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);  	num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi);  	orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi); +	memcpy(&new_key, &key, sizeof(new_key)); + +	if (start == key.offset && end < extent_end) { +		other_start = 0; +		other_end = start; +		if (extent_mergeable(leaf, path->slots[0] - 1, +				     inode->i_ino, bytenr, orig_offset, +				     &other_start, &other_end)) { +			new_key.offset = end; +			btrfs_set_item_key_safe(trans, root, path, &new_key); +			fi = btrfs_item_ptr(leaf, path->slots[0], +					    struct btrfs_file_extent_item); +			btrfs_set_file_extent_num_bytes(leaf, fi, +							extent_end - end); +			btrfs_set_file_extent_offset(leaf, fi, +						     end - orig_offset); +			fi = btrfs_item_ptr(leaf, path->slots[0] - 1, +					    struct btrfs_file_extent_item); +			btrfs_set_file_extent_num_bytes(leaf, fi, +							end - other_start); +			btrfs_mark_buffer_dirty(leaf); +			goto out; +		} +	} + +	if (start > key.offset && end == extent_end) { +		other_start = end; +		other_end = 0; +		if (extent_mergeable(leaf, path->slots[0] + 1, +				     inode->i_ino, bytenr, orig_offset, +				     &other_start, &other_end)) { +			fi = btrfs_item_ptr(leaf, path->slots[0], +					    struct btrfs_file_extent_item); +			btrfs_set_file_extent_num_bytes(leaf, fi, +							start - key.offset); +			path->slots[0]++; +			new_key.offset = start; +			btrfs_set_item_key_safe(trans, root, path, &new_key); + +			fi = btrfs_item_ptr(leaf, path->slots[0], +					    struct btrfs_file_extent_item); +			btrfs_set_file_extent_num_bytes(leaf, fi, +							other_end - start); +			btrfs_set_file_extent_offset(leaf, fi, +						     start - orig_offset); +			btrfs_mark_buffer_dirty(leaf); +			goto out; +		} +	}  	while (start > key.offset || end < extent_end) {  		if (key.offset == start)  			split = end; -		memcpy(&new_key, &key, sizeof(new_key));  		new_key.offset = split;  		ret = btrfs_duplicate_item(trans, root, path, &new_key);  		if (ret == -EAGAIN) { @@ -631,15 +683,18 @@ again:  			path->slots[0]--;  			extent_end = end;  		} +		recow = 1;  	} -	fi = btrfs_item_ptr(leaf, path->slots[0], -			    struct btrfs_file_extent_item); -  	other_start = end;  	other_end = 0; -	if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino, -			     bytenr, &other_start, &other_end)) { +	if (extent_mergeable(leaf, path->slots[0] + 1, +			     inode->i_ino, bytenr, orig_offset, +			     &other_start, &other_end)) { +		if (recow) { +			btrfs_release_path(root, path); +			goto again; +		}  		extent_end = other_end;  		del_slot = path->slots[0] + 1;  		del_nr++; @@ -650,8 +705,13 @@ again:  	}  	other_start = 0;  	other_end = start; -	if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino, -			     bytenr, &other_start, &other_end)) { +	if (extent_mergeable(leaf, path->slots[0] - 1, +			     inode->i_ino, bytenr, orig_offset, +			     &other_start, &other_end)) { +		if (recow) { +			btrfs_release_path(root, path); +			goto again; +		}  		key.offset = other_start;  		del_slot = path->slots[0];  		del_nr++; @@ -660,22 +720,22 @@ again:  					inode->i_ino, orig_offset);  		BUG_ON(ret);  	} +	fi = btrfs_item_ptr(leaf, path->slots[0], +			   struct btrfs_file_extent_item);  	if (del_nr == 0) {  		btrfs_set_file_extent_type(leaf, fi,  					   BTRFS_FILE_EXTENT_REG);  		btrfs_mark_buffer_dirty(leaf); -		goto out; -	} - -	fi = btrfs_item_ptr(leaf, del_slot - 1, -			    struct btrfs_file_extent_item); -	btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG); -	btrfs_set_file_extent_num_bytes(leaf, fi, -					extent_end - key.offset); -	btrfs_mark_buffer_dirty(leaf); +	} else { +		btrfs_set_file_extent_type(leaf, fi, +					   BTRFS_FILE_EXTENT_REG); +		btrfs_set_file_extent_num_bytes(leaf, fi, +						extent_end - key.offset); +		btrfs_mark_buffer_dirty(leaf); -	ret = btrfs_del_items(trans, root, path, del_slot, del_nr); -	BUG_ON(ret); +		ret = btrfs_del_items(trans, root, path, del_slot, del_nr); +		BUG_ON(ret); +	}  out:  	btrfs_free_path(path);  	return 0; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5440bab2363..b330e27c2d8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3796,6 +3796,12 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)  	if (location.type == BTRFS_INODE_ITEM_KEY) {  		inode = btrfs_iget(dir->i_sb, &location, root); +		if (unlikely(root->clean_orphans) && +		    !(inode->i_sb->s_flags & MS_RDONLY)) { +			down_read(&root->fs_info->cleanup_work_sem); +			btrfs_orphan_cleanup(root); +			up_read(&root->fs_info->cleanup_work_sem); +		}  		return inode;  	} @@ -3995,7 +4001,11 @@ skip:  	/* Reached end of directory/root. Bump pos past the last item. */  	if (key_type == BTRFS_DIR_INDEX_KEY) -		filp->f_pos = INT_LIMIT(off_t); +		/* +		 * 32-bit glibc will use getdents64, but then strtol - +		 * so the last number we can serve is this. +		 */ +		filp->f_pos = 0x7fffffff;  	else  		filp->f_pos++;  nopos: diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index b10a49d4bc6..5c2a9e78a94 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -626,6 +626,8 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,  	if (ordered)  		offset = entry_end(ordered); +	else +		offset = ALIGN(offset, BTRFS_I(inode)->root->sectorsize);  	mutex_lock(&tree->mutex);  	disk_i_size = BTRFS_I(inode)->disk_i_size; diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index a9728680eca..ed3e4a2ec2c 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -3281,8 +3281,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)  		return -ENOMEM;  	path = btrfs_alloc_path(); -	if (!path) +	if (!path) { +		kfree(cluster);  		return -ENOMEM; +	}  	rc->extents_found = 0;  	rc->extents_skipped = 0; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 198cff28766..220dad5db01 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2649,8 +2649,10 @@ again:  	em = lookup_extent_mapping(em_tree, logical, *length);  	read_unlock(&em_tree->lock); -	if (!em && unplug_page) +	if (!em && unplug_page) { +		kfree(multi);  		return 0; +	}  	if (!em) {  		printk(KERN_CRIT "unable to find logical %llu len %llu\n", diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 332dd00f089..c5c45de1a2e 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1005,6 +1005,9 @@ COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND)  COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST)  COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI)  #endif +/* Big V (don't complain on serial console) */ +IGNORE_IOCTL(VT_OPENQRY) +IGNORE_IOCTL(VT_GETMODE)  /* Little p (/dev/rtc, /dev/envctrl, etc.) */  COMPATIBLE_IOCTL(RTC_AIE_ON)  COMPATIBLE_IOCTL(RTC_AIE_OFF) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index fbb6e5eed69..7cb0a59f4b9 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1748,7 +1748,7 @@ ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm,  			    char *cipher_name, size_t *key_size)  {  	char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; -	char *full_alg_name; +	char *full_alg_name = NULL;  	int rc;  	*key_tfm = NULL; @@ -1763,7 +1763,6 @@ ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm,  	if (rc)  		goto out;  	*key_tfm = crypto_alloc_blkcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC); -	kfree(full_alg_name);  	if (IS_ERR(*key_tfm)) {  		rc = PTR_ERR(*key_tfm);  		printk(KERN_ERR "Unable to allocate crypto cipher with name " @@ -1786,6 +1785,7 @@ ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm,  		goto out;  	}  out: +	kfree(full_alg_name);  	return rc;  } diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 9e944057001..678172b61be 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -158,7 +158,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file)  	struct dentry *ecryptfs_dentry = file->f_path.dentry;  	/* Private value of ecryptfs_dentry allocated in  	 * ecryptfs_lookup() */ -	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); +	struct dentry *lower_dentry;  	struct ecryptfs_file_info *file_info;  	mount_crypt_stat = &ecryptfs_superblock_to_private( @@ -191,13 +191,6 @@ static int ecryptfs_open(struct inode *inode, struct file *file)  				      | ECRYPTFS_ENCRYPTED);  	}  	mutex_unlock(&crypt_stat->cs_mutex); -	if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY) -	    && !(file->f_flags & O_RDONLY)) { -		rc = -EPERM; -		printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs " -		       "file must hence be opened RO\n", __func__); -		goto out; -	}  	if (!ecryptfs_inode_to_private(inode)->lower_file) {  		rc = ecryptfs_init_persistent_file(ecryptfs_dentry);  		if (rc) { @@ -208,6 +201,13 @@ static int ecryptfs_open(struct inode *inode, struct file *file)  			goto out;  		}  	} +	if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY) +	    && !(file->f_flags & O_RDONLY)) { +		rc = -EPERM; +		printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs " +		       "file must hence be opened RO\n", __func__); +		goto out; +	}  	ecryptfs_set_file_lower(  		file, ecryptfs_inode_to_private(inode)->lower_file);  	if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { @@ -299,7 +299,6 @@ static int ecryptfs_ioctl(struct inode *inode, struct file *file,  const struct file_operations ecryptfs_dir_fops = {  	.readdir = ecryptfs_readdir,  	.ioctl = ecryptfs_ioctl, -	.mmap = generic_file_mmap,  	.open = ecryptfs_open,  	.flush = ecryptfs_flush,  	.release = ecryptfs_release, diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 7f854503293..4a430ab4115 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -282,7 +282,8 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,  		goto out;  	}  	rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, -				ecryptfs_dir_inode->i_sb, 1); +				ecryptfs_dir_inode->i_sb, +				ECRYPTFS_INTERPOSE_FLAG_D_ADD);  	if (rc) {  		printk(KERN_ERR "%s: Error interposing; rc = [%d]\n",  		       __func__, rc); @@ -463,9 +464,6 @@ out_lock:  	unlock_dir(lower_dir_dentry);  	dput(lower_new_dentry);  	dput(lower_old_dentry); -	d_drop(lower_old_dentry); -	d_drop(new_dentry); -	d_drop(old_dentry);  	return rc;  } @@ -614,6 +612,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,  	struct dentry *lower_new_dentry;  	struct dentry *lower_old_dir_dentry;  	struct dentry *lower_new_dir_dentry; +	struct dentry *trap = NULL;  	lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);  	lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry); @@ -621,7 +620,17 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,  	dget(lower_new_dentry);  	lower_old_dir_dentry = dget_parent(lower_old_dentry);  	lower_new_dir_dentry = dget_parent(lower_new_dentry); -	lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); +	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); +	/* source should not be ancestor of target */ +	if (trap == lower_old_dentry) { +		rc = -EINVAL; +		goto out_lock; +	} +	/* target should not be ancestor of source */ +	if (trap == lower_new_dentry) { +		rc = -ENOTEMPTY; +		goto out_lock; +	}  	rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,  			lower_new_dir_dentry->d_inode, lower_new_dentry);  	if (rc) @@ -772,18 +781,23 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat,  }  /** - * ecryptfs_truncate + * truncate_upper   * @dentry: The ecryptfs layer dentry - * @new_length: The length to expand the file to + * @ia: Address of the ecryptfs inode's attributes + * @lower_ia: Address of the lower inode's attributes   *   * Function to handle truncations modifying the size of the file. Note   * that the file sizes are interpolated. When expanding, we are simply - * writing strings of 0's out. When truncating, we need to modify the - * underlying file size according to the page index interpolations. + * writing strings of 0's out. When truncating, we truncate the upper + * inode and update the lower_ia according to the page index + * interpolations. If ATTR_SIZE is set in lower_ia->ia_valid upon return, + * the caller must use lower_ia in a call to notify_change() to perform + * the truncation of the lower inode.   *   * Returns zero on success; non-zero otherwise   */ -int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) +static int truncate_upper(struct dentry *dentry, struct iattr *ia, +			  struct iattr *lower_ia)  {  	int rc = 0;  	struct inode *inode = dentry->d_inode; @@ -794,8 +808,10 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)  	loff_t lower_size_before_truncate;  	loff_t lower_size_after_truncate; -	if (unlikely((new_length == i_size))) +	if (unlikely((ia->ia_size == i_size))) { +		lower_ia->ia_valid &= ~ATTR_SIZE;  		goto out; +	}  	crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;  	/* Set up a fake ecryptfs file, this is used to interface with  	 * the file in the underlying filesystem so that the @@ -815,28 +831,30 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)  		&fake_ecryptfs_file,  		ecryptfs_inode_to_private(dentry->d_inode)->lower_file);  	/* Switch on growing or shrinking file */ -	if (new_length > i_size) { +	if (ia->ia_size > i_size) {  		char zero[] = { 0x00 }; +		lower_ia->ia_valid &= ~ATTR_SIZE;  		/* Write a single 0 at the last position of the file;  		 * this triggers code that will fill in 0's throughout  		 * the intermediate portion of the previous end of the  		 * file and the new and of the file */  		rc = ecryptfs_write(&fake_ecryptfs_file, zero, -				    (new_length - 1), 1); -	} else { /* new_length < i_size_read(inode) */ -		/* We're chopping off all the pages down do the page -		 * in which new_length is located. Fill in the end of -		 * that page from (new_length & ~PAGE_CACHE_MASK) to +				    (ia->ia_size - 1), 1); +	} else { /* ia->ia_size < i_size_read(inode) */ +		/* We're chopping off all the pages down to the page +		 * in which ia->ia_size is located. Fill in the end of +		 * that page from (ia->ia_size & ~PAGE_CACHE_MASK) to  		 * PAGE_CACHE_SIZE with zeros. */  		size_t num_zeros = (PAGE_CACHE_SIZE -				    - (new_length & ~PAGE_CACHE_MASK)); +				    - (ia->ia_size & ~PAGE_CACHE_MASK));  		if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { -			rc = vmtruncate(inode, new_length); +			rc = vmtruncate(inode, ia->ia_size);  			if (rc)  				goto out_free; -			rc = vmtruncate(lower_dentry->d_inode, new_length); +			lower_ia->ia_size = ia->ia_size; +			lower_ia->ia_valid |= ATTR_SIZE;  			goto out_free;  		}  		if (num_zeros) { @@ -848,7 +866,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)  				goto out_free;  			}  			rc = ecryptfs_write(&fake_ecryptfs_file, zeros_virt, -					    new_length, num_zeros); +					    ia->ia_size, num_zeros);  			kfree(zeros_virt);  			if (rc) {  				printk(KERN_ERR "Error attempting to zero out " @@ -857,7 +875,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)  				goto out_free;  			}  		} -		vmtruncate(inode, new_length); +		vmtruncate(inode, ia->ia_size);  		rc = ecryptfs_write_inode_size_to_metadata(inode);  		if (rc) {  			printk(KERN_ERR	"Problem with " @@ -870,10 +888,12 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)  		lower_size_before_truncate =  		    upper_size_to_lower_size(crypt_stat, i_size);  		lower_size_after_truncate = -		    upper_size_to_lower_size(crypt_stat, new_length); -		if (lower_size_after_truncate < lower_size_before_truncate) -			vmtruncate(lower_dentry->d_inode, -				   lower_size_after_truncate); +		    upper_size_to_lower_size(crypt_stat, ia->ia_size); +		if (lower_size_after_truncate < lower_size_before_truncate) { +			lower_ia->ia_size = lower_size_after_truncate; +			lower_ia->ia_valid |= ATTR_SIZE; +		} else +			lower_ia->ia_valid &= ~ATTR_SIZE;  	}  out_free:  	if (ecryptfs_file_to_private(&fake_ecryptfs_file)) @@ -883,6 +903,33 @@ out:  	return rc;  } +/** + * ecryptfs_truncate + * @dentry: The ecryptfs layer dentry + * @new_length: The length to expand the file to + * + * Simple function that handles the truncation of an eCryptfs inode and + * its corresponding lower inode. + * + * Returns zero on success; non-zero otherwise + */ +int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) +{ +	struct iattr ia = { .ia_valid = ATTR_SIZE, .ia_size = new_length }; +	struct iattr lower_ia = { .ia_valid = 0 }; +	int rc; + +	rc = truncate_upper(dentry, &ia, &lower_ia); +	if (!rc && lower_ia.ia_valid & ATTR_SIZE) { +		struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); + +		mutex_lock(&lower_dentry->d_inode->i_mutex); +		rc = notify_change(lower_dentry, &lower_ia); +		mutex_unlock(&lower_dentry->d_inode->i_mutex); +	} +	return rc; +} +  static int  ecryptfs_permission(struct inode *inode, int mask)  { @@ -905,6 +952,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)  {  	int rc = 0;  	struct dentry *lower_dentry; +	struct iattr lower_ia;  	struct inode *inode;  	struct inode *lower_inode;  	struct ecryptfs_crypt_stat *crypt_stat; @@ -943,15 +991,11 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)  		}  	}  	mutex_unlock(&crypt_stat->cs_mutex); +	memcpy(&lower_ia, ia, sizeof(lower_ia)); +	if (ia->ia_valid & ATTR_FILE) +		lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file);  	if (ia->ia_valid & ATTR_SIZE) { -		ecryptfs_printk(KERN_DEBUG, -				"ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]\n", -				ia->ia_valid, ATTR_SIZE); -		rc = ecryptfs_truncate(dentry, ia->ia_size); -		/* ecryptfs_truncate handles resizing of the lower file */ -		ia->ia_valid &= ~ATTR_SIZE; -		ecryptfs_printk(KERN_DEBUG, "ia->ia_valid = [%x]\n", -				ia->ia_valid); +		rc = truncate_upper(dentry, ia, &lower_ia);  		if (rc < 0)  			goto out;  	} @@ -960,17 +1004,32 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)  	 * mode change is for clearing setuid/setgid bits. Allow lower fs  	 * to interpret this in its own way.  	 */ -	if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) -		ia->ia_valid &= ~ATTR_MODE; +	if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) +		lower_ia.ia_valid &= ~ATTR_MODE;  	mutex_lock(&lower_dentry->d_inode->i_mutex); -	rc = notify_change(lower_dentry, ia); +	rc = notify_change(lower_dentry, &lower_ia);  	mutex_unlock(&lower_dentry->d_inode->i_mutex);  out:  	fsstack_copy_attr_all(inode, lower_inode);  	return rc;  } +int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, +		     struct kstat *stat) +{ +	struct kstat lower_stat; +	int rc; + +	rc = vfs_getattr(ecryptfs_dentry_to_lower_mnt(dentry), +			 ecryptfs_dentry_to_lower(dentry), &lower_stat); +	if (!rc) { +		generic_fillattr(dentry->d_inode, stat); +		stat->blocks = lower_stat.blocks; +	} +	return rc; +} +  int  ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,  		  size_t size, int flags) @@ -1100,6 +1159,7 @@ const struct inode_operations ecryptfs_dir_iops = {  const struct inode_operations ecryptfs_main_iops = {  	.permission = ecryptfs_permission,  	.setattr = ecryptfs_setattr, +	.getattr = ecryptfs_getattr,  	.setxattr = ecryptfs_setxattr,  	.getxattr = ecryptfs_getxattr,  	.listxattr = ecryptfs_listxattr, diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 567bc4b9f70..ea2f92101df 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -585,8 +585,8 @@ out:   *                        with as much information as it can before needing   *                        the lower filesystem.   * ecryptfs_read_super(): this accesses the lower filesystem and uses - *                        ecryptfs_interpolate to perform most of the linking - * ecryptfs_interpolate(): links the lower filesystem into ecryptfs + *                        ecryptfs_interpose to perform most of the linking + * ecryptfs_interpose(): links the lower filesystem into ecryptfs (inode.c)   */  static int ecryptfs_get_sb(struct file_system_type *fs_type, int flags,  			const char *dev_name, void *raw_data, diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 9d7febde10a..09469971472 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -152,7 +152,7 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache)  #include <linux/hardirq.h>  #define ACPI_PREEMPTION_POINT() \  	do { \ -		if (!in_atomic_preempt_off()) \ +		if (!in_atomic_preempt_off() && !irqs_disabled()) \  			cond_resched(); \  	} while (0) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 36924255c0d..b926afe8c03 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -80,7 +80,7 @@ char * __acpi_map_table (unsigned long phys_addr, unsigned long size);  void __acpi_unmap_table(char *map, unsigned long size);  int early_acpi_boot_init(void);  int acpi_boot_init (void); -int acpi_boot_table_init (void); +void acpi_boot_table_init (void);  int acpi_mps_check (void);  int acpi_numa_init (void); @@ -321,9 +321,9 @@ static inline int acpi_boot_init(void)  	return 0;  } -static inline int acpi_boot_table_init(void) +static inline void acpi_boot_table_init(void)  { -	return 0; +	return;  }  static inline int acpi_mps_check(void) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 9b98173a818..5c8018977ef 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -938,6 +938,8 @@ extern void blk_queue_io_opt(struct request_queue *q, unsigned int opt);  extern void blk_set_default_limits(struct queue_limits *lim);  extern int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,  			    sector_t offset); +extern int bdev_stack_limits(struct queue_limits *t, struct block_device *bdev, +			    sector_t offset);  extern void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,  			      sector_t offset);  extern void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b); @@ -1148,8 +1150,11 @@ static inline int queue_discard_alignment(struct request_queue *q)  static inline int queue_sector_discard_alignment(struct request_queue *q,  						 sector_t sector)  { -	return ((sector << 9) - q->limits.discard_alignment) -		& (q->limits.discard_granularity - 1); +	struct queue_limits *lim = &q->limits; +	unsigned int alignment = (sector << 9) & (lim->discard_granularity - 1); + +	return (lim->discard_granularity + lim->discard_alignment - alignment) +		& (lim->discard_granularity - 1);  }  static inline unsigned int queue_discard_zeroes_data(struct request_queue *q) diff --git a/include/linux/drbd.h b/include/linux/drbd.h index e84f4733cb5..78962272338 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h @@ -53,7 +53,7 @@  extern const char *drbd_buildtag(void); -#define REL_VERSION "8.3.6" +#define REL_VERSION "8.3.7"  #define API_VERSION 88  #define PRO_VERSION_MIN 86  #define PRO_VERSION_MAX 91 diff --git a/include/linux/drbd_nl.h b/include/linux/drbd_nl.h index db5721ad50d..a4d82f89599 100644 --- a/include/linux/drbd_nl.h +++ b/include/linux/drbd_nl.h @@ -69,6 +69,7 @@ NL_PACKET(disconnect, 6, )  NL_PACKET(resize, 7,  	NL_INT64(		29,	T_MAY_IGNORE,	resize_size) +	NL_BIT(			68,	T_MAY_IGNORE,	resize_force)  )  NL_PACKET(syncer_conf, 8, diff --git a/include/linux/genhd.h b/include/linux/genhd.h index c6c0c41af35..9717081c75a 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -256,9 +256,9 @@ extern struct hd_struct *disk_map_sector_rcu(struct gendisk *disk,  #define part_stat_read(part, field)					\  ({									\  	typeof((part)->dkstats->field) res = 0;				\ -	int i;								\ -	for_each_possible_cpu(i)					\ -		res += per_cpu_ptr((part)->dkstats, i)->field;		\ +	unsigned int _cpu;						\ +	for_each_possible_cpu(_cpu)					\ +		res += per_cpu_ptr((part)->dkstats, _cpu)->field;	\  	res;								\  }) diff --git a/include/linux/i2c-pnx.h b/include/linux/i2c-pnx.h index 9eb07bbc652..a87124d4d53 100644 --- a/include/linux/i2c-pnx.h +++ b/include/linux/i2c-pnx.h @@ -12,9 +12,8 @@  #ifndef __I2C_PNX_H__  #define __I2C_PNX_H__ -#include <linux/pm.h> -  struct platform_device; +struct clk;  struct i2c_pnx_mif {  	int			ret;		/* Return value */ @@ -26,20 +25,18 @@ struct i2c_pnx_mif {  };  struct i2c_pnx_algo_data { -	u32			base; -	u32			ioaddr; -	int			irq; +	void __iomem		*ioaddr;  	struct i2c_pnx_mif	mif;  	int			last; +	struct clk		*clk; +	struct i2c_pnx_data	*i2c_pnx; +	struct i2c_adapter	adapter;  };  struct i2c_pnx_data { -	int (*suspend) (struct platform_device *pdev, pm_message_t state); -	int (*resume) (struct platform_device *pdev); -	u32 (*calculate_input_freq) (struct platform_device *pdev); -	int (*set_clock_run) (struct platform_device *pdev); -	int (*set_clock_stop) (struct platform_device *pdev); -	struct i2c_adapter *adapter; +	const char *name; +	u32 base; +	int irq;  };  #endif /* __I2C_PNX_H__ */ diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h index a6323599630..78ef023227d 100644 --- a/include/linux/iocontext.h +++ b/include/linux/iocontext.h @@ -4,32 +4,6 @@  #include <linux/radix-tree.h>  #include <linux/rcupdate.h> -/* - * This is the per-process anticipatory I/O scheduler state. - */ -struct as_io_context { -	spinlock_t lock; - -	void (*dtor)(struct as_io_context *aic); /* destructor */ -	void (*exit)(struct as_io_context *aic); /* called on task exit */ - -	unsigned long state; -	atomic_t nr_queued; /* queued reads & sync writes */ -	atomic_t nr_dispatched; /* number of requests gone to the drivers */ - -	/* IO History tracking */ -	/* Thinktime */ -	unsigned long last_end_request; -	unsigned long ttime_total; -	unsigned long ttime_samples; -	unsigned long ttime_mean; -	/* Layout pattern */ -	unsigned int seek_samples; -	sector_t last_request_pos; -	u64 seek_total; -	sector_t seek_mean; -}; -  struct cfq_queue;  struct cfq_io_context {  	void *key; @@ -78,7 +52,6 @@ struct io_context {  	unsigned long last_waited; /* Time last woken after wait for request */  	int nr_batch_requests;     /* Number of requests left in the batch */ -	struct as_io_context *aic;  	struct radix_tree_root radix_root;  	struct hlist_head cic_list;  	void *ioc_data; diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index c66b34f75ee..8fa71874113 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -814,9 +814,14 @@ extern int perf_event_overflow(struct perf_event *event, int nmi,   */  static inline int is_software_event(struct perf_event *event)  { -	return (event->attr.type != PERF_TYPE_RAW) && -		(event->attr.type != PERF_TYPE_HARDWARE) && -		(event->attr.type != PERF_TYPE_HW_CACHE); +	switch (event->attr.type) { +	case PERF_TYPE_SOFTWARE: +	case PERF_TYPE_TRACEPOINT: +	/* for now the breakpoint stuff also works as software event */ +	case PERF_TYPE_BREAKPOINT: +		return 1; +	} +	return 0;  }  extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX]; diff --git a/include/linux/topology.h b/include/linux/topology.h index 57e63579bfd..5b81156780b 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -99,7 +99,7 @@ int arch_update_cpu_topology(void);  				| 1*SD_WAKE_AFFINE			\  				| 1*SD_SHARE_CPUPOWER			\  				| 0*SD_POWERSAVINGS_BALANCE		\ -				| 0*SD_SHARE_PKG_RESOURCES		\ +				| 1*SD_SHARE_PKG_RESOURCES		\  				| 0*SD_SERIALIZE			\  				| 0*SD_PREFER_SIBLING			\  				,					\ diff --git a/include/linux/usb.h b/include/linux/usb.h index e101a2d04d7..d7ace1b80f0 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -192,6 +192,7 @@ struct usb_interface {  	unsigned needs_altsetting0:1;	/* switch to altsetting 0 is pending */  	unsigned needs_binding:1;	/* needs delayed unbind/rebind */  	unsigned reset_running:1; +	unsigned resetting_device:1;	/* true: bandwidth alloc after reset */  	struct device dev;		/* interface specific device info */  	struct device *usb_dev; diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 603c0d8b5df..d27746bd3a0 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -3268,6 +3268,9 @@ static void perf_event_task_output(struct perf_event *event,  static int perf_event_task_match(struct perf_event *event)  { +	if (event->state != PERF_EVENT_STATE_ACTIVE) +		return 0; +  	if (event->cpu != -1 && event->cpu != smp_processor_id())  		return 0; @@ -3377,6 +3380,9 @@ static void perf_event_comm_output(struct perf_event *event,  static int perf_event_comm_match(struct perf_event *event)  { +	if (event->state != PERF_EVENT_STATE_ACTIVE) +		return 0; +  	if (event->cpu != -1 && event->cpu != smp_processor_id())  		return 0; @@ -3494,6 +3500,9 @@ static void perf_event_mmap_output(struct perf_event *event,  static int perf_event_mmap_match(struct perf_event *event,  				   struct perf_mmap_event *mmap_event)  { +	if (event->state != PERF_EVENT_STATE_ACTIVE) +		return 0; +  	if (event->cpu != -1 && event->cpu != smp_processor_id())  		return 0; diff --git a/kernel/sched.c b/kernel/sched.c index c535cc4f642..4508fe7048b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5530,8 +5530,11 @@ need_resched_nonpreemptible:  	post_schedule(rq); -	if (unlikely(reacquire_kernel_lock(current) < 0)) +	if (unlikely(reacquire_kernel_lock(current) < 0)) { +		prev = rq->curr; +		switch_count = &prev->nivcsw;  		goto need_resched_nonpreemptible; +	}  	preempt_enable_no_resched();  	if (need_resched()) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 42ac3c9f66f..8fe7ee81c55 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1508,7 +1508,7 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag  			 * If there's an idle sibling in this domain, make that  			 * the wake_affine target instead of the current cpu.  			 */ -			if (tmp->flags & SD_PREFER_SIBLING) +			if (tmp->flags & SD_SHARE_PKG_RESOURCES)  				target = select_idle_sibling(p, tmp, target);  			if (target >= 0) { diff --git a/kernel/timer.c b/kernel/timer.c index 15533b79239..c61a7949387 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1198,6 +1198,7 @@ void update_process_times(int user_tick)  	run_local_timers();  	rcu_check_callbacks(cpu, user_tick);  	printk_tick(); +	perf_event_do_pending();  	scheduler_tick();  	run_posix_cpu_timers(p);  } @@ -1209,8 +1210,6 @@ static void run_timer_softirq(struct softirq_action *h)  {  	struct tvec_base *base = __get_cpu_var(tvec_bases); -	perf_event_do_pending(); -  	hrtimer_run_pending();  	if (time_after_eq(jiffies, base->timer_jiffies)) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 37e69295f25..d55d905463e 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -555,10 +555,8 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,  	}  	rcu_read_unlock(); -	if (nr) { -		BUG_ON(nr > atomic_read(&vmap_lazy_nr)); +	if (nr)  		atomic_sub(nr, &vmap_lazy_nr); -	}  	if (nr || force_flush)  		flush_tlb_kernel_range(*start, *end); diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 7ceb7416c31..93c67bf53d2 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -375,7 +375,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session,  	printf("%.102s\n", graph_dotted_line);  	printf(" %-34s |",  is_caller ? "Callsite": "Alloc Ptr"); -	printf(" Total_alloc/Per | Total_req/Per   | Hit   | Ping-pong | Frag\n"); +	printf(" Total_alloc/Per | Total_req/Per   | Hit      | Ping-pong | Frag\n");  	printf("%.102s\n", graph_dotted_line);  	next = rb_first(root); @@ -401,7 +401,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session,  			snprintf(buf, sizeof(buf), "%#Lx", addr);  		printf(" %-34s |", buf); -		printf(" %9llu/%-5lu | %9llu/%-5lu | %6lu | %8lu | %6.3f%%\n", +		printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %8lu | %6.3f%%\n",  		       (unsigned long long)data->bytes_alloc,  		       (unsigned long)data->bytes_alloc / data->hit,  		       (unsigned long long)data->bytes_req, @@ -784,7 +784,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __used)  			setup_sorting(&alloc_sort, default_sort_order);  		return __cmd_kmem(); -	} +	} else +		usage_with_options(kmem_usage, kmem_options);  	return 0;  } diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index a589a43112d..3f8bbcfb1e9 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -280,7 +280,7 @@ static u64 cpus_pstate_state[MAX_CPUS];  static int process_comm_event(event_t *event, struct perf_session *session __used)  { -	pid_set_comm(event->comm.pid, event->comm.comm); +	pid_set_comm(event->comm.tid, event->comm.comm);  	return 0;  }  |