diff options
| author | Tony Lindgren <tony@atomide.com> | 2010-12-21 16:53:00 -0800 | 
|---|---|---|
| committer | Tony Lindgren <tony@atomide.com> | 2010-12-21 16:53:00 -0800 | 
| commit | bb3613aa34a81a5e2f1227ccdb801fde04a7da10 (patch) | |
| tree | bb79c15d5da41113bd7b83d9e74fbfc4a1bf8569 | |
| parent | 6971071cdda79cad5f53ba390e466d696e7e9006 (diff) | |
| parent | bb1c9034b3ce7f29d3d178a87b42b767611d6574 (diff) | |
| download | olio-linux-3.10-bb3613aa34a81a5e2f1227ccdb801fde04a7da10.tar.xz olio-linux-3.10-bb3613aa34a81a5e2f1227ccdb801fde04a7da10.zip  | |
Merge branch 'pm-next' of ssh://master.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into omap-for-linus
196 files changed, 2673 insertions, 1994 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index cdd2a6e8a3b..8b61c936099 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2175,11 +2175,6 @@ and is between 256 and 4096 characters. It is defined in the file  	reset_devices	[KNL] Force drivers to reset the underlying device  			during initialization. -	resource_alloc_from_bottom -			Allocate new resources from the beginning of available -			space, not the end.  If you need to use this, please -			report a bug. -  	resume=		[SWSUSP]  			Specify the partition device for software suspend diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 489e9bacd16..41cc7b30d7d 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -379,8 +379,8 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:        zero)    bool pm_runtime_suspended(struct device *dev); -    - return true if the device's runtime PM status is 'suspended', or false -      otherwise +    - return true if the device's runtime PM status is 'suspended' and its +      'power.disable_depth' field is equal to zero, or false otherwise    void pm_runtime_allow(struct device *dev);      - set the power.runtime_auto flag for the device and decrease its usage @@ -1,7 +1,7 @@  VERSION = 2  PATCHLEVEL = 6  SUBLEVEL = 37 -EXTRAVERSION = -rc6 +EXTRAVERSION = -rc7  NAME = Flesh-Eating Bats with Fangs  # *DOCUMENTATION* diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 62d686f0b42..d13add71f72 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -65,7 +65,7 @@ obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o  obj-$(CONFIG_MACH_CPU9G20)	+= board-cpu9krea.o  obj-$(CONFIG_MACH_STAMP9G20)	+= board-stamp9g20.o  obj-$(CONFIG_MACH_PORTUXG20)	+= board-stamp9g20.o -obj-$(CONFIG_MACH_PCONTROL_G20)	+= board-pcontrol-g20.o +obj-$(CONFIG_MACH_PCONTROL_G20)	+= board-pcontrol-g20.o board-stamp9g20.o  # AT91SAM9260/AT91SAM9G20 board-specific support  obj-$(CONFIG_MACH_SNAPPER_9260)	+= board-snapper9260.o diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c index bba5a560e02..feb65787c30 100644 --- a/arch/arm/mach-at91/board-pcontrol-g20.c +++ b/arch/arm/mach-at91/board-pcontrol-g20.c @@ -31,6 +31,7 @@  #include <mach/board.h>  #include <mach/at91sam9_smc.h> +#include <mach/stamp9g20.h>  #include "sam9_smc.h"  #include "generic.h" @@ -38,11 +39,7 @@  static void __init pcontrol_g20_map_io(void)  { -	/* Initialize processor: 18.432 MHz crystal */ -	at91sam9260_initialize(18432000); - -	/* DGBU on ttyS0. (Rx, Tx) only TTL -> JTAG connector X7 17,19 ) */ -	at91_register_uart(0, 0, 0); +	stamp9g20_map_io();  	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback  A2 */  	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS @@ -54,9 +51,6 @@ static void __init pcontrol_g20_map_io(void)  	/* USART2 on ttyS3. (Rx, Tx)  9bit-Bus  Multidrop-mode  X4 */  	at91_register_uart(AT91SAM9260_ID_US4, 3, 0); - -	/* set serial console to ttyS0 (ie, DBGU) */ -	at91_set_serial_console(0);  } @@ -66,38 +60,6 @@ static void __init init_irq(void)  } -/* - * NAND flash 512MiB 1,8V 8-bit, sector size 128 KiB - */ -static struct atmel_nand_data __initdata nand_data = { -	.ale		= 21, -	.cle		= 22, -	.rdy_pin	= AT91_PIN_PC13, -	.enable_pin	= AT91_PIN_PC14, -}; - -/* - * Bus timings; unit = 7.57ns - */ -static struct sam9_smc_config __initdata nand_smc_config = { -	.ncs_read_setup		= 0, -	.nrd_setup		= 2, -	.ncs_write_setup	= 0, -	.nwe_setup		= 2, - -	.ncs_read_pulse		= 4, -	.nrd_pulse		= 4, -	.ncs_write_pulse	= 4, -	.nwe_pulse		= 4, - -	.read_cycle		= 7, -	.write_cycle		= 7, - -	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE -			| AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, -	.tdf_cycles		= 3, -}; -  static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {  	.ncs_read_setup		= 16,  	.nrd_setup		= 18, @@ -138,14 +100,6 @@ static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {  	.tdf_cycles		= 1,  } }; -static void __init add_device_nand(void) -{ -	/* configure chip-select 3 (NAND) */ -	sam9_smc_configure(3, &nand_smc_config); -	at91_add_device_nand(&nand_data); -} - -  static void __init add_device_pcontrol(void)  {  	/* configure chip-select 4 (IO compatible to 8051  X4 ) */ @@ -156,23 +110,6 @@ static void __init add_device_pcontrol(void)  /* - * MCI (SD/MMC) - * det_pin, wp_pin and vcc_pin are not connected - */ -#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) -static struct mci_platform_data __initdata mmc_data = { -	.slot[0] = { -		.bus_width	= 4, -	}, -}; -#else -static struct at91_mmc_data __initdata mmc_data = { -	.wire4		= 1, -}; -#endif - - -/*   * USB Host port   */  static struct at91_usbh_data __initdata usbh_data = { @@ -265,42 +202,13 @@ static struct spi_board_info pcontrol_g20_spi_devices[] = {  }; -/* - * Dallas 1-Wire  DS2431 - */ -static struct w1_gpio_platform_data w1_gpio_pdata = { -	.pin		= AT91_PIN_PA29, -	.is_open_drain	= 1, -}; - -static struct platform_device w1_device = { -	.name			= "w1-gpio", -	.id			= -1, -	.dev.platform_data	= &w1_gpio_pdata, -}; - -static void add_wire1(void) -{ -	at91_set_GPIO_periph(w1_gpio_pdata.pin, 1); -	at91_set_multi_drive(w1_gpio_pdata.pin, 1); -	platform_device_register(&w1_device); -} - -  static void __init pcontrol_g20_board_init(void)  { -	at91_add_device_serial(); -	add_device_nand(); -#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) -	at91_add_device_mci(0, &mmc_data); -#else -	at91_add_device_mmc(0, &mmc_data); -#endif +	stamp9g20_board_init();  	at91_add_device_usbh(&usbh_data);  	at91_add_device_eth(&macb_data);  	at91_add_device_i2c(pcontrol_g20_i2c_devices,  		ARRAY_SIZE(pcontrol_g20_i2c_devices)); -	add_wire1();  	add_device_pcontrol();  	at91_add_device_spi(pcontrol_g20_spi_devices,  		ARRAY_SIZE(pcontrol_g20_spi_devices)); diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c index 5206eef4a67..f8902b11896 100644 --- a/arch/arm/mach-at91/board-stamp9g20.c +++ b/arch/arm/mach-at91/board-stamp9g20.c @@ -32,7 +32,7 @@  #include "generic.h" -static void __init portuxg20_map_io(void) +void __init stamp9g20_map_io(void)  {  	/* Initialize processor: 18.432 MHz crystal */  	at91sam9260_initialize(18432000); @@ -40,6 +40,24 @@ static void __init portuxg20_map_io(void)  	/* DGBU on ttyS0. (Rx & Tx only) */  	at91_register_uart(0, 0, 0); +	/* set serial console to ttyS0 (ie, DBGU) */ +	at91_set_serial_console(0); +} + +static void __init stamp9g20evb_map_io(void) +{ +	stamp9g20_map_io(); + +	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ +	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS +						| ATMEL_UART_DTR | ATMEL_UART_DSR +						| ATMEL_UART_DCD | ATMEL_UART_RI); +} + +static void __init portuxg20_map_io(void) +{ +	stamp9g20_map_io(); +  	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */  	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS  						| ATMEL_UART_DTR | ATMEL_UART_DSR @@ -56,26 +74,6 @@ static void __init portuxg20_map_io(void)  	/* USART5 on ttyS6. (Rx, Tx only) */  	at91_register_uart(AT91SAM9260_ID_US5, 6, 0); - -	/* set serial console to ttyS0 (ie, DBGU) */ -	at91_set_serial_console(0); -} - -static void __init stamp9g20_map_io(void) -{ -	/* Initialize processor: 18.432 MHz crystal */ -	at91sam9260_initialize(18432000); - -	/* DGBU on ttyS0. (Rx & Tx only) */ -	at91_register_uart(0, 0, 0); - -	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ -	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS -						| ATMEL_UART_DTR | ATMEL_UART_DSR -						| ATMEL_UART_DCD | ATMEL_UART_RI); - -	/* set serial console to ttyS0 (ie, DBGU) */ -	at91_set_serial_console(0);  }  static void __init init_irq(void) @@ -156,7 +154,7 @@ static struct at91_udc_data __initdata portuxg20_udc_data = {  	.pullup_pin	= 0,		/* pull-up driven by UDC */  }; -static struct at91_udc_data __initdata stamp9g20_udc_data = { +static struct at91_udc_data __initdata stamp9g20evb_udc_data = {  	.vbus_pin	= AT91_PIN_PA22,  	.pullup_pin	= 0,		/* pull-up driven by UDC */  }; @@ -190,7 +188,7 @@ static struct gpio_led portuxg20_leds[] = {  	}  }; -static struct gpio_led stamp9g20_leds[] = { +static struct gpio_led stamp9g20evb_leds[] = {  	{  		.name			= "D8",  		.gpio			= AT91_PIN_PB18, @@ -250,7 +248,7 @@ void add_w1(void)  } -static void __init generic_board_init(void) +void __init stamp9g20_board_init(void)  {  	/* Serial */  	at91_add_device_serial(); @@ -262,34 +260,40 @@ static void __init generic_board_init(void)  #else  	at91_add_device_mmc(0, &mmc_data);  #endif -	/* USB Host */ -	at91_add_device_usbh(&usbh_data); -	/* Ethernet */ -	at91_add_device_eth(&macb_data); -	/* I2C */ -	at91_add_device_i2c(NULL, 0);  	/* W1 */  	add_w1();  }  static void __init portuxg20_board_init(void)  { -	generic_board_init(); -	/* SPI */ -	at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices)); +	stamp9g20_board_init(); +	/* USB Host */ +	at91_add_device_usbh(&usbh_data);  	/* USB Device */  	at91_add_device_udc(&portuxg20_udc_data); +	/* Ethernet */ +	at91_add_device_eth(&macb_data); +	/* I2C */ +	at91_add_device_i2c(NULL, 0); +	/* SPI */ +	at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices));  	/* LEDs */  	at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds));  } -static void __init stamp9g20_board_init(void) +static void __init stamp9g20evb_board_init(void)  { -	generic_board_init(); +	stamp9g20_board_init(); +	/* USB Host */ +	at91_add_device_usbh(&usbh_data);  	/* USB Device */ -	at91_add_device_udc(&stamp9g20_udc_data); +	at91_add_device_udc(&stamp9g20evb_udc_data); +	/* Ethernet */ +	at91_add_device_eth(&macb_data); +	/* I2C */ +	at91_add_device_i2c(NULL, 0);  	/* LEDs */ -	at91_gpio_leds(stamp9g20_leds, ARRAY_SIZE(stamp9g20_leds)); +	at91_gpio_leds(stamp9g20evb_leds, ARRAY_SIZE(stamp9g20evb_leds));  }  MACHINE_START(PORTUXG20, "taskit PortuxG20") @@ -305,7 +309,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20")  	/* Maintainer: taskit GmbH */  	.boot_params	= AT91_SDRAM_BASE + 0x100,  	.timer		= &at91sam926x_timer, -	.map_io		= stamp9g20_map_io, +	.map_io		= stamp9g20evb_map_io,  	.init_irq	= init_irq, -	.init_machine	= stamp9g20_board_init, +	.init_machine	= stamp9g20evb_board_init,  MACHINE_END diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 7525cee3983..9113da6845f 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -658,7 +658,7 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock)  	/* Now set uhpck values */  	uhpck.parent = &utmi_clk;  	uhpck.pmc_mask = AT91SAM926x_PMC_UHP; -	uhpck.rate_hz = utmi_clk.parent->rate_hz; +	uhpck.rate_hz = utmi_clk.rate_hz;  	uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8);  } diff --git a/arch/arm/mach-at91/include/mach/stamp9g20.h b/arch/arm/mach-at91/include/mach/stamp9g20.h new file mode 100644 index 00000000000..6120f9c46d5 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/stamp9g20.h @@ -0,0 +1,7 @@ +#ifndef __MACH_STAMP9G20_H +#define __MACH_STAMP9G20_H + +void stamp9g20_map_io(void); +void stamp9g20_board_init(void); + +#endif diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index 1fa3294b604..0269bb055b6 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -239,9 +239,19 @@ void omap3_save_scratchpad_contents(void)  	struct omap3_scratchpad_prcm_block prcm_block_contents;  	struct omap3_scratchpad_sdrc_block sdrc_block_contents; -	/* Populate the Scratchpad contents */ +	/* +	 * Populate the Scratchpad contents +	 * +	 * The "get_*restore_pointer" functions are used to provide a +	 * physical restore address where the ROM code jumps while waking +	 * up from MPU OFF/OSWR state. +	 * The restore pointer is stored into the scratchpad. +	 */  	scratchpad_contents.boot_config_ptr = 0x0; -	if (omap_rev() != OMAP3430_REV_ES3_0 && +	if (cpu_is_omap3630()) +		scratchpad_contents.public_restore_ptr = +			virt_to_phys(get_omap3630_restore_pointer()); +	else if (omap_rev() != OMAP3430_REV_ES3_0 &&  					omap_rev() != OMAP3430_REV_ES3_1)  		scratchpad_contents.public_restore_ptr =  			virt_to_phys(get_restore_pointer()); @@ -474,4 +484,12 @@ void omap3_control_restore_context(void)  	omap_ctrl_writel(control_context.csi, OMAP343X_CONTROL_CSI);  	return;  } + +void omap3630_ctrl_disable_rta(void) +{ +	if (!cpu_is_omap3630()) +		return; +	omap_ctrl_writel(OMAP36XX_RTA_DISABLE, OMAP36XX_CONTROL_MEM_RTA_CTRL); +} +  #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */ diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h index b6c6b7c450b..6e5f7e512ff 100644 --- a/arch/arm/mach-omap2/control.h +++ b/arch/arm/mach-omap2/control.h @@ -204,6 +204,10 @@  #define OMAP343X_CONTROL_WKUP_DEBOBS3 (OMAP343X_CONTROL_GENERAL_WKUP + 0x014)  #define OMAP343X_CONTROL_WKUP_DEBOBS4 (OMAP343X_CONTROL_GENERAL_WKUP + 0x018) +/* 36xx-only RTA - Retention till Accesss control registers and bits */ +#define OMAP36XX_CONTROL_MEM_RTA_CTRL	0x40C +#define OMAP36XX_RTA_DISABLE		0x0 +  /* 34xx D2D idle-related pins, handled by PM core */  #define OMAP3_PADCONF_SAD2D_MSTANDBY   0x250  #define OMAP3_PADCONF_SAD2D_IDLEACK    0x254 @@ -270,6 +274,8 @@  #define OMAP343X_SCRATCHPAD_ROM		(OMAP343X_CTRL_BASE + 0x860)  #define OMAP343X_SCRATCHPAD		(OMAP343X_CTRL_BASE + 0x910)  #define OMAP343X_SCRATCHPAD_ROM_OFFSET	0x19C +#define OMAP343X_SCRATCHPAD_REGADDR(reg)	OMAP2_L4_IO_ADDRESS(\ +						OMAP343X_SCRATCHPAD + reg)  /* AM35XX_CONTROL_IPSS_CLK_CTRL bits */  #define AM35XX_USBOTG_VBUSP_CLK_SHIFT   0 @@ -347,10 +353,11 @@ extern void omap3_save_scratchpad_contents(void);  extern void omap3_clear_scratchpad_contents(void);  extern u32 *get_restore_pointer(void);  extern u32 *get_es3_restore_pointer(void); +extern u32 *get_omap3630_restore_pointer(void);  extern u32 omap3_arm_context[128];  extern void omap3_control_save_context(void);  extern void omap3_control_restore_context(void); - +extern void omap3630_ctrl_disable_rta(void);  #else  #define omap_ctrl_base_get()		0  #define omap_ctrl_readb(x)		0 diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 0d50b45d041..0fb619c5258 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -293,25 +293,26 @@ select_state:  DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);  /** - * omap3_cpuidle_update_states - Update the cpuidle states. + * omap3_cpuidle_update_states() - Update the cpuidle states + * @mpu_deepest_state:	Enable states upto and including this for mpu domain + * @core_deepest_state:	Enable states upto and including this for core domain   * - * Currently, this function toggles the validity of idle states based upon - * the flag 'enable_off_mode'. When the flag is set all states are valid. - * Else, states leading to OFF state set to be invalid. + * This goes through the list of states available and enables and disables the + * validity of C states based on deepest state that can be achieved for the + * variable domain   */ -void omap3_cpuidle_update_states(void) +void omap3_cpuidle_update_states(u32 mpu_deepest_state, u32 core_deepest_state)  {  	int i;  	for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) {  		struct omap3_processor_cx *cx = &omap3_power_states[i]; -		if (enable_off_mode) { +		if ((cx->mpu_state >= mpu_deepest_state) && +		    (cx->core_state >= core_deepest_state)) {  			cx->valid = 1;  		} else { -			if ((cx->mpu_state == PWRDM_POWER_OFF) || -				(cx->core_state	== PWRDM_POWER_OFF)) -				cx->valid = 0; +			cx->valid = 0;  		}  	}  } @@ -452,6 +453,18 @@ void omap_init_power_states(void)  	omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF;  	omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID |  				CPUIDLE_FLAG_CHECK_BM; + +	/* +	 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot +	 * enable OFF mode in a stable form for previous revisions. +	 * we disable C7 state as a result. +	 */ +	if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) { +		omap3_power_states[OMAP3_STATE_C7].valid = 0; +		cpuidle_params_table[OMAP3_STATE_C7].valid = 0; +		WARN_ONCE(1, "%s: core off state C7 disabled due to i583\n", +				__func__); +	}  }  struct cpuidle_driver omap3_idle_driver = { @@ -504,7 +517,10 @@ int __init omap3_idle_init(void)  		return -EINVAL;  	dev->state_count = count; -	omap3_cpuidle_update_states(); +	if (enable_off_mode) +		omap3_cpuidle_update_states(PWRDM_POWER_OFF, PWRDM_POWER_OFF); +	else +		omap3_cpuidle_update_states(PWRDM_POWER_RET, PWRDM_POWER_RET);  	if (cpuidle_register_device(dev)) {  		printk(KERN_ERR "%s: CPUidle register device failed\n", diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 59ca03b0e69..6ec2ee12272 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -143,5 +143,5 @@ static int __init omap2_common_pm_init(void)  	return 0;  } -device_initcall(omap2_common_pm_init); +postcore_initcall(omap2_common_pm_init); diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 0d75bfd1fdb..c04f7b50e26 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -58,7 +58,7 @@ extern u32 sleep_while_idle;  #endif  #if defined(CONFIG_CPU_IDLE) -extern void omap3_cpuidle_update_states(void); +extern void omap3_cpuidle_update_states(u32, u32);  #endif  #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) @@ -80,9 +80,20 @@ extern void save_secure_ram_context(u32 *addr);  extern void omap3_save_scratchpad_contents(void);  extern unsigned int omap24xx_idle_loop_suspend_sz; -extern unsigned int omap34xx_suspend_sz;  extern unsigned int save_secure_ram_context_sz;  extern unsigned int omap24xx_cpu_suspend_sz;  extern unsigned int omap34xx_cpu_suspend_sz; +#define PM_RTA_ERRATUM_i608		(1 << 0) +#define PM_SDRC_WAKEUP_ERRATUM_i583	(1 << 1) + +#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) +extern u16 pm34xx_errata; +#define IS_PM34XX_ERRATUM(id)		(pm34xx_errata & (id)) +extern void enable_omap3630_toggle_l2_on_restore(void); +#else +#define IS_PM34XX_ERRATUM(id)		0 +static inline void enable_omap3630_toggle_l2_on_restore(void) { } +#endif		/* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */ +  #endif diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index aaeea49b9bd..aea7ced9a2f 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -301,14 +301,8 @@ out:  static int omap2_pm_begin(suspend_state_t state)  { -	suspend_state = state; -	return 0; -} - -static int omap2_pm_prepare(void) -{ -	/* We cannot sleep in idle until we have resumed */  	disable_hlt(); +	suspend_state = state;  	return 0;  } @@ -349,21 +343,15 @@ static int omap2_pm_enter(suspend_state_t state)  	return ret;  } -static void omap2_pm_finish(void) -{ -	enable_hlt(); -} -  static void omap2_pm_end(void)  {  	suspend_state = PM_SUSPEND_ON; +	enable_hlt();  }  static struct platform_suspend_ops omap_pm_ops = {  	.begin		= omap2_pm_begin, -	.prepare	= omap2_pm_prepare,  	.enter		= omap2_pm_enter, -	.finish		= omap2_pm_finish,  	.end		= omap2_pm_end,  	.valid		= suspend_valid_only_mem,  }; diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 648b8c50d02..c45b4fa1dee 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -68,6 +68,9 @@ static inline bool is_suspending(void)  #define OMAP343X_TABLE_VALUE_OFFSET	   0xc0  #define OMAP343X_CONTROL_REG_VALUE_OFFSET  0xc8 +/* pm34xx errata defined in pm.h */ +u16 pm34xx_errata; +  struct power_state {  	struct powerdomain *pwrdm;  	u32 next_state; @@ -143,7 +146,7 @@ static void omap3_core_save_context(void)  	/*  	 * Force write last pad into memory, as this can fail in some -	 * cases according to erratas 1.157, 1.185 +	 * cases according to errata 1.157, 1.185  	 */  	omap_ctrl_writel(omap_ctrl_readl(OMAP343X_PADCONF_ETK_D14),  		OMAP343X_CONTROL_MEM_WKUP + 0x2a0); @@ -430,7 +433,7 @@ void omap_sram_idle(void)  	/*  	* On EMU/HS devices ROM code restores a SRDC value  	* from scratchpad which has automatic self refresh on timeout -	* of AUTO_CNT = 1 enabled. This takes care of errata 1.142. +	* of AUTO_CNT = 1 enabled. This takes care of erratum ID i443.  	* Hence store/restore the SDRC_POWER register here.  	*/  	if (omap_rev() >= OMAP3430_REV_ES3_0 && @@ -529,12 +532,6 @@ out:  }  #ifdef CONFIG_SUSPEND -static int omap3_pm_prepare(void) -{ -	disable_hlt(); -	return 0; -} -  static int omap3_pm_suspend(void)  {  	struct power_state *pwrst; @@ -597,14 +594,10 @@ static int omap3_pm_enter(suspend_state_t unused)  	return ret;  } -static void omap3_pm_finish(void) -{ -	enable_hlt(); -} -  /* Hooks to enable / disable UART interrupts during suspend */  static int omap3_pm_begin(suspend_state_t state)  { +	disable_hlt();  	suspend_state = state;  	omap_uart_enable_irqs(0);  	return 0; @@ -614,15 +607,14 @@ static void omap3_pm_end(void)  {  	suspend_state = PM_SUSPEND_ON;  	omap_uart_enable_irqs(1); +	enable_hlt();  	return;  }  static struct platform_suspend_ops omap_pm_ops = {  	.begin		= omap3_pm_begin,  	.end		= omap3_pm_end, -	.prepare	= omap3_pm_prepare,  	.enter		= omap3_pm_enter, -	.finish		= omap3_pm_finish,  	.valid		= suspend_valid_only_mem,  };  #endif /* CONFIG_SUSPEND */ @@ -925,12 +917,29 @@ void omap3_pm_off_mode_enable(int enable)  		state = PWRDM_POWER_RET;  #ifdef CONFIG_CPU_IDLE -	omap3_cpuidle_update_states(); +	/* +	 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot +	 * enable OFF mode in a stable form for previous revisions, restrict +	 * instead to RET +	 */ +	if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) +		omap3_cpuidle_update_states(state, PWRDM_POWER_RET); +	else +		omap3_cpuidle_update_states(state, state);  #endif  	list_for_each_entry(pwrst, &pwrst_list, node) { -		pwrst->next_state = state; -		omap_set_pwrdm_state(pwrst->pwrdm, state); +		if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) && +				pwrst->pwrdm == core_pwrdm && +				state == PWRDM_POWER_OFF) { +			pwrst->next_state = PWRDM_POWER_RET; +			WARN_ONCE(1, +				"%s: Core OFF disabled due to errata i583\n", +				__func__); +		} else { +			pwrst->next_state = state; +		} +		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);  	}  } @@ -1002,6 +1011,17 @@ void omap_push_sram_idle(void)  				save_secure_ram_context_sz);  } +static void __init pm_errata_configure(void) +{ +	if (cpu_is_omap3630()) { +		pm34xx_errata |= PM_RTA_ERRATUM_i608; +		/* Enable the l2 cache toggling in sleep logic */ +		enable_omap3630_toggle_l2_on_restore(); +		if (omap_rev() < OMAP3630_REV_ES1_2) +			pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583; +	} +} +  static int __init omap3_pm_init(void)  {  	struct power_state *pwrst, *tmp; @@ -1011,6 +1031,8 @@ static int __init omap3_pm_init(void)  	if (!cpu_is_omap34xx())  		return -ENODEV; +	pm_errata_configure(); +  	printk(KERN_ERR "Power Management for TI OMAP3.\n");  	/* XXX prcm_setup_regs needs to be before enabling hw @@ -1058,6 +1080,14 @@ static int __init omap3_pm_init(void)  	pm_idle = omap3_pm_idle;  	omap3_idle_init(); +	/* +	 * RTA is disabled during initialization as per erratum i608 +	 * it is safer to disable RTA by the bootloader, but we would like +	 * to be doubly sure here and prevent any mishaps. +	 */ +	if (IS_PM34XX_ERRATUM(PM_RTA_ERRATUM_i608)) +		omap3630_ctrl_disable_rta(); +  	clkdm_add_wkdep(neon_clkdm, mpu_clkdm);  	if (omap_type() != OMAP2_DEVICE_TYPE_GP) {  		omap3_secure_ram_storage = diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index 54544b4fc76..6aff9961e35 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -31,12 +31,6 @@ struct power_state {  static LIST_HEAD(pwrst_list);  #ifdef CONFIG_SUSPEND -static int omap4_pm_prepare(void) -{ -	disable_hlt(); -	return 0; -} -  static int omap4_pm_suspend(void)  {  	do_wfi(); @@ -59,28 +53,22 @@ static int omap4_pm_enter(suspend_state_t suspend_state)  	return ret;  } -static void omap4_pm_finish(void) -{ -	enable_hlt(); -	return; -} -  static int omap4_pm_begin(suspend_state_t state)  { +	disable_hlt();  	return 0;  }  static void omap4_pm_end(void)  { +	enable_hlt();  	return;  }  static struct platform_suspend_ops omap_pm_ops = {  	.begin		= omap4_pm_begin,  	.end		= omap4_pm_end, -	.prepare	= omap4_pm_prepare,  	.enter		= omap4_pm_enter, -	.finish		= omap4_pm_finish,  	.valid		= suspend_valid_only_mem,  };  #endif /* CONFIG_SUSPEND */ diff --git a/arch/arm/mach-omap2/sdrc.h b/arch/arm/mach-omap2/sdrc.h index 68f57bb67fc..b3f83799e6c 100644 --- a/arch/arm/mach-omap2/sdrc.h +++ b/arch/arm/mach-omap2/sdrc.h @@ -74,5 +74,4 @@ static inline u32 sms_read_reg(u16 reg)   */  #define SDRC_MPURATE_LOOPS		96 -  #endif diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S index 2fb205a7f28..e3b5cd76c54 100644 --- a/arch/arm/mach-omap2/sleep34xx.S +++ b/arch/arm/mach-omap2/sleep34xx.S @@ -1,6 +1,4 @@  /* - * linux/arch/arm/mach-omap2/sleep.S - *   * (C) Copyright 2007   * Texas Instruments   * Karthik Dasu <karthik-dp@ti.com> @@ -26,6 +24,7 @@   */  #include <linux/linkage.h>  #include <asm/assembler.h> +#include <plat/sram.h>  #include <mach/io.h>  #include "cm.h" @@ -33,21 +32,27 @@  #include "sdrc.h"  #include "control.h" -#define SDRC_SCRATCHPAD_SEM_V	0xfa00291c - -#define PM_PREPWSTST_CORE_V	OMAP34XX_PRM_REGADDR(CORE_MOD, \ -				OMAP3430_PM_PREPWSTST) -#define PM_PREPWSTST_CORE_P	0x48306AE8 -#define PM_PREPWSTST_MPU_V	OMAP34XX_PRM_REGADDR(MPU_MOD, \ -				OMAP3430_PM_PREPWSTST) +/* + * Registers access definitions + */ +#define SDRC_SCRATCHPAD_SEM_OFFS	0xc +#define SDRC_SCRATCHPAD_SEM_V	OMAP343X_SCRATCHPAD_REGADDR\ +					(SDRC_SCRATCHPAD_SEM_OFFS) +#define PM_PREPWSTST_CORE_P	OMAP3430_PRM_BASE + CORE_MOD +\ +					OMAP3430_PM_PREPWSTST  #define PM_PWSTCTRL_MPU_P	OMAP3430_PRM_BASE + MPU_MOD + OMAP2_PM_PWSTCTRL  #define CM_IDLEST1_CORE_V	OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST1) -#define SRAM_BASE_P		0x40200000 -#define CONTROL_STAT		0x480022F0 -#define SCRATCHPAD_MEM_OFFS	0x310 /* Move this as correct place is -				       * available */ -#define SCRATCHPAD_BASE_P	(OMAP343X_CTRL_BASE + OMAP343X_CONTROL_MEM_WKUP\ -						+ SCRATCHPAD_MEM_OFFS) +#define CM_IDLEST_CKGEN_V	OMAP34XX_CM_REGADDR(PLL_MOD, CM_IDLEST) +#define SRAM_BASE_P		OMAP3_SRAM_PA +#define CONTROL_STAT		OMAP343X_CTRL_BASE + OMAP343X_CONTROL_STATUS +#define CONTROL_MEM_RTA_CTRL	(OMAP343X_CTRL_BASE +\ +					OMAP36XX_CONTROL_MEM_RTA_CTRL) + +/* Move this as correct place is available */ +#define SCRATCHPAD_MEM_OFFS	0x310 +#define SCRATCHPAD_BASE_P	(OMAP343X_CTRL_BASE +\ +					OMAP343X_CONTROL_MEM_WKUP +\ +					SCRATCHPAD_MEM_OFFS)  #define SDRC_POWER_V		OMAP34XX_SDRC_REGADDR(SDRC_POWER)  #define SDRC_SYSCONFIG_P	(OMAP343X_SDRC_BASE + SDRC_SYSCONFIG)  #define SDRC_MR_0_P		(OMAP343X_SDRC_BASE + SDRC_MR_0) @@ -59,48 +64,38 @@  #define SDRC_DLLA_STATUS_V	OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS)  #define SDRC_DLLA_CTRL_V	OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL) -        .text -/* Function to acquire the semaphore in scratchpad */ -ENTRY(lock_scratchpad_sem) -	stmfd	sp!, {lr}	@ save registers on stack -wait_sem: -	mov	r0,#1 -	ldr	r1, sdrc_scratchpad_sem -wait_loop: -	ldr	r2, [r1]	@ load the lock value -	cmp	r2, r0		@ is the lock free ? -	beq	wait_loop	@ not free... -	swp	r2, r0, [r1]	@ semaphore free so lock it and proceed -	cmp	r2, r0		@ did we succeed ? -	beq	wait_sem	@ no - try again -	ldmfd	sp!, {pc}	@ restore regs and return -sdrc_scratchpad_sem: -        .word SDRC_SCRATCHPAD_SEM_V -ENTRY(lock_scratchpad_sem_sz) -        .word   . - lock_scratchpad_sem -        .text -/* Function to release the scratchpad semaphore */ -ENTRY(unlock_scratchpad_sem) -	stmfd	sp!, {lr}	@ save registers on stack -	ldr	r3, sdrc_scratchpad_sem -	mov	r2,#0 -	str	r2,[r3] -	ldmfd	sp!, {pc}	@ restore regs and return -ENTRY(unlock_scratchpad_sem_sz) -        .word   . - unlock_scratchpad_sem +/* + * API functions + */ + +/* + * The "get_*restore_pointer" functions are used to provide a + * physical restore address where the ROM code jumps while waking + * up from MPU OFF/OSWR state. + * The restore pointer is stored into the scratchpad. + */  	.text  /* Function call to get the restore pointer for resume from OFF */  ENTRY(get_restore_pointer) -        stmfd   sp!, {lr}     @ save registers on stack +	stmfd	sp!, {lr}	@ save registers on stack  	adr	r0, restore -        ldmfd   sp!, {pc}     @ restore regs and return +	ldmfd	sp!, {pc}	@ restore regs and return  ENTRY(get_restore_pointer_sz) -        .word   . - get_restore_pointer +	.word	. - get_restore_pointer  	.text -/* Function call to get the restore pointer for for ES3 to resume from OFF */ +/* Function call to get the restore pointer for 3630 resume from OFF */ +ENTRY(get_omap3630_restore_pointer) +	stmfd	sp!, {lr}	@ save registers on stack +	adr	r0, restore_3630 +	ldmfd	sp!, {pc}	@ restore regs and return +ENTRY(get_omap3630_restore_pointer_sz) +	.word	. - get_omap3630_restore_pointer + +	.text +/* Function call to get the restore pointer for ES3 to resume from OFF */  ENTRY(get_es3_restore_pointer)  	stmfd	sp!, {lr}	@ save registers on stack  	adr	r0, restore_es3 @@ -108,54 +103,23 @@ ENTRY(get_es3_restore_pointer)  ENTRY(get_es3_restore_pointer_sz)  	.word	. - get_es3_restore_pointer -ENTRY(es3_sdrc_fix) -	ldr	r4, sdrc_syscfg		@ get config addr -	ldr	r5, [r4]		@ get value -	tst	r5, #0x100		@ is part access blocked -	it	eq -	biceq	r5, r5, #0x100		@ clear bit if set -	str	r5, [r4]		@ write back change -	ldr	r4, sdrc_mr_0		@ get config addr -	ldr	r5, [r4]		@ get value -	str	r5, [r4]		@ write back change -	ldr	r4, sdrc_emr2_0		@ get config addr -	ldr	r5, [r4]		@ get value -	str	r5, [r4]		@ write back change -	ldr	r4, sdrc_manual_0	@ get config addr -	mov	r5, #0x2		@ autorefresh command -	str	r5, [r4]		@ kick off refreshes -	ldr	r4, sdrc_mr_1		@ get config addr -	ldr	r5, [r4]		@ get value -	str	r5, [r4]		@ write back change -	ldr	r4, sdrc_emr2_1		@ get config addr -	ldr	r5, [r4]		@ get value -	str	r5, [r4]		@ write back change -	ldr	r4, sdrc_manual_1	@ get config addr -	mov	r5, #0x2		@ autorefresh command -	str	r5, [r4]		@ kick off refreshes -	bx	lr -sdrc_syscfg: -	.word	SDRC_SYSCONFIG_P -sdrc_mr_0: -	.word	SDRC_MR_0_P -sdrc_emr2_0: -	.word	SDRC_EMR2_0_P -sdrc_manual_0: -	.word	SDRC_MANUAL_0_P -sdrc_mr_1: -	.word	SDRC_MR_1_P -sdrc_emr2_1: -	.word	SDRC_EMR2_1_P -sdrc_manual_1: -	.word	SDRC_MANUAL_1_P -ENTRY(es3_sdrc_fix_sz) -	.word	. - es3_sdrc_fix +	.text +/* + * L2 cache needs to be toggled for stable OFF mode functionality on 3630. + * This function sets up a flag that will allow for this toggling to take + * place on 3630. Hopefully some version in the future may not need this. + */ +ENTRY(enable_omap3630_toggle_l2_on_restore) +	stmfd	sp!, {lr}	@ save registers on stack +	/* Setup so that we will disable and enable l2 */ +	mov	r1, #0x1 +	str	r1, l2dis_3630 +	ldmfd	sp!, {pc}	@ restore regs and return +	.text  /* Function to call rom code to save secure ram context */  ENTRY(save_secure_ram_context)  	stmfd	sp!, {r1-r12, lr}	@ save registers on stack -save_secure_ram_debug: -	/* b save_secure_ram_debug */	@ enable to debug save code  	adr	r3, api_params		@ r3 points to parameters  	str	r0, [r3,#0x4]		@ r0 has sdram address  	ldr	r12, high_mask @@ -185,35 +149,162 @@ ENTRY(save_secure_ram_context_sz)  	.word	. - save_secure_ram_context  /* + * ====================== + * == Idle entry point == + * ====================== + */ + +/*   * Forces OMAP into idle state   * - * omap34xx_suspend() - This bit of code just executes the WFI - * for normal idles. + * omap34xx_cpu_suspend() - This bit of code saves the CPU context if needed + * and executes the WFI instruction. Calling WFI effectively changes the + * power domains states to the desired target power states.   * - * Note: This code get's copied to internal SRAM at boot. When the OMAP - *	 wakes up it continues execution at the point it went to sleep. + * + * Notes: + * - this code gets copied to internal SRAM at boot and after wake-up + *   from OFF mode. The execution pointer in SRAM is _omap_sram_idle. + * - when the OMAP wakes up it continues at different execution points + *   depending on the low power mode (non-OFF vs OFF modes), + *   cf. 'Resume path for xxx mode' comments.   */  ENTRY(omap34xx_cpu_suspend) -	stmfd	sp!, {r0-r12, lr}		@ save registers on stack -loop: -	/*b	loop*/	@Enable to debug by stepping through code -	/* r0 contains restore pointer in sdram */ -	/* r1 contains information about saving context */ -	ldr     r4, sdrc_power          @ read the SDRC_POWER register -	ldr     r5, [r4]                @ read the contents of SDRC_POWER -	orr     r5, r5, #0x40           @ enable self refresh on idle req -	str     r5, [r4]                @ write back to SDRC_POWER register +	stmfd	sp!, {r0-r12, lr}	@ save registers on stack + +	/* +	 * r0 contains restore pointer in sdram +	 * r1 contains information about saving context: +	 *   0 - No context lost +	 *   1 - Only L1 and logic lost +	 *   2 - Only L2 lost +	 *   3 - Both L1 and L2 lost +	 */ +	/* Directly jump to WFI is the context save is not required */  	cmp	r1, #0x0 -	/* If context save is required, do that and execute wfi */ -	bne	save_context_wfi +	beq	omap3_do_wfi + +	/* Otherwise fall through to the save context code */ +save_context_wfi: +	mov	r8, r0			@ Store SDRAM address in r8 +	mrc	p15, 0, r5, c1, c0, 1	@ Read Auxiliary Control Register +	mov	r4, #0x1		@ Number of parameters for restore call +	stmia	r8!, {r4-r5}		@ Push parameters for restore call +	mrc	p15, 1, r5, c9, c0, 2	@ Read L2 AUX ctrl register +	stmia	r8!, {r4-r5}		@ Push parameters for restore call + +        /* Check what that target sleep state is from r1 */ +	cmp	r1, #0x2		@ Only L2 lost, no need to save context +	beq	clean_caches + +l1_logic_lost: +	/* Store sp and spsr to SDRAM */ +	mov	r4, sp +	mrs	r5, spsr +	mov	r6, lr +	stmia	r8!, {r4-r6} +	/* Save all ARM registers */ +	/* Coprocessor access control register */ +	mrc	p15, 0, r6, c1, c0, 2 +	stmia	r8!, {r6} +	/* TTBR0, TTBR1 and Translation table base control */ +	mrc	p15, 0, r4, c2, c0, 0 +	mrc	p15, 0, r5, c2, c0, 1 +	mrc	p15, 0, r6, c2, c0, 2 +	stmia	r8!, {r4-r6} +	/* +	 * Domain access control register, data fault status register, +	 * and instruction fault status register +	 */ +	mrc	p15, 0, r4, c3, c0, 0 +	mrc	p15, 0, r5, c5, c0, 0 +	mrc	p15, 0, r6, c5, c0, 1 +	stmia	r8!, {r4-r6} +	/* +	 * Data aux fault status register, instruction aux fault status, +	 * data fault address register and instruction fault address register +	 */ +	mrc	p15, 0, r4, c5, c1, 0 +	mrc	p15, 0, r5, c5, c1, 1 +	mrc	p15, 0, r6, c6, c0, 0 +	mrc	p15, 0, r7, c6, c0, 2 +	stmia	r8!, {r4-r7} +	/* +	 * user r/w thread and process ID, user r/o thread and process ID, +	 * priv only thread and process ID, cache size selection +	 */ +	mrc	p15, 0, r4, c13, c0, 2 +	mrc	p15, 0, r5, c13, c0, 3 +	mrc	p15, 0, r6, c13, c0, 4 +	mrc	p15, 2, r7, c0, c0, 0 +	stmia	r8!, {r4-r7} +	/* Data TLB lockdown, instruction TLB lockdown registers */ +	mrc	p15, 0, r5, c10, c0, 0 +	mrc	p15, 0, r6, c10, c0, 1 +	stmia	r8!, {r5-r6} +	/* Secure or non secure vector base address, FCSE PID, Context PID*/ +	mrc	p15, 0, r4, c12, c0, 0 +	mrc	p15, 0, r5, c13, c0, 0 +	mrc	p15, 0, r6, c13, c0, 1 +	stmia	r8!, {r4-r6} +	/* Primary remap, normal remap registers */ +	mrc	p15, 0, r4, c10, c2, 0 +	mrc	p15, 0, r5, c10, c2, 1 +	stmia	r8!,{r4-r5} + +	/* Store current cpsr*/ +	mrs	r2, cpsr +	stmia	r8!, {r2} + +	mrc	p15, 0, r4, c1, c0, 0 +	/* save control register */ +	stmia	r8!, {r4} + +clean_caches: +	/* +	 * Clean Data or unified cache to POU +	 * How to invalidate only L1 cache???? - #FIX_ME# +	 * mcr	p15, 0, r11, c7, c11, 1 +	 */ +	cmp	r1, #0x1 		@ Check whether L2 inval is required +	beq	omap3_do_wfi + +clean_l2: +	/* +	 * jump out to kernel flush routine +	 *  - reuse that code is better +	 *  - it executes in a cached space so is faster than refetch per-block +	 *  - should be faster and will change with kernel +	 *  - 'might' have to copy address, load and jump to it +	 */ +	ldr	r1, kernel_flush +	mov	lr, pc +	bx	r1 + +omap3_do_wfi: +	ldr	r4, sdrc_power		@ read the SDRC_POWER register +	ldr	r5, [r4]		@ read the contents of SDRC_POWER +	orr	r5, r5, #0x40		@ enable self refresh on idle req +	str	r5, [r4]		@ write back to SDRC_POWER register +  	/* Data memory barrier and Data sync barrier */  	mov	r1, #0  	mcr	p15, 0, r1, c7, c10, 4  	mcr	p15, 0, r1, c7, c10, 5 +/* + * =================================== + * == WFI instruction => Enter idle == + * =================================== + */  	wfi				@ wait for interrupt +/* + * =================================== + * == Resume path for non-OFF modes == + * =================================== + */  	nop  	nop  	nop @@ -226,9 +317,30 @@ loop:  	nop  	bl wait_sdrc_ok -	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return +/* + * =================================== + * == Exit point from non-OFF modes == + * =================================== + */ +	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return + + +/* + * ============================== + * == Resume path for OFF mode == + * ============================== + */ + +/* + * The restore_* functions are called by the ROM code + *  when back from WFI in OFF mode. + * Cf. the get_*restore_pointer functions. + * + *  restore_es3: applies to 34xx >= ES3.0 + *  restore_3630: applies to 36xx + *  restore: common code for 3xxx + */  restore_es3: -	/*b restore_es3*/		@ Enable to debug restore code  	ldr	r5, pm_prepwstst_core_p  	ldr	r4, [r5]  	and	r4, r4, #0x3 @@ -245,82 +357,117 @@ copy_to_sram:  	bne	copy_to_sram  	ldr	r1, sram_base  	blx	r1 +	b	restore + +restore_3630: +	ldr	r1, pm_prepwstst_core_p +	ldr	r2, [r1] +	and	r2, r2, #0x3 +	cmp	r2, #0x0	@ Check if previous power state of CORE is OFF +	bne	restore +	/* Disable RTA before giving control */ +	ldr	r1, control_mem_rta +	mov	r2, #OMAP36XX_RTA_DISABLE +	str	r2, [r1] + +	/* Fall through to common code for the remaining logic */ +  restore: -	/* b restore*/  @ Enable to debug restore code -        /* Check what was the reason for mpu reset and store the reason in r9*/ -        /* 1 - Only L1 and logic lost */ -        /* 2 - Only L2 lost - In this case, we wont be here */ -        /* 3 - Both L1 and L2 lost */ -	ldr     r1, pm_pwstctrl_mpu +	/* +	 * Check what was the reason for mpu reset and store the reason in r9: +	 *  0 - No context lost +	 *  1 - Only L1 and logic lost +	 *  2 - Only L2 lost - In this case, we wont be here +	 *  3 - Both L1 and L2 lost +	 */ +	ldr	r1, pm_pwstctrl_mpu  	ldr	r2, [r1] -	and     r2, r2, #0x3 -	cmp     r2, #0x0	@ Check if target power state was OFF or RET -        moveq   r9, #0x3        @ MPU OFF => L1 and L2 lost +	and	r2, r2, #0x3 +	cmp	r2, #0x0	@ Check if target power state was OFF or RET +	moveq	r9, #0x3	@ MPU OFF => L1 and L2 lost  	movne	r9, #0x1	@ Only L1 and L2 lost => avoid L2 invalidation  	bne	logic_l1_restore + +	ldr	r0, l2dis_3630 +	cmp	r0, #0x1	@ should we disable L2 on 3630? +	bne	skipl2dis +	mrc	p15, 0, r0, c1, c0, 1 +	bic	r0, r0, #2	@ disable L2 cache +	mcr	p15, 0, r0, c1, c0, 1 +skipl2dis:  	ldr	r0, control_stat  	ldr	r1, [r0]  	and	r1, #0x700  	cmp	r1, #0x300  	beq	l2_inv_gp -	mov	r0, #40		@ set service ID for PPA -	mov	r12, r0		@ copy secure Service ID in r12 -	mov	r1, #0		@ set task id for ROM code in r1 -	mov	r2, #4		@ set some flags in r2, r6 +	mov	r0, #40			@ set service ID for PPA +	mov	r12, r0			@ copy secure Service ID in r12 +	mov	r1, #0			@ set task id for ROM code in r1 +	mov	r2, #4			@ set some flags in r2, r6  	mov	r6, #0xff  	adr	r3, l2_inv_api_params	@ r3 points to dummy parameters  	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier  	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier  	.word	0xE1600071		@ call SMI monitor (smi #1)  	/* Write to Aux control register to set some bits */ -	mov	r0, #42		@ set service ID for PPA -	mov	r12, r0		@ copy secure Service ID in r12 -	mov	r1, #0		@ set task id for ROM code in r1 -	mov	r2, #4		@ set some flags in r2, r6 +	mov	r0, #42			@ set service ID for PPA +	mov	r12, r0			@ copy secure Service ID in r12 +	mov	r1, #0			@ set task id for ROM code in r1 +	mov	r2, #4			@ set some flags in r2, r6  	mov	r6, #0xff  	ldr	r4, scratchpad_base -	ldr	r3, [r4, #0xBC]	@ r3 points to parameters +	ldr	r3, [r4, #0xBC]		@ r3 points to parameters  	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier  	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier  	.word	0xE1600071		@ call SMI monitor (smi #1)  #ifdef CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE  	/* Restore L2 aux control register */ -	@ set service ID for PPA +					@ set service ID for PPA  	mov	r0, #CONFIG_OMAP3_L2_AUX_SECURE_SERVICE_SET_ID -	mov	r12, r0		@ copy service ID in r12 -	mov	r1, #0		@ set task ID for ROM code in r1 -	mov	r2, #4		@ set some flags in r2, r6 +	mov	r12, r0			@ copy service ID in r12 +	mov	r1, #0			@ set task ID for ROM code in r1 +	mov	r2, #4			@ set some flags in r2, r6  	mov	r6, #0xff  	ldr	r4, scratchpad_base  	ldr	r3, [r4, #0xBC] -	adds	r3, r3, #8	@ r3 points to parameters +	adds	r3, r3, #8		@ r3 points to parameters  	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier  	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier  	.word	0xE1600071		@ call SMI monitor (smi #1)  #endif  	b	logic_l1_restore +  l2_inv_api_params: -	.word   0x1, 0x00 +	.word	0x1, 0x00  l2_inv_gp:  	/* Execute smi to invalidate L2 cache */ -	mov r12, #0x1                         @ set up to invalide L2 -smi:    .word 0xE1600070		@ Call SMI monitor (smieq) +	mov r12, #0x1			@ set up to invalidate L2 +	.word 0xE1600070		@ Call SMI monitor (smieq)  	/* Write to Aux control register to set some bits */  	ldr	r4, scratchpad_base  	ldr	r3, [r4,#0xBC]  	ldr	r0, [r3,#4]  	mov	r12, #0x3 -	.word 0xE1600070	@ Call SMI monitor (smieq) +	.word	0xE1600070		@ Call SMI monitor (smieq)  	ldr	r4, scratchpad_base  	ldr	r3, [r4,#0xBC]  	ldr	r0, [r3,#12]  	mov	r12, #0x2 -	.word 0xE1600070	@ Call SMI monitor (smieq) +	.word	0xE1600070		@ Call SMI monitor (smieq)  logic_l1_restore: +	ldr	r1, l2dis_3630 +	cmp	r1, #0x1		@ Test if L2 re-enable needed on 3630 +	bne	skipl2reen +	mrc	p15, 0, r1, c1, c0, 1 +	orr	r1, r1, #2		@ re-enable L2 cache +	mcr	p15, 0, r1, c1, c0, 1 +skipl2reen:  	mov	r1, #0 -	/* Invalidate all instruction caches to PoU -	 * and flush branch target cache */ +	/* +	 * Invalidate all instruction caches to PoU +	 * and flush branch target cache +	 */  	mcr	p15, 0, r1, c7, c5, 0  	ldr	r4, scratchpad_base @@ -341,33 +488,33 @@ logic_l1_restore:  	MCR p15, 0, r6, c2, c0, 1  	/* Translation table base control register */  	MCR p15, 0, r7, c2, c0, 2 -	/*domain access Control Register */ +	/* Domain access Control Register */  	MCR p15, 0, r8, c3, c0, 0 -	/* data fault status Register */ +	/* Data fault status Register */  	MCR p15, 0, r9, c5, c0, 0 -	ldmia  r3!,{r4-r8} -	/* instruction fault status Register */ +	ldmia	r3!,{r4-r8} +	/* Instruction fault status Register */  	MCR p15, 0, r4, c5, c0, 1 -	/*Data Auxiliary Fault Status Register */ +	/* Data Auxiliary Fault Status Register */  	MCR p15, 0, r5, c5, c1, 0 -	/*Instruction Auxiliary Fault Status Register*/ +	/* Instruction Auxiliary Fault Status Register*/  	MCR p15, 0, r6, c5, c1, 1 -	/*Data Fault Address Register */ +	/* Data Fault Address Register */  	MCR p15, 0, r7, c6, c0, 0 -	/*Instruction Fault Address Register*/ +	/* Instruction Fault Address Register*/  	MCR p15, 0, r8, c6, c0, 2 -	ldmia  r3!,{r4-r7} +	ldmia	r3!,{r4-r7} -	/* user r/w thread and process ID */ +	/* User r/w thread and process ID */  	MCR p15, 0, r4, c13, c0, 2 -	/* user ro thread and process ID */ +	/* User ro thread and process ID */  	MCR p15, 0, r5, c13, c0, 3 -	/*Privileged only thread and process ID */ +	/* Privileged only thread and process ID */  	MCR p15, 0, r6, c13, c0, 4 -	/* cache size selection */ +	/* Cache size selection */  	MCR p15, 2, r7, c0, c0, 0 -	ldmia  r3!,{r4-r8} +	ldmia	r3!,{r4-r8}  	/* Data TLB lockdown registers */  	MCR p15, 0, r4, c10, c0, 0  	/* Instruction TLB lockdown registers */ @@ -379,26 +526,27 @@ logic_l1_restore:  	/* Context PID */  	MCR p15, 0, r8, c13, c0, 1 -	ldmia  r3!,{r4-r5} -	/* primary memory remap register */ +	ldmia	r3!,{r4-r5} +	/* Primary memory remap register */  	MCR p15, 0, r4, c10, c2, 0 -	/*normal memory remap register */ +	/* Normal memory remap register */  	MCR p15, 0, r5, c10, c2, 1  	/* Restore cpsr */ -	ldmia	r3!,{r4}	/*load CPSR from SDRAM*/ -	msr	cpsr, r4	/*store cpsr */ +	ldmia	r3!,{r4}		@ load CPSR from SDRAM +	msr	cpsr, r4		@ store cpsr  	/* Enabling MMU here */ -	mrc	p15, 0, r7, c2, c0, 2 /* Read TTBRControl */ -	/* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1*/ +	mrc	p15, 0, r7, c2, c0, 2 	@ Read TTBRControl +	/* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1 */  	and	r7, #0x7  	cmp	r7, #0x0  	beq	usettbr0  ttbr_error: -	/* More work needs to be done to support N[0:2] value other than 0 -	* So looping here so that the error can be detected -	*/ +	/* +	 * More work needs to be done to support N[0:2] value other than 0 +	 * So looping here so that the error can be detected +	 */  	b	ttbr_error  usettbr0:  	mrc	p15, 0, r2, c2, c0, 0 @@ -406,21 +554,25 @@ usettbr0:  	and	r2, r5  	mov	r4, pc  	ldr	r5, table_index_mask -	and	r4, r5 /* r4 = 31 to 20 bits of pc */ +	and	r4, r5			@ r4 = 31 to 20 bits of pc  	/* Extract the value to be written to table entry */  	ldr	r1, table_entry -	add	r1, r1, r4 /* r1 has value to be written to table entry*/ +	/* r1 has the value to be written to table entry*/ +	add	r1, r1, r4  	/* Getting the address of table entry to modify */  	lsr	r4, #18 -	add	r2, r4 /* r2 has the location which needs to be modified */ +	/* r2 has the location which needs to be modified */ +	add	r2, r4  	/* Storing previous entry of location being modified */  	ldr	r5, scratchpad_base  	ldr	r4, [r2]  	str	r4, [r5, #0xC0]  	/* Modify the table entry */  	str	r1, [r2] -	/* Storing address of entry being modified -	 * - will be restored after enabling MMU */ +	/* +	 * Storing address of entry being modified +	 * - will be restored after enabling MMU +	 */  	ldr	r5, scratchpad_base  	str	r2, [r5, #0xC4] @@ -429,8 +581,11 @@ usettbr0:  	mcr	p15, 0, r0, c7, c5, 6	@ Invalidate branch predictor array  	mcr	p15, 0, r0, c8, c5, 0	@ Invalidate instruction TLB  	mcr	p15, 0, r0, c8, c6, 0	@ Invalidate data TLB -	/* Restore control register  but dont enable caches here*/ -	/* Caches will be enabled after restoring MMU table entry */ +	/* +	 * Restore control register. This enables the MMU. +	 * The caches and prediction are not enabled here, they +	 * will be enabled after restoring the MMU table entry. +	 */  	ldmia	r3!, {r4}  	/* Store previous value of control register in scratchpad */  	str	r4, [r5, #0xC8] @@ -438,212 +593,144 @@ usettbr0:  	and	r4, r2  	mcr	p15, 0, r4, c1, c0, 0 -	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return -save_context_wfi: -	/*b	save_context_wfi*/	@ enable to debug save code -	mov	r8, r0 /* Store SDRAM address in r8 */ -	mrc	p15, 0, r5, c1, c0, 1	@ Read Auxiliary Control Register -	mov	r4, #0x1		@ Number of parameters for restore call -	stmia	r8!, {r4-r5}		@ Push parameters for restore call -	mrc	p15, 1, r5, c9, c0, 2	@ Read L2 AUX ctrl register -	stmia	r8!, {r4-r5}		@ Push parameters for restore call -        /* Check what that target sleep state is:stored in r1*/ -        /* 1 - Only L1 and logic lost */ -        /* 2 - Only L2 lost */ -        /* 3 - Both L1 and L2 lost */ -	cmp	r1, #0x2 /* Only L2 lost */ -	beq	clean_l2 -	cmp	r1, #0x1 /* L2 retained */ -	/* r9 stores whether to clean L2 or not*/ -	moveq	r9, #0x0 /* Dont Clean L2 */ -	movne	r9, #0x1 /* Clean L2 */ -l1_logic_lost: -	/* Store sp and spsr to SDRAM */ -	mov	r4, sp -	mrs	r5, spsr -	mov	r6, lr -	stmia	r8!, {r4-r6} -	/* Save all ARM registers */ -	/* Coprocessor access control register */ -	mrc	p15, 0, r6, c1, c0, 2 -	stmia	r8!, {r6} -	/* TTBR0, TTBR1 and Translation table base control */ -	mrc	p15, 0, r4, c2, c0, 0 -	mrc	p15, 0, r5, c2, c0, 1 -	mrc	p15, 0, r6, c2, c0, 2 -	stmia	r8!, {r4-r6} -	/* Domain access control register, data fault status register, -	and instruction fault status register */ -	mrc	p15, 0, r4, c3, c0, 0 -	mrc	p15, 0, r5, c5, c0, 0 -	mrc	p15, 0, r6, c5, c0, 1 -	stmia	r8!, {r4-r6} -	/* Data aux fault status register, instruction aux fault status, -	datat fault address register and instruction fault address register*/ -	mrc	p15, 0, r4, c5, c1, 0 -	mrc	p15, 0, r5, c5, c1, 1 -	mrc	p15, 0, r6, c6, c0, 0 -	mrc	p15, 0, r7, c6, c0, 2 -	stmia	r8!, {r4-r7} -	/* user r/w thread and process ID, user r/o thread and process ID, -	priv only thread and process ID, cache size selection */ -	mrc	p15, 0, r4, c13, c0, 2 -	mrc	p15, 0, r5, c13, c0, 3 -	mrc	p15, 0, r6, c13, c0, 4 -	mrc	p15, 2, r7, c0, c0, 0 -	stmia	r8!, {r4-r7} -	/* Data TLB lockdown, instruction TLB lockdown registers */ -	mrc	p15, 0, r5, c10, c0, 0 -	mrc	p15, 0, r6, c10, c0, 1 -	stmia	r8!, {r5-r6} -	/* Secure or non secure vector base address, FCSE PID, Context PID*/ -	mrc	p15, 0, r4, c12, c0, 0 -	mrc	p15, 0, r5, c13, c0, 0 -	mrc	p15, 0, r6, c13, c0, 1 -	stmia	r8!, {r4-r6} -	/* Primary remap, normal remap registers */ -	mrc	p15, 0, r4, c10, c2, 0 -	mrc	p15, 0, r5, c10, c2, 1 -	stmia	r8!,{r4-r5} +/* + * ============================== + * == Exit point from OFF mode == + * ============================== + */ +	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return -	/* Store current cpsr*/ -	mrs	r2, cpsr -	stmia	r8!, {r2} -	mrc	p15, 0, r4, c1, c0, 0 -	/* save control register */ -	stmia	r8!, {r4} -clean_caches: -	/* Clean Data or unified cache to POU*/ -	/* How to invalidate only L1 cache???? - #FIX_ME# */ -	/* mcr	p15, 0, r11, c7, c11, 1 */ -	cmp	r9, #1 /* Check whether L2 inval is required or not*/ -	bne	skip_l2_inval -clean_l2: -	/* read clidr */ -	mrc     p15, 1, r0, c0, c0, 1 -	/* extract loc from clidr */ -	ands    r3, r0, #0x7000000 -	/* left align loc bit field */ -	mov     r3, r3, lsr #23 -	/* if loc is 0, then no need to clean */ -	beq     finished -	/* start clean at cache level 0 */ -	mov     r10, #0 -loop1: -	/* work out 3x current cache level */ -	add     r2, r10, r10, lsr #1 -	/* extract cache type bits from clidr*/ -	mov     r1, r0, lsr r2 -	/* mask of the bits for current cache only */ -	and     r1, r1, #7 -	/* see what cache we have at this level */ -	cmp     r1, #2 -	/* skip if no cache, or just i-cache */ -	blt     skip -	/* select current cache level in cssr */ -	mcr     p15, 2, r10, c0, c0, 0 -	/* isb to sych the new cssr&csidr */ -	isb -	/* read the new csidr */ -	mrc     p15, 1, r1, c0, c0, 0 -	/* extract the length of the cache lines */ -	and     r2, r1, #7 -	/* add 4 (line length offset) */ -	add     r2, r2, #4 -	ldr     r4, assoc_mask -	/* find maximum number on the way size */ -	ands    r4, r4, r1, lsr #3 -	/* find bit position of way size increment */ -	clz     r5, r4 -	ldr     r7, numset_mask -	/* extract max number of the index size*/ -	ands    r7, r7, r1, lsr #13 -loop2: -	mov     r9, r4 -	/* create working copy of max way size*/ -loop3: -	/* factor way and cache number into r11 */ -	orr     r11, r10, r9, lsl r5 -	/* factor index number into r11 */ -	orr     r11, r11, r7, lsl r2 -	/*clean & invalidate by set/way */ -	mcr     p15, 0, r11, c7, c10, 2 -	/* decrement the way*/ -	subs    r9, r9, #1 -	bge     loop3 -	/*decrement the index */ -	subs    r7, r7, #1 -	bge     loop2 -skip: -	add     r10, r10, #2 -	/* increment cache number */ -	cmp     r3, r10 -	bgt     loop1 -finished: -	/*swith back to cache level 0 */ -	mov     r10, #0 -	/* select current cache level in cssr */ -	mcr     p15, 2, r10, c0, c0, 0 -	isb -skip_l2_inval: -	/* Data memory barrier and Data sync barrier */ -	mov     r1, #0 -	mcr     p15, 0, r1, c7, c10, 4 -	mcr     p15, 0, r1, c7, c10, 5 +/* + * Internal functions + */ -	wfi                             @ wait for interrupt -	nop -	nop -	nop -	nop -	nop -	nop -	nop -	nop -	nop -	nop -	bl wait_sdrc_ok -	/* restore regs and return */ -	ldmfd   sp!, {r0-r12, pc} +/* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */ +	.text +ENTRY(es3_sdrc_fix) +	ldr	r4, sdrc_syscfg		@ get config addr +	ldr	r5, [r4]		@ get value +	tst	r5, #0x100		@ is part access blocked +	it	eq +	biceq	r5, r5, #0x100		@ clear bit if set +	str	r5, [r4]		@ write back change +	ldr	r4, sdrc_mr_0		@ get config addr +	ldr	r5, [r4]		@ get value +	str	r5, [r4]		@ write back change +	ldr	r4, sdrc_emr2_0		@ get config addr +	ldr	r5, [r4]		@ get value +	str	r5, [r4]		@ write back change +	ldr	r4, sdrc_manual_0	@ get config addr +	mov	r5, #0x2		@ autorefresh command +	str	r5, [r4]		@ kick off refreshes +	ldr	r4, sdrc_mr_1		@ get config addr +	ldr	r5, [r4]		@ get value +	str	r5, [r4]		@ write back change +	ldr	r4, sdrc_emr2_1		@ get config addr +	ldr	r5, [r4]		@ get value +	str	r5, [r4]		@ write back change +	ldr	r4, sdrc_manual_1	@ get config addr +	mov	r5, #0x2		@ autorefresh command +	str	r5, [r4]		@ kick off refreshes +	bx	lr + +sdrc_syscfg: +	.word	SDRC_SYSCONFIG_P +sdrc_mr_0: +	.word	SDRC_MR_0_P +sdrc_emr2_0: +	.word	SDRC_EMR2_0_P +sdrc_manual_0: +	.word	SDRC_MANUAL_0_P +sdrc_mr_1: +	.word	SDRC_MR_1_P +sdrc_emr2_1: +	.word	SDRC_EMR2_1_P +sdrc_manual_1: +	.word	SDRC_MANUAL_1_P +ENTRY(es3_sdrc_fix_sz) +	.word	. - es3_sdrc_fix + +/* + * This function implements the erratum ID i581 WA: + *  SDRC state restore before accessing the SDRAM + * + * Only used at return from non-OFF mode. For OFF + * mode the ROM code configures the SDRC and + * the DPLL before calling the restore code directly + * from DDR. + */  /* Make sure SDRC accesses are ok */  wait_sdrc_ok: -        ldr     r4, cm_idlest1_core -        ldr     r5, [r4] -        and     r5, r5, #0x2 -        cmp     r5, #0 -        bne     wait_sdrc_ok -        ldr     r4, sdrc_power -        ldr     r5, [r4] -        bic     r5, r5, #0x40 -        str     r5, [r4] + +/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */ +	ldr	r4, cm_idlest_ckgen +wait_dpll3_lock: +	ldr	r5, [r4] +	tst	r5, #1 +	beq	wait_dpll3_lock + +	ldr	r4, cm_idlest1_core +wait_sdrc_ready: +	ldr	r5, [r4] +	tst	r5, #0x2 +	bne	wait_sdrc_ready +	/* allow DLL powerdown upon hw idle req */ +	ldr	r4, sdrc_power +	ldr	r5, [r4] +	bic	r5, r5, #0x40 +	str	r5, [r4] + +is_dll_in_lock_mode: +	/* Is dll in lock mode? */ +	ldr	r4, sdrc_dlla_ctrl +	ldr	r5, [r4] +	tst	r5, #0x4 +	bxne	lr			@ Return if locked +	/* wait till dll locks */ +wait_dll_lock_timed: +	ldr	r4, wait_dll_lock_counter +	add	r4, r4, #1 +	str	r4, wait_dll_lock_counter +	ldr	r4, sdrc_dlla_status +	/* Wait 20uS for lock */ +	mov	r6, #8  wait_dll_lock: -        /* Is dll in lock mode? */ -        ldr     r4, sdrc_dlla_ctrl -        ldr     r5, [r4] -        tst     r5, #0x4 -        bxne    lr -        /* wait till dll locks */ -        ldr     r4, sdrc_dlla_status -        ldr     r5, [r4] -        and     r5, r5, #0x4 -        cmp     r5, #0x4 -        bne     wait_dll_lock -        bx      lr +	subs	r6, r6, #0x1 +	beq	kick_dll +	ldr	r5, [r4] +	and	r5, r5, #0x4 +	cmp	r5, #0x4 +	bne	wait_dll_lock +	bx	lr			@ Return when locked + +	/* disable/reenable DLL if not locked */ +kick_dll: +	ldr	r4, sdrc_dlla_ctrl +	ldr	r5, [r4] +	mov	r6, r5 +	bic	r6, #(1<<3)		@ disable dll +	str	r6, [r4] +	dsb +	orr	r6, r6, #(1<<3)		@ enable dll +	str	r6, [r4] +	dsb +	ldr	r4, kick_counter +	add	r4, r4, #1 +	str	r4, kick_counter +	b	wait_dll_lock_timed  cm_idlest1_core:  	.word	CM_IDLEST1_CORE_V +cm_idlest_ckgen: +	.word	CM_IDLEST_CKGEN_V  sdrc_dlla_status:  	.word	SDRC_DLLA_STATUS_V  sdrc_dlla_ctrl:  	.word	SDRC_DLLA_CTRL_V -pm_prepwstst_core: -	.word	PM_PREPWSTST_CORE_V  pm_prepwstst_core_p:  	.word	PM_PREPWSTST_CORE_P -pm_prepwstst_mpu: -	.word	PM_PREPWSTST_MPU_V  pm_pwstctrl_mpu:  	.word	PM_PWSTCTRL_MPU_P  scratchpad_base: @@ -651,13 +738,7 @@ scratchpad_base:  sram_base:  	.word	SRAM_BASE_P + 0x8000  sdrc_power: -	.word SDRC_POWER_V -clk_stabilize_delay: -	.word 0x000001FF -assoc_mask: -	.word	0x3ff -numset_mask: -	.word	0x7fff +	.word	SDRC_POWER_V  ttbrbit_mask:  	.word	0xFFFFC000  table_index_mask: @@ -668,5 +749,20 @@ cache_pred_disable_mask:  	.word	0xFFFFE7FB  control_stat:  	.word	CONTROL_STAT +control_mem_rta: +	.word	CONTROL_MEM_RTA_CTRL +kernel_flush: +	.word	v7_flush_dcache_all +l2dis_3630: +	.word	0 +	/* +	 * When exporting to userspace while the counters are in SRAM, +	 * these 2 words need to be at the end to facilitate retrival! +	 */ +kick_counter: +	.word	0 +wait_dll_lock_counter: +	.word	0 +  ENTRY(omap34xx_cpu_suspend_sz)  	.word	. - omap34xx_cpu_suspend diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig index fa2e5bffbb8..6983cb4d4ca 100644 --- a/arch/arm/mach-s3c2412/Kconfig +++ b/arch/arm/mach-s3c2412/Kconfig @@ -28,9 +28,16 @@ config S3C2412_DMA  config S3C2412_PM  	bool +	select S3C2412_PM_SLEEP  	help  	  Internal config node to apply S3C2412 power management +config S3C2412_PM_SLEEP +	bool +	help +	  Internal config node to apply sleep for S3C2412 power management. +	  Can be selected by another SoCs with similar sleep procedure. +  # Note, the S3C2412 IOtiming support is in plat-s3c24xx  config S3C2412_CPUFREQ diff --git a/arch/arm/mach-s3c2412/Makefile b/arch/arm/mach-s3c2412/Makefile index 530ec46cbae..6c48a91ea39 100644 --- a/arch/arm/mach-s3c2412/Makefile +++ b/arch/arm/mach-s3c2412/Makefile @@ -14,7 +14,8 @@ obj-$(CONFIG_CPU_S3C2412)	+= irq.o  obj-$(CONFIG_CPU_S3C2412)	+= clock.o  obj-$(CONFIG_CPU_S3C2412)	+= gpio.o  obj-$(CONFIG_S3C2412_DMA)	+= dma.o -obj-$(CONFIG_S3C2412_PM)	+= pm.o sleep.o +obj-$(CONFIG_S3C2412_PM)	+= pm.o +obj-$(CONFIG_S3C2412_PM_SLEEP)	+= sleep.o  obj-$(CONFIG_S3C2412_CPUFREQ)	+= cpu-freq.o  # Machine support diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig index 27b3e7c9d61..df8d14974c9 100644 --- a/arch/arm/mach-s3c2416/Kconfig +++ b/arch/arm/mach-s3c2416/Kconfig @@ -27,6 +27,7 @@ config S3C2416_DMA  config S3C2416_PM  	bool +	select S3C2412_PM_SLEEP  	help  	  Internal config node to apply S3C2416 power management diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index 28677caf361..461aa035afc 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -378,6 +378,12 @@ static struct max8998_regulator_data aquila_regulators[] = {  static struct max8998_platform_data aquila_max8998_pdata = {  	.num_regulators	= ARRAY_SIZE(aquila_regulators),  	.regulators	= aquila_regulators, +	.buck1_set1	= S5PV210_GPH0(3), +	.buck1_set2	= S5PV210_GPH0(4), +	.buck2_set3	= S5PV210_GPH0(5), +	.buck1_max_voltage1 = 1200000, +	.buck1_max_voltage2 = 1200000, +	.buck2_max_voltage = 1200000,  };  #endif diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index b1dcf964a76..e22d5112fd4 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -518,6 +518,12 @@ static struct max8998_regulator_data goni_regulators[] = {  static struct max8998_platform_data goni_max8998_pdata = {  	.num_regulators	= ARRAY_SIZE(goni_regulators),  	.regulators	= goni_regulators, +	.buck1_set1	= S5PV210_GPH0(3), +	.buck1_set2	= S5PV210_GPH0(4), +	.buck2_set3	= S5PV210_GPH0(5), +	.buck1_max_voltage1 = 1200000, +	.buck1_max_voltage2 = 1200000, +	.buck2_max_voltage = 1200000,  };  #endif diff --git a/arch/arm/mach-shmobile/include/mach/entry-macro.S b/arch/arm/mach-shmobile/include/mach/entry-macro.S index a285d13c741..f428c4db2b6 100644 --- a/arch/arm/mach-shmobile/include/mach/entry-macro.S +++ b/arch/arm/mach-shmobile/include/mach/entry-macro.S @@ -1,4 +1,5 @@  /* + * Copyright (C) 2010 Magnus Damm   * Copyright (C) 2008 Renesas Solutions Corp.   *   * This program is free software; you can redistribute it and/or modify @@ -14,24 +15,45 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA   */ -#include <mach/hardware.h>  #include <mach/irqs.h> +#define INTCA_BASE	0xe6980000 +#define INTFLGA_OFFS	0x00000018 /* accept pending interrupt */ +#define INTEVTA_OFFS	0x00000020 /* vector number of accepted interrupt */ +#define INTLVLA_OFFS	0x00000030 /* priority level of accepted interrupt */ +#define INTLVLB_OFFS	0x00000034 /* previous priority level */ +  	.macro  disable_fiq  	.endm  	.macro  get_irqnr_preamble, base, tmp -	ldr     \base, =INTFLGA +	ldr     \base, =INTCA_BASE  	.endm  	.macro  arch_ret_to_user, tmp1, tmp2  	.endm  	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp -	ldr     \irqnr, [\base] +	/* The single INTFLGA read access below results in the following: +	 * +	 * 1. INTLVLB is updated with old priority value from INTLVLA +	 * 2. Highest priority interrupt is accepted +	 * 3. INTLVLA is updated to contain priority of accepted interrupt +	 * 4. Accepted interrupt vector is stored in INTFLGA and INTEVTA +	 */ +	ldr     \irqnr, [\base, #INTFLGA_OFFS] + +	/* Restore INTLVLA with the value saved in INTLVLB. +	 * This is required to support interrupt priorities properly. +	 */ +	ldrb	\tmp, [\base, #INTLVLB_OFFS] +	strb    \tmp, [\base, #INTLVLA_OFFS] + +	/* Handle invalid vector number case */  	cmp	\irqnr, #0  	beq	1000f -	/* intevt to irq number */ + +	/* Convert vector to irq number, same as the evt2irq() macro */  	lsr	\irqnr, \irqnr, #0x5  	subs	\irqnr, \irqnr, #16 diff --git a/arch/arm/mach-shmobile/include/mach/vmalloc.h b/arch/arm/mach-shmobile/include/mach/vmalloc.h index 4aecf6e3a85..2b8fd8b942f 100644 --- a/arch/arm/mach-shmobile/include/mach/vmalloc.h +++ b/arch/arm/mach-shmobile/include/mach/vmalloc.h @@ -2,6 +2,6 @@  #define __ASM_MACH_VMALLOC_H  /* Vmalloc at ... - 0xe5ffffff */ -#define VMALLOC_END 0xe6000000 +#define VMALLOC_END 0xe6000000UL  #endif /* __ASM_MACH_VMALLOC_H */ diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h index 5905100b29a..9967d5e855c 100644 --- a/arch/arm/plat-omap/include/plat/sram.h +++ b/arch/arm/plat-omap/include/plat/sram.h @@ -11,6 +11,7 @@  #ifndef __ARCH_ARM_OMAP_SRAM_H  #define __ARCH_ARM_OMAP_SRAM_H +#ifndef __ASSEMBLY__  extern void * omap_sram_push(void * start, unsigned long size);  extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl); @@ -74,4 +75,14 @@ extern void omap_push_sram_idle(void);  static inline void omap_push_sram_idle(void) {}  #endif /* CONFIG_PM */ +#endif /* __ASSEMBLY__ */ + +/* + * OMAP2+: define the SRAM PA addresses. + * Used by the SRAM management code and the idle sleep code. + */ +#define OMAP2_SRAM_PA		0x40200000 +#define OMAP3_SRAM_PA           0x40200000 +#define OMAP4_SRAM_PA		0x40300000 +  #endif diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 819ea0cfb81..1a686c89d8d 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -41,15 +41,12 @@  #define OMAP1_SRAM_PA		0x20000000  #define OMAP1_SRAM_VA		VMALLOC_END -#define OMAP2_SRAM_PA		0x40200000 -#define OMAP2_SRAM_PUB_PA	0x4020f800 +#define OMAP2_SRAM_PUB_PA	(OMAP2_SRAM_PA + 0xf800)  #define OMAP2_SRAM_VA		0xfe400000  #define OMAP2_SRAM_PUB_VA	(OMAP2_SRAM_VA + 0x800) -#define OMAP3_SRAM_PA           0x40200000  #define OMAP3_SRAM_VA           0xfe400000 -#define OMAP3_SRAM_PUB_PA       0x40208000 +#define OMAP3_SRAM_PUB_PA       (OMAP3_SRAM_PA + 0x8000)  #define OMAP3_SRAM_PUB_VA       (OMAP3_SRAM_VA + 0x8000) -#define OMAP4_SRAM_PA		0x40300000  #define OMAP4_SRAM_VA		0xfe400000  #define OMAP4_SRAM_PUB_PA	(OMAP4_SRAM_PA + 0x4000)  #define OMAP4_SRAM_PUB_VA	(OMAP4_SRAM_VA + 0x4000) diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index 5a27b1b538f..eb105e61c74 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig @@ -8,7 +8,7 @@ config PLAT_S3C24XX  	default y  	select NO_IOPORT  	select ARCH_REQUIRE_GPIOLIB -	select S3C_DEVICE_NAND +	select S3C_DEV_NAND  	select S3C_GPIO_CFG_S3C24XX  	help  	  Base platform code for any Samsung S3C24XX device diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 67a2fa2caa4..0a9b5b8b2a1 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -19,6 +19,8 @@ config MIPS  	select GENERIC_ATOMIC64 if !64BIT  	select HAVE_DMA_ATTRS  	select HAVE_DMA_API_DEBUG +	select HAVE_GENERIC_HARDIRQS +	select GENERIC_IRQ_PROBE  menu "Machine selection" @@ -1664,6 +1666,28 @@ config PAGE_SIZE_64KB  endchoice +config FORCE_MAX_ZONEORDER +	int "Maximum zone order" +	range 13 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB +	default "13" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB +	range 12 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB +	default "12" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB +	range 11 64 +	default "11" +	help +	  The kernel memory allocator divides physically contiguous memory +	  blocks into "zones", where each zone is a power of two number of +	  pages.  This option selects the largest power of two that the kernel +	  keeps in the memory allocator.  If you need to allocate very large +	  blocks of physically contiguous memory, then you may need to +	  increase this value. + +	  This config option is actually maximum order plus one. For example, +	  a value of 11 means that the largest free memory block is 2^10 pages. + +	  The page size is not necessarily 4KB.  Keep this in mind +	  when choosing a value for this option. +  config BOARD_SCACHE  	bool @@ -1922,20 +1946,6 @@ config CPU_R4400_WORKAROUNDS  	bool  # -# Use the generic interrupt handling code in kernel/irq/: -# -config GENERIC_HARDIRQS -	bool -	default y - -config GENERIC_IRQ_PROBE -	bool -	default y - -config IRQ_PER_CPU -	bool - -#  # - Highmem only makes sense for the 32-bit kernel.  # - The current highmem code will only work properly on physically indexed  #   caches such as R3000, SB1, R7000 or those that look like they're virtually diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index 3691630931d..9e7814db3d0 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c @@ -27,6 +27,7 @@  static void alchemy_8250_pm(struct uart_port *port, unsigned int state,  			    unsigned int old_state)  { +#ifdef CONFIG_SERIAL_8250  	switch (state) {  	case 0:  		if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) { @@ -49,6 +50,7 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state,  		serial8250_do_pm(port, state, old_state);  		break;  	} +#endif  }  #define PORT(_base, _irq)					\ diff --git a/arch/mips/alchemy/devboards/prom.c b/arch/mips/alchemy/devboards/prom.c index b30df5c97ad..baeb2138505 100644 --- a/arch/mips/alchemy/devboards/prom.c +++ b/arch/mips/alchemy/devboards/prom.c @@ -54,10 +54,9 @@ void __init prom_init(void)  	prom_init_cmdline();  	memsize_str = prom_getenv("memsize"); -	if (!memsize_str) +	if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize))  		memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE; -	else -		strict_strtoul(memsize_str, 0, &memsize); +  	add_memory_region(0, memsize, BOOT_MEM_RAM);  } diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c index fc0e7154e8d..2ca4ada1c29 100644 --- a/arch/mips/ar7/clock.c +++ b/arch/mips/ar7/clock.c @@ -239,12 +239,12 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,  	calculate(base_clock, frequency, &prediv, &postdiv, &mul);  	writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl); -	msleep(1); +	mdelay(1);  	writel(4, &clock->pll);  	while (readl(&clock->pll) & PLL_STATUS)  		;  	writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll); -	msleep(75); +	mdelay(75);  }  static void __init tnetd7300_init_clocks(void) @@ -456,7 +456,7 @@ void clk_put(struct clk *clk)  }  EXPORT_SYMBOL(clk_put); -int __init ar7_init_clocks(void) +void __init ar7_init_clocks(void)  {  	switch (ar7_chip_id()) {  	case AR7_CHIP_7100: @@ -472,7 +472,4 @@ int __init ar7_init_clocks(void)  	}  	/* adjust vbus clock rate */  	vbus_clk.rate = bus_clk.rate / 2; - -	return 0;  } -arch_initcall(ar7_init_clocks); diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c index 5fb8a013408..22c93213b23 100644 --- a/arch/mips/ar7/time.c +++ b/arch/mips/ar7/time.c @@ -30,6 +30,9 @@ void __init plat_time_init(void)  {  	struct clk *cpu_clk; +	/* Initialize ar7 clocks so the CPU clock frequency is correct */ +	ar7_init_clocks(); +  	cpu_clk = clk_get(NULL, "cpu");  	if (IS_ERR(cpu_clk)) {  		printk(KERN_ERR "unable to get cpu clock\n"); diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index b1aee33efd1..c95f90bf734 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -32,7 +32,6 @@  #include <asm/reboot.h>  #include <asm/time.h>  #include <bcm47xx.h> -#include <asm/fw/cfe/cfe_api.h>  #include <asm/mach-bcm47xx/nvram.h>  struct ssb_bus ssb_bcm47xx; @@ -57,68 +56,112 @@ static void bcm47xx_machine_halt(void)  		cpu_relax();  } -static void str2eaddr(char *str, char *dest) +#define READ_FROM_NVRAM(_outvar, name, buf) \ +	if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\ +		sprom->_outvar = simple_strtoul(buf, NULL, 0); + +static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)  { -	int i = 0; +	char buf[100]; +	u32 boardflags; -	if (str == NULL) { -		memset(dest, 0, 6); -		return; -	} +	memset(sprom, 0, sizeof(struct ssb_sprom)); + +	sprom->revision = 1; /* Fallback: Old hardware does not define this. */ +	READ_FROM_NVRAM(revision, "sromrev", buf); +	if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0) +		nvram_parse_macaddr(buf, sprom->il0mac); +	if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0) +		nvram_parse_macaddr(buf, sprom->et0mac); +	if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0) +		nvram_parse_macaddr(buf, sprom->et1mac); +	READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf); +	READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf); +	READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf); +	READ_FROM_NVRAM(et1mdcport, "et1mdcport", buf); +	READ_FROM_NVRAM(board_rev, "boardrev", buf); +	READ_FROM_NVRAM(country_code, "ccode", buf); +	READ_FROM_NVRAM(ant_available_a, "aa5g", buf); +	READ_FROM_NVRAM(ant_available_bg, "aa2g", buf); +	READ_FROM_NVRAM(pa0b0, "pa0b0", buf); +	READ_FROM_NVRAM(pa0b1, "pa0b1", buf); +	READ_FROM_NVRAM(pa0b2, "pa0b2", buf); +	READ_FROM_NVRAM(pa1b0, "pa1b0", buf); +	READ_FROM_NVRAM(pa1b1, "pa1b1", buf); +	READ_FROM_NVRAM(pa1b2, "pa1b2", buf); +	READ_FROM_NVRAM(pa1lob0, "pa1lob0", buf); +	READ_FROM_NVRAM(pa1lob2, "pa1lob1", buf); +	READ_FROM_NVRAM(pa1lob1, "pa1lob2", buf); +	READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf); +	READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf); +	READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf); +	READ_FROM_NVRAM(gpio0, "wl0gpio0", buf); +	READ_FROM_NVRAM(gpio1, "wl0gpio1", buf); +	READ_FROM_NVRAM(gpio2, "wl0gpio2", buf); +	READ_FROM_NVRAM(gpio3, "wl0gpio3", buf); +	READ_FROM_NVRAM(maxpwr_bg, "pa0maxpwr", buf); +	READ_FROM_NVRAM(maxpwr_al, "pa1lomaxpwr", buf); +	READ_FROM_NVRAM(maxpwr_a, "pa1maxpwr", buf); +	READ_FROM_NVRAM(maxpwr_ah, "pa1himaxpwr", buf); +	READ_FROM_NVRAM(itssi_a, "pa1itssit", buf); +	READ_FROM_NVRAM(itssi_bg, "pa0itssit", buf); +	READ_FROM_NVRAM(tri2g, "tri2g", buf); +	READ_FROM_NVRAM(tri5gl, "tri5gl", buf); +	READ_FROM_NVRAM(tri5g, "tri5g", buf); +	READ_FROM_NVRAM(tri5gh, "tri5gh", buf); +	READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf); +	READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf); +	READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf); +	READ_FROM_NVRAM(rssismc2g, "rssismc2g", buf); +	READ_FROM_NVRAM(rssismf2g, "rssismf2g", buf); +	READ_FROM_NVRAM(bxa2g, "bxa2g", buf); +	READ_FROM_NVRAM(rssisav5g, "rssisav5g", buf); +	READ_FROM_NVRAM(rssismc5g, "rssismc5g", buf); +	READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf); +	READ_FROM_NVRAM(bxa5g, "bxa5g", buf); +	READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf); +	READ_FROM_NVRAM(ofdm2gpo, "ofdm2gpo", buf); +	READ_FROM_NVRAM(ofdm5glpo, "ofdm5glpo", buf); +	READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf); +	READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf); -	for (;;) { -		dest[i++] = (char) simple_strtoul(str, NULL, 16); -		str += 2; -		if (!*str++ || i == 6) -			break; +	if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) { +		boardflags = simple_strtoul(buf, NULL, 0); +		if (boardflags) { +			sprom->boardflags_lo = (boardflags & 0x0000FFFFU); +			sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16; +		} +	} +	if (nvram_getenv("boardflags2", buf, sizeof(buf)) >= 0) { +		boardflags = simple_strtoul(buf, NULL, 0); +		if (boardflags) { +			sprom->boardflags2_lo = (boardflags & 0x0000FFFFU); +			sprom->boardflags2_hi = (boardflags & 0xFFFF0000U) >> 16; +		}  	}  }  static int bcm47xx_get_invariants(struct ssb_bus *bus,  				   struct ssb_init_invariants *iv)  { -	char buf[100]; +	char buf[20];  	/* Fill boardinfo structure */  	memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); -	if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0) +	if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0) +		iv->boardinfo.vendor = (u16)simple_strtoul(buf, NULL, 0); +	else +		iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM; +	if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)  		iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); -	if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("boardtype", buf, sizeof(buf)) >= 0) -		iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); -	if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("boardrev", buf, sizeof(buf)) >= 0) +	if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)  		iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); -	/* Fill sprom structure */ -	memset(&(iv->sprom), 0, sizeof(struct ssb_sprom)); -	iv->sprom.revision = 3; - -	if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0) -		str2eaddr(buf, iv->sprom.et0mac); +	bcm47xx_fill_sprom(&iv->sprom); -	if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0) -		str2eaddr(buf, iv->sprom.et1mac); - -	if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) -		iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0); - -	if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) -		iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0); - -	if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0) -		iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10); - -	if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 || -	    nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0) -		iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10); +	if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) +		iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);  	return 0;  } @@ -126,12 +169,28 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,  void __init plat_mem_setup(void)  {  	int err; +	char buf[100]; +	struct ssb_mipscore *mcore;  	err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,  				      bcm47xx_get_invariants);  	if (err)  		panic("Failed to initialize SSB bus (err %d)\n", err); +	mcore = &ssb_bcm47xx.mipscore; +	if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) { +		if (strstr(buf, "console=ttyS1")) { +			struct ssb_serial_port port; + +			printk(KERN_DEBUG "Swapping serial ports!\n"); +			/* swap serial ports */ +			memcpy(&port, &mcore->serial_ports[0], sizeof(port)); +			memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], +			       sizeof(port)); +			memcpy(&mcore->serial_ports[1], &port, sizeof(port)); +		} +	} +  	_machine_restart = bcm47xx_machine_restart;  	_machine_halt = bcm47xx_machine_halt;  	pm_power_off = bcm47xx_machine_halt; diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 06d59dcbe24..86877539c6e 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -111,8 +111,8 @@   * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM   */ -#define PRID_IMP_BMIPS4KC	0x4000 -#define PRID_IMP_BMIPS32	0x8000 +#define PRID_IMP_BMIPS32_REV4	0x4000 +#define PRID_IMP_BMIPS32_REV8	0x8000  #define PRID_IMP_BMIPS3300	0x9000  #define PRID_IMP_BMIPS3300_ALT	0x9100  #define PRID_IMP_BMIPS3300_BUG	0x0000 diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index fd1d39eb743..455c0ac7d4e 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -249,7 +249,8 @@ extern struct mips_abi mips_abi_n32;  #define SET_PERSONALITY(ex)						\  do {									\ -	set_personality(PER_LINUX);					\ +	if (personality(current->personality) != PER_LINUX)		\ +		set_personality(PER_LINUX);				\  									\  	current->thread.abi = &mips_abi;				\  } while (0) @@ -296,6 +297,8 @@ do {									\  #define SET_PERSONALITY(ex)						\  do {									\ +	unsigned int p;							\ +									\  	clear_thread_flag(TIF_32BIT_REGS);				\  	clear_thread_flag(TIF_32BIT_ADDR);				\  									\ @@ -304,7 +307,8 @@ do {									\  	else								\  		current->thread.abi = &mips_abi;			\  									\ -	if (current->personality != PER_LINUX32)			\ +	p = personality(current->personality);				\ +	if (p != PER_LINUX32 && p != PER_LINUX)				\  		set_personality(PER_LINUX);				\  } while (0) diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index c98bf514ec7..5b017f23e24 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -329,10 +329,14 @@ static inline void pfx##write##bwlq(type val,				\  			"dsrl32	%L0, %L0, 0"			"\n\t"	\  			"dsll32	%M0, %M0, 0"			"\n\t"	\  			"or	%L0, %L0, %M0"			"\n\t"	\ +			".set	push"				"\n\t"	\ +			".set	noreorder"			"\n\t"	\ +			".set	nomacro"			"\n\t"	\  			"sd	%L0, %2"			"\n\t"	\ +			".set	pop"				"\n\t"	\  			".set	mips0"				"\n"	\  			: "=r" (__tmp)					\ -			: "0" (__val), "m" (*__mem));			\ +			: "0" (__val), "R" (*__mem));			\  		if (irq)						\  			local_irq_restore(__flags);			\  	} else								\ @@ -355,12 +359,16 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem)	\  			local_irq_save(__flags);			\  		__asm__ __volatile__(					\  			".set	mips3"		"\t\t# __readq"	"\n\t"	\ +			".set	push"				"\n\t"	\ +			".set	noreorder"			"\n\t"	\ +			".set	nomacro"			"\n\t"	\  			"ld	%L0, %1"			"\n\t"	\ +			".set	pop"				"\n\t"	\  			"dsra32	%M0, %L0, 0"			"\n\t"	\  			"sll	%L0, %L0, 0"			"\n\t"	\  			".set	mips0"				"\n"	\  			: "=r" (__val)					\ -			: "m" (*__mem));				\ +			: "R" (*__mem));				\  		if (irq)						\  			local_irq_restore(__flags);			\  	} else {							\ diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h index 7919d76186b..07d3fadb244 100644 --- a/arch/mips/include/asm/mach-ar7/ar7.h +++ b/arch/mips/include/asm/mach-ar7/ar7.h @@ -201,7 +201,6 @@ static inline void ar7_device_off(u32 bit)  }  int __init ar7_gpio_init(void); - -int __init ar7_gpio_init(void); +void __init ar7_init_clocks(void);  #endif /* __AR7_H__ */ diff --git a/arch/mips/include/asm/mach-bcm47xx/nvram.h b/arch/mips/include/asm/mach-bcm47xx/nvram.h index c58ebd8bc15..9759588ba3c 100644 --- a/arch/mips/include/asm/mach-bcm47xx/nvram.h +++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h @@ -12,6 +12,7 @@  #define __NVRAM_H  #include <linux/types.h> +#include <linux/kernel.h>  struct nvram_header {  	u32 magic; @@ -36,4 +37,10 @@ struct nvram_header {  extern int nvram_getenv(char *name, char *val, size_t val_len); +static inline void nvram_parse_macaddr(char *buf, u8 *macaddr) +{ +	sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], &macaddr[1], +	       &macaddr[2], &macaddr[3], &macaddr[4], &macaddr[5]); +} +  #endif diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 5742bb4d78f..5c0a3575877 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -5,7 +5,7 @@   *   * Copyright (c) 2009 Qi Hardware inc.,   * Author: Xiangfu Liu <xiangfu@qi-hardware.com> - * Copyright 2010, Lars-Petrer Clausen <lars@metafoo.de> + * Copyright 2010, Lars-Peter Clausen <lars@metafoo.de>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License version 2 or later @@ -235,7 +235,7 @@ static const unsigned int qi_lb60_keypad_rows[] = {  	QI_LB60_GPIO_KEYIN(3),  	QI_LB60_GPIO_KEYIN(4),  	QI_LB60_GPIO_KEYIN(5), -	QI_LB60_GPIO_KEYIN(7), +	QI_LB60_GPIO_KEYIN(6),  	QI_LB60_GPIO_KEYIN8,  }; diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c index 95bc2b5b14f..1cc9e544d16 100644 --- a/arch/mips/jz4740/platform.c +++ b/arch/mips/jz4740/platform.c @@ -208,7 +208,7 @@ struct platform_device jz4740_i2s_device = {  /* PCM */  struct platform_device jz4740_pcm_device = { -	.name		= "jz4740-pcm", +	.name		= "jz4740-pcm-audio",  	.id		= -1,  }; diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c index cfeac15eb2e..4a70407f55b 100644 --- a/arch/mips/jz4740/prom.c +++ b/arch/mips/jz4740/prom.c @@ -23,7 +23,7 @@  #include <asm/bootinfo.h>  #include <asm/mach-jz4740/base.h> -void jz4740_init_cmdline(int argc, char *argv[]) +static __init void jz4740_init_cmdline(int argc, char *argv[])  {  	unsigned int count = COMMAND_LINE_SIZE - 1;  	int i; diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 2f4d7a99bcc..98c5a9737c1 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -32,7 +32,7 @@ static int mips_next_event(unsigned long delta,  	cnt = read_c0_count();  	cnt += delta;  	write_c0_compare(cnt); -	res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0; +	res = ((int)(read_c0_count() - cnt) >= 0) ? -ETIME : 0;  	return res;  } diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 71620e19827..68dae7b6b5d 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -905,7 +905,8 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)  {  	decode_configs(c);  	switch (c->processor_id & 0xff00) { -	case PRID_IMP_BMIPS32: +	case PRID_IMP_BMIPS32_REV4: +	case PRID_IMP_BMIPS32_REV8:  		c->cputype = CPU_BMIPS32;  		__cpu_name[cpu] = "Broadcom BMIPS32";  		break; @@ -933,10 +934,6 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)  		__cpu_name[cpu] = "Broadcom BMIPS5000";  		c->options |= MIPS_CPU_ULRI;  		break; -	case PRID_IMP_BMIPS4KC: -		c->cputype = CPU_4KC; -		__cpu_name[cpu] = "MIPS 4Kc"; -		break;  	}  } diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 6343b4a5b83..876a75cc376 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -251,14 +251,15 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,  SYSCALL_DEFINE1(32_personality, unsigned long, personality)  { +	unsigned int p = personality & 0xffffffff;  	int ret; -	personality &= 0xffffffff; +  	if (personality(current->personality) == PER_LINUX32 && -	    personality == PER_LINUX) -		personality = PER_LINUX32; -	ret = sys_personality(personality); -	if (ret == PER_LINUX32) -		ret = PER_LINUX; +	    personality(p) == PER_LINUX) +		p = (p & ~PER_MASK) | PER_LINUX32; +	ret = sys_personality(p); +	if (ret != -1 && personality(ret) == PER_LINUX32) +		ret = (ret & ~PER_MASK) | PER_LINUX;  	return ret;  } diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 99960940d4a..ae167df73dd 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -142,7 +142,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,  	childregs->regs[7] = 0;	/* Clear error flag */  	childregs->regs[2] = 0;	/* Child gets zero as return value */ -	regs->regs[2] = p->pid;  	if (childregs->cp0_status & ST0_CU0) {  		childregs->regs[28] = (unsigned long) ti; diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index e000b278f02..9dbe5836895 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -100,7 +100,7 @@ void __init device_tree_init(void)  		return;  	base = virt_to_phys((void *)initial_boot_params); -	size = initial_boot_params->totalsize; +	size = be32_to_cpu(initial_boot_params->totalsize);  	/* Before we do anything, lets reserve the dt blob */  	reserve_mem_mach(base, size); diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 43e7cdc5ded..c0e81418ba2 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -153,7 +153,7 @@ static void __cpuinit vsmp_init_secondary(void)  {  	extern int gic_present; -	/* This is Malta specific: IPI,performance and timer inetrrupts */ +	/* This is Malta specific: IPI,performance and timer interrupts */  	if (gic_present)  		change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |  					 STATUSF_IP6 | STATUSF_IP7); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 8e9fbe75894..e9710430254 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -83,7 +83,8 @@ extern asmlinkage void handle_mcheck(void);  extern asmlinkage void handle_reserved(void);  extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, -	struct mips_fpu_struct *ctx, int has_fpu); +				    struct mips_fpu_struct *ctx, int has_fpu, +				    void *__user *fault_addr);  void (*board_be_init)(void);  int (*board_be_handler)(struct pt_regs *regs, int is_fixup); @@ -661,12 +662,36 @@ asmlinkage void do_ov(struct pt_regs *regs)  	force_sig_info(SIGFPE, &info, current);  } +static int process_fpemu_return(int sig, void __user *fault_addr) +{ +	if (sig == SIGSEGV || sig == SIGBUS) { +		struct siginfo si = {0}; +		si.si_addr = fault_addr; +		si.si_signo = sig; +		if (sig == SIGSEGV) { +			if (find_vma(current->mm, (unsigned long)fault_addr)) +				si.si_code = SEGV_ACCERR; +			else +				si.si_code = SEGV_MAPERR; +		} else { +			si.si_code = BUS_ADRERR; +		} +		force_sig_info(sig, &si, current); +		return 1; +	} else if (sig) { +		force_sig(sig, current); +		return 1; +	} else { +		return 0; +	} +} +  /*   * XXX Delayed fp exceptions when doing a lazy ctx switch XXX   */  asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)  { -	siginfo_t info; +	siginfo_t info = {0};  	if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE)  	    == NOTIFY_STOP) @@ -675,6 +700,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)  	if (fcr31 & FPU_CSR_UNI_X) {  		int sig; +		void __user *fault_addr = NULL;  		/*  		 * Unimplemented operation exception.  If we've got the full @@ -690,7 +716,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)  		lose_fpu(1);  		/* Run the emulator */ -		sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1); +		sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, +					       &fault_addr);  		/*  		 * We can't allow the emulated instruction to leave any of @@ -702,8 +729,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)  		own_fpu(1);	/* Using the FPU again.  */  		/* If something went wrong, signal */ -		if (sig) -			force_sig(sig, current); +		process_fpemu_return(sig, fault_addr);  		return;  	} else if (fcr31 & FPU_CSR_INV_X) @@ -996,11 +1022,11 @@ asmlinkage void do_cpu(struct pt_regs *regs)  		if (!raw_cpu_has_fpu) {  			int sig; +			void __user *fault_addr = NULL;  			sig = fpu_emulator_cop1Handler(regs, -						¤t->thread.fpu, 0); -			if (sig) -				force_sig(sig, current); -			else +						       ¤t->thread.fpu, +						       0, &fault_addr); +			if (!process_fpemu_return(sig, fault_addr))  				mt_ase_fp_affinity();  		} diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 3eb3cde2f66..6a1fdfef8fd 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -1092,6 +1092,10 @@ static int vpe_open(struct inode *inode, struct file *filp)  	/* this of-course trashes what was there before... */  	v->pbuffer = vmalloc(P_SIZE); +	if (!v->pbuffer) { +		pr_warning("VPE loader: unable to allocate memory\n"); +		return -ENOMEM; +	}  	v->plen = P_SIZE;  	v->load_addr = NULL;  	v->len = 0; @@ -1149,10 +1153,9 @@ static int vpe_release(struct inode *inode, struct file *filp)  	if (ret < 0)  		v->shared_ptr = NULL; -	// cleanup any temp buffers -	if (v->pbuffer) -		vfree(v->pbuffer); +	vfree(v->pbuffer);  	v->plen = 0; +  	return ret;  } @@ -1169,11 +1172,6 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,  	if (v == NULL)  		return -ENODEV; -	if (v->pbuffer == NULL) { -		printk(KERN_ERR "VPE loader: no buffer for program\n"); -		return -ENOMEM; -	} -  	if ((count + v->len) > v->plen) {  		printk(KERN_WARNING  		       "VPE loader: elf size too big. Perhaps strip uneeded symbols\n"); diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S index 77dc3b20110..606c8a9efe3 100644 --- a/arch/mips/lib/memset.S +++ b/arch/mips/lib/memset.S @@ -161,16 +161,16 @@ FEXPORT(__bzero)  .Lfwd_fixup:  	PTR_L		t0, TI_TASK($28) -	LONG_L		t0, THREAD_BUADDR(t0)  	andi		a2, 0x3f +	LONG_L		t0, THREAD_BUADDR(t0)  	LONG_ADDU	a2, t1  	jr		ra  	 LONG_SUBU	a2, t0  .Lpartial_fixup:  	PTR_L		t0, TI_TASK($28) -	LONG_L		t0, THREAD_BUADDR(t0)  	andi		a2, LONGMASK +	LONG_L		t0, THREAD_BUADDR(t0)  	LONG_ADDU	a2, t1  	jr		ra  	 LONG_SUBU	a2, t0 diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c index ae4cff97a56..11b193f848f 100644 --- a/arch/mips/loongson/common/env.c +++ b/arch/mips/loongson/common/env.c @@ -29,9 +29,9 @@ unsigned long memsize, highmemsize;  #define parse_even_earlier(res, option, p)				\  do {									\ +	int ret;							\  	if (strncmp(option, (char *)p, strlen(option)) == 0)		\ -			strict_strtol((char *)p + strlen(option"="),	\ -					10, &res);			\ +		ret = strict_strtol((char *)p + strlen(option"="), 10, &res); \  } while (0)  void __init prom_init_env(void) diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index b2ad1b0910f..d32cb050311 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -64,7 +64,7 @@ static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,  #if __mips >= 4 && __mips != 32  static int fpux_emu(struct pt_regs *, -	struct mips_fpu_struct *, mips_instruction); +	struct mips_fpu_struct *, mips_instruction, void *__user *);  #endif  /* Further private data for which no space exists in mips_fpu_struct */ @@ -208,16 +208,23 @@ static inline int cop1_64bit(struct pt_regs *xcp)   * Two instructions if the instruction is in a branch delay slot.   */ -static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) +static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, +		       void *__user *fault_addr)  {  	mips_instruction ir;  	unsigned long emulpc, contpc;  	unsigned int cond; -	if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) { +	if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) {  		MIPS_FPU_EMU_INC_STATS(errors); +		*fault_addr = (mips_instruction __user *)xcp->cp0_epc;  		return SIGBUS;  	} +	if (__get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) { +		MIPS_FPU_EMU_INC_STATS(errors); +		*fault_addr = (mips_instruction __user *)xcp->cp0_epc; +		return SIGSEGV; +	}  	/* XXX NEC Vr54xx bug workaround */  	if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) @@ -245,10 +252,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  #endif  			return SIGILL;  		} -		if (get_user(ir, (mips_instruction __user *) emulpc)) { +		if (!access_ok(VERIFY_READ, emulpc, sizeof(mips_instruction))) {  			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = (mips_instruction __user *)emulpc;  			return SIGBUS;  		} +		if (__get_user(ir, (mips_instruction __user *) emulpc)) { +			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = (mips_instruction __user *)emulpc; +			return SIGSEGV; +		}  		/* __compute_return_epc() will have updated cp0_epc */  		contpc = xcp->cp0_epc;  		/* In order not to confuse ptrace() et al, tweak context */ @@ -269,10 +282,17 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  		u64 val;  		MIPS_FPU_EMU_INC_STATS(loads); -		if (get_user(val, va)) { + +		if (!access_ok(VERIFY_READ, va, sizeof(u64))) {  			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va;  			return SIGBUS;  		} +		if (__get_user(val, va)) { +			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va; +			return SIGSEGV; +		}  		DITOREG(val, MIPSInst_RT(ir));  		break;  	} @@ -284,10 +304,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  		MIPS_FPU_EMU_INC_STATS(stores);  		DIFROMREG(val, MIPSInst_RT(ir)); -		if (put_user(val, va)) { +		if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {  			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va;  			return SIGBUS;  		} +		if (__put_user(val, va)) { +			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va; +			return SIGSEGV; +		}  		break;  	} @@ -297,10 +323,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  		u32 val;  		MIPS_FPU_EMU_INC_STATS(loads); -		if (get_user(val, va)) { +		if (!access_ok(VERIFY_READ, va, sizeof(u32))) {  			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va;  			return SIGBUS;  		} +		if (__get_user(val, va)) { +			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va; +			return SIGSEGV; +		}  		SITOREG(val, MIPSInst_RT(ir));  		break;  	} @@ -312,10 +344,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  		MIPS_FPU_EMU_INC_STATS(stores);  		SIFROMREG(val, MIPSInst_RT(ir)); -		if (put_user(val, va)) { +		if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {  			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va;  			return SIGBUS;  		} +		if (__put_user(val, va)) { +			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = va; +			return SIGSEGV; +		}  		break;  	} @@ -440,11 +478,18 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  				contpc = (xcp->cp0_epc +  					(MIPSInst_SIMM(ir) << 2)); -				if (get_user(ir, -				    (mips_instruction __user *) xcp->cp0_epc)) { +				if (!access_ok(VERIFY_READ, xcp->cp0_epc, +					       sizeof(mips_instruction))) {  					MIPS_FPU_EMU_INC_STATS(errors); +					*fault_addr = (mips_instruction __user *)xcp->cp0_epc;  					return SIGBUS;  				} +				if (__get_user(ir, +				    (mips_instruction __user *) xcp->cp0_epc)) { +					MIPS_FPU_EMU_INC_STATS(errors); +					*fault_addr = (mips_instruction __user *)xcp->cp0_epc; +					return SIGSEGV; +				}  				switch (MIPSInst_OPCODE(ir)) {  				case lwc1_op: @@ -506,9 +551,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)  #if __mips >= 4 && __mips != 32  	case cop1x_op:{ -		int sig; - -		if ((sig = fpux_emu(xcp, ctx, ir))) +		int sig = fpux_emu(xcp, ctx, ir, fault_addr); +		if (sig)  			return sig;  		break;  	} @@ -604,7 +648,7 @@ DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);  DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);  static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, -	mips_instruction ir) +	mips_instruction ir, void *__user *fault_addr)  {  	unsigned rcsr = 0;	/* resulting csr */ @@ -624,10 +668,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  				xcp->regs[MIPSInst_FT(ir)]);  			MIPS_FPU_EMU_INC_STATS(loads); -			if (get_user(val, va)) { +			if (!access_ok(VERIFY_READ, va, sizeof(u32))) {  				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va;  				return SIGBUS;  			} +			if (__get_user(val, va)) { +				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va; +				return SIGSEGV; +			}  			SITOREG(val, MIPSInst_FD(ir));  			break; @@ -638,10 +688,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			MIPS_FPU_EMU_INC_STATS(stores);  			SIFROMREG(val, MIPSInst_FS(ir)); -			if (put_user(val, va)) { +			if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {  				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va;  				return SIGBUS;  			} +			if (put_user(val, va)) { +				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va; +				return SIGSEGV; +			}  			break;  		case madd_s_op: @@ -701,10 +757,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  				xcp->regs[MIPSInst_FT(ir)]);  			MIPS_FPU_EMU_INC_STATS(loads); -			if (get_user(val, va)) { +			if (!access_ok(VERIFY_READ, va, sizeof(u64))) {  				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va;  				return SIGBUS;  			} +			if (__get_user(val, va)) { +				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va; +				return SIGSEGV; +			}  			DITOREG(val, MIPSInst_FD(ir));  			break; @@ -714,10 +776,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			MIPS_FPU_EMU_INC_STATS(stores);  			DIFROMREG(val, MIPSInst_FS(ir)); -			if (put_user(val, va)) { +			if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {  				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va;  				return SIGBUS;  			} +			if (__put_user(val, va)) { +				MIPS_FPU_EMU_INC_STATS(errors); +				*fault_addr = va; +				return SIGSEGV; +			}  			break;  		case madd_d_op: @@ -1242,7 +1310,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  }  int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, -	int has_fpu) +	int has_fpu, void *__user *fault_addr)  {  	unsigned long oldepc, prevepc;  	mips_instruction insn; @@ -1252,10 +1320,16 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  	do {  		prevepc = xcp->cp0_epc; -		if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) { +		if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) {  			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = (mips_instruction __user *)xcp->cp0_epc;  			return SIGBUS;  		} +		if (__get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) { +			MIPS_FPU_EMU_INC_STATS(errors); +			*fault_addr = (mips_instruction __user *)xcp->cp0_epc; +			return SIGSEGV; +		}  		if (insn == 0)  			xcp->cp0_epc += 4;	/* skip nops */  		else { @@ -1267,7 +1341,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,  			 */  			/* convert to ieee library modes */  			ieee754_csr.rm = ieee_rm[ieee754_csr.rm]; -			sig = cop1Emulate(xcp, ctx); +			sig = cop1Emulate(xcp, ctx, fault_addr);  			/* revert to mips rounding mode */  			ieee754_csr.rm = mips_rm[ieee754_csr.rm];  		} diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 4fc1a0fbe00..21ea14efb83 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -288,7 +288,7 @@ int mips_dma_supported(struct device *dev, u64 mask)  	return plat_dma_supported(dev, mask);  } -void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size, +void dma_cache_sync(struct device *dev, void *vaddr, size_t size,  			 enum dma_data_direction direction)  {  	BUG_ON(direction == DMA_NONE); @@ -298,6 +298,8 @@ void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size,  		__dma_sync((unsigned long)vaddr, size, direction);  } +EXPORT_SYMBOL(dma_cache_sync); +  static struct dma_map_ops mips_default_dma_map_ops = {  	.alloc_coherent = mips_dma_alloc_coherent,  	.free_coherent = mips_dma_free_coherent, diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index 505fecad468..9cca8de0054 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c @@ -68,6 +68,9 @@ static struct bcache_ops mips_sc_ops = {   */  static inline int mips_sc_is_activated(struct cpuinfo_mips *c)  { +	unsigned int config2 = read_c0_config2(); +	unsigned int tmp; +  	/* Check the bypass bit (L2B) */  	switch (c->cputype) {  	case CPU_34K: @@ -83,6 +86,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)  		c->scache.linesz = 2 << tmp;  	else  		return 0; +	return 1;  }  static inline int __init mips_sc_probe(void) diff --git a/arch/mips/pmc-sierra/yosemite/py-console.c b/arch/mips/pmc-sierra/yosemite/py-console.c index b7f1d9c4a8a..434d7b1a8c6 100644 --- a/arch/mips/pmc-sierra/yosemite/py-console.c +++ b/arch/mips/pmc-sierra/yosemite/py-console.c @@ -65,11 +65,15 @@ static unsigned char readb_outer_space(unsigned long long phys)  	__asm__ __volatile__ (  	"	.set	mips3		\n" +	"	.set	push		\n" +	"	.set	noreorder	\n" +	"	.set	nomacro		\n"  	"	ld	%0, %1		\n" +	"	.set	pop		\n"  	"	lbu	%0, (%0)	\n"  	"	.set	mips0		\n"  	: "=r" (res) -	: "m" (vaddr)); +	: "R" (vaddr));  	write_c0_status(sr);  	ssnop_4(); @@ -89,11 +93,15 @@ static void writeb_outer_space(unsigned long long phys, unsigned char c)  	__asm__ __volatile__ (  	"	.set	mips3		\n" +	"	.set	push		\n" +	"	.set	noreorder	\n" +	"	.set	nomacro		\n"  	"	ld	%0, %1		\n" +	"	.set	pop		\n"  	"	sb	%2, (%0)	\n"  	"	.set	mips0		\n"  	: "=&r" (tmp) -	: "m" (vaddr), "r" (c)); +	: "R" (vaddr), "r" (c));  	write_c0_status(sr);  	ssnop_4(); diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c index c308989fc46..41707a245de 100644 --- a/arch/mips/sibyte/swarm/setup.c +++ b/arch/mips/sibyte/swarm/setup.c @@ -82,7 +82,7 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup)  enum swarm_rtc_type {  	RTC_NONE,  	RTC_XICOR, -	RTC_M4LT81 +	RTC_M41T81,  };  enum swarm_rtc_type swarm_rtc_type; @@ -96,7 +96,7 @@ void read_persistent_clock(struct timespec *ts)  		sec = xicor_get_time();  		break; -	case RTC_M4LT81: +	case RTC_M41T81:  		sec = m41t81_get_time();  		break; @@ -115,7 +115,7 @@ int rtc_mips_set_time(unsigned long sec)  	case RTC_XICOR:  		return xicor_set_time(sec); -	case RTC_M4LT81: +	case RTC_M41T81:  		return m41t81_set_time(sec);  	case RTC_NONE: @@ -141,7 +141,7 @@ void __init plat_mem_setup(void)  	if (xicor_probe())  		swarm_rtc_type = RTC_XICOR;  	if (m41t81_probe()) -		swarm_rtc_type = RTC_M4LT81; +		swarm_rtc_type = RTC_M41T81;  #ifdef CONFIG_VT  	screen_info = (struct screen_info) { diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index f860a340acc..75da468090b 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c @@ -40,21 +40,17 @@ unsigned long long sched_clock(void)  		unsigned long long ll;  		unsigned l[2];  	} tsc64, result; -	unsigned long tsc, tmp; +	unsigned long tmp;  	unsigned product[3]; /* 96-bit intermediate value */  	/* cnt32_to_63() is not safe with preemption */  	preempt_disable(); -	/* read the TSC value -	 */ -	tsc = get_cycles(); - -	/* expand to 64-bits. +	/* expand the tsc to 64-bits.  	 * - sched_clock() must be called once a minute or better or the  	 *   following will go horribly wrong - see cnt32_to_63()  	 */ -	tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL; +	tsc64.ll = cnt32_to_63(get_cycles()) & 0x7fffffffffffffffULL;  	preempt_enable(); diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h index c1ee1d61d44..81d92a45cd4 100644 --- a/arch/tile/include/asm/signal.h +++ b/arch/tile/include/asm/signal.h @@ -25,7 +25,7 @@  #if defined(__KERNEL__) && !defined(__ASSEMBLY__)  struct pt_regs; -int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); +int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);  int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);  void do_signal(struct pt_regs *regs);  #endif diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index 543d6a33aa2..dbb0dfc7bec 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c @@ -290,12 +290,12 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,  	return ret;  } +/* The assembly shim for this function arranges to ignore the return value. */  long compat_sys_rt_sigreturn(struct pt_regs *regs)  {  	struct compat_rt_sigframe __user *frame =  		(struct compat_rt_sigframe __user *) compat_ptr(regs->sp);  	sigset_t set; -	long r0;  	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))  		goto badframe; @@ -308,13 +308,13 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)  	recalc_sigpending();  	spin_unlock_irq(¤t->sighand->siglock); -	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) +	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))  		goto badframe;  	if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)  		goto badframe; -	return r0; +	return 0;  badframe:  	force_sig(SIGSEGV, current); diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index f5821626247..5eed4a02bf6 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S @@ -1342,8 +1342,8 @@ handle_syscall:  	lw      r20, r20  	/* Jump to syscall handler. */ -	jalr    r20; .Lhandle_syscall_link: -	FEEDBACK_REENTER(handle_syscall) +	jalr    r20 +.Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */  	/*  	 * Write our r0 onto the stack so it gets restored instead @@ -1352,6 +1352,9 @@ handle_syscall:  	PTREGS_PTR(r29, PTREGS_OFFSET_REG(0))  	sw      r29, r0 +.Lsyscall_sigreturn_skip: +	FEEDBACK_REENTER(handle_syscall) +  	/* Do syscall trace again, if requested. */  	lw	r30, r31  	andi    r30, r30, _TIF_SYSCALL_TRACE @@ -1536,9 +1539,24 @@ STD_ENTRY_LOCAL(bad_intr)  	};                                              \  	STD_ENDPROC(_##x) +/* + * Special-case sigreturn to not write r0 to the stack on return. + * This is technically more efficient, but it also avoids difficulties + * in the 64-bit OS when handling 32-bit compat code, since we must not + * sign-extend r0 for the sigreturn return-value case. + */ +#define PTREGS_SYSCALL_SIGRETURN(x, reg)                \ +	STD_ENTRY(_##x);                                \ +	addli   lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \ +	{                                               \ +	 PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \ +	 j      x                                       \ +	};                                              \ +	STD_ENDPROC(_##x) +  PTREGS_SYSCALL(sys_execve, r3)  PTREGS_SYSCALL(sys_sigaltstack, r2) -PTREGS_SYSCALL(sys_rt_sigreturn, r0) +PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)  PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)  /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 8430f45daea..e90eb53173b 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -212,6 +212,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,  	childregs->sp = sp;  /* override with new user stack pointer */  	/* +	 * If CLONE_SETTLS is set, set "tp" in the new task to "r4", +	 * which is passed in as arg #5 to sys_clone(). +	 */ +	if (clone_flags & CLONE_SETTLS) +		childregs->tp = regs->regs[4]; + +	/*  	 * Copy the callee-saved registers from the passed pt_regs struct  	 * into the context-switch callee-saved registers area.  	 * This way when we start the interrupt-return sequence, the @@ -539,6 +546,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,  	return __switch_to(prev, next, next_current_ksp0(next));  } +/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */  SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,  		void __user *, parent_tidptr, void __user *, child_tidptr,  		struct pt_regs *, regs) diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 757407e3669..1260321155f 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c @@ -52,7 +52,7 @@ SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,   */  int restore_sigcontext(struct pt_regs *regs, -		       struct sigcontext __user *sc, long *pr0) +		       struct sigcontext __user *sc)  {  	int err = 0;  	int i; @@ -75,17 +75,15 @@ int restore_sigcontext(struct pt_regs *regs,  	regs->faultnum = INT_SWINT_1_SIGRETURN; -	err |= __get_user(*pr0, &sc->gregs[0]);  	return err;  } -/* sigreturn() returns long since it restores r0 in the interrupted code. */ +/* The assembly shim for this function arranges to ignore the return value. */  SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)  {  	struct rt_sigframe __user *frame =  		(struct rt_sigframe __user *)(regs->sp);  	sigset_t set; -	long r0;  	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))  		goto badframe; @@ -98,13 +96,13 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)  	recalc_sigpending();  	spin_unlock_irq(¤t->sighand->siglock); -	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) +	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))  		goto badframe;  	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)  		goto badframe; -	return r0; +	return 0;  badframe:  	force_sig(SIGSEGV, current); diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 23f315c9f21..325c05294fc 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -355,7 +355,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,  	if (heap > 0x3fffffffffffUL)  		error("Destination address too large");  #else -	if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff)) +	if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff))  		error("Destination address too large");  #endif  #ifndef CONFIG_RELOCATABLE diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index 5be1542fbfa..e99d55d74df 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -72,6 +72,9 @@ struct e820map {  #define BIOS_BEGIN		0x000a0000  #define BIOS_END		0x00100000 +#define BIOS_ROM_BASE		0xffe00000 +#define BIOS_ROM_END		0xffffffff +  #ifdef __KERNEL__  /* see comment in arch/x86/kernel/e820.c */  extern struct e820map e820; diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 9e6fe391094..f702f82aa1e 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -79,7 +79,7 @@  #define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT)  #define KVM_MIN_FREE_MMU_PAGES 5  #define KVM_REFILL_PAGES 25 -#define KVM_MAX_CPUID_ENTRIES 40 +#define KVM_MAX_CPUID_ENTRIES 80  #define KVM_NR_FIXED_MTRR_REGION 88  #define KVM_NR_VAR_MTRR 8 diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 9e13763b609..1e994754d32 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -45,6 +45,7 @@ obj-y			+= pci-dma.o quirks.o i8237.o topology.o kdebugfs.o  obj-y			+= alternative.o i8253.o pci-nommu.o hw_breakpoint.o  obj-y			+= tsc.o io_delay.o rtc.o  obj-y			+= pci-iommu_table.o +obj-y			+= resource.o  obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o  obj-y				+= process.o diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 3f838d53739..78218135b48 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1389,6 +1389,14 @@ void __cpuinit end_local_APIC_setup(void)  	setup_apic_nmi_watchdog(NULL);  	apic_pm_activate(); + +	/* +	 * Now that local APIC setup is completed for BP, configure the fault +	 * handling for interrupt remapping. +	 */ +	if (!smp_processor_id() && intr_remapping_enabled) +		enable_drhd_fault_handling(); +  }  #ifdef CONFIG_X86_X2APIC diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 7cc0a721f62..fadcd743a74 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2430,13 +2430,12 @@ static void ack_apic_level(struct irq_data *data)  {  	struct irq_cfg *cfg = data->chip_data;  	int i, do_unmask_irq = 0, irq = data->irq; -	struct irq_desc *desc = irq_to_desc(irq);  	unsigned long v;  	irq_complete_move(cfg);  #ifdef CONFIG_GENERIC_PENDING_IRQ  	/* If we are moving the irq we need to mask it */ -	if (unlikely(desc->status & IRQ_MOVE_PENDING)) { +	if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) {  		do_unmask_irq = 1;  		mask_ioapic(cfg);  	} @@ -3413,6 +3412,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,  	msg.data |= MSI_DATA_VECTOR(cfg->vector);  	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;  	msg.address_lo |= MSI_ADDR_DEST_ID(dest); +	msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest);  	dmar_msi_write(irq, &msg); diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index f9e4e6a5407..d8c4a6feb28 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c @@ -79,13 +79,6 @@ void __init default_setup_apic_routing(void)  		/* need to update phys_pkg_id */  		apic->phys_pkg_id = apicid_phys_pkg_id;  	} - -	/* -	 * Now that apic routing model is selected, configure the -	 * fault handling for intr remapping. -	 */ -	if (intr_remapping_enabled) -		enable_drhd_fault_handling();  }  /* Same for both flat and physical. */ diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index bcece91dd31..c0dbd9ac24f 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -60,16 +60,18 @@  #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)  #endif +/* Number of possible pages in the lowmem region */ +LOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) +	  /* Enough space to fit pagetables for the low memory linear map */ -MAPPING_BEYOND_END = \ -	PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT +MAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT  /*   * Worst-case size of the kernel mapping we need to make: - * the worst-case size of the kernel itself, plus the extra we need - * to map for the linear map. + * a relocatable kernel can live anywhere in lowmem, so we need to be able + * to map all of lowmem.   */ -KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT +KERNEL_PAGES = LOWMEM_PAGES  INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm  RESERVE_BRK(pagetables, INIT_MAP_SIZE) @@ -620,13 +622,13 @@ ENTRY(initial_code)  __PAGE_ALIGNED_BSS  	.align PAGE_SIZE_asm  #ifdef CONFIG_X86_PAE -initial_pg_pmd: +ENTRY(initial_pg_pmd)  	.fill 1024*KPMDS,4,0  #else  ENTRY(initial_page_table)  	.fill 1024,4,0  #endif -initial_pg_fixmap: +ENTRY(initial_pg_fixmap)  	.fill 1024,4,0  ENTRY(empty_zero_page)  	.fill 4096,1,0 diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index ae03cab4352..4ff5968f12d 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -27,6 +27,9 @@  #define HPET_DEV_FSB_CAP		0x1000  #define HPET_DEV_PERI_CAP		0x2000 +#define HPET_MIN_CYCLES			128 +#define HPET_MIN_PROG_DELTA		(HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1)) +  #define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt)  /* @@ -299,8 +302,9 @@ static void hpet_legacy_clockevent_register(void)  	/* Calculate the min / max delta */  	hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,  							   &hpet_clockevent); -	/* 5 usec minimum reprogramming delta. */ -	hpet_clockevent.min_delta_ns = 5000; +	/* Setup minimum reprogramming delta. */ +	hpet_clockevent.min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA, +							   &hpet_clockevent);  	/*  	 * Start hpet with the boot cpu mask and make it @@ -393,22 +397,24 @@ static int hpet_next_event(unsigned long delta,  	 * the wraparound into account) nor a simple count down event  	 * mode. Further the write to the comparator register is  	 * delayed internally up to two HPET clock cycles in certain -	 * chipsets (ATI, ICH9,10). We worked around that by reading -	 * back the compare register, but that required another -	 * workaround for ICH9,10 chips where the first readout after -	 * write can return the old stale value. We already have a -	 * minimum delta of 5us enforced, but a NMI or SMI hitting +	 * chipsets (ATI, ICH9,10). Some newer AMD chipsets have even +	 * longer delays. We worked around that by reading back the +	 * compare register, but that required another workaround for +	 * ICH9,10 chips where the first readout after write can +	 * return the old stale value. We already had a minimum +	 * programming delta of 5us enforced, but a NMI or SMI hitting  	 * between the counter readout and the comparator write can  	 * move us behind that point easily. Now instead of reading  	 * the compare register back several times, we make the ETIME  	 * decision based on the following: Return ETIME if the -	 * counter value after the write is less than 8 HPET cycles +	 * counter value after the write is less than HPET_MIN_CYCLES  	 * away from the event or if the counter is already ahead of -	 * the event. +	 * the event. The minimum programming delta for the generic +	 * clockevents code is set to 1.5 * HPET_MIN_CYCLES.  	 */  	res = (s32)(cnt - hpet_readl(HPET_COUNTER)); -	return res < 8 ? -ETIME : 0; +	return res < HPET_MIN_CYCLES ? -ETIME : 0;  }  static void hpet_legacy_set_mode(enum clock_event_mode mode, diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c new file mode 100644 index 00000000000..2a26819bb6a --- /dev/null +++ b/arch/x86/kernel/resource.c @@ -0,0 +1,48 @@ +#include <linux/ioport.h> +#include <asm/e820.h> + +static void resource_clip(struct resource *res, resource_size_t start, +			  resource_size_t end) +{ +	resource_size_t low = 0, high = 0; + +	if (res->end < start || res->start > end) +		return;		/* no conflict */ + +	if (res->start < start) +		low = start - res->start; + +	if (res->end > end) +		high = res->end - end; + +	/* Keep the area above or below the conflict, whichever is larger */ +	if (low > high) +		res->end = start - 1; +	else +		res->start = end + 1; +} + +static void remove_e820_regions(struct resource *avail) +{ +	int i; +	struct e820entry *entry; + +	for (i = 0; i < e820.nr_map; i++) { +		entry = &e820.map[i]; + +		resource_clip(avail, entry->addr, +			      entry->addr + entry->size - 1); +	} +} + +void arch_remove_reservations(struct resource *avail) +{ +	/* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */ +	if (avail->flags & IORESOURCE_MEM) { +		if (avail->start < BIOS_END) +			avail->start = BIOS_END; +		resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END); + +		remove_e820_regions(avail); +	} +} diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 21c6746338a..85268f8eadf 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -769,7 +769,6 @@ void __init setup_arch(char **cmdline_p)  	x86_init.oem.arch_setup(); -	resource_alloc_from_bottom = 0;  	iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1;  	setup_memory_map();  	parse_setup_data(); diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 9c253bd65e2..547128546cc 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -394,7 +394,8 @@ static void __init setup_xstate_init(void)  	 * Setup init_xstate_buf to represent the init state of  	 * all the features managed by the xsave  	 */ -	init_xstate_buf = alloc_bootmem(xstate_size); +	init_xstate_buf = alloc_bootmem_align(xstate_size, +					      __alignof__(struct xsave_struct));  	init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT;  	clts(); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 1ca12298ffc..b81a9b7c2ca 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3494,6 +3494,10 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu)  static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)  {  	switch (func) { +	case 0x00000001: +		/* Mask out xsave bit as long as it is not supported by SVM */ +		entry->ecx &= ~(bit(X86_FEATURE_XSAVE)); +		break;  	case 0x80000001:  		if (nested)  			entry->ecx |= (1 << 2); /* Set SVM bit */ diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ff21fdda0c5..81fcbe9515c 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4227,11 +4227,6 @@ static int vmx_get_lpage_level(void)  		return PT_PDPE_LEVEL;  } -static inline u32 bit(int bitno) -{ -	return 1 << (bitno & 31); -} -  static void vmx_cpuid_update(struct kvm_vcpu *vcpu)  {  	struct kvm_cpuid_entry2 *best; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index cdac9e592aa..b989e1f1e5d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -155,11 +155,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {  u64 __read_mostly host_xcr0; -static inline u32 bit(int bitno) -{ -	return 1 << (bitno & 31); -} -  static void kvm_on_user_return(struct user_return_notifier *urn)  {  	unsigned slot; @@ -4569,9 +4564,11 @@ static void kvm_timer_init(void)  #ifdef CONFIG_CPU_FREQ  		struct cpufreq_policy policy;  		memset(&policy, 0, sizeof(policy)); -		cpufreq_get_policy(&policy, get_cpu()); +		cpu = get_cpu(); +		cpufreq_get_policy(&policy, cpu);  		if (policy.cpuinfo.max_freq)  			max_tsc_khz = policy.cpuinfo.max_freq; +		put_cpu();  #endif  		cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block,  					  CPUFREQ_TRANSITION_NOTIFIER); @@ -5522,6 +5519,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,  	mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4;  	kvm_x86_ops->set_cr4(vcpu, sregs->cr4); +	if (sregs->cr4 & X86_CR4_OSXSAVE) +		update_cpuid(vcpu);  	if (!is_long_mode(vcpu) && is_pae(vcpu)) {  		load_pdptrs(vcpu, vcpu->arch.walk_mmu, vcpu->arch.cr3);  		mmu_reset_needed = 1; diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 2cea414489f..c600da830ce 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -70,6 +70,11 @@ static inline int is_paging(struct kvm_vcpu *vcpu)  	return kvm_read_cr0_bits(vcpu, X86_CR0_PG);  } +static inline u32 bit(int bitno) +{ +	return 1 << (bitno & 31); +} +  void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);  void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);  int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq); diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 73b1e1a1f48..4996cf5f73a 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -531,7 +531,10 @@ static void lguest_write_cr3(unsigned long cr3)  {  	lguest_data.pgdir = cr3;  	lazy_hcall1(LHCALL_NEW_PGTABLE, cr3); -	cr3_changed = true; + +	/* These two page tables are simple, linear, and used during boot */ +	if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table)) +		cr3_changed = true;  }  static unsigned long lguest_read_cr3(void) @@ -703,9 +706,9 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)   * to forget all of them.  Fortunately, this is very rare.   *   * ... except in early boot when the kernel sets up the initial pagetables, - * which makes booting astonishingly slow: 1.83 seconds!  So we don't even tell - * the Host anything changed until we've done the first page table switch, - * which brings boot back to 0.25 seconds. + * which makes booting astonishingly slow: 48 seconds!  So we don't even tell + * the Host anything changed until we've done the first real page table switch, + * which brings boot back to 4.3 seconds.   */  static void lguest_set_pte(pte_t *ptep, pte_t pteval)  { @@ -1002,7 +1005,7 @@ static void lguest_time_init(void)  	clockevents_register_device(&lguest_clockevent);  	/* Finally, we unblock the timer interrupt. */ -	enable_lguest_irq(0); +	clear_bit(0, lguest_data.blocked_interrupts);  }  /* @@ -1349,9 +1352,6 @@ __init void lguest_init(void)  	 */  	switch_to_new_gdt(0); -	/* We actually boot with all memory mapped, but let's say 128MB. */ -	max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT; -  	/*  	 * The Host<->Guest Switcher lives at the top of our address space, and  	 * the Host told us how big it is when we made LGUEST_INIT hypercall: diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index 4f420c2f2d5..e7d5382ef26 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S @@ -4,6 +4,7 @@  #include <asm/asm-offsets.h>  #include <asm/thread_info.h>  #include <asm/processor-flags.h> +#include <asm/pgtable.h>  /*G:020   * Our story starts with the kernel booting into startup_32 in @@ -37,9 +38,113 @@ ENTRY(lguest_entry)  	/* Set up the initial stack so we can run C code. */  	movl $(init_thread_union+THREAD_SIZE),%esp +	call init_pagetables +  	/* Jumps are relative: we're running __PAGE_OFFSET too low. */  	jmp lguest_init+__PAGE_OFFSET +/* + * Initialize page tables.  This creates a PDE and a set of page + * tables, which are located immediately beyond __brk_base.  The variable + * _brk_end is set up to point to the first "safe" location. + * Mappings are created both at virtual address 0 (identity mapping) + * and PAGE_OFFSET for up to _end. + * + * FIXME: This code is taken verbatim from arch/x86/kernel/head_32.S: they + * don't have a stack at this point, so we can't just use call and ret. + */ +init_pagetables: +#if PTRS_PER_PMD > 1 +#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD) +#else +#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) +#endif +#define pa(X) ((X) - __PAGE_OFFSET) + +/* Enough space to fit pagetables for the low memory linear map */ +MAPPING_BEYOND_END = \ +	PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT +#ifdef CONFIG_X86_PAE + +	/* +	 * In PAE mode initial_page_table is statically defined to contain +	 * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3 +	 * entries). The identity mapping is handled by pointing two PGD entries +	 * to the first kernel PMD. +	 * +	 * Note the upper half of each PMD or PTE are always zero at this stage. +	 */ + +#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */ + +	xorl %ebx,%ebx				/* %ebx is kept at zero */ + +	movl $pa(__brk_base), %edi +	movl $pa(initial_pg_pmd), %edx +	movl $PTE_IDENT_ATTR, %eax +10: +	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PMD entry */ +	movl %ecx,(%edx)			/* Store PMD entry */ +						/* Upper half already zero */ +	addl $8,%edx +	movl $512,%ecx +11: +	stosl +	xchgl %eax,%ebx +	stosl +	xchgl %eax,%ebx +	addl $0x1000,%eax +	loop 11b + +	/* +	 * End condition: we must map up to the end + MAPPING_BEYOND_END. +	 */ +	movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp +	cmpl %ebp,%eax +	jb 10b +1: +	addl $__PAGE_OFFSET, %edi +	movl %edi, pa(_brk_end) +	shrl $12, %eax +	movl %eax, pa(max_pfn_mapped) + +	/* Do early initialization of the fixmap area */ +	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax +	movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8) +#else	/* Not PAE */ + +page_pde_offset = (__PAGE_OFFSET >> 20); + +	movl $pa(__brk_base), %edi +	movl $pa(initial_page_table), %edx +	movl $PTE_IDENT_ATTR, %eax +10: +	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PDE entry */ +	movl %ecx,(%edx)			/* Store identity PDE entry */ +	movl %ecx,page_pde_offset(%edx)		/* Store kernel PDE entry */ +	addl $4,%edx +	movl $1024, %ecx +11: +	stosl +	addl $0x1000,%eax +	loop 11b +	/* +	 * End condition: we must map up to the end + MAPPING_BEYOND_END. +	 */ +	movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp +	cmpl %ebp,%eax +	jb 10b +	addl $__PAGE_OFFSET, %edi +	movl %edi, pa(_brk_end) +	shrl $12, %eax +	movl %eax, pa(max_pfn_mapped) + +	/* Do early initialization of the fixmap area */ +	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax +	movl %eax,pa(initial_page_table+0xffc) +#endif +	ret +  /*G:055   * We create a macro which puts the assembler code between lgstart_ and lgend_   * markers.  These templates are put in the .text section: they can't be diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index c4bb261c106..b1805b78842 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -65,21 +65,13 @@ pcibios_align_resource(void *data, const struct resource *res,  			resource_size_t size, resource_size_t align)  {  	struct pci_dev *dev = data; -	resource_size_t start = round_down(res->end - size + 1, align); +	resource_size_t start = res->start;  	if (res->flags & IORESOURCE_IO) { - -		/* -		 * If we're avoiding ISA aliases, the largest contiguous I/O -		 * port space is 256 bytes.  Clearing bits 9 and 10 preserves -		 * all 256-byte and smaller alignments, so the result will -		 * still be correctly aligned. -		 */ -		if (!skip_isa_ioresource_align(dev)) -			start &= ~0x300; -	} else if (res->flags & IORESOURCE_MEM) { -		if (start < BIOS_END) -			start = res->end;	/* fail; no space */ +		if (skip_isa_ioresource_align(dev)) +			return start; +		if (start & 0x300) +			start = (start + 0x3ff) & ~0x3ff;  	}  	return start;  } diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile index 4a2afa1bac5..b6552b189bc 100644 --- a/arch/x86/vdso/Makefile +++ b/arch/x86/vdso/Makefile @@ -25,7 +25,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)  export CPPFLAGS_vdso.lds += -P -C -VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \ +VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \  		      	-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096  $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so @@ -69,7 +69,7 @@ vdso32.so-$(VDSO32-y)		+= sysenter  vdso32-images			= $(vdso32.so-y:%=vdso32-%.so)  CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds) -VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1 +VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1  # This makes sure the $(obj) subdirectory exists even though vdso32/  # is not a kbuild sub-make subdirectory. diff --git a/block/blk-map.c b/block/blk-map.c index 5d5dbe47c22..e663ac2d8e6 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -201,12 +201,13 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,  	for (i = 0; i < iov_count; i++) {  		unsigned long uaddr = (unsigned long)iov[i].iov_base; +		if (!iov[i].iov_len) +			return -EINVAL; +  		if (uaddr & queue_dma_alignment(q)) {  			unaligned = 1;  			break;  		} -		if (!iov[i].iov_len) -			return -EINVAL;  	}  	if (unaligned || (q->dma_pad_mask & len) || map_data) diff --git a/block/blk-merge.c b/block/blk-merge.c index 77b7c26df6b..74bc4a768f3 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -21,7 +21,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,  		return 0;  	fbio = bio; -	cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); +	cluster = blk_queue_cluster(q);  	seg_size = 0;  	nr_phys_segs = 0;  	for_each_bio(bio) { @@ -87,7 +87,7 @@ EXPORT_SYMBOL(blk_recount_segments);  static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,  				   struct bio *nxt)  { -	if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) +	if (!blk_queue_cluster(q))  		return 0;  	if (bio->bi_seg_back_size + nxt->bi_seg_front_size > @@ -123,7 +123,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,  	int nsegs, cluster;  	nsegs = 0; -	cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); +	cluster = blk_queue_cluster(q);  	/*  	 * for each bio in rq diff --git a/block/blk-settings.c b/block/blk-settings.c index 701859fb964..36c8c1f2af1 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -126,7 +126,7 @@ void blk_set_default_limits(struct queue_limits *lim)  	lim->alignment_offset = 0;  	lim->io_opt = 0;  	lim->misaligned = 0; -	lim->no_cluster = 0; +	lim->cluster = 1;  }  EXPORT_SYMBOL(blk_set_default_limits); @@ -229,8 +229,8 @@ void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask)  EXPORT_SYMBOL(blk_queue_bounce_limit);  /** - * blk_queue_max_hw_sectors - set max sectors for a request for this queue - * @q:  the request queue for the device + * blk_limits_max_hw_sectors - set hard and soft limit of max sectors for request + * @limits: the queue limits   * @max_hw_sectors:  max hardware sectors in the usual 512b unit   *   * Description: @@ -244,7 +244,7 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);   *    per-device basis in /sys/block/<device>/queue/max_sectors_kb.   *    The soft limit can not exceed max_hw_sectors.   **/ -void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors) +void blk_limits_max_hw_sectors(struct queue_limits *limits, unsigned int max_hw_sectors)  {  	if ((max_hw_sectors << 9) < PAGE_CACHE_SIZE) {  		max_hw_sectors = 1 << (PAGE_CACHE_SHIFT - 9); @@ -252,9 +252,23 @@ void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_secto  		       __func__, max_hw_sectors);  	} -	q->limits.max_hw_sectors = max_hw_sectors; -	q->limits.max_sectors = min_t(unsigned int, max_hw_sectors, -				      BLK_DEF_MAX_SECTORS); +	limits->max_hw_sectors = max_hw_sectors; +	limits->max_sectors = min_t(unsigned int, max_hw_sectors, +				    BLK_DEF_MAX_SECTORS); +} +EXPORT_SYMBOL(blk_limits_max_hw_sectors); + +/** + * blk_queue_max_hw_sectors - set max sectors for a request for this queue + * @q:  the request queue for the device + * @max_hw_sectors:  max hardware sectors in the usual 512b unit + * + * Description: + *    See description for blk_limits_max_hw_sectors(). + **/ +void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors) +{ +	blk_limits_max_hw_sectors(&q->limits, max_hw_sectors);  }  EXPORT_SYMBOL(blk_queue_max_hw_sectors); @@ -464,15 +478,6 @@ EXPORT_SYMBOL(blk_queue_io_opt);  void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)  {  	blk_stack_limits(&t->limits, &b->limits, 0); - -	if (!t->queue_lock) -		WARN_ON_ONCE(1); -	else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) { -		unsigned long flags; -		spin_lock_irqsave(t->queue_lock, flags); -		queue_flag_clear(QUEUE_FLAG_CLUSTER, t); -		spin_unlock_irqrestore(t->queue_lock, flags); -	}  }  EXPORT_SYMBOL(blk_queue_stack_limits); @@ -545,7 +550,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,  	t->io_min = max(t->io_min, b->io_min);  	t->io_opt = lcm(t->io_opt, b->io_opt); -	t->no_cluster |= b->no_cluster; +	t->cluster &= b->cluster;  	t->discard_zeroes_data &= b->discard_zeroes_data;  	/* Physical block size a multiple of the logical block size? */ @@ -641,7 +646,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,  		       sector_t offset)  {  	struct request_queue *t = disk->queue; -	struct request_queue *b = bdev_get_queue(bdev);  	if (bdev_stack_limits(&t->limits, bdev, offset >> 9) < 0) {  		char top[BDEVNAME_SIZE], bottom[BDEVNAME_SIZE]; @@ -652,17 +656,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,  		printk(KERN_NOTICE "%s: Warning: Device %s is misaligned\n",  		       top, bottom);  	} - -	if (!t->queue_lock) -		WARN_ON_ONCE(1); -	else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) { -		unsigned long flags; - -		spin_lock_irqsave(t->queue_lock, flags); -		if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) -			queue_flag_clear(QUEUE_FLAG_CLUSTER, t); -		spin_unlock_irqrestore(t->queue_lock, flags); -	}  }  EXPORT_SYMBOL(disk_stack_limits); diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 013457f47fd..41fb69150b4 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -119,7 +119,7 @@ static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *  static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)  { -	if (test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) +	if (blk_queue_cluster(q))  		return queue_var_show(queue_max_segment_size(q), (page));  	return queue_var_show(PAGE_CACHE_SIZE, (page)); diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 004be80fd89..381b09bb562 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -355,6 +355,12 @@ throtl_start_new_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)  			tg->slice_end[rw], jiffies);  } +static inline void throtl_set_slice_end(struct throtl_data *td, +		struct throtl_grp *tg, bool rw, unsigned long jiffy_end) +{ +	tg->slice_end[rw] = roundup(jiffy_end, throtl_slice); +} +  static inline void throtl_extend_slice(struct throtl_data *td,  		struct throtl_grp *tg, bool rw, unsigned long jiffy_end)  { @@ -391,6 +397,16 @@ throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)  	if (throtl_slice_used(td, tg, rw))  		return; +	/* +	 * A bio has been dispatched. Also adjust slice_end. It might happen +	 * that initially cgroup limit was very low resulting in high +	 * slice_end, but later limit was bumped up and bio was dispached +	 * sooner, then we need to reduce slice_end. A high bogus slice_end +	 * is bad because it does not allow new slice to start. +	 */ + +	throtl_set_slice_end(td, tg, rw, jiffies + throtl_slice); +  	time_elapsed = jiffies - tg->slice_start[rw];  	nr_slices = time_elapsed / throtl_slice; @@ -709,26 +725,21 @@ static void throtl_process_limit_change(struct throtl_data *td)  	struct throtl_grp *tg;  	struct hlist_node *pos, *n; -	/* -	 * Make sure atomic_inc() effects from -	 * throtl_update_blkio_group_read_bps(), group of functions are -	 * visible. -	 * Is this required or smp_mb__after_atomic_inc() was suffcient -	 * after the atomic_inc(). -	 */ -	smp_rmb();  	if (!atomic_read(&td->limits_changed))  		return;  	throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed)); -	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) { -		/* -		 * Do I need an smp_rmb() here to make sure tg->limits_changed -		 * update is visible. I am relying on smp_rmb() at the -		 * beginning of function and not putting a new one here. -		 */ +	/* +	 * Make sure updates from throtl_update_blkio_group_read_bps() group +	 * of functions to tg->limits_changed are visible. We do not +	 * want update td->limits_changed to be visible but update to +	 * tg->limits_changed not being visible yet on this cpu. Hence +	 * the read barrier. +	 */ +	smp_rmb(); +	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {  		if (throtl_tg_on_rr(tg) && tg->limits_changed) {  			throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"  				" riops=%u wiops=%u", tg->bps[READ], diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index f291587d753..8e0f9256eb5 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2834,6 +2834,8 @@ static int cciss_revalidate(struct gendisk *disk)  	InquiryData_struct *inq_buff = NULL;  	for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { +		if (!h->drv[logvol]) +			continue;  		if (memcmp(h->drv[logvol]->LunID, drv->LunID,  			sizeof(drv->LunID)) == 0) {  			FOUND = 1; diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 89d8a7cc405..24487d4fb20 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3627,17 +3627,19 @@ static void drbdd(struct drbd_conf *mdev)  		}  		shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header); -		rv = drbd_recv(mdev, &header->h80.payload, shs); -		if (unlikely(rv != shs)) { -			dev_err(DEV, "short read while reading sub header: rv=%d\n", rv); -			goto err_out; -		} -  		if (packet_size - shs > 0 && !drbd_cmd_handler[cmd].expect_payload) {  			dev_err(DEV, "No payload expected %s l:%d\n", cmdname(cmd), packet_size);  			goto err_out;  		} +		if (shs) { +			rv = drbd_recv(mdev, &header->h80.payload, shs); +			if (unlikely(rv != shs)) { +				dev_err(DEV, "short read while reading sub header: rv=%d\n", rv); +				goto err_out; +			} +		} +  		rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs);  		if (unlikely(!rv)) { diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 181ea036482..ab2bd09d54b 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h @@ -339,7 +339,8 @@ static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)  }  /* completion of master bio is outside of spinlock. - * If you need it irqsave, do it your self! */ + * If you need it irqsave, do it your self! + * Which means: don't use from bio endio callback. */  static inline int req_mod(struct drbd_request *req,  		enum drbd_req_event what)  { diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 47d223c2409..34f224b018b 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -193,8 +193,10 @@ void drbd_endio_sec(struct bio *bio, int error)   */  void drbd_endio_pri(struct bio *bio, int error)  { +	unsigned long flags;  	struct drbd_request *req = bio->bi_private;  	struct drbd_conf *mdev = req->mdev; +	struct bio_and_error m;  	enum drbd_req_event what;  	int uptodate = bio_flagged(bio, BIO_UPTODATE); @@ -220,7 +222,13 @@ void drbd_endio_pri(struct bio *bio, int error)  	bio_put(req->private_bio);  	req->private_bio = ERR_PTR(error); -	req_mod(req, what); +	/* not req_mod(), we need irqsave here! */ +	spin_lock_irqsave(&mdev->req_lock, flags); +	__req_mod(req, what, &m); +	spin_unlock_irqrestore(&mdev->req_lock, flags); + +	if (m.bio) +		complete_master_bio(mdev, &m);  }  int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index d68d3aa1814..f975d24890f 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -283,16 +283,21 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,  	} while (delay);  } -static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) +static void __sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)  { -	unsigned long flags; -  	if (delta > p->max_match_value)  		dev_warn(&p->pdev->dev, "delta out of range\n"); -	spin_lock_irqsave(&p->lock, flags);  	p->next_match_value = delta;  	sh_cmt_clock_event_program_verify(p, 0); +} + +static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) +{ +	unsigned long flags; + +	spin_lock_irqsave(&p->lock, flags); +	__sh_cmt_set_next(p, delta);  	spin_unlock_irqrestore(&p->lock, flags);  } @@ -359,7 +364,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)  	/* setup timeout if no clockevent */  	if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT))) -		sh_cmt_set_next(p, p->max_match_value); +		__sh_cmt_set_next(p, p->max_match_value);   out:  	spin_unlock_irqrestore(&p->lock, flags); @@ -381,7 +386,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)  	/* adjust the timeout to maximum if only clocksource left */  	if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE)) -		sh_cmt_set_next(p, p->max_match_value); +		__sh_cmt_set_next(p, p->max_match_value);  	spin_unlock_irqrestore(&p->lock, flags);  } diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e3f7fc6f956..68f09a86843 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -534,76 +534,73 @@ static int handle_eviocgbit(struct input_dev *dev,  }  #undef OLD_KEY_MAX -static int evdev_handle_get_keycode(struct input_dev *dev, -				    void __user *p, size_t size) +static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p)  { -	struct input_keymap_entry ke; +	struct input_keymap_entry ke = { +		.len	= sizeof(unsigned int), +		.flags	= 0, +	}; +	int __user *ip = (int __user *)p;  	int error; -	memset(&ke, 0, sizeof(ke)); - -	if (size == sizeof(unsigned int[2])) { -		/* legacy case */ -		int __user *ip = (int __user *)p; +	/* legacy case */ +	if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) +		return -EFAULT; -		if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) -			return -EFAULT; +	error = input_get_keycode(dev, &ke); +	if (error) +		return error; -		ke.len = sizeof(unsigned int); -		ke.flags = 0; +	if (put_user(ke.keycode, ip + 1)) +		return -EFAULT; -		error = input_get_keycode(dev, &ke); -		if (error) -			return error; +	return 0; +} -		if (put_user(ke.keycode, ip + 1)) -			return -EFAULT; +static int evdev_handle_get_keycode_v2(struct input_dev *dev, void __user *p) +{ +	struct input_keymap_entry ke; +	int error; -	} else { -		size = min(size, sizeof(ke)); +	if (copy_from_user(&ke, p, sizeof(ke))) +		return -EFAULT; -		if (copy_from_user(&ke, p, size)) -			return -EFAULT; +	error = input_get_keycode(dev, &ke); +	if (error) +		return error; -		error = input_get_keycode(dev, &ke); -		if (error) -			return error; +	if (copy_to_user(p, &ke, sizeof(ke))) +		return -EFAULT; -		if (copy_to_user(p, &ke, size)) -			return -EFAULT; -	}  	return 0;  } -static int evdev_handle_set_keycode(struct input_dev *dev, -				    void __user *p, size_t size) +static int evdev_handle_set_keycode(struct input_dev *dev, void __user *p)  { -	struct input_keymap_entry ke; - -	memset(&ke, 0, sizeof(ke)); +	struct input_keymap_entry ke = { +		.len	= sizeof(unsigned int), +		.flags	= 0, +	}; +	int __user *ip = (int __user *)p; -	if (size == sizeof(unsigned int[2])) { -		/* legacy case */ -		int __user *ip = (int __user *)p; +	if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) +		return -EFAULT; -		if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) -			return -EFAULT; +	if (get_user(ke.keycode, ip + 1)) +		return -EFAULT; -		if (get_user(ke.keycode, ip + 1)) -			return -EFAULT; +	return input_set_keycode(dev, &ke); +} -		ke.len = sizeof(unsigned int); -		ke.flags = 0; +static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) +{ +	struct input_keymap_entry ke; -	} else { -		size = min(size, sizeof(ke)); +	if (copy_from_user(&ke, p, sizeof(ke))) +		return -EFAULT; -		if (copy_from_user(&ke, p, size)) -			return -EFAULT; - -		if (ke.len > sizeof(ke.scancode)) -			return -EINVAL; -	} +	if (ke.len > sizeof(ke.scancode)) +		return -EINVAL;  	return input_set_keycode(dev, &ke);  } @@ -669,6 +666,18 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,  			return evdev_grab(evdev, client);  		else  			return evdev_ungrab(evdev, client); + +	case EVIOCGKEYCODE: +		return evdev_handle_get_keycode(dev, p); + +	case EVIOCSKEYCODE: +		return evdev_handle_set_keycode(dev, p); + +	case EVIOCGKEYCODE_V2: +		return evdev_handle_get_keycode_v2(dev, p); + +	case EVIOCSKEYCODE_V2: +		return evdev_handle_set_keycode_v2(dev, p);  	}  	size = _IOC_SIZE(cmd); @@ -708,12 +717,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,  			return -EFAULT;  		return error; - -	case EVIOC_MASK_SIZE(EVIOCGKEYCODE): -		return evdev_handle_get_keycode(dev, p, size); - -	case EVIOC_MASK_SIZE(EVIOCSKEYCODE): -		return evdev_handle_set_keycode(dev, p, size);  	}  	/* Multi-number variable-length handlers */ diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 4852b440960..435b0af401e 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1436,6 +1436,8 @@ static struct wacom_features wacom_features_0xD2 =  	{ "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };  static struct wacom_features wacom_features_0xD3 =  	{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023, 63, BAMBOO_PT }; +static const struct wacom_features wacom_features_0xD4 = +	{ "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200,  255, 63, BAMBOO_PT };  static struct wacom_features wacom_features_0xD8 =  	{ "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13530, 1023, 63, BAMBOO_PT };  static struct wacom_features wacom_features_0xDA = @@ -1510,6 +1512,7 @@ const struct usb_device_id wacom_ids[] = {  	{ USB_DEVICE_WACOM(0xD1) },  	{ USB_DEVICE_WACOM(0xD2) },  	{ USB_DEVICE_WACOM(0xD3) }, +	{ USB_DEVICE_WACOM(0xD4) },  	{ USB_DEVICE_WACOM(0xD8) },  	{ USB_DEVICE_WACOM(0xDA) },  	{ USB_DEVICE_WACOM(0xDB) }, diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 90267f8d64e..4d705cea0f8 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -517,9 +517,8 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,  	 */  	if (q->merge_bvec_fn && !ti->type->merge) -		limits->max_sectors = -			min_not_zero(limits->max_sectors, -				     (unsigned int) (PAGE_SIZE >> 9)); +		blk_limits_max_hw_sectors(limits, +					  (unsigned int) (PAGE_SIZE >> 9));  	return 0;  }  EXPORT_SYMBOL_GPL(dm_set_device_limits); @@ -1131,11 +1130,6 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,  	 */  	q->limits = *limits; -	if (limits->no_cluster) -		queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q); -	else -		queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); -  	if (!dm_table_supports_discards(t))  		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);  	else diff --git a/drivers/md/md.c b/drivers/md/md.c index e71c5fa527f..175c424f201 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4295,9 +4295,6 @@ static int md_alloc(dev_t dev, char *name)  		goto abort;  	mddev->queue->queuedata = mddev; -	/* Can be unlocked because the queue is new: no concurrency */ -	queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, mddev->queue); -  	blk_queue_make_request(mddev->queue, md_make_request);  	disk = alloc_disk(1 << shift); diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c index 05bde9ccb77..1d1d8d20075 100644 --- a/drivers/media/common/saa7146_hlp.c +++ b/drivers/media/common/saa7146_hlp.c @@ -558,7 +558,7 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e  static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)  {  	struct saa7146_vv *vv = dev->vv_data; -	struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat); +	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat);  	int b_depth = vv->ov_fmt->depth;  	int b_bpl = vv->ov_fb.fmt.bytesperline; @@ -702,7 +702,7 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71  	struct saa7146_vv *vv = dev->vv_data;  	struct saa7146_video_dma vdma1; -	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); +	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);  	int width = buf->fmt->width;  	int height = buf->fmt->height; @@ -827,7 +827,7 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71  	struct saa7146_video_dma vdma2;  	struct saa7146_video_dma vdma3; -	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); +	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);  	int width = buf->fmt->width;  	int height = buf->fmt->height; @@ -994,7 +994,7 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar)  void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)  { -	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); +	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);  	struct saa7146_vv *vv = dev->vv_data;  	u32 vdma1_prot_addr; diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 741c5732b43..d246910129e 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -84,7 +84,7 @@ static struct saa7146_format formats[] = {  static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format); -struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc) +struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc)  {  	int i, j = NUM_FORMATS; @@ -266,7 +266,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu  	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);  	struct scatterlist *list = dma->sglist;  	int length = dma->sglen; -	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); +	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);  	DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length)); @@ -408,7 +408,7 @@ static int video_begin(struct saa7146_fh *fh)  		}  	} -	fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); +	fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);  	/* we need to have a valid format set here */  	BUG_ON(NULL == fmt); @@ -460,7 +460,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file)  		return -EBUSY;  	} -	fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); +	fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);  	/* we need to have a valid format set here */  	BUG_ON(NULL == fmt); @@ -536,7 +536,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f  		return -EPERM;  	/* check args */ -	fmt = format_by_fourcc(dev, fb->fmt.pixelformat); +	fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat);  	if (NULL == fmt)  		return -EINVAL; @@ -760,7 +760,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma  	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh)); -	fmt = format_by_fourcc(dev, f->fmt.pix.pixelformat); +	fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);  	if (NULL == fmt)  		return -EINVAL; @@ -1264,7 +1264,7 @@ static int buffer_prepare(struct videobuf_queue *q,  		buf->fmt       = &fh->video_fmt;  		buf->vb.field  = fh->video_fmt.field; -		sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); +		sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);  		release_all_pagetables(dev, buf);  		if( 0 != IS_PLANAR(sfmt->trans)) { @@ -1378,7 +1378,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)  	fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;  	fh->video_fmt.bytesperline = 0;  	fh->video_fmt.field = V4L2_FIELD_ANY; -	sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); +	sfmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);  	fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;  	videobuf_queue_sg_init(&fh->video_q, &video_qops, diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 5bf4985daed..05e832f61c3 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -361,7 +361,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations rtrack_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops rtrack_ioctl_ops = { @@ -412,13 +412,6 @@ static int __init rtrack_init(void)  	rt->vdev.release = video_device_release_empty;  	video_set_drvdata(&rt->vdev, rt); -	if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -		v4l2_device_unregister(&rt->v4l2_dev); -		release_region(rt->io, 2); -		return -EINVAL; -	} -	v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n"); -  	/* Set up the I/O locking */  	mutex_init(&rt->lock); @@ -430,6 +423,13 @@ static int __init rtrack_init(void)  	sleep_delay(2000000);	/* make sure it's totally down	*/  	outb(0xc0, rt->io);		/* steady volume, mute card	*/ +	if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +		v4l2_device_unregister(&rt->v4l2_dev); +		release_region(rt->io, 2); +		return -EINVAL; +	} +	v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n"); +  	return 0;  } diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index c2231139362..dd8a6ab0d43 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -324,7 +324,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,  static const struct v4l2_file_operations aztech_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops aztech_ioctl_ops = { @@ -375,6 +375,8 @@ static int __init aztech_init(void)  	az->vdev.ioctl_ops = &aztech_ioctl_ops;  	az->vdev.release = video_device_release_empty;  	video_set_drvdata(&az->vdev, az); +	/* mute card - prevents noisy bootups */ +	outb(0, az->io);  	if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {  		v4l2_device_unregister(v4l2_dev); @@ -383,8 +385,6 @@ static int __init aztech_init(void)  	}  	v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); -	/* mute card - prevents noisy bootups */ -	outb(0, az->io);  	return 0;  } diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index b701ea6e7c7..bc9ad0897c5 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -328,11 +328,10 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo  	unsigned char readbuf[RDS_BUFFER];  	int i = 0; +	mutex_lock(&dev->lock);  	if (dev->rdsstat == 0) { -		mutex_lock(&dev->lock);  		dev->rdsstat = 1;  		outb(0x80, dev->io);        /* Select RDS fifo */ -		mutex_unlock(&dev->lock);  		init_timer(&dev->readtimer);  		dev->readtimer.function = cadet_handler;  		dev->readtimer.data = (unsigned long)dev; @@ -340,12 +339,15 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo  		add_timer(&dev->readtimer);  	}  	if (dev->rdsin == dev->rdsout) { +		mutex_unlock(&dev->lock);  		if (file->f_flags & O_NONBLOCK)  			return -EWOULDBLOCK;  		interruptible_sleep_on(&dev->read_queue); +		mutex_lock(&dev->lock);  	}  	while (i < count && dev->rdsin != dev->rdsout)  		readbuf[i++] = dev->rdsbuf[dev->rdsout++]; +	mutex_unlock(&dev->lock);  	if (copy_to_user(data, readbuf, i))  		return -EFAULT; @@ -525,9 +527,11 @@ static int cadet_open(struct file *file)  {  	struct cadet *dev = video_drvdata(file); +	mutex_lock(&dev->lock);  	dev->users++;  	if (1 == dev->users)  		init_waitqueue_head(&dev->read_queue); +	mutex_unlock(&dev->lock);  	return 0;  } @@ -535,11 +539,13 @@ static int cadet_release(struct file *file)  {  	struct cadet *dev = video_drvdata(file); +	mutex_lock(&dev->lock);  	dev->users--;  	if (0 == dev->users) {  		del_timer_sync(&dev->readtimer);  		dev->rdsstat = 0;  	} +	mutex_unlock(&dev->lock);  	return 0;  } @@ -559,7 +565,7 @@ static const struct v4l2_file_operations cadet_fops = {  	.open		= cadet_open,  	.release       	= cadet_release,  	.read		= cadet_read, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  	.poll		= cadet_poll,  }; diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index 79039674a0e..28fa85ba208 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c @@ -361,7 +361,7 @@ MODULE_DEVICE_TABLE(pci, gemtek_pci_id);  static const struct v4l2_file_operations gemtek_pci_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = { @@ -422,11 +422,11 @@ static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_dev  	card->vdev.release = video_device_release_empty;  	video_set_drvdata(&card->vdev, card); +	gemtek_pci_mute(card); +  	if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0)  		goto err_video; -	gemtek_pci_mute(card); -  	v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",  		pdev->revision, card->iobase, card->iobase + card->length - 1); diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 73985f641f0..259936422e4 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -378,7 +378,7 @@ static int gemtek_probe(struct gemtek *gt)  static const struct v4l2_file_operations gemtek_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static int vidioc_querycap(struct file *file, void *priv, @@ -577,12 +577,6 @@ static int __init gemtek_init(void)  	gt->vdev.release = video_device_release_empty;  	video_set_drvdata(>->vdev, gt); -	if (video_register_device(>->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -		v4l2_device_unregister(v4l2_dev); -		release_region(gt->io, 1); -		return -EBUSY; -	} -  	/* Set defaults */  	gt->lastfreq = GEMTEK_LOWFREQ;  	gt->bu2614data = 0; @@ -590,6 +584,12 @@ static int __init gemtek_init(void)  	if (initmute)  		gemtek_mute(gt); +	if (video_register_device(>->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +		v4l2_device_unregister(v4l2_dev); +		release_region(gt->io, 1); +		return -EBUSY; +	} +  	return 0;  } diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 08f1051979c..6af61bfeb17 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -299,7 +299,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations maestro_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops maestro_ioctl_ops = { @@ -383,22 +383,20 @@ static int __devinit maestro_probe(struct pci_dev *pdev,  	dev->vdev.release = video_device_release_empty;  	video_set_drvdata(&dev->vdev, dev); +	if (!radio_power_on(dev)) { +		retval = -EIO; +		goto errfr1; +	} +  	retval = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr);  	if (retval) {  		v4l2_err(v4l2_dev, "can't register video device!\n");  		goto errfr1;  	} -	if (!radio_power_on(dev)) { -		retval = -EIO; -		goto errunr; -	} -  	v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n");  	return 0; -errunr: -	video_unregister_device(&dev->vdev);  errfr1:  	v4l2_device_unregister(v4l2_dev);  errfr: diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 255d40df4b4..6459a220b0d 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -346,7 +346,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,  static const struct v4l2_file_operations maxiradio_fops = {  	.owner		= THIS_MODULE, -	.ioctl          = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  };  static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c index 4ff885445fd..3fb76e3834c 100644 --- a/drivers/media/radio/radio-miropcm20.c +++ b/drivers/media/radio/radio-miropcm20.c @@ -33,6 +33,7 @@ struct pcm20 {  	unsigned long freq;  	int muted;  	struct snd_miro_aci *aci; +	struct mutex lock;  };  static struct pcm20 pcm20_card = { @@ -72,7 +73,7 @@ static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq)  static const struct v4l2_file_operations pcm20_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static int vidioc_querycap(struct file *file, void *priv, @@ -229,7 +230,7 @@ static int __init pcm20_init(void)  		return -ENODEV;  	}  	strlcpy(v4l2_dev->name, "miropcm20", sizeof(v4l2_dev->name)); - +	mutex_init(&dev->lock);  	res = v4l2_device_register(NULL, v4l2_dev);  	if (res < 0) { @@ -242,6 +243,7 @@ static int __init pcm20_init(void)  	dev->vdev.fops = &pcm20_fops;  	dev->vdev.ioctl_ops = &pcm20_ioctl_ops;  	dev->vdev.release = video_device_release_empty; +	dev->vdev.lock = &dev->lock;  	video_set_drvdata(&dev->vdev, dev);  	if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index a79296aac9a..8d6ea591bd1 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -266,7 +266,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations rtrack2_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = { @@ -315,6 +315,10 @@ static int __init rtrack2_init(void)  	dev->vdev.release = video_device_release_empty;  	video_set_drvdata(&dev->vdev, dev); +	/* mute card - prevents noisy bootups */ +	outb(1, dev->io); +	dev->muted = 1; +  	mutex_init(&dev->lock);  	if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {  		v4l2_device_unregister(v4l2_dev); @@ -324,10 +328,6 @@ static int __init rtrack2_init(void)  	v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n"); -	/* mute card - prevents noisy bootups */ -	outb(1, dev->io); -	dev->muted = 1; -  	return 0;  } diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 985359d18aa..b5a5f89e238 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -260,7 +260,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations fmi_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops fmi_ioctl_ops = { @@ -382,6 +382,9 @@ static int __init fmi_init(void)  	mutex_init(&fmi->lock); +	/* mute card - prevents noisy bootups */ +	fmi_mute(fmi); +  	if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {  		v4l2_device_unregister(v4l2_dev);  		release_region(fmi->io, 2); @@ -391,8 +394,6 @@ static int __init fmi_init(void)  	}  	v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io); -	/* mute card - prevents noisy bootups */ -	fmi_mute(fmi);  	return 0;  } diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 52c7bbb32b8..dc3f04c52d5 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -376,7 +376,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations fmr2_fops = {  	.owner          = THIS_MODULE, -	.ioctl          = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  };  static const struct v4l2_ioctl_ops fmr2_ioctl_ops = { @@ -424,6 +424,10 @@ static int __init fmr2_init(void)  	fmr2->vdev.release = video_device_release_empty;  	video_set_drvdata(&fmr2->vdev, fmr2); +	/* mute card - prevents noisy bootups */ +	fmr2_mute(fmr2->io); +	fmr2_product_info(fmr2); +  	if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {  		v4l2_device_unregister(v4l2_dev);  		release_region(fmr2->io, 2); @@ -431,11 +435,6 @@ static int __init fmr2_init(void)  	}  	v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io); -	/* mute card - prevents noisy bootups */ -	mutex_lock(&fmr2->lock); -	fmr2_mute(fmr2->io); -	fmr2_product_info(fmr2); -	mutex_unlock(&fmr2->lock);  	debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type));  	return 0;  } diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c index 03829e6818b..726d367ad8d 100644 --- a/drivers/media/radio/radio-si4713.c +++ b/drivers/media/radio/radio-si4713.c @@ -53,7 +53,8 @@ struct radio_si4713_device {  /* radio_si4713_fops - file operations interface */  static const struct v4l2_file_operations radio_si4713_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	/* Note: locking is done at the subdev level in the i2c driver. */ +	.unlocked_ioctl	= video_ioctl2,  };  /* Video4Linux Interface */ diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 789d2ec66e1..0e71d816c72 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -142,7 +142,6 @@ struct tea5764_device {  	struct video_device		*videodev;  	struct tea5764_regs		regs;  	struct mutex			mutex; -	int				users;  };  /* I2C code related */ @@ -458,41 +457,10 @@ static int vidioc_s_audio(struct file *file, void *priv,  	return 0;  } -static int tea5764_open(struct file *file) -{ -	/* Currently we support only one device */ -	struct tea5764_device *radio = video_drvdata(file); - -	mutex_lock(&radio->mutex); -	/* Only exclusive access */ -	if (radio->users) { -		mutex_unlock(&radio->mutex); -		return -EBUSY; -	} -	radio->users++; -	mutex_unlock(&radio->mutex); -	file->private_data = radio; -	return 0; -} - -static int tea5764_close(struct file *file) -{ -	struct tea5764_device *radio = video_drvdata(file); - -	if (!radio) -		return -ENODEV; -	mutex_lock(&radio->mutex); -	radio->users--; -	mutex_unlock(&radio->mutex); -	return 0; -} -  /* File system interface */  static const struct v4l2_file_operations tea5764_fops = {  	.owner		= THIS_MODULE, -	.open           = tea5764_open, -	.release        = tea5764_close, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops tea5764_ioctl_ops = { @@ -527,7 +495,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,  	int ret;  	PDEBUG("probe"); -	radio = kmalloc(sizeof(struct tea5764_device), GFP_KERNEL); +	radio = kzalloc(sizeof(struct tea5764_device), GFP_KERNEL);  	if (!radio)  		return -ENOMEM; @@ -555,12 +523,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,  	i2c_set_clientdata(client, radio);  	video_set_drvdata(radio->videodev, radio); - -	ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); -	if (ret < 0) { -		PWARN("Could not register video device!"); -		goto errrel; -	} +	radio->videodev->lock = &radio->mutex;  	/* initialize and power off the chip */  	tea5764_i2c_read(radio); @@ -568,6 +531,12 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,  	tea5764_mute(radio, 1);  	tea5764_power_down(radio); +	ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); +	if (ret < 0) { +		PWARN("Could not register video device!"); +		goto errrel; +	} +  	PINFO("registered.");  	return 0;  errrel: diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index fc1c860fd43..a3266391705 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c @@ -338,7 +338,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations terratec_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops terratec_ioctl_ops = { @@ -389,6 +389,9 @@ static int __init terratec_init(void)  	mutex_init(&tt->lock); +	/* mute card - prevents noisy bootups */ +	tt_write_vol(tt, 0); +  	if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {  		v4l2_device_unregister(&tt->v4l2_dev);  		release_region(tt->io, 2); @@ -396,9 +399,6 @@ static int __init terratec_init(void)  	}  	v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n"); - -	/* mute card - prevents noisy bootups */ -	tt_write_vol(tt, 0);  	return 0;  } diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index b8bb3ef47df..a185610b376 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c @@ -34,6 +34,7 @@ struct timbradio {  	struct v4l2_subdev	*sd_dsp;  	struct video_device	video_dev;  	struct v4l2_device	v4l2_dev; +	struct mutex		lock;  }; @@ -142,7 +143,7 @@ static const struct v4l2_ioctl_ops timbradio_ioctl_ops = {  static const struct v4l2_file_operations timbradio_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static int __devinit timbradio_probe(struct platform_device *pdev) @@ -164,6 +165,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)  	}  	tr->pdata = *pdata; +	mutex_init(&tr->lock);  	strlcpy(tr->video_dev.name, "Timberdale Radio",  		sizeof(tr->video_dev.name)); @@ -171,6 +173,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)  	tr->video_dev.ioctl_ops = &timbradio_ioctl_ops;  	tr->video_dev.release = video_device_release_empty;  	tr->video_dev.minor = -1; +	tr->video_dev.lock = &tr->lock;  	strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));  	err = v4l2_device_register(NULL, &tr->v4l2_dev); diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c index 9d6dcf8af5b..22fa9cc28ab 100644 --- a/drivers/media/radio/radio-trust.c +++ b/drivers/media/radio/radio-trust.c @@ -344,7 +344,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations trust_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops trust_ioctl_ops = { @@ -396,14 +396,6 @@ static int __init trust_init(void)  	tr->vdev.release = video_device_release_empty;  	video_set_drvdata(&tr->vdev, tr); -	if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -		v4l2_device_unregister(v4l2_dev); -		release_region(tr->io, 2); -		return -EINVAL; -	} - -	v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n"); -  	write_i2c(tr, 2, TDA7318_ADDR, 0x80);	/* speaker att. LF = 0 dB */  	write_i2c(tr, 2, TDA7318_ADDR, 0xa0);	/* speaker att. RF = 0 dB */  	write_i2c(tr, 2, TDA7318_ADDR, 0xc0);	/* speaker att. LR = 0 dB */ @@ -418,6 +410,14 @@ static int __init trust_init(void)  	/* mute card - prevents noisy bootups */  	tr_setmute(tr, 1); +	if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +		v4l2_device_unregister(v4l2_dev); +		release_region(tr->io, 2); +		return -EINVAL; +	} + +	v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n"); +  	return 0;  } diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index b1f630527dc..8dbbf08f220 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -317,7 +317,7 @@ static int vidioc_log_status(struct file *file, void *priv)  static const struct v4l2_file_operations typhoon_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops typhoon_ioctl_ops = { @@ -344,18 +344,18 @@ static int __init typhoon_init(void)  	strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name));  	dev->io = io; -	dev->curfreq = dev->mutefreq = mutefreq;  	if (dev->io == -1) {  		v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316 or io=0x336\n");  		return -EINVAL;  	} -	if (dev->mutefreq < 87000 || dev->mutefreq > 108500) { +	if (mutefreq < 87000 || mutefreq > 108500) {  		v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when muting the card,\n");  		v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n");  		return -EINVAL;  	} +	dev->curfreq = dev->mutefreq = mutefreq << 4;  	mutex_init(&dev->lock);  	if (!request_region(dev->io, 8, "typhoon")) { @@ -378,17 +378,17 @@ static int __init typhoon_init(void)  	dev->vdev.ioctl_ops = &typhoon_ioctl_ops;  	dev->vdev.release = video_device_release_empty;  	video_set_drvdata(&dev->vdev, dev); + +	/* mute card - prevents noisy bootups */ +	typhoon_mute(dev); +  	if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {  		v4l2_device_unregister(&dev->v4l2_dev);  		release_region(dev->io, 8);  		return -EINVAL;  	}  	v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io); -	v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", dev->mutefreq); -	dev->mutefreq <<= 4; - -	/* mute card - prevents noisy bootups */ -	typhoon_mute(dev); +	v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", mutefreq);  	return 0;  } diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index f31eab99c94..af99c5bd88c 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -377,7 +377,7 @@ static int vidioc_s_audio(struct file *file, void *priv,  static const struct v4l2_file_operations zoltrix_fops =  {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = { @@ -424,20 +424,6 @@ static int __init zoltrix_init(void)  		return res;  	} -	strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name)); -	zol->vdev.v4l2_dev = v4l2_dev; -	zol->vdev.fops = &zoltrix_fops; -	zol->vdev.ioctl_ops = &zoltrix_ioctl_ops; -	zol->vdev.release = video_device_release_empty; -	video_set_drvdata(&zol->vdev, zol); - -	if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -		v4l2_device_unregister(v4l2_dev); -		release_region(zol->io, 2); -		return -EINVAL; -	} -	v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n"); -  	mutex_init(&zol->lock);  	/* mute card - prevents noisy bootups */ @@ -452,6 +438,20 @@ static int __init zoltrix_init(void)  	zol->curvol = 0;  	zol->stereo = 1; +	strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name)); +	zol->vdev.v4l2_dev = v4l2_dev; +	zol->vdev.fops = &zoltrix_fops; +	zol->vdev.ioctl_ops = &zoltrix_ioctl_ops; +	zol->vdev.release = video_device_release_empty; +	video_set_drvdata(&zol->vdev, zol); + +	if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { +		v4l2_device_unregister(v4l2_dev); +		release_region(zol->io, 2); +		return -EINVAL; +	} +	v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n"); +  	return 0;  } diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 31e7a123d19..f989f2820d8 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -712,7 +712,7 @@ static int ar_initialize(struct ar *ar)  static const struct v4l2_file_operations ar_fops = {  	.owner		= THIS_MODULE,  	.read		= ar_read, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  };  static const struct v4l2_ioctl_ops ar_ioctl_ops = { diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index a529619e51f..0902ec041c7 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -854,7 +854,6 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)  		xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;  	/* is it free? */ -	mutex_lock(&btv->lock);  	if (btv->resources & xbits) {  		/* no, someone else uses it */  		goto fail; @@ -884,11 +883,9 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)  	/* it's free, grab it */  	fh->resources  |= bit;  	btv->resources |= bit; -	mutex_unlock(&btv->lock);  	return 1;   fail: -	mutex_unlock(&btv->lock);  	return 0;  } @@ -940,7 +937,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)  		/* trying to free ressources not allocated by us ... */  		printk("bttv: BUG! (btres)\n");  	} -	mutex_lock(&btv->lock);  	fh->resources  &= ~bits;  	btv->resources &= ~bits; @@ -951,8 +947,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)  	if (0 == (bits & VBI_RESOURCES))  		disclaim_vbi_lines(btv); - -	mutex_unlock(&btv->lock);  }  /* ----------------------------------------------------------------------- */ @@ -1713,28 +1707,20 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,  		/* Make sure tvnorm and vbi_end remain consistent  		   until we're done. */ -		mutex_lock(&btv->lock);  		norm = btv->tvnorm;  		/* In this mode capturing always starts at defrect.top  		   (default VDELAY), ignoring cropping parameters. */  		if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) { -			mutex_unlock(&btv->lock);  			return -EINVAL;  		} -		mutex_unlock(&btv->lock); -  		c.rect = bttv_tvnorms[norm].cropcap.defrect;  	} else { -		mutex_lock(&btv->lock); -  		norm = btv->tvnorm;  		c = btv->crop[!!fh->do_crop]; -		mutex_unlock(&btv->lock); -  		if (width < c.min_scaled_width ||  		    width > c.max_scaled_width ||  		    height < c.min_scaled_height) @@ -1858,7 +1844,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)  	unsigned int i;  	int err; -	mutex_lock(&btv->lock);  	err = v4l2_prio_check(&btv->prio, fh->prio);  	if (err)  		goto err; @@ -1874,7 +1859,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)  	set_tvnorm(btv, i);  err: -	mutex_unlock(&btv->lock);  	return err;  } @@ -1898,7 +1882,6 @@ static int bttv_enum_input(struct file *file, void *priv,  	struct bttv *btv = fh->btv;  	int rc = 0; -	mutex_lock(&btv->lock);  	if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {  		rc = -EINVAL;  		goto err; @@ -1928,7 +1911,6 @@ static int bttv_enum_input(struct file *file, void *priv,  	i->std = BTTV_NORMS;  err: -	mutex_unlock(&btv->lock);  	return rc;  } @@ -1938,9 +1920,7 @@ static int bttv_g_input(struct file *file, void *priv, unsigned int *i)  	struct bttv_fh *fh = priv;  	struct bttv *btv = fh->btv; -	mutex_lock(&btv->lock);  	*i = btv->input; -	mutex_unlock(&btv->lock);  	return 0;  } @@ -1952,7 +1932,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)  	int err; -	mutex_lock(&btv->lock);  	err = v4l2_prio_check(&btv->prio, fh->prio);  	if (unlikely(err))  		goto err; @@ -1965,7 +1944,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)  	set_input(btv, i, btv->tvnorm);  err: -	mutex_unlock(&btv->lock);  	return 0;  } @@ -1979,7 +1957,6 @@ static int bttv_s_tuner(struct file *file, void *priv,  	if (unlikely(0 != t->index))  		return -EINVAL; -	mutex_lock(&btv->lock);  	if (unlikely(btv->tuner_type == TUNER_ABSENT)) {  		err = -EINVAL;  		goto err; @@ -1995,7 +1972,6 @@ static int bttv_s_tuner(struct file *file, void *priv,  		btv->audio_mode_gpio(btv, t, 1);  err: -	mutex_unlock(&btv->lock);  	return 0;  } @@ -2006,10 +1982,8 @@ static int bttv_g_frequency(struct file *file, void *priv,  	struct bttv_fh *fh  = priv;  	struct bttv *btv = fh->btv; -	mutex_lock(&btv->lock);  	f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;  	f->frequency = btv->freq; -	mutex_unlock(&btv->lock);  	return 0;  } @@ -2024,7 +1998,6 @@ static int bttv_s_frequency(struct file *file, void *priv,  	if (unlikely(f->tuner != 0))  		return -EINVAL; -	mutex_lock(&btv->lock);  	err = v4l2_prio_check(&btv->prio, fh->prio);  	if (unlikely(err))  		goto err; @@ -2039,7 +2012,6 @@ static int bttv_s_frequency(struct file *file, void *priv,  	if (btv->has_matchbox && btv->radio_user)  		tea5757_set_freq(btv, btv->freq);  err: -	mutex_unlock(&btv->lock);  	return 0;  } @@ -2172,7 +2144,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,  	/* Make sure tvnorm, vbi_end and the current cropping parameters  	   remain consistent until we're done. */ -	mutex_lock(&btv->lock);  	b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds; @@ -2250,7 +2221,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,  	rc = 0; /* success */   fail: -	mutex_unlock(&btv->lock);  	return rc;  } @@ -2282,9 +2252,7 @@ verify_window_lock		(struct bttv_fh *               fh,  	if (V4L2_FIELD_ANY == field) {  		__s32 height2; -		mutex_lock(&fh->btv->lock);  		height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1; -		mutex_unlock(&fh->btv->lock);  		field = (win->w.height > height2)  			? V4L2_FIELD_INTERLACED  			: V4L2_FIELD_TOP; @@ -2360,7 +2328,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,  		}  	} -	mutex_lock(&fh->cap.vb_lock);  	/* clip against screen */  	if (NULL != btv->fbuf.base)  		n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height, @@ -2391,13 +2358,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,  	fh->ov.field    = win->field;  	fh->ov.setup_ok = 1; -	/* -	 * FIXME: btv is protected by btv->lock mutex, while btv->init -	 *	  is protected by fh->cap.vb_lock. This seems to open the -	 *	  possibility for some race situations. Maybe the better would -	 *	  be to unify those locks or to use another way to store the -	 *	  init values that will be consumed by videobuf callbacks -	 */  	btv->init.ov.w.width   = win->w.width;  	btv->init.ov.w.height  = win->w.height;  	btv->init.ov.field     = win->field; @@ -2412,7 +2372,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,  		bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);  		retval = bttv_switch_overlay(btv,fh,new);  	} -	mutex_unlock(&fh->cap.vb_lock);  	return retval;  } @@ -2526,9 +2485,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,  	if (V4L2_FIELD_ANY == field) {  		__s32 height2; -		mutex_lock(&btv->lock);  		height2 = btv->crop[!!fh->do_crop].rect.height >> 1; -		mutex_unlock(&btv->lock);  		field = (f->fmt.pix.height > height2)  			? V4L2_FIELD_INTERLACED  			: V4L2_FIELD_BOTTOM; @@ -2614,7 +2571,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,  	fmt = format_by_fourcc(f->fmt.pix.pixelformat);  	/* update our state informations */ -	mutex_lock(&fh->cap.vb_lock);  	fh->fmt              = fmt;  	fh->cap.field        = f->fmt.pix.field;  	fh->cap.last         = V4L2_FIELD_NONE; @@ -2623,7 +2579,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,  	btv->init.fmt        = fmt;  	btv->init.width      = f->fmt.pix.width;  	btv->init.height     = f->fmt.pix.height; -	mutex_unlock(&fh->cap.vb_lock);  	return 0;  } @@ -2649,11 +2604,9 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)  	unsigned int i;  	struct bttv_fh *fh = priv; -	mutex_lock(&fh->cap.vb_lock);  	retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,  				     V4L2_MEMORY_MMAP);  	if (retval < 0) { -		mutex_unlock(&fh->cap.vb_lock);  		return retval;  	} @@ -2665,7 +2618,6 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)  	for (i = 0; i < gbuffers; i++)  		mbuf->offsets[i] = i * gbufsize; -	mutex_unlock(&fh->cap.vb_lock);  	return 0;  }  #endif @@ -2775,10 +2727,8 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)  	int retval = 0;  	if (on) { -		mutex_lock(&fh->cap.vb_lock);  		/* verify args */  		if (unlikely(!btv->fbuf.base)) { -			mutex_unlock(&fh->cap.vb_lock);  			return -EINVAL;  		}  		if (unlikely(!fh->ov.setup_ok)) { @@ -2787,13 +2737,11 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)  		}  		if (retval)  			return retval; -		mutex_unlock(&fh->cap.vb_lock);  	}  	if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))  		return -EBUSY; -	mutex_lock(&fh->cap.vb_lock);  	if (on) {  		fh->ov.tvnorm = btv->tvnorm;  		new = videobuf_sg_alloc(sizeof(*new)); @@ -2805,7 +2753,6 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)  	/* switch over */  	retval = bttv_switch_overlay(btv, fh, new); -	mutex_unlock(&fh->cap.vb_lock);  	return retval;  } @@ -2844,7 +2791,6 @@ static int bttv_s_fbuf(struct file *file, void *f,  	}  	/* ok, accept it */ -	mutex_lock(&fh->cap.vb_lock);  	btv->fbuf.base       = fb->base;  	btv->fbuf.fmt.width  = fb->fmt.width;  	btv->fbuf.fmt.height = fb->fmt.height; @@ -2876,7 +2822,6 @@ static int bttv_s_fbuf(struct file *file, void *f,  			retval = bttv_switch_overlay(btv, fh, new);  		}  	} -	mutex_unlock(&fh->cap.vb_lock);  	return retval;  } @@ -2955,7 +2900,6 @@ static int bttv_queryctrl(struct file *file, void *priv,  	     c->id >= V4L2_CID_PRIVATE_LASTP1))  		return -EINVAL; -	mutex_lock(&btv->lock);  	if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))  		*c = no_ctl;  	else { @@ -2963,7 +2907,6 @@ static int bttv_queryctrl(struct file *file, void *priv,  		*c = (NULL != ctrl) ? *ctrl : no_ctl;  	} -	mutex_unlock(&btv->lock);  	return 0;  } @@ -2974,10 +2917,8 @@ static int bttv_g_parm(struct file *file, void *f,  	struct bttv_fh *fh = f;  	struct bttv *btv = fh->btv; -	mutex_lock(&btv->lock);  	v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,  				    &parm->parm.capture.timeperframe); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -2993,7 +2934,6 @@ static int bttv_g_tuner(struct file *file, void *priv,  	if (0 != t->index)  		return -EINVAL; -	mutex_lock(&btv->lock);  	t->rxsubchans = V4L2_TUNER_SUB_MONO;  	bttv_call_all(btv, tuner, g_tuner, t);  	strcpy(t->name, "Television"); @@ -3005,7 +2945,6 @@ static int bttv_g_tuner(struct file *file, void *priv,  	if (btv->audio_mode_gpio)  		btv->audio_mode_gpio(btv, t, 0); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3014,9 +2953,7 @@ static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)  	struct bttv_fh *fh = f;  	struct bttv *btv = fh->btv; -	mutex_lock(&btv->lock);  	*p = v4l2_prio_max(&btv->prio); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3028,9 +2965,7 @@ static int bttv_s_priority(struct file *file, void *f,  	struct bttv *btv = fh->btv;  	int	rc; -	mutex_lock(&btv->lock);  	rc = v4l2_prio_change(&btv->prio, &fh->prio, prio); -	mutex_unlock(&btv->lock);  	return rc;  } @@ -3045,9 +2980,7 @@ static int bttv_cropcap(struct file *file, void *priv,  	    cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)  		return -EINVAL; -	mutex_lock(&btv->lock);  	*cap = bttv_tvnorms[btv->tvnorm].cropcap; -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3065,9 +2998,7 @@ static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)  	   inconsistent with fh->width or fh->height and apps  	   do not expect a change here. */ -	mutex_lock(&btv->lock);  	crop->c = btv->crop[!!fh->do_crop].rect; -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3091,17 +3022,14 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)  	/* Make sure tvnorm, vbi_end and the current cropping  	   parameters remain consistent until we're done. Note  	   read() may change vbi_end in check_alloc_btres_lock(). */ -	mutex_lock(&btv->lock);  	retval = v4l2_prio_check(&btv->prio, fh->prio);  	if (0 != retval) { -		mutex_unlock(&btv->lock);  		return retval;  	}  	retval = -EBUSY;  	if (locked_btres(fh->btv, VIDEO_RESOURCES)) { -		mutex_unlock(&btv->lock);  		return retval;  	} @@ -3113,7 +3041,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)  	b_top = max(b->top, btv->vbi_end);  	if (b_top + 32 >= b_bottom) { -		mutex_unlock(&btv->lock);  		return retval;  	} @@ -3136,12 +3063,8 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)  	btv->crop[1] = c; -	mutex_unlock(&btv->lock); -  	fh->do_crop = 1; -	mutex_lock(&fh->cap.vb_lock); -  	if (fh->width < c.min_scaled_width) {  		fh->width = c.min_scaled_width;  		btv->init.width = c.min_scaled_width; @@ -3158,8 +3081,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)  		btv->init.height = c.max_scaled_height;  	} -	mutex_unlock(&fh->cap.vb_lock); -  	return 0;  } @@ -3227,7 +3148,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)  		return videobuf_poll_stream(file, &fh->vbi, wait);  	} -	mutex_lock(&fh->cap.vb_lock);  	if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {  		/* streaming capture */  		if (list_empty(&fh->cap.stream)) @@ -3262,7 +3182,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)  	else  		rc = 0;  err: -	mutex_unlock(&fh->cap.vb_lock);  	return rc;  } @@ -3293,23 +3212,11 @@ static int bttv_open(struct file *file)  		return -ENOMEM;  	file->private_data = fh; -	/* -	 * btv is protected by btv->lock mutex, while btv->init and other -	 * streaming vars are protected by fh->cap.vb_lock. We need to take -	 * care of both locks to avoid troubles. However, vb_lock is used also -	 * inside videobuf, without calling buf->lock. So, it is a very bad -	 * idea to hold both locks at the same time. -	 * Let's first copy btv->init at fh, holding cap.vb_lock, and then work -	 * with the rest of init, holding btv->lock. -	 */ -	mutex_lock(&fh->cap.vb_lock);  	*fh = btv->init; -	mutex_unlock(&fh->cap.vb_lock);  	fh->type = type;  	fh->ov.setup_ok = 0; -	mutex_lock(&btv->lock);  	v4l2_prio_open(&btv->prio, &fh->prio);  	videobuf_queue_sg_init(&fh->cap, &bttv_video_qops, @@ -3317,13 +3224,13 @@ static int bttv_open(struct file *file)  			    V4L2_BUF_TYPE_VIDEO_CAPTURE,  			    V4L2_FIELD_INTERLACED,  			    sizeof(struct bttv_buffer), -			    fh, NULL); +			    fh, &btv->lock);  	videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,  			    &btv->c.pci->dev, &btv->s_lock,  			    V4L2_BUF_TYPE_VBI_CAPTURE,  			    V4L2_FIELD_SEQ_TB,  			    sizeof(struct bttv_buffer), -			    fh, NULL); +			    fh, &btv->lock);  	set_tvnorm(btv,btv->tvnorm);  	set_input(btv, btv->input, btv->tvnorm); @@ -3346,7 +3253,6 @@ static int bttv_open(struct file *file)  	bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);  	bttv_field_count(btv); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3355,7 +3261,6 @@ static int bttv_release(struct file *file)  	struct bttv_fh *fh = file->private_data;  	struct bttv *btv = fh->btv; -	mutex_lock(&btv->lock);  	/* turn off overlay */  	if (check_btres(fh, RESOURCE_OVERLAY))  		bttv_switch_overlay(btv,fh,NULL); @@ -3381,14 +3286,8 @@ static int bttv_release(struct file *file)  	/* free stuff */ -	/* -	 * videobuf uses cap.vb_lock - we should avoid holding btv->lock, -	 * otherwise we may have dead lock conditions -	 */ -	mutex_unlock(&btv->lock);  	videobuf_mmap_free(&fh->cap);  	videobuf_mmap_free(&fh->vbi); -	mutex_lock(&btv->lock);  	v4l2_prio_close(&btv->prio, fh->prio);  	file->private_data = NULL;  	kfree(fh); @@ -3398,7 +3297,6 @@ static int bttv_release(struct file *file)  	if (!btv->users)  		audio_mute(btv, 1); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3502,11 +3400,8 @@ static int radio_open(struct file *file)  	if (unlikely(!fh))  		return -ENOMEM;  	file->private_data = fh; -	mutex_lock(&fh->cap.vb_lock);  	*fh = btv->init; -	mutex_unlock(&fh->cap.vb_lock); -	mutex_lock(&btv->lock);  	v4l2_prio_open(&btv->prio, &fh->prio);  	btv->radio_user++; @@ -3514,7 +3409,6 @@ static int radio_open(struct file *file)  	bttv_call_all(btv, tuner, s_radio);  	audio_input(btv,TVAUDIO_INPUT_RADIO); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3524,7 +3418,6 @@ static int radio_release(struct file *file)  	struct bttv *btv = fh->btv;  	struct rds_command cmd; -	mutex_lock(&btv->lock);  	v4l2_prio_close(&btv->prio, fh->prio);  	file->private_data = NULL;  	kfree(fh); @@ -3532,7 +3425,6 @@ static int radio_release(struct file *file)  	btv->radio_user--;  	bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd); -	mutex_unlock(&btv->lock);  	return 0;  } @@ -3561,7 +3453,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)  		return -EINVAL;  	if (0 != t->index)  		return -EINVAL; -	mutex_lock(&btv->lock);  	strcpy(t->name, "Radio");  	t->type = V4L2_TUNER_RADIO; @@ -3570,8 +3461,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)  	if (btv->audio_mode_gpio)  		btv->audio_mode_gpio(btv, t, 0); -	mutex_unlock(&btv->lock); -  	return 0;  } @@ -3692,7 +3581,7 @@ static const struct v4l2_file_operations radio_fops =  	.open	  = radio_open,  	.read     = radio_read,  	.release  = radio_release, -	.ioctl	  = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  	.poll     = radio_poll,  }; diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 935e0c9a967..c1193506131 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -860,7 +860,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,  static const struct v4l2_file_operations qcam_fops = {  	.owner		= THIS_MODULE, -	.ioctl          = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  	.read		= qcam_read,  }; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 6e4b19698c1..24fc00965a1 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -718,7 +718,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,  static const struct v4l2_file_operations qcam_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  	.read		= qcam_read,  }; diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 260c666ce93..0dfff50891e 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -1775,7 +1775,7 @@ static const struct v4l2_file_operations cafe_v4l_fops = {  	.read = cafe_v4l_read,  	.poll = cafe_v4l_poll,  	.mmap = cafe_v4l_mmap, -	.ioctl = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  };  static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = { diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.c b/drivers/media/video/cx18/cx18-alsa-pcm.c index 8f55692db36..82d195be919 100644 --- a/drivers/media/video/cx18/cx18-alsa-pcm.c +++ b/drivers/media/video/cx18/cx18-alsa-pcm.c @@ -218,7 +218,13 @@ static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream)  static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream,  		     unsigned int cmd, void *arg)  { -	return snd_pcm_lib_ioctl(substream, cmd, arg); +	struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); +	int ret; + +	snd_cx18_lock(cxsc); +	ret = snd_pcm_lib_ioctl(substream, cmd, arg); +	snd_cx18_unlock(cxsc); +	return ret;  } diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 9045f1ece0e..ab461e27d9d 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -41,7 +41,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = {  	.read = cx18_v4l2_read,  	.open = cx18_v4l2_open,  	/* FIXME change to video_ioctl2 if serialization lock can be removed */ -	.ioctl = cx18_v4l2_ioctl, +	.unlocked_ioctl = cx18_v4l2_ioctl,  	.release = cx18_v4l2_close,  	.poll = cx18_v4l2_enc_poll,  }; diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index a5cfc76b40b..bb164099ea2 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -2530,7 +2530,7 @@ static const struct v4l2_file_operations et61x251_fops = {  	.owner = THIS_MODULE,  	.open =    et61x251_open,  	.release = et61x251_release, -	.ioctl =   et61x251_ioctl, +	.unlocked_ioctl =   et61x251_ioctl,  	.read =    et61x251_read,  	.poll =    et61x251_poll,  	.mmap =    et61x251_mmap, diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 330dadc0010..e23de57e2c7 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -63,7 +63,10 @@ struct sd {  #define QUALITY_DEF 80  	u8 jpegqual;			/* webcam quality */ +	u8 reg01; +	u8 reg17;  	u8 reg18; +	u8 flags;  	s8 ag_cnt;  #define AG_CNT_START 13 @@ -96,6 +99,22 @@ enum sensors {  	SENSOR_SP80708,  }; +/* device flags */ +#define PDN_INV	1		/* inverse pin S_PWR_DN / sn_xxx tables */ + +/* sn9c1xx definitions */ +/* register 0x01 */ +#define S_PWR_DN	0x01	/* sensor power down */ +#define S_PDN_INV	0x02	/* inverse pin S_PWR_DN */ +#define V_TX_EN		0x04	/* video transfer enable */ +#define LED		0x08	/* output to pin LED */ +#define SCL_SEL_OD	0x20	/* open-drain mode */ +#define SYS_SEL_48M	0x40	/* system clock 0: 24MHz, 1: 48MHz */ +/* register 0x17 */ +#define MCK_SIZE_MASK	0x1f	/* sensor master clock */ +#define SEN_CLK_EN	0x20	/* enable sensor clock */ +#define DEF_EN		0x80	/* defect pixel by 0: soft, 1: hard */ +  /* V4L2 controls supported by the driver */  static void setbrightness(struct gspca_dev *gspca_dev);  static void setcontrast(struct gspca_dev *gspca_dev); @@ -1755,141 +1774,6 @@ static void po2030n_probe(struct gspca_dev *gspca_dev)  	}  } -static void bridge_init(struct gspca_dev *gspca_dev, -			  const u8 *sn9c1xx) -{ -	struct sd *sd = (struct sd *) gspca_dev; -	u8 reg0102[2]; -	const u8 *reg9a; -	static const u8 reg9a_def[] = -		{0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; -	static const u8 reg9a_spec[] = -		{0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; -	static const u8 regd4[] = {0x60, 0x00, 0x00}; - -	/* sensor clock already enabled in sd_init */ -	/* reg_w1(gspca_dev, 0xf1, 0x00); */ -	reg_w1(gspca_dev, 0x01, sn9c1xx[1]); - -	/* configure gpio */ -	reg0102[0] = sn9c1xx[1]; -	reg0102[1] = sn9c1xx[2]; -	if (gspca_dev->audio) -		reg0102[1] |= 0x04;	/* keep the audio connection */ -	reg_w(gspca_dev, 0x01, reg0102, 2); -	reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); -	reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); -	switch (sd->sensor) { -	case SENSOR_GC0307: -	case SENSOR_OV7660: -	case SENSOR_PO1030: -	case SENSOR_PO2030N: -	case SENSOR_SOI768: -	case SENSOR_SP80708: -		reg9a = reg9a_spec; -		break; -	default: -		reg9a = reg9a_def; -		break; -	} -	reg_w(gspca_dev, 0x9a, reg9a, 6); - -	reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); - -	reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); - -	switch (sd->sensor) { -	case SENSOR_ADCM1700: -		reg_w1(gspca_dev, 0x01, 0x43); -		reg_w1(gspca_dev, 0x17, 0x62); -		reg_w1(gspca_dev, 0x01, 0x42); -		reg_w1(gspca_dev, 0x01, 0x42); -		break; -	case SENSOR_GC0307: -		msleep(50); -		reg_w1(gspca_dev, 0x01, 0x61); -		reg_w1(gspca_dev, 0x17, 0x22); -		reg_w1(gspca_dev, 0x01, 0x60); -		reg_w1(gspca_dev, 0x01, 0x40); -		msleep(50); -		break; -	case SENSOR_MI0360B: -		reg_w1(gspca_dev, 0x01, 0x61); -		reg_w1(gspca_dev, 0x17, 0x60); -		reg_w1(gspca_dev, 0x01, 0x60); -		reg_w1(gspca_dev, 0x01, 0x40); -		break; -	case SENSOR_MT9V111: -		reg_w1(gspca_dev, 0x01, 0x61); -		reg_w1(gspca_dev, 0x17, 0x61); -		reg_w1(gspca_dev, 0x01, 0x60); -		reg_w1(gspca_dev, 0x01, 0x40); -		break; -	case SENSOR_OM6802: -		msleep(10); -		reg_w1(gspca_dev, 0x02, 0x73); -		reg_w1(gspca_dev, 0x17, 0x60); -		reg_w1(gspca_dev, 0x01, 0x22); -		msleep(100); -		reg_w1(gspca_dev, 0x01, 0x62); -		reg_w1(gspca_dev, 0x17, 0x64); -		reg_w1(gspca_dev, 0x17, 0x64); -		reg_w1(gspca_dev, 0x01, 0x42); -		msleep(10); -		reg_w1(gspca_dev, 0x01, 0x42); -		i2c_w8(gspca_dev, om6802_init0[0]); -		i2c_w8(gspca_dev, om6802_init0[1]); -		msleep(15); -		reg_w1(gspca_dev, 0x02, 0x71); -		msleep(150); -		break; -	case SENSOR_OV7630: -		reg_w1(gspca_dev, 0x01, 0x61); -		reg_w1(gspca_dev, 0x17, 0xe2); -		reg_w1(gspca_dev, 0x01, 0x60); -		reg_w1(gspca_dev, 0x01, 0x40); -		break; -	case SENSOR_OV7648: -		reg_w1(gspca_dev, 0x01, 0x63); -		reg_w1(gspca_dev, 0x17, 0x20); -		reg_w1(gspca_dev, 0x01, 0x62); -		reg_w1(gspca_dev, 0x01, 0x42); -		break; -	case SENSOR_PO1030: -	case SENSOR_SOI768: -		reg_w1(gspca_dev, 0x01, 0x61); -		reg_w1(gspca_dev, 0x17, 0x20); -		reg_w1(gspca_dev, 0x01, 0x60); -		reg_w1(gspca_dev, 0x01, 0x40); -		break; -	case SENSOR_PO2030N: -	case SENSOR_OV7660: -		reg_w1(gspca_dev, 0x01, 0x63); -		reg_w1(gspca_dev, 0x17, 0x20); -		reg_w1(gspca_dev, 0x01, 0x62); -		reg_w1(gspca_dev, 0x01, 0x42); -		break; -	case SENSOR_SP80708: -		reg_w1(gspca_dev, 0x01, 0x63); -		reg_w1(gspca_dev, 0x17, 0x20); -		reg_w1(gspca_dev, 0x01, 0x62); -		reg_w1(gspca_dev, 0x01, 0x42); -		msleep(100); -		reg_w1(gspca_dev, 0x02, 0x62); -		break; -	default: -/*	case SENSOR_HV7131R: */ -/*	case SENSOR_MI0360: */ -/*	case SENSOR_MO4000: */ -		reg_w1(gspca_dev, 0x01, 0x43); -		reg_w1(gspca_dev, 0x17, 0x61); -		reg_w1(gspca_dev, 0x01, 0x42); -		if (sd->sensor == SENSOR_HV7131R) -			hv7131r_probe(gspca_dev); -		break; -	} -} -  /* this function is called at probe time */  static int sd_config(struct gspca_dev *gspca_dev,  			const struct usb_device_id *id) @@ -1898,7 +1782,8 @@ static int sd_config(struct gspca_dev *gspca_dev,  	struct cam *cam;  	sd->bridge = id->driver_info >> 16; -	sd->sensor = id->driver_info; +	sd->sensor = id->driver_info >> 8; +	sd->flags = id->driver_info;  	cam = &gspca_dev->cam;  	if (sd->sensor == SENSOR_ADCM1700) { @@ -1929,7 +1814,7 @@ static int sd_init(struct gspca_dev *gspca_dev)  	/* setup a selector by bridge */  	reg_w1(gspca_dev, 0xf1, 0x01);  	reg_r(gspca_dev, 0x00, 1); -	reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]); +	reg_w1(gspca_dev, 0xf1, 0x00);  	reg_r(gspca_dev, 0x00, 1);		/* get sonix chip id */  	regF1 = gspca_dev->usb_buf[0];  	if (gspca_dev->usb_err < 0) @@ -2423,10 +2308,17 @@ static int sd_start(struct gspca_dev *gspca_dev)  {  	struct sd *sd = (struct sd *) gspca_dev;  	int i; -	u8 reg1, reg17; +	u8 reg01, reg17; +	u8 reg0102[2];  	const u8 *sn9c1xx;  	const u8 (*init)[8]; +	const u8 *reg9a;  	int mode; +	static const u8 reg9a_def[] = +		{0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; +	static const u8 reg9a_spec[] = +		{0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; +	static const u8 regd4[] = {0x60, 0x00, 0x00};  	static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };  	static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };  	static const u8 CA_adcm1700[] = @@ -2448,7 +2340,85 @@ static int sd_start(struct gspca_dev *gspca_dev)  	/* initialize the bridge */  	sn9c1xx = sn_tb[sd->sensor]; -	bridge_init(gspca_dev, sn9c1xx); + +	/* sensor clock already enabled in sd_init */ +	/* reg_w1(gspca_dev, 0xf1, 0x00); */ +	reg01 = sn9c1xx[1]; +	if (sd->flags & PDN_INV) +		reg01 ^= S_PDN_INV;		/* power down inverted */ +	reg_w1(gspca_dev, 0x01, reg01); + +	/* configure gpio */ +	reg0102[0] = reg01; +	reg0102[1] = sn9c1xx[2]; +	if (gspca_dev->audio) +		reg0102[1] |= 0x04;	/* keep the audio connection */ +	reg_w(gspca_dev, 0x01, reg0102, 2); +	reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); +	reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); +	switch (sd->sensor) { +	case SENSOR_GC0307: +	case SENSOR_OV7660: +	case SENSOR_PO1030: +	case SENSOR_PO2030N: +	case SENSOR_SOI768: +	case SENSOR_SP80708: +		reg9a = reg9a_spec; +		break; +	default: +		reg9a = reg9a_def; +		break; +	} +	reg_w(gspca_dev, 0x9a, reg9a, 6); + +	reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); + +	reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); + +	reg17 = sn9c1xx[0x17]; +	switch (sd->sensor) { +	case SENSOR_GC0307: +		msleep(50);		/*fixme: is it useful? */ +		break; +	case SENSOR_OM6802: +		msleep(10); +		reg_w1(gspca_dev, 0x02, 0x73); +		reg17 |= SEN_CLK_EN; +		reg_w1(gspca_dev, 0x17, reg17); +		reg_w1(gspca_dev, 0x01, 0x22); +		msleep(100); +		reg01 = SCL_SEL_OD | S_PDN_INV; +		reg17 &= MCK_SIZE_MASK; +		reg17 |= 0x04;		/* clock / 4 */ +		break; +	} +	reg01 |= SYS_SEL_48M; +	reg_w1(gspca_dev, 0x01, reg01); +	reg17 |= SEN_CLK_EN; +	reg_w1(gspca_dev, 0x17, reg17); +	reg01 &= ~S_PWR_DN;		/* sensor power on */ +	reg_w1(gspca_dev, 0x01, reg01); +	reg01 &= ~SYS_SEL_48M; +	reg_w1(gspca_dev, 0x01, reg01); + +	switch (sd->sensor) { +	case SENSOR_HV7131R: +		hv7131r_probe(gspca_dev);	/*fixme: is it useful? */ +		break; +	case SENSOR_OM6802: +		msleep(10); +		reg_w1(gspca_dev, 0x01, reg01); +		i2c_w8(gspca_dev, om6802_init0[0]); +		i2c_w8(gspca_dev, om6802_init0[1]); +		msleep(15); +		reg_w1(gspca_dev, 0x02, 0x71); +		msleep(150); +		break; +	case SENSOR_SP80708: +		msleep(100); +		reg_w1(gspca_dev, 0x02, 0x62); +		break; +	}  	/* initialize the sensor */  	i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); @@ -2476,30 +2446,11 @@ static int sd_start(struct gspca_dev *gspca_dev)  	}  	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);  	switch (sd->sensor) { -	case SENSOR_GC0307: -		reg17 = 0xa2; -		break; -	case SENSOR_MT9V111: -	case SENSOR_MI0360B: -		reg17 = 0xe0; -		break; -	case SENSOR_ADCM1700: -	case SENSOR_OV7630: -		reg17 = 0xe2; -		break; -	case SENSOR_OV7648: -		reg17 = 0x20; -		break; -	case SENSOR_OV7660: -	case SENSOR_SOI768: -		reg17 = 0xa0; -		break; -	case SENSOR_PO1030: -	case SENSOR_PO2030N: -		reg17 = 0xa0; +	case SENSOR_OM6802: +/*	case SENSOR_OV7648:		* fixme: sometimes */  		break;  	default: -		reg17 = 0x60; +		reg17 |= DEF_EN;  		break;  	}  	reg_w1(gspca_dev, 0x17, reg17); @@ -2546,95 +2497,67 @@ static int sd_start(struct gspca_dev *gspca_dev)  	init = NULL;  	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; -	if (mode) -		reg1 = 0x46;	/* 320x240: clk 48Mhz, video trf enable */ -	else -		reg1 = 0x06;	/* 640x480: clk 24Mhz, video trf enable */ -	reg17 = 0x61;		/* 0x:20: enable sensor clock */ +	reg01 |= SYS_SEL_48M | V_TX_EN; +	reg17 &= ~MCK_SIZE_MASK; +	reg17 |= 0x02;			/* clock / 2 */  	switch (sd->sensor) {  	case SENSOR_ADCM1700:  		init = adcm1700_sensor_param1; -		reg1 = 0x46; -		reg17 = 0xe2;  		break;  	case SENSOR_GC0307:  		init = gc0307_sensor_param1; -		reg17 = 0xa2; -		reg1 = 0x44; +		break; +	case SENSOR_HV7131R: +	case SENSOR_MI0360: +		if (mode) +			reg01 |= SYS_SEL_48M;	/* 320x240: clk 48Mhz */ +		else +			reg01 &= ~SYS_SEL_48M;	/* 640x480: clk 24Mhz */ +		reg17 &= ~MCK_SIZE_MASK; +		reg17 |= 0x01;			/* clock / 1 */  		break;  	case SENSOR_MI0360B:  		init = mi0360b_sensor_param1; -		reg1 &= ~0x02;		/* don't inverse pin S_PWR_DN */ -		reg17 = 0xe2;  		break;  	case SENSOR_MO4000: -		if (mode) { -/*			reg1 = 0x46;	 * 320 clk 48Mhz 60fp/s */ -			reg1 = 0x06;	/* clk 24Mz */ -		} else { -			reg17 = 0x22;	/* 640 MCKSIZE */ -/*			reg1 = 0x06;	 * 640 clk 24Mz (done) */ +		if (mode) {			/* if 320x240 */ +			reg01 &= ~SYS_SEL_48M;	/* clk 24Mz */ +			reg17 &= ~MCK_SIZE_MASK; +			reg17 |= 0x01;		/* clock / 1 */  		}  		break;  	case SENSOR_MT9V111:  		init = mt9v111_sensor_param1; -		if (mode) { -			reg1 = 0x04;	/* 320 clk 48Mhz */ -		} else { -/*			reg1 = 0x06;	 * 640 clk 24Mz (done) */ -			reg17 = 0xc2; -		}  		break;  	case SENSOR_OM6802:  		init = om6802_sensor_param1; -		reg17 = 0x64;		/* 640 MCKSIZE */ +		if (!mode) {			/* if 640x480 */ +			reg17 &= ~MCK_SIZE_MASK; +			reg17 |= 0x01;		/* clock / 4 */ +		}  		break;  	case SENSOR_OV7630:  		init = ov7630_sensor_param1; -		reg17 = 0xe2; -		reg1 = 0x44;  		break;  	case SENSOR_OV7648:  		init = ov7648_sensor_param1; -		reg17 = 0x21; -/*		reg1 = 0x42;		 * 42 - 46? */ +		reg17 &= ~MCK_SIZE_MASK; +		reg17 |= 0x01;			/* clock / 1 */  		break;  	case SENSOR_OV7660:  		init = ov7660_sensor_param1; -		if (sd->bridge == BRIDGE_SN9C120) { -			if (mode) {		/* 320x240 - 160x120 */ -				reg17 = 0xa2; -				reg1 = 0x44;	/* 48 Mhz, video trf eneble */ -			} -		} else { -			reg17 = 0x22; -			reg1 = 0x06;	/* 24 Mhz, video trf eneble -					 * inverse power down */ -		}  		break;  	case SENSOR_PO1030:  		init = po1030_sensor_param1; -		reg17 = 0xa2; -		reg1 = 0x44;  		break;  	case SENSOR_PO2030N:  		init = po2030n_sensor_param1; -		reg1 = 0x46; -		reg17 = 0xa2;  		break;  	case SENSOR_SOI768:  		init = soi768_sensor_param1; -		reg1 = 0x44; -		reg17 = 0xa2;  		break;  	case SENSOR_SP80708:  		init = sp80708_sensor_param1; -		if (mode) { -/*??			reg1 = 0x04;	 * 320 clk 48Mhz */ -		} else { -			reg1 = 0x46;	 /* 640 clk 48Mz */ -			reg17 = 0xa2; -		}  		break;  	} @@ -2684,7 +2607,9 @@ static int sd_start(struct gspca_dev *gspca_dev)  	setjpegqual(gspca_dev);  	reg_w1(gspca_dev, 0x17, reg17); -	reg_w1(gspca_dev, 0x01, reg1); +	reg_w1(gspca_dev, 0x01, reg01); +	sd->reg01 = reg01; +	sd->reg17 = reg17;  	sethvflip(gspca_dev);  	setbrightness(gspca_dev); @@ -2706,41 +2631,64 @@ static void sd_stopN(struct gspca_dev *gspca_dev)  		{ 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };  	static const u8 stopsoi768[] =  		{ 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 }; -	u8 data; -	const u8 *sn9c1xx; +	u8 reg01; +	u8 reg17; -	data = 0x0b; +	reg01 = sd->reg01; +	reg17 = sd->reg17 & ~SEN_CLK_EN;  	switch (sd->sensor) { +	case SENSOR_ADCM1700:  	case SENSOR_GC0307: -		data = 0x29; +	case SENSOR_PO2030N: +	case SENSOR_SP80708: +		reg01 |= LED; +		reg_w1(gspca_dev, 0x01, reg01); +		reg01 &= ~(LED | V_TX_EN); +		reg_w1(gspca_dev, 0x01, reg01); +/*		reg_w1(gspca_dev, 0x02, 0x??);	 * LED off ? */  		break;  	case SENSOR_HV7131R: +		reg01 &= ~V_TX_EN; +		reg_w1(gspca_dev, 0x01, reg01);  		i2c_w8(gspca_dev, stophv7131); -		data = 0x2b;  		break;  	case SENSOR_MI0360:  	case SENSOR_MI0360B: +		reg01 &= ~V_TX_EN; +		reg_w1(gspca_dev, 0x01, reg01); +/*		reg_w1(gspca_dev, 0x02, 0x40);	  * LED off ? */  		i2c_w8(gspca_dev, stopmi0360); -		data = 0x29;  		break; -	case SENSOR_OV7648: -		i2c_w8(gspca_dev, stopov7648); -		/* fall thru */  	case SENSOR_MT9V111: -	case SENSOR_OV7630: +	case SENSOR_OM6802:  	case SENSOR_PO1030: -		data = 0x29; +		reg01 &= ~V_TX_EN; +		reg_w1(gspca_dev, 0x01, reg01); +		break; +	case SENSOR_OV7630: +	case SENSOR_OV7648: +		reg01 &= ~V_TX_EN; +		reg_w1(gspca_dev, 0x01, reg01); +		i2c_w8(gspca_dev, stopov7648); +		break; +	case SENSOR_OV7660: +		reg01 &= ~V_TX_EN; +		reg_w1(gspca_dev, 0x01, reg01);  		break;  	case SENSOR_SOI768:  		i2c_w8(gspca_dev, stopsoi768); -		data = 0x29;  		break;  	} -	sn9c1xx = sn_tb[sd->sensor]; -	reg_w1(gspca_dev, 0x01, sn9c1xx[1]); -	reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); -	reg_w1(gspca_dev, 0x01, sn9c1xx[1]); -	reg_w1(gspca_dev, 0x01, data); + +	reg01 |= SCL_SEL_OD; +	reg_w1(gspca_dev, 0x01, reg01); +	reg01 |= S_PWR_DN;		/* sensor power down */ +	reg_w1(gspca_dev, 0x01, reg01); +	reg_w1(gspca_dev, 0x17, reg17); +	reg01 &= ~SYS_SEL_48M;		/* clock 24MHz */ +	reg_w1(gspca_dev, 0x01, reg01); +	reg01 |= LED; +	reg_w1(gspca_dev, 0x01, reg01);  	/* Don't disable sensor clock as that disables the button on the cam */  	/* reg_w1(gspca_dev, 0xf1, 0x01); */  } @@ -2954,14 +2902,18 @@ static const struct sd_desc sd_desc = {  /* -- module initialisation -- */  #define BS(bridge, sensor) \  	.driver_info = (BRIDGE_ ## bridge << 16) \ -			| SENSOR_ ## sensor +			| (SENSOR_ ## sensor << 8) +#define BSF(bridge, sensor, flags) \ +	.driver_info = (BRIDGE_ ## bridge << 16) \ +			| (SENSOR_ ## sensor << 8) \ +			| (flags)  static const __devinitdata struct usb_device_id device_table[] = {  #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE  	{USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},  	{USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},  #endif -	{USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)}, -	{USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)}, +	{USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, PDN_INV)}, +	{USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)},  	{USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},  	{USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},  	{USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)}, diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 2be23bccd3c..48d2c2419c1 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1659,7 +1659,7 @@ static const struct v4l2_file_operations meye_fops = {  	.open		= meye_open,  	.release	= meye_release,  	.mmap		= meye_mmap, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  	.poll		= meye_poll,  }; @@ -1831,12 +1831,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,  	msleep(1);  	mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK); -	if (video_register_device(meye.vdev, VFL_TYPE_GRABBER, -				  video_nr) < 0) { -		v4l2_err(v4l2_dev, "video_register_device failed\n"); -		goto outvideoreg; -	} -  	mutex_init(&meye.lock);  	init_waitqueue_head(&meye.proc_list);  	meye.brightness = 32 << 10; @@ -1858,6 +1852,12 @@ static int __devinit meye_probe(struct pci_dev *pcidev,  	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0);  	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48); +	if (video_register_device(meye.vdev, VFL_TYPE_GRABBER, +				  video_nr) < 0) { +		v4l2_err(v4l2_dev, "video_register_device failed\n"); +		goto outvideoreg; +	} +  	v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n",  	       MEYE_DRIVER_VERSION);  	v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n", diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 7129b50757d..7551907f8c2 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -932,7 +932,7 @@ static ssize_t pms_read(struct file *file, char __user *buf,  static const struct v4l2_file_operations pms_fops = {  	.owner		= THIS_MODULE, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  	.read           = pms_read,  }; diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c index 4e5a8cf76de..07cf0c6c7c1 100644 --- a/drivers/media/video/sh_vou.c +++ b/drivers/media/video/sh_vou.c @@ -75,6 +75,7 @@ struct sh_vou_device {  	int pix_idx;  	struct videobuf_buffer *active;  	enum sh_vou_status status; +	struct mutex fop_lock;  };  struct sh_vou_file { @@ -235,7 +236,7 @@ static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb)  	vb->state = VIDEOBUF_NEEDS_INIT;  } -/* Locking: caller holds vq->vb_lock mutex */ +/* Locking: caller holds fop_lock mutex */  static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,  			    unsigned int *size)  { @@ -257,7 +258,7 @@ static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,  	return 0;  } -/* Locking: caller holds vq->vb_lock mutex */ +/* Locking: caller holds fop_lock mutex */  static int sh_vou_buf_prepare(struct videobuf_queue *vq,  			      struct videobuf_buffer *vb,  			      enum v4l2_field field) @@ -306,7 +307,7 @@ static int sh_vou_buf_prepare(struct videobuf_queue *vq,  	return 0;  } -/* Locking: caller holds vq->vb_lock mutex and vq->irqlock spinlock */ +/* Locking: caller holds fop_lock mutex and vq->irqlock spinlock */  static void sh_vou_buf_queue(struct videobuf_queue *vq,  			     struct videobuf_buffer *vb)  { @@ -1190,7 +1191,7 @@ static int sh_vou_open(struct file *file)  				       V4L2_BUF_TYPE_VIDEO_OUTPUT,  				       V4L2_FIELD_NONE,  				       sizeof(struct videobuf_buffer), vdev, -				       NULL); +				       &vou_dev->fop_lock);  	return 0;  } @@ -1292,7 +1293,7 @@ static const struct v4l2_file_operations sh_vou_fops = {  	.owner		= THIS_MODULE,  	.open		= sh_vou_open,  	.release	= sh_vou_release, -	.ioctl		= video_ioctl2, +	.unlocked_ioctl	= video_ioctl2,  	.mmap		= sh_vou_mmap,  	.poll		= sh_vou_poll,  }; @@ -1331,6 +1332,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)  	INIT_LIST_HEAD(&vou_dev->queue);  	spin_lock_init(&vou_dev->lock); +	mutex_init(&vou_dev->fop_lock);  	atomic_set(&vou_dev->use_count, 0);  	vou_dev->pdata = vou_pdata;  	vou_dev->status = SH_VOU_IDLE; @@ -1388,6 +1390,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)  		vdev->tvnorms |= V4L2_STD_PAL;  	vdev->v4l2_dev = &vou_dev->v4l2_dev;  	vdev->release = video_device_release; +	vdev->lock = &vou_dev->fop_lock;  	vou_dev->vdev = vdev;  	video_set_drvdata(vdev, vou_dev); diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 28e19daadec..f49fbfb7dc1 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -3238,7 +3238,7 @@ static const struct v4l2_file_operations sn9c102_fops = {  	.owner = THIS_MODULE,  	.open = sn9c102_open,  	.release = sn9c102_release, -	.ioctl = sn9c102_ioctl, +	.unlocked_ioctl = sn9c102_ioctl,  	.read = sn9c102_read,  	.poll = sn9c102_poll,  	.mmap = sn9c102_mmap, diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index f169f773667..59f8a9ad379 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -785,7 +785,7 @@ static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id,  	}  } -struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, +static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,  	__u32 v4l2_id, struct uvc_control_mapping **mapping)  {  	struct uvc_control *ctrl = NULL; @@ -944,6 +944,52 @@ done:  	return ret;  } +/* + * Mapping V4L2 controls to UVC controls can be straighforward if done well. + * Most of the UVC controls exist in V4L2, and can be mapped directly. Some + * must be grouped (for instance the Red Balance, Blue Balance and Do White + * Balance V4L2 controls use the White Balance Component UVC control) or + * otherwise translated. The approach we take here is to use a translation + * table for the controls that can be mapped directly, and handle the others + * manually. + */ +int uvc_query_v4l2_menu(struct uvc_video_chain *chain, +	struct v4l2_querymenu *query_menu) +{ +	struct uvc_menu_info *menu_info; +	struct uvc_control_mapping *mapping; +	struct uvc_control *ctrl; +	u32 index = query_menu->index; +	u32 id = query_menu->id; +	int ret; + +	memset(query_menu, 0, sizeof(*query_menu)); +	query_menu->id = id; +	query_menu->index = index; + +	ret = mutex_lock_interruptible(&chain->ctrl_mutex); +	if (ret < 0) +		return -ERESTARTSYS; + +	ctrl = uvc_find_control(chain, query_menu->id, &mapping); +	if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) { +		ret = -EINVAL; +		goto done; +	} + +	if (query_menu->index >= mapping->menu_count) { +		ret = -EINVAL; +		goto done; +	} + +	menu_info = &mapping->menu_info[query_menu->index]; +	strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name); + +done: +	mutex_unlock(&chain->ctrl_mutex); +	return ret; +} +  /* --------------------------------------------------------------------------   * Control transactions diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index ed6d5449741..f14581bd707 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -90,6 +90,39 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,  }  /* + * Free the video buffers. + * + * This function must be called with the queue lock held. + */ +static int __uvc_free_buffers(struct uvc_video_queue *queue) +{ +	unsigned int i; + +	for (i = 0; i < queue->count; ++i) { +		if (queue->buffer[i].vma_use_count != 0) +			return -EBUSY; +	} + +	if (queue->count) { +		vfree(queue->mem); +		queue->count = 0; +	} + +	return 0; +} + +int uvc_free_buffers(struct uvc_video_queue *queue) +{ +	int ret; + +	mutex_lock(&queue->mutex); +	ret = __uvc_free_buffers(queue); +	mutex_unlock(&queue->mutex); + +	return ret; +} + +/*   * Allocate the video buffers.   *   * Pages are reserved to make sure they will not be swapped, as they will be @@ -110,7 +143,7 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,  	mutex_lock(&queue->mutex); -	if ((ret = uvc_free_buffers(queue)) < 0) +	if ((ret = __uvc_free_buffers(queue)) < 0)  		goto done;  	/* Bail out if no buffers should be allocated. */ @@ -152,28 +185,6 @@ done:  }  /* - * Free the video buffers. - * - * This function must be called with the queue lock held. - */ -int uvc_free_buffers(struct uvc_video_queue *queue) -{ -	unsigned int i; - -	for (i = 0; i < queue->count; ++i) { -		if (queue->buffer[i].vma_use_count != 0) -			return -EBUSY; -	} - -	if (queue->count) { -		vfree(queue->mem); -		queue->count = 0; -	} - -	return 0; -} - -/*   * Check if buffers have been allocated.   */  int uvc_queue_allocated(struct uvc_video_queue *queue) @@ -369,6 +380,82 @@ done:  }  /* + * VMA operations. + */ +static void uvc_vm_open(struct vm_area_struct *vma) +{ +	struct uvc_buffer *buffer = vma->vm_private_data; +	buffer->vma_use_count++; +} + +static void uvc_vm_close(struct vm_area_struct *vma) +{ +	struct uvc_buffer *buffer = vma->vm_private_data; +	buffer->vma_use_count--; +} + +static const struct vm_operations_struct uvc_vm_ops = { +	.open		= uvc_vm_open, +	.close		= uvc_vm_close, +}; + +/* + * Memory-map a video buffer. + * + * This function implements video buffers memory mapping and is intended to be + * used by the device mmap handler. + */ +int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) +{ +	struct uvc_buffer *uninitialized_var(buffer); +	struct page *page; +	unsigned long addr, start, size; +	unsigned int i; +	int ret = 0; + +	start = vma->vm_start; +	size = vma->vm_end - vma->vm_start; + +	mutex_lock(&queue->mutex); + +	for (i = 0; i < queue->count; ++i) { +		buffer = &queue->buffer[i]; +		if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) +			break; +	} + +	if (i == queue->count || size != queue->buf_size) { +		ret = -EINVAL; +		goto done; +	} + +	/* +	 * VM_IO marks the area as being an mmaped region for I/O to a +	 * device. It also prevents the region from being core dumped. +	 */ +	vma->vm_flags |= VM_IO; + +	addr = (unsigned long)queue->mem + buffer->buf.m.offset; +	while (size > 0) { +		page = vmalloc_to_page((void *)addr); +		if ((ret = vm_insert_page(vma, start, page)) < 0) +			goto done; + +		start += PAGE_SIZE; +		addr += PAGE_SIZE; +		size -= PAGE_SIZE; +	} + +	vma->vm_ops = &uvc_vm_ops; +	vma->vm_private_data = buffer; +	uvc_vm_open(vma); + +done: +	mutex_unlock(&queue->mutex); +	return ret; +} + +/*   * Poll the video queue.   *   * This function implements video queue polling and is intended to be used by diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 6d15de9b520..8cf61e8a634 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -101,40 +101,6 @@ done:   */  /* - * Mapping V4L2 controls to UVC controls can be straighforward if done well. - * Most of the UVC controls exist in V4L2, and can be mapped directly. Some - * must be grouped (for instance the Red Balance, Blue Balance and Do White - * Balance V4L2 controls use the White Balance Component UVC control) or - * otherwise translated. The approach we take here is to use a translation - * table for the controls that can be mapped directly, and handle the others - * manually. - */ -static int uvc_v4l2_query_menu(struct uvc_video_chain *chain, -	struct v4l2_querymenu *query_menu) -{ -	struct uvc_menu_info *menu_info; -	struct uvc_control_mapping *mapping; -	struct uvc_control *ctrl; -	u32 index = query_menu->index; -	u32 id = query_menu->id; - -	ctrl = uvc_find_control(chain, query_menu->id, &mapping); -	if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) -		return -EINVAL; - -	if (query_menu->index >= mapping->menu_count) -		return -EINVAL; - -	memset(query_menu, 0, sizeof(*query_menu)); -	query_menu->id = id; -	query_menu->index = index; - -	menu_info = &mapping->menu_info[query_menu->index]; -	strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name); -	return 0; -} - -/*   * Find the frame interval closest to the requested frame interval for the   * given frame format and size. This should be done by the device as part of   * the Video Probe and Commit negotiation, but some hardware don't implement @@ -260,12 +226,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,  	 * developers test their webcams with the Linux driver as well as with  	 * the Windows driver).  	 */ +	mutex_lock(&stream->mutex);  	if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)  		probe->dwMaxVideoFrameSize =  			stream->ctrl.dwMaxVideoFrameSize;  	/* Probe the device. */  	ret = uvc_probe_video(stream, probe); +	mutex_unlock(&stream->mutex);  	if (ret < 0)  		goto done; @@ -289,14 +257,21 @@ done:  static int uvc_v4l2_get_format(struct uvc_streaming *stream,  	struct v4l2_format *fmt)  { -	struct uvc_format *format = stream->cur_format; -	struct uvc_frame *frame = stream->cur_frame; +	struct uvc_format *format; +	struct uvc_frame *frame; +	int ret = 0;  	if (fmt->type != stream->type)  		return -EINVAL; -	if (format == NULL || frame == NULL) -		return -EINVAL; +	mutex_lock(&stream->mutex); +	format = stream->cur_format; +	frame = stream->cur_frame; + +	if (format == NULL || frame == NULL) { +		ret = -EINVAL; +		goto done; +	}  	fmt->fmt.pix.pixelformat = format->fcc;  	fmt->fmt.pix.width = frame->wWidth; @@ -307,7 +282,9 @@ static int uvc_v4l2_get_format(struct uvc_streaming *stream,  	fmt->fmt.pix.colorspace = format->colorspace;  	fmt->fmt.pix.priv = 0; -	return 0; +done: +	mutex_unlock(&stream->mutex); +	return ret;  }  static int uvc_v4l2_set_format(struct uvc_streaming *stream, @@ -321,18 +298,24 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,  	if (fmt->type != stream->type)  		return -EINVAL; -	if (uvc_queue_allocated(&stream->queue)) -		return -EBUSY; -  	ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);  	if (ret < 0)  		return ret; +	mutex_lock(&stream->mutex); + +	if (uvc_queue_allocated(&stream->queue)) { +		ret = -EBUSY; +		goto done; +	} +  	memcpy(&stream->ctrl, &probe, sizeof probe);  	stream->cur_format = format;  	stream->cur_frame = frame; -	return 0; +done: +	mutex_unlock(&stream->mutex); +	return ret;  }  static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, @@ -343,7 +326,10 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,  	if (parm->type != stream->type)  		return -EINVAL; +	mutex_lock(&stream->mutex);  	numerator = stream->ctrl.dwFrameInterval; +	mutex_unlock(&stream->mutex); +  	denominator = 10000000;  	uvc_simplify_fraction(&numerator, &denominator, 8, 333); @@ -370,7 +356,6 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,  static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,  		struct v4l2_streamparm *parm)  { -	struct uvc_frame *frame = stream->cur_frame;  	struct uvc_streaming_control probe;  	struct v4l2_fract timeperframe;  	uint32_t interval; @@ -379,28 +364,36 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,  	if (parm->type != stream->type)  		return -EINVAL; -	if (uvc_queue_streaming(&stream->queue)) -		return -EBUSY; -  	if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)  		timeperframe = parm->parm.capture.timeperframe;  	else  		timeperframe = parm->parm.output.timeperframe; -	memcpy(&probe, &stream->ctrl, sizeof probe);  	interval = uvc_fraction_to_interval(timeperframe.numerator,  		timeperframe.denominator); -  	uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",  		timeperframe.numerator, timeperframe.denominator, interval); -	probe.dwFrameInterval = uvc_try_frame_interval(frame, interval); + +	mutex_lock(&stream->mutex); + +	if (uvc_queue_streaming(&stream->queue)) { +		mutex_unlock(&stream->mutex); +		return -EBUSY; +	} + +	memcpy(&probe, &stream->ctrl, sizeof probe); +	probe.dwFrameInterval = +		uvc_try_frame_interval(stream->cur_frame, interval);  	/* Probe the device with the new settings. */  	ret = uvc_probe_video(stream, &probe); -	if (ret < 0) +	if (ret < 0) { +		mutex_unlock(&stream->mutex);  		return ret; +	}  	memcpy(&stream->ctrl, &probe, sizeof probe); +	mutex_unlock(&stream->mutex);  	/* Return the actual frame period. */  	timeperframe.numerator = probe.dwFrameInterval; @@ -528,11 +521,9 @@ static int uvc_v4l2_release(struct file *file)  	if (uvc_has_privileges(handle)) {  		uvc_video_enable(stream, 0); -		mutex_lock(&stream->queue.mutex);  		if (uvc_free_buffers(&stream->queue) < 0)  			uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to "  					"free buffers.\n"); -		mutex_unlock(&stream->queue.mutex);  	}  	/* Release the file handle. */ @@ -624,7 +615,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  	}  	case VIDIOC_QUERYMENU: -		return uvc_v4l2_query_menu(chain, arg); +		return uvc_query_v4l2_menu(chain, arg);  	case VIDIOC_G_EXT_CTRLS:  	{ @@ -905,15 +896,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  	case VIDIOC_CROPCAP:  	{  		struct v4l2_cropcap *ccap = arg; -		struct uvc_frame *frame = stream->cur_frame;  		if (ccap->type != stream->type)  			return -EINVAL;  		ccap->bounds.left = 0;  		ccap->bounds.top = 0; -		ccap->bounds.width = frame->wWidth; -		ccap->bounds.height = frame->wHeight; + +		mutex_lock(&stream->mutex); +		ccap->bounds.width = stream->cur_frame->wWidth; +		ccap->bounds.height = stream->cur_frame->wHeight; +		mutex_unlock(&stream->mutex);  		ccap->defrect = ccap->bounds; @@ -930,8 +923,6 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  	case VIDIOC_REQBUFS:  	{  		struct v4l2_requestbuffers *rb = arg; -		unsigned int bufsize = -			stream->ctrl.dwMaxVideoFrameSize;  		if (rb->type != stream->type ||  		    rb->memory != V4L2_MEMORY_MMAP) @@ -940,7 +931,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  		if ((ret = uvc_acquire_privileges(handle)) < 0)  			return ret; -		ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize); +		mutex_lock(&stream->mutex); +		ret = uvc_alloc_buffers(&stream->queue, rb->count, +					stream->ctrl.dwMaxVideoFrameSize); +		mutex_unlock(&stream->mutex);  		if (ret < 0)  			return ret; @@ -988,7 +982,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  		if (!uvc_has_privileges(handle))  			return -EBUSY; +		mutex_lock(&stream->mutex);  		ret = uvc_video_enable(stream, 1); +		mutex_unlock(&stream->mutex);  		if (ret < 0)  			return ret;  		break; @@ -1068,79 +1064,14 @@ static ssize_t uvc_v4l2_read(struct file *file, char __user *data,  	return -EINVAL;  } -/* - * VMA operations. - */ -static void uvc_vm_open(struct vm_area_struct *vma) -{ -	struct uvc_buffer *buffer = vma->vm_private_data; -	buffer->vma_use_count++; -} - -static void uvc_vm_close(struct vm_area_struct *vma) -{ -	struct uvc_buffer *buffer = vma->vm_private_data; -	buffer->vma_use_count--; -} - -static const struct vm_operations_struct uvc_vm_ops = { -	.open		= uvc_vm_open, -	.close		= uvc_vm_close, -}; -  static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)  {  	struct uvc_fh *handle = file->private_data;  	struct uvc_streaming *stream = handle->stream; -	struct uvc_video_queue *queue = &stream->queue; -	struct uvc_buffer *uninitialized_var(buffer); -	struct page *page; -	unsigned long addr, start, size; -	unsigned int i; -	int ret = 0;  	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n"); -	start = vma->vm_start; -	size = vma->vm_end - vma->vm_start; - -	mutex_lock(&queue->mutex); - -	for (i = 0; i < queue->count; ++i) { -		buffer = &queue->buffer[i]; -		if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) -			break; -	} - -	if (i == queue->count || size != queue->buf_size) { -		ret = -EINVAL; -		goto done; -	} - -	/* -	 * VM_IO marks the area as being an mmaped region for I/O to a -	 * device. It also prevents the region from being core dumped. -	 */ -	vma->vm_flags |= VM_IO; - -	addr = (unsigned long)queue->mem + buffer->buf.m.offset; -	while (size > 0) { -		page = vmalloc_to_page((void *)addr); -		if ((ret = vm_insert_page(vma, start, page)) < 0) -			goto done; - -		start += PAGE_SIZE; -		addr += PAGE_SIZE; -		size -= PAGE_SIZE; -	} - -	vma->vm_ops = &uvc_vm_ops; -	vma->vm_private_data = buffer; -	uvc_vm_open(vma); - -done: -	mutex_unlock(&queue->mutex); -	return ret; +	return uvc_queue_mmap(&stream->queue, vma);  }  static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) @@ -1157,7 +1088,7 @@ const struct v4l2_file_operations uvc_fops = {  	.owner		= THIS_MODULE,  	.open		= uvc_v4l2_open,  	.release	= uvc_v4l2_release, -	.ioctl		= uvc_v4l2_ioctl, +	.unlocked_ioctl	= uvc_v4l2_ioctl,  	.read		= uvc_v4l2_read,  	.mmap		= uvc_v4l2_mmap,  	.poll		= uvc_v4l2_poll, diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 5555f010283..5673d673504 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -293,8 +293,6 @@ int uvc_probe_video(struct uvc_streaming *stream,  	unsigned int i;  	int ret; -	mutex_lock(&stream->mutex); -  	/* Perform probing. The device should adjust the requested values  	 * according to its capabilities. However, some devices, namely the  	 * first generation UVC Logitech webcams, don't implement the Video @@ -346,7 +344,6 @@ int uvc_probe_video(struct uvc_streaming *stream,  	}  done: -	mutex_unlock(&stream->mutex);  	return ret;  } diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index d97cf6d6a4f..45f01e7e13d 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -436,7 +436,9 @@ struct uvc_streaming {  	struct uvc_streaming_control ctrl;  	struct uvc_format *cur_format;  	struct uvc_frame *cur_frame; - +	/* Protect access to ctrl, cur_format, cur_frame and hardware video +	 * probe control. +	 */  	struct mutex mutex;  	unsigned int frozen : 1; @@ -574,6 +576,8 @@ extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);  extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);  extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,  		struct uvc_buffer *buf); +extern int uvc_queue_mmap(struct uvc_video_queue *queue, +		struct vm_area_struct *vma);  extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,  		struct file *file, poll_table *wait);  extern int uvc_queue_allocated(struct uvc_video_queue *queue); @@ -606,10 +610,10 @@ extern int uvc_status_suspend(struct uvc_device *dev);  extern int uvc_status_resume(struct uvc_device *dev);  /* Controls */ -extern struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, -		__u32 v4l2_id, struct uvc_control_mapping **mapping);  extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,  		struct v4l2_queryctrl *v4l2_ctrl); +extern int uvc_query_v4l2_menu(struct uvc_video_chain *chain, +		struct v4l2_querymenu *query_menu);  extern int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,  		const struct uvc_control_mapping *mapping); diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 03f7f4670e9..359e23290a7 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -186,12 +186,12 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,  		size_t sz, loff_t *off)  {  	struct video_device *vdev = video_devdata(filp); -	int ret = -EIO; +	int ret = -ENODEV;  	if (!vdev->fops->read)  		return -EINVAL; -	if (vdev->lock) -		mutex_lock(vdev->lock); +	if (vdev->lock && mutex_lock_interruptible(vdev->lock)) +		return -ERESTARTSYS;  	if (video_is_registered(vdev))  		ret = vdev->fops->read(filp, buf, sz, off);  	if (vdev->lock) @@ -203,12 +203,12 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,  		size_t sz, loff_t *off)  {  	struct video_device *vdev = video_devdata(filp); -	int ret = -EIO; +	int ret = -ENODEV;  	if (!vdev->fops->write)  		return -EINVAL; -	if (vdev->lock) -		mutex_lock(vdev->lock); +	if (vdev->lock && mutex_lock_interruptible(vdev->lock)) +		return -ERESTARTSYS;  	if (video_is_registered(vdev))  		ret = vdev->fops->write(filp, buf, sz, off);  	if (vdev->lock) @@ -219,10 +219,10 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,  static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)  {  	struct video_device *vdev = video_devdata(filp); -	int ret = DEFAULT_POLLMASK; +	int ret = POLLERR | POLLHUP;  	if (!vdev->fops->poll) -		return ret; +		return DEFAULT_POLLMASK;  	if (vdev->lock)  		mutex_lock(vdev->lock);  	if (video_is_registered(vdev)) @@ -238,20 +238,45 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  	int ret = -ENODEV;  	if (vdev->fops->unlocked_ioctl) { -		if (vdev->lock) -			mutex_lock(vdev->lock); +		if (vdev->lock && mutex_lock_interruptible(vdev->lock)) +			return -ERESTARTSYS;  		if (video_is_registered(vdev))  			ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);  		if (vdev->lock)  			mutex_unlock(vdev->lock);  	} else if (vdev->fops->ioctl) { -		/* TODO: convert all drivers to unlocked_ioctl */ +		/* This code path is a replacement for the BKL. It is a major +		 * hack but it will have to do for those drivers that are not +		 * yet converted to use unlocked_ioctl. +		 * +		 * There are two options: if the driver implements struct +		 * v4l2_device, then the lock defined there is used to +		 * serialize the ioctls. Otherwise the v4l2 core lock defined +		 * below is used. This lock is really bad since it serializes +		 * completely independent devices. +		 * +		 * Both variants suffer from the same problem: if the driver +		 * sleeps, then it blocks all ioctls since the lock is still +		 * held. This is very common for VIDIOC_DQBUF since that +		 * normally waits for a frame to arrive. As a result any other +		 * ioctl calls will proceed very, very slowly since each call +		 * will have to wait for the VIDIOC_QBUF to finish. Things that +		 * should take 0.01s may now take 10-20 seconds. +		 * +		 * The workaround is to *not* take the lock for VIDIOC_DQBUF. +		 * This actually works OK for videobuf-based drivers, since +		 * videobuf will take its own internal lock. +		 */  		static DEFINE_MUTEX(v4l2_ioctl_mutex); +		struct mutex *m = vdev->v4l2_dev ? +			&vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex; -		mutex_lock(&v4l2_ioctl_mutex); +		if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m)) +			return -ERESTARTSYS;  		if (video_is_registered(vdev))  			ret = vdev->fops->ioctl(filp, cmd, arg); -		mutex_unlock(&v4l2_ioctl_mutex); +		if (cmd != VIDIOC_DQBUF) +			mutex_unlock(m);  	} else  		ret = -ENOTTY; @@ -265,8 +290,8 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)  	if (!vdev->fops->mmap)  		return ret; -	if (vdev->lock) -		mutex_lock(vdev->lock); +	if (vdev->lock && mutex_lock_interruptible(vdev->lock)) +		return -ERESTARTSYS;  	if (video_is_registered(vdev))  		ret = vdev->fops->mmap(filp, vm);  	if (vdev->lock) @@ -284,7 +309,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)  	mutex_lock(&videodev_lock);  	vdev = video_devdata(filp);  	/* return ENODEV if the video device has already been removed. */ -	if (vdev == NULL) { +	if (vdev == NULL || !video_is_registered(vdev)) {  		mutex_unlock(&videodev_lock);  		return -ENODEV;  	} @@ -292,8 +317,10 @@ static int v4l2_open(struct inode *inode, struct file *filp)  	video_get(vdev);  	mutex_unlock(&videodev_lock);  	if (vdev->fops->open) { -		if (vdev->lock) -			mutex_lock(vdev->lock); +		if (vdev->lock && mutex_lock_interruptible(vdev->lock)) { +			ret = -ERESTARTSYS; +			goto err; +		}  		if (video_is_registered(vdev))  			ret = vdev->fops->open(filp);  		else @@ -302,6 +329,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)  			mutex_unlock(vdev->lock);  	} +err:  	/* decrease the refcount in case of an error */  	if (ret)  		video_put(vdev); @@ -596,7 +624,12 @@ void video_unregister_device(struct video_device *vdev)  	if (!vdev || !video_is_registered(vdev))  		return; +	mutex_lock(&videodev_lock); +	/* This must be in a critical section to prevent a race with v4l2_open. +	 * Once this bit has been cleared video_get may never be called again. +	 */  	clear_bit(V4L2_FL_REGISTERED, &vdev->flags); +	mutex_unlock(&videodev_lock);  	device_unregister(&vdev->dev);  }  EXPORT_SYMBOL(video_unregister_device); diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index 0b08f96b74a..7fe6f92af48 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -35,6 +35,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)  	INIT_LIST_HEAD(&v4l2_dev->subdevs);  	spin_lock_init(&v4l2_dev->lock); +	mutex_init(&v4l2_dev->ioctl_lock);  	v4l2_dev->dev = dev;  	if (dev == NULL) {  		/* If dev == NULL, then name must be filled in by the caller */ diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 635420d8d84..019ee206cbe 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -815,7 +815,7 @@ out:  static const struct v4l2_file_operations w9966_fops = {  	.owner		= THIS_MODULE, -	.ioctl          = video_ioctl2, +	.unlocked_ioctl = video_ioctl2,  	.read           = w9966_v4l_read,  }; diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 003170ea2e3..69546e9213d 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -64,77 +64,6 @@ void pci_bus_remove_resources(struct pci_bus *bus)  	}  } -static bool pci_bus_resource_better(struct resource *res1, bool pos1, -				    struct resource *res2, bool pos2) -{ -	/* If exactly one is positive decode, always prefer that one */ -	if (pos1 != pos2) -		return pos1 ? true : false; - -	/* Prefer the one that contains the highest address */ -	if (res1->end != res2->end) -		return (res1->end > res2->end) ? true : false; - -	/* Otherwise, prefer the one with highest "center of gravity" */ -	if (res1->start != res2->start) -		return (res1->start > res2->start) ? true : false; - -	/* Otherwise, choose one arbitrarily (but consistently) */ -	return (res1 > res2) ? true : false; -} - -static bool pci_bus_resource_positive(struct pci_bus *bus, struct resource *res) -{ -	struct pci_bus_resource *bus_res; - -	/* -	 * This relies on the fact that pci_bus.resource[] refers to P2P or -	 * CardBus bridge base/limit registers, which are always positively -	 * decoded.  The pci_bus.resources list contains host bridge or -	 * subtractively decoded resources. -	 */ -	list_for_each_entry(bus_res, &bus->resources, list) { -		if (bus_res->res == res) -			return (bus_res->flags & PCI_SUBTRACTIVE_DECODE) ? -				false : true; -	} -	return true; -} - -/* - * Find the next-best bus resource after the cursor "res".  If the cursor is - * NULL, return the best resource.  "Best" means that we prefer positive - * decode regions over subtractive decode, then those at higher addresses. - */ -static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus, -						   unsigned int type, -						   struct resource *res) -{ -	bool res_pos, r_pos, prev_pos = false; -	struct resource *r, *prev = NULL; -	int i; - -	res_pos = pci_bus_resource_positive(bus, res); -	pci_bus_for_each_resource(bus, r, i) { -		if (!r) -			continue; - -		if ((r->flags & IORESOURCE_TYPE_BITS) != type) -			continue; - -		r_pos = pci_bus_resource_positive(bus, r); -		if (!res || pci_bus_resource_better(res, res_pos, r, r_pos)) { -			if (!prev || pci_bus_resource_better(r, r_pos, -							     prev, prev_pos)) { -				prev = r; -				prev_pos = r_pos; -			} -		} -	} - -	return prev; -} -  /**   * pci_bus_alloc_resource - allocate a resource from a parent bus   * @bus: PCI bus @@ -160,10 +89,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,  					  resource_size_t),  		void *alignf_data)  { -	int ret = -ENOMEM; +	int i, ret = -ENOMEM;  	struct resource *r;  	resource_size_t max = -1; -	unsigned int type = res->flags & IORESOURCE_TYPE_BITS;  	type_mask |= IORESOURCE_IO | IORESOURCE_MEM; @@ -171,9 +99,10 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,  	if (!(res->flags & IORESOURCE_MEM_64))  		max = PCIBIOS_MAX_MEM_32; -	/* Look for space at highest addresses first */ -	r = pci_bus_find_resource_prev(bus, type, NULL); -	for ( ; r; r = pci_bus_find_resource_prev(bus, type, r)) { +	pci_bus_for_each_resource(bus, r, i) { +		if (!r) +			continue; +  		/* type_mask must match */  		if ((res->flags ^ r->flags) & type_mask)  			continue; diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 0157708d474..09933eb9126 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -1417,6 +1417,11 @@ int __init enable_drhd_fault_handling(void)  			       (unsigned long long)drhd->reg_base_addr, ret);  			return -1;  		} + +		/* +		 * Clear any previous faults. +		 */ +		dmar_fault(iommu->irq, iommu);  	}  	return 0; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 6f9350cabbd..53a786fd0d4 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2329,6 +2329,9 @@ static void __devinit nvbridge_check_legacy_irq_routing(struct pci_dev *dev)  {  	u32 cfg; +	if (!pci_find_capability(dev, PCI_CAP_ID_HT)) +		return; +  	pci_read_config_dword(dev, 0x74, &cfg);  	if (cfg & ((1 << 2) | (1 << 15))) { @@ -2764,6 +2767,29 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_m  DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);  #endif /*CONFIG_MMC_RICOH_MMC*/ +#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP) +#define VTUNCERRMSK_REG	0x1ac +#define VTD_MSK_SPEC_ERRORS	(1 << 31) +/* + * This is a quirk for masking vt-d spec defined errors to platform error + * handling logic. With out this, platforms using Intel 7500, 5500 chipsets + * (and the derivative chipsets like X58 etc) seem to generate NMI/SMI (based + * on the RAS config settings of the platform) when a vt-d fault happens. + * The resulting SMI caused the system to hang. + * + * VT-d spec related errors are already handled by the VT-d OS code, so no + * need to report the same error through other channels. + */ +static void vtd_mask_spec_errors(struct pci_dev *dev) +{ +	u32 word; + +	pci_read_config_dword(dev, VTUNCERRMSK_REG, &word); +	pci_write_config_dword(dev, VTUNCERRMSK_REG, word | VTD_MSK_SPEC_ERRORS); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors); +#endif  static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,  			  struct pci_fixup *end) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 5b6bbaea59f..4a3842212c5 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1637,9 +1637,8 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,  	blk_queue_max_segment_size(q, dma_get_max_seg_size(dev)); -	/* New queue, no concurrency on queue_flags */  	if (!shost->use_clustering) -		queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q); +		q->limits.cluster = 0;  	/*  	 * set a reasonable default alignment on word boundaries: the diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index e7f1d5778ce..52389308f33 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c @@ -92,7 +92,7 @@ int cx25821_get_format_size(void)  	return ARRAY_SIZE(formats);  } -struct cx25821_fmt *format_by_fourcc(unsigned int fourcc) +struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)  {  	unsigned int i; @@ -848,7 +848,7 @@ static int video_open(struct file *file)         pix_format =  	   (dev->channels[ch_id].pixel_formats ==  	    PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; -       fh->fmt = format_by_fourcc(pix_format); +       fh->fmt = cx25821_format_by_fourcc(pix_format);         v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio); @@ -1010,7 +1010,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,         if (0 != err)  	       return err; -       fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); +       fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);         fh->vidq.field = f->fmt.pix.field;         /* check if width and height is valid based on set standard */ @@ -1119,7 +1119,7 @@ int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fo  	enum v4l2_field field;  	unsigned int maxw, maxh; -	fmt = format_by_fourcc(f->fmt.pix.pixelformat); +	fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);  	if (NULL == fmt)  		return -EINVAL; diff --git a/drivers/staging/cx25821/cx25821-video.h b/drivers/staging/cx25821/cx25821-video.h index cc6034b1a95..a2415d33235 100644 --- a/drivers/staging/cx25821/cx25821-video.h +++ b/drivers/staging/cx25821/cx25821-video.h @@ -87,7 +87,7 @@ extern unsigned int vid_limit;  #define FORMAT_FLAGS_PACKED       0x01  extern struct cx25821_fmt formats[]; -extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc); +extern struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc);  extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];  extern void cx25821_dump_video_queue(struct cx25821_dev *dev, diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 81b46585edf..c5f8e5bda2b 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -716,8 +716,8 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)  		if (msg->len < 128)  			*--dp = (msg->len << 1) | EA;  		else { -			*--dp = ((msg->len & 127) << 1) | EA; -			*--dp = (msg->len >> 6) & 0xfe; +			*--dp = (msg->len >> 7);	/* bits 7 - 15 */ +			*--dp = (msg->len & 127) << 1;	/* bits 0 - 6 */  		}  	} @@ -968,6 +968,8 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data,  {  	struct gsm_msg *msg;  	msg = gsm_data_alloc(gsm, 0, dlen + 2, gsm->ftype); +	if (msg == NULL) +		return;  	msg->data[0] = (cmd & 0xFE) << 1 | EA;	/* Clear C/R */  	msg->data[1] = (dlen << 1) | EA;  	memcpy(msg->data + 2, data, dlen); diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 9eed5b52d9d..bcc24779ba0 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -107,11 +107,19 @@ config USB_SUSPEND  	  If you are unsure about this, say N here.  config USB_OTG -	bool +	bool "OTG support"  	depends on USB && EXPERIMENTAL  	depends on USB_SUSPEND  	default n +	help +	  The most notable feature of USB OTG is support for a +	  "Dual-Role" device, which can act as either a device +	  or a host. The initial role is decided by the type of +	  plug inserted and can be changed later when two dual +	  role devices talk to each other. +	  Select this only if your board has Mini-AB/Micro-AB +	  connector.  config USB_OTG_WHITELIST  	bool "Rely on OTG Targeted Peripherals List" diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 7b5cc16e4a0..8572dad5ecb 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1047,9 +1047,9 @@ composite_unbind(struct usb_gadget *gadget)  		kfree(cdev->req->buf);  		usb_ep_free_request(gadget->ep0, cdev->req);  	} +	device_remove_file(&gadget->dev, &dev_attr_suspended);  	kfree(cdev);  	set_gadget_data(gadget, NULL); -	device_remove_file(&gadget->dev, &dev_attr_suspended);  	composite = NULL;  } @@ -1107,14 +1107,6 @@ static int composite_bind(struct usb_gadget *gadget)  	 */  	usb_ep_autoconfig_reset(cdev->gadget); -	/* standardized runtime overrides for device ID data */ -	if (idVendor) -		cdev->desc.idVendor = cpu_to_le16(idVendor); -	if (idProduct) -		cdev->desc.idProduct = cpu_to_le16(idProduct); -	if (bcdDevice) -		cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); -  	/* composite gadget needs to assign strings for whole device (like  	 * serial number), register function drivers, potentially update  	 * power state and consumption, etc @@ -1126,6 +1118,14 @@ static int composite_bind(struct usb_gadget *gadget)  	cdev->desc = *composite->dev;  	cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; +	/* standardized runtime overrides for device ID data */ +	if (idVendor) +		cdev->desc.idVendor = cpu_to_le16(idVendor); +	if (idProduct) +		cdev->desc.idProduct = cpu_to_le16(idProduct); +	if (bcdDevice) +		cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); +  	/* stirng overrides */  	if (iManufacturer || !cdev->desc.iManufacturer) {  		if (!iManufacturer && !composite->iManufacturer && diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 0fae58ef8af..1d0f45f0e7a 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1680,6 +1680,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,  				xhci->port_array[i] = (u8) -1;  			}  			/* FIXME: Should we disable the port? */ +			continue;  		}  		xhci->port_array[i] = major_revision;  		if (major_revision == 0x03) @@ -1758,16 +1759,20 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)  			return -ENOMEM;  		port_index = 0; -		for (i = 0; i < num_ports; i++) -			if (xhci->port_array[i] != 0x03) { -				xhci->usb2_ports[port_index] = -					&xhci->op_regs->port_status_base + -					NUM_PORT_REGS*i; -				xhci_dbg(xhci, "USB 2.0 port at index %u, " -						"addr = %p\n", i, -						xhci->usb2_ports[port_index]); -				port_index++; -			} +		for (i = 0; i < num_ports; i++) { +			if (xhci->port_array[i] == 0x03 || +					xhci->port_array[i] == 0 || +					xhci->port_array[i] == -1) +				continue; + +			xhci->usb2_ports[port_index] = +				&xhci->op_regs->port_status_base + +				NUM_PORT_REGS*i; +			xhci_dbg(xhci, "USB 2.0 port at index %u, " +					"addr = %p\n", i, +					xhci->usb2_ports[port_index]); +			port_index++; +		}  	}  	if (xhci->num_usb3_ports) {  		xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)* diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 796e2f68f74..4ff21587ab0 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -3,7 +3,7 @@  /*   *	uss720.c  --  USS720 USB Parport Cable.   * - *	Copyright (C) 1999, 2005 + *	Copyright (C) 1999, 2005, 2010   *	    Thomas Sailer (t.sailer@alumni.ethz.ch)   *   *	This program is free software; you can redistribute it and/or modify @@ -776,6 +776,8 @@ static const struct usb_device_id uss720_table[] = {  	{ USB_DEVICE(0x0557, 0x2001) },  	{ USB_DEVICE(0x0729, 0x1284) },  	{ USB_DEVICE(0x1293, 0x0002) }, +	{ USB_DEVICE(0x1293, 0x0002) }, +	{ USB_DEVICE(0x050d, 0x0002) },  	{ }						/* Terminating entry */  }; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 6a50965e23f..2dec5001352 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -796,6 +796,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, +	{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },  	{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),  		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },  	{ },					/* Optional parameter entry */ diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 1286f1e23d8..bf086728548 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1081,6 +1081,11 @@  #define MJSG_HD_RADIO_PID	0x937C  /* + * D.O.Tec products (http://www.directout.eu) + */ +#define FTDI_DOTEC_PID 0x9868 + +/*   * Xverve Signalyzer tools (http://www.signalyzer.com/)   */  #define XVERVE_SIGNALYZER_ST_PID	0xBCA0 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6ccdd3dd525..fcc1e32ce25 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -481,6 +481,13 @@ UNUSUAL_DEV(  0x04e8, 0x507c, 0x0220, 0x0220,  		USB_SC_DEVICE, USB_PR_DEVICE, NULL,  		US_FL_MAX_SECTORS_64), +/* Reported by Vitaly Kuznetsov <vitty@altlinux.ru> */ +UNUSUAL_DEV(  0x04e8, 0x5122, 0x0000, 0x9999, +		"Samsung", +		"YP-CP3", +		USB_SC_DEVICE, USB_PR_DEVICE, NULL, +		US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG), +  /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.   * Device uses standards-violating 32-byte Bulk Command Block Wrappers and   * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011. diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 455c6055325..083c8fe53e2 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -1,7 +1,7 @@  config FB_OMAP  	tristate "OMAP frame buffer support (EXPERIMENTAL)" -	depends on FB && ARCH_OMAP && (OMAP2_DSS = "n") - +	depends on FB && (OMAP2_DSS = "n") +	depends on ARCH_OMAP1 || ARCH_OMAP2 || ARCH_OMAP3  	select FB_CFB_FILLRECT  	select FB_CFB_COPYAREA  	select FB_CFB_IMAGEBLIT diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c index 2fd7e5271be..9441e2eb3de 100644 --- a/drivers/video/omap2/vram.c +++ b/drivers/video/omap2/vram.c @@ -551,7 +551,7 @@ void __init omap_vram_reserve_sdram_memblock(void)  	if (!size)  		return; -	size = PAGE_ALIGN(size); +	size = ALIGN(size, SZ_2M);  	if (paddr) {  		if (paddr & ~PAGE_MASK) { @@ -576,7 +576,7 @@ void __init omap_vram_reserve_sdram_memblock(void)  			return;  		}  	} else { -		paddr = memblock_alloc(size, PAGE_SIZE); +		paddr = memblock_alloc(size, SZ_2M);  	}  	memblock_free(paddr, size); diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c index 6f044447359..659f532d26a 100644 --- a/fs/btrfs/export.c +++ b/fs/btrfs/export.c @@ -166,7 +166,7 @@ static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh,  static struct dentry *btrfs_get_parent(struct dentry *child)  {  	struct inode *dir = child->d_inode; -	static struct dentry *dentry; +	struct dentry *dentry;  	struct btrfs_root *root = BTRFS_I(dir)->root;  	struct btrfs_path *path;  	struct extent_buffer *leaf; diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 158c700fdca..d902948a90d 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -40,7 +40,8 @@ int ceph_init_dentry(struct dentry *dentry)  	if (dentry->d_fsdata)  		return 0; -	if (ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP) +	if (dentry->d_parent == NULL ||   /* nfs fh_to_dentry */ +	    ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)  		dentry->d_op = &ceph_dentry_ops;  	else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)  		dentry->d_op = &ceph_snapdir_dentry_ops; diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 8d79b8912e3..7d0e4a82d89 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -282,7 +282,8 @@ int ceph_release(struct inode *inode, struct file *file)  static int striped_read(struct inode *inode,  			u64 off, u64 len,  			struct page **pages, int num_pages, -			int *checkeof, bool align_to_pages) +			int *checkeof, bool align_to_pages, +			unsigned long buf_align)  {  	struct ceph_fs_client *fsc = ceph_inode_to_client(inode);  	struct ceph_inode_info *ci = ceph_inode(inode); @@ -307,7 +308,7 @@ static int striped_read(struct inode *inode,  more:  	if (align_to_pages) -		page_align = (pos - io_align) & ~PAGE_MASK; +		page_align = (pos - io_align + buf_align) & ~PAGE_MASK;  	else  		page_align = pos & ~PAGE_MASK;  	this_len = left; @@ -376,16 +377,18 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,  	struct inode *inode = file->f_dentry->d_inode;  	struct page **pages;  	u64 off = *poff; -	int num_pages = calc_pages_for(off, len); -	int ret; +	int num_pages, ret;  	dout("sync_read on file %p %llu~%u %s\n", file, off, len,  	     (file->f_flags & O_DIRECT) ? "O_DIRECT" : ""); -	if (file->f_flags & O_DIRECT) -		pages = ceph_get_direct_page_vector(data, num_pages); -	else +	if (file->f_flags & O_DIRECT) { +		num_pages = calc_pages_for((unsigned long)data, len); +		pages = ceph_get_direct_page_vector(data, num_pages, true); +	} else { +		num_pages = calc_pages_for(off, len);  		pages = ceph_alloc_page_vector(num_pages, GFP_NOFS); +	}  	if (IS_ERR(pages))  		return PTR_ERR(pages); @@ -400,7 +403,8 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,  		goto done;  	ret = striped_read(inode, off, len, pages, num_pages, checkeof, -			   file->f_flags & O_DIRECT); +			   file->f_flags & O_DIRECT, +			   (unsigned long)data & ~PAGE_MASK);  	if (ret >= 0 && (file->f_flags & O_DIRECT) == 0)  		ret = ceph_copy_page_vector_to_user(pages, data, off, ret); @@ -409,7 +413,7 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,  done:  	if (file->f_flags & O_DIRECT) -		ceph_put_page_vector(pages, num_pages); +		ceph_put_page_vector(pages, num_pages, true);  	else  		ceph_release_page_vector(pages, num_pages);  	dout("sync_read result %d\n", ret); @@ -456,6 +460,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,  	int do_sync = 0;  	int check_caps = 0;  	int page_align, io_align; +	unsigned long buf_align;  	int ret;  	struct timespec mtime = CURRENT_TIME; @@ -471,6 +476,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,  		pos = *offset;  	io_align = pos & ~PAGE_MASK; +	buf_align = (unsigned long)data & ~PAGE_MASK;  	ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left);  	if (ret < 0) @@ -496,12 +502,15 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,  	 */  more:  	len = left; -	if (file->f_flags & O_DIRECT) +	if (file->f_flags & O_DIRECT) {  		/* write from beginning of first page, regardless of  		   io alignment */ -		page_align = (pos - io_align) & ~PAGE_MASK; -	else +		page_align = (pos - io_align + buf_align) & ~PAGE_MASK; +		num_pages = calc_pages_for((unsigned long)data, len); +	} else {  		page_align = pos & ~PAGE_MASK; +		num_pages = calc_pages_for(pos, len); +	}  	req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,  				    ceph_vino(inode), pos, &len,  				    CEPH_OSD_OP_WRITE, flags, @@ -512,10 +521,8 @@ more:  	if (!req)  		return -ENOMEM; -	num_pages = calc_pages_for(pos, len); -  	if (file->f_flags & O_DIRECT) { -		pages = ceph_get_direct_page_vector(data, num_pages); +		pages = ceph_get_direct_page_vector(data, num_pages, false);  		if (IS_ERR(pages)) {  			ret = PTR_ERR(pages);  			goto out; @@ -565,7 +572,7 @@ more:  	}  	if (file->f_flags & O_DIRECT) -		ceph_put_page_vector(pages, num_pages); +		ceph_put_page_vector(pages, num_pages, false);  	else if (file->f_flags & O_SYNC)  		ceph_release_page_vector(pages, num_pages); diff --git a/fs/namei.c b/fs/namei.c index 5362af9b737..4ff7ca53053 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1748,6 +1748,9 @@ struct file *do_filp_open(int dfd, const char *pathname,  	if (!(open_flag & O_CREAT))  		mode = 0; +	/* Must never be set by userspace */ +	open_flag &= ~FMODE_NONOTIFY; +  	/*  	 * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only  	 * check for O_DSYNC if the need any syncing at all we enforce it's diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c index 33ad25ddd5c..caf9a6a3fb5 100644 --- a/fs/nilfs2/gcinode.c +++ b/fs/nilfs2/gcinode.c @@ -176,7 +176,6 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh)  int nilfs_init_gcinode(struct inode *inode)  {  	struct nilfs_inode_info *ii = NILFS_I(inode); -	struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;  	inode->i_mode = S_IFREG;  	mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); @@ -186,14 +185,6 @@ int nilfs_init_gcinode(struct inode *inode)  	ii->i_flags = 0;  	nilfs_bmap_init_gc(ii->i_bmap); -	/* -	 * Add the inode to GC inode list. Garbage Collection -	 * is serialized and no two processes manipulate the -	 * list simultaneously. -	 */ -	igrab(inode); -	list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes); -  	return 0;  } diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index e00d9457c25..b185e937a33 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -337,6 +337,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,  				   struct nilfs_argv *argv, void *buf)  {  	size_t nmembs = argv->v_nmembs; +	struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;  	struct inode *inode;  	struct nilfs_vdesc *vdesc;  	struct buffer_head *bh, *n; @@ -353,6 +354,17 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,  			ret = PTR_ERR(inode);  			goto failed;  		} +		if (list_empty(&NILFS_I(inode)->i_dirty)) { +			/* +			 * Add the inode to GC inode list. Garbage Collection +			 * is serialized and no two processes manipulate the +			 * list simultaneously. +			 */ +			igrab(inode); +			list_add(&NILFS_I(inode)->i_dirty, +				 &nilfs->ns_gc_inodes); +		} +  		do {  			ret = nilfs_ioctl_move_inode_block(inode, vdesc,  							   &buffers); diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index b04f88eed09..f35794b97e8 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -92,7 +92,11 @@ static int fanotify_get_response_from_access(struct fsnotify_group *group,  	pr_debug("%s: group=%p event=%p\n", __func__, group, event); -	wait_event(group->fanotify_data.access_waitq, event->response); +	wait_event(group->fanotify_data.access_waitq, event->response || +				atomic_read(&group->fanotify_data.bypass_perm)); + +	if (!event->response) /* bypass_perm set */ +		return 0;  	/* userspace responded, convert to something usable */  	spin_lock(&event->lock); diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 063224812b7..8b61220cffc 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -106,20 +106,29 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)  	return client_fd;  } -static ssize_t fill_event_metadata(struct fsnotify_group *group, +static int fill_event_metadata(struct fsnotify_group *group,  				   struct fanotify_event_metadata *metadata,  				   struct fsnotify_event *event)  { +	int ret = 0; +  	pr_debug("%s: group=%p metadata=%p event=%p\n", __func__,  		 group, metadata, event);  	metadata->event_len = FAN_EVENT_METADATA_LEN; +	metadata->metadata_len = FAN_EVENT_METADATA_LEN;  	metadata->vers = FANOTIFY_METADATA_VERSION;  	metadata->mask = event->mask & FAN_ALL_OUTGOING_EVENTS;  	metadata->pid = pid_vnr(event->tgid); -	metadata->fd = create_fd(group, event); +	if (unlikely(event->mask & FAN_Q_OVERFLOW)) +		metadata->fd = FAN_NOFD; +	else { +		metadata->fd = create_fd(group, event); +		if (metadata->fd < 0) +			ret = metadata->fd; +	} -	return metadata->fd; +	return ret;  }  #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS @@ -200,7 +209,7 @@ static int prepare_for_access_response(struct fsnotify_group *group,  	mutex_lock(&group->fanotify_data.access_mutex); -	if (group->fanotify_data.bypass_perm) { +	if (atomic_read(&group->fanotify_data.bypass_perm)) {  		mutex_unlock(&group->fanotify_data.access_mutex);  		kmem_cache_free(fanotify_response_event_cache, re);  		event->response = FAN_ALLOW; @@ -257,24 +266,34 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,  	pr_debug("%s: group=%p event=%p\n", __func__, group, event); -	fd = fill_event_metadata(group, &fanotify_event_metadata, event); -	if (fd < 0) -		return fd; +	ret = fill_event_metadata(group, &fanotify_event_metadata, event); +	if (ret < 0) +		goto out; +	fd = fanotify_event_metadata.fd;  	ret = prepare_for_access_response(group, event, fd);  	if (ret)  		goto out_close_fd;  	ret = -EFAULT; -	if (copy_to_user(buf, &fanotify_event_metadata, FAN_EVENT_METADATA_LEN)) +	if (copy_to_user(buf, &fanotify_event_metadata, +			 fanotify_event_metadata.event_len))  		goto out_kill_access_response; -	return FAN_EVENT_METADATA_LEN; +	return fanotify_event_metadata.event_len;  out_kill_access_response:  	remove_access_response(group, event, fd);  out_close_fd: -	sys_close(fd); +	if (fd != FAN_NOFD) +		sys_close(fd); +out: +#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS +	if (event->mask & FAN_ALL_PERM_EVENTS) { +		event->response = FAN_DENY; +		wake_up(&group->fanotify_data.access_waitq); +	} +#endif  	return ret;  } @@ -382,7 +401,7 @@ static int fanotify_release(struct inode *ignored, struct file *file)  	mutex_lock(&group->fanotify_data.access_mutex); -	group->fanotify_data.bypass_perm = true; +	atomic_inc(&group->fanotify_data.bypass_perm);  	list_for_each_entry_safe(re, lre, &group->fanotify_data.access_list, list) {  		pr_debug("%s: found group=%p re=%p event=%p\n", __func__, group, @@ -586,11 +605,10 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,  {  	struct fsnotify_mark *fsn_mark;  	__u32 added; +	int ret = 0;  	fsn_mark = fsnotify_find_vfsmount_mark(group, mnt);  	if (!fsn_mark) { -		int ret; -  		if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)  			return -ENOSPC; @@ -600,17 +618,16 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,  		fsnotify_init_mark(fsn_mark, fanotify_free_mark);  		ret = fsnotify_add_mark(fsn_mark, group, NULL, mnt, 0); -		if (ret) { -			fanotify_free_mark(fsn_mark); -			return ret; -		} +		if (ret) +			goto err;  	}  	added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); -	fsnotify_put_mark(fsn_mark); +  	if (added & ~mnt->mnt_fsnotify_mask)  		fsnotify_recalc_vfsmount_mask(mnt); - -	return 0; +err: +	fsnotify_put_mark(fsn_mark); +	return ret;  }  static int fanotify_add_inode_mark(struct fsnotify_group *group, @@ -619,6 +636,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,  {  	struct fsnotify_mark *fsn_mark;  	__u32 added; +	int ret = 0;  	pr_debug("%s: group=%p inode=%p\n", __func__, group, inode); @@ -634,8 +652,6 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,  	fsn_mark = fsnotify_find_inode_mark(group, inode);  	if (!fsn_mark) { -		int ret; -  		if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)  			return -ENOSPC; @@ -645,16 +661,16 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,  		fsnotify_init_mark(fsn_mark, fanotify_free_mark);  		ret = fsnotify_add_mark(fsn_mark, group, inode, NULL, 0); -		if (ret) { -			fanotify_free_mark(fsn_mark); -			return ret; -		} +		if (ret) +			goto err;  	}  	added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); -	fsnotify_put_mark(fsn_mark); +  	if (added & ~inode->i_fsnotify_mask)  		fsnotify_recalc_inode_mask(inode); -	return 0; +err: +	fsnotify_put_mark(fsn_mark); +	return ret;  }  /* fanotify syscalls */ @@ -687,8 +703,10 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)  	/* fsnotify_alloc_group takes a ref.  Dropped in fanotify_release */  	group = fsnotify_alloc_group(&fanotify_fsnotify_ops); -	if (IS_ERR(group)) +	if (IS_ERR(group)) { +		free_uid(user);  		return PTR_ERR(group); +	}  	group->fanotify_data.user = user;  	atomic_inc(&user->fanotify_listeners); @@ -698,6 +716,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)  	mutex_init(&group->fanotify_data.access_mutex);  	init_waitqueue_head(&group->fanotify_data.access_waitq);  	INIT_LIST_HEAD(&group->fanotify_data.access_list); +	atomic_set(&group->fanotify_data.bypass_perm, 0);  #endif  	switch (flags & FAN_ALL_CLASS_BITS) {  	case FAN_CLASS_NOTIF: @@ -764,8 +783,10 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,  	if (flags & ~FAN_ALL_MARK_FLAGS)  		return -EINVAL;  	switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) { -	case FAN_MARK_ADD: +	case FAN_MARK_ADD:		/* fallthrough */  	case FAN_MARK_REMOVE: +		if (!mask) +			return -EINVAL;  	case FAN_MARK_FLUSH:  		break;  	default: diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 444c305a468..4cd5d5d78f9 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -752,6 +752,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)  	if (ret >= 0)  		return ret; +	fsnotify_put_group(group);  	atomic_dec(&user->inotify_devs);  out_free_uid:  	free_uid(user); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index aae86fd10c4..36ab42c9bb9 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -250,7 +250,7 @@ struct queue_limits {  	unsigned char		misaligned;  	unsigned char		discard_misaligned; -	unsigned char		no_cluster; +	unsigned char		cluster;  	signed char		discard_zeroes_data;  }; @@ -380,7 +380,6 @@ struct request_queue  #endif  }; -#define QUEUE_FLAG_CLUSTER	0	/* cluster several segments into 1 */  #define QUEUE_FLAG_QUEUED	1	/* uses generic tag queueing */  #define QUEUE_FLAG_STOPPED	2	/* queue is stopped */  #define	QUEUE_FLAG_SYNCFULL	3	/* read queue has been filled */ @@ -403,7 +402,6 @@ struct request_queue  #define QUEUE_FLAG_SECDISCARD  19	/* supports SECDISCARD */  #define QUEUE_FLAG_DEFAULT	((1 << QUEUE_FLAG_IO_STAT) |		\ -				 (1 << QUEUE_FLAG_CLUSTER) |		\  				 (1 << QUEUE_FLAG_STACKABLE)	|	\  				 (1 << QUEUE_FLAG_SAME_COMP)	|	\  				 (1 << QUEUE_FLAG_ADD_RANDOM)) @@ -510,6 +508,11 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)  #define rq_data_dir(rq)		((rq)->cmd_flags & 1) +static inline unsigned int blk_queue_cluster(struct request_queue *q) +{ +	return q->limits.cluster; +} +  /*   * We regard a request as sync, if either a read or a sync write   */ @@ -805,6 +808,7 @@ extern struct request_queue *blk_init_allocated_queue(struct request_queue *,  extern void blk_cleanup_queue(struct request_queue *);  extern void blk_queue_make_request(struct request_queue *, make_request_fn *);  extern void blk_queue_bounce_limit(struct request_queue *, u64); +extern void blk_limits_max_hw_sectors(struct queue_limits *, unsigned int);  extern void blk_queue_max_hw_sectors(struct request_queue *, unsigned int);  extern void blk_queue_max_segments(struct request_queue *, unsigned short);  extern void blk_queue_max_segment_size(struct request_queue *, unsigned int); diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index 266ab929123..499dfe982a0 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -105,6 +105,8 @@ extern void *__alloc_bootmem_low_node(pg_data_t *pgdat,  #define alloc_bootmem(x) \  	__alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) +#define alloc_bootmem_align(x, align) \ +	__alloc_bootmem(x, align, __pa(MAX_DMA_ADDRESS))  #define alloc_bootmem_nopanic(x) \  	__alloc_bootmem_nopanic(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))  #define alloc_bootmem_pages(x) \ diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h index 9e76d35670d..72c72bfccb8 100644 --- a/include/linux/ceph/libceph.h +++ b/include/linux/ceph/libceph.h @@ -227,8 +227,10 @@ extern int ceph_open_session(struct ceph_client *client);  extern void ceph_release_page_vector(struct page **pages, int num_pages);  extern struct page **ceph_get_direct_page_vector(const char __user *data, -						 int num_pages); -extern void ceph_put_page_vector(struct page **pages, int num_pages); +						 int num_pages, +						 bool write_page); +extern void ceph_put_page_vector(struct page **pages, int num_pages, +				 bool dirty);  extern void ceph_release_page_vector(struct page **pages, int num_pages);  extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);  extern int ceph_copy_user_to_page_vector(struct page **pages, diff --git a/include/linux/cnt32_to_63.h b/include/linux/cnt32_to_63.h index 7605fdd1eb6..e3d8bf26e5e 100644 --- a/include/linux/cnt32_to_63.h +++ b/include/linux/cnt32_to_63.h @@ -61,13 +61,31 @@ union cnt32_to_63 {   *   * 2) this code must not be preempted for a duration longer than the   *    32-bit counter half period minus the longest period between two - *    calls to this code. + *    calls to this code;   *   * Those requirements ensure proper update to the state bit in memory.   * This is usually not a problem in practice, but if it is then a kernel   * timer should be scheduled to manage for this code to be executed often   * enough.   * + * And finally: + * + * 3) the cnt_lo argument must be seen as a globally incrementing value, + *    meaning that it should be a direct reference to the counter data which + *    can be evaluated according to a specific ordering within the macro, + *    and not the result of a previous evaluation stored in a variable. + * + * For example, this is wrong: + * + *	u32 partial = get_hw_count(); + *	u64 full = cnt32_to_63(partial); + *	return full; + * + * This is fine: + * + *	u64 full = cnt32_to_63(get_hw_count()); + *	return full; + *   * Note that the top bit (bit 63) in the returned value should be considered   * as garbage.  It is not cleared here because callers are likely to use a   * multiplier on the returned value which can get rid of the top bit diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index 0f0121467fc..6c6133f76e1 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -83,11 +83,13 @@  				 FAN_ALL_PERM_EVENTS |\  				 FAN_Q_OVERFLOW) -#define FANOTIFY_METADATA_VERSION	2 +#define FANOTIFY_METADATA_VERSION	3  struct fanotify_event_metadata {  	__u32 event_len; -	__u32 vers; +	__u8 vers; +	__u8 reserved; +	__u16 metadata_len;  	__aligned_u64 mask;  	__s32 fd;  	__s32 pid; @@ -96,11 +98,13 @@ struct fanotify_event_metadata {  struct fanotify_response {  	__s32 fd;  	__u32 response; -} __attribute__ ((packed)); +};  /* Legit userspace responses to a _PERM event */  #define FAN_ALLOW	0x01  #define FAN_DENY	0x02 +/* No fd set in event */ +#define FAN_NOFD	-1  /* Helper functions to deal with fanotify_event_metadata buffers */  #define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata)) diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 5c185fa2708..b10bcdeaef7 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -235,9 +235,6 @@ static inline void fsnotify_open(struct file *file)  	if (S_ISDIR(inode->i_mode))  		mask |= FS_ISDIR; -	/* FMODE_NONOTIFY must never be set from user */ -	file->f_mode &= ~FMODE_NONOTIFY; -  	fsnotify_parent(path, NULL, mask);  	fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);  } diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 0a68f924f06..7380763595d 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -166,7 +166,7 @@ struct fsnotify_group {  			struct mutex access_mutex;  			struct list_head access_list;  			wait_queue_head_t access_waitq; -			bool bypass_perm; /* protected by access_mutex */ +			atomic_t bypass_perm;  #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */  			int f_flags;  			unsigned int max_marks; diff --git a/include/linux/input.h b/include/linux/input.h index a8af21d42bc..9777668883b 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -104,8 +104,10 @@ struct input_keymap_entry {  #define EVIOCGREP		_IOR('E', 0x03, unsigned int[2])	/* get repeat settings */  #define EVIOCSREP		_IOW('E', 0x03, unsigned int[2])	/* set repeat settings */ -#define EVIOCGKEYCODE		_IOR('E', 0x04, struct input_keymap_entry)	/* get keycode */ -#define EVIOCSKEYCODE		_IOW('E', 0x04, struct input_keymap_entry)	/* set keycode */ +#define EVIOCGKEYCODE		_IOR('E', 0x04, unsigned int[2])        /* get keycode */ +#define EVIOCGKEYCODE_V2	_IOR('E', 0x04, struct input_keymap_entry) +#define EVIOCSKEYCODE		_IOW('E', 0x04, unsigned int[2])        /* set keycode */ +#define EVIOCSKEYCODE_V2	_IOW('E', 0x04, struct input_keymap_entry)  #define EVIOCGNAME(len)		_IOC(_IOC_READ, 'E', 0x06, len)		/* get device name */  #define EVIOCGPHYS(len)		_IOC(_IOC_READ, 'E', 0x07, len)		/* get physical location */ diff --git a/include/linux/ioport.h b/include/linux/ioport.h index d377ea815d4..e9bb22cba76 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -112,7 +112,6 @@ struct resource_list {  /* PC/ISA/whatever - the normal PC address spaces: IO and memory */  extern struct resource ioport_resource;  extern struct resource iomem_resource; -extern int resource_alloc_from_bottom;  extern struct resource *request_resource_conflict(struct resource *root, struct resource *new);  extern int request_resource(struct resource *root, struct resource *new); @@ -124,6 +123,7 @@ extern void reserve_region_with_split(struct resource *root,  extern struct resource *insert_resource_conflict(struct resource *parent, struct resource *new);  extern int insert_resource(struct resource *parent, struct resource *new);  extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new); +extern void arch_remove_reservations(struct resource *avail);  extern int allocate_resource(struct resource *root, struct resource *new,  			     resource_size_t size, resource_size_t min,  			     resource_size_t max, resource_size_t align, diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index de2c41758e2..4f1279e105e 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -887,6 +887,7 @@ struct perf_cpu_context {  	int				exclusive;  	struct list_head		rotation_list;  	int				jiffies_interval; +	struct pmu			*active_pmu;  };  struct perf_output_handle { diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 3ec2358f869..d19f1cca7f7 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -77,7 +77,8 @@ static inline void device_set_run_wake(struct device *dev, bool enable)  static inline bool pm_runtime_suspended(struct device *dev)  { -	return dev->power.runtime_status == RPM_SUSPENDED; +	return dev->power.runtime_status == RPM_SUSPENDED +		&& !dev->power.disable_depth;  }  static inline void pm_runtime_mark_last_busy(struct device *dev) diff --git a/include/linux/sched.h b/include/linux/sched.h index 2c79e921a68..223874538b3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -143,7 +143,7 @@ extern unsigned long nr_iowait_cpu(int cpu);  extern unsigned long this_cpu_load(void); -extern void calc_global_load(void); +extern void calc_global_load(unsigned long ticks);  extern unsigned long get_parent_ip(unsigned long addr); diff --git a/include/linux/ssb/ssb_driver_gige.h b/include/linux/ssb/ssb_driver_gige.h index 942e3873690..eba52a10053 100644 --- a/include/linux/ssb/ssb_driver_gige.h +++ b/include/linux/ssb/ssb_driver_gige.h @@ -96,16 +96,21 @@ static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)  	return 0;  } -extern char * nvram_get(const char *name); +#ifdef CONFIG_BCM47XX +#include <asm/mach-bcm47xx/nvram.h>  /* Get the device MAC address */  static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)  { -#ifdef CONFIG_BCM47XX -	char *res = nvram_get("et0macaddr"); -	if (res) -		memcpy(macaddr, res, 6); -#endif +	char buf[20]; +	if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0) +		return; +	nvram_parse_macaddr(buf, macaddr);  } +#else +static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr) +{ +} +#endif  extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,  					  struct pci_dev *pdev); diff --git a/include/media/saa7146.h b/include/media/saa7146.h index 7a9f76ecbbb..ac7ce00f39c 100644 --- a/include/media/saa7146.h +++ b/include/media/saa7146.h @@ -161,7 +161,7 @@ extern struct list_head saa7146_devices;  extern struct mutex saa7146_devices_lock;  int saa7146_register_extension(struct saa7146_extension*);  int saa7146_unregister_extension(struct saa7146_extension*); -struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc); +struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc);  int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt);  void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt);  int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length ); diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index 6648036b728..b16f307d471 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -51,6 +51,8 @@ struct v4l2_device {  			unsigned int notification, void *arg);  	/* The control handler. May be NULL. */  	struct v4l2_ctrl_handler *ctrl_handler; +	/* BKL replacement mutex. Temporary solution only. */ +	struct mutex ioctl_lock;  };  /* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev. diff --git a/kernel/fork.c b/kernel/fork.c index 3b159c5991b..5447dc7defa 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -273,6 +273,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)  	setup_thread_stack(tsk, orig);  	clear_user_return_notifier(tsk); +	clear_tsk_need_resched(tsk);  	stackend = end_of_stack(tsk);  	*stackend = STACK_END_MAGIC;	/* for overflow detection */ diff --git a/kernel/perf_event.c b/kernel/perf_event.c index eac7e336433..2870feee81d 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -3824,6 +3824,8 @@ static void perf_event_task_event(struct perf_task_event *task_event)  	rcu_read_lock();  	list_for_each_entry_rcu(pmu, &pmus, entry) {  		cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); +		if (cpuctx->active_pmu != pmu) +			goto next;  		perf_event_task_ctx(&cpuctx->ctx, task_event);  		ctx = task_event->task_ctx; @@ -3959,6 +3961,8 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)  	rcu_read_lock();  	list_for_each_entry_rcu(pmu, &pmus, entry) {  		cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); +		if (cpuctx->active_pmu != pmu) +			goto next;  		perf_event_comm_ctx(&cpuctx->ctx, comm_event);  		ctxn = pmu->task_ctx_nr; @@ -4144,6 +4148,8 @@ got_name:  	rcu_read_lock();  	list_for_each_entry_rcu(pmu, &pmus, entry) {  		cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); +		if (cpuctx->active_pmu != pmu) +			goto next;  		perf_event_mmap_ctx(&cpuctx->ctx, mmap_event,  					vma->vm_flags & VM_EXEC); @@ -4713,7 +4719,7 @@ static int perf_swevent_init(struct perf_event *event)  		break;  	} -	if (event_id > PERF_COUNT_SW_MAX) +	if (event_id >= PERF_COUNT_SW_MAX)  		return -ENOENT;  	if (!event->parent) { @@ -5145,20 +5151,36 @@ static void *find_pmu_context(int ctxn)  	return NULL;  } -static void free_pmu_context(void * __percpu cpu_context) +static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu)  { -	struct pmu *pmu; +	int cpu; + +	for_each_possible_cpu(cpu) { +		struct perf_cpu_context *cpuctx; + +		cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); + +		if (cpuctx->active_pmu == old_pmu) +			cpuctx->active_pmu = pmu; +	} +} + +static void free_pmu_context(struct pmu *pmu) +{ +	struct pmu *i;  	mutex_lock(&pmus_lock);  	/*  	 * Like a real lame refcount.  	 */ -	list_for_each_entry(pmu, &pmus, entry) { -		if (pmu->pmu_cpu_context == cpu_context) +	list_for_each_entry(i, &pmus, entry) { +		if (i->pmu_cpu_context == pmu->pmu_cpu_context) { +			update_pmu_context(i, pmu);  			goto out; +		}  	} -	free_percpu(cpu_context); +	free_percpu(pmu->pmu_cpu_context);  out:  	mutex_unlock(&pmus_lock);  } @@ -5190,6 +5212,7 @@ int perf_pmu_register(struct pmu *pmu)  		cpuctx->ctx.pmu = pmu;  		cpuctx->jiffies_interval = 1;  		INIT_LIST_HEAD(&cpuctx->rotation_list); +		cpuctx->active_pmu = pmu;  	}  got_cpu_context: @@ -5241,7 +5264,7 @@ void perf_pmu_unregister(struct pmu *pmu)  	synchronize_rcu();  	free_percpu(pmu->pmu_disable_count); -	free_pmu_context(pmu->pmu_cpu_context); +	free_pmu_context(pmu);  }  struct pmu *perf_init_event(struct perf_event *event) diff --git a/kernel/power/swap.c b/kernel/power/swap.c index baf667bb279..8c7e4832b9b 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -30,7 +30,7 @@  #include "power.h" -#define HIBERNATE_SIG	"LINHIB0001" +#define HIBERNATE_SIG	"S1SUSPEND"  /*   *	The swap map is a data structure used for keeping track of each page diff --git a/kernel/power/user.c b/kernel/power/user.c index 1b2ea31e6bd..c36c3b9e8a8 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -137,7 +137,7 @@ static int snapshot_release(struct inode *inode, struct file *filp)  	free_all_swap_pages(data->swap);  	if (data->frozen)  		thaw_processes(); -	pm_notifier_call_chain(data->mode == O_WRONLY ? +	pm_notifier_call_chain(data->mode == O_RDONLY ?  			PM_POST_HIBERNATION : PM_POST_RESTORE);  	atomic_inc(&snapshot_device_available); diff --git a/kernel/resource.c b/kernel/resource.c index 9fad33efd0d..798e2fae2a0 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -40,23 +40,6 @@ EXPORT_SYMBOL(iomem_resource);  static DEFINE_RWLOCK(resource_lock); -/* - * By default, we allocate free space bottom-up.  The architecture can request - * top-down by clearing this flag.  The user can override the architecture's - * choice with the "resource_alloc_from_bottom" kernel boot option, but that - * should only be a debugging tool. - */ -int resource_alloc_from_bottom = 1; - -static __init int setup_alloc_from_bottom(char *s) -{ -	printk(KERN_INFO -	       "resource: allocating from bottom-up; please report a bug\n"); -	resource_alloc_from_bottom = 1; -	return 0; -} -early_param("resource_alloc_from_bottom", setup_alloc_from_bottom); -  static void *r_next(struct seq_file *m, void *v, loff_t *pos)  {  	struct resource *p = v; @@ -374,6 +357,10 @@ int __weak page_is_ram(unsigned long pfn)  	return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1;  } +void __weak arch_remove_reservations(struct resource *avail) +{ +} +  static resource_size_t simple_align_resource(void *data,  					     const struct resource *avail,  					     resource_size_t size, @@ -397,74 +384,7 @@ static bool resource_contains(struct resource *res1, struct resource *res2)  }  /* - * Find the resource before "child" in the sibling list of "root" children. - */ -static struct resource *find_sibling_prev(struct resource *root, struct resource *child) -{ -	struct resource *this; - -	for (this = root->child; this; this = this->sibling) -		if (this->sibling == child) -			return this; - -	return NULL; -} - -/*   * Find empty slot in the resource tree given range and alignment. - * This version allocates from the end of the root resource first. - */ -static int find_resource_from_top(struct resource *root, struct resource *new, -				  resource_size_t size, resource_size_t min, -				  resource_size_t max, resource_size_t align, -				  resource_size_t (*alignf)(void *, -						   const struct resource *, -						   resource_size_t, -						   resource_size_t), -				  void *alignf_data) -{ -	struct resource *this; -	struct resource tmp, avail, alloc; - -	tmp.start = root->end; -	tmp.end = root->end; - -	this = find_sibling_prev(root, NULL); -	for (;;) { -		if (this) { -			if (this->end < root->end) -				tmp.start = this->end + 1; -		} else -			tmp.start = root->start; - -		resource_clip(&tmp, min, max); - -		/* Check for overflow after ALIGN() */ -		avail = *new; -		avail.start = ALIGN(tmp.start, align); -		avail.end = tmp.end; -		if (avail.start >= tmp.start) { -			alloc.start = alignf(alignf_data, &avail, size, align); -			alloc.end = alloc.start + size - 1; -			if (resource_contains(&avail, &alloc)) { -				new->start = alloc.start; -				new->end = alloc.end; -				return 0; -			} -		} - -		if (!this || this->start == root->start) -			break; - -		tmp.end = this->start - 1; -		this = find_sibling_prev(root, this); -	} -	return -EBUSY; -} - -/* - * Find empty slot in the resource tree given range and alignment. - * This version allocates from the beginning of the root resource first.   */  static int find_resource(struct resource *root, struct resource *new,  			 resource_size_t size, resource_size_t min, @@ -478,23 +398,24 @@ static int find_resource(struct resource *root, struct resource *new,  	struct resource *this = root->child;  	struct resource tmp = *new, avail, alloc; +	tmp.flags = new->flags;  	tmp.start = root->start;  	/* -	 * Skip past an allocated resource that starts at 0, since the -	 * assignment of this->start - 1 to tmp->end below would cause an -	 * underflow. +	 * Skip past an allocated resource that starts at 0, since the assignment +	 * of this->start - 1 to tmp->end below would cause an underflow.  	 */  	if (this && this->start == 0) {  		tmp.start = this->end + 1;  		this = this->sibling;  	} -	for (;;) { +	for(;;) {  		if (this)  			tmp.end = this->start - 1;  		else  			tmp.end = root->end;  		resource_clip(&tmp, min, max); +		arch_remove_reservations(&tmp);  		/* Check for overflow after ALIGN() */  		avail = *new; @@ -509,10 +430,8 @@ static int find_resource(struct resource *root, struct resource *new,  				return 0;  			}  		} -  		if (!this)  			break; -  		tmp.start = this->end + 1;  		this = this->sibling;  	} @@ -545,10 +464,7 @@ int allocate_resource(struct resource *root, struct resource *new,  		alignf = simple_align_resource;  	write_lock(&resource_lock); -	if (resource_alloc_from_bottom) -		err = find_resource(root, new, size, min, max, align, alignf, alignf_data); -	else -		err = find_resource_from_top(root, new, size, min, max, align, alignf, alignf_data); +	err = find_resource(root, new, size, min, max, align, alignf, alignf_data);  	if (err >= 0 && __request_resource(root, new))  		err = -EBUSY;  	write_unlock(&resource_lock); diff --git a/kernel/sched.c b/kernel/sched.c index dc91a4d09ac..297d1a0eedb 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -636,22 +636,18 @@ static inline struct task_group *task_group(struct task_struct *p)  #endif /* CONFIG_CGROUP_SCHED */ -static u64 irq_time_cpu(int cpu); -static void sched_irq_time_avg_update(struct rq *rq, u64 irq_time); +static void update_rq_clock_task(struct rq *rq, s64 delta); -inline void update_rq_clock(struct rq *rq) +static void update_rq_clock(struct rq *rq)  { -	if (!rq->skip_clock_update) { -		int cpu = cpu_of(rq); -		u64 irq_time; +	s64 delta; -		rq->clock = sched_clock_cpu(cpu); -		irq_time = irq_time_cpu(cpu); -		if (rq->clock - irq_time > rq->clock_task) -			rq->clock_task = rq->clock - irq_time; +	if (rq->skip_clock_update) +		return; -		sched_irq_time_avg_update(rq, irq_time); -	} +	delta = sched_clock_cpu(cpu_of(rq)) - rq->clock; +	rq->clock += delta; +	update_rq_clock_task(rq, delta);  }  /* @@ -1924,10 +1920,9 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int flags)   * They are read and saved off onto struct rq in update_rq_clock().   * This may result in other CPU reading this CPU's irq time and can   * race with irq/account_system_vtime on this CPU. We would either get old - * or new value (or semi updated value on 32 bit) with a side effect of - * accounting a slice of irq time to wrong task when irq is in progress - * while we read rq->clock. That is a worthy compromise in place of having - * locks on each irq in account_system_time. + * or new value with a side effect of accounting a slice of irq time to wrong + * task when irq is in progress while we read rq->clock. That is a worthy + * compromise in place of having locks on each irq in account_system_time.   */  static DEFINE_PER_CPU(u64, cpu_hardirq_time);  static DEFINE_PER_CPU(u64, cpu_softirq_time); @@ -1945,19 +1940,58 @@ void disable_sched_clock_irqtime(void)  	sched_clock_irqtime = 0;  } -static u64 irq_time_cpu(int cpu) +#ifndef CONFIG_64BIT +static DEFINE_PER_CPU(seqcount_t, irq_time_seq); + +static inline void irq_time_write_begin(void)  { -	if (!sched_clock_irqtime) -		return 0; +	__this_cpu_inc(irq_time_seq.sequence); +	smp_wmb(); +} + +static inline void irq_time_write_end(void) +{ +	smp_wmb(); +	__this_cpu_inc(irq_time_seq.sequence); +} + +static inline u64 irq_time_read(int cpu) +{ +	u64 irq_time; +	unsigned seq; +	do { +		seq = read_seqcount_begin(&per_cpu(irq_time_seq, cpu)); +		irq_time = per_cpu(cpu_softirq_time, cpu) + +			   per_cpu(cpu_hardirq_time, cpu); +	} while (read_seqcount_retry(&per_cpu(irq_time_seq, cpu), seq)); + +	return irq_time; +} +#else /* CONFIG_64BIT */ +static inline void irq_time_write_begin(void) +{ +} + +static inline void irq_time_write_end(void) +{ +} + +static inline u64 irq_time_read(int cpu) +{  	return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu);  } +#endif /* CONFIG_64BIT */ +/* + * Called before incrementing preempt_count on {soft,}irq_enter + * and before decrementing preempt_count on {soft,}irq_exit. + */  void account_system_vtime(struct task_struct *curr)  {  	unsigned long flags; +	s64 delta;  	int cpu; -	u64 now, delta;  	if (!sched_clock_irqtime)  		return; @@ -1965,9 +1999,10 @@ void account_system_vtime(struct task_struct *curr)  	local_irq_save(flags);  	cpu = smp_processor_id(); -	now = sched_clock_cpu(cpu); -	delta = now - per_cpu(irq_start_time, cpu); -	per_cpu(irq_start_time, cpu) = now; +	delta = sched_clock_cpu(cpu) - __this_cpu_read(irq_start_time); +	__this_cpu_add(irq_start_time, delta); + +	irq_time_write_begin();  	/*  	 * We do not account for softirq time from ksoftirqd here.  	 * We want to continue accounting softirq time to ksoftirqd thread @@ -1975,33 +2010,55 @@ void account_system_vtime(struct task_struct *curr)  	 * that do not consume any time, but still wants to run.  	 */  	if (hardirq_count()) -		per_cpu(cpu_hardirq_time, cpu) += delta; +		__this_cpu_add(cpu_hardirq_time, delta);  	else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD)) -		per_cpu(cpu_softirq_time, cpu) += delta; +		__this_cpu_add(cpu_softirq_time, delta); +	irq_time_write_end();  	local_irq_restore(flags);  }  EXPORT_SYMBOL_GPL(account_system_vtime); -static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) +static void update_rq_clock_task(struct rq *rq, s64 delta)  { -	if (sched_clock_irqtime && sched_feat(NONIRQ_POWER)) { -		u64 delta_irq = curr_irq_time - rq->prev_irq_time; -		rq->prev_irq_time = curr_irq_time; -		sched_rt_avg_update(rq, delta_irq); -	} +	s64 irq_delta; + +	irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time; + +	/* +	 * Since irq_time is only updated on {soft,}irq_exit, we might run into +	 * this case when a previous update_rq_clock() happened inside a +	 * {soft,}irq region. +	 * +	 * When this happens, we stop ->clock_task and only update the +	 * prev_irq_time stamp to account for the part that fit, so that a next +	 * update will consume the rest. This ensures ->clock_task is +	 * monotonic. +	 * +	 * It does however cause some slight miss-attribution of {soft,}irq +	 * time, a more accurate solution would be to update the irq_time using +	 * the current rq->clock timestamp, except that would require using +	 * atomic ops. +	 */ +	if (irq_delta > delta) +		irq_delta = delta; + +	rq->prev_irq_time += irq_delta; +	delta -= irq_delta; +	rq->clock_task += delta; + +	if (irq_delta && sched_feat(NONIRQ_POWER)) +		sched_rt_avg_update(rq, irq_delta);  } -#else +#else /* CONFIG_IRQ_TIME_ACCOUNTING */ -static u64 irq_time_cpu(int cpu) +static void update_rq_clock_task(struct rq *rq, s64 delta)  { -	return 0; +	rq->clock_task += delta;  } -static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { } - -#endif +#endif /* CONFIG_IRQ_TIME_ACCOUNTING */  #include "sched_idletask.c"  #include "sched_fair.c" @@ -2129,7 +2186,7 @@ static void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)  	 * A queue event has occurred, and we're going to schedule.  In  	 * this case, we can save a useless back to back clock update.  	 */ -	if (test_tsk_need_resched(rq->curr)) +	if (rq->curr->se.on_rq && test_tsk_need_resched(rq->curr))  		rq->skip_clock_update = 1;  } @@ -3119,6 +3176,15 @@ static long calc_load_fold_active(struct rq *this_rq)  	return delta;  } +static unsigned long +calc_load(unsigned long load, unsigned long exp, unsigned long active) +{ +	load *= exp; +	load += active * (FIXED_1 - exp); +	load += 1UL << (FSHIFT - 1); +	return load >> FSHIFT; +} +  #ifdef CONFIG_NO_HZ  /*   * For NO_HZ we delay the active fold to the next LOAD_FREQ update. @@ -3148,6 +3214,128 @@ static long calc_load_fold_idle(void)  	return delta;  } + +/** + * fixed_power_int - compute: x^n, in O(log n) time + * + * @x:         base of the power + * @frac_bits: fractional bits of @x + * @n:         power to raise @x to. + * + * By exploiting the relation between the definition of the natural power + * function: x^n := x*x*...*x (x multiplied by itself for n times), and + * the binary encoding of numbers used by computers: n := \Sum n_i * 2^i, + * (where: n_i \elem {0, 1}, the binary vector representing n), + * we find: x^n := x^(\Sum n_i * 2^i) := \Prod x^(n_i * 2^i), which is + * of course trivially computable in O(log_2 n), the length of our binary + * vector. + */ +static unsigned long +fixed_power_int(unsigned long x, unsigned int frac_bits, unsigned int n) +{ +	unsigned long result = 1UL << frac_bits; + +	if (n) for (;;) { +		if (n & 1) { +			result *= x; +			result += 1UL << (frac_bits - 1); +			result >>= frac_bits; +		} +		n >>= 1; +		if (!n) +			break; +		x *= x; +		x += 1UL << (frac_bits - 1); +		x >>= frac_bits; +	} + +	return result; +} + +/* + * a1 = a0 * e + a * (1 - e) + * + * a2 = a1 * e + a * (1 - e) + *    = (a0 * e + a * (1 - e)) * e + a * (1 - e) + *    = a0 * e^2 + a * (1 - e) * (1 + e) + * + * a3 = a2 * e + a * (1 - e) + *    = (a0 * e^2 + a * (1 - e) * (1 + e)) * e + a * (1 - e) + *    = a0 * e^3 + a * (1 - e) * (1 + e + e^2) + * + *  ... + * + * an = a0 * e^n + a * (1 - e) * (1 + e + ... + e^n-1) [1] + *    = a0 * e^n + a * (1 - e) * (1 - e^n)/(1 - e) + *    = a0 * e^n + a * (1 - e^n) + * + * [1] application of the geometric series: + * + *              n         1 - x^(n+1) + *     S_n := \Sum x^i = ------------- + *             i=0          1 - x + */ +static unsigned long +calc_load_n(unsigned long load, unsigned long exp, +	    unsigned long active, unsigned int n) +{ + +	return calc_load(load, fixed_power_int(exp, FSHIFT, n), active); +} + +/* + * NO_HZ can leave us missing all per-cpu ticks calling + * calc_load_account_active(), but since an idle CPU folds its delta into + * calc_load_tasks_idle per calc_load_account_idle(), all we need to do is fold + * in the pending idle delta if our idle period crossed a load cycle boundary. + * + * Once we've updated the global active value, we need to apply the exponential + * weights adjusted to the number of cycles missed. + */ +static void calc_global_nohz(unsigned long ticks) +{ +	long delta, active, n; + +	if (time_before(jiffies, calc_load_update)) +		return; + +	/* +	 * If we crossed a calc_load_update boundary, make sure to fold +	 * any pending idle changes, the respective CPUs might have +	 * missed the tick driven calc_load_account_active() update +	 * due to NO_HZ. +	 */ +	delta = calc_load_fold_idle(); +	if (delta) +		atomic_long_add(delta, &calc_load_tasks); + +	/* +	 * If we were idle for multiple load cycles, apply them. +	 */ +	if (ticks >= LOAD_FREQ) { +		n = ticks / LOAD_FREQ; + +		active = atomic_long_read(&calc_load_tasks); +		active = active > 0 ? active * FIXED_1 : 0; + +		avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n); +		avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n); +		avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n); + +		calc_load_update += n * LOAD_FREQ; +	} + +	/* +	 * Its possible the remainder of the above division also crosses +	 * a LOAD_FREQ period, the regular check in calc_global_load() +	 * which comes after this will take care of that. +	 * +	 * Consider us being 11 ticks before a cycle completion, and us +	 * sleeping for 4*LOAD_FREQ + 22 ticks, then the above code will +	 * age us 4 cycles, and the test in calc_global_load() will +	 * pick up the final one. +	 */ +}  #else  static void calc_load_account_idle(struct rq *this_rq)  { @@ -3157,6 +3345,10 @@ static inline long calc_load_fold_idle(void)  {  	return 0;  } + +static void calc_global_nohz(unsigned long ticks) +{ +}  #endif  /** @@ -3174,24 +3366,17 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift)  	loads[2] = (avenrun[2] + offset) << shift;  } -static unsigned long -calc_load(unsigned long load, unsigned long exp, unsigned long active) -{ -	load *= exp; -	load += active * (FIXED_1 - exp); -	return load >> FSHIFT; -} -  /*   * calc_load - update the avenrun load estimates 10 ticks after the   * CPUs have updated calc_load_tasks.   */ -void calc_global_load(void) +void calc_global_load(unsigned long ticks)  { -	unsigned long upd = calc_load_update + 10;  	long active; -	if (time_before(jiffies, upd)) +	calc_global_nohz(ticks); + +	if (time_before(jiffies, calc_load_update + 10))  		return;  	active = atomic_long_read(&calc_load_tasks); @@ -3845,7 +4030,6 @@ static void put_prev_task(struct rq *rq, struct task_struct *prev)  {  	if (prev->se.on_rq)  		update_rq_clock(rq); -	rq->skip_clock_update = 0;  	prev->sched_class->put_prev_task(rq, prev);  } @@ -3903,7 +4087,6 @@ need_resched_nonpreemptible:  		hrtick_clear(rq);  	raw_spin_lock_irq(&rq->lock); -	clear_tsk_need_resched(prev);  	switch_count = &prev->nivcsw;  	if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { @@ -3935,6 +4118,8 @@ need_resched_nonpreemptible:  	put_prev_task(rq, prev);  	next = pick_next_task(rq); +	clear_tsk_need_resched(prev); +	rq->skip_clock_update = 0;  	if (likely(prev != next)) {  		sched_info_switch(prev, next); diff --git a/kernel/timer.c b/kernel/timer.c index 68a9ae7679b..353b9227c2e 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1252,6 +1252,12 @@ unsigned long get_next_timer_interrupt(unsigned long now)  	struct tvec_base *base = __get_cpu_var(tvec_bases);  	unsigned long expires; +	/* +	 * Pretend that there is no timer pending if the cpu is offline. +	 * Possible pending timers will be migrated later to an active cpu. +	 */ +	if (cpu_is_offline(smp_processor_id())) +		return now + NEXT_TIMER_MAX_DELTA;  	spin_lock(&base->lock);  	if (time_before_eq(base->next_timer, base->timer_jiffies))  		base->next_timer = __next_timer_interrupt(base); @@ -1319,7 +1325,7 @@ void do_timer(unsigned long ticks)  {  	jiffies_64 += ticks;  	update_wall_time(); -	calc_global_load(); +	calc_global_load(ticks);  }  #ifdef __ARCH_WANT_SYS_ALARM diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index c380612273b..f8cf959bad4 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2338,11 +2338,19 @@ tracing_write_stub(struct file *filp, const char __user *ubuf,  	return count;  } +static loff_t tracing_seek(struct file *file, loff_t offset, int origin) +{ +	if (file->f_mode & FMODE_READ) +		return seq_lseek(file, offset, origin); +	else +		return 0; +} +  static const struct file_operations tracing_fops = {  	.open		= tracing_open,  	.read		= seq_read,  	.write		= tracing_write_stub, -	.llseek		= seq_lseek, +	.llseek		= tracing_seek,  	.release	= tracing_release,  }; diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 1c7a2ec4f3c..b6ff4a1519a 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -97,11 +97,9 @@ struct workqueue_struct *ceph_msgr_wq;  int ceph_msgr_init(void)  {  	ceph_msgr_wq = create_workqueue("ceph-msgr"); -	if (IS_ERR(ceph_msgr_wq)) { -		int ret = PTR_ERR(ceph_msgr_wq); -		pr_err("msgr_init failed to create workqueue: %d\n", ret); -		ceph_msgr_wq = NULL; -		return ret; +	if (!ceph_msgr_wq) { +		pr_err("msgr_init failed to create workqueue\n"); +		return -ENOMEM;  	}  	return 0;  } diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c index ac34feeb2b3..1a040e64c69 100644 --- a/net/ceph/pagevec.c +++ b/net/ceph/pagevec.c @@ -13,7 +13,7 @@   * build a vector of user pages   */  struct page **ceph_get_direct_page_vector(const char __user *data, -					  int num_pages) +					  int num_pages, bool write_page)  {  	struct page **pages;  	int rc; @@ -24,24 +24,27 @@ struct page **ceph_get_direct_page_vector(const char __user *data,  	down_read(¤t->mm->mmap_sem);  	rc = get_user_pages(current, current->mm, (unsigned long)data, -			    num_pages, 0, 0, pages, NULL); +			    num_pages, write_page, 0, pages, NULL);  	up_read(¤t->mm->mmap_sem); -	if (rc < 0) +	if (rc < num_pages)  		goto fail;  	return pages;  fail: -	kfree(pages); +	ceph_put_page_vector(pages, rc > 0 ? rc : 0, false);  	return ERR_PTR(rc);  }  EXPORT_SYMBOL(ceph_get_direct_page_vector); -void ceph_put_page_vector(struct page **pages, int num_pages) +void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty)  {  	int i; -	for (i = 0; i < num_pages; i++) +	for (i = 0; i < num_pages; i++) { +		if (dirty) +			set_page_dirty_lock(pages[i]);  		put_page(pages[i]); +	}  	kfree(pages);  }  EXPORT_SYMBOL(ceph_put_page_vector); diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h index 58e933a2054..39667174971 100644 --- a/scripts/recordmcount.h +++ b/scripts/recordmcount.h @@ -119,7 +119,7 @@ static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM;  static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)  { -	rp->r_info = ELF_R_INFO(sym, type); +	rp->r_info = _w(ELF_R_INFO(sym, type));  }  static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO; diff --git a/scripts/tags.sh b/scripts/tags.sh index 8509bb51293..bbbe584d449 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -125,7 +125,9 @@ exuberant()  	-I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \  	--extra=+f --c-kinds=-px                                \  	--regex-asm='/^ENTRY\(([^)]*)\).*/\1/'                  \ -	--regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' +	--regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ +	--regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/'		\ +	--regex-c++='/^DEFINE_EVENT\(([^,)]*).*/trace_\1/'  	all_kconfigs | xargs $1 -a                              \  	--langdef=kconfig --language-force=kconfig              \ diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2d7d7de8498..427da45d790 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10830,7 +10830,8 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)  {  	struct alc_spec *spec = codec->spec;  	struct auto_pin_cfg *cfg = &spec->autocfg; -	int i, err; +	int i, err, type; +	int type_idx = 0;  	hda_nid_t nid;  	for (i = 0; i < cfg->num_inputs; i++) { @@ -10839,9 +10840,15 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)  		nid = cfg->inputs[i].pin;  		if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {  			char label[32]; +			type = cfg->inputs[i].type; +			if (i > 0 && type == cfg->inputs[i - 1].type) +				type_idx++; +			else +				type_idx = 0;  			snprintf(label, sizeof(label), "%s Boost",  				 hda_get_autocfg_input_label(codec, cfg, i)); -			err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0, +			err = add_control(spec, ALC_CTL_WIDGET_VOL, label, +					  type_idx,  				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));  			if (err < 0)  				return err; @@ -14800,6 +14807,8 @@ static int alc269_resume(struct hda_codec *codec)  enum {  	ALC269_FIXUP_SONY_VAIO,  	ALC269_FIXUP_DELL_M101Z, +	ALC269_FIXUP_LENOVO_EDGE14, +	ALC269_FIXUP_ASUS_G73JW,  };  static const struct alc_fixup alc269_fixups[] = { @@ -14817,11 +14826,22 @@ static const struct alc_fixup alc269_fixups[] = {  			{}  		}  	}, +	[ALC269_FIXUP_LENOVO_EDGE14] = { +		.sku = ALC_FIXUP_SKU_IGNORE, +	}, +	[ALC269_FIXUP_ASUS_G73JW] = { +		.pins = (const struct alc_pincfg[]) { +			{ 0x17, 0x99130111 }, /* subwoofer */ +			{ } +		} +	},  };  static struct snd_pci_quirk alc269_fixup_tbl[] = {  	SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),  	SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), +	SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_LENOVO_EDGE14), +	SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),  	{}  }; diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 879dff2714d..8725d4e7543 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -161,7 +161,7 @@  static const u16 wm8580_reg[] = {  	0x0121, 0x017e, 0x007d, 0x0014, /*R3*/  	0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ -	0x001c, 0x0002, 0x0002, 0x00c2, /*R11*/ +	0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/  	0x0182, 0x0082, 0x000a, 0x0024, /*R15*/  	0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/  	0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index fca60a0b57b..9001cc48ba1 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -818,7 +818,8 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol,  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);  	struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); -	return wm8904->deemph; +	ucontrol->value.enumerated.item[0] = wm8904->deemph; +	return 0;  }  static int wm8904_put_deemph(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index f89ad6c9a80..9cbab8e1de0 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -380,7 +380,8 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);  	struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); -	return wm8955->deemph; +	ucontrol->value.enumerated.item[0] = wm8955->deemph; +	return 0;  }  static int wm8955_put_deemph(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 8d5efb333c3..21986c42272 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -138,7 +138,8 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,  	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);  	struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); -	return wm8960->deemph; +	ucontrol->value.enumerated.item[0] = wm8960->deemph; +	return 0;  }  static int wm8960_put_deemph(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 75ed6491222..c721502833b 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -944,6 +944,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)  		case SND_SOC_DAPM_STREAM_RESUME:  			sys_power = 1;  			break; +		case SND_SOC_DAPM_STREAM_STOP: +			sys_power = !!codec->active; +			break;  		case SND_SOC_DAPM_STREAM_SUSPEND:  			sys_power = 0;  			break;  |