diff options
222 files changed, 2121 insertions, 1457 deletions
@@ -1,7 +1,7 @@  VERSION = 3  PATCHLEVEL = 0  SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2  NAME = Sneaky Weasel  # *DOCUMENTATION* diff --git a/arch/arm/mach-imx/mach-apf9328.c b/arch/arm/mach-imx/mach-apf9328.c index 15e45c84e37..59d2a3b137d 100644 --- a/arch/arm/mach-imx/mach-apf9328.c +++ b/arch/arm/mach-imx/mach-apf9328.c @@ -115,6 +115,8 @@ static struct platform_device *devices[] __initdata = {  static void __init apf9328_init(void)  { +	imx1_soc_init(); +  	mxc_gpio_setup_multiple_pins(apf9328_pins,  			ARRAY_SIZE(apf9328_pins),  			"APF9328"); diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c index ffb40ff619b..ede2710f8b7 100644 --- a/arch/arm/mach-imx/mach-armadillo5x0.c +++ b/arch/arm/mach-imx/mach-armadillo5x0.c @@ -490,6 +490,8 @@ static struct platform_device *devices[] __initdata = {   */  static void __init armadillo5x0_init(void)  { +	imx31_soc_init(); +  	mxc_iomux_setup_multiple_pins(armadillo5x0_pins,  			ARRAY_SIZE(armadillo5x0_pins), "armadillo5x0"); diff --git a/arch/arm/mach-imx/mach-bug.c b/arch/arm/mach-imx/mach-bug.c index 42e4f078a19..f49470553bd 100644 --- a/arch/arm/mach-imx/mach-bug.c +++ b/arch/arm/mach-imx/mach-bug.c @@ -42,6 +42,8 @@ static const unsigned int bug_pins[] __initconst = {  static void __init bug_board_init(void)  { +	imx31_soc_init(); +  	mxc_iomux_setup_multiple_pins(bug_pins,  				      ARRAY_SIZE(bug_pins), "uart-4");  	imx31_add_imx_uart4(&uart_pdata); diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c index 46a2e41d43d..87887ac5806 100644 --- a/arch/arm/mach-imx/mach-cpuimx27.c +++ b/arch/arm/mach-imx/mach-cpuimx27.c @@ -250,6 +250,8 @@ __setup("otg_mode=", eukrea_cpuimx27_otg_mode);  static void __init eukrea_cpuimx27_init(void)  { +	imx27_soc_init(); +  	mxc_gpio_setup_multiple_pins(eukrea_cpuimx27_pins,  		ARRAY_SIZE(eukrea_cpuimx27_pins), "CPUIMX27"); diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c index 3f8ef825fa6..f39a478ba1a 100644 --- a/arch/arm/mach-imx/mach-cpuimx35.c +++ b/arch/arm/mach-imx/mach-cpuimx35.c @@ -156,6 +156,8 @@ __setup("otg_mode=", eukrea_cpuimx35_otg_mode);   */  static void __init eukrea_cpuimx35_init(void)  { +	imx35_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx35_pads,  			ARRAY_SIZE(eukrea_cpuimx35_pads)); diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c index 148cff2819b..da36da52969 100644 --- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c +++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c @@ -125,6 +125,8 @@ __setup("otg_mode=", eukrea_cpuimx25_otg_mode);  static void __init eukrea_cpuimx25_init(void)  { +	imx25_soc_init(); +  	if (mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx25_pads,  			ARRAY_SIZE(eukrea_cpuimx25_pads)))  		printk(KERN_ERR "error setting cpuimx25 pads !\n"); diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c index 7ae43b1ec51..c6269d60ddb 100644 --- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c +++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c @@ -231,6 +231,8 @@ static void __init visstrim_m10_board_init(void)  {  	int ret; +	imx27_soc_init(); +  	ret = mxc_gpio_setup_multiple_pins(visstrim_m10_pins,  			ARRAY_SIZE(visstrim_m10_pins), "VISSTRIM_M10");  	if (ret) diff --git a/arch/arm/mach-imx/mach-imx27ipcam.c b/arch/arm/mach-imx/mach-imx27ipcam.c index 9be6cd6fbf8..272f793e924 100644 --- a/arch/arm/mach-imx/mach-imx27ipcam.c +++ b/arch/arm/mach-imx/mach-imx27ipcam.c @@ -50,6 +50,8 @@ static const int mx27ipcam_pins[] __initconst = {  static void __init mx27ipcam_init(void)  { +	imx27_soc_init(); +  	mxc_gpio_setup_multiple_pins(mx27ipcam_pins, ARRAY_SIZE(mx27ipcam_pins),  		"mx27ipcam"); diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c index 841140516ed..d81a769fe89 100644 --- a/arch/arm/mach-imx/mach-imx27lite.c +++ b/arch/arm/mach-imx/mach-imx27lite.c @@ -59,6 +59,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {  static void __init mx27lite_init(void)  { +	imx27_soc_init(); +  	mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins),  		"imx27lite");  	imx27_add_imx_uart0(&uart_pdata); diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c index 1ecae20cf4e..e472a1d8805 100644 --- a/arch/arm/mach-imx/mach-kzm_arm11_01.c +++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c @@ -223,6 +223,8 @@ static int kzm_pins[] __initdata = {   */  static void __init kzm_board_init(void)  { +	imx31_soc_init(); +  	mxc_iomux_setup_multiple_pins(kzm_pins,  				      ARRAY_SIZE(kzm_pins), "kzm");  	kzm_init_ext_uart(); diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c index 38ec5cbbda9..5cd8bee4696 100644 --- a/arch/arm/mach-imx/mach-mx1ads.c +++ b/arch/arm/mach-imx/mach-mx1ads.c @@ -115,6 +115,8 @@ static struct i2c_board_info mx1ads_i2c_devices[] = {   */  static void __init mx1ads_init(void)  { +	imx1_soc_init(); +  	mxc_gpio_setup_multiple_pins(mx1ads_pins,  		ARRAY_SIZE(mx1ads_pins), "mx1ads"); diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c index 74ac88978dd..d389ecf9b5a 100644 --- a/arch/arm/mach-imx/mach-mx21ads.c +++ b/arch/arm/mach-imx/mach-mx21ads.c @@ -279,6 +279,8 @@ static struct platform_device *platform_devices[] __initdata = {  static void __init mx21ads_board_init(void)  { +	imx21_soc_init(); +  	mxc_gpio_setup_multiple_pins(mx21ads_pins, ARRAY_SIZE(mx21ads_pins),  			"mx21ads"); diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c index 58ea3fdf091..01534bb6130 100644 --- a/arch/arm/mach-imx/mach-mx25_3ds.c +++ b/arch/arm/mach-imx/mach-mx25_3ds.c @@ -219,6 +219,8 @@ static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {  static void __init mx25pdk_init(void)  { +	imx25_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,  			ARRAY_SIZE(mx25pdk_pads)); diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c index 6e1accf93f8..117ce0a50f4 100644 --- a/arch/arm/mach-imx/mach-mx27_3ds.c +++ b/arch/arm/mach-imx/mach-mx27_3ds.c @@ -267,6 +267,8 @@ static const struct imxi2c_platform_data mx27_3ds_i2c0_data __initconst = {  static void __init mx27pdk_init(void)  { +	imx27_soc_init(); +  	mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),  		"mx27pdk");  	mx27_3ds_sdhc1_enable_level_translator(); diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c index 1db79506f5e..fc26ed71b9e 100644 --- a/arch/arm/mach-imx/mach-mx27ads.c +++ b/arch/arm/mach-imx/mach-mx27ads.c @@ -288,6 +288,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {  static void __init mx27ads_board_init(void)  { +	imx27_soc_init(); +  	mxc_gpio_setup_multiple_pins(mx27ads_pins, ARRAY_SIZE(mx27ads_pins),  			"mx27ads"); diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c index 9b982449cb5..ab2a6268b50 100644 --- a/arch/arm/mach-imx/mach-mx31_3ds.c +++ b/arch/arm/mach-imx/mach-mx31_3ds.c @@ -689,6 +689,8 @@ static void __init mx31_3ds_init(void)  {  	int ret; +	imx31_soc_init(); +  	mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins),  				      "mx31_3ds"); diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c index f4dee025463..0ce49478a47 100644 --- a/arch/arm/mach-imx/mach-mx31ads.c +++ b/arch/arm/mach-imx/mach-mx31ads.c @@ -516,6 +516,8 @@ static void __init mx31ads_init_irq(void)  static void __init mx31ads_init(void)  { +	imx31_soc_init(); +  	mxc_init_extuart();  	mxc_init_imx_uart();  	mxc_init_i2c(); diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c index 410e676ae08..750368ddf0f 100644 --- a/arch/arm/mach-imx/mach-mx31lilly.c +++ b/arch/arm/mach-imx/mach-mx31lilly.c @@ -243,6 +243,8 @@ core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444);  static void __init mx31lilly_board_init(void)  { +	imx31_soc_init(); +  	switch (mx31lilly_baseboard) {  	case MX31LILLY_NOBOARD:  		break; diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c index ac9b4cad320..4b47fd9fdd8 100644 --- a/arch/arm/mach-imx/mach-mx31lite.c +++ b/arch/arm/mach-imx/mach-mx31lite.c @@ -230,6 +230,8 @@ static void __init mx31lite_init(void)  {  	int ret; +	imx31_soc_init(); +  	switch (mx31lite_baseboard) {  	case MX31LITE_NOBOARD:  		break; diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c index eaa51e49ca9..a52fd36e2b5 100644 --- a/arch/arm/mach-imx/mach-mx31moboard.c +++ b/arch/arm/mach-imx/mach-mx31moboard.c @@ -507,6 +507,8 @@ core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);   */  static void __init mx31moboard_init(void)  { +	imx31_soc_init(); +  	mxc_iomux_setup_multiple_pins(moboard_pins, ARRAY_SIZE(moboard_pins),  		"moboard"); diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c index 882880ac1bb..48b3c6fd5cf 100644 --- a/arch/arm/mach-imx/mach-mx35_3ds.c +++ b/arch/arm/mach-imx/mach-mx35_3ds.c @@ -179,6 +179,8 @@ static const struct imxi2c_platform_data mx35_3ds_i2c0_data __initconst = {   */  static void __init mx35_3ds_init(void)  { +	imx35_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));  	imx35_add_fec(NULL); diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c index 2774541511e..c85876fed66 100644 --- a/arch/arm/mach-imx/mach-mxt_td60.c +++ b/arch/arm/mach-imx/mach-mxt_td60.c @@ -233,6 +233,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {  static void __init mxt_td60_board_init(void)  { +	imx27_soc_init(); +  	mxc_gpio_setup_multiple_pins(mxt_td60_pins, ARRAY_SIZE(mxt_td60_pins),  			"MXT_TD60"); diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c index bbddc5a11c4..71083aa1603 100644 --- a/arch/arm/mach-imx/mach-pca100.c +++ b/arch/arm/mach-imx/mach-pca100.c @@ -357,6 +357,8 @@ static void __init pca100_init(void)  {  	int ret; +	imx27_soc_init(); +  	/* SSI unit */  	mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,  				  MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */ diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c index 89c213b8129..f45b7cd72c8 100644 --- a/arch/arm/mach-imx/mach-pcm037.c +++ b/arch/arm/mach-imx/mach-pcm037.c @@ -576,6 +576,8 @@ static void __init pcm037_init(void)  {  	int ret; +	imx31_soc_init(); +  	mxc_iomux_set_gpr(MUX_PGP_UH2, 1);  	mxc_iomux_setup_multiple_pins(pcm037_pins, ARRAY_SIZE(pcm037_pins), diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c index 853bb871c7e..2d6a64bbac4 100644 --- a/arch/arm/mach-imx/mach-pcm038.c +++ b/arch/arm/mach-imx/mach-pcm038.c @@ -295,6 +295,8 @@ static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {  static void __init pcm038_init(void)  { +	imx27_soc_init(); +  	mxc_gpio_setup_multiple_pins(pcm038_pins, ARRAY_SIZE(pcm038_pins),  			"PCM038"); diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c index 026441628df..163cc318caf 100644 --- a/arch/arm/mach-imx/mach-pcm043.c +++ b/arch/arm/mach-imx/mach-pcm043.c @@ -356,6 +356,8 @@ static struct esdhc_platform_data sd1_pdata = {   */  static void __init pcm043_init(void)  { +	imx35_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads));  	mxc_audmux_v2_configure_port(3, diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c index c1632871593..3626f486498 100644 --- a/arch/arm/mach-imx/mach-qong.c +++ b/arch/arm/mach-imx/mach-qong.c @@ -244,6 +244,8 @@ static void __init qong_init_fpga(void)   */  static void __init qong_init(void)  { +	imx31_soc_init(); +  	mxc_init_imx_uart();  	qong_init_nor_mtd();  	qong_init_fpga(); diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c index dcaee043628..82805260e19 100644 --- a/arch/arm/mach-imx/mach-scb9328.c +++ b/arch/arm/mach-imx/mach-scb9328.c @@ -129,6 +129,8 @@ static struct platform_device *devices[] __initdata = {   */  static void __init scb9328_init(void)  { +	imx1_soc_init(); +  	imx1_add_imx_uart0(&uart_pdata);  	printk(KERN_INFO"Scb9328: Adding devices\n"); diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c index d74e3473d23..7d8e012a633 100644 --- a/arch/arm/mach-imx/mach-vpr200.c +++ b/arch/arm/mach-imx/mach-vpr200.c @@ -267,6 +267,8 @@ static struct platform_device *devices[] __initdata = {   */  static void __init vpr200_board_init(void)  { +	imx35_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(vpr200_pads, ARRAY_SIZE(vpr200_pads));  	imx35_add_fec(NULL); diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c index 2e482ba5a0e..b486595701b 100644 --- a/arch/arm/mach-imx/mm-imx1.c +++ b/arch/arm/mach-imx/mm-imx1.c @@ -23,7 +23,6 @@  #include <mach/common.h>  #include <mach/hardware.h> -#include <mach/gpio.h>  #include <mach/irqs.h>  #include <mach/iomux-v1.h> @@ -44,15 +43,15 @@ void __init imx1_init_early(void)  			MX1_NUM_GPIO_PORT);  } -static struct mxc_gpio_port imx1_gpio_ports[] = { -	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 0, 1, MX1_GPIO_INT_PORTA), -	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 1, 2, MX1_GPIO_INT_PORTB), -	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 2, 3, MX1_GPIO_INT_PORTC), -	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 3, 4, MX1_GPIO_INT_PORTD), -}; -  void __init mx1_init_irq(void)  {  	mxc_init_irq(MX1_IO_ADDRESS(MX1_AVIC_BASE_ADDR)); -	mxc_gpio_init(imx1_gpio_ports,	ARRAY_SIZE(imx1_gpio_ports)); +} + +void __init imx1_soc_init(void) +{ +	mxc_register_gpio(0, MX1_GPIO1_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTA, 0); +	mxc_register_gpio(1, MX1_GPIO2_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTB, 0); +	mxc_register_gpio(2, MX1_GPIO3_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTC, 0); +	mxc_register_gpio(3, MX1_GPIO4_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTD, 0);  } diff --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c index 7a0c500ac2c..f0fb8bcce6f 100644 --- a/arch/arm/mach-imx/mm-imx21.c +++ b/arch/arm/mach-imx/mm-imx21.c @@ -24,7 +24,6 @@  #include <mach/common.h>  #include <asm/pgtable.h>  #include <asm/mach/map.h> -#include <mach/gpio.h>  #include <mach/irqs.h>  #include <mach/iomux-v1.h> @@ -70,17 +69,17 @@ void __init imx21_init_early(void)  			MX21_NUM_GPIO_PORT);  } -static struct mxc_gpio_port imx21_gpio_ports[] = { -	DEFINE_IMX_GPIO_PORT_IRQ(MX21, 0, 1, MX21_INT_GPIO), -	DEFINE_IMX_GPIO_PORT(MX21, 1, 2), -	DEFINE_IMX_GPIO_PORT(MX21, 2, 3), -	DEFINE_IMX_GPIO_PORT(MX21, 3, 4), -	DEFINE_IMX_GPIO_PORT(MX21, 4, 5), -	DEFINE_IMX_GPIO_PORT(MX21, 5, 6), -}; -  void __init mx21_init_irq(void)  {  	mxc_init_irq(MX21_IO_ADDRESS(MX21_AVIC_BASE_ADDR)); -	mxc_gpio_init(imx21_gpio_ports,	ARRAY_SIZE(imx21_gpio_ports)); +} + +void __init imx21_soc_init(void) +{ +	mxc_register_gpio(0, MX21_GPIO1_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); +	mxc_register_gpio(1, MX21_GPIO2_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); +	mxc_register_gpio(2, MX21_GPIO3_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); +	mxc_register_gpio(3, MX21_GPIO4_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); +	mxc_register_gpio(4, MX21_GPIO5_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0); +	mxc_register_gpio(5, MX21_GPIO6_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0);  } diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c index 02f7b5c7fa8..1b6d583f750 100644 --- a/arch/arm/mach-imx/mm-imx25.c +++ b/arch/arm/mach-imx/mm-imx25.c @@ -27,7 +27,6 @@  #include <mach/hardware.h>  #include <mach/mx25.h>  #include <mach/iomux-v3.h> -#include <mach/gpio.h>  #include <mach/irqs.h>  /* @@ -57,16 +56,15 @@ void __init imx25_init_early(void)  	mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR));  } -static struct mxc_gpio_port imx25_gpio_ports[] = { -	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 0, 1, MX25_INT_GPIO1), -	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 1, 2, MX25_INT_GPIO2), -	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 2, 3, MX25_INT_GPIO3), -	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 3, 4, MX25_INT_GPIO4), -}; -  void __init mx25_init_irq(void)  {  	mxc_init_irq(MX25_IO_ADDRESS(MX25_AVIC_BASE_ADDR)); -	mxc_gpio_init(imx25_gpio_ports,	ARRAY_SIZE(imx25_gpio_ports));  } +void __init imx25_soc_init(void) +{ +	mxc_register_gpio(0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0); +	mxc_register_gpio(1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0); +	mxc_register_gpio(2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0); +	mxc_register_gpio(3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0); +} diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c index a6761a39f08..d3700cec8ec 100644 --- a/arch/arm/mach-imx/mm-imx27.c +++ b/arch/arm/mach-imx/mm-imx27.c @@ -24,7 +24,6 @@  #include <mach/common.h>  #include <asm/pgtable.h>  #include <asm/mach/map.h> -#include <mach/gpio.h>  #include <mach/irqs.h>  #include <mach/iomux-v1.h> @@ -70,17 +69,17 @@ void __init imx27_init_early(void)  			MX27_NUM_GPIO_PORT);  } -static struct mxc_gpio_port imx27_gpio_ports[] = { -	DEFINE_IMX_GPIO_PORT_IRQ(MX27, 0, 1, MX27_INT_GPIO), -	DEFINE_IMX_GPIO_PORT(MX27, 1, 2), -	DEFINE_IMX_GPIO_PORT(MX27, 2, 3), -	DEFINE_IMX_GPIO_PORT(MX27, 3, 4), -	DEFINE_IMX_GPIO_PORT(MX27, 4, 5), -	DEFINE_IMX_GPIO_PORT(MX27, 5, 6), -}; -  void __init mx27_init_irq(void)  {  	mxc_init_irq(MX27_IO_ADDRESS(MX27_AVIC_BASE_ADDR)); -	mxc_gpio_init(imx27_gpio_ports,	ARRAY_SIZE(imx27_gpio_ports)); +} + +void __init imx27_soc_init(void) +{ +	mxc_register_gpio(0, MX27_GPIO1_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); +	mxc_register_gpio(1, MX27_GPIO2_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); +	mxc_register_gpio(2, MX27_GPIO3_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); +	mxc_register_gpio(3, MX27_GPIO4_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); +	mxc_register_gpio(4, MX27_GPIO5_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0); +	mxc_register_gpio(5, MX27_GPIO6_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0);  } diff --git a/arch/arm/mach-imx/mm-imx31.c b/arch/arm/mach-imx/mm-imx31.c index 86b9b45864d..cb16ac66177 100644 --- a/arch/arm/mach-imx/mm-imx31.c +++ b/arch/arm/mach-imx/mm-imx31.c @@ -26,7 +26,6 @@  #include <mach/common.h>  #include <mach/hardware.h>  #include <mach/iomux-v3.h> -#include <mach/gpio.h>  #include <mach/irqs.h>  static struct map_desc mx31_io_desc[] __initdata = { @@ -53,14 +52,14 @@ void __init imx31_init_early(void)  	mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));  } -static struct mxc_gpio_port imx31_gpio_ports[] = { -	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 0, 1, MX31_INT_GPIO1), -	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 1, 2, MX31_INT_GPIO2), -	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 2, 3, MX31_INT_GPIO3), -}; -  void __init mx31_init_irq(void)  {  	mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR)); -	mxc_gpio_init(imx31_gpio_ports,	ARRAY_SIZE(imx31_gpio_ports)); +} + +void __init imx31_soc_init(void) +{ +	mxc_register_gpio(0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0); +	mxc_register_gpio(1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0); +	mxc_register_gpio(2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);  } diff --git a/arch/arm/mach-imx/mm-imx35.c b/arch/arm/mach-imx/mm-imx35.c index c880e6d1ae5..648bfca0163 100644 --- a/arch/arm/mach-imx/mm-imx35.c +++ b/arch/arm/mach-imx/mm-imx35.c @@ -27,7 +27,6 @@  #include <mach/common.h>  #include <mach/hardware.h>  #include <mach/iomux-v3.h> -#include <mach/gpio.h>  #include <mach/irqs.h>  static struct map_desc mx35_io_desc[] __initdata = { @@ -50,14 +49,14 @@ void __init imx35_init_early(void)  	mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));  } -static struct mxc_gpio_port imx35_gpio_ports[] = { -	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 0, 1, MX35_INT_GPIO1), -	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 1, 2, MX35_INT_GPIO2), -	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 2, 3, MX35_INT_GPIO3), -}; -  void __init mx35_init_irq(void)  {  	mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR)); -	mxc_gpio_init(imx35_gpio_ports,	ARRAY_SIZE(imx35_gpio_ports)); +} + +void __init imx35_soc_init(void) +{ +	mxc_register_gpio(0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0); +	mxc_register_gpio(1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0); +	mxc_register_gpio(2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);  } diff --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c index 4efa02ee163..add0d42de7a 100644 --- a/arch/arm/mach-mx5/board-cpuimx51.c +++ b/arch/arm/mach-mx5/board-cpuimx51.c @@ -245,6 +245,8 @@ __setup("otg_mode=", eukrea_cpuimx51_otg_mode);   */  static void __init eukrea_cpuimx51_init(void)  { +	imx51_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,  					ARRAY_SIZE(eukrea_cpuimx51_pads)); diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c index 5ef25a59614..ff096d58729 100644 --- a/arch/arm/mach-mx5/board-cpuimx51sd.c +++ b/arch/arm/mach-mx5/board-cpuimx51sd.c @@ -264,6 +264,8 @@ static struct platform_device *platform_devices[] __initdata = {  static void __init eukrea_cpuimx51sd_init(void)  { +	imx51_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,  					ARRAY_SIZE(eukrea_cpuimx51sd_pads)); diff --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c index 11210e1ae42..7de25c6712e 100644 --- a/arch/arm/mach-mx5/board-mx50_rdp.c +++ b/arch/arm/mach-mx5/board-mx50_rdp.c @@ -192,6 +192,8 @@ static const struct imxi2c_platform_data i2c_data __initconst = {   */  static void __init mx50_rdp_board_init(void)  { +	imx50_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads,  					ARRAY_SIZE(mx50_rdp_pads)); diff --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c index 63dfbeafbc1..3112d15feeb 100644 --- a/arch/arm/mach-mx5/board-mx51_3ds.c +++ b/arch/arm/mach-mx5/board-mx51_3ds.c @@ -135,6 +135,8 @@ static struct spi_board_info mx51_3ds_spi_nor_device[] = {   */  static void __init mx51_3ds_init(void)  { +	imx51_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,  					ARRAY_SIZE(mx51_3ds_pads)); diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c index c7b3fabf50f..6021dd00ec7 100644 --- a/arch/arm/mach-mx5/board-mx51_babbage.c +++ b/arch/arm/mach-mx5/board-mx51_babbage.c @@ -340,6 +340,8 @@ static void __init mx51_babbage_init(void)  	iomux_v3_cfg_t power_key = _MX51_PAD_EIM_A27__GPIO2_21 |  		MUX_PAD_CTRL(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP); +	imx51_soc_init(); +  #if defined(CONFIG_CPU_FREQ_IMX)  	get_cpu_op = mx51_get_cpu_op;  #endif diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c index 6e362315291..3be603b9075 100644 --- a/arch/arm/mach-mx5/board-mx51_efikamx.c +++ b/arch/arm/mach-mx5/board-mx51_efikamx.c @@ -236,6 +236,8 @@ late_initcall(mx51_efikamx_power_init);  static void __init mx51_efikamx_init(void)  { +	imx51_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,  					ARRAY_SIZE(mx51efikamx_pads));  	efika_board_common_init(); diff --git a/arch/arm/mach-mx5/board-mx51_efikasb.c b/arch/arm/mach-mx5/board-mx51_efikasb.c index 474fc6e4c6d..4b2e522de0f 100644 --- a/arch/arm/mach-mx5/board-mx51_efikasb.c +++ b/arch/arm/mach-mx5/board-mx51_efikasb.c @@ -248,6 +248,8 @@ static void __init mx51_efikasb_board_id(void)  static void __init efikasb_board_init(void)  { +	imx51_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,  					ARRAY_SIZE(mx51efikasb_pads));  	efika_board_common_init(); diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c index f87d571882c..0d9218a6e2d 100644 --- a/arch/arm/mach-mx5/board-mx53_evk.c +++ b/arch/arm/mach-mx5/board-mx53_evk.c @@ -117,6 +117,8 @@ static const struct spi_imx_master mx53_evk_spi_data __initconst = {  static void __init mx53_evk_board_init(void)  { +	imx53_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,  					ARRAY_SIZE(mx53_evk_pads));  	mx53_evk_init_uart(); diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c index 1b947e8c9c0..359c3e248ad 100644 --- a/arch/arm/mach-mx5/board-mx53_loco.c +++ b/arch/arm/mach-mx5/board-mx53_loco.c @@ -227,6 +227,8 @@ static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {  static void __init mx53_loco_board_init(void)  { +	imx53_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,  					ARRAY_SIZE(mx53_loco_pads));  	imx53_add_imx_uart(0, NULL); diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c index 817c08938f5..bc02894eafe 100644 --- a/arch/arm/mach-mx5/board-mx53_smd.c +++ b/arch/arm/mach-mx5/board-mx53_smd.c @@ -113,6 +113,8 @@ static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {  static void __init mx53_smd_board_init(void)  { +	imx53_soc_init(); +  	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,  					ARRAY_SIZE(mx53_smd_pads));  	mx53_smd_init_uart(); diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c index 153ada53e57..371ca8c8414 100644 --- a/arch/arm/mach-mx5/devices.c +++ b/arch/arm/mach-mx5/devices.c @@ -12,7 +12,6 @@  #include <linux/platform_device.h>  #include <linux/dma-mapping.h> -#include <linux/gpio.h>  #include <mach/hardware.h>  #include <mach/imx-uart.h>  #include <mach/irqs.h> @@ -119,66 +118,3 @@ struct platform_device mxc_usbh2_device = {  		.coherent_dma_mask = DMA_BIT_MASK(32),  	},  }; - -static struct mxc_gpio_port mxc_gpio_ports[] = { -	{ -		.chip.label = "gpio-0", -		.base = MX51_IO_ADDRESS(MX51_GPIO1_BASE_ADDR), -		.irq = MX51_MXC_INT_GPIO1_LOW, -		.irq_high = MX51_MXC_INT_GPIO1_HIGH, -		.virtual_irq_start = MXC_GPIO_IRQ_START -	}, -	{ -		.chip.label = "gpio-1", -		.base = MX51_IO_ADDRESS(MX51_GPIO2_BASE_ADDR), -		.irq = MX51_MXC_INT_GPIO2_LOW, -		.irq_high = MX51_MXC_INT_GPIO2_HIGH, -		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 1 -	}, -	{ -		.chip.label = "gpio-2", -		.base = MX51_IO_ADDRESS(MX51_GPIO3_BASE_ADDR), -		.irq = MX51_MXC_INT_GPIO3_LOW, -		.irq_high = MX51_MXC_INT_GPIO3_HIGH, -		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 2 -	}, -	{ -		.chip.label = "gpio-3", -		.base = MX51_IO_ADDRESS(MX51_GPIO4_BASE_ADDR), -		.irq = MX51_MXC_INT_GPIO4_LOW, -		.irq_high = MX51_MXC_INT_GPIO4_HIGH, -		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 3 -	}, -	{ -		.chip.label = "gpio-4", -		.base = MX53_IO_ADDRESS(MX53_GPIO5_BASE_ADDR), -		.irq = MX53_INT_GPIO5_LOW, -		.irq_high = MX53_INT_GPIO5_HIGH, -		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 4 -	}, -	{ -		.chip.label = "gpio-5", -		.base = MX53_IO_ADDRESS(MX53_GPIO6_BASE_ADDR), -		.irq = MX53_INT_GPIO6_LOW, -		.irq_high = MX53_INT_GPIO6_HIGH, -		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 5 -	}, -	{ -		.chip.label = "gpio-6", -		.base = MX53_IO_ADDRESS(MX53_GPIO7_BASE_ADDR), -		.irq = MX53_INT_GPIO7_LOW, -		.irq_high = MX53_INT_GPIO7_HIGH, -		.virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 6 -	}, -}; - -int __init imx51_register_gpios(void) -{ -	return mxc_gpio_init(mxc_gpio_ports, 4); -} - -int __init imx53_register_gpios(void) -{ -	return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports)); -} - diff --git a/arch/arm/mach-mx5/mm-mx50.c b/arch/arm/mach-mx5/mm-mx50.c index b9c363b514a..28c3f60f734 100644 --- a/arch/arm/mach-mx5/mm-mx50.c +++ b/arch/arm/mach-mx5/mm-mx50.c @@ -26,7 +26,6 @@  #include <mach/hardware.h>  #include <mach/common.h>  #include <mach/iomux-v3.h> -#include <mach/gpio.h>  #include <mach/irqs.h>  /* @@ -56,17 +55,17 @@ void __init imx50_init_early(void)  	mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));  } -static struct mxc_gpio_port imx50_gpio_ports[] = { -	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 0, 1, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH), -	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 1, 2, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH), -	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 2, 3, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH), -	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 3, 4, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH), -	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 4, 5, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH), -	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 5, 6, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH), -}; -  void __init mx50_init_irq(void)  {  	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR)); -	mxc_gpio_init(imx50_gpio_ports,	ARRAY_SIZE(imx50_gpio_ports)); +} + +void __init imx50_soc_init(void) +{ +	mxc_register_gpio(0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH); +	mxc_register_gpio(1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH); +	mxc_register_gpio(2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH); +	mxc_register_gpio(3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH); +	mxc_register_gpio(4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH); +	mxc_register_gpio(5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);  } diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c index ff557301b42..800bb8b2108 100644 --- a/arch/arm/mach-mx5/mm.c +++ b/arch/arm/mach-mx5/mm.c @@ -69,8 +69,6 @@ void __init imx53_init_early(void)  	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));  } -int imx51_register_gpios(void); -  void __init mx51_init_irq(void)  {  	unsigned long tzic_addr; @@ -86,11 +84,8 @@ void __init mx51_init_irq(void)  		panic("unable to map TZIC interrupt controller\n");  	tzic_init_irq(tzic_virt); -	imx51_register_gpios();  } -int imx53_register_gpios(void); -  void __init mx53_init_irq(void)  {  	unsigned long tzic_addr; @@ -103,5 +98,23 @@ void __init mx53_init_irq(void)  		panic("unable to map TZIC interrupt controller\n");  	tzic_init_irq(tzic_virt); -	imx53_register_gpios(); +} + +void __init imx51_soc_init(void) +{ +	mxc_register_gpio(0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH); +	mxc_register_gpio(1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH); +	mxc_register_gpio(2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH); +	mxc_register_gpio(3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH); +} + +void __init imx53_soc_init(void) +{ +	mxc_register_gpio(0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH); +	mxc_register_gpio(1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH); +	mxc_register_gpio(2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH); +	mxc_register_gpio(3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH); +	mxc_register_gpio(4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH); +	mxc_register_gpio(5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH); +	mxc_register_gpio(6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);  } diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile index 58e892376bf..6c38262a3aa 100644 --- a/arch/arm/mach-mxs/Makefile +++ b/arch/arm/mach-mxs/Makefile @@ -1,5 +1,5 @@  # Common support -obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o +obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o  obj-$(CONFIG_MXS_OCOTP) += ocotp.o  obj-$(CONFIG_PM) += pm.o diff --git a/arch/arm/mach-mxs/devices.c b/arch/arm/mach-mxs/devices.c index cfdb6b28470..fe3e847930c 100644 --- a/arch/arm/mach-mxs/devices.c +++ b/arch/arm/mach-mxs/devices.c @@ -88,3 +88,14 @@ int __init mxs_add_amba_device(const struct amba_device *dev)  	return amba_device_register(adev, &iomem_resource);  } + +struct device mxs_apbh_bus = { +	.init_name	= "mxs_apbh", +	.parent         = &platform_bus, +}; + +static int __init mxs_device_init(void) +{ +	return device_register(&mxs_apbh_bus); +} +core_initcall(mxs_device_init); diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile index 324f2824d38..351915c683f 100644 --- a/arch/arm/mach-mxs/devices/Makefile +++ b/arch/arm/mach-mxs/devices/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o  obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o  obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o  obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o +obj-y += platform-gpio-mxs.o  obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o diff --git a/arch/arm/mach-mxs/devices/platform-gpio-mxs.c b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c new file mode 100644 index 00000000000..ed0885e414e --- /dev/null +++ b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c @@ -0,0 +1,53 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + */ +#include <linux/compiler.h> +#include <linux/err.h> +#include <linux/init.h> + +#include <mach/mx23.h> +#include <mach/mx28.h> +#include <mach/devices-common.h> + +struct platform_device *__init mxs_add_gpio( +	int id, resource_size_t iobase, int irq) +{ +	struct resource res[] = { +		{ +			.start = iobase, +			.end = iobase + SZ_8K - 1, +			.flags = IORESOURCE_MEM, +		}, { +			.start = irq, +			.end = irq, +			.flags = IORESOURCE_IRQ, +		}, +	}; + +	return platform_device_register_resndata(&mxs_apbh_bus, +			"gpio-mxs", id, res, ARRAY_SIZE(res), NULL, 0); +} + +static int __init mxs_add_mxs_gpio(void) +{ +	if (cpu_is_mx23()) { +		mxs_add_gpio(0, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO0); +		mxs_add_gpio(1, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO1); +		mxs_add_gpio(2, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO2); +	} + +	if (cpu_is_mx28()) { +		mxs_add_gpio(0, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO0); +		mxs_add_gpio(1, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO1); +		mxs_add_gpio(2, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO2); +		mxs_add_gpio(3, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO3); +		mxs_add_gpio(4, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO4); +	} + +	return 0; +} +postcore_initcall(mxs_add_mxs_gpio); diff --git a/arch/arm/mach-mxs/gpio.h b/arch/arm/mach-mxs/gpio.h deleted file mode 100644 index 005bb06630b..00000000000 --- a/arch/arm/mach-mxs/gpio.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2008 Juergen Beisert, kernel@pengutronix.de - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA  02110-1301, USA. - */ - -#ifndef __MXS_GPIO_H__ -#define __MXS_GPIO_H__ - -struct mxs_gpio_port { -	void __iomem *base; -	int id; -	int irq; -	int irq_high; -	int virtual_irq_start; -	struct gpio_chip chip; -}; - -int mxs_gpio_init(struct mxs_gpio_port*, int); - -#endif /* __MXS_GPIO_H__ */ diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h index 7a37469ed5b..812d7a813a7 100644 --- a/arch/arm/mach-mxs/include/mach/devices-common.h +++ b/arch/arm/mach-mxs/include/mach/devices-common.h @@ -11,6 +11,8 @@  #include <linux/init.h>  #include <linux/amba/bus.h> +extern struct device mxs_apbh_bus; +  struct platform_device *mxs_add_platform_device_dmamask(  		const char *name, int id,  		const struct resource *res, unsigned int num_resources, diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c index eacdc6b0e70..56767a5cce0 100644 --- a/arch/arm/mach-mxs/mach-mx28evk.c +++ b/arch/arm/mach-mxs/mach-mx28evk.c @@ -26,7 +26,6 @@  #include <mach/iomux-mx28.h>  #include "devices-mx28.h" -#include "gpio.h"  #define MX28EVK_FLEXCAN_SWITCH	MXS_GPIO_NR(2, 13)  #define MX28EVK_FEC_PHY_POWER	MXS_GPIO_NR(2, 15) diff --git a/arch/arm/mach-mxs/mm-mx23.c b/arch/arm/mach-mxs/mm-mx23.c index 5148cd64a6b..1b2345ac1a8 100644 --- a/arch/arm/mach-mxs/mm-mx23.c +++ b/arch/arm/mach-mxs/mm-mx23.c @@ -41,5 +41,4 @@ void __init mx23_map_io(void)  void __init mx23_init_irq(void)  {  	icoll_init_irq(); -	mx23_register_gpios();  } diff --git a/arch/arm/mach-mxs/mm-mx28.c b/arch/arm/mach-mxs/mm-mx28.c index 7e4cea32ebc..b6e18ddb92c 100644 --- a/arch/arm/mach-mxs/mm-mx28.c +++ b/arch/arm/mach-mxs/mm-mx28.c @@ -41,5 +41,4 @@ void __init mx28_map_io(void)  void __init mx28_init_irq(void)  {  	icoll_init_irq(); -	mx28_register_gpios();  } diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 08acb6ec813..f6b687f61c2 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -249,6 +249,29 @@ static int slot_cn7_get_cd(struct platform_device *pdev)  {  	return !gpio_get_value(GPIO_PORT41);  } +/* MERAM */ +static struct sh_mobile_meram_info meram_info = { +	.addr_mode      = SH_MOBILE_MERAM_MODE1, +}; + +static struct resource meram_resources[] = { +	[0] = { +		.name   = "MERAM", +		.start  = 0xe8000000, +		.end    = 0xe81fffff, +		.flags  = IORESOURCE_MEM, +	}, +}; + +static struct platform_device meram_device = { +	.name           = "sh_mobile_meram", +	.id             = 0, +	.num_resources  = ARRAY_SIZE(meram_resources), +	.resource       = meram_resources, +	.dev            = { +		.platform_data = &meram_info, +	}, +};  /* SH_MMCIF */  static struct resource sh_mmcif_resources[] = { @@ -447,13 +470,29 @@ const static struct fb_videomode ap4evb_lcdc_modes[] = {  #endif  	},  }; +static struct sh_mobile_meram_cfg lcd_meram_cfg = { +	.icb[0] = { +		.marker_icb     = 28, +		.cache_icb      = 24, +		.meram_offset   = 0x0, +		.meram_size     = 0x40, +	}, +	.icb[1] = { +		.marker_icb     = 29, +		.cache_icb      = 25, +		.meram_offset   = 0x40, +		.meram_size     = 0x40, +	}, +};  static struct sh_mobile_lcdc_info lcdc_info = { +	.meram_dev = &meram_info,  	.ch[0] = {  		.chan = LCDC_CHAN_MAINLCD,  		.bpp = 16,  		.lcd_cfg = ap4evb_lcdc_modes,  		.num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes), +		.meram_cfg = &lcd_meram_cfg,  	}  }; @@ -724,15 +763,31 @@ static struct platform_device fsi_device = {  static struct platform_device fsi_ak4643_device = {  	.name		= "sh_fsi2_a_ak4643",  }; +static struct sh_mobile_meram_cfg hdmi_meram_cfg = { +	.icb[0] = { +		.marker_icb     = 30, +		.cache_icb      = 26, +		.meram_offset   = 0x80, +		.meram_size     = 0x100, +	}, +	.icb[1] = { +		.marker_icb     = 31, +		.cache_icb      = 27, +		.meram_offset   = 0x180, +		.meram_size     = 0x100, +	}, +};  static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {  	.clock_source = LCDC_CLK_EXTERNAL, +	.meram_dev = &meram_info,  	.ch[0] = {  		.chan = LCDC_CHAN_MAINLCD,  		.bpp = 16,  		.interface_type = RGB24,  		.clock_divider = 1,  		.flags = LCDC_FLAGS_DWPOL, +		.meram_cfg = &hdmi_meram_cfg,  	}  }; @@ -961,6 +1016,7 @@ static struct platform_device *ap4evb_devices[] __initdata = {  	&csi2_device,  	&ceu_device,  	&ap4evb_camera, +	&meram_device,  };  static void __init hdmi_init_pm_clock(void) diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 448ddbe4333..776f20560e7 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -39,6 +39,7 @@  #include <linux/mtd/mtd.h>  #include <linux/mtd/partitions.h>  #include <linux/mtd/physmap.h> +#include <linux/pm_runtime.h>  #include <linux/smsc911x.h>  #include <linux/sh_intc.h>  #include <linux/tca6416_keypad.h> @@ -314,6 +315,30 @@ static struct platform_device smc911x_device = {  	},  }; +/* MERAM */ +static struct sh_mobile_meram_info mackerel_meram_info = { +	.addr_mode	= SH_MOBILE_MERAM_MODE1, +}; + +static struct resource meram_resources[] = { +	[0] = { +		.name	= "MERAM", +		.start	= 0xe8000000, +		.end	= 0xe81fffff, +		.flags	= IORESOURCE_MEM, +	}, +}; + +static struct platform_device meram_device = { +	.name		= "sh_mobile_meram", +	.id		= 0, +	.num_resources	= ARRAY_SIZE(meram_resources), +	.resource	= meram_resources, +	.dev		= { +		.platform_data = &mackerel_meram_info, +	}, +}; +  /* LCDC */  static struct fb_videomode mackerel_lcdc_modes[] = {  	{ @@ -342,7 +367,23 @@ static int mackerel_get_brightness(void *board_data)  	return gpio_get_value(GPIO_PORT31);  } +static struct sh_mobile_meram_cfg lcd_meram_cfg = { +	.icb[0] = { +		.marker_icb     = 28, +		.cache_icb      = 24, +		.meram_offset   = 0x0, +		.meram_size     = 0x40, +	}, +	.icb[1] = { +		.marker_icb     = 29, +		.cache_icb      = 25, +		.meram_offset   = 0x40, +		.meram_size     = 0x40, +	}, +}; +  static struct sh_mobile_lcdc_info lcdc_info = { +	.meram_dev = &mackerel_meram_info,  	.clock_source = LCDC_CLK_BUS,  	.ch[0] = {  		.chan = LCDC_CHAN_MAINLCD, @@ -362,6 +403,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {  			.name = "sh_mobile_lcdc_bl",  			.max_brightness = 1,  		}, +		.meram_cfg = &lcd_meram_cfg,  	}  }; @@ -388,8 +430,23 @@ static struct platform_device lcdc_device = {  	},  }; +static struct sh_mobile_meram_cfg hdmi_meram_cfg = { +	.icb[0] = { +		.marker_icb     = 30, +		.cache_icb      = 26, +		.meram_offset   = 0x80, +		.meram_size     = 0x100, +	}, +	.icb[1] = { +		.marker_icb     = 31, +		.cache_icb      = 27, +		.meram_offset   = 0x180, +		.meram_size     = 0x100, +	}, +};  /* HDMI */  static struct sh_mobile_lcdc_info hdmi_lcdc_info = { +	.meram_dev = &mackerel_meram_info,  	.clock_source = LCDC_CLK_EXTERNAL,  	.ch[0] = {  		.chan = LCDC_CHAN_MAINLCD, @@ -397,6 +454,7 @@ static struct sh_mobile_lcdc_info hdmi_lcdc_info = {  		.interface_type = RGB24,  		.clock_divider = 1,  		.flags = LCDC_FLAGS_DWPOL, +		.meram_cfg = &hdmi_meram_cfg,  	}  }; @@ -856,6 +914,17 @@ static int slot_cn7_get_cd(struct platform_device *pdev)  }  /* SDHI0 */ +static irqreturn_t mackerel_sdhi0_gpio_cd(int irq, void *arg) +{ +	struct device *dev = arg; +	struct sh_mobile_sdhi_info *info = dev->platform_data; +	struct tmio_mmc_data *pdata = info->pdata; + +	tmio_mmc_cd_wakeup(pdata); + +	return IRQ_HANDLED; +} +  static struct sh_mobile_sdhi_info sdhi0_info = {  	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,  	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX, @@ -1150,6 +1219,7 @@ static struct platform_device *mackerel_devices[] __initdata = {  	&mackerel_camera,  	&hdmi_lcdc_device,  	&hdmi_device, +	&meram_device,  };  /* Keypad Initialization */ @@ -1238,6 +1308,7 @@ static void __init mackerel_init(void)  {  	u32 srcr4;  	struct clk *clk; +	int ret;  	sh7372_pinmux_init(); @@ -1343,6 +1414,13 @@ static void __init mackerel_init(void)  	gpio_request(GPIO_FN_SDHID0_1, NULL);  	gpio_request(GPIO_FN_SDHID0_0, NULL); +	ret = request_irq(evt2irq(0x3340), mackerel_sdhi0_gpio_cd, +			  IRQF_TRIGGER_FALLING, "sdhi0 cd", &sdhi0_device.dev); +	if (!ret) +		sdhi0_info.tmio_flags |= TMIO_MMC_HAS_COLD_CD; +	else +		pr_err("Cannot get IRQ #%d: %d\n", evt2irq(0x3340), ret); +  #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)  	/* enable SDHI1 */  	gpio_request(GPIO_FN_SDHICMD1, NULL); diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index d17eb66f4ac..c0800d83971 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -509,6 +509,7 @@ enum { MSTP001,         MSTP118, MSTP117, MSTP116, MSTP113,         MSTP106, MSTP101, MSTP100,         MSTP223, +       MSTP218, MSTP217, MSTP216,         MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,         MSTP329, MSTP328, MSTP323, MSTP322, MSTP314, MSTP313, MSTP312,         MSTP423, MSTP415, MSTP413, MSTP411, MSTP410, MSTP406, MSTP403, @@ -534,6 +535,9 @@ static struct clk mstp_clks[MSTP_NR] = {  	[MSTP101] = MSTP(&div4_clks[DIV4_M1], SMSTPCR1, 1, 0), /* VPU */  	[MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */  	[MSTP223] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR2, 23, 0), /* SPU2 */ +	[MSTP218] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC1 */ +	[MSTP217] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* DMAC2 */ +	[MSTP216] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 16, 0), /* DMAC3 */  	[MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */  	[MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */  	[MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */ @@ -626,6 +630,9 @@ static struct clk_lookup lookups[] = {  	CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */  	CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[MSTP223]), /* SPU2DSP0 */  	CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[MSTP223]), /* SPU2DSP1 */ +	CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* DMAC1 */ +	CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), /* DMAC2 */ +	CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]), /* DMAC3 */  	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */  	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP206]), /* SCIFB */  	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */ diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c index c84442cabe0..5ad8b2f94f8 100644 --- a/arch/arm/mach-tegra/board-harmony-power.c +++ b/arch/arm/mach-tegra/board-harmony-power.c @@ -24,6 +24,8 @@  #include <mach/irqs.h> +#include "board-harmony.h" +  #define PMC_CTRL		0x0  #define PMC_CTRL_INTR_LOW	(1 << 17) @@ -98,7 +100,7 @@ static struct tps6586x_platform_data tps_platform = {  	.irq_base	= TEGRA_NR_IRQS,  	.num_subdevs	= ARRAY_SIZE(tps_devs),  	.subdevs	= tps_devs, -	.gpio_base	= TEGRA_NR_GPIOS, +	.gpio_base	= HARMONY_GPIO_TPS6586X(0),  };  static struct i2c_board_info __initdata harmony_regulators[] = { diff --git a/arch/arm/mach-tegra/board-harmony.h b/arch/arm/mach-tegra/board-harmony.h index 1e57b071f52..d85142edaf6 100644 --- a/arch/arm/mach-tegra/board-harmony.h +++ b/arch/arm/mach-tegra/board-harmony.h @@ -17,7 +17,8 @@  #ifndef _MACH_TEGRA_BOARD_HARMONY_H  #define _MACH_TEGRA_BOARD_HARMONY_H -#define HARMONY_GPIO_WM8903(_x_)	(TEGRA_NR_GPIOS + (_x_)) +#define HARMONY_GPIO_TPS6586X(_x_)	(TEGRA_NR_GPIOS + (_x_)) +#define HARMONY_GPIO_WM8903(_x_)	(HARMONY_GPIO_TPS6586X(4) + (_x_))  #define TEGRA_GPIO_SD2_CD		TEGRA_GPIO_PI5  #define TEGRA_GPIO_SD2_WP		TEGRA_GPIO_PH1 diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index a1387875a49..d53c35fe2ea 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile @@ -3,7 +3,7 @@  #  # Common support -obj-y := clock.o gpio.o time.o devices.o cpu.o system.o irq-common.o +obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o  # MX51 uses the TZIC interrupt controller, older platforms use AVIC  obj-$(CONFIG_MXC_TZIC) += tzic.o diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c index eee1b6096a0..fb166b20f60 100644 --- a/arch/arm/plat-mxc/devices.c +++ b/arch/arm/plat-mxc/devices.c @@ -89,3 +89,14 @@ err:  	return pdev;  } + +struct device mxc_aips_bus = { +	.init_name	= "mxc_aips", +	.parent		= &platform_bus, +}; + +static int __init mxc_device_init(void) +{ +	return device_register(&mxc_aips_bus); +} +core_initcall(mxc_device_init); diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile index ad2922acf48..b41bf972b54 100644 --- a/arch/arm/plat-mxc/devices/Makefile +++ b/arch/arm/plat-mxc/devices/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o  obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o  obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC) += platform-fsl-usb2-udc.o  obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o +obj-y += platform-gpio-mxc.o  obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX21_HCD) += platform-imx21-hcd.o  obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT) += platform-imx2-wdt.o  obj-$(CONFIG_IMX_HAVE_PLATFORM_IMXDI_RTC) += platform-imxdi_rtc.o diff --git a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c new file mode 100644 index 00000000000..cf1b7fdfa20 --- /dev/null +++ b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c @@ -0,0 +1,32 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2011 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + */ +#include <mach/devices-common.h> + +struct platform_device *__init mxc_register_gpio(int id, +	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high) +{ +	struct resource res[] = { +		{ +			.start = iobase, +			.end = iobase + iosize - 1, +			.flags = IORESOURCE_MEM, +		}, { +			.start = irq, +			.end = irq, +			.flags = IORESOURCE_IRQ, +		}, { +			.start = irq_high, +			.end = irq_high, +			.flags = IORESOURCE_IRQ, +		}, +	}; + +	return platform_device_register_resndata(&mxc_aips_bus, +			"gpio-mxc", id, res, ARRAY_SIZE(res), NULL, 0); +} diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index da7991832af..91fa2632aa5 100644 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -43,6 +43,15 @@ extern void mx35_init_irq(void);  extern void mx50_init_irq(void);  extern void mx51_init_irq(void);  extern void mx53_init_irq(void); +extern void imx1_soc_init(void); +extern void imx21_soc_init(void); +extern void imx25_soc_init(void); +extern void imx27_soc_init(void); +extern void imx31_soc_init(void); +extern void imx35_soc_init(void); +extern void imx50_soc_init(void); +extern void imx51_soc_init(void); +extern void imx53_soc_init(void);  extern void epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq);  extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int);  extern int mx1_clocks_init(unsigned long fref); @@ -55,7 +64,8 @@ extern int mx51_clocks_init(unsigned long ckil, unsigned long osc,  			unsigned long ckih1, unsigned long ckih2);  extern int mx53_clocks_init(unsigned long ckil, unsigned long osc,  			unsigned long ckih1, unsigned long ckih2); -extern int mxc_register_gpios(void); +extern struct platform_device *mxc_register_gpio(int id, +	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);  extern int mxc_register_device(struct platform_device *pdev, void *data);  extern void mxc_set_cpu_type(unsigned int type);  extern void mxc_arch_reset_init(void __iomem *); diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h index fa8477337f9..03f62664537 100644 --- a/arch/arm/plat-mxc/include/mach/devices-common.h +++ b/arch/arm/plat-mxc/include/mach/devices-common.h @@ -10,6 +10,8 @@  #include <linux/platform_device.h>  #include <linux/init.h> +extern struct device mxc_aips_bus; +  struct platform_device *imx_add_platform_device_dmamask(  		const char *name, int id,  		const struct resource *res, unsigned int num_resources, diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h index a2747f12813..31c820c1b79 100644 --- a/arch/arm/plat-mxc/include/mach/gpio.h +++ b/arch/arm/plat-mxc/include/mach/gpio.h @@ -36,31 +36,4 @@  #define gpio_to_irq(gpio)	(MXC_GPIO_IRQ_START + (gpio))  #define irq_to_gpio(irq)	((irq) - MXC_GPIO_IRQ_START) -struct mxc_gpio_port { -	void __iomem *base; -	int irq; -	int irq_high; -	int virtual_irq_start; -	struct gpio_chip chip; -	u32 both_edges; -	spinlock_t lock; -}; - -#define DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, _irq_high)	\ -	{								\ -		.chip.label = "gpio-" #_id,				\ -		.irq = _irq,						\ -		.irq_high = _irq_high,					\ -		.base = soc ## _IO_ADDRESS(				\ -				soc ## _GPIO ## _hwid ## _BASE_ADDR),	\ -		.virtual_irq_start = MXC_GPIO_IRQ_START + (_id) * 32,	\ -	} - -#define DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, _irq)			\ -	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, 0) -#define DEFINE_IMX_GPIO_PORT(soc, _id, _hwid)				\ -	DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, 0) - -int mxc_gpio_init(struct mxc_gpio_port*, int); -  #endif diff --git a/arch/blackfin/lib/strncpy.S b/arch/blackfin/lib/strncpy.S index f3931d50b4a..2c07dddac99 100644 --- a/arch/blackfin/lib/strncpy.S +++ b/arch/blackfin/lib/strncpy.S @@ -25,7 +25,7 @@  ENTRY(_strncpy)  	CC = R2 == 0; -	if CC JUMP 4f; +	if CC JUMP 6f;  	P2 = R2 ;       /* size */  	P0 = R0 ;       /* dst*/ diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 74495a5ea02..f03338c2f08 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -161,7 +161,7 @@ config ARCH_HAS_CPU_IDLE_WAIT  config NO_IOPORT  	def_bool !PCI -	depends on !SH_CAYMAN && !SH_SH4202_MICRODEV +	depends on !SH_CAYMAN && !SH_SH4202_MICRODEV && !SH_SHMIN  config IO_TRAPPED  	bool diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index 618bd566cf5..969421f64a1 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c @@ -359,37 +359,31 @@ static struct soc_camera_link camera_link = {  	.priv		= &camera_info,  }; -static void dummy_release(struct device *dev) +static struct platform_device *camera_device; + +static void ap325rxa_camera_release(struct device *dev)  { +	soc_camera_platform_release(&camera_device);  } -static struct platform_device camera_device = { -	.name		= "soc_camera_platform", -	.dev		= { -		.platform_data	= &camera_info, -		.release	= dummy_release, -	}, -}; -  static int ap325rxa_camera_add(struct soc_camera_link *icl,  			       struct device *dev)  { -	if (icl != &camera_link || camera_probe() <= 0) -		return -ENODEV; +	int ret = soc_camera_platform_add(icl, dev, &camera_device, &camera_link, +					  ap325rxa_camera_release, 0); +	if (ret < 0) +		return ret; -	camera_info.dev = dev; +	ret = camera_probe(); +	if (ret < 0) +		soc_camera_platform_del(icl, camera_device, &camera_link); -	return platform_device_register(&camera_device); +	return ret;  }  static void ap325rxa_camera_del(struct soc_camera_link *icl)  { -	if (icl != &camera_link) -		return; - -	platform_device_unregister(&camera_device); -	memset(&camera_device.dev.kobj, 0, -	       sizeof(camera_device.dev.kobj)); +	soc_camera_platform_del(icl, camera_device, &camera_link);  }  #endif /* CONFIG_I2C */ diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index bb13d0e1b96..3a32741cc0a 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -885,6 +885,9 @@ static struct platform_device sh_mmcif_device = {  	},  	.num_resources	= ARRAY_SIZE(sh_mmcif_resources),  	.resource	= sh_mmcif_resources, +	.archdata = { +		.hwblk_id = HWBLK_MMC, +	},  };  #endif diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h index db85916b9e9..9210e93a92c 100644 --- a/arch/sh/include/asm/pgtable.h +++ b/arch/sh/include/asm/pgtable.h @@ -18,6 +18,7 @@  #include <asm/pgtable-2level.h>  #endif  #include <asm/page.h> +#include <asm/mmu.h>  #ifndef __ASSEMBLY__  #include <asm/addrspace.h> diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h index 40725b4a801..88bd6be168a 100644 --- a/arch/sh/include/asm/ptrace.h +++ b/arch/sh/include/asm/ptrace.h @@ -41,7 +41,9 @@  #define user_mode(regs)			(((regs)->sr & 0x40000000)==0)  #define kernel_stack_pointer(_regs)	((unsigned long)(_regs)->regs[15]) -#define GET_USP(regs) ((regs)->regs[15]) + +#define GET_FP(regs)	((regs)->regs[14]) +#define GET_USP(regs)	((regs)->regs[15])  extern void show_regs(struct pt_regs *); @@ -131,7 +133,7 @@ extern void ptrace_triggered(struct perf_event *bp, int nmi,  static inline unsigned long profile_pc(struct pt_regs *regs)  { -	unsigned long pc = instruction_pointer(regs); +	unsigned long pc = regs->pc;  	if (virt_addr_uncached(pc))  		return CAC_ADDR(pc); diff --git a/arch/sh/include/asm/tlb.h b/arch/sh/include/asm/tlb.h index 6c308d8b9a5..ec88bfcdf7c 100644 --- a/arch/sh/include/asm/tlb.h +++ b/arch/sh/include/asm/tlb.h @@ -9,6 +9,7 @@  #include <linux/pagemap.h>  #ifdef CONFIG_MMU +#include <linux/swap.h>  #include <asm/pgalloc.h>  #include <asm/tlbflush.h>  #include <asm/mmu_context.h> diff --git a/arch/sh/include/cpu-sh4/cpu/sh7722.h b/arch/sh/include/cpu-sh4/cpu/sh7722.h index 7a5b8a331b4..bd0622788d6 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7722.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7722.h @@ -236,6 +236,7 @@ enum {  };  enum { +	SHDMA_SLAVE_INVALID,  	SHDMA_SLAVE_SCIF0_TX,  	SHDMA_SLAVE_SCIF0_RX,  	SHDMA_SLAVE_SCIF1_TX, diff --git a/arch/sh/include/cpu-sh4/cpu/sh7724.h b/arch/sh/include/cpu-sh4/cpu/sh7724.h index 7eb43599942..3daef8ecbc6 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7724.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7724.h @@ -285,6 +285,7 @@ enum {  };  enum { +	SHDMA_SLAVE_INVALID,  	SHDMA_SLAVE_SCIF0_TX,  	SHDMA_SLAVE_SCIF0_RX,  	SHDMA_SLAVE_SCIF1_TX, diff --git a/arch/sh/include/cpu-sh4/cpu/sh7757.h b/arch/sh/include/cpu-sh4/cpu/sh7757.h index 05b8196c775..41f9f8b9db7 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7757.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7757.h @@ -252,6 +252,7 @@ enum {  };  enum { +	SHDMA_SLAVE_INVALID,  	SHDMA_SLAVE_SDHI_TX,  	SHDMA_SLAVE_SDHI_RX,  	SHDMA_SLAVE_MMCIF_TX, diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 762a13984bb..b473f0c06fb 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -21,6 +21,7 @@  #include <linux/fs.h>  #include <linux/ftrace.h>  #include <linux/hw_breakpoint.h> +#include <linux/prefetch.h>  #include <asm/uaccess.h>  #include <asm/mmu_context.h>  #include <asm/system.h> diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index 40733a95240..f251b5f2765 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -82,7 +82,7 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,  	void *addr;  	addr = __in_29bit_mode() ? -	       (void *)P1SEGADDR((unsigned long)vaddr) : vaddr; +	       (void *)CAC_ADDR((unsigned long)vaddr) : vaddr;  	switch (direction) {  	case DMA_FROM_DEVICE:		/* invalidate only */ diff --git a/block/blk-ioc.c b/block/blk-ioc.c index c898049dafd..342eae9b0d3 100644 --- a/block/blk-ioc.c +++ b/block/blk-ioc.c @@ -21,7 +21,7 @@ static void cfq_dtor(struct io_context *ioc)  	if (!hlist_empty(&ioc->cic_list)) {  		struct cfq_io_context *cic; -		cic = list_entry(ioc->cic_list.first, struct cfq_io_context, +		cic = hlist_entry(ioc->cic_list.first, struct cfq_io_context,  								cic_list);  		cic->dtor(ioc);  	} @@ -57,7 +57,7 @@ static void cfq_exit(struct io_context *ioc)  	if (!hlist_empty(&ioc->cic_list)) {  		struct cfq_io_context *cic; -		cic = list_entry(ioc->cic_list.first, struct cfq_io_context, +		cic = hlist_entry(ioc->cic_list.first, struct cfq_io_context,  								cic_list);  		cic->exit(ioc);  	} diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 7c52d688892..3c7b537bf90 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -185,7 +185,7 @@ struct cfq_group {  	int nr_cfqq;  	/* -	 * Per group busy queus average. Useful for workload slice calc. We +	 * Per group busy queues average. Useful for workload slice calc. We  	 * create the array for each prio class but at run time it is used  	 * only for RT and BE class and slot for IDLE class remains unused.  	 * This is primarily done to avoid confusion and a gcc warning. @@ -369,16 +369,16 @@ CFQ_CFQQ_FNS(wait_busy);  #define cfq_log_cfqq(cfqd, cfqq, fmt, args...)	\  	blk_add_trace_msg((cfqd)->queue, "cfq%d%c %s " fmt, (cfqq)->pid, \  			cfq_cfqq_sync((cfqq)) ? 'S' : 'A', \ -			blkg_path(&(cfqq)->cfqg->blkg), ##args); +			blkg_path(&(cfqq)->cfqg->blkg), ##args)  #define cfq_log_cfqg(cfqd, cfqg, fmt, args...)				\  	blk_add_trace_msg((cfqd)->queue, "%s " fmt,			\ -				blkg_path(&(cfqg)->blkg), ##args);      \ +				blkg_path(&(cfqg)->blkg), ##args)       \  #else  #define cfq_log_cfqq(cfqd, cfqq, fmt, args...)	\  	blk_add_trace_msg((cfqd)->queue, "cfq%d " fmt, (cfqq)->pid, ##args) -#define cfq_log_cfqg(cfqd, cfqg, fmt, args...)		do {} while (0); +#define cfq_log_cfqg(cfqd, cfqg, fmt, args...)		do {} while (0)  #endif  #define cfq_log(cfqd, fmt, args...)	\  	blk_add_trace_msg((cfqd)->queue, "cfq " fmt, ##args) @@ -3786,9 +3786,6 @@ new_queue:  	return 0;  queue_fail: -	if (cic) -		put_io_context(cic->ioc); -  	cfq_schedule_dispatch(cfqd);  	spin_unlock_irqrestore(q->queue_lock, flags);  	cfq_log(cfqd, "set_request fail"); diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index e6fc716aca4..f533f3375e2 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -192,7 +192,8 @@ static int sock_xmit(struct nbd_device *lo, int send, void *buf, int size,  			if (lo->xmit_timeout)  				del_timer_sync(&ti);  		} else -			result = kernel_recvmsg(sock, &msg, &iov, 1, size, 0); +			result = kernel_recvmsg(sock, &msg, &iov, 1, size, +						msg.msg_flags);  		if (signal_pending(current)) {  			siginfo_t info; @@ -753,9 +754,26 @@ static int __init nbd_init(void)  		return -ENOMEM;  	part_shift = 0; -	if (max_part > 0) +	if (max_part > 0) {  		part_shift = fls(max_part); +		/* +		 * Adjust max_part according to part_shift as it is exported +		 * to user space so that user can know the max number of +		 * partition kernel should be able to manage. +		 * +		 * Note that -1 is required because partition 0 is reserved +		 * for the whole disk. +		 */ +		max_part = (1UL << part_shift) - 1; +	} + +	if ((1UL << part_shift) > DISK_MAX_PARTS) +		return -EINVAL; + +	if (nbds_max > 1UL << (MINORBITS - part_shift)) +		return -EINVAL; +  	for (i = 0; i < nbds_max; i++) {  		struct gendisk *disk = alloc_disk(1 << part_shift);  		if (!disk) diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index c73910cc28c..5cf2993a833 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -809,11 +809,13 @@ static int __init xen_blkif_init(void)   failed_init:  	kfree(blkbk->pending_reqs);  	kfree(blkbk->pending_grant_handles); -	for (i = 0; i < mmap_pages; i++) { -		if (blkbk->pending_pages[i]) -			__free_page(blkbk->pending_pages[i]); +	if (blkbk->pending_pages) { +		for (i = 0; i < mmap_pages; i++) { +			if (blkbk->pending_pages[i]) +				__free_page(blkbk->pending_pages[i]); +		} +		kfree(blkbk->pending_pages);  	} -	kfree(blkbk->pending_pages);  	kfree(blkbk);  	blkbk = NULL;  	return rc; diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 34570823355..6cc0db1bf52 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -357,14 +357,13 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,  	}  	vbd->bdev = bdev; -	vbd->size = vbd_sz(vbd); -  	if (vbd->bdev->bd_disk == NULL) {  		DPRINTK("xen_vbd_create: device %08x doesn't exist.\n",  			vbd->pdevice);  		xen_vbd_free(vbd);  		return -ENOENT;  	} +	vbd->size = vbd_sz(vbd);  	if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || cdrom)  		vbd->type |= VDISK_CDROM; diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index b3f01996318..48ad2a7ab08 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -355,29 +355,24 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)   *             flags        pointer to flags for data   *             count        count of received data in bytes   *      - * Return Value:    Number of bytes received + * Return Value:    None   */ -static unsigned int hci_uart_tty_receive(struct tty_struct *tty, -		const u8 *data, char *flags, int count) +static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)  {  	struct hci_uart *hu = (void *)tty->disc_data; -	int received;  	if (!hu || tty != hu->tty) -		return -ENODEV; +		return;  	if (!test_bit(HCI_UART_PROTO_SET, &hu->flags)) -		return -EINVAL; +		return;  	spin_lock(&hu->rx_lock); -	received = hu->proto->recv(hu, (void *) data, count); -	if (received > 0) -		hu->hdev->stat.byte_rx += received; +	hu->proto->recv(hu, (void *) data, count); +	hu->hdev->stat.byte_rx += count;  	spin_unlock(&hu->rx_lock);  	tty_unthrottle(tty); - -	return received;  }  static int hci_uart_register_dev(struct hci_uart *hu) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 036e5865eb4..dc7c033ef58 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -24,7 +24,6 @@  #include <linux/ioport.h>  #include <linux/io.h>  #include <linux/clk.h> -#include <linux/pm_runtime.h>  #include <linux/irq.h>  #include <linux/err.h>  #include <linux/clocksource.h> @@ -153,12 +152,10 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)  {  	int ret; -	/* wake up device and enable clock */ -	pm_runtime_get_sync(&p->pdev->dev); +	/* enable clock */  	ret = clk_enable(p->clk);  	if (ret) {  		dev_err(&p->pdev->dev, "cannot enable clock\n"); -		pm_runtime_put_sync(&p->pdev->dev);  		return ret;  	} @@ -190,9 +187,8 @@ static void sh_cmt_disable(struct sh_cmt_priv *p)  	/* disable interrupts in CMT block */  	sh_cmt_write(p, CMCSR, 0); -	/* stop clock and mark device as idle */ +	/* stop clock */  	clk_disable(p->clk); -	pm_runtime_put_sync(&p->pdev->dev);  }  /* private flags */ @@ -664,7 +660,6 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev)  	if (p) {  		dev_info(&pdev->dev, "kept as earlytimer\n"); -		pm_runtime_enable(&pdev->dev);  		return 0;  	} @@ -679,9 +674,6 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev)  		kfree(p);  		platform_set_drvdata(pdev, NULL);  	} - -	if (!is_early_platform_device(pdev)) -		pm_runtime_enable(&pdev->dev);  	return ret;  } diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 17296288a20..80813576861 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -25,7 +25,6 @@  #include <linux/delay.h>  #include <linux/io.h>  #include <linux/clk.h> -#include <linux/pm_runtime.h>  #include <linux/irq.h>  #include <linux/err.h>  #include <linux/clocksource.h> @@ -110,12 +109,10 @@ static int sh_tmu_enable(struct sh_tmu_priv *p)  {  	int ret; -	/* wake up device and enable clock */ -	pm_runtime_get_sync(&p->pdev->dev); +	/* enable clock */  	ret = clk_enable(p->clk);  	if (ret) {  		dev_err(&p->pdev->dev, "cannot enable clock\n"); -		pm_runtime_put_sync(&p->pdev->dev);  		return ret;  	} @@ -144,9 +141,8 @@ static void sh_tmu_disable(struct sh_tmu_priv *p)  	/* disable interrupts in TMU block */  	sh_tmu_write(p, TCR, 0x0000); -	/* stop clock and mark device as idle */ +	/* stop clock */  	clk_disable(p->clk); -	pm_runtime_put_sync(&p->pdev->dev);  }  static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta, @@ -415,7 +411,6 @@ static int __devinit sh_tmu_probe(struct platform_device *pdev)  	if (p) {  		dev_info(&pdev->dev, "kept as earlytimer\n"); -		pm_runtime_enable(&pdev->dev);  		return 0;  	} @@ -430,9 +425,6 @@ static int __devinit sh_tmu_probe(struct platform_device *pdev)  		kfree(p);  		platform_set_drvdata(pdev, NULL);  	} - -	if (!is_early_platform_device(pdev)) -		pm_runtime_enable(&pdev->dev);  	return ret;  } diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 636e40925b1..2a638f9f09a 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -343,7 +343,7 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)  		dmae_set_dmars(sh_chan, cfg->mid_rid);  		dmae_set_chcr(sh_chan, cfg->chcr); -	} else if ((sh_dmae_readl(sh_chan, CHCR) & 0xf00) != 0x400) { +	} else {  		dmae_init(sh_chan);  	} @@ -1144,6 +1144,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)  	/* platform data */  	shdev->pdata = pdata; +	platform_set_drvdata(pdev, shdev); +  	pm_runtime_enable(&pdev->dev);  	pm_runtime_get_sync(&pdev->dev); @@ -1256,7 +1258,6 @@ static int __init sh_dmae_probe(struct platform_device *pdev)  	pm_runtime_put(&pdev->dev); -	platform_set_drvdata(pdev, shdev);  	dma_async_device_register(&shdev->common);  	return err; @@ -1278,6 +1279,8 @@ rst_err:  	if (dmars)  		iounmap(shdev->dmars); + +	platform_set_drvdata(pdev, NULL);  emapdmars:  	iounmap(shdev->chan_reg);  	synchronize_rcu(); @@ -1316,6 +1319,8 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)  		iounmap(shdev->dmars);  	iounmap(shdev->chan_reg); +	platform_set_drvdata(pdev, NULL); +  	synchronize_rcu();  	kfree(shdev); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 21271a5209a..f8b6e7d27e4 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -94,6 +94,15 @@ config GPIO_EXYNOS4  	def_bool y  	depends on CPU_EXYNOS4210 +config GPIO_MXS +	def_bool y +	depends on ARCH_MXS + +config GPIO_MXC +	def_bool y +	depends on ARCH_MXC +	select GPIO_BASIC_MMIO_CORE +  config GPIO_PLAT_SAMSUNG  	def_bool y  	depends on SAMSUNG_GPIOLIB_4BIT diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index e6e503229c8..66923cf3ad6 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -10,6 +10,8 @@ obj-$(CONFIG_GPIO_BASIC_MMIO_CORE)	+= basic_mmio_gpio.o  obj-$(CONFIG_GPIO_BASIC_MMIO)	+= basic_mmio_gpio.o  obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o  obj-$(CONFIG_GPIO_EXYNOS4)	+= gpio-exynos4.o +obj-$(CONFIG_GPIO_MXC)		+= gpio-mxc.o +obj-$(CONFIG_GPIO_MXS)		+= gpio-mxs.o  obj-$(CONFIG_GPIO_PLAT_SAMSUNG)	+= gpio-plat-samsung.o  obj-$(CONFIG_GPIO_S5PC100)	+= gpio-s5pc100.o  obj-$(CONFIG_GPIO_S5PV210)	+= gpio-s5pv210.o diff --git a/arch/arm/plat-mxc/gpio.c b/drivers/gpio/gpio-mxc.c index 6cd6d7f686f..b351952893b 100644 --- a/arch/arm/plat-mxc/gpio.c +++ b/drivers/gpio/gpio-mxc.c @@ -24,11 +24,28 @@  #include <linux/io.h>  #include <linux/irq.h>  #include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/basic_mmio_gpio.h>  #include <mach/hardware.h>  #include <asm-generic/bug.h> -static struct mxc_gpio_port *mxc_gpio_ports; -static int gpio_table_size; +struct mxc_gpio_port { +	struct list_head node; +	void __iomem *base; +	int irq; +	int irq_high; +	int virtual_irq_start; +	struct bgpio_chip bgc; +	u32 both_edges; +}; + +/* + * MX2 has one interrupt *for all* gpio ports. The list is used + * to save the references to all ports, so that mx2_gpio_irq_handler + * can walk through all interrupt status registers. + */ +static LIST_HEAD(mxc_gpio_ports);  #define cpu_is_mx1_mx2()	(cpu_is_mx1() || cpu_is_mx2()) @@ -50,7 +67,7 @@ static int gpio_table_size;  static void _clear_gpio_irqstatus(struct mxc_gpio_port *port, u32 index)  { -	__raw_writel(1 << index, port->base + GPIO_ISR); +	writel(1 << index, port->base + GPIO_ISR);  }  static void _set_gpio_irqenable(struct mxc_gpio_port *port, u32 index, @@ -58,35 +75,36 @@ static void _set_gpio_irqenable(struct mxc_gpio_port *port, u32 index,  {  	u32 l; -	l = __raw_readl(port->base + GPIO_IMR); +	l = readl(port->base + GPIO_IMR);  	l = (l & (~(1 << index))) | (!!enable << index); -	__raw_writel(l, port->base + GPIO_IMR); +	writel(l, port->base + GPIO_IMR);  }  static void gpio_ack_irq(struct irq_data *d)  { +	struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d);  	u32 gpio = irq_to_gpio(d->irq); -	_clear_gpio_irqstatus(&mxc_gpio_ports[gpio / 32], gpio & 0x1f); +	_clear_gpio_irqstatus(port, gpio & 0x1f);  }  static void gpio_mask_irq(struct irq_data *d)  { +	struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d);  	u32 gpio = irq_to_gpio(d->irq); -	_set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 0); +	_set_gpio_irqenable(port, gpio & 0x1f, 0);  }  static void gpio_unmask_irq(struct irq_data *d)  { +	struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d);  	u32 gpio = irq_to_gpio(d->irq); -	_set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 1); +	_set_gpio_irqenable(port, gpio & 0x1f, 1);  } -static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset); -  static int gpio_set_irq_type(struct irq_data *d, u32 type)  {  	u32 gpio = irq_to_gpio(d->irq); -	struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32]; +	struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d);  	u32 bit, val;  	int edge;  	void __iomem *reg = port->base; @@ -100,7 +118,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)  		edge = GPIO_INT_FALL_EDGE;  		break;  	case IRQ_TYPE_EDGE_BOTH: -		val = mxc_gpio_get(&port->chip, gpio & 31); +		val = gpio_get_value(gpio & 31);  		if (val) {  			edge = GPIO_INT_LOW_LEV;  			pr_debug("mxc: set GPIO %d to low trigger\n", gpio); @@ -122,8 +140,8 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)  	reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */  	bit = gpio & 0xf; -	val = __raw_readl(reg) & ~(0x3 << (bit << 1)); -	__raw_writel(val | (edge << (bit << 1)), reg); +	val = readl(reg) & ~(0x3 << (bit << 1)); +	writel(val | (edge << (bit << 1)), reg);  	_clear_gpio_irqstatus(port, gpio & 0x1f);  	return 0; @@ -137,7 +155,7 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)  	reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */  	bit = gpio & 0xf; -	val = __raw_readl(reg); +	val = readl(reg);  	edge = (val >> (bit << 1)) & 3;  	val &= ~(0x3 << (bit << 1));  	if (edge == GPIO_INT_HIGH_LEV) { @@ -151,7 +169,7 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)  		       gpio, edge);  		return;  	} -	__raw_writel(val | (edge << (bit << 1)), reg); +	writel(val | (edge << (bit << 1)), reg);  }  /* handle 32 interrupts in one status register */ @@ -177,8 +195,7 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)  	u32 irq_stat;  	struct mxc_gpio_port *port = irq_get_handler_data(irq); -	irq_stat = __raw_readl(port->base + GPIO_ISR) & -			__raw_readl(port->base + GPIO_IMR); +	irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);  	mxc_gpio_irq_handler(port, irq_stat);  } @@ -186,19 +203,18 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)  /* MX2 has one interrupt *for all* gpio ports */  static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)  { -	int i;  	u32 irq_msk, irq_stat; -	struct mxc_gpio_port *port = irq_get_handler_data(irq); +	struct mxc_gpio_port *port;  	/* walk through all interrupt status registers */ -	for (i = 0; i < gpio_table_size; i++) { -		irq_msk = __raw_readl(port[i].base + GPIO_IMR); +	list_for_each_entry(port, &mxc_gpio_ports, node) { +		irq_msk = readl(port->base + GPIO_IMR);  		if (!irq_msk)  			continue; -		irq_stat = __raw_readl(port[i].base + GPIO_ISR) & irq_msk; +		irq_stat = readl(port->base + GPIO_ISR) & irq_msk;  		if (irq_stat) -			mxc_gpio_irq_handler(&port[i], irq_stat); +			mxc_gpio_irq_handler(port, irq_stat);  	}  } @@ -215,7 +231,7 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)  {  	u32 gpio = irq_to_gpio(d->irq);  	u32 gpio_idx = gpio & 0x1F; -	struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32]; +	struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d);  	if (enable) {  		if (port->irq_high && (gpio_idx >= 16)) @@ -241,121 +257,123 @@ static struct irq_chip gpio_irq_chip = {  	.irq_set_wake = gpio_set_wake_irq,  }; -static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, -				int dir) -{ -	struct mxc_gpio_port *port = -		container_of(chip, struct mxc_gpio_port, chip); -	u32 l; -	unsigned long flags; - -	spin_lock_irqsave(&port->lock, flags); -	l = __raw_readl(port->base + GPIO_GDIR); -	if (dir) -		l |= 1 << offset; -	else -		l &= ~(1 << offset); -	__raw_writel(l, port->base + GPIO_GDIR); -	spin_unlock_irqrestore(&port->lock, flags); -} - -static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ -	struct mxc_gpio_port *port = -		container_of(chip, struct mxc_gpio_port, chip); -	void __iomem *reg = port->base + GPIO_DR; -	u32 l; -	unsigned long flags; - -	spin_lock_irqsave(&port->lock, flags); -	l = (__raw_readl(reg) & (~(1 << offset))) | (!!value << offset); -	__raw_writel(l, reg); -	spin_unlock_irqrestore(&port->lock, flags); -} - -static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset) -{ -	struct mxc_gpio_port *port = -		container_of(chip, struct mxc_gpio_port, chip); - -	return (__raw_readl(port->base + GPIO_PSR) >> offset) & 1; -} - -static int mxc_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ -	_set_gpio_direction(chip, offset, 0); -	return 0; -} - -static int mxc_gpio_direction_output(struct gpio_chip *chip, -				     unsigned offset, int value) -{ -	mxc_gpio_set(chip, offset, value); -	_set_gpio_direction(chip, offset, 1); -	return 0; -} -  /*   * This lock class tells lockdep that GPIO irqs are in a different   * category than their parents, so it won't report false recursion.   */  static struct lock_class_key gpio_lock_class; -int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt) +static int __devinit mxc_gpio_probe(struct platform_device *pdev)  { -	int i, j; +	struct mxc_gpio_port *port; +	struct resource *iores; +	int err, i; -	/* save for local usage */ -	mxc_gpio_ports = port; -	gpio_table_size = cnt; +	port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL); +	if (!port) +		return -ENOMEM; -	printk(KERN_INFO "MXC GPIO hardware\n"); +	port->virtual_irq_start = MXC_GPIO_IRQ_START + pdev->id * 32; -	for (i = 0; i < cnt; i++) { -		/* disable the interrupt and clear the status */ -		__raw_writel(0, port[i].base + GPIO_IMR); -		__raw_writel(~0, port[i].base + GPIO_ISR); -		for (j = port[i].virtual_irq_start; -			j < port[i].virtual_irq_start + 32; j++) { -			irq_set_lockdep_class(j, &gpio_lock_class); -			irq_set_chip_and_handler(j, &gpio_irq_chip, -						 handle_level_irq); -			set_irq_flags(j, IRQF_VALID); -		} +	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!iores) { +		err = -ENODEV; +		goto out_kfree; +	} -		/* register gpio chip */ -		port[i].chip.direction_input = mxc_gpio_direction_input; -		port[i].chip.direction_output = mxc_gpio_direction_output; -		port[i].chip.get = mxc_gpio_get; -		port[i].chip.set = mxc_gpio_set; -		port[i].chip.base = i * 32; -		port[i].chip.ngpio = 32; +	if (!request_mem_region(iores->start, resource_size(iores), +				pdev->name)) { +		err = -EBUSY; +		goto out_kfree; +	} -		spin_lock_init(&port[i].lock); +	port->base = ioremap(iores->start, resource_size(iores)); +	if (!port->base) { +		err = -ENOMEM; +		goto out_release_mem; +	} -		/* its a serious configuration bug when it fails */ -		BUG_ON( gpiochip_add(&port[i].chip) < 0 ); +	port->irq_high = platform_get_irq(pdev, 1); +	port->irq = platform_get_irq(pdev, 0); +	if (port->irq < 0) { +		err = -EINVAL; +		goto out_iounmap; +	} -		if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) { -			/* setup one handler for each entry */ -			irq_set_chained_handler(port[i].irq, -						mx3_gpio_irq_handler); -			irq_set_handler_data(port[i].irq, &port[i]); -			if (port[i].irq_high) { -				/* setup handler for GPIO 16 to 31 */ -				irq_set_chained_handler(port[i].irq_high, -							mx3_gpio_irq_handler); -				irq_set_handler_data(port[i].irq_high, -						     &port[i]); -			} -		} +	/* disable the interrupt and clear the status */ +	writel(0, port->base + GPIO_IMR); +	writel(~0, port->base + GPIO_ISR); + +	for (i = port->virtual_irq_start; +		i < port->virtual_irq_start + 32; i++) { +		irq_set_lockdep_class(i, &gpio_lock_class); +		irq_set_chip_and_handler(i, &gpio_irq_chip, handle_level_irq); +		set_irq_flags(i, IRQF_VALID); +		irq_set_chip_data(i, port);  	}  	if (cpu_is_mx2()) {  		/* setup one handler for all GPIO interrupts */ -		irq_set_chained_handler(port[0].irq, mx2_gpio_irq_handler); -		irq_set_handler_data(port[0].irq, port); +		if (pdev->id == 0) +			irq_set_chained_handler(port->irq, +						mx2_gpio_irq_handler); +	} else { +		/* setup one handler for each entry */ +		irq_set_chained_handler(port->irq, mx3_gpio_irq_handler); +		irq_set_handler_data(port->irq, port); +		if (port->irq_high > 0) { +			/* setup handler for GPIO 16 to 31 */ +			irq_set_chained_handler(port->irq_high, +						mx3_gpio_irq_handler); +			irq_set_handler_data(port->irq_high, port); +		}  	} +	err = bgpio_init(&port->bgc, &pdev->dev, 4, +			 port->base + GPIO_PSR, +			 port->base + GPIO_DR, NULL, +			 port->base + GPIO_GDIR, NULL, false); +	if (err) +		goto out_iounmap; + +	port->bgc.gc.base = pdev->id * 32; + +	err = gpiochip_add(&port->bgc.gc); +	if (err) +		goto out_bgpio_remove; + +	list_add_tail(&port->node, &mxc_gpio_ports); +  	return 0; + +out_bgpio_remove: +	bgpio_remove(&port->bgc); +out_iounmap: +	iounmap(port->base); +out_release_mem: +	release_mem_region(iores->start, resource_size(iores)); +out_kfree: +	kfree(port); +	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err); +	return err;  } + +static struct platform_driver mxc_gpio_driver = { +	.driver		= { +		.name	= "gpio-mxc", +		.owner	= THIS_MODULE, +	}, +	.probe		= mxc_gpio_probe, +}; + +static int __init gpio_mxc_init(void) +{ +	return platform_driver_register(&mxc_gpio_driver); +} +postcore_initcall(gpio_mxc_init); + +MODULE_AUTHOR("Freescale Semiconductor, " +	      "Daniel Mack <danielncaiaq.de>, " +	      "Juergen Beisert <kernel@pengutronix.de>"); +MODULE_DESCRIPTION("Freescale MXC GPIO"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-mxs/gpio.c b/drivers/gpio/gpio-mxs.c index 2c950fef71a..a28761428bb 100644 --- a/arch/arm/mach-mxs/gpio.c +++ b/drivers/gpio/gpio-mxs.c @@ -25,14 +25,12 @@  #include <linux/io.h>  #include <linux/irq.h>  #include <linux/gpio.h> -#include <mach/mx23.h> -#include <mach/mx28.h> -#include <asm-generic/bug.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <mach/mxs.h> -#include "gpio.h" - -static struct mxs_gpio_port *mxs_gpio_ports; -static int gpio_table_size; +#define MXS_SET		0x4 +#define MXS_CLR		0x8  #define PINCTRL_DOUT(n)		((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10)  #define PINCTRL_DIN(n)		((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10) @@ -50,40 +48,55 @@ static int gpio_table_size;  #define GPIO_INT_LEV_MASK	(1 << 0)  #define GPIO_INT_POL_MASK	(1 << 1) +struct mxs_gpio_port { +	void __iomem *base; +	int id; +	int irq; +	int irq_high; +	int virtual_irq_start; +	struct gpio_chip chip; +}; +  /* Note: This driver assumes 32 GPIOs are handled in one register */  static void clear_gpio_irqstatus(struct mxs_gpio_port *port, u32 index)  { -	__mxs_clrl(1 << index, port->base + PINCTRL_IRQSTAT(port->id)); +	writel(1 << index, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR);  }  static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index,  				int enable)  {  	if (enable) { -		__mxs_setl(1 << index, port->base + PINCTRL_IRQEN(port->id)); -		__mxs_setl(1 << index, port->base + PINCTRL_PIN2IRQ(port->id)); +		writel(1 << index, +			port->base + PINCTRL_IRQEN(port->id) + MXS_SET); +		writel(1 << index, +			port->base + PINCTRL_PIN2IRQ(port->id) + MXS_SET);  	} else { -		__mxs_clrl(1 << index, port->base + PINCTRL_IRQEN(port->id)); +		writel(1 << index, +			port->base + PINCTRL_IRQEN(port->id) + MXS_CLR);  	}  }  static void mxs_gpio_ack_irq(struct irq_data *d)  { +	struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);  	u32 gpio = irq_to_gpio(d->irq); -	clear_gpio_irqstatus(&mxs_gpio_ports[gpio / 32], gpio & 0x1f); +	clear_gpio_irqstatus(port, gpio & 0x1f);  }  static void mxs_gpio_mask_irq(struct irq_data *d)  { +	struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);  	u32 gpio = irq_to_gpio(d->irq); -	set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 0); +	set_gpio_irqenable(port, gpio & 0x1f, 0);  }  static void mxs_gpio_unmask_irq(struct irq_data *d)  { +	struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);  	u32 gpio = irq_to_gpio(d->irq); -	set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 1); +	set_gpio_irqenable(port, gpio & 0x1f, 1);  }  static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset); @@ -92,7 +105,7 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)  {  	u32 gpio = irq_to_gpio(d->irq);  	u32 pin_mask = 1 << (gpio & 31); -	struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32]; +	struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);  	void __iomem *pin_addr;  	int edge; @@ -116,16 +129,16 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)  	/* set level or edge */  	pin_addr = port->base + PINCTRL_IRQLEV(port->id);  	if (edge & GPIO_INT_LEV_MASK) -		__mxs_setl(pin_mask, pin_addr); +		writel(pin_mask, pin_addr + MXS_SET);  	else -		__mxs_clrl(pin_mask, pin_addr); +		writel(pin_mask, pin_addr + MXS_CLR);  	/* set polarity */  	pin_addr = port->base + PINCTRL_IRQPOL(port->id);  	if (edge & GPIO_INT_POL_MASK) -		__mxs_setl(pin_mask, pin_addr); +		writel(pin_mask, pin_addr + MXS_SET);  	else -		__mxs_clrl(pin_mask, pin_addr); +		writel(pin_mask, pin_addr + MXS_CLR);  	clear_gpio_irqstatus(port, gpio & 0x1f); @@ -136,13 +149,13 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)  static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)  {  	u32 irq_stat; -	struct mxs_gpio_port *port = (struct mxs_gpio_port *)irq_get_handler_data(irq); +	struct mxs_gpio_port *port = irq_get_handler_data(irq);  	u32 gpio_irq_no_base = port->virtual_irq_start;  	desc->irq_data.chip->irq_ack(&desc->irq_data); -	irq_stat = __raw_readl(port->base + PINCTRL_IRQSTAT(port->id)) & -			__raw_readl(port->base + PINCTRL_IRQEN(port->id)); +	irq_stat = readl(port->base + PINCTRL_IRQSTAT(port->id)) & +			readl(port->base + PINCTRL_IRQEN(port->id));  	while (irq_stat != 0) {  		int irqoffset = fls(irq_stat) - 1; @@ -164,7 +177,7 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)  {  	u32 gpio = irq_to_gpio(d->irq);  	u32 gpio_idx = gpio & 0x1f; -	struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32]; +	struct mxs_gpio_port *port = irq_data_get_irq_chip_data(d);  	if (enable) {  		if (port->irq_high && (gpio_idx >= 16)) @@ -198,9 +211,9 @@ static void mxs_set_gpio_direction(struct gpio_chip *chip, unsigned offset,  	void __iomem *pin_addr = port->base + PINCTRL_DOE(port->id);  	if (dir) -		__mxs_setl(1 << offset, pin_addr); +		writel(1 << offset, pin_addr + MXS_SET);  	else -		__mxs_clrl(1 << offset, pin_addr); +		writel(1 << offset, pin_addr + MXS_CLR);  }  static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset) @@ -208,7 +221,7 @@ static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset)  	struct mxs_gpio_port *port =  		container_of(chip, struct mxs_gpio_port, chip); -	return (__raw_readl(port->base + PINCTRL_DIN(port->id)) >> offset) & 1; +	return (readl(port->base + PINCTRL_DIN(port->id)) >> offset) & 1;  }  static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value) @@ -218,9 +231,9 @@ static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value)  	void __iomem *pin_addr = port->base + PINCTRL_DOUT(port->id);  	if (value) -		__mxs_setl(1 << offset, pin_addr); +		writel(1 << offset, pin_addr + MXS_SET);  	else -		__mxs_clrl(1 << offset, pin_addr); +		writel(1 << offset, pin_addr + MXS_CLR);  }  static int mxs_gpio_to_irq(struct gpio_chip *chip, unsigned offset) @@ -245,87 +258,113 @@ static int mxs_gpio_direction_output(struct gpio_chip *chip,  	return 0;  } -int __init mxs_gpio_init(struct mxs_gpio_port *port, int cnt) +static int __devinit mxs_gpio_probe(struct platform_device *pdev)  { -	int i, j; +	static void __iomem *base; +	struct mxs_gpio_port *port; +	struct resource *iores = NULL; +	int err, i; -	/* save for local usage */ -	mxs_gpio_ports = port; -	gpio_table_size = cnt; +	port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL); +	if (!port) +		return -ENOMEM; -	pr_info("MXS GPIO hardware\n"); +	port->id = pdev->id; +	port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32; -	for (i = 0; i < cnt; i++) { -		/* disable the interrupt and clear the status */ -		__raw_writel(0, port[i].base + PINCTRL_PIN2IRQ(i)); -		__raw_writel(0, port[i].base + PINCTRL_IRQEN(i)); +	/* +	 * map memory region only once, as all the gpio ports +	 * share the same one +	 */ +	if (!base) { +		iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); +		if (!iores) { +			err = -ENODEV; +			goto out_kfree; +		} -		/* clear address has to be used to clear IRQSTAT bits */ -		__mxs_clrl(~0U, port[i].base + PINCTRL_IRQSTAT(i)); +		if (!request_mem_region(iores->start, resource_size(iores), +					pdev->name)) { +			err = -EBUSY; +			goto out_kfree; +		} -		for (j = port[i].virtual_irq_start; -			j < port[i].virtual_irq_start + 32; j++) { -			irq_set_chip_and_handler(j, &gpio_irq_chip, -						 handle_level_irq); -			set_irq_flags(j, IRQF_VALID); +		base = ioremap(iores->start, resource_size(iores)); +		if (!base) { +			err = -ENOMEM; +			goto out_release_mem;  		} +	} +	port->base = base; + +	port->irq = platform_get_irq(pdev, 0); +	if (port->irq < 0) { +		err = -EINVAL; +		goto out_iounmap; +	} -		/* setup one handler for each entry */ -		irq_set_chained_handler(port[i].irq, mxs_gpio_irq_handler); -		irq_set_handler_data(port[i].irq, &port[i]); +	/* disable the interrupt and clear the status */ +	writel(0, port->base + PINCTRL_PIN2IRQ(port->id)); +	writel(0, port->base + PINCTRL_IRQEN(port->id)); -		/* register gpio chip */ -		port[i].chip.direction_input = mxs_gpio_direction_input; -		port[i].chip.direction_output = mxs_gpio_direction_output; -		port[i].chip.get = mxs_gpio_get; -		port[i].chip.set = mxs_gpio_set; -		port[i].chip.to_irq = mxs_gpio_to_irq; -		port[i].chip.base = i * 32; -		port[i].chip.ngpio = 32; +	/* clear address has to be used to clear IRQSTAT bits */ +	writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); -		/* its a serious configuration bug when it fails */ -		BUG_ON(gpiochip_add(&port[i].chip) < 0); +	for (i = port->virtual_irq_start; +		i < port->virtual_irq_start + 32; i++) { +		irq_set_chip_and_handler(i, &gpio_irq_chip, +					 handle_level_irq); +		set_irq_flags(i, IRQF_VALID); +		irq_set_chip_data(i, port);  	} -	return 0; -} +	/* setup one handler for each entry */ +	irq_set_chained_handler(port->irq, mxs_gpio_irq_handler); +	irq_set_handler_data(port->irq, port); -#define MX23_GPIO_BASE	MX23_IO_ADDRESS(MX23_PINCTRL_BASE_ADDR) -#define MX28_GPIO_BASE	MX28_IO_ADDRESS(MX28_PINCTRL_BASE_ADDR) +	/* register gpio chip */ +	port->chip.direction_input = mxs_gpio_direction_input; +	port->chip.direction_output = mxs_gpio_direction_output; +	port->chip.get = mxs_gpio_get; +	port->chip.set = mxs_gpio_set; +	port->chip.to_irq = mxs_gpio_to_irq; +	port->chip.base = port->id * 32; +	port->chip.ngpio = 32; -#define DEFINE_MXS_GPIO_PORT(_base, _irq, _id)				\ -	{								\ -		.chip.label = "gpio-" #_id,				\ -		.id = _id,						\ -		.irq = _irq,						\ -		.base = _base,						\ -		.virtual_irq_start = MXS_GPIO_IRQ_START + (_id) * 32,	\ -	} +	err = gpiochip_add(&port->chip); +	if (err) +		goto out_iounmap; -#ifdef CONFIG_SOC_IMX23 -static struct mxs_gpio_port mx23_gpio_ports[] = { -	DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO0, 0), -	DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO1, 1), -	DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO2, 2), -}; +	return 0; -int __init mx23_register_gpios(void) -{ -	return mxs_gpio_init(mx23_gpio_ports, ARRAY_SIZE(mx23_gpio_ports)); +out_iounmap: +	if (iores) +		iounmap(port->base); +out_release_mem: +	if (iores) +		release_mem_region(iores->start, resource_size(iores)); +out_kfree: +	kfree(port); +	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err); +	return err;  } -#endif -#ifdef CONFIG_SOC_IMX28 -static struct mxs_gpio_port mx28_gpio_ports[] = { -	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO0, 0), -	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO1, 1), -	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO2, 2), -	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO3, 3), -	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO4, 4), +static struct platform_driver mxs_gpio_driver = { +	.driver		= { +		.name	= "gpio-mxs", +		.owner	= THIS_MODULE, +	}, +	.probe		= mxs_gpio_probe,  }; -int __init mx28_register_gpios(void) +static int __init mxs_gpio_init(void)  { -	return mxs_gpio_init(mx28_gpio_ports, ARRAY_SIZE(mx28_gpio_ports)); +	return platform_driver_register(&mxs_gpio_driver);  } -#endif +postcore_initcall(mxs_gpio_init); + +MODULE_AUTHOR("Freescale Semiconductor, " +	      "Daniel Mack <danielncaiaq.de>, " +	      "Juergen Beisert <kernel@pengutronix.de>"); +MODULE_DESCRIPTION("Freescale MXS GPIO"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index de3d2465fe2..85e937984ff 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -296,7 +296,7 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)  		 * If the TjMax is not plausible, an assumption  		 * will be used  		 */ -		if (val > 80 && val < 120) { +		if (val) {  			dev_info(dev, "TjMax is %d C.\n", val);  			return val * 1000;  		} @@ -304,24 +304,9 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)  	/*  	 * An assumption is made for early CPUs and unreadable MSR. -	 * NOTE: the given value may not be correct. +	 * NOTE: the calculated value may not be correct.  	 */ - -	switch (c->x86_model) { -	case 0xe: -	case 0xf: -	case 0x16: -	case 0x1a: -		dev_warn(dev, "TjMax is assumed as 100 C!\n"); -		return 100000; -	case 0x17: -	case 0x1c:		/* Atom CPUs */ -		return adjust_tjmax(c, id, dev); -	default: -		dev_warn(dev, "CPU (model=0x%x) is not supported yet," -			" using default TjMax of 100C.\n", c->x86_model); -		return 100000; -	} +	return adjust_tjmax(c, id, dev);  }  static void __devinit get_ucode_rev_on_cpu(void *edx) @@ -341,7 +326,7 @@ static int get_pkg_tjmax(unsigned int cpu, struct device *dev)  	err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);  	if (!err) {  		val = (eax >> 16) & 0xff; -		if (val > 80 && val < 120) +		if (val)  			return val * 1000;  	}  	dev_warn(dev, "Unable to read Pkg-TjMax from CPU:%u\n", cpu); diff --git a/drivers/hwmon/max6642.c b/drivers/hwmon/max6642.c index 0f9fc40379c..e855d3b0bd1 100644 --- a/drivers/hwmon/max6642.c +++ b/drivers/hwmon/max6642.c @@ -136,15 +136,29 @@ static int max6642_detect(struct i2c_client *client,  	if (man_id != 0x4D)  		return -ENODEV; +	/* sanity check */ +	if (i2c_smbus_read_byte_data(client, 0x04) != 0x4D +	    || i2c_smbus_read_byte_data(client, 0x06) != 0x4D +	    || i2c_smbus_read_byte_data(client, 0xff) != 0x4D) +		return -ENODEV; +  	/*  	 * We read the config and status register, the 4 lower bits in the  	 * config register should be zero and bit 5, 3, 1 and 0 should be  	 * zero in the status register.  	 */  	reg_config = i2c_smbus_read_byte_data(client, MAX6642_REG_R_CONFIG); +	if ((reg_config & 0x0f) != 0x00) +		return -ENODEV; + +	/* in between, another round of sanity checks */ +	if (i2c_smbus_read_byte_data(client, 0x04) != reg_config +	    || i2c_smbus_read_byte_data(client, 0x06) != reg_config +	    || i2c_smbus_read_byte_data(client, 0xff) != reg_config) +		return -ENODEV; +  	reg_status = i2c_smbus_read_byte_data(client, MAX6642_REG_R_STATUS); -	if (((reg_config & 0x0f) != 0x00) || -	    ((reg_status & 0x2b) != 0x00)) +	if ((reg_status & 0x2b) != 0x00)  		return -ENODEV;  	strlcpy(info->type, "max6642", I2C_NAME_SIZE); @@ -246,7 +260,7 @@ static SENSOR_DEVICE_ATTR_2(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,  			    set_temp_max, 0, MAX6642_REG_W_LOCAL_HIGH);  static SENSOR_DEVICE_ATTR_2(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,  			    set_temp_max, 1, MAX6642_REG_W_REMOTE_HIGH); -static SENSOR_DEVICE_ATTR(temp_fault, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);  static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);  static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); @@ -256,7 +270,7 @@ static struct attribute *max6642_attributes[] = {  	&sensor_dev_attr_temp1_max.dev_attr.attr,  	&sensor_dev_attr_temp2_max.dev_attr.attr, -	&sensor_dev_attr_temp_fault.dev_attr.attr, +	&sensor_dev_attr_temp2_fault.dev_attr.attr,  	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,  	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,  	NULL diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index f3698967edf..8755f5f3ad3 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -120,21 +120,17 @@ static void serport_ldisc_close(struct tty_struct *tty)   * 'interrupt' routine.   */ -static unsigned int serport_ldisc_receive(struct tty_struct *tty, -		const unsigned char *cp, char *fp, int count) +static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)  {  	struct serport *serport = (struct serport*) tty->disc_data;  	unsigned long flags;  	unsigned int ch_flags; -	int ret = 0;  	int i;  	spin_lock_irqsave(&serport->lock, flags); -	if (!test_bit(SERPORT_ACTIVE, &serport->flags)) { -		ret = -EINVAL; +	if (!test_bit(SERPORT_ACTIVE, &serport->flags))  		goto out; -	}  	for (i = 0; i < count; i++) {  		switch (fp[i]) { @@ -156,8 +152,6 @@ static unsigned int serport_ldisc_receive(struct tty_struct *tty,  out:  	spin_unlock_irqrestore(&serport->lock, flags); - -	return ret == 0 ? count : ret;  }  /* diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 1d44d470897..86a5c4f7775 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -674,7 +674,7 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,   *	cflags	buffer containing error flags for received characters (ignored)   *	count	number of received characters   */ -static unsigned int +static void  gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,  		    char *cflags, int count)  { @@ -683,12 +683,12 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,  	struct inbuf_t *inbuf;  	if (!cs) -		return -ENODEV; +		return;  	inbuf = cs->inbuf;  	if (!inbuf) {  		dev_err(cs->dev, "%s: no inbuf\n", __func__);  		cs_put(cs); -		return -EINVAL; +		return;  	}  	tail = inbuf->tail; @@ -725,8 +725,6 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,  	gig_dbg(DEBUG_INTR, "%s-->BH", __func__);  	gigaset_schedule_event(cs);  	cs_put(cs); - -	return count;  }  /* diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index 1a05fe08e2c..f91f82eabda 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c @@ -747,8 +747,8 @@ static void st_tty_close(struct tty_struct *tty)  	pr_debug("%s: done ", __func__);  } -static unsigned int st_tty_receive(struct tty_struct *tty, -		const unsigned char *data, char *tty_flags, int count) +static void st_tty_receive(struct tty_struct *tty, const unsigned char *data, +			   char *tty_flags, int count)  {  #ifdef VERBOSE  	print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE, @@ -761,8 +761,6 @@ static unsigned int st_tty_receive(struct tty_struct *tty,  	 */  	st_recv(tty->disc_data, data, count);  	pr_debug("done %s", __func__); - -	return count;  }  /* wake-up function called in from the TTY layer diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 5f25889e27e..44b28b2d700 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -185,7 +185,7 @@ static int max_interrupt_work = 10;  static int nopnp;  #endif -static int el3_common_init(struct net_device *dev); +static int __devinit el3_common_init(struct net_device *dev);  static void el3_common_remove(struct net_device *dev);  static ushort id_read_eeprom(int index);  static ushort read_eeprom(int ioaddr, int index); @@ -395,7 +395,7 @@ static struct isa_driver el3_isa_driver = {  static int isa_registered;  #ifdef CONFIG_PNP -static const struct pnp_device_id el3_pnp_ids[] __devinitconst = { +static struct pnp_device_id el3_pnp_ids[] = {  	{ .id = "TCM5090" }, /* 3Com Etherlink III (TP) */  	{ .id = "TCM5091" }, /* 3Com Etherlink III */  	{ .id = "TCM5094" }, /* 3Com Etherlink III (combo) */ @@ -478,7 +478,7 @@ static int pnp_registered;  #endif /* CONFIG_PNP */  #ifdef CONFIG_EISA -static const struct eisa_device_id el3_eisa_ids[] __devinitconst = { +static struct eisa_device_id el3_eisa_ids[] = {  		{ "TCM5090" },  		{ "TCM5091" },  		{ "TCM5092" }, @@ -508,7 +508,7 @@ static int eisa_registered;  #ifdef CONFIG_MCA  static int el3_mca_probe(struct device *dev); -static const short el3_mca_adapter_ids[] __devinitconst = { +static short el3_mca_adapter_ids[] __initdata = {  		0x627c,  		0x627d,  		0x62db, @@ -517,7 +517,7 @@ static const short el3_mca_adapter_ids[] __devinitconst = {  		0x0000  }; -static const char *const el3_mca_adapter_names[] __devinitconst = { +static char *el3_mca_adapter_names[] __initdata = {  		"3Com 3c529 EtherLink III (10base2)",  		"3Com 3c529 EtherLink III (10baseT)",  		"3Com 3c529 EtherLink III (test mode)", @@ -601,7 +601,7 @@ static void el3_common_remove (struct net_device *dev)  }  #ifdef CONFIG_MCA -static int __devinit el3_mca_probe(struct device *device) +static int __init el3_mca_probe(struct device *device)  {  	/* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch,  	 * heavily modified by Chris Beauregard @@ -671,7 +671,7 @@ static int __devinit el3_mca_probe(struct device *device)  #endif /* CONFIG_MCA */  #ifdef CONFIG_EISA -static int __devinit el3_eisa_probe (struct device *device) +static int __init el3_eisa_probe (struct device *device)  {  	short i;  	int ioaddr, irq, if_port; diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 99f43d27544..8cc22568ebd 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -901,14 +901,14 @@ static const struct dev_pm_ops vortex_pm_ops = {  #endif /* !CONFIG_PM */  #ifdef CONFIG_EISA -static const struct eisa_device_id vortex_eisa_ids[] __devinitconst = { +static struct eisa_device_id vortex_eisa_ids[] = {  	{ "TCM5920", CH_3C592 },  	{ "TCM5970", CH_3C597 },  	{ "" }  };  MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids); -static int __devinit vortex_eisa_probe(struct device *device) +static int __init vortex_eisa_probe(struct device *device)  {  	void __iomem *ioaddr;  	struct eisa_device *edev; diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 73c7e03617e..3df0c0f8b8b 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -167,8 +167,8 @@ static inline void debugfs_tx(struct ser_device *ser, const u8 *data, int size)  #endif -static unsigned int ldisc_receive(struct tty_struct *tty, -		const u8 *data, char *flags, int count) +static void ldisc_receive(struct tty_struct *tty, const u8 *data, +			char *flags, int count)  {  	struct sk_buff *skb = NULL;  	struct ser_device *ser; @@ -215,8 +215,6 @@ static unsigned int ldisc_receive(struct tty_struct *tty,  	} else  		++ser->dev->stats.rx_dropped;  	update_tty_status(ser); - -	return count;  }  static int handle_tx(struct ser_device *ser) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index d4990568bae..17678117ed6 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -923,7 +923,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)  	mem_size = resource_size(mem);  	if (!request_mem_region(mem->start, mem_size, pdev->name)) {  		err = -EBUSY; -		goto failed_req; +		goto failed_get;  	}  	base = ioremap(mem->start, mem_size); @@ -977,9 +977,8 @@ static int __devinit flexcan_probe(struct platform_device *pdev)  	iounmap(base);   failed_map:  	release_mem_region(mem->start, mem_size); - failed_req: -	clk_put(clk);   failed_get: +	clk_put(clk);   failed_clock:  	return err;  } diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index 75622d54581..1b49df6b247 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -425,17 +425,16 @@ static void slc_setup(struct net_device *dev)   * in parallel   */ -static unsigned int slcan_receive_buf(struct tty_struct *tty, +static void slcan_receive_buf(struct tty_struct *tty,  			      const unsigned char *cp, char *fp, int count)  {  	struct slcan *sl = (struct slcan *) tty->disc_data; -	int bytes = count;  	if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev)) -		return -ENODEV; +		return;  	/* Read the characters out of the buffer */ -	while (bytes--) { +	while (count--) {  		if (fp && *fp++) {  			if (!test_and_set_bit(SLF_ERROR, &sl->flags))  				sl->dev->stats.rx_errors++; @@ -444,8 +443,6 @@ static unsigned int slcan_receive_buf(struct tty_struct *tty,  		}  		slcan_unesc(sl, *cp++);  	} - -	return count;  }  /************************************ diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 29a4f06fbfc..dcc4a170b0f 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -1781,8 +1781,8 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)  	ndev = alloc_etherdev(sizeof(struct emac_priv));  	if (!ndev) {  		dev_err(&pdev->dev, "error allocating net_device\n"); -		clk_put(emac_clk); -		return -ENOMEM; +		rc = -ENOMEM; +		goto free_clk;  	}  	platform_set_drvdata(pdev, ndev); @@ -1796,7 +1796,8 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)  	pdata = pdev->dev.platform_data;  	if (!pdata) {  		dev_err(&pdev->dev, "no platform data\n"); -		return -ENODEV; +		rc = -ENODEV; +		goto probe_quit;  	}  	/* MAC addr and PHY mask , RMII enable info from platform_data */ @@ -1929,8 +1930,9 @@ no_dma:  	iounmap(priv->remap_addr);  probe_quit: -	clk_put(emac_clk);  	free_netdev(ndev); +free_clk: +	clk_put(emac_clk);  	return rc;  } diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 17654059922..8b0084d17c8 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -331,18 +331,18 @@ static struct {                           "DE422",\                           ""} -static const char* const depca_signature[] __devinitconst = DEPCA_SIGNATURE; +static char* __initdata depca_signature[] = DEPCA_SIGNATURE;  enum depca_type {  	DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown  }; -static const char depca_string[] = "depca"; +static char depca_string[] = "depca";  static int depca_device_remove (struct device *device);  #ifdef CONFIG_EISA -static const struct eisa_device_id depca_eisa_ids[] __devinitconst = { +static struct eisa_device_id depca_eisa_ids[] = {  	{ "DEC4220", de422 },  	{ "" }  }; @@ -367,19 +367,19 @@ static struct eisa_driver depca_eisa_driver = {  #define DE210_ID 0x628d  #define DE212_ID 0x6def -static const short depca_mca_adapter_ids[] __devinitconst = { +static short depca_mca_adapter_ids[] = {  	DE210_ID,  	DE212_ID,  	0x0000  }; -static const char *depca_mca_adapter_name[] = { +static char *depca_mca_adapter_name[] = {  	"DEC EtherWORKS MC Adapter (DE210)",  	"DEC EtherWORKS MC Adapter (DE212)",  	NULL  }; -static const enum depca_type depca_mca_adapter_type[] = { +static enum depca_type depca_mca_adapter_type[] = {  	de210,  	de212,  	0 @@ -541,9 +541,10 @@ static void SetMulticastFilter(struct net_device *dev);  static int load_packet(struct net_device *dev, struct sk_buff *skb);  static void depca_dbg_open(struct net_device *dev); -static const u_char de1xx_irq[] __devinitconst = { 2, 3, 4, 5, 7, 9, 0 }; -static const u_char de2xx_irq[] __devinitconst = { 5, 9, 10, 11, 15, 0 }; -static const u_char de422_irq[] __devinitconst = { 5, 9, 10, 11, 0 }; +static u_char de1xx_irq[] __initdata = { 2, 3, 4, 5, 7, 9, 0 }; +static u_char de2xx_irq[] __initdata = { 5, 9, 10, 11, 15, 0 }; +static u_char de422_irq[] __initdata = { 5, 9, 10, 11, 0 }; +static u_char *depca_irq;  static int irq;  static int io; @@ -579,7 +580,7 @@ static const struct net_device_ops depca_netdev_ops = {  	.ndo_validate_addr	= eth_validate_addr,  }; -static int __devinit depca_hw_init (struct net_device *dev, struct device *device) +static int __init depca_hw_init (struct net_device *dev, struct device *device)  {  	struct depca_private *lp;  	int i, j, offset, netRAM, mem_len, status = 0; @@ -747,7 +748,6 @@ static int __devinit depca_hw_init (struct net_device *dev, struct device *devic  	if (dev->irq < 2) {  		unsigned char irqnum;  		unsigned long irq_mask, delay; -		const u_char *depca_irq;  		irq_mask = probe_irq_on(); @@ -770,7 +770,6 @@ static int __devinit depca_hw_init (struct net_device *dev, struct device *devic  			break;  		default: -			depca_irq = NULL;  			break;	/* Not reached */  		} @@ -1303,7 +1302,7 @@ static void SetMulticastFilter(struct net_device *dev)  	}  } -static int __devinit depca_common_init (u_long ioaddr, struct net_device **devp) +static int __init depca_common_init (u_long ioaddr, struct net_device **devp)  {  	int status = 0; @@ -1334,7 +1333,7 @@ static int __devinit depca_common_init (u_long ioaddr, struct net_device **devp)  /*  ** Microchannel bus I/O device probe  */ -static int __devinit depca_mca_probe(struct device *device) +static int __init depca_mca_probe(struct device *device)  {  	unsigned char pos[2];  	unsigned char where; @@ -1458,7 +1457,7 @@ static int __devinit depca_mca_probe(struct device *device)  ** ISA bus I/O device probe  */ -static void __devinit depca_platform_probe (void) +static void __init depca_platform_probe (void)  {  	int i;  	struct platform_device *pldev; @@ -1498,7 +1497,7 @@ static void __devinit depca_platform_probe (void)  	}  } -static enum depca_type __devinit depca_shmem_probe (ulong *mem_start) +static enum depca_type __init depca_shmem_probe (ulong *mem_start)  {  	u_long mem_base[] = DEPCA_RAM_BASE_ADDRESSES;  	enum depca_type adapter = unknown; @@ -1559,7 +1558,7 @@ static int __devinit depca_isa_probe (struct platform_device *device)  */  #ifdef CONFIG_EISA -static int __devinit depca_eisa_probe (struct device *device) +static int __init depca_eisa_probe (struct device *device)  {  	enum depca_type adapter = unknown;  	struct eisa_device *edev; @@ -1630,7 +1629,7 @@ static int __devexit depca_device_remove (struct device *device)  ** and Boot (readb) ROM. This will also give us a clue to the network RAM  ** base address.  */ -static int __devinit DepcaSignature(char *name, u_long base_addr) +static int __init DepcaSignature(char *name, u_long base_addr)  {  	u_int i, j, k;  	void __iomem *ptr; diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index fbaff3584bd..ee597e676ee 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -1157,9 +1157,6 @@ dm9000_open(struct net_device *dev)  	irqflags |= IRQF_SHARED; -	if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev)) -		return -EAGAIN; -  	/* GPIO0 on pre-activate PHY, Reg 1F is not set by reset */  	iow(db, DM9000_GPR, 0);	/* REG_1F bit0 activate phyxcer */  	mdelay(1); /* delay needs by DM9000B */ @@ -1168,6 +1165,9 @@ dm9000_open(struct net_device *dev)  	dm9000_reset(db);  	dm9000_init_dm9000(dev); +	if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev)) +		return -EAGAIN; +  	/* Init driver variable */  	db->dbug_cnt = 0; diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 992089639ea..3e5d0b6b651 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -456,7 +456,7 @@ out:   * a block of 6pack data has been received, which can now be decapsulated   * and sent on to some IP layer for further processing.   */ -static unsigned int sixpack_receive_buf(struct tty_struct *tty, +static void sixpack_receive_buf(struct tty_struct *tty,  	const unsigned char *cp, char *fp, int count)  {  	struct sixpack *sp; @@ -464,11 +464,11 @@ static unsigned int sixpack_receive_buf(struct tty_struct *tty,  	int count1;  	if (!count) -		return 0; +		return;  	sp = sp_get(tty);  	if (!sp) -		return -ENODEV; +		return;  	memcpy(buf, cp, count < sizeof(buf) ? count : sizeof(buf)); @@ -487,8 +487,6 @@ static unsigned int sixpack_receive_buf(struct tty_struct *tty,  	sp_put(sp);  	tty_unthrottle(tty); - -	return count1;  }  /* diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 0e4f2353114..4c628393c8b 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -923,14 +923,13 @@ static long mkiss_compat_ioctl(struct tty_struct *tty, struct file *file,   * a block of data has been received, which can now be decapsulated   * and sent on to the AX.25 layer for further processing.   */ -static unsigned int mkiss_receive_buf(struct tty_struct *tty, -		const unsigned char *cp, char *fp, int count) +static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp, +	char *fp, int count)  {  	struct mkiss *ax = mkiss_get(tty); -	int bytes = count;  	if (!ax) -		return -ENODEV; +		return;  	/*  	 * Argh! mtu change time! - costs us the packet part received @@ -940,7 +939,7 @@ static unsigned int mkiss_receive_buf(struct tty_struct *tty,  		ax_changedmtu(ax);  	/* Read the characters out of the buffer */ -	while (bytes--) { +	while (count--) {  		if (fp != NULL && *fp++) {  			if (!test_and_set_bit(AXF_ERROR, &ax->flags))  				ax->dev->stats.rx_errors++; @@ -953,8 +952,6 @@ static unsigned int mkiss_receive_buf(struct tty_struct *tty,  	mkiss_put(ax);  	tty_unthrottle(tty); - -	return count;  }  /* diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index c52a1df5d92..8e10d2f6a5a 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -188,14 +188,14 @@ struct hp100_private {   *  variables   */  #ifdef CONFIG_ISA -static const char *const hp100_isa_tbl[] __devinitconst = { +static const char *hp100_isa_tbl[] = {  	"HWPF150", /* HP J2573 rev A */  	"HWP1950", /* HP J2573 */  };  #endif  #ifdef CONFIG_EISA -static const struct eisa_device_id hp100_eisa_tbl[] __devinitconst = { +static struct eisa_device_id hp100_eisa_tbl[] = {  	{ "HWPF180" }, /* HP J2577 rev A */  	{ "HWP1920" }, /* HP 27248B */  	{ "HWP1940" }, /* HP J2577 */ @@ -336,7 +336,7 @@ static __devinit const char *hp100_read_id(int ioaddr)  }  #ifdef CONFIG_ISA -static __devinit int hp100_isa_probe1(struct net_device *dev, int ioaddr) +static __init int hp100_isa_probe1(struct net_device *dev, int ioaddr)  {  	const char *sig;  	int i; @@ -372,7 +372,7 @@ static __devinit int hp100_isa_probe1(struct net_device *dev, int ioaddr)   * EISA and PCI are handled by device infrastructure.   */ -static int  __devinit hp100_isa_probe(struct net_device *dev, int addr) +static int  __init hp100_isa_probe(struct net_device *dev, int addr)  {  	int err = -ENODEV; @@ -396,7 +396,7 @@ static int  __devinit hp100_isa_probe(struct net_device *dev, int addr)  #endif /* CONFIG_ISA */  #if !defined(MODULE) && defined(CONFIG_ISA) -struct net_device * __devinit hp100_probe(int unit) +struct net_device * __init hp100_probe(int unit)  {  	struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private));  	int err; @@ -2843,7 +2843,7 @@ static void cleanup_dev(struct net_device *d)  }  #ifdef CONFIG_EISA -static int __devinit hp100_eisa_probe (struct device *gendev) +static int __init hp100_eisa_probe (struct device *gendev)  {  	struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private));  	struct eisa_device *edev = to_eisa_device(gendev); diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c index 136d7544cc3..a7d6cad3295 100644 --- a/drivers/net/ibmlana.c +++ b/drivers/net/ibmlana.c @@ -895,12 +895,12 @@ static int ibmlana_irq;  static int ibmlana_io;  static int startslot;		/* counts through slots when probing multiple devices */ -static const short ibmlana_adapter_ids[] __devinitconst = { +static short ibmlana_adapter_ids[] __initdata = {  	IBM_LANA_ID,  	0x0000  }; -static const char *const ibmlana_adapter_names[] __devinitconst = { +static char *ibmlana_adapter_names[] __devinitdata = {  	"IBM LAN Adapter/A",  	NULL  }; diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 035861d8acb..3352b2443e5 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -216,23 +216,23 @@ static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t   * usbserial:	urb-complete-interrupt / softint   */ -static unsigned int irtty_receive_buf(struct tty_struct *tty, -		const unsigned char *cp, char *fp, int count) +static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, +			      char *fp, int count)   {  	struct sir_dev *dev;  	struct sirtty_cb *priv = tty->disc_data;  	int	i; -	IRDA_ASSERT(priv != NULL, return -ENODEV;); -	IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -EINVAL;); +	IRDA_ASSERT(priv != NULL, return;); +	IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);  	if (unlikely(count==0))		/* yes, this happens */ -		return 0; +		return;  	dev = priv->dev;  	if (!dev) {  		IRDA_WARNING("%s(), not ready yet!\n", __func__); -		return -ENODEV; +		return;  	}  	for (i = 0; i < count; i++) { @@ -242,13 +242,11 @@ static unsigned int irtty_receive_buf(struct tty_struct *tty,   		if (fp && *fp++) {   			IRDA_DEBUG(0, "Framing or parity error!\n");  			sirdev_receive(dev, NULL, 0);	/* notify sir_dev (updating stats) */ -			return -EINVAL; +			return;   		}  	}  	sirdev_receive(dev, cp, count); - -	return count;  }  /* diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index 69b5707db36..8800e1fe412 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c @@ -222,19 +222,19 @@ static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 s  static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self);  /* Probing */ -static int smsc_ircc_look_for_chips(void); -static const struct smsc_chip * smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type); -static int smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfg_base, char *type); -static int smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); -static int smsc_superio_fdc(unsigned short cfg_base); -static int smsc_superio_lpc(unsigned short cfg_base); +static int __init smsc_ircc_look_for_chips(void); +static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type); +static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfg_base, char *type); +static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); +static int __init smsc_superio_fdc(unsigned short cfg_base); +static int __init smsc_superio_lpc(unsigned short cfg_base);  #ifdef CONFIG_PCI -static int preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf); -static int preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); -static void preconfigure_ali_port(struct pci_dev *dev, +static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf); +static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); +static void __init preconfigure_ali_port(struct pci_dev *dev,  					 unsigned short port); -static int preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); -static int smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, +static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); +static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,  						    unsigned short ircc_fir,  						    unsigned short ircc_sir,  						    unsigned char ircc_dma, @@ -366,7 +366,7 @@ static inline void register_bank(int iobase, int bank)  }  /* PNP hotplug support */ -static const struct pnp_device_id smsc_ircc_pnp_table[] __devinitconst = { +static const struct pnp_device_id smsc_ircc_pnp_table[] = {  	{ .id = "SMCf010", .driver_data = 0 },  	/* and presumably others */  	{ } @@ -515,7 +515,7 @@ static const struct net_device_ops smsc_ircc_netdev_ops = {   *    Try to open driver instance   *   */ -static int __devinit smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq) +static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)  {  	struct smsc_ircc_cb *self;  	struct net_device *dev; @@ -2273,7 +2273,7 @@ static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned sho  } -static int __devinit smsc_access(unsigned short cfg_base, unsigned char reg) +static int __init smsc_access(unsigned short cfg_base, unsigned char reg)  {  	IRDA_DEBUG(1, "%s\n", __func__); @@ -2281,7 +2281,7 @@ static int __devinit smsc_access(unsigned short cfg_base, unsigned char reg)  	return inb(cfg_base) != reg ? -1 : 0;  } -static const struct smsc_chip * __devinit smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type) +static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type)  {  	u8 devid, xdevid, rev; @@ -2406,7 +2406,7 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)  #ifdef CONFIG_PCI  #define PCIID_VENDOR_INTEL 0x8086  #define PCIID_VENDOR_ALI 0x10b9 -static const struct smsc_ircc_subsystem_configuration subsystem_configurations[] __devinitconst = { +static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __initdata = {  	/*  	 * Subsystems needing entries:  	 * 0x10b9:0x1533 0x103c:0x0850 HP nx9010 family @@ -2532,7 +2532,7 @@ static const struct smsc_ircc_subsystem_configuration subsystem_configurations[]   * (FIR port, SIR port, FIR DMA, FIR IRQ)   * through the chip configuration port.   */ -static int __devinit preconfigure_smsc_chip(struct +static int __init preconfigure_smsc_chip(struct  					 smsc_ircc_subsystem_configuration  					 *conf)  { @@ -2633,7 +2633,7 @@ static int __devinit preconfigure_smsc_chip(struct   * or Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge.   * They all work the same way!   */ -static int __devinit preconfigure_through_82801(struct pci_dev *dev, +static int __init preconfigure_through_82801(struct pci_dev *dev,  					     struct  					     smsc_ircc_subsystem_configuration  					     *conf) @@ -2786,7 +2786,7 @@ static int __devinit preconfigure_through_82801(struct pci_dev *dev,   * This is based on reverse-engineering since ALi does not   * provide any data sheet for the 1533 chip.   */ -static void __devinit preconfigure_ali_port(struct pci_dev *dev, +static void __init preconfigure_ali_port(struct pci_dev *dev,  					 unsigned short port)  {  	unsigned char reg; @@ -2824,7 +2824,7 @@ static void __devinit preconfigure_ali_port(struct pci_dev *dev,  	IRDA_MESSAGE("Activated ALi 1533 ISA bridge port 0x%04x.\n", port);  } -static int __devinit preconfigure_through_ali(struct pci_dev *dev, +static int __init preconfigure_through_ali(struct pci_dev *dev,  					   struct  					   smsc_ircc_subsystem_configuration  					   *conf) @@ -2837,7 +2837,7 @@ static int __devinit preconfigure_through_ali(struct pci_dev *dev,  	return preconfigure_smsc_chip(conf);  } -static int __devinit smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, +static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,  						    unsigned short ircc_fir,  						    unsigned short ircc_sir,  						    unsigned char ircc_dma, @@ -2849,7 +2849,7 @@ static int __devinit smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,  	int ret = 0;  	for_each_pci_dev(dev) { -		const struct smsc_ircc_subsystem_configuration *conf; +		struct smsc_ircc_subsystem_configuration *conf;  		/*  		 * Cache the subsystem vendor/device: diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c index 4d40626b3bf..fc12ac0d9f2 100644 --- a/drivers/net/ks8842.c +++ b/drivers/net/ks8842.c @@ -661,7 +661,7 @@ static void ks8842_rx_frame(struct net_device *netdev,  	/* check the status */  	if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) { -		struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev, len); +		struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev, len + 3);  		if (skb) { diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c index e8984b0ca52..243ed2aee88 100644 --- a/drivers/net/ne3210.c +++ b/drivers/net/ne3210.c @@ -80,20 +80,17 @@ static void ne3210_block_output(struct net_device *dev, int count, const unsigne  #define NE3210_DEBUG	0x0 -static const unsigned char irq_map[] __devinitconst = -	{ 15, 12, 11, 10, 9, 7, 5, 3 }; -static const unsigned int shmem_map[] __devinitconst = -	{ 0xff0, 0xfe0, 0xfff0, 0xd8, 0xffe0, 0xffc0, 0xd0, 0x0 }; -static const char *const ifmap[] __devinitconst = -	{ "UTP", "?", "BNC", "AUI" }; -static const int ifmap_val[] __devinitconst = { +static unsigned char irq_map[] __initdata = {15, 12, 11, 10, 9, 7, 5, 3}; +static unsigned int shmem_map[] __initdata = {0xff0, 0xfe0, 0xfff0, 0xd8, 0xffe0, 0xffc0, 0xd0, 0x0}; +static const char *ifmap[] __initdata = {"UTP", "?", "BNC", "AUI"}; +static int ifmap_val[] __initdata = {  		IF_PORT_10BASET,  		IF_PORT_UNKNOWN,  		IF_PORT_10BASE2,  		IF_PORT_AUI,  }; -static int __devinit ne3210_eisa_probe (struct device *device) +static int __init ne3210_eisa_probe (struct device *device)  {  	unsigned long ioaddr, phys_mem;  	int i, retval, port_index; @@ -316,7 +313,7 @@ static void ne3210_block_output(struct net_device *dev, int count,  	memcpy_toio(shmem, buf, count);  } -static const struct eisa_device_id ne3210_ids[] __devinitconst = { +static struct eisa_device_id ne3210_ids[] = {  	{ "EGL0101" },  	{ "NVL1801" },  	{ "" }, diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 53872d7d738..a1b82c9c67d 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -340,7 +340,7 @@ ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)  }  /* May sleep, don't call from interrupt level or with interrupts disabled */ -static unsigned int +static void  ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,  		  char *cflags, int count)  { @@ -348,7 +348,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,  	unsigned long flags;  	if (!ap) -		return -ENODEV; +		return;  	spin_lock_irqsave(&ap->recv_lock, flags);  	ppp_async_input(ap, buf, cflags, count);  	spin_unlock_irqrestore(&ap->recv_lock, flags); @@ -356,8 +356,6 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,  		tasklet_schedule(&ap->tsk);  	ap_put(ap);  	tty_unthrottle(tty); - -	return count;  }  static void diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 0815790a5cf..2573f525f11 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -381,7 +381,7 @@ ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait)  }  /* May sleep, don't call from interrupt level or with interrupts disabled */ -static unsigned int +static void  ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,  		  char *cflags, int count)  { @@ -389,7 +389,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,  	unsigned long flags;  	if (!ap) -		return -ENODEV; +		return;  	spin_lock_irqsave(&ap->recv_lock, flags);  	ppp_sync_input(ap, buf, cflags, count);  	spin_unlock_irqrestore(&ap->recv_lock, flags); @@ -397,8 +397,6 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,  		tasklet_schedule(&ap->tsk);  	sp_put(ap);  	tty_unthrottle(tty); - -	return count;  }  static void diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 584809c656d..8ec1a9a0bb9 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -670,17 +670,16 @@ static void sl_setup(struct net_device *dev)   * in parallel   */ -static unsigned int slip_receive_buf(struct tty_struct *tty, -		const unsigned char *cp, char *fp, int count) +static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, +							char *fp, int count)  {  	struct slip *sl = tty->disc_data; -	int bytes = count;  	if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev)) -		return -ENODEV; +		return;  	/* Read the characters out of the buffer */ -	while (bytes--) { +	while (count--) {  		if (fp && *fp++) {  			if (!test_and_set_bit(SLF_ERROR, &sl->flags))  				sl->dev->stats.rx_errors++; @@ -694,8 +693,6 @@ static unsigned int slip_receive_buf(struct tty_struct *tty,  #endif  			slip_unesc(sl, *cp++);  	} - -	return count;  }  /************************************ diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c index 0f29f261fcf..d07c39cb4da 100644 --- a/drivers/net/smc-mca.c +++ b/drivers/net/smc-mca.c @@ -156,7 +156,7 @@ static const struct {     { 14, 15 }  }; -static const short smc_mca_adapter_ids[] __devinitconst = { +static short smc_mca_adapter_ids[] __initdata = {  	0x61c8,  	0x61c9,  	0x6fc0, @@ -168,7 +168,7 @@ static const short smc_mca_adapter_ids[] __devinitconst = {  	0x0000  }; -static const char *const smc_mca_adapter_names[] __devinitconst = { +static char *smc_mca_adapter_names[] __initdata = {  	"SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)",  	"SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)",  	"WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)", @@ -199,7 +199,7 @@ static const struct net_device_ops ultramca_netdev_ops = {  #endif  }; -static int __devinit ultramca_probe(struct device *gen_dev) +static int __init ultramca_probe(struct device *gen_dev)  {  	unsigned short ioaddr;  	struct net_device *dev; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f4b01c638a3..a1f9f9eef37 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -5774,7 +5774,7 @@ static void tg3_skb_error_unmap(struct tg3_napi *tnapi,  			 dma_unmap_addr(txb, mapping),  			 skb_headlen(skb),  			 PCI_DMA_TODEVICE); -	for (i = 0; i <= last; i++) { +	for (i = 0; i < last; i++) {  		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];  		entry = NEXT_TX(entry); diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c index 1313aa1315f..2bedc0ace81 100644 --- a/drivers/net/tokenring/madgemc.c +++ b/drivers/net/tokenring/madgemc.c @@ -727,7 +727,7 @@ static int __devexit madgemc_remove(struct device *device)  	return 0;  } -static const short madgemc_adapter_ids[] __devinitconst = { +static short madgemc_adapter_ids[] __initdata = {  	0x002d,  	0x0000  }; diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 45144d5bd11..efaa1d69b72 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -1995,7 +1995,7 @@ SetMulticastFilter(struct net_device *dev)  static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST; -static int __devinit de4x5_eisa_probe (struct device *gendev) +static int __init de4x5_eisa_probe (struct device *gendev)  {  	struct eisa_device *edev;  	u_long iobase; @@ -2097,7 +2097,7 @@ static int __devexit de4x5_eisa_remove (struct device *device)  	return 0;  } -static const struct eisa_device_id de4x5_eisa_ids[] __devinitconst = { +static struct eisa_device_id de4x5_eisa_ids[] = {          { "DEC4250", 0 },	/* 0 is the board name index... */          { "" }  }; diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index d7221c4a5dc..8056f8a27c6 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -495,7 +495,7 @@ static void catc_ctrl_run(struct catc *catc)  	if (!q->dir && q->buf && q->len)  		memcpy(catc->ctrl_buf, q->buf, q->len); -	if ((status = usb_submit_urb(catc->ctrl_urb, GFP_KERNEL))) +	if ((status = usb_submit_urb(catc->ctrl_urb, GFP_ATOMIC)))  		err("submit(ctrl_urb) status %d", status);  } diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index cdd3ae48610..f33ca6aa29e 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -54,7 +54,7 @@  #include <linux/usb/usbnet.h>  #include <linux/usb/cdc.h> -#define	DRIVER_VERSION				"24-May-2011" +#define	DRIVER_VERSION				"01-June-2011"  /* CDC NCM subclass 3.2.1 */  #define USB_CDC_NCM_NDP16_LENGTH_MIN		0x10 @@ -1234,6 +1234,7 @@ static struct usb_driver cdc_ncm_driver = {  	.disconnect = cdc_ncm_disconnect,  	.suspend = usbnet_suspend,  	.resume = usbnet_resume, +	.reset_resume =	usbnet_resume,  	.supports_autosuspend = 1,  }; diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 40398bf7d03..24297b274cd 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -517,18 +517,17 @@ static int x25_asy_close(struct net_device *dev)   * and sent on to some IP layer for further processing.   */ -static unsigned int x25_asy_receive_buf(struct tty_struct *tty, +static void x25_asy_receive_buf(struct tty_struct *tty,  				const unsigned char *cp, char *fp, int count)  {  	struct x25_asy *sl = tty->disc_data; -	int bytes = count;  	if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))  		return;  	/* Read the characters out of the buffer */ -	while (bytes--) { +	while (count--) {  		if (fp && *fp++) {  			if (!test_and_set_bit(SLF_ERROR, &sl->flags))  				sl->dev->stats.rx_errors++; @@ -537,8 +536,6 @@ static unsigned int x25_asy_receive_buf(struct tty_struct *tty,  		}  		x25_asy_unesc(sl, *cp++);  	} - -	return count;  }  /* diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index d9ff8413ab9..d9c08c619a3 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -26,7 +26,6 @@ config ATH9K  config ATH9K_PCI  	bool "Atheros ath9k PCI/PCIe bus support"  	depends on ATH9K && PCI -	default PCI  	---help---  	  This option enables the PCI bus support in ath9k. diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 015d9743993..2d4c0910295 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -829,7 +829,7 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)  	if (AR_SREV_9271(ah)) {  		if (!ar9285_hw_cl_cal(ah, chan))  			return false; -	} else if (AR_SREV_9285_12_OR_LATER(ah)) { +	} else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {  		if (!ar9285_hw_clc(ah, chan))  			return false;  	} else { diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 0ca7635d066..ff8150e46f0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4645,10 +4645,16 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,  	case 1:  		break;  	case 2: -		scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; +		if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN) +			scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; +		else +			scaledPower = 0;  		break;  	case 3: -		scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; +		if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN) +			scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; +		else +			scaledPower = 0;  		break;  	} diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index eee23ecd118..892c48b1543 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1381,3 +1381,25 @@ void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)  		"==== BB update: done ====\n\n");  }  EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info); + +void ar9003_hw_disable_phy_restart(struct ath_hw *ah) +{ +	u32 val; + +	/* While receiving unsupported rate frame rx state machine +	 * gets into a state 0xb and if phy_restart happens in that +	 * state, BB would go hang. If RXSM is in 0xb state after +	 * first bb panic, ensure to disable the phy_restart. +	 */ +	if (!((MS(ah->bb_watchdog_last_status, +		  AR_PHY_WATCHDOG_RX_OFDM_SM) == 0xb) || +	    ah->bb_hang_rx_ofdm)) +		return; + +	ah->bb_hang_rx_ofdm = true; +	val = REG_READ(ah, AR_PHY_RESTART); +	val &= ~AR_PHY_RESTART_ENA; + +	REG_WRITE(ah, AR_PHY_RESTART, val); +} +EXPORT_SYMBOL(ar9003_hw_disable_phy_restart); diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 7856f0d4512..343fc9f946d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -524,10 +524,16 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,  	case 1:  		break;  	case 2: -		scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; +		if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN) +			scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; +		else +			scaledPower = 0;  		break;  	case 3: -		scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; +		if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN) +			scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; +		else +			scaledPower = 0;  		break;  	}  	scaledPower = max((u16)0, scaledPower); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 72543ce8f61..1be7c8bbef8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1555,9 +1555,12 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  	if (ah->btcoex_hw.enabled)  		ath9k_hw_btcoex_enable(ah); -	if (AR_SREV_9300_20_OR_LATER(ah)) +	if (AR_SREV_9300_20_OR_LATER(ah)) {  		ar9003_hw_bb_watchdog_config(ah); +		ar9003_hw_disable_phy_restart(ah); +	} +  	ath9k_hw_apply_gpio_override(ah);  	return 0; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 57435ce6279..4b157c53d1a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -842,6 +842,7 @@ struct ath_hw {  	u32 bb_watchdog_last_status;  	u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */ +	u8 bb_hang_rx_ofdm; /* true if bb hang due to rx_ofdm */  	unsigned int paprd_target_power;  	unsigned int paprd_training_power; @@ -990,6 +991,7 @@ void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);  void ar9003_hw_bb_watchdog_config(struct ath_hw *ah);  void ar9003_hw_bb_watchdog_read(struct ath_hw *ah);  void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); +void ar9003_hw_disable_phy_restart(struct ath_hw *ah);  void ar9003_paprd_enable(struct ath_hw *ah, bool val);  void ar9003_paprd_populate_single_table(struct ath_hw *ah,  					struct ath9k_hw_cal_data *caldata, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a198ee374b0..2ca351fe6d3 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -670,7 +670,8 @@ void ath9k_tasklet(unsigned long data)  	u32 status = sc->intrstatus;  	u32 rxmask; -	if (status & ATH9K_INT_FATAL) { +	if ((status & ATH9K_INT_FATAL) || +	    (status & ATH9K_INT_BB_WATCHDOG)) {  		ath_reset(sc, true);  		return;  	} @@ -737,6 +738,7 @@ irqreturn_t ath_isr(int irq, void *dev)  {  #define SCHED_INTR (				\  		ATH9K_INT_FATAL |		\ +		ATH9K_INT_BB_WATCHDOG |		\  		ATH9K_INT_RXORN |		\  		ATH9K_INT_RXEOL |		\  		ATH9K_INT_RX |			\ diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 17542214c93..ba7f36ab0a7 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -689,7 +689,8 @@ static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table,  	if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) {  		rate->flags |= IEEE80211_TX_RC_MCS; -		if (WLAN_RC_PHY_40(rate_table->info[rix].phy)) +		if (WLAN_RC_PHY_40(rate_table->info[rix].phy) && +		    conf_is_ht40(&txrc->hw->conf))  			rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;  		if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))  			rate->flags |= IEEE80211_TX_RC_SHORT_GI; diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 9ed65157bef..05960ddde24 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -3093,7 +3093,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,  	int freq;  	bool avoid = false;  	u8 length; -	u16 tmp, core, type, count, max, numb, last, cmd; +	u16 tmp, core, type, count, max, numb, last = 0, cmd;  	const u16 *table;  	bool phy6or5x; diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c index 7e5e85a017b..a7a4739880d 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c @@ -628,11 +628,11 @@ void iwl4965_rx_reply_rx(struct iwl_priv *priv,  	/* rx_status carries information about the packet to mac80211 */  	rx_status.mactime = le64_to_cpu(phy_res->timestamp); +	rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? +				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;  	rx_status.freq =  		ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),  							rx_status.band); -	rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? -				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;  	rx_status.rate_idx =  		iwl4965_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);  	rx_status.flag = 0; diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c index f5433c74b84..f9db25bb35c 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965.c @@ -1543,7 +1543,7 @@ static void iwl4965_temperature_calib(struct iwl_priv *priv)  	s32 temp;  	temp = iwl4965_hw_get_temperature(priv); -	if (temp < 0) +	if (IWL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(temp))  		return;  	if (priv->temperature != temp) { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index f8c710db6e6..fda6fe08cf9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -603,19 +603,27 @@ struct iwl_cfg iwl6050_2abg_cfg = {  	IWL_DEVICE_6050,  }; +#define IWL_DEVICE_6150						\ +	.fw_name_pre = IWL6050_FW_PRE,				\ +	.ucode_api_max = IWL6050_UCODE_API_MAX,			\ +	.ucode_api_min = IWL6050_UCODE_API_MIN,			\ +	.ops = &iwl6150_ops,					\ +	.eeprom_ver = EEPROM_6150_EEPROM_VERSION,		\ +	.eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION,	\ +	.base_params = &iwl6050_base_params,			\ +	.need_dc_calib = true,					\ +	.led_mode = IWL_LED_BLINK,				\ +	.internal_wimax_coex = true +  struct iwl_cfg iwl6150_bgn_cfg = {  	.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN", -	.fw_name_pre = IWL6050_FW_PRE, -	.ucode_api_max = IWL6050_UCODE_API_MAX, -	.ucode_api_min = IWL6050_UCODE_API_MIN, -	.eeprom_ver = EEPROM_6150_EEPROM_VERSION, -	.eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, -	.ops = &iwl6150_ops, -	.base_params = &iwl6050_base_params, +	IWL_DEVICE_6150,  	.ht_params = &iwl6000_ht_params, -	.need_dc_calib = true, -	.led_mode = IWL_LED_RF_STATE, -	.internal_wimax_coex = true, +}; + +struct iwl_cfg iwl6150_bg_cfg = { +	.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG", +	IWL_DEVICE_6150,  };  struct iwl_cfg iwl6000_3agn_cfg = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 11c6c1169e7..a662adcb2ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3831,11 +3831,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {  /* 6150 WiFi/WiMax Series */  	{IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0885, 0x1306, iwl6150_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)},  	{IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0885, 0x1326, iwl6150_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)},  	{IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0886, 0x1316, iwl6150_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)},  /* 1000 Series WiFi */  	{IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)}, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 2495fe7a58c..d1716844002 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -89,6 +89,7 @@ extern struct iwl_cfg iwl6000_3agn_cfg;  extern struct iwl_cfg iwl6050_2agn_cfg;  extern struct iwl_cfg iwl6050_2abg_cfg;  extern struct iwl_cfg iwl6150_bgn_cfg; +extern struct iwl_cfg iwl6150_bg_cfg;  extern struct iwl_cfg iwl1000_bgn_cfg;  extern struct iwl_cfg iwl1000_bg_cfg;  extern struct iwl_cfg iwl100_bgn_cfg; diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 84566db486d..71c8f3fccfa 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -994,6 +994,8 @@ static void lbs_submit_command(struct lbs_private *priv,  	cmd = cmdnode->cmdbuf;  	spin_lock_irqsave(&priv->driver_lock, flags); +	priv->seqnum++; +	cmd->seqnum = cpu_to_le16(priv->seqnum);  	priv->cur_cmd = cmdnode;  	spin_unlock_irqrestore(&priv->driver_lock, flags); @@ -1621,11 +1623,9 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,  	/* Copy the incoming command to the buffer */  	memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size); -	/* Set sequence number, clean result, move to buffer */ -	priv->seqnum++; +	/* Set command, clean result, move to buffer */  	cmdnode->cmdbuf->command = cpu_to_le16(command);  	cmdnode->cmdbuf->size    = cpu_to_le16(in_cmd_size); -	cmdnode->cmdbuf->seqnum  = cpu_to_le16(priv->seqnum);  	cmdnode->cmdbuf->result  = 0;  	lbs_deb_host("PREP_CMD: command 0x%04x\n", command); diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index a0e9bc5253e..4e97e90aa39 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h @@ -167,8 +167,8 @@  /* Rx unit register */  #define CARD_RX_UNIT_REG		0x63 -/* Event header Len*/ -#define MWIFIEX_EVENT_HEADER_LEN           8 +/* Event header len w/o 4 bytes of interface header */ +#define MWIFIEX_EVENT_HEADER_LEN           4  /* Max retry number of CMD53 write */  #define MAX_WRITE_IOMEM_RETRY		2 diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 9def1e5369a..b2f8b8fd4d2 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -166,7 +166,6 @@ config RT2800USB_RT35XX  config RT2800USB_RT53XX         bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)"         depends on EXPERIMENTAL -       default y         ---help---           This adds support for rt53xx wireless chipset family to the           rt2800pci driver. diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index a4095284543..89100e7c553 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -669,11 +669,6 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)  							 &rx_status,  							 (u8 *) pdesc, skb); -			pci_unmap_single(rtlpci->pdev, -					 *((dma_addr_t *) skb->cb), -					 rtlpci->rxbuffersize, -					 PCI_DMA_FROMDEVICE); -  			skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc,  							 false,  							 HW_DESC_RXPKT_LEN)); @@ -690,6 +685,21 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)  			hdr = rtl_get_hdr(skb);  			fc = rtl_get_fc(skb); +			/* try for new buffer - if allocation fails, drop +			 * frame and reuse old buffer +			 */ +			new_skb = dev_alloc_skb(rtlpci->rxbuffersize); +			if (unlikely(!new_skb)) { +				RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), +					 DBG_DMESG, +					 ("can't alloc skb for rx\n")); +				goto done; +			} +			pci_unmap_single(rtlpci->pdev, +					 *((dma_addr_t *) skb->cb), +					 rtlpci->rxbuffersize, +					 PCI_DMA_FROMDEVICE); +  			if (!stats.crc || !stats.hwerror) {  				memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,  				       sizeof(rx_status)); @@ -758,15 +768,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)  				rtl_lps_leave(hw);  			} -			new_skb = dev_alloc_skb(rtlpci->rxbuffersize); -			if (unlikely(!new_skb)) { -				RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), -					 DBG_DMESG, -					 ("can't alloc skb for rx\n")); -				goto done; -			}  			skb = new_skb; -			/*skb->dev = dev; */  			rtlpci->rx_ring[rx_queue_idx].rx_buf[rtlpci->  							     rx_ring @@ -1113,6 +1115,13 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw)  		rtlpci->rx_ring[rx_queue_idx].idx = 0; +		/* If amsdu_8k is disabled, set buffersize to 4096. This +		 * change will reduce memory fragmentation. +		 */ +		if (rtlpci->rxbuffersize > 4096 && +		    rtlpriv->rtlhal.disable_amsdu_8k) +			rtlpci->rxbuffersize = 4096; +  		for (i = 0; i < rtlpci->rxringcount; i++) {  			struct sk_buff *skb =  			    dev_alloc_skb(rtlpci->rxbuffersize); diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 1ab6c86aac4..c83fefb6662 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -1157,6 +1157,9 @@ struct conf_sched_scan_settings {  	/* time to wait on the channel for passive scans (in TUs) */  	u32 dwell_time_passive; +	/* time to wait on the channel for DFS scans (in TUs) */ +	u32 dwell_time_dfs; +  	/* number of probe requests to send on each channel in active scans */  	u8 num_probe_reqs; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index bc00e52f644..e6497dc669d 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -311,6 +311,7 @@ static struct conf_drv_settings default_conf = {  		.min_dwell_time_active = 8,  		.max_dwell_time_active = 30,  		.dwell_time_passive    = 100, +		.dwell_time_dfs        = 150,  		.num_probe_reqs        = 2,  		.rssi_threshold        = -90,  		.snr_threshold         = 0, diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index f37e5a39197..56f76abc754 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -331,16 +331,22 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,  	struct conf_sched_scan_settings *c = &wl->conf.sched_scan;  	int i, j;  	u32 flags; +	bool force_passive = !req->n_ssids;  	for (i = 0, j = start;  	     i < req->n_channels && j < MAX_CHANNELS_ALL_BANDS;  	     i++) {  		flags = req->channels[i]->flags; -		if (!(flags & IEEE80211_CHAN_DISABLED) && -		    ((flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive) && -		    ((flags & IEEE80211_CHAN_RADAR) == radar) && -		    (req->channels[i]->band == band)) { +		if (force_passive) +			flags |= IEEE80211_CHAN_PASSIVE_SCAN; + +		if ((req->channels[i]->band == band) && +		    !(flags & IEEE80211_CHAN_DISABLED) && +		    (!!(flags & IEEE80211_CHAN_RADAR) == radar) && +		    /* if radar is set, we ignore the passive flag */ +		    (radar || +		     !!(flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive)) {  			wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ",  				     req->channels[i]->band,  				     req->channels[i]->center_freq); @@ -350,7 +356,12 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,  			wl1271_debug(DEBUG_SCAN, "max_power %d",  				     req->channels[i]->max_power); -			if (flags & IEEE80211_CHAN_PASSIVE_SCAN) { +			if (flags & IEEE80211_CHAN_RADAR) { +				channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS; +				channels[j].passive_duration = +					cpu_to_le16(c->dwell_time_dfs); +			} +			else if (flags & IEEE80211_CHAN_PASSIVE_SCAN) {  				channels[j].passive_duration =  					cpu_to_le16(c->dwell_time_passive);  			} else { @@ -359,7 +370,7 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,  				channels[j].max_duration =  					cpu_to_le16(c->max_dwell_time_active);  			} -			channels[j].tx_power_att = req->channels[j]->max_power; +			channels[j].tx_power_att = req->channels[i]->max_power;  			channels[j].channel = req->channels[i]->hw_value;  			j++; @@ -386,7 +397,11 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,  		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,  						    IEEE80211_BAND_2GHZ,  						    false, false, idx); -	idx += cfg->active[0]; +	/* +	 * 5GHz channels always start at position 14, not immediately +	 * after the last 2.4GHz channel +	 */ +	idx = 14;  	cfg->passive[1] =  		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, @@ -394,22 +409,23 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,  						    false, true, idx);  	idx += cfg->passive[1]; -	cfg->active[1] = +	cfg->dfs =  		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,  						    IEEE80211_BAND_5GHZ, -						    false, false, 14); -	idx += cfg->active[1]; +						    true, true, idx); +	idx += cfg->dfs; -	cfg->dfs = +	cfg->active[1] =  		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,  						    IEEE80211_BAND_5GHZ, -						    true, false, idx); -	idx += cfg->dfs; +						    false, false, idx); +	idx += cfg->active[1];  	wl1271_debug(DEBUG_SCAN, "    2.4GHz: active %d passive %d",  		     cfg->active[0], cfg->passive[0]);  	wl1271_debug(DEBUG_SCAN, "    5GHz: active %d passive %d",  		     cfg->active[1], cfg->passive[1]); +	wl1271_debug(DEBUG_SCAN, "    DFS: %d", cfg->dfs);  	return idx;  } @@ -421,6 +437,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,  	struct wl1271_cmd_sched_scan_config *cfg = NULL;  	struct conf_sched_scan_settings *c = &wl->conf.sched_scan;  	int i, total_channels, ret; +	bool force_passive = !req->n_ssids;  	wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config"); @@ -444,7 +461,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,  	for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++)  		cfg->intervals[i] = cpu_to_le32(req->interval); -	if (req->ssids[0].ssid_len && req->ssids[0].ssid) { +	if (!force_passive && req->ssids[0].ssid_len && req->ssids[0].ssid) {  		cfg->filter_type = SCAN_SSID_FILTER_SPECIFIC;  		cfg->ssid_len = req->ssids[0].ssid_len;  		memcpy(cfg->ssid, req->ssids[0].ssid, @@ -461,7 +478,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,  		goto out;  	} -	if (cfg->active[0]) { +	if (!force_passive && cfg->active[0]) {  		ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid,  						 req->ssids[0].ssid_len,  						 ies->ie[IEEE80211_BAND_2GHZ], @@ -473,7 +490,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,  		}  	} -	if (cfg->active[1]) { +	if (!force_passive && cfg->active[1]) {  		ret = wl1271_cmd_build_probe_req(wl,  req->ssids[0].ssid,  						 req->ssids[0].ssid_len,  						 ies->ie[IEEE80211_BAND_5GHZ], diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h index c83319579ca..a0b6c5d67b0 100644 --- a/drivers/net/wireless/wl12xx/scan.h +++ b/drivers/net/wireless/wl12xx/scan.h @@ -137,6 +137,9 @@ enum {  	SCAN_BSS_TYPE_ANY,  }; +#define SCAN_CHANNEL_FLAGS_DFS		BIT(0) +#define SCAN_CHANNEL_FLAGS_DFS_ENABLED	BIT(1) +  struct conn_scan_ch_params {  	__le16 min_duration;  	__le16 max_duration; diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 0e819943b9e..631194d4982 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -1533,6 +1533,31 @@ static void __exit usb_exit(void)  module_init(usb_init);  module_exit(usb_exit); +static int zd_ep_regs_out_msg(struct usb_device *udev, void *data, int len, +			      int *actual_length, int timeout) +{ +	/* In USB 2.0 mode EP_REGS_OUT endpoint is interrupt type. However in +	 * USB 1.1 mode endpoint is bulk. Select correct type URB by endpoint +	 * descriptor. +	 */ +	struct usb_host_endpoint *ep; +	unsigned int pipe; + +	pipe = usb_sndintpipe(udev, EP_REGS_OUT); +	ep = usb_pipe_endpoint(udev, pipe); +	if (!ep) +		return -EINVAL; + +	if (usb_endpoint_xfer_int(&ep->desc)) { +		return usb_interrupt_msg(udev, pipe, data, len, +					 actual_length, timeout); +	} else { +		pipe = usb_sndbulkpipe(udev, EP_REGS_OUT); +		return usb_bulk_msg(udev, pipe, data, len, actual_length, +				    timeout); +	} +} +  static int usb_int_regs_length(unsigned int count)  {  	return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data); @@ -1648,15 +1673,14 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,  	udev = zd_usb_to_usbdev(usb);  	prepare_read_regs_int(usb); -	r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT), -			      req, req_len, &actual_req_len, 50 /* ms */); +	r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);  	if (r) {  		dev_dbg_f(zd_usb_dev(usb), -			"error in usb_interrupt_msg(). Error number %d\n", r); +			"error in zd_ep_regs_out_msg(). Error number %d\n", r);  		goto error;  	}  	if (req_len != actual_req_len) { -		dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()\n" +		dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()\n"  			" req_len %d != actual_req_len %d\n",  			req_len, actual_req_len);  		r = -EIO; @@ -1818,9 +1842,17 @@ int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,  		rw->value = cpu_to_le16(ioreqs[i].value);  	} -	usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT), -			 req, req_len, iowrite16v_urb_complete, usb, -			 ep->desc.bInterval); +	/* In USB 2.0 mode endpoint is interrupt type. However in USB 1.1 mode +	 * endpoint is bulk. Select correct type URB by endpoint descriptor. +	 */ +	if (usb_endpoint_xfer_int(&ep->desc)) +		usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT), +				 req, req_len, iowrite16v_urb_complete, usb, +				 ep->desc.bInterval); +	else +		usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_REGS_OUT), +				  req, req_len, iowrite16v_urb_complete, usb); +  	urb->transfer_flags |= URB_FREE_BUFFER;  	/* Submit previous URB */ @@ -1924,15 +1956,14 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)  	}  	udev = zd_usb_to_usbdev(usb); -	r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT), -			      req, req_len, &actual_req_len, 50 /* ms */); +	r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);  	if (r) {  		dev_dbg_f(zd_usb_dev(usb), -			"error in usb_interrupt_msg(). Error number %d\n", r); +			"error in zd_ep_regs_out_msg(). Error number %d\n", r);  		goto out;  	}  	if (req_len != actual_req_len) { -		dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()" +		dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()"  			" req_len %d != actual_req_len %d\n",  			req_len, actual_req_len);  		r = -EIO; diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 58584dc0724..44e8ca398ef 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -297,7 +297,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,  		kfree(sdev);  		goto out;  	} - +	blk_get_queue(sdev->request_queue);  	sdev->request_queue->queuedata = sdev;  	scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index e63912510fb..e0bd3f790fc 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -322,6 +322,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)  		kfree(evt);  	} +	blk_put_queue(sdev->request_queue);  	/* NULL queue means the device can't be used */  	sdev->request_queue = NULL; diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index a4c42a75a3b..09e8c7d53af 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2128,8 +2128,8 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)  	gsm->tty = NULL;  } -static unsigned int gsmld_receive_buf(struct tty_struct *tty, -		const unsigned char *cp, char *fp, int count) +static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, +			      char *fp, int count)  {  	struct gsm_mux *gsm = tty->disc_data;  	const unsigned char *dp; @@ -2162,8 +2162,6 @@ static unsigned int gsmld_receive_buf(struct tty_struct *tty,  	}  	/* FASYNC if needed ? */  	/* If clogged call tty_throttle(tty); */ - -	return count;  }  /** diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index cac666314ae..cea56033b34 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -188,8 +188,8 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,  				    poll_table *wait);  static int n_hdlc_tty_open(struct tty_struct *tty);  static void n_hdlc_tty_close(struct tty_struct *tty); -static unsigned int n_hdlc_tty_receive(struct tty_struct *tty, -		const __u8 *cp, char *fp, int count); +static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *cp, +			       char *fp, int count);  static void n_hdlc_tty_wakeup(struct tty_struct *tty);  #define bset(p,b)	((p)[(b) >> 5] |= (1 << ((b) & 0x1f))) @@ -509,8 +509,8 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty)   * Called by tty low level driver when receive data is available. Data is   * interpreted as one HDLC frame.   */ -static unsigned int n_hdlc_tty_receive(struct tty_struct *tty, -		const __u8 *data, char *flags, int count) +static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, +			       char *flags, int count)  {  	register struct n_hdlc *n_hdlc = tty2n_hdlc (tty);  	register struct n_hdlc_buf *buf; @@ -521,20 +521,20 @@ static unsigned int n_hdlc_tty_receive(struct tty_struct *tty,  	/* This can happen if stuff comes in on the backup tty */  	if (!n_hdlc || tty != n_hdlc->tty) -		return -ENODEV; +		return;  	/* verify line is using HDLC discipline */  	if (n_hdlc->magic != HDLC_MAGIC) {  		printk("%s(%d) line not using HDLC discipline\n",  			__FILE__,__LINE__); -		return -EINVAL; +		return;  	}  	if ( count>maxframe ) {  		if (debuglevel >= DEBUG_LEVEL_INFO)	  			printk("%s(%d) rx count>maxframesize, data discarded\n",  			       __FILE__,__LINE__); -		return -EINVAL; +		return;  	}  	/* get a free HDLC buffer */	 @@ -550,7 +550,7 @@ static unsigned int n_hdlc_tty_receive(struct tty_struct *tty,  		if (debuglevel >= DEBUG_LEVEL_INFO)	  			printk("%s(%d) no more rx buffers, data discarded\n",  			       __FILE__,__LINE__); -		return -EINVAL; +		return;  	}  	/* copy received data to HDLC buffer */ @@ -565,8 +565,6 @@ static unsigned int n_hdlc_tty_receive(struct tty_struct *tty,  	if (n_hdlc->tty->fasync != NULL)  		kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN); -	return count; -  }	/* end of n_hdlc_tty_receive() */  /** diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index a4bc39c21a4..5c6c31459a2 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -139,8 +139,8 @@ static int r3964_ioctl(struct tty_struct *tty, struct file *file,  static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old);  static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,  		struct poll_table_struct *wait); -static unsigned int r3964_receive_buf(struct tty_struct *tty, -		const unsigned char *cp, char *fp, int count); +static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, +		char *fp, int count);  static struct tty_ldisc_ops tty_ldisc_N_R3964 = {  	.owner = THIS_MODULE, @@ -1239,8 +1239,8 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,  	return result;  } -static unsigned int r3964_receive_buf(struct tty_struct *tty, -		const unsigned char *cp, char *fp, int count) +static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, +			char *fp, int count)  {  	struct r3964_info *pInfo = tty->disc_data;  	const unsigned char *p; @@ -1257,8 +1257,6 @@ static unsigned int r3964_receive_buf(struct tty_struct *tty,  		}  	} - -	return count;  }  MODULE_LICENSE("GPL"); diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 95d0a9c2dd1..0ad32888091 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -81,6 +81,38 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,  	return put_user(x, ptr);  } +/** + *	n_tty_set__room	-	receive space + *	@tty: terminal + * + *	Called by the driver to find out how much data it is + *	permitted to feed to the line discipline without any being lost + *	and thus to manage flow control. Not serialized. Answers for the + *	"instant". + */ + +static void n_tty_set_room(struct tty_struct *tty) +{ +	/* tty->read_cnt is not read locked ? */ +	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1; +	int old_left; + +	/* +	 * If we are doing input canonicalization, and there are no +	 * pending newlines, let characters through without limit, so +	 * that erase characters will be handled.  Other excess +	 * characters will be beeped. +	 */ +	if (left <= 0) +		left = tty->icanon && !tty->canon_data; +	old_left = tty->receive_room; +	tty->receive_room = left; + +	/* Did this open up the receive buffer? We may need to flip */ +	if (left && !old_left) +		schedule_work(&tty->buf.work); +} +  static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)  {  	if (tty->read_cnt < N_TTY_BUF_SIZE) { @@ -152,6 +184,7 @@ static void reset_buffer_flags(struct tty_struct *tty)  	tty->canon_head = tty->canon_data = tty->erasing = 0;  	memset(&tty->read_flags, 0, sizeof tty->read_flags); +	n_tty_set_room(tty);  	check_unthrottle(tty);  } @@ -1327,19 +1360,17 @@ static void n_tty_write_wakeup(struct tty_struct *tty)   *	calls one at a time and in order (or using flush_to_ldisc)   */ -static unsigned int n_tty_receive_buf(struct tty_struct *tty, -		const unsigned char *cp, char *fp, int count) +static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, +			      char *fp, int count)  {  	const unsigned char *p;  	char *f, flags = TTY_NORMAL;  	int	i;  	char	buf[64];  	unsigned long cpuflags; -	int left; -	int ret = 0;  	if (!tty->read_buf) -		return 0; +		return;  	if (tty->real_raw) {  		spin_lock_irqsave(&tty->read_lock, cpuflags); @@ -1349,7 +1380,6 @@ static unsigned int n_tty_receive_buf(struct tty_struct *tty,  		memcpy(tty->read_buf + tty->read_head, cp, i);  		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);  		tty->read_cnt += i; -		ret += i;  		cp += i;  		count -= i; @@ -1359,10 +1389,8 @@ static unsigned int n_tty_receive_buf(struct tty_struct *tty,  		memcpy(tty->read_buf + tty->read_head, cp, i);  		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);  		tty->read_cnt += i; -		ret += i;  		spin_unlock_irqrestore(&tty->read_lock, cpuflags);  	} else { -		ret = count;  		for (i = count, p = cp, f = fp; i; i--, p++) {  			if (f)  				flags = *f++; @@ -1390,6 +1418,8 @@ static unsigned int n_tty_receive_buf(struct tty_struct *tty,  			tty->ops->flush_chars(tty);  	} +	n_tty_set_room(tty); +  	if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||  		L_EXTPROC(tty)) {  		kill_fasync(&tty->fasync, SIGIO, POLL_IN); @@ -1402,12 +1432,8 @@ static unsigned int n_tty_receive_buf(struct tty_struct *tty,  	 * mode.  We don't want to throttle the driver if we're in  	 * canonical mode and don't have a newline yet!  	 */ -	left = N_TTY_BUF_SIZE - tty->read_cnt - 1; - -	if (left < TTY_THRESHOLD_THROTTLE) +	if (tty->receive_room < TTY_THRESHOLD_THROTTLE)  		tty_throttle(tty); - -	return ret;  }  int is_ignored(int sig) @@ -1451,6 +1477,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)  	if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {  		tty->raw = 1;  		tty->real_raw = 1; +		n_tty_set_room(tty);  		return;  	}  	if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || @@ -1503,6 +1530,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)  		else  			tty->real_raw = 0;  	} +	n_tty_set_room(tty);  	/* The termios change make the tty ready for I/O */  	wake_up_interruptible(&tty->write_wait);  	wake_up_interruptible(&tty->read_wait); @@ -1784,6 +1812,8 @@ do_it_again:  				retval = -ERESTARTSYS;  				break;  			} +			/* FIXME: does n_tty_set_room need locking ? */ +			n_tty_set_room(tty);  			timeout = schedule_timeout(timeout);  			continue;  		} @@ -1855,8 +1885,10 @@ do_it_again:  		 * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,  		 * we won't get any more characters.  		 */ -		if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) +		if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) { +			n_tty_set_room(tty);  			check_unthrottle(tty); +		}  		if (b - buf >= minimum)  			break; @@ -1878,6 +1910,7 @@ do_it_again:  	} else if (test_and_clear_bit(TTY_PUSH, &tty->flags))  		 goto do_it_again; +	n_tty_set_room(tty);  	return retval;  } diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 46de2e075da..f1a7918d71a 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -416,7 +416,6 @@ static void flush_to_ldisc(struct work_struct *work)  		struct tty_buffer *head, *tail = tty->buf.tail;  		int seen_tail = 0;  		while ((head = tty->buf.head) != NULL) { -			int copied;  			int count;  			char *char_buf;  			unsigned char *flag_buf; @@ -443,19 +442,17 @@ static void flush_to_ldisc(struct work_struct *work)  			   line discipline as we want to empty the queue */  			if (test_bit(TTY_FLUSHPENDING, &tty->flags))  				break; +			if (!tty->receive_room || seen_tail) +				break; +			if (count > tty->receive_room) +				count = tty->receive_room;  			char_buf = head->char_buf_ptr + head->read;  			flag_buf = head->flag_buf_ptr + head->read; +			head->read += count;  			spin_unlock_irqrestore(&tty->buf.lock, flags); -			copied = disc->ops->receive_buf(tty, char_buf, +			disc->ops->receive_buf(tty, char_buf,  							flag_buf, count);  			spin_lock_irqsave(&tty->buf.lock, flags); - -			head->read += copied; - -			if (copied == 0 || seen_tail) { -				schedule_work(&tty->buf.work); -				break; -			}  		}  		clear_bit(TTY_FLUSHING, &tty->flags);  	} diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 67b1d0d7c8a..fb864e7fcd1 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -332,7 +332,8 @@ int paste_selection(struct tty_struct *tty)  			continue;  		}  		count = sel_buffer_lth - pasted; -		count = tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted, +		count = min(count, tty->receive_room); +		tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,  								NULL, count);  		pasted += count;  	} diff --git a/fs/block_dev.c b/fs/block_dev.c index 1f2b1997833..1a2421f908f 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1272,8 +1272,8 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)  		 * individual writeable reference is too fragile given the  		 * way @mode is used in blkdev_get/put().  		 */ -		if ((disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE) && -		    !res && (mode & FMODE_WRITE) && !bdev->bd_write_holder) { +		if (!res && (mode & FMODE_WRITE) && !bdev->bd_write_holder && +		    (disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE)) {  			bdev->bd_write_holder = true;  			disk_block_events(disk);  		} diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 93b1aa93201..52d7eca8c7b 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -121,9 +121,6 @@ struct btrfs_inode {  	 */  	u64 index_cnt; -	/* the start of block group preferred for allocations. */ -	u64 block_group; -  	/* the fsync log has some corner cases that mean we have to check  	 * directories to see if any unlinks have been done before  	 * the directory was logged.  See tree-log.c for all the diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index b0e18d986e0..d84089349c8 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -43,8 +43,6 @@ struct btrfs_path *btrfs_alloc_path(void)  {  	struct btrfs_path *path;  	path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS); -	if (path) -		path->reada = 1;  	return path;  } @@ -1224,6 +1222,7 @@ static void reada_for_search(struct btrfs_root *root,  	u64 search;  	u64 target;  	u64 nread = 0; +	u64 gen;  	int direction = path->reada;  	struct extent_buffer *eb;  	u32 nr; @@ -1251,6 +1250,15 @@ static void reada_for_search(struct btrfs_root *root,  	nritems = btrfs_header_nritems(node);  	nr = slot;  	while (1) { +		if (!node->map_token) { +			unsigned long offset = btrfs_node_key_ptr_offset(nr); +			map_private_extent_buffer(node, offset, +						  sizeof(struct btrfs_key_ptr), +						  &node->map_token, +						  &node->kaddr, +						  &node->map_start, +						  &node->map_len, KM_USER1); +		}  		if (direction < 0) {  			if (nr == 0)  				break; @@ -1268,14 +1276,23 @@ static void reada_for_search(struct btrfs_root *root,  		search = btrfs_node_blockptr(node, nr);  		if ((search <= target && target - search <= 65536) ||  		    (search > target && search - target <= 65536)) { -			readahead_tree_block(root, search, blocksize, -				     btrfs_node_ptr_generation(node, nr)); +			gen = btrfs_node_ptr_generation(node, nr); +			if (node->map_token) { +				unmap_extent_buffer(node, node->map_token, +						    KM_USER1); +				node->map_token = NULL; +			} +			readahead_tree_block(root, search, blocksize, gen);  			nread += blocksize;  		}  		nscan++;  		if ((nread > 65536 || nscan > 32))  			break;  	} +	if (node->map_token) { +		unmap_extent_buffer(node, node->map_token, KM_USER1); +		node->map_token = NULL; +	}  }  /* @@ -1648,9 +1665,6 @@ again:  		}  cow_done:  		BUG_ON(!cow && ins_len); -		if (level != btrfs_header_level(b)) -			WARN_ON(1); -		level = btrfs_header_level(b);  		p->nodes[level] = b;  		if (!p->skip_locking) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 6c093fa98f6..378b5b4443f 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -930,7 +930,6 @@ struct btrfs_fs_info {  	 * is required instead of the faster short fsync log commits  	 */  	u64 last_trans_log_full_commit; -	u64 open_ioctl_trans;  	unsigned long mount_opt:20;  	unsigned long compress_type:4;  	u64 max_inline; @@ -947,7 +946,6 @@ struct btrfs_fs_info {  	struct super_block *sb;  	struct inode *btree_inode;  	struct backing_dev_info bdi; -	struct mutex trans_mutex;  	struct mutex tree_log_mutex;  	struct mutex transaction_kthread_mutex;  	struct mutex cleaner_mutex; @@ -968,6 +966,7 @@ struct btrfs_fs_info {  	struct rw_semaphore subvol_sem;  	struct srcu_struct subvol_srcu; +	spinlock_t trans_lock;  	struct list_head trans_list;  	struct list_head hashers;  	struct list_head dead_roots; @@ -980,6 +979,7 @@ struct btrfs_fs_info {  	atomic_t async_submit_draining;  	atomic_t nr_async_bios;  	atomic_t async_delalloc_pages; +	atomic_t open_ioctl_trans;  	/*  	 * this is used by the balancing code to wait for all the pending @@ -1044,6 +1044,7 @@ struct btrfs_fs_info {  	int closing;  	int log_root_recovering;  	int enospc_unlink; +	int trans_no_join;  	u64 total_pinned; @@ -1065,7 +1066,6 @@ struct btrfs_fs_info {  	struct reloc_control *reloc_ctl;  	spinlock_t delalloc_lock; -	spinlock_t new_trans_lock;  	u64 delalloc_bytes;  	/* data_alloc_cluster is only used in ssd mode */ @@ -1340,6 +1340,7 @@ struct btrfs_ioctl_defrag_range_args {  #define BTRFS_MOUNT_USER_SUBVOL_RM_ALLOWED (1 << 14)  #define BTRFS_MOUNT_ENOSPC_DEBUG	 (1 << 15)  #define BTRFS_MOUNT_AUTO_DEFRAG		(1 << 16) +#define BTRFS_MOUNT_INODE_MAP_CACHE	(1 << 17)  #define btrfs_clear_opt(o, opt)		((o) &= ~BTRFS_MOUNT_##opt)  #define btrfs_set_opt(o, opt)		((o) |= BTRFS_MOUNT_##opt) @@ -2238,6 +2239,9 @@ int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv,  void btrfs_block_rsv_release(struct btrfs_root *root,  			     struct btrfs_block_rsv *block_rsv,  			     u64 num_bytes); +int btrfs_truncate_reserve_metadata(struct btrfs_trans_handle *trans, +				    struct btrfs_root *root, +				    struct btrfs_block_rsv *rsv);  int btrfs_set_block_group_ro(struct btrfs_root *root,  			     struct btrfs_block_group_cache *cache);  int btrfs_set_block_group_rw(struct btrfs_root *root, @@ -2350,6 +2354,15 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,  			struct btrfs_root *root,  			struct extent_buffer *node,  			struct extent_buffer *parent); +static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info) +{ +	/* +	 * Get synced with close_ctree() +	 */ +	smp_mb(); +	return fs_info->closing; +} +  /* root-item.c */  int btrfs_find_root_ref(struct btrfs_root *tree_root,  			struct btrfs_path *path, @@ -2512,8 +2525,7 @@ int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,  int btrfs_writepages(struct address_space *mapping,  		     struct writeback_control *wbc);  int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, -			     struct btrfs_root *new_root, -			     u64 new_dirid, u64 alloc_hint); +			     struct btrfs_root *new_root, u64 new_dirid);  int btrfs_merge_bio_hook(struct page *page, unsigned long offset,  			 size_t size, struct bio *bio, unsigned long bio_flags); diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 01e29503a54..6462c29d2d3 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -678,6 +678,7 @@ static int btrfs_batch_insert_items(struct btrfs_trans_handle *trans,  	INIT_LIST_HEAD(&head);  	next = item; +	nitems = 0;  	/*  	 * count the number of the continuous items that we can insert in batch @@ -1129,7 +1130,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work)  	delayed_node = async_node->delayed_node;  	root = delayed_node->root; -	trans = btrfs_join_transaction(root, 0); +	trans = btrfs_join_transaction(root);  	if (IS_ERR(trans))  		goto free_path; @@ -1572,8 +1573,7 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans,  	btrfs_set_stack_inode_transid(inode_item, trans->transid);  	btrfs_set_stack_inode_rdev(inode_item, inode->i_rdev);  	btrfs_set_stack_inode_flags(inode_item, BTRFS_I(inode)->flags); -	btrfs_set_stack_inode_block_group(inode_item, -					  BTRFS_I(inode)->block_group); +	btrfs_set_stack_inode_block_group(inode_item, 0);  	btrfs_set_stack_timespec_sec(btrfs_inode_atime(inode_item),  				     inode->i_atime.tv_sec); @@ -1595,7 +1595,7 @@ int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans,  			       struct btrfs_root *root, struct inode *inode)  {  	struct btrfs_delayed_node *delayed_node; -	int ret; +	int ret = 0;  	delayed_node = btrfs_get_or_create_delayed_node(inode);  	if (IS_ERR(delayed_node)) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 98b6a71decb..a203d363184 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1505,24 +1505,24 @@ static int transaction_kthread(void *arg)  		vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);  		mutex_lock(&root->fs_info->transaction_kthread_mutex); -		spin_lock(&root->fs_info->new_trans_lock); +		spin_lock(&root->fs_info->trans_lock);  		cur = root->fs_info->running_transaction;  		if (!cur) { -			spin_unlock(&root->fs_info->new_trans_lock); +			spin_unlock(&root->fs_info->trans_lock);  			goto sleep;  		}  		now = get_seconds();  		if (!cur->blocked &&  		    (now < cur->start_time || now - cur->start_time < 30)) { -			spin_unlock(&root->fs_info->new_trans_lock); +			spin_unlock(&root->fs_info->trans_lock);  			delay = HZ * 5;  			goto sleep;  		}  		transid = cur->transid; -		spin_unlock(&root->fs_info->new_trans_lock); +		spin_unlock(&root->fs_info->trans_lock); -		trans = btrfs_join_transaction(root, 1); +		trans = btrfs_join_transaction(root);  		BUG_ON(IS_ERR(trans));  		if (transid == trans->transid) {  			ret = btrfs_commit_transaction(trans, root); @@ -1613,7 +1613,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,  	INIT_LIST_HEAD(&fs_info->ordered_operations);  	INIT_LIST_HEAD(&fs_info->caching_block_groups);  	spin_lock_init(&fs_info->delalloc_lock); -	spin_lock_init(&fs_info->new_trans_lock); +	spin_lock_init(&fs_info->trans_lock);  	spin_lock_init(&fs_info->ref_cache_lock);  	spin_lock_init(&fs_info->fs_roots_radix_lock);  	spin_lock_init(&fs_info->delayed_iput_lock); @@ -1645,6 +1645,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,  	fs_info->max_inline = 8192 * 1024;  	fs_info->metadata_ratio = 0;  	fs_info->defrag_inodes = RB_ROOT; +	fs_info->trans_no_join = 0;  	fs_info->thread_pool_size = min_t(unsigned long,  					  num_online_cpus() + 2, 8); @@ -1709,7 +1710,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,  	fs_info->do_barriers = 1; -	mutex_init(&fs_info->trans_mutex);  	mutex_init(&fs_info->ordered_operations_mutex);  	mutex_init(&fs_info->tree_log_mutex);  	mutex_init(&fs_info->chunk_mutex); @@ -2479,13 +2479,13 @@ int btrfs_commit_super(struct btrfs_root *root)  	down_write(&root->fs_info->cleanup_work_sem);  	up_write(&root->fs_info->cleanup_work_sem); -	trans = btrfs_join_transaction(root, 1); +	trans = btrfs_join_transaction(root);  	if (IS_ERR(trans))  		return PTR_ERR(trans);  	ret = btrfs_commit_transaction(trans, root);  	BUG_ON(ret);  	/* run commit again to drop the original snapshot */ -	trans = btrfs_join_transaction(root, 1); +	trans = btrfs_join_transaction(root);  	if (IS_ERR(trans))  		return PTR_ERR(trans);  	btrfs_commit_transaction(trans, root); @@ -3024,10 +3024,13 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)  	WARN_ON(1); -	mutex_lock(&root->fs_info->trans_mutex);  	mutex_lock(&root->fs_info->transaction_kthread_mutex); +	spin_lock(&root->fs_info->trans_lock);  	list_splice_init(&root->fs_info->trans_list, &list); +	root->fs_info->trans_no_join = 1; +	spin_unlock(&root->fs_info->trans_lock); +  	while (!list_empty(&list)) {  		t = list_entry(list.next, struct btrfs_transaction, list);  		if (!t) @@ -3052,23 +3055,18 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)  		t->blocked = 0;  		if (waitqueue_active(&root->fs_info->transaction_wait))  			wake_up(&root->fs_info->transaction_wait); -		mutex_unlock(&root->fs_info->trans_mutex); -		mutex_lock(&root->fs_info->trans_mutex);  		t->commit_done = 1;  		if (waitqueue_active(&t->commit_wait))  			wake_up(&t->commit_wait); -		mutex_unlock(&root->fs_info->trans_mutex); - -		mutex_lock(&root->fs_info->trans_mutex);  		btrfs_destroy_pending_snapshots(t);  		btrfs_destroy_delalloc_inodes(root); -		spin_lock(&root->fs_info->new_trans_lock); +		spin_lock(&root->fs_info->trans_lock);  		root->fs_info->running_transaction = NULL; -		spin_unlock(&root->fs_info->new_trans_lock); +		spin_unlock(&root->fs_info->trans_lock);  		btrfs_destroy_marked_extents(root, &t->dirty_pages,  					     EXTENT_DIRTY); @@ -3082,8 +3080,10 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)  		kmem_cache_free(btrfs_transaction_cachep, t);  	} +	spin_lock(&root->fs_info->trans_lock); +	root->fs_info->trans_no_join = 0; +	spin_unlock(&root->fs_info->trans_lock);  	mutex_unlock(&root->fs_info->transaction_kthread_mutex); -	mutex_unlock(&root->fs_info->trans_mutex);  	return 0;  } diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 169bd62ce77..5b9b6b6df24 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -348,7 +348,7 @@ static int caching_kthread(void *data)  	 */  	path->skip_locking = 1;  	path->search_commit_root = 1; -	path->reada = 2; +	path->reada = 1;  	key.objectid = last;  	key.offset = 0; @@ -366,8 +366,7 @@ again:  	nritems = btrfs_header_nritems(leaf);  	while (1) { -		smp_mb(); -		if (fs_info->closing > 1) { +		if (btrfs_fs_closing(fs_info) > 1) {  			last = (u64)-1;  			break;  		} @@ -379,15 +378,18 @@ again:  			if (ret)  				break; -			caching_ctl->progress = last; -			btrfs_release_path(path); -			up_read(&fs_info->extent_commit_sem); -			mutex_unlock(&caching_ctl->mutex); -			if (btrfs_transaction_in_commit(fs_info)) -				schedule_timeout(1); -			else +			if (need_resched() || +			    btrfs_next_leaf(extent_root, path)) { +				caching_ctl->progress = last; +				btrfs_release_path(path); +				up_read(&fs_info->extent_commit_sem); +				mutex_unlock(&caching_ctl->mutex);  				cond_resched(); -			goto again; +				goto again; +			} +			leaf = path->nodes[0]; +			nritems = btrfs_header_nritems(leaf); +			continue;  		}  		if (key.objectid < block_group->key.objectid) { @@ -3065,7 +3067,7 @@ again:  			spin_unlock(&data_sinfo->lock);  alloc:  			alloc_target = btrfs_get_alloc_profile(root, 1); -			trans = btrfs_join_transaction(root, 1); +			trans = btrfs_join_transaction(root);  			if (IS_ERR(trans))  				return PTR_ERR(trans); @@ -3091,9 +3093,10 @@ alloc:  		/* commit the current transaction and try again */  commit_trans: -		if (!committed && !root->fs_info->open_ioctl_trans) { +		if (!committed && +		    !atomic_read(&root->fs_info->open_ioctl_trans)) {  			committed = 1; -			trans = btrfs_join_transaction(root, 1); +			trans = btrfs_join_transaction(root);  			if (IS_ERR(trans))  				return PTR_ERR(trans);  			ret = btrfs_commit_transaction(trans, root); @@ -3472,7 +3475,7 @@ again:  		goto out;  	ret = -ENOSPC; -	trans = btrfs_join_transaction(root, 1); +	trans = btrfs_join_transaction(root);  	if (IS_ERR(trans))  		goto out;  	ret = btrfs_commit_transaction(trans, root); @@ -3699,7 +3702,7 @@ int btrfs_block_rsv_check(struct btrfs_trans_handle *trans,  		if (trans)  			return -EAGAIN; -		trans = btrfs_join_transaction(root, 1); +		trans = btrfs_join_transaction(root);  		BUG_ON(IS_ERR(trans));  		ret = btrfs_commit_transaction(trans, root);  		return 0; @@ -3837,6 +3840,37 @@ static void release_global_block_rsv(struct btrfs_fs_info *fs_info)  	WARN_ON(fs_info->chunk_block_rsv.reserved > 0);  } +int btrfs_truncate_reserve_metadata(struct btrfs_trans_handle *trans, +				    struct btrfs_root *root, +				    struct btrfs_block_rsv *rsv) +{ +	struct btrfs_block_rsv *trans_rsv = &root->fs_info->trans_block_rsv; +	u64 num_bytes; +	int ret; + +	/* +	 * Truncate should be freeing data, but give us 2 items just in case it +	 * needs to use some space.  We may want to be smarter about this in the +	 * future. +	 */ +	num_bytes = btrfs_calc_trans_metadata_size(root, 2); + +	/* We already have enough bytes, just return */ +	if (rsv->reserved >= num_bytes) +		return 0; + +	num_bytes -= rsv->reserved; + +	/* +	 * You should have reserved enough space before hand to do this, so this +	 * should not fail. +	 */ +	ret = block_rsv_migrate_bytes(trans_rsv, rsv, num_bytes); +	BUG_ON(ret); + +	return 0; +} +  int btrfs_trans_reserve_metadata(struct btrfs_trans_handle *trans,  				 struct btrfs_root *root,  				 int num_items) @@ -3877,23 +3911,18 @@ int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans,  	struct btrfs_block_rsv *dst_rsv = root->orphan_block_rsv;  	/* -	 * one for deleting orphan item, one for updating inode and -	 * two for calling btrfs_truncate_inode_items. -	 * -	 * btrfs_truncate_inode_items is a delete operation, it frees -	 * more space than it uses in most cases. So two units of -	 * metadata space should be enough for calling it many times. -	 * If all of the metadata space is used, we can commit -	 * transaction and use space it freed. +	 * We need to hold space in order to delete our orphan item once we've +	 * added it, so this takes the reservation so we can release it later +	 * when we are truly done with the orphan item.  	 */ -	u64 num_bytes = btrfs_calc_trans_metadata_size(root, 4); +	u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1);  	return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes);  }  void btrfs_orphan_release_metadata(struct inode *inode)  {  	struct btrfs_root *root = BTRFS_I(inode)->root; -	u64 num_bytes = btrfs_calc_trans_metadata_size(root, 4); +	u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1);  	btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes);  } @@ -4987,6 +5016,15 @@ have_block_group:  		if (unlikely(block_group->ro))  			goto loop; +		spin_lock(&block_group->free_space_ctl->tree_lock); +		if (cached && +		    block_group->free_space_ctl->free_space < +		    num_bytes + empty_size) { +			spin_unlock(&block_group->free_space_ctl->tree_lock); +			goto loop; +		} +		spin_unlock(&block_group->free_space_ctl->tree_lock); +  		/*  		 * Ok we want to try and use the cluster allocator, so lets look  		 * there, unless we are on LOOP_NO_EMPTY_SIZE, since we will @@ -5150,6 +5188,7 @@ checks:  			btrfs_add_free_space(block_group, offset,  					     search_start - offset);  		BUG_ON(offset > search_start); +		btrfs_put_block_group(block_group);  		break;  loop:  		failed_cluster_refill = false; @@ -5242,14 +5281,7 @@ loop:  		ret = -ENOSPC;  	} else if (!ins->objectid) {  		ret = -ENOSPC; -	} - -	/* we found what we needed */ -	if (ins->objectid) { -		if (!(data & BTRFS_BLOCK_GROUP_DATA)) -			trans->block_group = block_group->key.objectid; - -		btrfs_put_block_group(block_group); +	} else if (ins->objectid) {  		ret = 0;  	} @@ -6526,7 +6558,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,  	BUG_ON(cache->ro); -	trans = btrfs_join_transaction(root, 1); +	trans = btrfs_join_transaction(root);  	BUG_ON(IS_ERR(trans));  	alloc_flags = update_block_group_flags(root, cache->flags); @@ -6882,6 +6914,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; +	path->reada = 1;  	cache_gen = btrfs_super_cache_generation(&root->fs_info->super_copy);  	if (cache_gen != 0 && diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index c5d9fbb92bc..7055d11c1ef 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1476,7 +1476,7 @@ u64 count_range_bits(struct extent_io_tree *tree,  			if (total_bytes >= max_bytes)  				break;  			if (!found) { -				*start = state->start; +				*start = max(cur_start, state->start);  				found = 1;  			}  			last = state->end; diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index c6a22d783c3..fa4ef18b66b 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -129,7 +129,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,  	if (!btrfs_test_opt(root, AUTO_DEFRAG))  		return 0; -	if (root->fs_info->closing) +	if (btrfs_fs_closing(root->fs_info))  		return 0;  	if (BTRFS_I(inode)->in_defrag) @@ -144,7 +144,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,  	if (!defrag)  		return -ENOMEM; -	defrag->ino = inode->i_ino; +	defrag->ino = btrfs_ino(inode);  	defrag->transid = transid;  	defrag->root = root->root_key.objectid; @@ -229,7 +229,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)  		first_ino = defrag->ino + 1;  		rb_erase(&defrag->rb_node, &fs_info->defrag_inodes); -		if (fs_info->closing) +		if (btrfs_fs_closing(fs_info))  			goto next_free;  		spin_unlock(&fs_info->defrag_inodes_lock); @@ -1480,14 +1480,12 @@ int btrfs_sync_file(struct file *file, int datasync)  	 * the current transaction, we can bail out now without any  	 * syncing  	 */ -	mutex_lock(&root->fs_info->trans_mutex); +	smp_mb();  	if (BTRFS_I(inode)->last_trans <=  	    root->fs_info->last_trans_committed) {  		BTRFS_I(inode)->last_trans = 0; -		mutex_unlock(&root->fs_info->trans_mutex);  		goto out;  	} -	mutex_unlock(&root->fs_info->trans_mutex);  	/*  	 * ok we haven't committed the transaction yet, lets do a commit diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 70d45795d75..ad144736a5f 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -98,7 +98,7 @@ struct inode *lookup_free_space_inode(struct btrfs_root *root,  		return inode;  	spin_lock(&block_group->lock); -	if (!root->fs_info->closing) { +	if (!btrfs_fs_closing(root->fs_info)) {  		block_group->inode = igrab(inode);  		block_group->iref = 1;  	} @@ -402,7 +402,14 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,  				spin_lock(&ctl->tree_lock);  				ret = link_free_space(ctl, e);  				spin_unlock(&ctl->tree_lock); -				BUG_ON(ret); +				if (ret) { +					printk(KERN_ERR "Duplicate entries in " +					       "free space cache, dumping\n"); +					kunmap(page); +					unlock_page(page); +					page_cache_release(page); +					goto free_cache; +				}  			} else {  				e->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);  				if (!e->bitmap) { @@ -419,6 +426,14 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,  				ctl->op->recalc_thresholds(ctl);  				spin_unlock(&ctl->tree_lock);  				list_add_tail(&e->list, &bitmaps); +				if (ret) { +					printk(KERN_ERR "Duplicate entries in " +					       "free space cache, dumping\n"); +					kunmap(page); +					unlock_page(page); +					page_cache_release(page); +					goto free_cache; +				}  			}  			num_entries--; @@ -478,8 +493,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,  	 * If we're unmounting then just return, since this does a search on the  	 * normal root and not the commit root and we could deadlock.  	 */ -	smp_mb(); -	if (fs_info->closing) +	if (btrfs_fs_closing(fs_info))  		return 0;  	/* @@ -575,10 +589,25 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,  	num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>  		PAGE_CACHE_SHIFT; + +	/* Since the first page has all of our checksums and our generation we +	 * need to calculate the offset into the page that we can start writing +	 * our entries. +	 */ +	first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64); +  	filemap_write_and_wait(inode->i_mapping);  	btrfs_wait_ordered_range(inode, inode->i_size &  				 ~(root->sectorsize - 1), (u64)-1); +	/* make sure we don't overflow that first page */ +	if (first_page_offset + sizeof(struct btrfs_free_space_entry) >= PAGE_CACHE_SIZE) { +		/* this is really the same as running out of space, where we also return 0 */ +		printk(KERN_CRIT "Btrfs: free space cache was too big for the crc page\n"); +		ret = 0; +		goto out_update; +	} +  	/* We need a checksum per page. */  	crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS);  	if (!crc) @@ -590,12 +619,6 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,  		return -1;  	} -	/* Since the first page has all of our checksums and our generation we -	 * need to calculate the offset into the page that we can start writing -	 * our entries. -	 */ -	first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64); -  	/* Get the cluster for this block_group if it exists */  	if (block_group && !list_empty(&block_group->cluster_list))  		cluster = list_entry(block_group->cluster_list.next, @@ -857,12 +880,14 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,  	ret = 1;  out_free: +	kfree(checksums); +	kfree(pages); + +out_update:  	if (ret != 1) {  		invalidate_inode_pages2_range(inode->i_mapping, 0, index);  		BTRFS_I(inode)->generation = 0;  	} -	kfree(checksums); -	kfree(pages);  	btrfs_update_inode(trans, root, inode);  	return ret;  } @@ -963,10 +988,16 @@ static int tree_insert_offset(struct rb_root *root, u64 offset,  			 * logically.  			 */  			if (bitmap) { -				WARN_ON(info->bitmap); +				if (info->bitmap) { +					WARN_ON_ONCE(1); +					return -EEXIST; +				}  				p = &(*p)->rb_right;  			} else { -				WARN_ON(!info->bitmap); +				if (!info->bitmap) { +					WARN_ON_ONCE(1); +					return -EEXIST; +				}  				p = &(*p)->rb_left;  			}  		} @@ -2481,7 +2512,7 @@ struct inode *lookup_free_ino_inode(struct btrfs_root *root,  		return inode;  	spin_lock(&root->cache_lock); -	if (!root->fs_info->closing) +	if (!btrfs_fs_closing(root->fs_info))  		root->cache_inode = igrab(inode);  	spin_unlock(&root->cache_lock); @@ -2504,12 +2535,14 @@ int load_free_ino_cache(struct btrfs_fs_info *fs_info, struct btrfs_root *root)  	int ret = 0;  	u64 root_gen = btrfs_root_generation(&root->root_item); +	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) +		return 0; +  	/*  	 * If we're unmounting then just return, since this does a search on the  	 * normal root and not the commit root and we could deadlock.  	 */ -	smp_mb(); -	if (fs_info->closing) +	if (btrfs_fs_closing(fs_info))  		return 0;  	path = btrfs_alloc_path(); @@ -2543,6 +2576,9 @@ int btrfs_write_out_ino_cache(struct btrfs_root *root,  	struct inode *inode;  	int ret; +	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) +		return 0; +  	inode = lookup_free_ino_inode(root, path);  	if (IS_ERR(inode))  		return 0; diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index 3262cd17a12..b4087e0fa87 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c @@ -38,6 +38,9 @@ static int caching_kthread(void *data)  	int slot;  	int ret; +	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) +		return 0; +  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; @@ -59,8 +62,7 @@ again:  		goto out;  	while (1) { -		smp_mb(); -		if (fs_info->closing) +		if (btrfs_fs_closing(fs_info))  			goto out;  		leaf = path->nodes[0]; @@ -141,6 +143,9 @@ static void start_caching(struct btrfs_root *root)  	int ret;  	u64 objectid; +	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) +		return; +  	spin_lock(&root->cache_lock);  	if (root->cached != BTRFS_CACHE_NO) {  		spin_unlock(&root->cache_lock); @@ -178,6 +183,9 @@ static void start_caching(struct btrfs_root *root)  int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid)  { +	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) +		return btrfs_find_free_objectid(root, objectid); +  again:  	*objectid = btrfs_find_ino_for_alloc(root); @@ -201,6 +209,10 @@ void btrfs_return_ino(struct btrfs_root *root, u64 objectid)  {  	struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;  	struct btrfs_free_space_ctl *pinned = root->free_ino_pinned; + +	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) +		return; +  again:  	if (root->cached == BTRFS_CACHE_FINISHED) {  		__btrfs_add_free_space(ctl, objectid, 1); @@ -250,6 +262,9 @@ void btrfs_unpin_free_ino(struct btrfs_root *root)  	struct rb_node *n;  	u64 count; +	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) +		return; +  	while (1) {  		n = rb_first(rbroot);  		if (!n) @@ -388,9 +403,24 @@ int btrfs_save_ino_cache(struct btrfs_root *root,  	int prealloc;  	bool retry = false; +	/* only fs tree and subvol/snap needs ino cache */ +	if (root->root_key.objectid != BTRFS_FS_TREE_OBJECTID && +	    (root->root_key.objectid < BTRFS_FIRST_FREE_OBJECTID || +	     root->root_key.objectid > BTRFS_LAST_FREE_OBJECTID)) +		return 0; + +	/* Don't save inode cache if we are deleting this root */ +	if (btrfs_root_refs(&root->root_item) == 0 && +	    root != root->fs_info->tree_root) +		return 0; + +	if (!btrfs_test_opt(root, INODE_MAP_CACHE)) +		return 0; +  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; +  again:  	inode = lookup_free_ino_inode(root, path);  	if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 39a9d5750ef..ebf95f7a44d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -138,7 +138,6 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,  		return -ENOMEM;  	path->leave_spinning = 1; -	btrfs_set_trans_block_group(trans, inode);  	key.objectid = btrfs_ino(inode);  	key.offset = start; @@ -426,9 +425,8 @@ again:  		}  	}  	if (start == 0) { -		trans = btrfs_join_transaction(root, 1); +		trans = btrfs_join_transaction(root);  		BUG_ON(IS_ERR(trans)); -		btrfs_set_trans_block_group(trans, inode);  		trans->block_rsv = &root->fs_info->delalloc_block_rsv;  		/* lets try to make an inline extent */ @@ -623,8 +621,9 @@ retry:  			    async_extent->start + async_extent->ram_size - 1,  			    GFP_NOFS); -		trans = btrfs_join_transaction(root, 1); +		trans = btrfs_join_transaction(root);  		BUG_ON(IS_ERR(trans)); +		trans->block_rsv = &root->fs_info->delalloc_block_rsv;  		ret = btrfs_reserve_extent(trans, root,  					   async_extent->compressed_size,  					   async_extent->compressed_size, @@ -793,9 +792,8 @@ static noinline int cow_file_range(struct inode *inode,  	int ret = 0;  	BUG_ON(is_free_space_inode(root, inode)); -	trans = btrfs_join_transaction(root, 1); +	trans = btrfs_join_transaction(root);  	BUG_ON(IS_ERR(trans)); -	btrfs_set_trans_block_group(trans, inode);  	trans->block_rsv = &root->fs_info->delalloc_block_rsv;  	num_bytes = (end - start + blocksize) & ~(blocksize - 1); @@ -1077,10 +1075,12 @@ static noinline int run_delalloc_nocow(struct inode *inode,  	nolock = is_free_space_inode(root, inode);  	if (nolock) -		trans = btrfs_join_transaction_nolock(root, 1); +		trans = btrfs_join_transaction_nolock(root);  	else -		trans = btrfs_join_transaction(root, 1); +		trans = btrfs_join_transaction(root); +  	BUG_ON(IS_ERR(trans)); +	trans->block_rsv = &root->fs_info->delalloc_block_rsv;  	cow_start = (u64)-1;  	cur_offset = start; @@ -1519,8 +1519,6 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans,  {  	struct btrfs_ordered_sum *sum; -	btrfs_set_trans_block_group(trans, inode); -  	list_for_each_entry(sum, list, list) {  		btrfs_csum_file_blocks(trans,  		       BTRFS_I(inode)->root->fs_info->csum_root, sum); @@ -1735,11 +1733,10 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)  		ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);  		if (!ret) {  			if (nolock) -				trans = btrfs_join_transaction_nolock(root, 1); +				trans = btrfs_join_transaction_nolock(root);  			else -				trans = btrfs_join_transaction(root, 1); +				trans = btrfs_join_transaction(root);  			BUG_ON(IS_ERR(trans)); -			btrfs_set_trans_block_group(trans, inode);  			trans->block_rsv = &root->fs_info->delalloc_block_rsv;  			ret = btrfs_update_inode(trans, root, inode);  			BUG_ON(ret); @@ -1752,11 +1749,10 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)  			 0, &cached_state, GFP_NOFS);  	if (nolock) -		trans = btrfs_join_transaction_nolock(root, 1); +		trans = btrfs_join_transaction_nolock(root);  	else -		trans = btrfs_join_transaction(root, 1); +		trans = btrfs_join_transaction(root);  	BUG_ON(IS_ERR(trans)); -	btrfs_set_trans_block_group(trans, inode);  	trans->block_rsv = &root->fs_info->delalloc_block_rsv;  	if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags)) @@ -2431,7 +2427,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)  					(u64)-1);  	if (root->orphan_block_rsv || root->orphan_item_inserted) { -		trans = btrfs_join_transaction(root, 1); +		trans = btrfs_join_transaction(root);  		if (!IS_ERR(trans))  			btrfs_end_transaction(trans, root);  	} @@ -2511,12 +2507,12 @@ static void btrfs_read_locked_inode(struct inode *inode)  	struct btrfs_root *root = BTRFS_I(inode)->root;  	struct btrfs_key location;  	int maybe_acls; -	u64 alloc_group_block;  	u32 rdev;  	int ret;  	path = btrfs_alloc_path();  	BUG_ON(!path); +	path->leave_spinning = 1;  	memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));  	ret = btrfs_lookup_inode(NULL, root, path, &location, 0); @@ -2526,6 +2522,12 @@ static void btrfs_read_locked_inode(struct inode *inode)  	leaf = path->nodes[0];  	inode_item = btrfs_item_ptr(leaf, path->slots[0],  				    struct btrfs_inode_item); +	if (!leaf->map_token) +		map_private_extent_buffer(leaf, (unsigned long)inode_item, +					  sizeof(struct btrfs_inode_item), +					  &leaf->map_token, &leaf->kaddr, +					  &leaf->map_start, &leaf->map_len, +					  KM_USER1);  	inode->i_mode = btrfs_inode_mode(leaf, inode_item);  	inode->i_nlink = btrfs_inode_nlink(leaf, inode_item); @@ -2555,8 +2557,6 @@ static void btrfs_read_locked_inode(struct inode *inode)  	BTRFS_I(inode)->index_cnt = (u64)-1;  	BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); -	alloc_group_block = btrfs_inode_block_group(leaf, inode_item); -  	/*  	 * try to precache a NULL acl entry for files that don't have  	 * any xattrs or acls @@ -2566,8 +2566,11 @@ static void btrfs_read_locked_inode(struct inode *inode)  	if (!maybe_acls)  		cache_no_acl(inode); -	BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0, -						alloc_group_block, 0); +	if (leaf->map_token) { +		unmap_extent_buffer(leaf, leaf->map_token, KM_USER1); +		leaf->map_token = NULL; +	} +  	btrfs_free_path(path);  	inode_item = NULL; @@ -2647,7 +2650,7 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,  	btrfs_set_inode_transid(leaf, item, trans->transid);  	btrfs_set_inode_rdev(leaf, item, inode->i_rdev);  	btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags); -	btrfs_set_inode_block_group(leaf, item, BTRFS_I(inode)->block_group); +	btrfs_set_inode_block_group(leaf, item, 0);  	if (leaf->map_token) {  		unmap_extent_buffer(leaf, leaf->map_token, KM_USER1); @@ -3004,8 +3007,6 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)  	if (IS_ERR(trans))  		return PTR_ERR(trans); -	btrfs_set_trans_block_group(trans, dir); -  	btrfs_record_unlink_dir(trans, dir, dentry->d_inode, 0);  	ret = btrfs_unlink_inode(trans, root, dir, dentry->d_inode, @@ -3094,8 +3095,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)  	if (IS_ERR(trans))  		return PTR_ERR(trans); -	btrfs_set_trans_block_group(trans, dir); -  	if (unlikely(btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {  		err = btrfs_unlink_subvol(trans, root, dir,  					  BTRFS_I(inode)->location.objectid, @@ -3514,7 +3513,6 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)  				err = PTR_ERR(trans);  				break;  			} -			btrfs_set_trans_block_group(trans, inode);  			err = btrfs_drop_extents(trans, inode, cur_offset,  						 cur_offset + hole_size, @@ -3650,7 +3648,6 @@ void btrfs_evict_inode(struct inode *inode)  	while (1) {  		trans = btrfs_start_transaction(root, 0);  		BUG_ON(IS_ERR(trans)); -		btrfs_set_trans_block_group(trans, inode);  		trans->block_rsv = root->orphan_block_rsv;  		ret = btrfs_block_rsv_check(trans, root, @@ -4133,7 +4130,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; -	path->reada = 2; + +	path->reada = 1;  	if (key_type == BTRFS_DIR_INDEX_KEY) {  		INIT_LIST_HEAD(&ins_list); @@ -4268,18 +4266,16 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc)  	if (BTRFS_I(inode)->dummy_inode)  		return 0; -	smp_mb(); -	if (root->fs_info->closing && is_free_space_inode(root, inode)) +	if (btrfs_fs_closing(root->fs_info) && is_free_space_inode(root, inode))  		nolock = true;  	if (wbc->sync_mode == WB_SYNC_ALL) {  		if (nolock) -			trans = btrfs_join_transaction_nolock(root, 1); +			trans = btrfs_join_transaction_nolock(root);  		else -			trans = btrfs_join_transaction(root, 1); +			trans = btrfs_join_transaction(root);  		if (IS_ERR(trans))  			return PTR_ERR(trans); -		btrfs_set_trans_block_group(trans, inode);  		if (nolock)  			ret = btrfs_end_transaction_nolock(trans, root);  		else @@ -4303,9 +4299,8 @@ void btrfs_dirty_inode(struct inode *inode, int flags)  	if (BTRFS_I(inode)->dummy_inode)  		return; -	trans = btrfs_join_transaction(root, 1); +	trans = btrfs_join_transaction(root);  	BUG_ON(IS_ERR(trans)); -	btrfs_set_trans_block_group(trans, inode);  	ret = btrfs_update_inode(trans, root, inode);  	if (ret && ret == -ENOSPC) { @@ -4319,7 +4314,6 @@ void btrfs_dirty_inode(struct inode *inode, int flags)  				       PTR_ERR(trans));  			return;  		} -		btrfs_set_trans_block_group(trans, inode);  		ret = btrfs_update_inode(trans, root, inode);  		if (ret) { @@ -4418,8 +4412,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,  				     struct btrfs_root *root,  				     struct inode *dir,  				     const char *name, int name_len, -				     u64 ref_objectid, u64 objectid, -				     u64 alloc_hint, int mode, u64 *index) +				     u64 ref_objectid, u64 objectid, int mode, +				     u64 *index)  {  	struct inode *inode;  	struct btrfs_inode_item *inode_item; @@ -4472,8 +4466,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,  		owner = 0;  	else  		owner = 1; -	BTRFS_I(inode)->block_group = -			btrfs_find_block_group(root, 0, alloc_hint, owner);  	key[0].objectid = objectid;  	btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY); @@ -4629,15 +4621,13 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,  	if (IS_ERR(trans))  		return PTR_ERR(trans); -	btrfs_set_trans_block_group(trans, dir); -  	err = btrfs_find_free_ino(root, &objectid);  	if (err)  		goto out_unlock;  	inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,  				dentry->d_name.len, btrfs_ino(dir), objectid, -				BTRFS_I(dir)->block_group, mode, &index); +				mode, &index);  	if (IS_ERR(inode)) {  		err = PTR_ERR(inode);  		goto out_unlock; @@ -4649,7 +4639,6 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,  		goto out_unlock;  	} -	btrfs_set_trans_block_group(trans, inode);  	err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);  	if (err)  		drop_inode = 1; @@ -4658,8 +4647,6 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,  		init_special_inode(inode, inode->i_mode, rdev);  		btrfs_update_inode(trans, root, inode);  	} -	btrfs_update_inode_block_group(trans, inode); -	btrfs_update_inode_block_group(trans, dir);  out_unlock:  	nr = trans->blocks_used;  	btrfs_end_transaction_throttle(trans, root); @@ -4692,15 +4679,13 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,  	if (IS_ERR(trans))  		return PTR_ERR(trans); -	btrfs_set_trans_block_group(trans, dir); -  	err = btrfs_find_free_ino(root, &objectid);  	if (err)  		goto out_unlock;  	inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,  				dentry->d_name.len, btrfs_ino(dir), objectid, -				BTRFS_I(dir)->block_group, mode, &index); +				mode, &index);  	if (IS_ERR(inode)) {  		err = PTR_ERR(inode);  		goto out_unlock; @@ -4712,7 +4697,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,  		goto out_unlock;  	} -	btrfs_set_trans_block_group(trans, inode);  	err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);  	if (err)  		drop_inode = 1; @@ -4723,8 +4707,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,  		inode->i_op = &btrfs_file_inode_operations;  		BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;  	} -	btrfs_update_inode_block_group(trans, inode); -	btrfs_update_inode_block_group(trans, dir);  out_unlock:  	nr = trans->blocks_used;  	btrfs_end_transaction_throttle(trans, root); @@ -4771,8 +4753,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,  	btrfs_inc_nlink(inode);  	inode->i_ctime = CURRENT_TIME; - -	btrfs_set_trans_block_group(trans, dir);  	ihold(inode);  	err = btrfs_add_nondir(trans, dir, dentry, inode, 1, index); @@ -4781,7 +4761,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,  		drop_inode = 1;  	} else {  		struct dentry *parent = dget_parent(dentry); -		btrfs_update_inode_block_group(trans, dir);  		err = btrfs_update_inode(trans, root, inode);  		BUG_ON(err);  		btrfs_log_new_name(trans, inode, NULL, parent); @@ -4818,7 +4797,6 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	trans = btrfs_start_transaction(root, 5);  	if (IS_ERR(trans))  		return PTR_ERR(trans); -	btrfs_set_trans_block_group(trans, dir);  	err = btrfs_find_free_ino(root, &objectid);  	if (err) @@ -4826,8 +4804,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,  				dentry->d_name.len, btrfs_ino(dir), objectid, -				BTRFS_I(dir)->block_group, S_IFDIR | mode, -				&index); +				S_IFDIR | mode, &index);  	if (IS_ERR(inode)) {  		err = PTR_ERR(inode);  		goto out_fail; @@ -4841,7 +4818,6 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	inode->i_op = &btrfs_dir_inode_operations;  	inode->i_fop = &btrfs_dir_file_operations; -	btrfs_set_trans_block_group(trans, inode);  	btrfs_i_size_write(inode, 0);  	err = btrfs_update_inode(trans, root, inode); @@ -4855,8 +4831,6 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	d_instantiate(dentry, inode);  	drop_on_err = 0; -	btrfs_update_inode_block_group(trans, inode); -	btrfs_update_inode_block_group(trans, dir);  out_fail:  	nr = trans->blocks_used; @@ -4989,7 +4963,15 @@ again:  	if (!path) {  		path = btrfs_alloc_path(); -		BUG_ON(!path); +		if (!path) { +			err = -ENOMEM; +			goto out; +		} +		/* +		 * Chances are we'll be called again, so go ahead and do +		 * readahead +		 */ +		path->reada = 1;  	}  	ret = btrfs_lookup_file_extent(trans, root, path, @@ -5130,8 +5112,10 @@ again:  				kunmap(page);  				free_extent_map(em);  				em = NULL; +  				btrfs_release_path(path); -				trans = btrfs_join_transaction(root, 1); +				trans = btrfs_join_transaction(root); +  				if (IS_ERR(trans))  					return ERR_CAST(trans);  				goto again; @@ -5375,7 +5359,7 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,  		btrfs_drop_extent_cache(inode, start, start + len - 1, 0);  	} -	trans = btrfs_join_transaction(root, 0); +	trans = btrfs_join_transaction(root);  	if (IS_ERR(trans))  		return ERR_CAST(trans); @@ -5611,7 +5595,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,  		 * to make sure the current transaction stays open  		 * while we look for nocow cross refs  		 */ -		trans = btrfs_join_transaction(root, 0); +		trans = btrfs_join_transaction(root);  		if (IS_ERR(trans))  			goto must_cow; @@ -5750,7 +5734,7 @@ again:  	BUG_ON(!ordered); -	trans = btrfs_join_transaction(root, 1); +	trans = btrfs_join_transaction(root);  	if (IS_ERR(trans)) {  		err = -ENOMEM;  		goto out; @@ -6500,6 +6484,7 @@ out:  static int btrfs_truncate(struct inode *inode)  {  	struct btrfs_root *root = BTRFS_I(inode)->root; +	struct btrfs_block_rsv *rsv;  	int ret;  	int err = 0;  	struct btrfs_trans_handle *trans; @@ -6513,28 +6498,80 @@ static int btrfs_truncate(struct inode *inode)  	btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);  	btrfs_ordered_update_i_size(inode, inode->i_size, NULL); -	trans = btrfs_start_transaction(root, 5); -	if (IS_ERR(trans)) -		return PTR_ERR(trans); +	/* +	 * Yes ladies and gentelment, this is indeed ugly.  The fact is we have +	 * 3 things going on here +	 * +	 * 1) We need to reserve space for our orphan item and the space to +	 * delete our orphan item.  Lord knows we don't want to have a dangling +	 * orphan item because we didn't reserve space to remove it. +	 * +	 * 2) We need to reserve space to update our inode. +	 * +	 * 3) We need to have something to cache all the space that is going to +	 * be free'd up by the truncate operation, but also have some slack +	 * space reserved in case it uses space during the truncate (thank you +	 * very much snapshotting). +	 * +	 * And we need these to all be seperate.  The fact is we can use alot of +	 * space doing the truncate, and we have no earthly idea how much space +	 * we will use, so we need the truncate reservation to be seperate so it +	 * doesn't end up using space reserved for updating the inode or +	 * removing the orphan item.  We also need to be able to stop the +	 * transaction and start a new one, which means we need to be able to +	 * update the inode several times, and we have no idea of knowing how +	 * many times that will be, so we can't just reserve 1 item for the +	 * entirety of the opration, so that has to be done seperately as well. +	 * Then there is the orphan item, which does indeed need to be held on +	 * to for the whole operation, and we need nobody to touch this reserved +	 * space except the orphan code. +	 * +	 * So that leaves us with +	 * +	 * 1) root->orphan_block_rsv - for the orphan deletion. +	 * 2) rsv - for the truncate reservation, which we will steal from the +	 * transaction reservation. +	 * 3) fs_info->trans_block_rsv - this will have 1 items worth left for +	 * updating the inode. +	 */ +	rsv = btrfs_alloc_block_rsv(root); +	if (!rsv) +		return -ENOMEM; +	btrfs_add_durable_block_rsv(root->fs_info, rsv); + +	trans = btrfs_start_transaction(root, 4); +	if (IS_ERR(trans)) { +		err = PTR_ERR(trans); +		goto out; +	} -	btrfs_set_trans_block_group(trans, inode); +	/* +	 * Reserve space for the truncate process.  Truncate should be adding +	 * space, but if there are snapshots it may end up using space. +	 */ +	ret = btrfs_truncate_reserve_metadata(trans, root, rsv); +	BUG_ON(ret);  	ret = btrfs_orphan_add(trans, inode);  	if (ret) {  		btrfs_end_transaction(trans, root); -		return ret; +		goto out;  	}  	nr = trans->blocks_used;  	btrfs_end_transaction(trans, root);  	btrfs_btree_balance_dirty(root, nr); -	/* Now start a transaction for the truncate */ -	trans = btrfs_start_transaction(root, 0); -	if (IS_ERR(trans)) -		return PTR_ERR(trans); -	btrfs_set_trans_block_group(trans, inode); -	trans->block_rsv = root->orphan_block_rsv; +	/* +	 * Ok so we've already migrated our bytes over for the truncate, so here +	 * just reserve the one slot we need for updating the inode. +	 */ +	trans = btrfs_start_transaction(root, 1); +	if (IS_ERR(trans)) { +		err = PTR_ERR(trans); +		goto out; +	} +	trans->block_rsv = rsv;  	/*  	 * setattr is responsible for setting the ordered_data_close flag, @@ -6558,24 +6595,17 @@ static int btrfs_truncate(struct inode *inode)  	while (1) {  		if (!trans) { -			trans = btrfs_start_transaction(root, 0); -			if (IS_ERR(trans)) -				return PTR_ERR(trans); -			btrfs_set_trans_block_group(trans, inode); -			trans->block_rsv = root->orphan_block_rsv; -		} +			trans = btrfs_start_transaction(root, 3); +			if (IS_ERR(trans)) { +				err = PTR_ERR(trans); +				goto out; +			} -		ret = btrfs_block_rsv_check(trans, root, -					    root->orphan_block_rsv, 0, 5); -		if (ret == -EAGAIN) { -			ret = btrfs_commit_transaction(trans, root); -			if (ret) -				return ret; -			trans = NULL; -			continue; -		} else if (ret) { -			err = ret; -			break; +			ret = btrfs_truncate_reserve_metadata(trans, root, +							      rsv); +			BUG_ON(ret); + +			trans->block_rsv = rsv;  		}  		ret = btrfs_truncate_inode_items(trans, root, inode, @@ -6586,6 +6616,7 @@ static int btrfs_truncate(struct inode *inode)  			break;  		} +		trans->block_rsv = &root->fs_info->trans_block_rsv;  		ret = btrfs_update_inode(trans, root, inode);  		if (ret) {  			err = ret; @@ -6599,6 +6630,7 @@ static int btrfs_truncate(struct inode *inode)  	}  	if (ret == 0 && inode->i_nlink > 0) { +		trans->block_rsv = root->orphan_block_rsv;  		ret = btrfs_orphan_del(trans, inode);  		if (ret)  			err = ret; @@ -6610,15 +6642,20 @@ static int btrfs_truncate(struct inode *inode)  		ret = btrfs_orphan_del(NULL, inode);  	} +	trans->block_rsv = &root->fs_info->trans_block_rsv;  	ret = btrfs_update_inode(trans, root, inode);  	if (ret && !err)  		err = ret;  	nr = trans->blocks_used;  	ret = btrfs_end_transaction_throttle(trans, root); +	btrfs_btree_balance_dirty(root, nr); + +out: +	btrfs_free_block_rsv(root, rsv); +  	if (ret && !err)  		err = ret; -	btrfs_btree_balance_dirty(root, nr);  	return err;  } @@ -6627,15 +6664,14 @@ static int btrfs_truncate(struct inode *inode)   * create a new subvolume directory/inode (helper for the ioctl).   */  int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, -			     struct btrfs_root *new_root, -			     u64 new_dirid, u64 alloc_hint) +			     struct btrfs_root *new_root, u64 new_dirid)  {  	struct inode *inode;  	int err;  	u64 index = 0;  	inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid, -				new_dirid, alloc_hint, S_IFDIR | 0700, &index); +				new_dirid, S_IFDIR | 0700, &index);  	if (IS_ERR(inode))  		return PTR_ERR(inode);  	inode->i_op = &btrfs_dir_inode_operations; @@ -6748,21 +6784,6 @@ void btrfs_destroy_inode(struct inode *inode)  		spin_unlock(&root->fs_info->ordered_extent_lock);  	} -	if (root == root->fs_info->tree_root) { -		struct btrfs_block_group_cache *block_group; - -		block_group = btrfs_lookup_block_group(root->fs_info, -						BTRFS_I(inode)->block_group); -		if (block_group && block_group->inode == inode) { -			spin_lock(&block_group->lock); -			block_group->inode = NULL; -			spin_unlock(&block_group->lock); -			btrfs_put_block_group(block_group); -		} else if (block_group) { -			btrfs_put_block_group(block_group); -		} -	} -  	spin_lock(&root->orphan_lock);  	if (!list_empty(&BTRFS_I(inode)->i_orphan)) {  		printk(KERN_INFO "BTRFS: inode %llu still on the orphan list\n", @@ -6948,8 +6969,6 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,                  goto out_notrans;          } -	btrfs_set_trans_block_group(trans, new_dir); -  	if (dest != root)  		btrfs_record_root_in_trans(trans, dest); @@ -7131,16 +7150,13 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,  	if (IS_ERR(trans))  		return PTR_ERR(trans); -	btrfs_set_trans_block_group(trans, dir); -  	err = btrfs_find_free_ino(root, &objectid);  	if (err)  		goto out_unlock;  	inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,  				dentry->d_name.len, btrfs_ino(dir), objectid, -				BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO, -				&index); +				S_IFLNK|S_IRWXUGO, &index);  	if (IS_ERR(inode)) {  		err = PTR_ERR(inode);  		goto out_unlock; @@ -7152,7 +7168,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,  		goto out_unlock;  	} -	btrfs_set_trans_block_group(trans, inode);  	err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);  	if (err)  		drop_inode = 1; @@ -7163,8 +7178,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,  		inode->i_op = &btrfs_file_inode_operations;  		BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;  	} -	btrfs_update_inode_block_group(trans, inode); -	btrfs_update_inode_block_group(trans, dir);  	if (drop_inode)  		goto out_unlock; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 85e818ce00c..ac37040e426 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -243,7 +243,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)  		ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);  	} -	trans = btrfs_join_transaction(root, 1); +	trans = btrfs_join_transaction(root);  	BUG_ON(IS_ERR(trans));  	ret = btrfs_update_inode(trans, root, inode); @@ -414,8 +414,7 @@ static noinline int create_subvol(struct btrfs_root *root,  	btrfs_record_root_in_trans(trans, new_root); -	ret = btrfs_create_subvol_root(trans, new_root, new_dirid, -				       BTRFS_I(dir)->block_group); +	ret = btrfs_create_subvol_root(trans, new_root, new_dirid);  	/*  	 * insert the directory item  	 */ @@ -707,16 +706,17 @@ static int find_new_extents(struct btrfs_root *root,  	struct btrfs_file_extent_item *extent;  	int type;  	int ret; +	u64 ino = btrfs_ino(inode);  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; -	min_key.objectid = inode->i_ino; +	min_key.objectid = ino;  	min_key.type = BTRFS_EXTENT_DATA_KEY;  	min_key.offset = *off; -	max_key.objectid = inode->i_ino; +	max_key.objectid = ino;  	max_key.type = (u8)-1;  	max_key.offset = (u64)-1; @@ -727,7 +727,7 @@ static int find_new_extents(struct btrfs_root *root,  					   path, 0, newer_than);  		if (ret != 0)  			goto none; -		if (min_key.objectid != inode->i_ino) +		if (min_key.objectid != ino)  			goto none;  		if (min_key.type != BTRFS_EXTENT_DATA_KEY)  			goto none; @@ -2489,12 +2489,10 @@ static long btrfs_ioctl_trans_start(struct file *file)  	if (ret)  		goto out; -	mutex_lock(&root->fs_info->trans_mutex); -	root->fs_info->open_ioctl_trans++; -	mutex_unlock(&root->fs_info->trans_mutex); +	atomic_inc(&root->fs_info->open_ioctl_trans);  	ret = -ENOMEM; -	trans = btrfs_start_ioctl_transaction(root, 0); +	trans = btrfs_start_ioctl_transaction(root);  	if (IS_ERR(trans))  		goto out_drop; @@ -2502,9 +2500,7 @@ static long btrfs_ioctl_trans_start(struct file *file)  	return 0;  out_drop: -	mutex_lock(&root->fs_info->trans_mutex); -	root->fs_info->open_ioctl_trans--; -	mutex_unlock(&root->fs_info->trans_mutex); +	atomic_dec(&root->fs_info->open_ioctl_trans);  	mnt_drop_write(file->f_path.mnt);  out:  	return ret; @@ -2738,9 +2734,7 @@ long btrfs_ioctl_trans_end(struct file *file)  	btrfs_end_transaction(trans, root); -	mutex_lock(&root->fs_info->trans_mutex); -	root->fs_info->open_ioctl_trans--; -	mutex_unlock(&root->fs_info->trans_mutex); +	atomic_dec(&root->fs_info->open_ioctl_trans);  	mnt_drop_write(file->f_path.mnt);  	return 0; diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index ca38eca70af..b1ef27cc673 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -677,6 +677,8 @@ struct backref_node *build_backref_tree(struct reloc_control *rc,  		err = -ENOMEM;  		goto out;  	} +	path1->reada = 1; +	path2->reada = 2;  	node = alloc_backref_node(cache);  	if (!node) { @@ -1999,6 +2001,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; +	path->reada = 1;  	reloc_root = root->reloc_root;  	root_item = &reloc_root->root_item; @@ -2139,10 +2142,10 @@ int prepare_to_merge(struct reloc_control *rc, int err)  	u64 num_bytes = 0;  	int ret; -	mutex_lock(&root->fs_info->trans_mutex); +	spin_lock(&root->fs_info->trans_lock);  	rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2;  	rc->merging_rsv_size += rc->nodes_relocated * 2; -	mutex_unlock(&root->fs_info->trans_mutex); +	spin_unlock(&root->fs_info->trans_lock);  again:  	if (!err) {  		num_bytes = rc->merging_rsv_size; @@ -2152,7 +2155,7 @@ again:  			err = ret;  	} -	trans = btrfs_join_transaction(rc->extent_root, 1); +	trans = btrfs_join_transaction(rc->extent_root);  	if (IS_ERR(trans)) {  		if (!err)  			btrfs_block_rsv_release(rc->extent_root, @@ -2211,9 +2214,9 @@ int merge_reloc_roots(struct reloc_control *rc)  	int ret;  again:  	root = rc->extent_root; -	mutex_lock(&root->fs_info->trans_mutex); +	spin_lock(&root->fs_info->trans_lock);  	list_splice_init(&rc->reloc_roots, &reloc_roots); -	mutex_unlock(&root->fs_info->trans_mutex); +	spin_unlock(&root->fs_info->trans_lock);  	while (!list_empty(&reloc_roots)) {  		found = 1; @@ -3236,7 +3239,7 @@ truncate:  		goto out;  	} -	trans = btrfs_join_transaction(root, 0); +	trans = btrfs_join_transaction(root);  	if (IS_ERR(trans)) {  		btrfs_free_path(path);  		ret = PTR_ERR(trans); @@ -3300,6 +3303,7 @@ static int find_data_references(struct reloc_control *rc,  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; +	path->reada = 1;  	root = read_fs_root(rc->extent_root->fs_info, ref_root);  	if (IS_ERR(root)) { @@ -3586,17 +3590,17 @@ next:  static void set_reloc_control(struct reloc_control *rc)  {  	struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; -	mutex_lock(&fs_info->trans_mutex); +	spin_lock(&fs_info->trans_lock);  	fs_info->reloc_ctl = rc; -	mutex_unlock(&fs_info->trans_mutex); +	spin_unlock(&fs_info->trans_lock);  }  static void unset_reloc_control(struct reloc_control *rc)  {  	struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; -	mutex_lock(&fs_info->trans_mutex); +	spin_lock(&fs_info->trans_lock);  	fs_info->reloc_ctl = NULL; -	mutex_unlock(&fs_info->trans_mutex); +	spin_unlock(&fs_info->trans_lock);  }  static int check_extent_flags(u64 flags) @@ -3645,7 +3649,7 @@ int prepare_to_relocate(struct reloc_control *rc)  	rc->create_reloc_tree = 1;  	set_reloc_control(rc); -	trans = btrfs_join_transaction(rc->extent_root, 1); +	trans = btrfs_join_transaction(rc->extent_root);  	BUG_ON(IS_ERR(trans));  	btrfs_commit_transaction(trans, rc->extent_root);  	return 0; @@ -3668,6 +3672,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; +	path->reada = 1;  	ret = prepare_to_relocate(rc);  	if (ret) { @@ -3834,7 +3839,7 @@ restart:  	btrfs_block_rsv_release(rc->extent_root, rc->block_rsv, (u64)-1);  	/* get rid of pinned extents */ -	trans = btrfs_join_transaction(rc->extent_root, 1); +	trans = btrfs_join_transaction(rc->extent_root);  	if (IS_ERR(trans))  		err = PTR_ERR(trans);  	else @@ -4093,6 +4098,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)  	path = btrfs_alloc_path();  	if (!path)  		return -ENOMEM; +	path->reada = -1;  	key.objectid = BTRFS_TREE_RELOC_OBJECTID;  	key.type = BTRFS_ROOT_ITEM_KEY; @@ -4159,7 +4165,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)  	set_reloc_control(rc); -	trans = btrfs_join_transaction(rc->extent_root, 1); +	trans = btrfs_join_transaction(rc->extent_root);  	if (IS_ERR(trans)) {  		unset_reloc_control(rc);  		err = PTR_ERR(trans); @@ -4193,7 +4199,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)  	unset_reloc_control(rc); -	trans = btrfs_join_transaction(rc->extent_root, 1); +	trans = btrfs_join_transaction(rc->extent_root);  	if (IS_ERR(trans))  		err = PTR_ERR(trans);  	else diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 6dfed0c27ac..df50fd1eca8 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -117,33 +117,37 @@ static void scrub_free_csums(struct scrub_dev *sdev)  	}  } +static void scrub_free_bio(struct bio *bio) +{ +	int i; +	struct page *last_page = NULL; + +	if (!bio) +		return; + +	for (i = 0; i < bio->bi_vcnt; ++i) { +		if (bio->bi_io_vec[i].bv_page == last_page) +			continue; +		last_page = bio->bi_io_vec[i].bv_page; +		__free_page(last_page); +	} +	bio_put(bio); +} +  static noinline_for_stack void scrub_free_dev(struct scrub_dev *sdev)  {  	int i; -	int j; -	struct page *last_page;  	if (!sdev)  		return;  	for (i = 0; i < SCRUB_BIOS_PER_DEV; ++i) {  		struct scrub_bio *sbio = sdev->bios[i]; -		struct bio *bio;  		if (!sbio)  			break; -		bio = sbio->bio; -		if (bio) { -			last_page = NULL; -			for (j = 0; j < bio->bi_vcnt; ++j) { -				if (bio->bi_io_vec[j].bv_page == last_page) -					continue; -				last_page = bio->bi_io_vec[j].bv_page; -				__free_page(last_page); -			} -			bio_put(bio); -		} +		scrub_free_bio(sbio->bio);  		kfree(sbio);  	} @@ -156,8 +160,6 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev)  {  	struct scrub_dev *sdev;  	int		i; -	int		j; -	int		ret;  	struct btrfs_fs_info *fs_info = dev->dev_root->fs_info;  	sdev = kzalloc(sizeof(*sdev), GFP_NOFS); @@ -165,7 +167,6 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev)  		goto nomem;  	sdev->dev = dev;  	for (i = 0; i < SCRUB_BIOS_PER_DEV; ++i) { -		struct bio *bio;  		struct scrub_bio *sbio;  		sbio = kzalloc(sizeof(*sbio), GFP_NOFS); @@ -173,32 +174,10 @@ struct scrub_dev *scrub_setup_dev(struct btrfs_device *dev)  			goto nomem;  		sdev->bios[i] = sbio; -		bio = bio_kmalloc(GFP_NOFS, SCRUB_PAGES_PER_BIO); -		if (!bio) -			goto nomem; -  		sbio->index = i;  		sbio->sdev = sdev; -		sbio->bio = bio;  		sbio->count = 0;  		sbio->work.func = scrub_checksum; -		bio->bi_private = sdev->bios[i]; -		bio->bi_end_io = scrub_bio_end_io; -		bio->bi_sector = 0; -		bio->bi_bdev = dev->bdev; -		bio->bi_size = 0; - -		for (j = 0; j < SCRUB_PAGES_PER_BIO; ++j) { -			struct page *page; -			page = alloc_page(GFP_NOFS); -			if (!page) -				goto nomem; - -			ret = bio_add_page(bio, page, PAGE_SIZE, 0); -			if (!ret) -				goto nomem; -		} -		WARN_ON(bio->bi_vcnt != SCRUB_PAGES_PER_BIO);  		if (i != SCRUB_BIOS_PER_DEV-1)  			sdev->bios[i]->next_free = i + 1; @@ -369,9 +348,6 @@ static int scrub_fixup_io(int rw, struct block_device *bdev, sector_t sector,  	int ret;  	DECLARE_COMPLETION_ONSTACK(complete); -	/* we are going to wait on this IO */ -	rw |= REQ_SYNC; -  	bio = bio_alloc(GFP_NOFS, 1);  	bio->bi_bdev = bdev;  	bio->bi_sector = sector; @@ -380,6 +356,7 @@ static int scrub_fixup_io(int rw, struct block_device *bdev, sector_t sector,  	bio->bi_private = &complete;  	submit_bio(rw, bio); +	/* this will also unplug the queue */  	wait_for_completion(&complete);  	ret = !test_bit(BIO_UPTODATE, &bio->bi_flags); @@ -394,6 +371,7 @@ static void scrub_bio_end_io(struct bio *bio, int err)  	struct btrfs_fs_info *fs_info = sdev->dev->dev_root->fs_info;  	sbio->err = err; +	sbio->bio = bio;  	btrfs_queue_worker(&fs_info->scrub_workers, &sbio->work);  } @@ -453,6 +431,8 @@ static void scrub_checksum(struct btrfs_work *work)  	}  out: +	scrub_free_bio(sbio->bio); +	sbio->bio = NULL;  	spin_lock(&sdev->list_lock);  	sbio->next_free = sdev->first_free;  	sdev->first_free = sbio->index; @@ -583,25 +563,50 @@ static int scrub_checksum_super(struct scrub_bio *sbio, void *buffer)  static int scrub_submit(struct scrub_dev *sdev)  {  	struct scrub_bio *sbio; +	struct bio *bio; +	int i;  	if (sdev->curr == -1)  		return 0;  	sbio = sdev->bios[sdev->curr]; -	sbio->bio->bi_sector = sbio->physical >> 9; -	sbio->bio->bi_size = sbio->count * PAGE_SIZE; -	sbio->bio->bi_next = NULL; -	sbio->bio->bi_flags |= 1 << BIO_UPTODATE; -	sbio->bio->bi_comp_cpu = -1; -	sbio->bio->bi_bdev = sdev->dev->bdev; +	bio = bio_alloc(GFP_NOFS, sbio->count); +	if (!bio) +		goto nomem; + +	bio->bi_private = sbio; +	bio->bi_end_io = scrub_bio_end_io; +	bio->bi_bdev = sdev->dev->bdev; +	bio->bi_sector = sbio->physical >> 9; + +	for (i = 0; i < sbio->count; ++i) { +		struct page *page; +		int ret; + +		page = alloc_page(GFP_NOFS); +		if (!page) +			goto nomem; + +		ret = bio_add_page(bio, page, PAGE_SIZE, 0); +		if (!ret) { +			__free_page(page); +			goto nomem; +		} +	} +  	sbio->err = 0;  	sdev->curr = -1;  	atomic_inc(&sdev->in_flight); -	submit_bio(0, sbio->bio); +	submit_bio(READ, bio);  	return 0; + +nomem: +	scrub_free_bio(bio); + +	return -ENOMEM;  }  static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len, @@ -633,7 +638,11 @@ again:  		sbio->logical = logical;  	} else if (sbio->physical + sbio->count * PAGE_SIZE != physical ||  		   sbio->logical + sbio->count * PAGE_SIZE != logical) { -		scrub_submit(sdev); +		int ret; + +		ret = scrub_submit(sdev); +		if (ret) +			return ret;  		goto again;  	}  	sbio->spag[sbio->count].flags = flags; @@ -645,8 +654,13 @@ again:  		memcpy(sbio->spag[sbio->count].csum, csum, sdev->csum_size);  	}  	++sbio->count; -	if (sbio->count == SCRUB_PAGES_PER_BIO || force) -		scrub_submit(sdev); +	if (sbio->count == SCRUB_PAGES_PER_BIO || force) { +		int ret; + +		ret = scrub_submit(sdev); +		if (ret) +			return ret; +	}  	return 0;  } @@ -727,6 +741,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev,  	struct btrfs_root *root = fs_info->extent_root;  	struct btrfs_root *csum_root = fs_info->csum_root;  	struct btrfs_extent_item *extent; +	struct blk_plug plug;  	u64 flags;  	int ret;  	int slot; @@ -831,6 +846,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_dev *sdev,  	 * the scrub. This might currently (crc32) end up to be about 1MB  	 */  	start_stripe = 0; +	blk_start_plug(&plug);  again:  	logical = base + offset + start_stripe * increment;  	for (i = start_stripe; i < nstripes; ++i) { @@ -972,6 +988,7 @@ next:  	scrub_submit(sdev);  out: +	blk_finish_plug(&plug);  	btrfs_free_path(path);  	return ret < 0 ? ret : 0;  } @@ -1166,7 +1183,7 @@ int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end,  	int ret;  	struct btrfs_device *dev; -	if (root->fs_info->closing) +	if (btrfs_fs_closing(root->fs_info))  		return -EINVAL;  	/* diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 9b2e7e5bc3e..117e74e3604 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -161,7 +161,8 @@ enum {  	Opt_compress_type, Opt_compress_force, Opt_compress_force_type,  	Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard,  	Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, -	Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_err, +	Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, +	Opt_inode_cache, Opt_err,  };  static match_table_t tokens = { @@ -193,6 +194,7 @@ static match_table_t tokens = {  	{Opt_enospc_debug, "enospc_debug"},  	{Opt_subvolrootid, "subvolrootid=%d"},  	{Opt_defrag, "autodefrag"}, +	{Opt_inode_cache, "inode_cache"},  	{Opt_err, NULL},  }; @@ -361,6 +363,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)  			printk(KERN_INFO "btrfs: enabling disk space caching\n");  			btrfs_set_opt(info->mount_opt, SPACE_CACHE);  			break; +		case Opt_inode_cache: +			printk(KERN_INFO "btrfs: enabling inode map caching\n"); +			btrfs_set_opt(info->mount_opt, INODE_MAP_CACHE); +			break;  		case Opt_clear_cache:  			printk(KERN_INFO "btrfs: force clearing of disk cache\n");  			btrfs_set_opt(info->mount_opt, CLEAR_CACHE); diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index dc80f715692..dd719662340 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -35,6 +35,7 @@ static noinline void put_transaction(struct btrfs_transaction *transaction)  {  	WARN_ON(atomic_read(&transaction->use_count) == 0);  	if (atomic_dec_and_test(&transaction->use_count)) { +		BUG_ON(!list_empty(&transaction->list));  		memset(transaction, 0, sizeof(*transaction));  		kmem_cache_free(btrfs_transaction_cachep, transaction);  	} @@ -49,46 +50,72 @@ static noinline void switch_commit_root(struct btrfs_root *root)  /*   * either allocate a new transaction or hop into the existing one   */ -static noinline int join_transaction(struct btrfs_root *root) +static noinline int join_transaction(struct btrfs_root *root, int nofail)  {  	struct btrfs_transaction *cur_trans; -	cur_trans = root->fs_info->running_transaction; -	if (!cur_trans) { -		cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, -					     GFP_NOFS); -		if (!cur_trans) -			return -ENOMEM; -		root->fs_info->generation++; -		atomic_set(&cur_trans->num_writers, 1); -		cur_trans->num_joined = 0; -		cur_trans->transid = root->fs_info->generation; -		init_waitqueue_head(&cur_trans->writer_wait); -		init_waitqueue_head(&cur_trans->commit_wait); -		cur_trans->in_commit = 0; -		cur_trans->blocked = 0; -		atomic_set(&cur_trans->use_count, 1); -		cur_trans->commit_done = 0; -		cur_trans->start_time = get_seconds(); -		cur_trans->delayed_refs.root = RB_ROOT; -		cur_trans->delayed_refs.num_entries = 0; -		cur_trans->delayed_refs.num_heads_ready = 0; -		cur_trans->delayed_refs.num_heads = 0; -		cur_trans->delayed_refs.flushing = 0; -		cur_trans->delayed_refs.run_delayed_start = 0; -		spin_lock_init(&cur_trans->delayed_refs.lock); +	spin_lock(&root->fs_info->trans_lock); +	if (root->fs_info->trans_no_join) { +		if (!nofail) { +			spin_unlock(&root->fs_info->trans_lock); +			return -EBUSY; +		} +	} -		INIT_LIST_HEAD(&cur_trans->pending_snapshots); -		list_add_tail(&cur_trans->list, &root->fs_info->trans_list); -		extent_io_tree_init(&cur_trans->dirty_pages, -				     root->fs_info->btree_inode->i_mapping); -		spin_lock(&root->fs_info->new_trans_lock); -		root->fs_info->running_transaction = cur_trans; -		spin_unlock(&root->fs_info->new_trans_lock); -	} else { +	cur_trans = root->fs_info->running_transaction; +	if (cur_trans) { +		atomic_inc(&cur_trans->use_count); +		atomic_inc(&cur_trans->num_writers); +		cur_trans->num_joined++; +		spin_unlock(&root->fs_info->trans_lock); +		return 0; +	} +	spin_unlock(&root->fs_info->trans_lock); + +	cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS); +	if (!cur_trans) +		return -ENOMEM; +	spin_lock(&root->fs_info->trans_lock); +	if (root->fs_info->running_transaction) { +		kmem_cache_free(btrfs_transaction_cachep, cur_trans); +		cur_trans = root->fs_info->running_transaction; +		atomic_inc(&cur_trans->use_count);  		atomic_inc(&cur_trans->num_writers);  		cur_trans->num_joined++; +		spin_unlock(&root->fs_info->trans_lock); +		return 0;  	} +	atomic_set(&cur_trans->num_writers, 1); +	cur_trans->num_joined = 0; +	init_waitqueue_head(&cur_trans->writer_wait); +	init_waitqueue_head(&cur_trans->commit_wait); +	cur_trans->in_commit = 0; +	cur_trans->blocked = 0; +	/* +	 * One for this trans handle, one so it will live on until we +	 * commit the transaction. +	 */ +	atomic_set(&cur_trans->use_count, 2); +	cur_trans->commit_done = 0; +	cur_trans->start_time = get_seconds(); + +	cur_trans->delayed_refs.root = RB_ROOT; +	cur_trans->delayed_refs.num_entries = 0; +	cur_trans->delayed_refs.num_heads_ready = 0; +	cur_trans->delayed_refs.num_heads = 0; +	cur_trans->delayed_refs.flushing = 0; +	cur_trans->delayed_refs.run_delayed_start = 0; +	spin_lock_init(&cur_trans->commit_lock); +	spin_lock_init(&cur_trans->delayed_refs.lock); + +	INIT_LIST_HEAD(&cur_trans->pending_snapshots); +	list_add_tail(&cur_trans->list, &root->fs_info->trans_list); +	extent_io_tree_init(&cur_trans->dirty_pages, +			     root->fs_info->btree_inode->i_mapping); +	root->fs_info->generation++; +	cur_trans->transid = root->fs_info->generation; +	root->fs_info->running_transaction = cur_trans; +	spin_unlock(&root->fs_info->trans_lock);  	return 0;  } @@ -99,39 +126,28 @@ static noinline int join_transaction(struct btrfs_root *root)   * to make sure the old root from before we joined the transaction is deleted   * when the transaction commits   */ -static noinline int record_root_in_trans(struct btrfs_trans_handle *trans, -					 struct btrfs_root *root) +int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, +			       struct btrfs_root *root)  {  	if (root->ref_cows && root->last_trans < trans->transid) {  		WARN_ON(root == root->fs_info->extent_root);  		WARN_ON(root->commit_root != root->node); +		spin_lock(&root->fs_info->fs_roots_radix_lock); +		if (root->last_trans == trans->transid) { +			spin_unlock(&root->fs_info->fs_roots_radix_lock); +			return 0; +		} +		root->last_trans = trans->transid;  		radix_tree_tag_set(&root->fs_info->fs_roots_radix,  			   (unsigned long)root->root_key.objectid,  			   BTRFS_ROOT_TRANS_TAG); -		root->last_trans = trans->transid; +		spin_unlock(&root->fs_info->fs_roots_radix_lock);  		btrfs_init_reloc_root(trans, root);  	}  	return 0;  } -int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, -			       struct btrfs_root *root) -{ -	if (!root->ref_cows) -		return 0; - -	mutex_lock(&root->fs_info->trans_mutex); -	if (root->last_trans == trans->transid) { -		mutex_unlock(&root->fs_info->trans_mutex); -		return 0; -	} - -	record_root_in_trans(trans, root); -	mutex_unlock(&root->fs_info->trans_mutex); -	return 0; -} -  /* wait for commit against the current transaction to become unblocked   * when this is done, it is safe to start a new transaction, but the current   * transaction might not be fully on disk. @@ -140,21 +156,23 @@ static void wait_current_trans(struct btrfs_root *root)  {  	struct btrfs_transaction *cur_trans; +	spin_lock(&root->fs_info->trans_lock);  	cur_trans = root->fs_info->running_transaction;  	if (cur_trans && cur_trans->blocked) {  		DEFINE_WAIT(wait);  		atomic_inc(&cur_trans->use_count); +		spin_unlock(&root->fs_info->trans_lock);  		while (1) {  			prepare_to_wait(&root->fs_info->transaction_wait, &wait,  					TASK_UNINTERRUPTIBLE);  			if (!cur_trans->blocked)  				break; -			mutex_unlock(&root->fs_info->trans_mutex);  			schedule(); -			mutex_lock(&root->fs_info->trans_mutex);  		}  		finish_wait(&root->fs_info->transaction_wait, &wait);  		put_transaction(cur_trans); +	} else { +		spin_unlock(&root->fs_info->trans_lock);  	}  } @@ -167,10 +185,16 @@ enum btrfs_trans_type {  static int may_wait_transaction(struct btrfs_root *root, int type)  { -	if (!root->fs_info->log_root_recovering && -	    ((type == TRANS_START && !root->fs_info->open_ioctl_trans) || -	     type == TRANS_USERSPACE)) +	if (root->fs_info->log_root_recovering) +		return 0; + +	if (type == TRANS_USERSPACE) +		return 1; + +	if (type == TRANS_START && +	    !atomic_read(&root->fs_info->open_ioctl_trans))  		return 1; +  	return 0;  } @@ -184,36 +208,44 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,  	if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)  		return ERR_PTR(-EROFS); + +	if (current->journal_info) { +		WARN_ON(type != TRANS_JOIN && type != TRANS_JOIN_NOLOCK); +		h = current->journal_info; +		h->use_count++; +		h->orig_rsv = h->block_rsv; +		h->block_rsv = NULL; +		goto got_it; +	}  again:  	h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);  	if (!h)  		return ERR_PTR(-ENOMEM); -	if (type != TRANS_JOIN_NOLOCK) -		mutex_lock(&root->fs_info->trans_mutex);  	if (may_wait_transaction(root, type))  		wait_current_trans(root); -	ret = join_transaction(root); +	do { +		ret = join_transaction(root, type == TRANS_JOIN_NOLOCK); +		if (ret == -EBUSY) +			wait_current_trans(root); +	} while (ret == -EBUSY); +  	if (ret < 0) {  		kmem_cache_free(btrfs_trans_handle_cachep, h); -		if (type != TRANS_JOIN_NOLOCK) -			mutex_unlock(&root->fs_info->trans_mutex);  		return ERR_PTR(ret);  	}  	cur_trans = root->fs_info->running_transaction; -	atomic_inc(&cur_trans->use_count); -	if (type != TRANS_JOIN_NOLOCK) -		mutex_unlock(&root->fs_info->trans_mutex);  	h->transid = cur_trans->transid;  	h->transaction = cur_trans;  	h->blocks_used = 0; -	h->block_group = 0;  	h->bytes_reserved = 0;  	h->delayed_ref_updates = 0; +	h->use_count = 1;  	h->block_rsv = NULL; +	h->orig_rsv = NULL;  	smp_mb();  	if (cur_trans->blocked && may_wait_transaction(root, type)) { @@ -241,11 +273,8 @@ again:  		}  	} -	if (type != TRANS_JOIN_NOLOCK) -		mutex_lock(&root->fs_info->trans_mutex); -	record_root_in_trans(h, root); -	if (type != TRANS_JOIN_NOLOCK) -		mutex_unlock(&root->fs_info->trans_mutex); +got_it: +	btrfs_record_root_in_trans(h, root);  	if (!current->journal_info && type != TRANS_USERSPACE)  		current->journal_info = h; @@ -257,22 +286,19 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,  {  	return start_transaction(root, num_items, TRANS_START);  } -struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root, -						   int num_blocks) +struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root)  {  	return start_transaction(root, 0, TRANS_JOIN);  } -struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root, -							  int num_blocks) +struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root)  {  	return start_transaction(root, 0, TRANS_JOIN_NOLOCK);  } -struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, -							 int num_blocks) +struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root)  { -	return start_transaction(r, 0, TRANS_USERSPACE); +	return start_transaction(root, 0, TRANS_USERSPACE);  }  /* wait for a transaction commit to be fully complete */ @@ -280,17 +306,13 @@ static noinline int wait_for_commit(struct btrfs_root *root,  				    struct btrfs_transaction *commit)  {  	DEFINE_WAIT(wait); -	mutex_lock(&root->fs_info->trans_mutex);  	while (!commit->commit_done) {  		prepare_to_wait(&commit->commit_wait, &wait,  				TASK_UNINTERRUPTIBLE);  		if (commit->commit_done)  			break; -		mutex_unlock(&root->fs_info->trans_mutex);  		schedule(); -		mutex_lock(&root->fs_info->trans_mutex);  	} -	mutex_unlock(&root->fs_info->trans_mutex);  	finish_wait(&commit->commit_wait, &wait);  	return 0;  } @@ -300,59 +322,56 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid)  	struct btrfs_transaction *cur_trans = NULL, *t;  	int ret; -	mutex_lock(&root->fs_info->trans_mutex); -  	ret = 0;  	if (transid) {  		if (transid <= root->fs_info->last_trans_committed) -			goto out_unlock; +			goto out;  		/* find specified transaction */ +		spin_lock(&root->fs_info->trans_lock);  		list_for_each_entry(t, &root->fs_info->trans_list, list) {  			if (t->transid == transid) {  				cur_trans = t; +				atomic_inc(&cur_trans->use_count);  				break;  			}  			if (t->transid > transid)  				break;  		} +		spin_unlock(&root->fs_info->trans_lock);  		ret = -EINVAL;  		if (!cur_trans) -			goto out_unlock;  /* bad transid */ +			goto out;  /* bad transid */  	} else {  		/* find newest transaction that is committing | committed */ +		spin_lock(&root->fs_info->trans_lock);  		list_for_each_entry_reverse(t, &root->fs_info->trans_list,  					    list) {  			if (t->in_commit) {  				if (t->commit_done) -					goto out_unlock; +					goto out;  				cur_trans = t; +				atomic_inc(&cur_trans->use_count);  				break;  			}  		} +		spin_unlock(&root->fs_info->trans_lock);  		if (!cur_trans) -			goto out_unlock;  /* nothing committing|committed */ +			goto out;  /* nothing committing|committed */  	} -	atomic_inc(&cur_trans->use_count); -	mutex_unlock(&root->fs_info->trans_mutex); -  	wait_for_commit(root, cur_trans); -	mutex_lock(&root->fs_info->trans_mutex);  	put_transaction(cur_trans);  	ret = 0; -out_unlock: -	mutex_unlock(&root->fs_info->trans_mutex); +out:  	return ret;  }  void btrfs_throttle(struct btrfs_root *root)  { -	mutex_lock(&root->fs_info->trans_mutex); -	if (!root->fs_info->open_ioctl_trans) +	if (!atomic_read(&root->fs_info->open_ioctl_trans))  		wait_current_trans(root); -	mutex_unlock(&root->fs_info->trans_mutex);  }  static int should_end_transaction(struct btrfs_trans_handle *trans, @@ -370,6 +389,7 @@ int btrfs_should_end_transaction(struct btrfs_trans_handle *trans,  	struct btrfs_transaction *cur_trans = trans->transaction;  	int updates; +	smp_mb();  	if (cur_trans->blocked || cur_trans->delayed_refs.flushing)  		return 1; @@ -388,6 +408,11 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,  	struct btrfs_fs_info *info = root->fs_info;  	int count = 0; +	if (--trans->use_count) { +		trans->block_rsv = trans->orig_rsv; +		return 0; +	} +  	while (count < 4) {  		unsigned long cur = trans->delayed_ref_updates;  		trans->delayed_ref_updates = 0; @@ -410,9 +435,11 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,  	btrfs_trans_release_metadata(trans, root); -	if (lock && !root->fs_info->open_ioctl_trans && -	    should_end_transaction(trans, root)) +	if (lock && !atomic_read(&root->fs_info->open_ioctl_trans) && +	    should_end_transaction(trans, root)) {  		trans->transaction->blocked = 1; +		smp_wmb(); +	}  	if (lock && cur_trans->blocked && !cur_trans->in_commit) {  		if (throttle) @@ -703,9 +730,9 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,   */  int btrfs_add_dead_root(struct btrfs_root *root)  { -	mutex_lock(&root->fs_info->trans_mutex); +	spin_lock(&root->fs_info->trans_lock);  	list_add(&root->root_list, &root->fs_info->dead_roots); -	mutex_unlock(&root->fs_info->trans_mutex); +	spin_unlock(&root->fs_info->trans_lock);  	return 0;  } @@ -721,6 +748,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,  	int ret;  	int err = 0; +	spin_lock(&fs_info->fs_roots_radix_lock);  	while (1) {  		ret = radix_tree_gang_lookup_tag(&fs_info->fs_roots_radix,  						 (void **)gang, 0, @@ -733,6 +761,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,  			radix_tree_tag_clear(&fs_info->fs_roots_radix,  					(unsigned long)root->root_key.objectid,  					BTRFS_ROOT_TRANS_TAG); +			spin_unlock(&fs_info->fs_roots_radix_lock);  			btrfs_free_log(trans, root);  			btrfs_update_reloc_root(trans, root); @@ -753,10 +782,12 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,  			err = btrfs_update_root(trans, fs_info->tree_root,  						&root->root_key,  						&root->root_item); +			spin_lock(&fs_info->fs_roots_radix_lock);  			if (err)  				break;  		}  	} +	spin_unlock(&fs_info->fs_roots_radix_lock);  	return err;  } @@ -786,7 +817,7 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)  		btrfs_btree_balance_dirty(info->tree_root, nr);  		cond_resched(); -		if (root->fs_info->closing || ret != -EAGAIN) +		if (btrfs_fs_closing(root->fs_info) || ret != -EAGAIN)  			break;  	}  	root->defrag_running = 0; @@ -851,7 +882,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,  	parent = dget_parent(dentry);  	parent_inode = parent->d_inode;  	parent_root = BTRFS_I(parent_inode)->root; -	record_root_in_trans(trans, parent_root); +	btrfs_record_root_in_trans(trans, parent_root);  	/*  	 * insert the directory item @@ -869,7 +900,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,  	ret = btrfs_update_inode(trans, parent_root, parent_inode);  	BUG_ON(ret); -	record_root_in_trans(trans, root); +	btrfs_record_root_in_trans(trans, root);  	btrfs_set_root_last_snapshot(&root->root_item, trans->transid);  	memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));  	btrfs_check_and_init_root_item(new_root_item); @@ -967,20 +998,20 @@ static void update_super_roots(struct btrfs_root *root)  int btrfs_transaction_in_commit(struct btrfs_fs_info *info)  {  	int ret = 0; -	spin_lock(&info->new_trans_lock); +	spin_lock(&info->trans_lock);  	if (info->running_transaction)  		ret = info->running_transaction->in_commit; -	spin_unlock(&info->new_trans_lock); +	spin_unlock(&info->trans_lock);  	return ret;  }  int btrfs_transaction_blocked(struct btrfs_fs_info *info)  {  	int ret = 0; -	spin_lock(&info->new_trans_lock); +	spin_lock(&info->trans_lock);  	if (info->running_transaction)  		ret = info->running_transaction->blocked; -	spin_unlock(&info->new_trans_lock); +	spin_unlock(&info->trans_lock);  	return ret;  } @@ -1004,9 +1035,7 @@ static void wait_current_trans_commit_start(struct btrfs_root *root,  				    &wait);  			break;  		} -		mutex_unlock(&root->fs_info->trans_mutex);  		schedule(); -		mutex_lock(&root->fs_info->trans_mutex);  		finish_wait(&root->fs_info->transaction_blocked_wait, &wait);  	}  } @@ -1032,9 +1061,7 @@ static void wait_current_trans_commit_start_and_unblock(struct btrfs_root *root,  				    &wait);  			break;  		} -		mutex_unlock(&root->fs_info->trans_mutex);  		schedule(); -		mutex_lock(&root->fs_info->trans_mutex);  		finish_wait(&root->fs_info->transaction_wait,  			    &wait);  	} @@ -1072,7 +1099,7 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,  	INIT_DELAYED_WORK(&ac->work, do_async_commit);  	ac->root = root; -	ac->newtrans = btrfs_join_transaction(root, 0); +	ac->newtrans = btrfs_join_transaction(root);  	if (IS_ERR(ac->newtrans)) {  		int err = PTR_ERR(ac->newtrans);  		kfree(ac); @@ -1080,22 +1107,18 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,  	}  	/* take transaction reference */ -	mutex_lock(&root->fs_info->trans_mutex);  	cur_trans = trans->transaction;  	atomic_inc(&cur_trans->use_count); -	mutex_unlock(&root->fs_info->trans_mutex);  	btrfs_end_transaction(trans, root);  	schedule_delayed_work(&ac->work, 0);  	/* wait for transaction to start and unblock */ -	mutex_lock(&root->fs_info->trans_mutex);  	if (wait_for_unblock)  		wait_current_trans_commit_start_and_unblock(root, cur_trans);  	else  		wait_current_trans_commit_start(root, cur_trans);  	put_transaction(cur_trans); -	mutex_unlock(&root->fs_info->trans_mutex);  	return 0;  } @@ -1139,38 +1162,41 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,  	ret = btrfs_run_delayed_refs(trans, root, 0);  	BUG_ON(ret); -	mutex_lock(&root->fs_info->trans_mutex); +	spin_lock(&cur_trans->commit_lock);  	if (cur_trans->in_commit) { +		spin_unlock(&cur_trans->commit_lock);  		atomic_inc(&cur_trans->use_count); -		mutex_unlock(&root->fs_info->trans_mutex);  		btrfs_end_transaction(trans, root);  		ret = wait_for_commit(root, cur_trans);  		BUG_ON(ret); -		mutex_lock(&root->fs_info->trans_mutex);  		put_transaction(cur_trans); -		mutex_unlock(&root->fs_info->trans_mutex);  		return 0;  	}  	trans->transaction->in_commit = 1;  	trans->transaction->blocked = 1; +	spin_unlock(&cur_trans->commit_lock);  	wake_up(&root->fs_info->transaction_blocked_wait); +	spin_lock(&root->fs_info->trans_lock);  	if (cur_trans->list.prev != &root->fs_info->trans_list) {  		prev_trans = list_entry(cur_trans->list.prev,  					struct btrfs_transaction, list);  		if (!prev_trans->commit_done) {  			atomic_inc(&prev_trans->use_count); -			mutex_unlock(&root->fs_info->trans_mutex); +			spin_unlock(&root->fs_info->trans_lock);  			wait_for_commit(root, prev_trans); -			mutex_lock(&root->fs_info->trans_mutex);  			put_transaction(prev_trans); +		} else { +			spin_unlock(&root->fs_info->trans_lock);  		} +	} else { +		spin_unlock(&root->fs_info->trans_lock);  	}  	if (now < cur_trans->start_time || now - cur_trans->start_time < 1) @@ -1178,12 +1204,12 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,  	do {  		int snap_pending = 0; +  		joined = cur_trans->num_joined;  		if (!list_empty(&trans->transaction->pending_snapshots))  			snap_pending = 1;  		WARN_ON(cur_trans != trans->transaction); -		mutex_unlock(&root->fs_info->trans_mutex);  		if (flush_on_commit || snap_pending) {  			btrfs_start_delalloc_inodes(root, 1); @@ -1206,14 +1232,15 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,  		prepare_to_wait(&cur_trans->writer_wait, &wait,  				TASK_UNINTERRUPTIBLE); -		smp_mb();  		if (atomic_read(&cur_trans->num_writers) > 1)  			schedule_timeout(MAX_SCHEDULE_TIMEOUT);  		else if (should_grow)  			schedule_timeout(1); -		mutex_lock(&root->fs_info->trans_mutex);  		finish_wait(&cur_trans->writer_wait, &wait); +		spin_lock(&root->fs_info->trans_lock); +		root->fs_info->trans_no_join = 1; +		spin_unlock(&root->fs_info->trans_lock);  	} while (atomic_read(&cur_trans->num_writers) > 1 ||  		 (should_grow && cur_trans->num_joined != joined)); @@ -1258,9 +1285,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,  	btrfs_prepare_extent_commit(trans, root);  	cur_trans = root->fs_info->running_transaction; -	spin_lock(&root->fs_info->new_trans_lock); -	root->fs_info->running_transaction = NULL; -	spin_unlock(&root->fs_info->new_trans_lock);  	btrfs_set_root_node(&root->fs_info->tree_root->root_item,  			    root->fs_info->tree_root->node); @@ -1281,10 +1305,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,  	       sizeof(root->fs_info->super_copy));  	trans->transaction->blocked = 0; +	spin_lock(&root->fs_info->trans_lock); +	root->fs_info->running_transaction = NULL; +	root->fs_info->trans_no_join = 0; +	spin_unlock(&root->fs_info->trans_lock);  	wake_up(&root->fs_info->transaction_wait); -	mutex_unlock(&root->fs_info->trans_mutex);  	ret = btrfs_write_and_wait_transaction(trans, root);  	BUG_ON(ret);  	write_ctree_super(trans, root, 0); @@ -1297,22 +1324,21 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,  	btrfs_finish_extent_commit(trans, root); -	mutex_lock(&root->fs_info->trans_mutex); -  	cur_trans->commit_done = 1;  	root->fs_info->last_trans_committed = cur_trans->transid;  	wake_up(&cur_trans->commit_wait); +	spin_lock(&root->fs_info->trans_lock);  	list_del_init(&cur_trans->list); +	spin_unlock(&root->fs_info->trans_lock); +  	put_transaction(cur_trans);  	put_transaction(cur_trans);  	trace_btrfs_transaction_commit(root); -	mutex_unlock(&root->fs_info->trans_mutex); -  	btrfs_scrub_continue(root);  	if (current->journal_info == trans) @@ -1334,9 +1360,9 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root)  	LIST_HEAD(list);  	struct btrfs_fs_info *fs_info = root->fs_info; -	mutex_lock(&fs_info->trans_mutex); +	spin_lock(&fs_info->trans_lock);  	list_splice_init(&fs_info->dead_roots, &list); -	mutex_unlock(&fs_info->trans_mutex); +	spin_unlock(&fs_info->trans_lock);  	while (!list_empty(&list)) {  		root = list_entry(list.next, struct btrfs_root, root_list); diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 804c88639e5..02564e6230a 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h @@ -28,10 +28,12 @@ struct btrfs_transaction {  	 * transaction can end  	 */  	atomic_t num_writers; +	atomic_t use_count;  	unsigned long num_joined; + +	spinlock_t commit_lock;  	int in_commit; -	atomic_t use_count;  	int commit_done;  	int blocked;  	struct list_head list; @@ -45,13 +47,14 @@ struct btrfs_transaction {  struct btrfs_trans_handle {  	u64 transid; -	u64 block_group;  	u64 bytes_reserved; +	unsigned long use_count;  	unsigned long blocks_reserved;  	unsigned long blocks_used;  	unsigned long delayed_ref_updates;  	struct btrfs_transaction *transaction;  	struct btrfs_block_rsv *block_rsv; +	struct btrfs_block_rsv *orig_rsv;  };  struct btrfs_pending_snapshot { @@ -66,19 +69,6 @@ struct btrfs_pending_snapshot {  	struct list_head list;  }; -static inline void btrfs_set_trans_block_group(struct btrfs_trans_handle *trans, -					       struct inode *inode) -{ -	trans->block_group = BTRFS_I(inode)->block_group; -} - -static inline void btrfs_update_inode_block_group( -					  struct btrfs_trans_handle *trans, -					  struct inode *inode) -{ -	BTRFS_I(inode)->block_group = trans->block_group; -} -  static inline void btrfs_set_inode_last_trans(struct btrfs_trans_handle *trans,  					      struct inode *inode)  { @@ -92,12 +82,9 @@ int btrfs_end_transaction_nolock(struct btrfs_trans_handle *trans,  				 struct btrfs_root *root);  struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,  						   int num_items); -struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root, -						  int num_blocks); -struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root, -							  int num_blocks); -struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, -							 int num_blocks); +struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root); +struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root); +struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root);  int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid);  int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,  				     struct btrfs_root *root); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index c48214ef5c0..da541dfca2e 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -504,7 +504,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)  		BUG_ON(!new_device);  		memcpy(new_device, device, sizeof(*new_device));  		new_device->name = kstrdup(device->name, GFP_NOFS); -		BUG_ON(!new_device->name); +		BUG_ON(device->name && !new_device->name);  		new_device->bdev = NULL;  		new_device->writeable = 0;  		new_device->in_fs_metadata = 0; diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index f3107e4b4d5..5366fe452ab 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -158,8 +158,6 @@ int __btrfs_setxattr(struct btrfs_trans_handle *trans,  	if (IS_ERR(trans))  		return PTR_ERR(trans); -	btrfs_set_trans_block_group(trans, inode); -  	ret = do_setxattr(trans, inode, name, value, size, flags);  	if (ret)  		goto out; diff --git a/fs/partitions/check.c b/fs/partitions/check.c index f82e762eeca..d545e97d99c 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -255,13 +255,7 @@ ssize_t part_discard_alignment_show(struct device *dev,  				   struct device_attribute *attr, char *buf)  {  	struct hd_struct *p = dev_to_part(dev); -	struct gendisk *disk = dev_to_disk(dev); -	unsigned int alignment = 0; - -	if (disk->queue) -		alignment = queue_limit_discard_alignment(&disk->queue->limits, -								p->start_sect); -	return sprintf(buf, "%u\n", alignment); +	return sprintf(buf, "%u\n", p->discard_alignment);  }  ssize_t part_stat_show(struct device *dev, @@ -455,6 +449,8 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno,  	p->start_sect = start;  	p->alignment_offset =  		queue_limit_alignment_offset(&disk->queue->limits, start); +	p->discard_alignment = +		queue_limit_discard_alignment(&disk->queue->limits, start);  	p->nr_sects = len;  	p->partno = partno;  	p->policy = get_disk_ro(disk); diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 166951e0dcd..3be645e012c 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -581,6 +581,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)  	ubifs_assert(wbuf->size % c->min_io_size == 0);  	ubifs_assert(mutex_is_locked(&wbuf->io_mutex));  	ubifs_assert(!c->ro_media && !c->ro_mount); +	ubifs_assert(!c->space_fixup);  	if (c->leb_size - wbuf->offs >= c->max_write_size)  		ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size)); @@ -759,6 +760,7 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,  	ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);  	ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);  	ubifs_assert(!c->ro_media && !c->ro_mount); +	ubifs_assert(!c->space_fixup);  	if (c->ro_error)  		return -EROFS; diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 34b1679e6e3..cef0460f4c5 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -669,6 +669,7 @@ out_free:  out_release:  	release_head(c, BASEHD); +	kfree(dent);  out_ro:  	ubifs_ro_mode(c, err);  	if (last_reference) diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c index bd644bf587a..a5422fffbd6 100644 --- a/fs/ubifs/orphan.c +++ b/fs/ubifs/orphan.c @@ -674,7 +674,7 @@ static int kill_orphans(struct ubifs_info *c)  		if (IS_ERR(sleb)) {  			if (PTR_ERR(sleb) == -EUCLEAN)  				sleb = ubifs_recover_leb(c, lnum, 0, -							 c->sbuf, 0); +							 c->sbuf, -1);  			if (IS_ERR(sleb)) {  				err = PTR_ERR(sleb);  				break; diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 731d9e2e7b5..783d8e0beb7 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -564,19 +564,15 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,  }  /** - * drop_last_node - drop the last node or group of nodes. + * drop_last_group - drop the last group of nodes.   * @sleb: scanned LEB information   * @offs: offset of dropped nodes is returned here - * @grouped: non-zero if whole group of nodes have to be dropped   *   * This is a helper function for 'ubifs_recover_leb()' which drops the last - * node of the scanned LEB or the last group of nodes if @grouped is not zero. - * This function returns %1 if a node was dropped and %0 otherwise. + * group of nodes of the scanned LEB.   */ -static int drop_last_node(struct ubifs_scan_leb *sleb, int *offs, int grouped) +static void drop_last_group(struct ubifs_scan_leb *sleb, int *offs)  { -	int dropped = 0; -  	while (!list_empty(&sleb->nodes)) {  		struct ubifs_scan_node *snod;  		struct ubifs_ch *ch; @@ -585,17 +581,40 @@ static int drop_last_node(struct ubifs_scan_leb *sleb, int *offs, int grouped)  				  list);  		ch = snod->node;  		if (ch->group_type != UBIFS_IN_NODE_GROUP) -			return dropped; -		dbg_rcvry("dropping node at %d:%d", sleb->lnum, snod->offs); +			break; + +		dbg_rcvry("dropping grouped node at %d:%d", +			  sleb->lnum, snod->offs); +		*offs = snod->offs; +		list_del(&snod->list); +		kfree(snod); +		sleb->nodes_cnt -= 1; +	} +} + +/** + * drop_last_node - drop the last node. + * @sleb: scanned LEB information + * @offs: offset of dropped nodes is returned here + * @grouped: non-zero if whole group of nodes have to be dropped + * + * This is a helper function for 'ubifs_recover_leb()' which drops the last + * node of the scanned LEB. + */ +static void drop_last_node(struct ubifs_scan_leb *sleb, int *offs) +{ +	struct ubifs_scan_node *snod; + +	if (!list_empty(&sleb->nodes)) { +		snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, +				  list); + +		dbg_rcvry("dropping last node at %d:%d", sleb->lnum, snod->offs);  		*offs = snod->offs;  		list_del(&snod->list);  		kfree(snod);  		sleb->nodes_cnt -= 1; -		dropped = 1; -		if (!grouped) -			break;  	} -	return dropped;  }  /** @@ -604,7 +623,8 @@ static int drop_last_node(struct ubifs_scan_leb *sleb, int *offs, int grouped)   * @lnum: LEB number   * @offs: offset   * @sbuf: LEB-sized buffer to use - * @grouped: nodes may be grouped for recovery + * @jhead: journal head number this LEB belongs to (%-1 if the LEB does not + *         belong to any journal head)   *   * This function does a scan of a LEB, but caters for errors that might have   * been caused by the unclean unmount from which we are attempting to recover. @@ -612,13 +632,14 @@ static int drop_last_node(struct ubifs_scan_leb *sleb, int *offs, int grouped)   * found, and a negative error code in case of failure.   */  struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, -					 int offs, void *sbuf, int grouped) +					 int offs, void *sbuf, int jhead)  {  	int ret = 0, err, len = c->leb_size - offs, start = offs, min_io_unit; +	int grouped = jhead == -1 ? 0 : c->jheads[jhead].grouped;  	struct ubifs_scan_leb *sleb;  	void *buf = sbuf + offs; -	dbg_rcvry("%d:%d", lnum, offs); +	dbg_rcvry("%d:%d, jhead %d, grouped %d", lnum, offs, jhead, grouped);  	sleb = ubifs_start_scan(c, lnum, offs, sbuf);  	if (IS_ERR(sleb)) @@ -635,7 +656,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,  		 * Scan quietly until there is an error from which we cannot  		 * recover  		 */ -		ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0); +		ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);  		if (ret == SCANNED_A_NODE) {  			/* A valid node, and not a padding node */  			struct ubifs_ch *ch = buf; @@ -695,59 +716,62 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,  		 * If nodes are grouped, always drop the incomplete group at  		 * the end.  		 */ -		drop_last_node(sleb, &offs, 1); +		drop_last_group(sleb, &offs); -	/* -	 * While we are in the middle of the same min. I/O unit keep dropping -	 * nodes. So basically, what we want is to make sure that the last min. -	 * I/O unit where we saw the corruption is dropped completely with all -	 * the uncorrupted node which may possibly sit there. -	 * -	 * In other words, let's name the min. I/O unit where the corruption -	 * starts B, and the previous min. I/O unit A. The below code tries to -	 * deal with a situation when half of B contains valid nodes or the end -	 * of a valid node, and the second half of B contains corrupted data or -	 * garbage. This means that UBIFS had been writing to B just before the -	 * power cut happened. I do not know how realistic is this scenario -	 * that half of the min. I/O unit had been written successfully and the -	 * other half not, but this is possible in our 'failure mode emulation' -	 * infrastructure at least. -	 * -	 * So what is the problem, why we need to drop those nodes? Whey can't -	 * we just clean-up the second half of B by putting a padding node -	 * there? We can, and this works fine with one exception which was -	 * reproduced with power cut emulation testing and happens extremely -	 * rarely. The description follows, but it is worth noting that that is -	 * only about the GC head, so we could do this trick only if the bud -	 * belongs to the GC head, but it does not seem to be worth an -	 * additional "if" statement. -	 * -	 * So, imagine the file-system is full, we run GC which is moving valid -	 * nodes from LEB X to LEB Y (obviously, LEB Y is the current GC head -	 * LEB). The @c->gc_lnum is -1, which means that GC will retain LEB X -	 * and will try to continue. Imagine that LEB X is currently the -	 * dirtiest LEB, and the amount of used space in LEB Y is exactly the -	 * same as amount of free space in LEB X. -	 * -	 * And a power cut happens when nodes are moved from LEB X to LEB Y. We -	 * are here trying to recover LEB Y which is the GC head LEB. We find -	 * the min. I/O unit B as described above. Then we clean-up LEB Y by -	 * padding min. I/O unit. And later 'ubifs_rcvry_gc_commit()' function -	 * fails, because it cannot find a dirty LEB which could be GC'd into -	 * LEB Y! Even LEB X does not match because the amount of valid nodes -	 * there does not fit the free space in LEB Y any more! And this is -	 * because of the padding node which we added to LEB Y. The -	 * user-visible effect of this which I once observed and analysed is -	 * that we cannot mount the file-system with -ENOSPC error. -	 * -	 * So obviously, to make sure that situation does not happen we should -	 * free min. I/O unit B in LEB Y completely and the last used min. I/O -	 * unit in LEB Y should be A. This is basically what the below code -	 * tries to do. -	 */ -	while (min_io_unit == round_down(offs, c->min_io_size) && -	       min_io_unit != offs && -	       drop_last_node(sleb, &offs, grouped)); +	if (jhead == GCHD) { +		/* +		 * If this LEB belongs to the GC head then while we are in the +		 * middle of the same min. I/O unit keep dropping nodes. So +		 * basically, what we want is to make sure that the last min. +		 * I/O unit where we saw the corruption is dropped completely +		 * with all the uncorrupted nodes which may possibly sit there. +		 * +		 * In other words, let's name the min. I/O unit where the +		 * corruption starts B, and the previous min. I/O unit A. The +		 * below code tries to deal with a situation when half of B +		 * contains valid nodes or the end of a valid node, and the +		 * second half of B contains corrupted data or garbage. This +		 * means that UBIFS had been writing to B just before the power +		 * cut happened. I do not know how realistic is this scenario +		 * that half of the min. I/O unit had been written successfully +		 * and the other half not, but this is possible in our 'failure +		 * mode emulation' infrastructure at least. +		 * +		 * So what is the problem, why we need to drop those nodes? Why +		 * can't we just clean-up the second half of B by putting a +		 * padding node there? We can, and this works fine with one +		 * exception which was reproduced with power cut emulation +		 * testing and happens extremely rarely. +		 * +		 * Imagine the file-system is full, we run GC which starts +		 * moving valid nodes from LEB X to LEB Y (obviously, LEB Y is +		 * the current GC head LEB). The @c->gc_lnum is -1, which means +		 * that GC will retain LEB X and will try to continue. Imagine +		 * that LEB X is currently the dirtiest LEB, and the amount of +		 * used space in LEB Y is exactly the same as amount of free +		 * space in LEB X. +		 * +		 * And a power cut happens when nodes are moved from LEB X to +		 * LEB Y. We are here trying to recover LEB Y which is the GC +		 * head LEB. We find the min. I/O unit B as described above. +		 * Then we clean-up LEB Y by padding min. I/O unit. And later +		 * 'ubifs_rcvry_gc_commit()' function fails, because it cannot +		 * find a dirty LEB which could be GC'd into LEB Y! Even LEB X +		 * does not match because the amount of valid nodes there does +		 * not fit the free space in LEB Y any more! And this is +		 * because of the padding node which we added to LEB Y. The +		 * user-visible effect of this which I once observed and +		 * analysed is that we cannot mount the file-system with +		 * -ENOSPC error. +		 * +		 * So obviously, to make sure that situation does not happen we +		 * should free min. I/O unit B in LEB Y completely and the last +		 * used min. I/O unit in LEB Y should be A. This is basically +		 * what the below code tries to do. +		 */ +		while (offs > min_io_unit) +			drop_last_node(sleb, &offs); +	}  	buf = sbuf + offs;  	len = c->leb_size - offs; @@ -881,7 +905,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,  		}  		ubifs_scan_destroy(sleb);  	} -	return ubifs_recover_leb(c, lnum, offs, sbuf, 0); +	return ubifs_recover_leb(c, lnum, offs, sbuf, -1);  }  /** diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index 6617280d167..5e97161ce4d 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c @@ -557,8 +557,7 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b)  		 * these LEBs could possibly be written to at the power cut  		 * time.  		 */ -		sleb = ubifs_recover_leb(c, lnum, offs, c->sbuf, -					 b->bud->jhead != GCHD); +		sleb = ubifs_recover_leb(c, lnum, offs, c->sbuf, b->bud->jhead);  	else  		sleb = ubifs_scan(c, lnum, offs, c->sbuf, 0);  	if (IS_ERR(sleb)) diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c index ca953a94502..9e1d05666fe 100644 --- a/fs/ubifs/shrinker.c +++ b/fs/ubifs/shrinker.c @@ -284,7 +284,11 @@ int ubifs_shrinker(struct shrinker *shrink, struct shrink_control *sc)  	long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt);  	if (nr == 0) -		return clean_zn_cnt; +		/* +		 * Due to the way UBIFS updates the clean znode counter it may +		 * temporarily be negative. +		 */ +		return clean_zn_cnt >= 0 ? clean_zn_cnt : 1;  	if (!clean_zn_cnt) {  		/* diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 1ab0d22e4c9..b5aeb5a8ebe 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -811,15 +811,18 @@ static int alloc_wbufs(struct ubifs_info *c)  		c->jheads[i].wbuf.sync_callback = &bud_wbuf_callback;  		c->jheads[i].wbuf.jhead = i; +		c->jheads[i].grouped = 1;  	}  	c->jheads[BASEHD].wbuf.dtype = UBI_SHORTTERM;  	/*  	 * Garbage Collector head likely contains long-term data and -	 * does not need to be synchronized by timer. +	 * does not need to be synchronized by timer. Also GC head nodes are +	 * not grouped.  	 */  	c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM;  	c->jheads[GCHD].wbuf.no_timer = 1; +	c->jheads[GCHD].grouped = 0;  	return 0;  } @@ -1284,12 +1287,25 @@ static int mount_ubifs(struct ubifs_info *c)  	if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {  		ubifs_msg("recovery needed");  		c->need_recovery = 1; -		if (!c->ro_mount) { -			err = ubifs_recover_inl_heads(c, c->sbuf); -			if (err) -				goto out_master; -		} -	} else if (!c->ro_mount) { +	} + +	if (c->need_recovery && !c->ro_mount) { +		err = ubifs_recover_inl_heads(c, c->sbuf); +		if (err) +			goto out_master; +	} + +	err = ubifs_lpt_init(c, 1, !c->ro_mount); +	if (err) +		goto out_master; + +	if (!c->ro_mount && c->space_fixup) { +		err = ubifs_fixup_free_space(c); +		if (err) +			goto out_master; +	} + +	if (!c->ro_mount) {  		/*  		 * Set the "dirty" flag so that if we reboot uncleanly we  		 * will notice this immediately on the next mount. @@ -1297,13 +1313,9 @@ static int mount_ubifs(struct ubifs_info *c)  		c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);  		err = ubifs_write_master(c);  		if (err) -			goto out_master; +			goto out_lpt;  	} -	err = ubifs_lpt_init(c, 1, !c->ro_mount); -	if (err) -		goto out_lpt; -  	err = dbg_check_idx_size(c, c->bi.old_idx_sz);  	if (err)  		goto out_lpt; @@ -1396,12 +1408,6 @@ static int mount_ubifs(struct ubifs_info *c)  	} else  		ubifs_assert(c->lst.taken_empty_lebs > 0); -	if (!c->ro_mount && c->space_fixup) { -		err = ubifs_fixup_free_space(c); -		if (err) -			goto out_infos; -	} -  	err = dbg_check_filesystem(c);  	if (err)  		goto out_infos; diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 8119b1fd8d9..91b4213dde8 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -2876,12 +2876,13 @@ static void tnc_destroy_cnext(struct ubifs_info *c)   */  void ubifs_tnc_close(struct ubifs_info *c)  { -	long clean_freed; -  	tnc_destroy_cnext(c);  	if (c->zroot.znode) { -		clean_freed = ubifs_destroy_tnc_subtree(c->zroot.znode); -		atomic_long_sub(clean_freed, &ubifs_clean_zn_cnt); +		long n; + +		ubifs_destroy_tnc_subtree(c->zroot.znode); +		n = atomic_long_read(&c->clean_zn_cnt); +		atomic_long_sub(n, &ubifs_clean_zn_cnt);  	}  	kfree(c->gap_lebs);  	kfree(c->ilebs); diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index a70d7b4ffb2..f79983d6f86 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -722,12 +722,14 @@ struct ubifs_bud {   * struct ubifs_jhead - journal head.   * @wbuf: head's write-buffer   * @buds_list: list of bud LEBs belonging to this journal head + * @grouped: non-zero if UBIFS groups nodes when writing to this journal head   *   * Note, the @buds list is protected by the @c->buds_lock.   */  struct ubifs_jhead {  	struct ubifs_wbuf wbuf;  	struct list_head buds_list; +	unsigned int grouped:1;  };  /** @@ -1742,7 +1744,7 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum);  int ubifs_recover_master_node(struct ubifs_info *c);  int ubifs_write_rcvrd_mst_node(struct ubifs_info *c);  struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, -					 int offs, void *sbuf, int grouped); +					 int offs, void *sbuf, int jhead);  struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,  					     int offs, void *sbuf);  int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf); diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h index ae90e0f6399..4f76959397f 100644 --- a/include/asm-generic/unistd.h +++ b/include/asm-generic/unistd.h @@ -683,9 +683,11 @@ __SC_COMP(__NR_clock_adjtime, sys_clock_adjtime, compat_sys_clock_adjtime)  __SYSCALL(__NR_syncfs, sys_syncfs)  #define __NR_setns 268  __SYSCALL(__NR_setns, sys_setns) +#define __NR_sendmmsg 269 +__SC_COMP(__NR_sendmmsg, sys_sendmmsg, compat_sys_sendmmsg)  #undef __NR_syscalls -#define __NR_syscalls 269 +#define __NR_syscalls 270  /*   * All syscalls below here should go away really, diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index ae9091a6848..1a23722e887 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1282,8 +1282,8 @@ queue_max_integrity_segments(struct request_queue *q)  #define blk_get_integrity(a)			(0)  #define blk_integrity_compare(a, b)		(0)  #define blk_integrity_register(a, b)		(0) -#define blk_integrity_unregister(a)		do { } while (0); -#define blk_queue_max_integrity_segments(a, b)	do { } while (0); +#define blk_integrity_unregister(a)		do { } while (0) +#define blk_queue_max_integrity_segments(a, b)	do { } while (0)  #define queue_max_integrity_segments(a)		(0)  #define blk_integrity_merge_rq(a, b, c)		(0)  #define blk_integrity_merge_bio(a, b, c)	(0) diff --git a/include/linux/genhd.h b/include/linux/genhd.h index b78956b3c2e..300d7582006 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -100,6 +100,7 @@ struct hd_struct {  	sector_t start_sect;  	sector_t nr_sects;  	sector_t alignment_offset; +	unsigned int discard_alignment;  	struct device __dev;  	struct kobject *holder_dir;  	int policy, partno; diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index b2eee587988..bf56b6f7827 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1003,8 +1003,12 @@ struct ieee80211_ht_info {  #define WLAN_CAPABILITY_ESS		(1<<0)  #define WLAN_CAPABILITY_IBSS		(1<<1) -/* A mesh STA sets the ESS and IBSS capability bits to zero */ -#define WLAN_CAPABILITY_IS_MBSS(cap)	\ +/* + * A mesh STA sets the ESS and IBSS capability bits to zero. + * however, this holds true for p2p probe responses (in the p2p_find + * phase) as well. + */ +#define WLAN_CAPABILITY_IS_STA_BSS(cap)	\  	(!((cap) & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)))  #define WLAN_CAPABILITY_CF_POLLABLE	(1<<2) diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h index 72bfa5a034d..6d66ce1791a 100644 --- a/include/linux/if_packet.h +++ b/include/linux/if_packet.h @@ -70,6 +70,7 @@ struct tpacket_auxdata {  #define TP_STATUS_COPY		0x2  #define TP_STATUS_LOSING	0x4  #define TP_STATUS_CSUMNOTREADY	0x8 +#define TP_STATUS_VLAN_VALID   0x10 /* auxdata has valid tp_vlan_tci */  /* Tx ring - header status */  #define TP_STATUS_AVAILABLE	0x0 diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index 5b07792ccb4..ff7dc08696a 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -76,7 +76,7 @@   * 	tty device.  It is solely the responsibility of the line   * 	discipline to handle poll requests.   * - * unsigned int (*receive_buf)(struct tty_struct *, const unsigned char *cp, + * void	(*receive_buf)(struct tty_struct *, const unsigned char *cp,   * 		       char *fp, int count);   *   * 	This function is called by the low-level tty driver to send @@ -84,8 +84,7 @@   * 	processing.  <cp> is a pointer to the buffer of input   * 	character received by the device.  <fp> is a pointer to a   * 	pointer of flag bytes which indicate whether a character was - * 	received with a parity error, etc. Returns the amount of bytes - * 	received. + * 	received with a parity error, etc.   *    * void	(*write_wakeup)(struct tty_struct *);   * @@ -141,8 +140,8 @@ struct tty_ldisc_ops {  	/*  	 * The following routines are called from below.  	 */ -	unsigned int (*receive_buf)(struct tty_struct *, -			const unsigned char *cp, char *fp, int count); +	void	(*receive_buf)(struct tty_struct *, const unsigned char *cp, +			       char *fp, int count);  	void	(*write_wakeup)(struct tty_struct *);  	void	(*dcd_change)(struct tty_struct *, unsigned int,  				struct pps_event_time *); diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index 2b447646ce4..dd6847e5d6e 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h @@ -107,6 +107,7 @@ typedef enum {  	SCTP_CMD_UPDATE_INITTAG, /* Update peer inittag */  	SCTP_CMD_SEND_MSG,	 /* Send the whole use message */  	SCTP_CMD_SEND_NEXT_ASCONF, /* Send the next ASCONF after ACK */ +	SCTP_CMD_PURGE_ASCONF_QUEUE, /* Purge all asconf queues.*/  	SCTP_CMD_LAST  } sctp_verb_t; diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 795f4886e11..7df327a6d56 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1993,7 +1993,7 @@ void sctp_assoc_clean_asconf_ack_cache(const struct sctp_association *asoc);  struct sctp_chunk *sctp_assoc_lookup_asconf_ack(  					const struct sctp_association *asoc,  					__be32 serial); - +void sctp_asconf_queue_teardown(struct sctp_association *asoc);  int sctp_cmp_addr_exact(const union sctp_addr *ss1,  			const union sctp_addr *ss2); diff --git a/include/trace/events/net.h b/include/trace/events/net.h index 5f247f5ffc5..f99645d05a8 100644 --- a/include/trace/events/net.h +++ b/include/trace/events/net.h @@ -12,22 +12,24 @@  TRACE_EVENT(net_dev_xmit,  	TP_PROTO(struct sk_buff *skb, -		 int rc), +		 int rc, +		 struct net_device *dev, +		 unsigned int skb_len), -	TP_ARGS(skb, rc), +	TP_ARGS(skb, rc, dev, skb_len),  	TP_STRUCT__entry(  		__field(	void *,		skbaddr		)  		__field(	unsigned int,	len		)  		__field(	int,		rc		) -		__string(	name,		skb->dev->name	) +		__string(	name,		dev->name	)  	),  	TP_fast_assign(  		__entry->skbaddr = skb; -		__entry->len = skb->len; +		__entry->len = skb_len;  		__entry->rc = rc; -		__assign_str(name, skb->dev->name); +		__assign_str(name, dev->name);  	),  	TP_printk("dev=%s skbaddr=%p len=%u rc=%d", diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 28afa4c5333..dd373c8ee94 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -697,7 +697,7 @@ config DEBUG_BUGVERBOSE  	bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EXPERT  	depends on BUG  	depends on ARM || AVR32 || M32R || M68K || SPARC32 || SPARC64 || \ -		   FRV || SUPERH || GENERIC_BUG || BLACKFIN || MN10300 +		   FRV || SUPERH || GENERIC_BUG || BLACKFIN || MN10300 || TILE  	default y  	help  	  Say Y here to make BUG() panics output the file name and line number diff --git a/mm/hugetlb.c b/mm/hugetlb.c index f33bb319b73..6402458fee3 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1033,10 +1033,10 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,  	 */  	chg = vma_needs_reservation(h, vma, addr);  	if (chg < 0) -		return ERR_PTR(chg); +		return ERR_PTR(-VM_FAULT_OOM);  	if (chg)  		if (hugetlb_get_quota(inode->i_mapping, chg)) -			return ERR_PTR(-ENOSPC); +			return ERR_PTR(-VM_FAULT_SIGBUS);  	spin_lock(&hugetlb_lock);  	page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve); diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index f247f5bff88..7ea5cf9ea08 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -165,7 +165,7 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,  		u64_stats_update_begin(&stats->syncp);  		stats->tx_packets++;  		stats->tx_bytes += len; -		u64_stats_update_begin(&stats->syncp); +		u64_stats_update_end(&stats->syncp);  	} else {  		this_cpu_inc(vlan_dev_info(dev)->vlan_pcpu_stats->tx_dropped);  	} diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a86f9ba4f05..e64a1c2df23 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -906,7 +906,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr  		if (c->psm == psm) {  			/* Exact match. */  			if (!bacmp(&bt_sk(sk)->src, src)) { -				read_unlock_bh(&chan_list_lock); +				read_unlock(&chan_list_lock);  				return c;  			} diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 649ebacaf6b..adbb424403d 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -139,17 +139,14 @@ static void close_work(struct work_struct *work)  	struct chnl_net *dev = NULL;  	struct list_head *list_node;  	struct list_head *_tmp; -	/* May be called with or without RTNL lock held */ -	int islocked = rtnl_is_locked(); -	if (!islocked) -		rtnl_lock(); + +	rtnl_lock();  	list_for_each_safe(list_node, _tmp, &chnl_net_list) {  		dev = list_entry(list_node, struct chnl_net, list_field);  		if (dev->state == CAIF_SHUTDOWN)  			dev_close(dev->netdev);  	} -	if (!islocked) -		rtnl_unlock(); +	rtnl_unlock();  }  static DECLARE_WORK(close_worker, close_work); diff --git a/net/core/dev.c b/net/core/dev.c index c7e305d13b7..939307891e7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2096,6 +2096,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,  {  	const struct net_device_ops *ops = dev->netdev_ops;  	int rc = NETDEV_TX_OK; +	unsigned int skb_len;  	if (likely(!skb->next)) {  		u32 features; @@ -2146,8 +2147,9 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,  			}  		} +		skb_len = skb->len;  		rc = ops->ndo_start_xmit(skb, dev); -		trace_net_dev_xmit(skb, rc); +		trace_net_dev_xmit(skb, rc, dev, skb_len);  		if (rc == NETDEV_TX_OK)  			txq_trans_update(txq);  		return rc; @@ -2167,8 +2169,9 @@ gso:  		if (dev->priv_flags & IFF_XMIT_DST_RELEASE)  			skb_dst_drop(nskb); +		skb_len = nskb->len;  		rc = ops->ndo_start_xmit(nskb, dev); -		trace_net_dev_xmit(nskb, rc); +		trace_net_dev_xmit(nskb, rc, dev, skb_len);  		if (unlikely(rc != NETDEV_TX_OK)) {  			if (rc & ~NETDEV_TX_MASK)  				goto out_kfree_gso_skb; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index cc1463156cd..9c1926027a2 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -465,6 +465,9 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)  	if (addr_len < sizeof(struct sockaddr_in))  		goto out; +	if (addr->sin_family != AF_INET) +		goto out; +  	chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);  	/* Not specified by any standard per-se, however it breaks too diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index c3118e1cd3b..ec93335901d 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -14,6 +14,7 @@  #include <linux/slab.h>  #include <linux/types.h>  #include <asm/uaccess.h> +#include <asm/unaligned.h>  #include <linux/skbuff.h>  #include <linux/ip.h>  #include <linux/icmp.h> @@ -350,7 +351,7 @@ int ip_options_compile(struct net *net,  				goto error;  			}  			if (optptr[2] <= optlen) { -				__be32 *timeptr = NULL; +				unsigned char *timeptr = NULL;  				if (optptr[2]+3 > optptr[1]) {  					pp_ptr = optptr + 2;  					goto error; @@ -359,7 +360,7 @@ int ip_options_compile(struct net *net,  				      case IPOPT_TS_TSONLY:  					opt->ts = optptr - iph;  					if (skb) -						timeptr = (__be32*)&optptr[optptr[2]-1]; +						timeptr = &optptr[optptr[2]-1];  					opt->ts_needtime = 1;  					optptr[2] += 4;  					break; @@ -371,7 +372,7 @@ int ip_options_compile(struct net *net,  					opt->ts = optptr - iph;  					if (rt)  {  						memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); -						timeptr = (__be32*)&optptr[optptr[2]+3]; +						timeptr = &optptr[optptr[2]+3];  					}  					opt->ts_needaddr = 1;  					opt->ts_needtime = 1; @@ -389,7 +390,7 @@ int ip_options_compile(struct net *net,  						if (inet_addr_type(net, addr) == RTN_UNICAST)  							break;  						if (skb) -							timeptr = (__be32*)&optptr[optptr[2]+3]; +							timeptr = &optptr[optptr[2]+3];  					}  					opt->ts_needtime = 1;  					optptr[2] += 8; @@ -403,10 +404,10 @@ int ip_options_compile(struct net *net,  				}  				if (timeptr) {  					struct timespec tv; -					__be32  midtime; +					u32  midtime;  					getnstimeofday(&tv); -					midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC); -					memcpy(timeptr, &midtime, sizeof(__be32)); +					midtime = (tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC; +					put_unaligned_be32(midtime, timeptr);  					opt->is_changed = 1;  				}  			} else { diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 4f6b2675e41..456cccf26b5 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -232,6 +232,9 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,  		WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type));  	} +	ieee80211_stop_queues_by_reason(&sdata->local->hw, +					IEEE80211_QUEUE_STOP_REASON_CSA); +  	/* channel_type change automatically detected */  	ieee80211_hw_config(local, 0); @@ -245,6 +248,9 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,  		rcu_read_unlock();  	} +	ieee80211_wake_queues_by_reason(&sdata->local->hw, +					IEEE80211_QUEUE_STOP_REASON_CSA); +  	ht_opmode = le16_to_cpu(hti->operation_mode);  	/* if bss configuration changed store the new one */ @@ -1089,6 +1095,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,  		local->hw.conf.flags &= ~IEEE80211_CONF_PS;  		config_changed |= IEEE80211_CONF_CHANGE_PS;  	} +	local->ps_sdata = NULL;  	ieee80211_hw_config(local, config_changed); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 27af6723cb5..58ffa7d069c 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -15,7 +15,6 @@  #include <linux/if_arp.h>  #include <linux/rtnetlink.h>  #include <linux/pm_qos_params.h> -#include <linux/slab.h>  #include <net/sch_generic.h>  #include <linux/slab.h>  #include <net/mac80211.h> diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 925f715686a..ba248d93399 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -798,7 +798,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,  			getnstimeofday(&ts);  		h.h2->tp_sec = ts.tv_sec;  		h.h2->tp_nsec = ts.tv_nsec; -		h.h2->tp_vlan_tci = vlan_tx_tag_get(skb); +		if (vlan_tx_tag_present(skb)) { +			h.h2->tp_vlan_tci = vlan_tx_tag_get(skb); +			status |= TP_STATUS_VLAN_VALID; +		} else { +			h.h2->tp_vlan_tci = 0; +		}  		hdrlen = sizeof(*h.h2);  		break;  	default: @@ -1725,8 +1730,12 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,  		aux.tp_snaplen = skb->len;  		aux.tp_mac = 0;  		aux.tp_net = skb_network_offset(skb); -		aux.tp_vlan_tci = vlan_tx_tag_get(skb); - +		if (vlan_tx_tag_present(skb)) { +			aux.tp_vlan_tci = vlan_tx_tag_get(skb); +			aux.tp_status |= TP_STATUS_VLAN_VALID; +		} else { +			aux.tp_vlan_tci = 0; +		}  		put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux);  	} diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 525f97c467e..4a62888f2e4 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -444,15 +444,7 @@ void sctp_association_free(struct sctp_association *asoc)  	asoc->peer.transport_count = 0; -	/* Free any cached ASCONF_ACK chunk. */ -	sctp_assoc_free_asconf_acks(asoc); - -	/* Free the ASCONF queue. */ -	sctp_assoc_free_asconf_queue(asoc); - -	/* Free any cached ASCONF chunk. */ -	if (asoc->addip_last_asconf) -		sctp_chunk_free(asoc->addip_last_asconf); +	sctp_asconf_queue_teardown(asoc);  	/* AUTH - Free the endpoint shared keys */  	sctp_auth_destroy_keys(&asoc->endpoint_shared_keys); @@ -1646,3 +1638,16 @@ struct sctp_chunk *sctp_assoc_lookup_asconf_ack(  	return NULL;  } + +void sctp_asconf_queue_teardown(struct sctp_association *asoc) +{ +	/* Free any cached ASCONF_ACK chunk. */ +	sctp_assoc_free_asconf_acks(asoc); + +	/* Free the ASCONF queue. */ +	sctp_assoc_free_asconf_queue(asoc); + +	/* Free any cached ASCONF chunk. */ +	if (asoc->addip_last_asconf) +		sctp_chunk_free(asoc->addip_last_asconf); +} diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index d612ca1ca6c..534c2e5feb0 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1670,6 +1670,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,  		case SCTP_CMD_SEND_NEXT_ASCONF:  			sctp_cmd_send_asconf(asoc);  			break; +		case SCTP_CMD_PURGE_ASCONF_QUEUE: +			sctp_asconf_queue_teardown(asoc); +			break;  		default:  			pr_warn("Impossible command: %u, %p\n",  				cmd->verb, cmd->obj.ptr); diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 7f4a4f8368e..a297283154d 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -1718,11 +1718,21 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,  		return SCTP_DISPOSITION_CONSUME;  	} -	/* For now, fail any unsent/unacked data.  Consider the optional -	 * choice of resending of this data. +	/* For now, stop pending T3-rtx and SACK timers, fail any unsent/unacked +	 * data. Consider the optional choice of resending of this data.  	 */ +	sctp_add_cmd_sf(commands, SCTP_CMD_T3_RTX_TIMERS_STOP, SCTP_NULL()); +	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, +			SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));  	sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL()); +	/* Stop pending T4-rto timer, teardown ASCONF queue, ASCONF-ACK queue +	 * and ASCONF-ACK cache. +	 */ +	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, +			SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); +	sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_ASCONF_QUEUE, SCTP_NULL()); +  	repl = sctp_make_cookie_ack(new_asoc, chunk);  	if (!repl)  		goto nomem; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ec83f413a7e..88a565f130a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3406,12 +3406,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)  	i = 0;  	if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {  		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { +			request->ssids[i].ssid_len = nla_len(attr);  			if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) {  				err = -EINVAL;  				goto out_free;  			}  			memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr)); -			request->ssids[i].ssid_len = nla_len(attr);  			i++;  		}  	} @@ -3572,6 +3572,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,  	if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {  		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS],  				    tmp) { +			request->ssids[i].ssid_len = nla_len(attr);  			if (request->ssids[i].ssid_len >  			    IEEE80211_MAX_SSID_LEN) {  				err = -EINVAL; @@ -3579,7 +3580,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,  			}  			memcpy(request->ssids[i].ssid, nla_data(attr),  			       nla_len(attr)); -			request->ssids[i].ssid_len = nla_len(attr);  			i++;  		}  	} diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 73a441d237b..7a6c67667d7 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -267,13 +267,35 @@ static bool is_bss(struct cfg80211_bss *a,  	return memcmp(ssidie + 2, ssid, ssid_len) == 0;  } +static bool is_mesh_bss(struct cfg80211_bss *a) +{ +	const u8 *ie; + +	if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) +		return false; + +	ie = cfg80211_find_ie(WLAN_EID_MESH_ID, +			      a->information_elements, +			      a->len_information_elements); +	if (!ie) +		return false; + +	ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, +			      a->information_elements, +			      a->len_information_elements); +	if (!ie) +		return false; + +	return true; +} +  static bool is_mesh(struct cfg80211_bss *a,  		    const u8 *meshid, size_t meshidlen,  		    const u8 *meshcfg)  {  	const u8 *ie; -	if (!WLAN_CAPABILITY_IS_MBSS(a->capability)) +	if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability))  		return false;  	ie = cfg80211_find_ie(WLAN_EID_MESH_ID, @@ -311,7 +333,7 @@ static int cmp_bss(struct cfg80211_bss *a,  	if (a->channel != b->channel)  		return b->channel->center_freq - a->channel->center_freq; -	if (WLAN_CAPABILITY_IS_MBSS(a->capability | b->capability)) { +	if (is_mesh_bss(a) && is_mesh_bss(b)) {  		r = cmp_ies(WLAN_EID_MESH_ID,  			    a->information_elements,  			    a->len_information_elements, @@ -457,7 +479,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,  		    struct cfg80211_internal_bss *res)  {  	struct cfg80211_internal_bss *found = NULL; -	const u8 *meshid, *meshcfg;  	/*  	 * The reference to "res" is donated to this function. @@ -470,22 +491,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,  	res->ts = jiffies; -	if (WLAN_CAPABILITY_IS_MBSS(res->pub.capability)) { -		/* must be mesh, verify */ -		meshid = cfg80211_find_ie(WLAN_EID_MESH_ID, -					  res->pub.information_elements, -					  res->pub.len_information_elements); -		meshcfg = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, -					   res->pub.information_elements, -					   res->pub.len_information_elements); -		if (!meshid || !meshcfg || -		    meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) { -			/* bogus mesh */ -			kref_put(&res->ref, bss_release); -			return NULL; -		} -	} -  	spin_lock_bh(&dev->bss_lock);  	found = rb_find_bss(dev, res); diff --git a/sound/pci/asihpi/hpidspcd.c b/sound/pci/asihpi/hpidspcd.c index fb311d8c05b..5c6ea113d21 100644 --- a/sound/pci/asihpi/hpidspcd.c +++ b/sound/pci/asihpi/hpidspcd.c @@ -60,7 +60,7 @@ struct code_header {  	    HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER)))  /***********************************************************************/ -#include "linux/pci.h" +#include <linux/pci.h>  /*-------------------------------------------------------------------*/  short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code,  	u32 *pos_error_code) diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index eacd4901a30..a7ec7030cf8 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -1234,9 +1234,12 @@ static int __devinit snd_fm801_create(struct snd_card *card,  	sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci));  	if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 &&  	    (tea575x_tuner & TUNER_TYPE_MASK) < 4) { -		if (snd_tea575x_init(&chip->tea)) +		if (snd_tea575x_init(&chip->tea)) {  			snd_printk(KERN_ERR "TEA575x radio not found\n"); -	} else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) +			snd_fm801_free(chip); +			return -ENODEV; +		} +	} else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) {  		/* autodetect tuner connection */  		for (tea575x_tuner = 1; tea575x_tuner <= 3; tea575x_tuner++) {  			chip->tea575x_tuner = tea575x_tuner; @@ -1246,6 +1249,12 @@ static int __devinit snd_fm801_create(struct snd_card *card,  				break;  			}  		} +		if (tea575x_tuner == 4) { +			snd_printk(KERN_ERR "TEA575x radio not found\n"); +			snd_fm801_free(chip); +			return -ENODEV; +		} +	}  	strlcpy(chip->tea.card, snd_fm801_tea575x_gpios[(tea575x_tuner & TUNER_TYPE_MASK) - 1].name, sizeof(chip->tea.card));  #endif diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 696ac259030..d694e9d4921 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -506,9 +506,11 @@ static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,  				hda_nid_t hp)  {  	struct ad198x_spec *spec = codec->spec; -	snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE, +	if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD) +		snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,  			    !spec->inv_eapd ? 0x00 : 0x02); -	snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE, +	if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD) +		snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,  			    !spec->inv_eapd ? 0x00 : 0x02);  } @@ -524,6 +526,10 @@ static void ad198x_power_eapd(struct hda_codec *codec)  	case 0x11d4184a:  	case 0x11d4194a:  	case 0x11d4194b: +	case 0x11d41988: +	case 0x11d4198b: +	case 0x11d4989a: +	case 0x11d4989b:  		ad198x_power_eapd_write(codec, 0x12, 0x11);  		break;  	case 0x11d41981: @@ -533,12 +539,6 @@ static void ad198x_power_eapd(struct hda_codec *codec)  	case 0x11d41986:  		ad198x_power_eapd_write(codec, 0x1b, 0x1a);  		break; -	case 0x11d41988: -	case 0x11d4198b: -	case 0x11d4989a: -	case 0x11d4989b: -		ad198x_power_eapd_write(codec, 0x29, 0x22); -		break;  	}  } diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index f8c663dcff0..d68ea532cc7 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -262,14 +262,14 @@ static int v253_hangup(struct tty_struct *tty)  }  /* Line discipline .receive_buf() */ -static unsigned int v253_receive(struct tty_struct *tty, -				 const unsigned char *cp, char *fp, int count) +static void v253_receive(struct tty_struct *tty, +				const unsigned char *cp, char *fp, int count)  {  	struct snd_soc_codec *codec = tty->disc_data;  	struct cx20442_priv *cx20442;  	if (!codec) -		return count; +		return;  	cx20442 = snd_soc_codec_get_drvdata(codec); @@ -281,8 +281,6 @@ static unsigned int v253_receive(struct tty_struct *tty,  		codec->hw_write = (hw_write_t)tty->ops->write;  		codec->card->pop_time = 1;  	} - -	return count;  }  /* Line discipline .write_wakeup() */ diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index e55b298c14a..9e370d14ad8 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -215,23 +215,23 @@ static const struct snd_kcontrol_new analogue_snd_controls[] = {  SOC_SINGLE_TLV("IN1L Volume", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,  	       inpga_tlv),  SOC_SINGLE("IN1L Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 1), -SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 0), +SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 6, 1, 0),  SOC_SINGLE_TLV("IN1R Volume", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,  	       inpga_tlv),  SOC_SINGLE("IN1R Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 1), -SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 0), +SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 6, 1, 0),  SOC_SINGLE_TLV("IN2L Volume", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,  	       inpga_tlv),  SOC_SINGLE("IN2L Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 1), -SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 0), +SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 6, 1, 0),  SOC_SINGLE_TLV("IN2R Volume", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,  	       inpga_tlv),  SOC_SINGLE("IN2R Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 1), -SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 0), +SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 6, 1, 0),  SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8993_INPUT_MIXER3, 7, 1, 0,  	       inmix_sw_tlv), diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 999bb08cdfb..776e6f41830 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -325,6 +325,7 @@ static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,  }  static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, +	struct snd_soc_dapm_widget *kcontrolw,  	const struct snd_kcontrol_new *kcontrol_new,  	struct snd_kcontrol **kcontrol)  { @@ -334,6 +335,8 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,  	*kcontrol = NULL;  	list_for_each_entry(w, &dapm->card->widgets, list) { +		if (w == kcontrolw || w->dapm != kcontrolw->dapm) +			continue;  		for (i = 0; i < w->num_kcontrols; i++) {  			if (&w->kcontrol_news[i] == kcontrol_new) {  				if (w->kcontrols) @@ -468,7 +471,7 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm,  		return -EINVAL;  	} -	shared = dapm_is_shared_kcontrol(dapm, &w->kcontrol_news[0], +	shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[0],  					 &kcontrol);  	if (kcontrol) {  		wlist = kcontrol->private_data; diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index d47beffedb0..a91719d5918 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c @@ -227,6 +227,7 @@ static int usb6fire_fw_ezusb_upload(  	ret = usb6fire_fw_ihex_init(fw, rec);  	if (ret < 0) {  		kfree(rec); +		release_firmware(fw);  		snd_printk(KERN_ERR PREFIX "error validating ezusb "  				"firmware %s.\n", fwname);  		return ret; diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 2e969cbb393..090e1930dfd 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -403,7 +403,7 @@ static int snd_usb_cm106_boot_quirk(struct usb_device *dev)  static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)  {  	int err, reg; -	int val[] = {0x200c, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000}; +	int val[] = {0x2004, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000};  	for (reg = 0; reg < ARRAY_SIZE(val); reg++) {  		err = snd_usb_cm106_write_int_reg(dev, reg, val[reg]); diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 1fd29b2daa9..cef28e6632b 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -788,7 +788,7 @@ sub wait_for_input  sub reboot_to {      if ($reboot_type eq "grub") { -	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; +	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'";  	return;      } @@ -1480,7 +1480,7 @@ sub process_config_ignore {  	or dodie "Failed to read $config";      while (<IN>) { -	if (/^(.*?(CONFIG\S*)(=.*| is not set))/) { +	if (/^((CONFIG\S*)=.*)/) {  	    $config_ignore{$2} = $1;  	}      } @@ -1638,7 +1638,7 @@ sub run_config_bisect {  	if (!$found) {  	    # try the other half  	    doprint "Top half produced no set configs, trying bottom half\n"; -	    @tophalf = @start_list[$half .. $#start_list]; +	    @tophalf = @start_list[$half + 1 .. $#start_list];  	    create_config @tophalf;  	    read_current_config \%current_config;  	    foreach my $config (@tophalf) { @@ -1690,7 +1690,7 @@ sub run_config_bisect {  	# remove half the configs we are looking at and see if  	# they are good.  	$half = int($#start_list / 2); -    } while ($half > 0); +    } while ($#start_list > 0);      # we found a single config, try it again unless we are running manually  |