diff options
Diffstat (limited to 'drivers')
388 files changed, 6869 insertions, 3545 deletions
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index d269a8f3329..446aced33af 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -46,6 +46,8 @@ static unsigned long power_saving_mwait_eax;  static unsigned char tsc_detected_unstable;  static unsigned char tsc_marked_unstable; +static unsigned char lapic_detected_unstable; +static unsigned char lapic_marked_unstable;  static void power_saving_mwait_init(void)  { @@ -75,9 +77,6 @@ static void power_saving_mwait_init(void)  	power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |  		(highest_subcstate - 1); -	for_each_online_cpu(i) -		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &i); -  #if defined(CONFIG_GENERIC_TIME) && defined(CONFIG_X86)  	switch (boot_cpu_data.x86_vendor) {  	case X86_VENDOR_AMD: @@ -86,13 +85,15 @@ static void power_saving_mwait_init(void)  		 * AMD Fam10h TSC will tick in all  		 * C/P/S0/S1 states when this bit is set.  		 */ -		if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) -			return; - -		/*FALL THROUGH*/ +		if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) +			tsc_detected_unstable = 1; +		if (!boot_cpu_has(X86_FEATURE_ARAT)) +			lapic_detected_unstable = 1; +		break;  	default: -		/* TSC could halt in idle */ +		/* TSC & LAPIC could halt in idle */  		tsc_detected_unstable = 1; +		lapic_detected_unstable = 1;  	}  #endif  } @@ -180,10 +181,20 @@ static int power_saving_thread(void *data)  				mark_tsc_unstable("TSC halts in idle");  				tsc_marked_unstable = 1;  			} +			if (lapic_detected_unstable && !lapic_marked_unstable) { +				int i; +				/* LAPIC could halt in idle, so notify users */ +				for_each_online_cpu(i) +					clockevents_notify( +						CLOCK_EVT_NOTIFY_BROADCAST_ON, +						&i); +				lapic_marked_unstable = 1; +			}  			local_irq_disable();  			cpu = smp_processor_id(); -			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, -				&cpu); +			if (lapic_marked_unstable) +				clockevents_notify( +					CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);  			stop_critical_timings();  			__monitor((void *)¤t_thread_info()->flags, 0, 0); @@ -192,8 +203,9 @@ static int power_saving_thread(void *data)  				__mwait(power_saving_mwait_eax, 1);  			start_critical_timings(); -			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, -				&cpu); +			if (lapic_marked_unstable) +				clockevents_notify( +					CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);  			local_irq_enable();  			if (jiffies > expire_time) { diff --git a/drivers/acpi/acpica/acconfig.h b/drivers/acpi/acpica/acconfig.h index 33181ad350d..b17d8de9f6f 100644 --- a/drivers/acpi/acpica/acconfig.h +++ b/drivers/acpi/acpica/acconfig.h @@ -119,6 +119,10 @@  #define ACPI_MAX_LOOP_ITERATIONS        0xFFFF +/* Maximum sleep allowed via Sleep() operator */ + +#define ACPI_MAX_SLEEP                  20000	/* Two seconds */ +  /******************************************************************************   *   * ACPI Specification constants (Do not change unless the specification changes) diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 64d1e5c2d4a..c3f43daa8be 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -80,10 +80,6 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);  acpi_status  acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info); -acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); - -acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); -  struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,  						       u32 gpe_number); diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 9070f1fe8f1..899d68afc3c 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -125,6 +125,14 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE);   */  u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE); +/* + * Optionally truncate I/O addresses to 16 bits. Provides compatibility + * with other ACPI implementations. NOTE: During ACPICA initialization, + * this value is set to TRUE if any Windows OSI strings have been + * requested by the BIOS. + */ +u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE); +  /* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */  struct acpi_table_fadt acpi_gbl_FADT; diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 5900f135dc6..32391588e16 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -90,7 +90,11 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width);  /*   * hwgpe - GPE support   */ -acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); +u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, +			     struct acpi_gpe_register_info *gpe_register_info); + +acpi_status +acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action);  acpi_status  acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info); diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index a221ad40416..7c2c336006a 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -69,7 +69,7 @@ acpi_status  acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)  {  	struct acpi_gpe_register_info *gpe_register_info; -	u8 register_bit; +	u32 register_bit;  	ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks); @@ -78,9 +78,8 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)  		return_ACPI_STATUS(AE_NOT_EXIST);  	} -	register_bit = (u8) -	    (1 << -	     (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number)); +	register_bit = acpi_hw_gpe_register_bit(gpe_event_info, +						gpe_register_info);  	/* Clear the wake/run bits up front */ @@ -100,106 +99,6 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)  	return_ACPI_STATUS(AE_OK);  } -/******************************************************************************* - * - * FUNCTION:    acpi_ev_enable_gpe - * - * PARAMETERS:  gpe_event_info          - GPE to enable - * - * RETURN:      Status - * - * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless - *              of type or number of references. - * - * Note: The GPE lock should be already acquired when this function is called. - * - ******************************************************************************/ - -acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) -{ -	acpi_status status; - - -	ACPI_FUNCTION_TRACE(ev_enable_gpe); - - -	/* -	 * We will only allow a GPE to be enabled if it has either an -	 * associated method (_Lxx/_Exx) or a handler. Otherwise, the -	 * GPE will be immediately disabled by acpi_ev_gpe_dispatch the -	 * first time it fires. -	 */ -	if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) { -		return_ACPI_STATUS(AE_NO_HANDLER); -	} - -	/* Ensure the HW enable masks are current */ - -	status = acpi_ev_update_gpe_enable_masks(gpe_event_info); -	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); -	} - -	/* Clear the GPE (of stale events) */ - -	status = acpi_hw_clear_gpe(gpe_event_info); -	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); -	} - -	/* Enable the requested GPE */ - -	status = acpi_hw_write_gpe_enable_reg(gpe_event_info); -	return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_ev_disable_gpe - * - * PARAMETERS:  gpe_event_info          - GPE to disable - * - * RETURN:      Status - * - * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE, - *              regardless of the type or number of references. - * - * Note: The GPE lock should be already acquired when this function is called. - * - ******************************************************************************/ - -acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) -{ -	acpi_status status; - -	ACPI_FUNCTION_TRACE(ev_disable_gpe); - - -	/* -	 * Note: Always disable the GPE, even if we think that that it is already -	 * disabled. It is possible that the AML or some other code has enabled -	 * the GPE behind our back. -	 */ - -	/* Ensure the HW enable masks are current */ - -	status = acpi_ev_update_gpe_enable_masks(gpe_event_info); -	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); -	} - -	/* -	 * Always H/W disable this GPE, even if we don't know the GPE type. -	 * Simply clear the enable bit for this particular GPE, but do not -	 * write out the current GPE enable mask since this may inadvertently -	 * enable GPEs too early. An example is a rogue GPE that has arrived -	 * during ACPICA initialization - possibly because AML or other code -	 * has enabled the GPE. -	 */ -	status = acpi_hw_low_disable_gpe(gpe_event_info); -	return_ACPI_STATUS(status); -} -  /*******************************************************************************   * @@ -451,10 +350,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)  		return_VOID;  	} -	/* Update the GPE register masks for return to enabled state */ - -	(void)acpi_ev_update_gpe_enable_masks(gpe_event_info); -  	/*  	 * Take a snapshot of the GPE info for this level - we copy the info to  	 * prevent a race condition with remove_handler/remove_block. @@ -607,7 +502,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)  		 * Disable the GPE, so it doesn't keep firing before the method has a  		 * chance to run (it runs asynchronously with interrupts enabled).  		 */ -		status = acpi_ev_disable_gpe(gpe_event_info); +		status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);  		if (ACPI_FAILURE(status)) {  			ACPI_EXCEPTION((AE_INFO, status,  					"Unable to disable GPE[0x%2X]", @@ -644,7 +539,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)  		 * Disable the GPE. The GPE will remain disabled a handler  		 * is installed or ACPICA is restarted.  		 */ -		status = acpi_ev_disable_gpe(gpe_event_info); +		status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);  		if (ACPI_FAILURE(status)) {  			ACPI_EXCEPTION((AE_INFO, status,  					"Unable to disable GPE[0x%2X]", diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 7c28f2d9fd3..341a38ce8aa 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -500,6 +500,19 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,  			gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;  			gpe_event_info = &gpe_block->event_info[gpe_index]; +			gpe_number = gpe_index + gpe_block->block_base_number; + +			/* +			 * If the GPE has already been enabled for runtime +			 * signaling, make sure it remains enabled, but do not +			 * increment its reference counter. +			 */ +			if (gpe_event_info->runtime_count) { +				acpi_set_gpe(gpe_device, gpe_number, +						ACPI_GPE_ENABLE); +				gpe_enabled_count++; +				continue; +			}  			if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {  				wake_gpe_count++; @@ -516,7 +529,6 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,  			/* Enable this GPE */ -			gpe_number = gpe_index + gpe_block->block_base_number;  			status = acpi_enable_gpe(gpe_device, gpe_number,  						 ACPI_GPE_TYPE_RUNTIME);  			if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index cc825023012..4a531cdf794 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -719,13 +719,6 @@ acpi_install_gpe_handler(acpi_handle gpe_device,  	handler->context = context;  	handler->method_node = gpe_event_info->dispatch.method_node; -	/* Disable the GPE before installing the handler */ - -	status = acpi_ev_disable_gpe(gpe_event_info); -	if (ACPI_FAILURE (status)) { -		goto unlock_and_exit; -	} -  	/* Install the handler */  	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index d5a5efc043b..18b3f1468b7 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -70,6 +70,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,  acpi_status acpi_enable(void)  {  	acpi_status status; +	int retry;  	ACPI_FUNCTION_TRACE(acpi_enable); @@ -98,16 +99,18 @@ acpi_status acpi_enable(void)  	/* Sanity check that transition succeeded */ -	if (acpi_hw_get_mode() != ACPI_SYS_MODE_ACPI) { -		ACPI_ERROR((AE_INFO, -			    "Hardware did not enter ACPI mode")); -		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); +	for (retry = 0; retry < 30000; ++retry) { +		if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) { +			if (retry != 0) +				ACPI_WARNING((AE_INFO, +				"Platform took > %d00 usec to enter ACPI mode", retry)); +			return_ACPI_STATUS(AE_OK); +		} +		acpi_os_stall(100);	/* 100 usec */  	} -	ACPI_DEBUG_PRINT((ACPI_DB_INIT, -			  "Transition to ACPI mode successful\n")); - -	return_ACPI_STATUS(AE_OK); +	ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode")); +	return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);  }  ACPI_EXPORT_SYMBOL(acpi_enable) @@ -210,6 +213,44 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event)  /*******************************************************************************   * + * FUNCTION:    acpi_clear_and_enable_gpe + * + * PARAMETERS:  gpe_event_info  - GPE to enable + * + * RETURN:      Status + * + * DESCRIPTION: Clear the given GPE from stale events and enable it. + * + ******************************************************************************/ +static acpi_status +acpi_clear_and_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) +{ +	acpi_status status; + +	/* +	 * We will only allow a GPE to be enabled if it has either an +	 * associated method (_Lxx/_Exx) or a handler. Otherwise, the +	 * GPE will be immediately disabled by acpi_ev_gpe_dispatch the +	 * first time it fires. +	 */ +	if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) { +		return_ACPI_STATUS(AE_NO_HANDLER); +	} + +	/* Clear the GPE (of stale events) */ +	status = acpi_hw_clear_gpe(gpe_event_info); +	if (ACPI_FAILURE(status)) { +		return_ACPI_STATUS(status); +	} + +	/* Enable the requested GPE */ +	status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE); + +	return_ACPI_STATUS(status); +} + +/******************************************************************************* + *   * FUNCTION:    acpi_set_gpe   *   * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1 @@ -249,11 +290,11 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)  	switch (action) {  	case ACPI_GPE_ENABLE: -		status = acpi_ev_enable_gpe(gpe_event_info); +		status = acpi_clear_and_enable_gpe(gpe_event_info);  		break;  	case ACPI_GPE_DISABLE: -		status = acpi_ev_disable_gpe(gpe_event_info); +		status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);  		break;  	default: @@ -316,7 +357,11 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)  		gpe_event_info->runtime_count++;  		if (gpe_event_info->runtime_count == 1) { -			status = acpi_ev_enable_gpe(gpe_event_info); +			status = acpi_ev_update_gpe_enable_masks(gpe_event_info); +			if (ACPI_SUCCESS(status)) { +				status = acpi_clear_and_enable_gpe(gpe_event_info); +			} +  			if (ACPI_FAILURE(status)) {  				gpe_event_info->runtime_count--;  				goto unlock_and_exit; @@ -343,7 +388,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)  		 */  		gpe_event_info->wakeup_count++;  		if (gpe_event_info->wakeup_count == 1) { -			(void)acpi_ev_update_gpe_enable_masks(gpe_event_info); +			status = acpi_ev_update_gpe_enable_masks(gpe_event_info);  		}  	} @@ -403,7 +448,12 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type  		gpe_event_info->runtime_count--;  		if (!gpe_event_info->runtime_count) { -			status = acpi_ev_disable_gpe(gpe_event_info); +			status = acpi_ev_update_gpe_enable_masks(gpe_event_info); +			if (ACPI_SUCCESS(status)) { +				status = acpi_hw_low_set_gpe(gpe_event_info, +							     ACPI_GPE_DISABLE); +			} +  			if (ACPI_FAILURE(status)) {  				gpe_event_info->runtime_count++;  				goto unlock_and_exit; @@ -424,7 +474,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type  		gpe_event_info->wakeup_count--;  		if (!gpe_event_info->wakeup_count) { -			(void)acpi_ev_update_gpe_enable_masks(gpe_event_info); +			status = acpi_ev_update_gpe_enable_masks(gpe_event_info);  		}  	} diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c index 6d32e09327f..675aaa91a77 100644 --- a/drivers/acpi/acpica/exsystem.c +++ b/drivers/acpi/acpica/exsystem.c @@ -201,6 +201,14 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long)  	acpi_ex_relinquish_interpreter(); +	/* +	 * For compatibility with other ACPI implementations and to prevent +	 * accidental deep sleeps, limit the sleep time to something reasonable. +	 */ +	if (how_long > ACPI_MAX_SLEEP) { +		how_long = ACPI_MAX_SLEEP; +	} +  	acpi_os_sleep(how_long);  	/* And now we must get the interpreter again */ diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index bd72319a38f..3450309c278 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -57,21 +57,47 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,  /******************************************************************************   * - * FUNCTION:	acpi_hw_low_disable_gpe + * FUNCTION:	acpi_hw_gpe_register_bit + * + * PARAMETERS:	gpe_event_info	    - Info block for the GPE + *		gpe_register_info   - Info block for the GPE register + * + * RETURN:	Status + * + * DESCRIPTION:	Compute GPE enable mask with one bit corresponding to the given + *		GPE set. + * + ******************************************************************************/ + +u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, +			     struct acpi_gpe_register_info *gpe_register_info) +{ +	return (u32)1 << (gpe_event_info->gpe_number - +				gpe_register_info->base_gpe_number); +} + +/****************************************************************************** + * + * FUNCTION:	acpi_hw_low_set_gpe   *   * PARAMETERS:	gpe_event_info	    - Info block for the GPE to be disabled + *		action		    - Enable or disable   *   * RETURN:	Status   * - * DESCRIPTION: Disable a single GPE in the enable register. + * DESCRIPTION: Enable or disable a single GPE in its enable register.   *   ******************************************************************************/ -acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) +acpi_status +acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)  {  	struct acpi_gpe_register_info *gpe_register_info;  	acpi_status status;  	u32 enable_mask; +	u32 register_bit; + +	ACPI_FUNCTION_ENTRY();  	/* Get the info block for the entire GPE register */ @@ -87,11 +113,27 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)  		return (status);  	} -	/* Clear just the bit that corresponds to this GPE */ +	/* Set ot clear just the bit that corresponds to this GPE */ -	ACPI_CLEAR_BIT(enable_mask, ((u32)1 << -				     (gpe_event_info->gpe_number - -				      gpe_register_info->base_gpe_number))); +	register_bit = acpi_hw_gpe_register_bit(gpe_event_info, +						gpe_register_info); +	switch (action) { +	case ACPI_GPE_COND_ENABLE: +		if (!(register_bit & gpe_register_info->enable_for_run)) +			return (AE_BAD_PARAMETER); + +	case ACPI_GPE_ENABLE: +		ACPI_SET_BIT(enable_mask, register_bit); +		break; + +	case ACPI_GPE_DISABLE: +		ACPI_CLEAR_BIT(enable_mask, register_bit); +		break; + +	default: +		ACPI_ERROR((AE_INFO, "Invalid action\n")); +		return (AE_BAD_PARAMETER); +	}  	/* Write the updated enable mask */ @@ -116,23 +158,11 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)  acpi_status  acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)  { -	struct acpi_gpe_register_info *gpe_register_info;  	acpi_status status;  	ACPI_FUNCTION_ENTRY(); -	/* Get the info block for the entire GPE register */ - -	gpe_register_info = gpe_event_info->register_info; -	if (!gpe_register_info) { -		return (AE_NOT_EXIST); -	} - -	/* Write the entire GPE (runtime) enable register */ - -	status = acpi_hw_write(gpe_register_info->enable_for_run, -			       &gpe_register_info->enable_address); - +	status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE);  	return (status);  } @@ -150,21 +180,28 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)  acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)  { +	struct acpi_gpe_register_info *gpe_register_info;  	acpi_status status; -	u8 register_bit; +	u32 register_bit;  	ACPI_FUNCTION_ENTRY(); -	register_bit = (u8)(1 << -			    (gpe_event_info->gpe_number - -			     gpe_event_info->register_info->base_gpe_number)); +	/* Get the info block for the entire GPE register */ + +	gpe_register_info = gpe_event_info->register_info; +	if (!gpe_register_info) { +		return (AE_NOT_EXIST); +	} + +	register_bit = acpi_hw_gpe_register_bit(gpe_event_info, +						gpe_register_info);  	/*  	 * Write a one to the appropriate bit in the status register to  	 * clear this GPE.  	 */  	status = acpi_hw_write(register_bit, -			       &gpe_event_info->register_info->status_address); +			       &gpe_register_info->status_address);  	return (status);  } @@ -187,7 +224,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,  		       acpi_event_status * event_status)  {  	u32 in_byte; -	u8 register_bit; +	u32 register_bit;  	struct acpi_gpe_register_info *gpe_register_info;  	acpi_status status;  	acpi_event_status local_event_status = 0; @@ -204,9 +241,8 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,  	/* Get the register bitmask for this GPE */ -	register_bit = (u8)(1 << -			    (gpe_event_info->gpe_number - -			     gpe_event_info->register_info->base_gpe_number)); +	register_bit = acpi_hw_gpe_register_bit(gpe_event_info, +						gpe_register_info);  	/* GPE currently enabled? (enabled for runtime?) */ diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c index c10d587c164..e1d9c777b21 100644 --- a/drivers/acpi/acpica/hwvalid.c +++ b/drivers/acpi/acpica/hwvalid.c @@ -222,6 +222,12 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)  	u32 one_byte;  	u32 i; +	/* Truncate address to 16 bits if requested */ + +	if (acpi_gbl_truncate_io_addresses) { +		address &= ACPI_UINT16_MAX; +	} +  	/* Validate the entire request and perform the I/O */  	status = acpi_hw_validate_io_request(address, width); @@ -279,6 +285,12 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)  	acpi_status status;  	u32 i; +	/* Truncate address to 16 bits if requested */ + +	if (acpi_gbl_truncate_io_addresses) { +		address &= ACPI_UINT16_MAX; +	} +  	/* Validate the entire request and perform the I/O */  	status = acpi_hw_validate_io_request(address, width); diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 9bd6f050f29..4e5272c313e 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -193,6 +193,15 @@ acpi_status acpi_ns_initialize_devices(void)  					acpi_ns_init_one_device, NULL, &info,  					NULL); +	/* +	 * Any _OSI requests should be completed by now. If the BIOS has +	 * requested any Windows OSI strings, we will always truncate +	 * I/O addresses to 16 bits -- for Windows compatibility. +	 */ +	if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) { +		acpi_gbl_truncate_io_addresses = TRUE; +	} +  	ACPI_FREE(info.evaluate_info);  	if (ACPI_FAILURE(status)) {  		goto error_exit; diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index db3946e9c66..216e1e948ff 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -34,6 +34,7 @@  #include <linux/module.h>  #include <linux/init.h>  #include <linux/acpi.h> +#include <linux/slab.h>  #include <linux/io.h>  #include <linux/kref.h>  #include <linux/rculist.h> diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 2ebc3911550..864dd46c346 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -781,7 +781,7 @@ static int __init erst_init(void)  	status = acpi_get_table(ACPI_SIG_ERST, 0,  				(struct acpi_table_header **)&erst_tab);  	if (status == AE_NOT_FOUND) { -		pr_err(ERST_PFX "Table is not found!\n"); +		pr_info(ERST_PFX "Table is not found!\n");  		goto err;  	} else if (ACPI_FAILURE(status)) {  		const char *msg = acpi_format_exception(status); diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c index 814b1924961..8f8bd736d4f 100644 --- a/drivers/acpi/atomicio.c +++ b/drivers/acpi/atomicio.c @@ -31,6 +31,7 @@  #include <linux/kref.h>  #include <linux/rculist.h>  #include <linux/interrupt.h> +#include <linux/slab.h>  #include <acpi/atomicio.h>  #define ACPI_PFX "ACPI: " diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 3026e3fa83e..dc58402b0a1 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -868,9 +868,15 @@ static void acpi_battery_remove_fs(struct acpi_device *device)  static void acpi_battery_notify(struct acpi_device *device, u32 event)  {  	struct acpi_battery *battery = acpi_driver_data(device); +#ifdef CONFIG_ACPI_SYSFS_POWER +	struct device *old; +#endif  	if (!battery)  		return; +#ifdef CONFIG_ACPI_SYSFS_POWER +	old = battery->bat.dev; +#endif  	acpi_battery_update(battery);  	acpi_bus_generate_proc_event(device, event,  				     acpi_battery_present(battery)); @@ -879,7 +885,7 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event)  					acpi_battery_present(battery));  #ifdef CONFIG_ACPI_SYSFS_POWER  	/* acpi_battery_update could remove power_supply object */ -	if (battery->bat.dev) +	if (old && battery->bat.dev)  		power_supply_changed(&battery->bat);  #endif  } diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 2815df66f6f..2bb28b9d91c 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -214,7 +214,15 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {  	.ident = "Sony VGN-SR290J",  	.matches = {  		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), -		     DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"), +		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"), +		}, +	}, +	{ +	.callback = dmi_disable_osi_vista, +	.ident = "VGN-NS50B_L", +	.matches = { +		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), +		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),  		},  	},  	{ diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index fd51c4ab482..7d857dabdde 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -425,7 +425,7 @@ static int acpi_button_add(struct acpi_device *device)  		/* Button's GPE is run-wake GPE */  		acpi_enable_gpe(device->wakeup.gpe_device,  				device->wakeup.gpe_number, -				ACPI_GPE_TYPE_WAKE_RUN); +				ACPI_GPE_TYPE_RUNTIME);  		device->wakeup.run_wake_count++;  		device->wakeup.state.enabled = 1;  	} @@ -449,7 +449,7 @@ static int acpi_button_remove(struct acpi_device *device, int type)  	if (device->wakeup.flags.valid) {  		acpi_disable_gpe(device->wakeup.gpe_device,  				device->wakeup.gpe_number, -				ACPI_GPE_TYPE_WAKE_RUN); +				ACPI_GPE_TYPE_RUNTIME);  		device->wakeup.run_wake_count--;  		device->wakeup.state.enabled = 0;  	} diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index acf2ab24984..8a3b840c0bb 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -347,7 +347,6 @@ static int __init acpi_fan_init(void)  {  	int result = 0; -  #ifdef CONFIG_ACPI_PROCFS  	acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);  	if (!acpi_fan_dir) @@ -356,7 +355,9 @@ static int __init acpi_fan_init(void)  	result = acpi_bus_register_driver(&acpi_fan_driver);  	if (result < 0) { +#ifdef CONFIG_ACPI_PROCFS  		remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); +#endif  		return -ENODEV;  	} diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 51284351418..e9699aaed10 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -223,7 +223,7 @@ static bool processor_physically_present(acpi_handle handle)  	type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;  	cpuid = acpi_get_cpuid(handle, type, acpi_id); -	if (cpuid == -1) +	if ((cpuid == -1) && (num_possible_cpus() > 1))  		return false;  	return true; diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index b1034a9ada4..38ea0cc6dc4 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -581,6 +581,11 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)  		return 0;  	} +#ifdef CONFIG_SMP +	if (pr->id >= setup_max_cpus && pr->id != 0) +		return 0; +#endif +  	BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));  	/* diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index b1b385692f4..e9a8026d39f 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -76,14 +76,19 @@ static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;  module_param(max_cstate, uint, 0000);  static unsigned int nocst __read_mostly;  module_param(nocst, uint, 0000); +static int bm_check_disable __read_mostly; +module_param(bm_check_disable, uint, 0000);  static unsigned int latency_factor __read_mostly = 2;  module_param(latency_factor, uint, 0644); +#ifdef CONFIG_ACPI_PROCFS  static u64 us_to_pm_timer_ticks(s64 t)  {  	return div64_u64(t * PM_TIMER_FREQUENCY, 1000000);  } +#endif +  /*   * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.   * For now disable this. Probably a bug somewhere else. @@ -763,6 +768,9 @@ static int acpi_idle_bm_check(void)  {  	u32 bm_status = 0; +	if (bm_check_disable) +		return 0; +  	acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);  	if (bm_status)  		acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); @@ -947,7 +955,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,  	if (acpi_idle_suspend)  		return(acpi_idle_enter_c1(dev, state)); -	if (acpi_idle_bm_check()) { +	if (!cx->bm_sts_skip && acpi_idle_bm_check()) {  		if (dev->safe_state) {  			dev->last_state = dev->safe_state;  			return dev->safe_state->enter(dev, dev->safe_state); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3fb4bdea7e0..2862c781b37 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -82,6 +82,20 @@ static int acpi_sleep_prepare(u32 acpi_state)  static u32 acpi_target_sleep_state = ACPI_STATE_S0;  /* + * The ACPI specification wants us to save NVS memory regions during hibernation + * and to restore them during the subsequent resume.  Windows does that also for + * suspend to RAM.  However, it is known that this mechanism does not work on + * all machines, so we allow the user to disable it with the help of the + * 'acpi_sleep=nonvs' kernel command line option. + */ +static bool nvs_nosave; + +void __init acpi_nvs_nosave(void) +{ +	nvs_nosave = true; +} + +/*   * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the   * user to request that behavior by using the 'acpi_old_suspend_ordering'   * kernel command line option that causes the following variable to be set. @@ -114,6 +128,8 @@ static int __acpi_pm_prepare(void)  {  	int error = acpi_sleep_prepare(acpi_target_sleep_state); +	suspend_nvs_save(); +  	if (error)  		acpi_target_sleep_state = ACPI_STATE_S0;  	return error; @@ -143,6 +159,9 @@ static void acpi_pm_finish(void)  {  	u32 acpi_state = acpi_target_sleep_state; +	suspend_nvs_free(); +	acpi_ec_unblock_transactions(); +  	if (acpi_state == ACPI_STATE_S0)  		return; @@ -192,6 +211,10 @@ static int acpi_suspend_begin(suspend_state_t pm_state)  	u32 acpi_state = acpi_suspend_states[pm_state];  	int error = 0; +	error = nvs_nosave ? 0 : suspend_nvs_alloc(); +	if (error) +		return error; +  	if (sleep_states[acpi_state]) {  		acpi_target_sleep_state = acpi_state;  		acpi_sleep_tts_switch(acpi_target_sleep_state); @@ -269,12 +292,13 @@ static int acpi_suspend_enter(suspend_state_t pm_state)  	if (acpi_state == ACPI_STATE_S3)  		acpi_restore_state_mem(); +	suspend_nvs_restore(); +  	return ACPI_SUCCESS(status) ? 0 : -EFAULT;  }  static void acpi_suspend_finish(void)  { -	acpi_ec_unblock_transactions();  	acpi_pm_finish();  } @@ -377,20 +401,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {  #endif /* CONFIG_SUSPEND */  #ifdef CONFIG_HIBERNATION -/* - * The ACPI specification wants us to save NVS memory regions during hibernation - * and to restore them during the subsequent resume.  However, it is not certain - * if this mechanism is going to work on all machines, so we allow the user to - * disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line - * option. - */ -static bool s4_no_nvs; - -void __init acpi_s4_no_nvs(void) -{ -	s4_no_nvs = true; -} -  static unsigned long s4_hardware_signature;  static struct acpi_table_facs *facs;  static bool nosigcheck; @@ -404,7 +414,7 @@ static int acpi_hibernation_begin(void)  {  	int error; -	error = s4_no_nvs ? 0 : hibernate_nvs_alloc(); +	error = nvs_nosave ? 0 : suspend_nvs_alloc();  	if (!error) {  		acpi_target_sleep_state = ACPI_STATE_S4;  		acpi_sleep_tts_switch(acpi_target_sleep_state); @@ -418,7 +428,7 @@ static int acpi_hibernation_pre_snapshot(void)  	int error = acpi_pm_prepare();  	if (!error) -		hibernate_nvs_save(); +		suspend_nvs_save();  	return error;  } @@ -441,13 +451,6 @@ static int acpi_hibernation_enter(void)  	return ACPI_SUCCESS(status) ? 0 : -EFAULT;  } -static void acpi_hibernation_finish(void) -{ -	hibernate_nvs_free(); -	acpi_ec_unblock_transactions(); -	acpi_pm_finish(); -} -  static void acpi_hibernation_leave(void)  {  	/* @@ -464,7 +467,7 @@ static void acpi_hibernation_leave(void)  		panic("ACPI S4 hardware signature mismatch");  	}  	/* Restore the NVS memory area */ -	hibernate_nvs_restore(); +	suspend_nvs_restore();  	/* Allow EC transactions to happen. */  	acpi_ec_unblock_transactions_early();  } @@ -479,7 +482,7 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {  	.begin = acpi_hibernation_begin,  	.end = acpi_pm_end,  	.pre_snapshot = acpi_hibernation_pre_snapshot, -	.finish = acpi_hibernation_finish, +	.finish = acpi_pm_finish,  	.prepare = acpi_pm_prepare,  	.enter = acpi_hibernation_enter,  	.leave = acpi_hibernation_leave, @@ -506,8 +509,8 @@ static int acpi_hibernation_begin_old(void)  	error = acpi_sleep_prepare(ACPI_STATE_S4);  	if (!error) { -		if (!s4_no_nvs) -			error = hibernate_nvs_alloc(); +		if (!nvs_nosave) +			error = suspend_nvs_alloc();  		if (!error)  			acpi_target_sleep_state = ACPI_STATE_S4;  	} @@ -517,7 +520,7 @@ static int acpi_hibernation_begin_old(void)  static int acpi_hibernation_pre_snapshot_old(void)  {  	acpi_pm_freeze(); -	hibernate_nvs_save(); +	suspend_nvs_save();  	return 0;  } @@ -529,8 +532,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = {  	.begin = acpi_hibernation_begin_old,  	.end = acpi_pm_end,  	.pre_snapshot = acpi_hibernation_pre_snapshot_old, -	.finish = acpi_hibernation_finish,  	.prepare = acpi_pm_freeze, +	.finish = acpi_pm_finish,  	.enter = acpi_hibernation_enter,  	.leave = acpi_hibernation_leave,  	.pre_restore = acpi_pm_freeze, diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index c79e789ed03..f8db50a0941 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -388,10 +388,12 @@ static ssize_t counter_set(struct kobject *kobj,  	if (index < num_gpes) {  		if (!strcmp(buf, "disable\n") &&  				(status & ACPI_EVENT_FLAG_ENABLED)) -			result = acpi_set_gpe(handle, index, ACPI_GPE_DISABLE); +			result = acpi_disable_gpe(handle, index, +						ACPI_GPE_TYPE_RUNTIME);  		else if (!strcmp(buf, "enable\n") &&  				!(status & ACPI_EVENT_FLAG_ENABLED)) -			result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE); +			result = acpi_enable_gpe(handle, index, +						ACPI_GPE_TYPE_RUNTIME);  		else if (!strcmp(buf, "clear\n") &&  				(status & ACPI_EVENT_FLAG_SET))  			result = acpi_clear_gpe(handle, index); diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c index 4b9d339a6e2..388747a7ef4 100644 --- a/drivers/acpi/wakeup.c +++ b/drivers/acpi/wakeup.c @@ -64,16 +64,13 @@ void acpi_enable_wakeup_device(u8 sleep_state)  		struct acpi_device *dev =  			container_of(node, struct acpi_device, wakeup_list); -		if (!dev->wakeup.flags.valid) -			continue; - -		if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count) +		if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled  		    || sleep_state > (u32) dev->wakeup.sleep_state)  			continue;  		/* The wake-up power should have been enabled already. */ -		acpi_set_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, -				ACPI_GPE_ENABLE); +		acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, +				ACPI_GPE_TYPE_WAKE);  	}  } @@ -96,6 +93,8 @@ void acpi_disable_wakeup_device(u8 sleep_state)  		    || (sleep_state > (u32) dev->wakeup.sleep_state))  			continue; +		acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, +				ACPI_GPE_TYPE_WAKE);  		acpi_disable_wakeup_device_power(dev);  	}  } @@ -109,13 +108,8 @@ int __init acpi_wakeup_device_init(void)  		struct acpi_device *dev = container_of(node,  						       struct acpi_device,  						       wakeup_list); -		/* In case user doesn't load button driver */ -		if (!dev->wakeup.flags.always_enabled || -		    dev->wakeup.state.enabled) -			continue; - 		acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, - 				ACPI_GPE_TYPE_WAKE); -		dev->wakeup.state.enabled = 1; +		if (dev->wakeup.flags.always_enabled) +			dev->wakeup.state.enabled = 1;  	}  	mutex_unlock(&acpi_device_lock);  	return 0; diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index f60b2b6a093..d31590e7011 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -122,6 +122,31 @@ static int __init amba_init(void)  postcore_initcall(amba_init); +static int amba_get_enable_pclk(struct amba_device *pcdev) +{ +	struct clk *pclk = clk_get(&pcdev->dev, "apb_pclk"); +	int ret; + +	pcdev->pclk = pclk; + +	if (IS_ERR(pclk)) +		return PTR_ERR(pclk); + +	ret = clk_enable(pclk); +	if (ret) +		clk_put(pclk); + +	return ret; +} + +static void amba_put_disable_pclk(struct amba_device *pcdev) +{ +	struct clk *pclk = pcdev->pclk; + +	clk_disable(pclk); +	clk_put(pclk); +} +  /*   * These are the device model conversion veneers; they convert the   * device model structures to our more specific structures. @@ -130,17 +155,33 @@ static int amba_probe(struct device *dev)  {  	struct amba_device *pcdev = to_amba_device(dev);  	struct amba_driver *pcdrv = to_amba_driver(dev->driver); -	struct amba_id *id; +	struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev); +	int ret; -	id = amba_lookup(pcdrv->id_table, pcdev); +	do { +		ret = amba_get_enable_pclk(pcdev); +		if (ret) +			break; + +		ret = pcdrv->probe(pcdev, id); +		if (ret == 0) +			break; -	return pcdrv->probe(pcdev, id); +		amba_put_disable_pclk(pcdev); +	} while (0); + +	return ret;  }  static int amba_remove(struct device *dev)  { +	struct amba_device *pcdev = to_amba_device(dev);  	struct amba_driver *drv = to_amba_driver(dev->driver); -	return drv->remove(to_amba_device(dev)); +	int ret = drv->remove(pcdev); + +	amba_put_disable_pclk(pcdev); + +	return ret;  }  static void amba_shutdown(struct device *dev) @@ -203,7 +244,6 @@ static void amba_device_release(struct device *dev)   */  int amba_device_register(struct amba_device *dev, struct resource *parent)  { -	u32 pid, cid;  	u32 size;  	void __iomem *tmp;  	int i, ret; @@ -241,25 +281,35 @@ int amba_device_register(struct amba_device *dev, struct resource *parent)  		goto err_release;  	} -	/* -	 * Read pid and cid based on size of resource -	 * they are located at end of region -	 */ -	for (pid = 0, i = 0; i < 4; i++) -		pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) << (i * 8); -	for (cid = 0, i = 0; i < 4; i++) -		cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) << (i * 8); +	ret = amba_get_enable_pclk(dev); +	if (ret == 0) { +		u32 pid, cid; -	iounmap(tmp); +		/* +		 * Read pid and cid based on size of resource +		 * they are located at end of region +		 */ +		for (pid = 0, i = 0; i < 4; i++) +			pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) << +				(i * 8); +		for (cid = 0, i = 0; i < 4; i++) +			cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) << +				(i * 8); -	if (cid == 0xb105f00d) -		dev->periphid = pid; +		amba_put_disable_pclk(dev); -	if (!dev->periphid) { -		ret = -ENODEV; -		goto err_release; +		if (cid == 0xb105f00d) +			dev->periphid = pid; + +		if (!dev->periphid) +			ret = -ENODEV;  	} +	iounmap(tmp); + +	if (ret) +		goto err_release; +  	ret = device_add(&dev->dev);  	if (ret)  		goto err_release; diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 8ca16f54e1e..f2522534ae6 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1053,6 +1053,16 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)  		return -ENODEV; +	/* +	 * For some reason, MCP89 on MacBook 7,1 doesn't work with +	 * ahci, use ata_generic instead. +	 */ +	if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && +	    pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && +	    pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && +	    pdev->subsystem_device == 0xcb89) +		return -ENODEV; +  	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.  	 * At the moment, we can only use the AHCI mode. Let the users know  	 * that for SAS drives they're out of luck. diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 573158a9668..7107a6929de 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -32,6 +32,11 @@   *	A generic parallel ATA driver using libata   */ +enum { +	ATA_GEN_CLASS_MATCH		= (1 << 0), +	ATA_GEN_FORCE_DMA		= (1 << 1), +}; +  /**   *	generic_set_mode	-	mode setting   *	@link: link to set up @@ -46,13 +51,17 @@  static int generic_set_mode(struct ata_link *link, struct ata_device **unused)  {  	struct ata_port *ap = link->ap; +	const struct pci_device_id *id = ap->host->private_data;  	int dma_enabled = 0;  	struct ata_device *dev;  	struct pci_dev *pdev = to_pci_dev(ap->host->dev); -	/* Bits 5 and 6 indicate if DMA is active on master/slave */ -	if (ap->ioaddr.bmdma_addr) +	if (id->driver_data & ATA_GEN_FORCE_DMA) { +		dma_enabled = 0xff; +	} else if (ap->ioaddr.bmdma_addr) { +		/* Bits 5 and 6 indicate if DMA is active on master/slave */  		dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); +	}  	if (pdev->vendor == PCI_VENDOR_ID_CENATEK)  		dma_enabled = 0xFF; @@ -126,7 +135,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id  	const struct ata_port_info *ppi[] = { &info, NULL };  	/* Don't use the generic entry unless instructed to do so */ -	if (id->driver_data == 1 && all_generic_ide == 0) +	if ((id->driver_data & ATA_GEN_CLASS_MATCH) && all_generic_ide == 0)  		return -ENODEV;  	/* Devices that need care */ @@ -155,7 +164,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id  			return rc;  		pcim_pin_device(dev);  	} -	return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, NULL, 0); +	return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, (void *)id, 0);  }  static struct pci_device_id ata_generic[] = { @@ -167,7 +176,15 @@ static struct pci_device_id ata_generic[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_HINT,   PCI_DEVICE_ID_HINT_VXPROII_IDE), },  	{ PCI_DEVICE(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C561), },  	{ PCI_DEVICE(PCI_VENDOR_ID_OPTI,   PCI_DEVICE_ID_OPTI_82C558), }, -	{ PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), }, +	{ PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), +	  .driver_data = ATA_GEN_FORCE_DMA }, +	/* +	 * For some reason, MCP89 on MacBook 7,1 doesn't work with +	 * ahci, use ata_generic instead. +	 */ +	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA, +	  PCI_VENDOR_ID_APPLE, 0xcb89, +	  .driver_data = ATA_GEN_FORCE_DMA },  #if !defined(CONFIG_PATA_TOSHIBA) && !defined(CONFIG_PATA_TOSHIBA_MODULE)  	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },  	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),  }, @@ -175,7 +192,8 @@ static struct pci_device_id ata_generic[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5),  },  #endif	  	/* Must come last. If you add entries adjust this table appropriately */ -	{ PCI_ANY_ID,		PCI_ANY_ID,			   PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1}, +	{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL), +	  .driver_data = ATA_GEN_CLASS_MATCH },  	{ 0, },  }; diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 261f86d102e..81e772a94d5 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -324,6 +324,7 @@ static ssize_t ahci_store_em_buffer(struct device *dev,  	struct ahci_host_priv *hpriv = ap->host->private_data;  	void __iomem *mmio = hpriv->mmio;  	void __iomem *em_mmio = mmio + hpriv->em_loc; +	const unsigned char *msg_buf = buf;  	u32 em_ctl, msg;  	unsigned long flags;  	int i; @@ -343,8 +344,8 @@ static ssize_t ahci_store_em_buffer(struct device *dev,  	}  	for (i = 0; i < size; i += 4) { -		msg = buf[i] | buf[i + 1] << 8 | -		      buf[i + 2] << 16 | buf[i + 3] << 24; +		msg = msg_buf[i] | msg_buf[i + 1] << 8 | +		      msg_buf[i + 2] << 16 | msg_buf[i + 3] << 24;  		writel(msg, em_mmio + i);  	} diff --git a/drivers/base/core.c b/drivers/base/core.c index 9630fbdf4e6..9b9d3bd54e3 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -673,7 +673,7 @@ static struct kobject *get_device_parent(struct device *dev,  		 */  		if (parent == NULL)  			parent_kobj = virtual_device_parent(dev); -		else if (parent->class) +		else if (parent->class && !dev->class->ns_type)  			return &parent->kobj;  		else  			parent_kobj = &parent->kobj; diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 3381505c8a6..72dae92f3ca 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -861,6 +861,7 @@ cciss_scsi_detect(int ctlr)  	sh->n_io_port = 0;	// I don't think we use these two...  	sh->this_id = SELF_SCSI_ID;    	sh->sg_tablesize = hba[ctlr]->maxsgentries; +	sh->max_cmd_len = MAX_COMMAND_SIZE;  	((struct cciss_scsi_adapter_data_t *)   		hba[ctlr]->scsi_ctlr)->scsi_host = sh; diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 91d11631cec..abb4ec6690f 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -386,7 +386,7 @@ static void __devexit cpqarray_remove_one_eisa (int i)  }  /* pdev is NULL for eisa */ -static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev) +static int __devinit cpqarray_register_ctlr( int i, struct pci_dev *pdev)  {  	struct request_queue *q;  	int j; @@ -503,7 +503,7 @@ Enomem4:  	return -1;  } -static int __init cpqarray_init_one( struct pci_dev *pdev, +static int __devinit cpqarray_init_one( struct pci_dev *pdev,  	const struct pci_device_id *ent)  {  	int i; @@ -740,7 +740,7 @@ __setup("smart2=", cpqarray_setup);  /*   * Find an EISA controller's signature.  Set up an hba if we find it.   */ -static int __init cpqarray_eisa_detect(void) +static int __devinit cpqarray_eisa_detect(void)  {  	int i=0, j;  	__u32 board_id; diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 6b077f93acc..7258c95e895 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1236,8 +1236,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,  	/* Last part of the attaching process ... */  	if (ns.conn >= C_CONNECTED &&  	    os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) { -		kfree(mdev->p_uuid); /* We expect to receive up-to-date UUIDs soon. */ -		mdev->p_uuid = NULL; /* ...to not use the old ones in the mean time */  		drbd_send_sizes(mdev, 0, 0);  /* to start sync... */  		drbd_send_uuids(mdev);  		drbd_send_state(mdev); diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 632e3245d1b..2151f18b21d 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1114,6 +1114,12 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp  		mdev->new_state_tmp.i = ns.i;  		ns.i = os.i;  		ns.disk = D_NEGOTIATING; + +		/* We expect to receive up-to-date UUIDs soon. +		   To avoid a race in receive_state, free p_uuid while +		   holding req_lock. I.e. atomic with the state change */ +		kfree(mdev->p_uuid); +		mdev->p_uuid = NULL;  	}  	rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL); diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 6f907ebed2d..6d34f405a2f 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -37,7 +37,7 @@  #include <linux/wait.h>  #include <linux/skbuff.h> -#include <asm/io.h> +#include <linux/io.h>  #include <pcmcia/cs_types.h>  #include <pcmcia/cs.h> diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 40aec0fb859..42d69d4de05 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -244,7 +244,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,  	if (rel) {  		hdr[0] |= 0x80 + bcsp->msgq_txseq;  		BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq); -		bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07; +		bcsp->msgq_txseq = (bcsp->msgq_txseq + 1) & 0x07;  	}  	if (bcsp->use_crc) diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 4b51982fd23..d2abf514398 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -97,20 +97,18 @@ EXPORT_SYMBOL(agp_flush_chipset);  void agp_alloc_page_array(size_t size, struct agp_memory *mem)  {  	mem->pages = NULL; -	mem->vmalloc_flag = false;  	if (size <= 2*PAGE_SIZE) -		mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NORETRY); +		mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);  	if (mem->pages == NULL) {  		mem->pages = vmalloc(size); -		mem->vmalloc_flag = true;  	}  }  EXPORT_SYMBOL(agp_alloc_page_array);  void agp_free_page_array(struct agp_memory *mem)  { -	if (mem->vmalloc_flag) { +	if (is_vmalloc_addr(mem->pages)) {  		vfree(mem->pages);  	} else {  		kfree(mem->pages); diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 9344216183a..a7547150a70 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1216,17 +1216,20 @@ static int intel_i915_get_gtt_size(void)  		/* G33's GTT size defined in gmch_ctrl */  		pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); -		switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { -		case G33_PGETBL_SIZE_1M: +		switch (gmch_ctrl & I830_GMCH_GMS_MASK) { +		case I830_GMCH_GMS_STOLEN_512: +			size = 512; +			break; +		case I830_GMCH_GMS_STOLEN_1024:  			size = 1024;  			break; -		case G33_PGETBL_SIZE_2M: -			size = 2048; +		case I830_GMCH_GMS_STOLEN_8192: +			size = 8*1024;  			break;  		default:  			dev_info(&agp_bridge->dev->dev,  				 "unknown page table size 0x%x, assuming 512KB\n", -				(gmch_ctrl & G33_PGETBL_SIZE_MASK)); +				(gmch_ctrl & I830_GMCH_GMS_MASK));  			size = 512;  		}  	} else { diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 35603dd4e6c..094bdc355b1 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -302,6 +302,12 @@ struct smi_info {  static int force_kipmid[SI_MAX_PARMS];  static int num_force_kipmid; +#ifdef CONFIG_PCI +static int pci_registered; +#endif +#ifdef CONFIG_PPC_OF +static int of_registered; +#endif  static unsigned int kipmid_max_busy_us[SI_MAX_PARMS];  static int num_max_busy_us; @@ -1018,7 +1024,7 @@ static int ipmi_thread(void *data)  		else if (smi_result == SI_SM_IDLE)  			schedule_timeout_interruptible(100);  		else -			schedule_timeout_interruptible(0); +			schedule_timeout_interruptible(1);  	}  	return 0;  } @@ -3314,6 +3320,8 @@ static __devinit int init_ipmi_si(void)  	rv = pci_register_driver(&ipmi_pci_driver);  	if (rv)  		printk(KERN_ERR PFX "Unable to register PCI driver: %d\n", rv); +	else +		pci_registered = 1;  #endif  #ifdef CONFIG_ACPI @@ -3330,6 +3338,7 @@ static __devinit int init_ipmi_si(void)  #ifdef CONFIG_PPC_OF  	of_register_platform_driver(&ipmi_of_platform_driver); +	of_registered = 1;  #endif  	/* We prefer devices with interrupts, but in the case of a machine @@ -3383,11 +3392,13 @@ static __devinit int init_ipmi_si(void)  	if (unload_when_empty && list_empty(&smi_infos)) {  		mutex_unlock(&smi_infos_lock);  #ifdef CONFIG_PCI -		pci_unregister_driver(&ipmi_pci_driver); +		if (pci_registered) +			pci_unregister_driver(&ipmi_pci_driver);  #endif  #ifdef CONFIG_PPC_OF -		of_unregister_platform_driver(&ipmi_of_platform_driver); +		if (of_registered) +			of_unregister_platform_driver(&ipmi_of_platform_driver);  #endif  		driver_unregister(&ipmi_driver.driver);  		printk(KERN_WARNING PFX @@ -3478,14 +3489,16 @@ static __exit void cleanup_ipmi_si(void)  		return;  #ifdef CONFIG_PCI -	pci_unregister_driver(&ipmi_pci_driver); +	if (pci_registered) +		pci_unregister_driver(&ipmi_pci_driver);  #endif  #ifdef CONFIG_ACPI  	pnp_unregister_driver(&ipmi_pnp_driver);  #endif  #ifdef CONFIG_PPC_OF -	of_unregister_platform_driver(&ipmi_of_platform_driver); +	if (of_registered) +		of_unregister_platform_driver(&ipmi_of_platform_driver);  #endif  	mutex_lock(&smi_infos_lock); diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 5d15630a583..878ac0c2cc6 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -493,7 +493,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)                  sysrq_key_table[i] = op_p;  } -static void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) +void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)  {  	struct sysrq_key_op *op_p;  	int orig_log_level; @@ -580,8 +580,12 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type,  	case KEY_RIGHTALT:  		if (value)  			sysrq_alt = code; -		else if (sysrq_down && code == sysrq_alt_use) -			sysrq_down = false; +		else { +			if (sysrq_down && code == sysrq_alt_use) +				sysrq_down = false; + +			sysrq_alt = 0; +		}  		break;  	case KEY_SYSRQ: diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 8e00b4ddd08..792868d24f2 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -224,6 +224,7 @@ struct	tpm_readpubek_params_out {  	u8	algorithm[4];  	u8	encscheme[2];  	u8	sigscheme[2]; +	__be32	paramsize;  	u8	parameters[12]; /*assuming RSA*/  	__be32	keysize;  	u8	modulus[256]; diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 24314a9cffe..1030f842013 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -623,7 +623,14 @@ static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)  static int tpm_tis_pnp_resume(struct pnp_dev *dev)  { -	return tpm_pm_resume(&dev->dev); +	struct tpm_chip *chip = pnp_get_drvdata(dev); +	int ret; + +	ret = tpm_pm_resume(&dev->dev); +	if (!ret) +		tpm_continue_selftest(chip); + +	return ret;  }  static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c index d7be69f1315..b7dab32ce63 100644 --- a/drivers/clocksource/cs5535-clockevt.c +++ b/drivers/clocksource/cs5535-clockevt.c @@ -194,6 +194,6 @@ err_timer:  module_init(cs5535_mfgpt_init); -MODULE_AUTHOR("Andres Salomon <dilinger@collabora.co.uk>"); +MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");  MODULE_DESCRIPTION("CS5535/CS5536 MFGPT clock event driver");  MODULE_LICENSE("GPL"); diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index f3d3898898e..717305d3044 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -449,7 +449,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,  	clk_disable(p->clk);  	/* TODO: calculate good shift from rate and counter bit width */ -	cs->shift = 10; +	cs->shift = 0;  	cs->mult = clocksource_hz2mult(p->rate, cs->shift);  	dev_info(&p->pdev->dev, "used as clock source\n"); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 063b2184caf..938b74ea9ff 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1077,6 +1077,7 @@ err_out_unregister:  err_unlock_policy:  	unlock_policy_rwsem_write(cpu); +	free_cpumask_var(policy->related_cpus);  err_free_cpumask:  	free_cpumask_var(policy->cpus);  err_free_policy: @@ -1762,17 +1763,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,  			dprintk("governor switch\n");  			/* end old governor */ -			if (data->governor) { -				/* -				 * Need to release the rwsem around governor -				 * stop due to lock dependency between -				 * cancel_delayed_work_sync and the read lock -				 * taken in the delayed work handler. -				 */ -				unlock_policy_rwsem_write(data->cpu); +			if (data->governor)  				__cpufreq_governor(data, CPUFREQ_GOV_STOP); -				lock_policy_rwsem_write(data->cpu); -			}  			/* start new governor */  			data->governor = policy->governor; diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 52ff8aa63f8..1b128702d30 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -143,7 +143,7 @@ static inline int which_bucket(unsigned int duration)  	 * This allows us to calculate  	 * E(duration)|iowait  	 */ -	if (nr_iowait_cpu()) +	if (nr_iowait_cpu(smp_processor_id()))  		bucket = BUCKETS/2;  	if (duration < 10) @@ -175,7 +175,7 @@ static inline int performance_multiplier(void)  	mult += 2 * get_loadavg();  	/* for IO wait tasks (per cpu!) we add 5x each */ -	mult += 10 * nr_iowait_cpu(); +	mult += 10 * nr_iowait_cpu(smp_processor_id());  	return mult;  } diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 637c105f53d..bd78acf3c36 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -1183,10 +1183,14 @@ static size_t sg_copy_end_to_buffer(struct scatterlist *sgl, unsigned int nents,  				/* Copy part of this segment */  				ignore = skip - offset;  				len = miter.length - ignore; +				if (boffset + len > buflen) +					len = buflen - boffset;  				memcpy(buf + boffset, miter.addr + ignore, len);  			} else { -				/* Copy all of this segment */ +				/* Copy all of this segment (up to buflen) */  				len = miter.length; +				if (boffset + len > buflen) +					len = buflen - boffset;  				memcpy(buf + boffset, miter.addr, len);  			}  			boffset += len; diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c index 5a22ca6927e..7c3747902a3 100644 --- a/drivers/dma/ppc4xx/adma.c +++ b/drivers/dma/ppc4xx/adma.c @@ -4257,10 +4257,12 @@ static int ppc440spe_adma_setup_irqs(struct ppc440spe_adma_device *adev,  				     struct ppc440spe_adma_chan *chan,  				     int *initcode)  { +	struct of_device *ofdev;  	struct device_node *np;  	int ret; -	np = container_of(adev->dev, struct of_device, dev)->node; +	ofdev = container_of(adev->dev, struct of_device, dev); +	np = ofdev->dev.of_node;  	if (adev->id != PPC440SPE_XOR_ID) {  		adev->err_irq = irq_of_parse_and_map(np, 1);  		if (adev->err_irq == NO_IRQ) { diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index aedef7941b2..0d2f9dbb47e 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -209,7 +209,7 @@ config EDAC_I5100  config EDAC_MPC85XX  	tristate "Freescale MPC83xx / MPC85xx" -	depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || MPC85xx) +	depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || PPC_85xx)  	help  	  Support for error detection and correction on the Freescale  	  MPC8349, MPC8560, MPC8540, MPC8548 diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index cf17dbb8014..ac9f7985096 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1958,20 +1958,20 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome)  	u32 value = 0;  	int err_sym = 0; -	amd64_read_pci_cfg(pvt->misc_f3_ctl, 0x180, &value); +	if (boot_cpu_data.x86 == 0x10) { -	/* F3x180[EccSymbolSize]=1, x8 symbols */ -	if (boot_cpu_data.x86 == 0x10 && -	    boot_cpu_data.x86_model > 7 && -	    value & BIT(25)) { -		err_sym = decode_syndrome(syndrome, x8_vectors, -					  ARRAY_SIZE(x8_vectors), 8); -		return map_err_sym_to_channel(err_sym, 8); -	} else { -		err_sym = decode_syndrome(syndrome, x4_vectors, -					  ARRAY_SIZE(x4_vectors), 4); -		return map_err_sym_to_channel(err_sym, 4); +		amd64_read_pci_cfg(pvt->misc_f3_ctl, 0x180, &value); + +		/* F3x180[EccSymbolSize]=1 => x8 symbols */ +		if (boot_cpu_data.x86_model > 7 && +		    value & BIT(25)) { +			err_sym = decode_syndrome(syndrome, x8_vectors, +						  ARRAY_SIZE(x8_vectors), 8); +			return map_err_sym_to_channel(err_sym, 8); +		}  	} +	err_sym = decode_syndrome(syndrome, x4_vectors, ARRAY_SIZE(x4_vectors), 4); +	return map_err_sym_to_channel(err_sym, 4);  }  /* diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 6b8b7b41ec5..e0187d16dd7 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1233,10 +1233,28 @@ static void __init i7core_xeon_pci_fixup(struct pci_id_table *table)  			for (i = 0; i < MAX_SOCKET_BUSES; i++)  				pcibios_scan_specific_bus(255-i);  		} +		pci_dev_put(pdev);  		table++;  	}  } +static unsigned i7core_pci_lastbus(void) +{ +	int last_bus = 0, bus; +	struct pci_bus *b = NULL; + +	while ((b = pci_find_next_bus(b)) != NULL) { +		bus = b->number; +		debugf0("Found bus %d\n", bus); +		if (bus > last_bus) +			last_bus = bus; +	} + +	debugf0("Last bus %d\n", last_bus); + +	return last_bus; +} +  /*   *	i7core_get_devices	Find and perform 'get' operation on the MCH's   *			device/functions we want to reference for this driver @@ -1244,7 +1262,8 @@ static void __init i7core_xeon_pci_fixup(struct pci_id_table *table)   *			Need to 'get' device 16 func 1 and func 2   */  int i7core_get_onedevice(struct pci_dev **prev, int devno, -			 struct pci_id_descr *dev_descr, unsigned n_devs) +			 struct pci_id_descr *dev_descr, unsigned n_devs, +			 unsigned last_bus)  {  	struct i7core_dev *i7core_dev; @@ -1281,7 +1300,7 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno,  		if (devno == 0)  			return -ENODEV; -		i7core_printk(KERN_ERR, +		i7core_printk(KERN_INFO,  			"Device not found: dev %02x.%d PCI ID %04x:%04x\n",  			dev_descr->dev, dev_descr->func,  			PCI_VENDOR_ID_INTEL, dev_descr->dev_id); @@ -1291,10 +1310,7 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno,  	}  	bus = pdev->bus->number; -	if (bus == 0x3f) -		socket = 0; -	else -		socket = 255 - bus; +	socket = last_bus - bus;  	i7core_dev = get_i7core_dev(socket);  	if (!i7core_dev) { @@ -1358,17 +1374,21 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno,  static int i7core_get_devices(struct pci_id_table *table)  { -	int i, rc; +	int i, rc, last_bus;  	struct pci_dev *pdev = NULL;  	struct pci_id_descr *dev_descr; +	last_bus = i7core_pci_lastbus(); +  	while (table && table->descr) {  		dev_descr = table->descr;  		for (i = 0; i < table->n_devs; i++) {  			pdev = NULL;  			do { -				rc = i7core_get_onedevice(&pdev, i, &dev_descr[i], -							  table->n_devs); +				rc = i7core_get_onedevice(&pdev, i, +							  &dev_descr[i], +							  table->n_devs, +							  last_bus);  				if (rc < 0) {  					if (i == 0) {  						i = table->n_devs; @@ -1927,21 +1947,26 @@ fail:   *		0 for FOUND a device   *		< 0 for error code   */ + +static int probed = 0; +  static int __devinit i7core_probe(struct pci_dev *pdev,  				  const struct pci_device_id *id)  { -	int dev_idx = id->driver_data;  	int rc;  	struct i7core_dev *i7core_dev; +	/* get the pci devices we want to reserve for our use */ +	mutex_lock(&i7core_edac_lock); +  	/*  	 * All memory controllers are allocated at the first pass.  	 */ -	if (unlikely(dev_idx >= 1)) +	if (unlikely(probed >= 1)) { +		mutex_unlock(&i7core_edac_lock);  		return -EINVAL; - -	/* get the pci devices we want to reserve for our use */ -	mutex_lock(&i7core_edac_lock); +	} +	probed++;  	rc = i7core_get_devices(pci_dev_table);  	if (unlikely(rc < 0)) @@ -2013,6 +2038,8 @@ static void __devexit i7core_remove(struct pci_dev *pdev)  				      i7core_dev->socket);  		}  	} +	probed--; +  	mutex_unlock(&i7core_edac_lock);  } diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 52ca09bf472..1052340e680 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -336,6 +336,7 @@ static struct of_device_id mpc85xx_pci_err_of_match[] = {  	},  	{},  }; +MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match);  static struct of_platform_driver mpc85xx_pci_err_driver = {  	.probe = mpc85xx_pci_err_probe, @@ -650,6 +651,7 @@ static struct of_device_id mpc85xx_l2_err_of_match[] = {  	{ .compatible = "fsl,p2020-l2-cache-controller", },  	{},  }; +MODULE_DEVICE_TABLE(of, mpc85xx_l2_err_of_match);  static struct of_platform_driver mpc85xx_l2_err_driver = {  	.probe = mpc85xx_l2_err_probe, @@ -1120,11 +1122,13 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = {  	{ .compatible = "fsl,mpc8555-memory-controller", },  	{ .compatible = "fsl,mpc8560-memory-controller", },  	{ .compatible = "fsl,mpc8568-memory-controller", }, +	{ .compatible = "fsl,mpc8569-memory-controller", },  	{ .compatible = "fsl,mpc8572-memory-controller", },  	{ .compatible = "fsl,mpc8349-memory-controller", },  	{ .compatible = "fsl,p2020-memory-controller", },  	{},  }; +MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);  static struct of_platform_driver mpc85xx_mc_err_driver = {  	.probe = mpc85xx_mc_err_probe, diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 724038dab4c..7face915b96 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1,5 +1,5 @@  # -# GPIO infrastructure and expanders +# platform-neutral GPIO infrastructure and expanders  #  config ARCH_WANT_OPTIONAL_GPIOLIB diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 51c3cdd41b5..e53dcff49b4 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -1,4 +1,8 @@ -# gpio support: dedicated expander chips, etc +# generic gpio support: dedicated expander chips, etc +# +# NOTE: platform-specific GPIO drivers don't belong in the +# drivers/gpio directory; put them with other platform setup +# code, IRQ controllers, board init, etc.  ccflags-$(CONFIG_DEBUG_GPIO)	+= -DDEBUG diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c index f73a1555e49..e23c06893d1 100644 --- a/drivers/gpio/cs5535-gpio.c +++ b/drivers/gpio/cs5535-gpio.c @@ -352,6 +352,6 @@ static void __exit cs5535_gpio_exit(void)  module_init(cs5535_gpio_init);  module_exit(cs5535_gpio_exit); -MODULE_AUTHOR("Andres Salomon <dilinger@collabora.co.uk>"); +MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");  MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");  MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 3ca36542e33..4e51fe3c1fc 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -893,10 +893,12 @@ EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low);  void gpio_unexport(unsigned gpio)  {  	struct gpio_desc	*desc; -	int			status = -EINVAL; +	int			status = 0; -	if (!gpio_is_valid(gpio)) +	if (!gpio_is_valid(gpio)) { +		status = -EINVAL;  		goto done; +	}  	mutex_lock(&sysfs_lock); @@ -911,7 +913,6 @@ void gpio_unexport(unsigned gpio)  			clear_bit(FLAG_EXPORT, &desc->flags);  			put_device(dev);  			device_unregister(dev); -			status = 0;  		} else  			status = -ENODEV;  	} diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c index ee568c8fcbd..5005990f751 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/pl061.c @@ -232,7 +232,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)  	desc->chip->unmask(irq);  } -static int __init pl061_probe(struct amba_device *dev, struct amba_id *id) +static int pl061_probe(struct amba_device *dev, struct amba_id *id)  {  	struct pl061_platform_data *pdata;  	struct pl061_gpio *chip; @@ -333,7 +333,7 @@ free_mem:  	return ret;  } -static struct amba_id pl061_ids[] __initdata = { +static struct amba_id pl061_ids[] = {  	{  		.id	= 0x00041061,  		.mask	= 0x000fffff, diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index da06476f2df..9585e531ac6 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -864,8 +864,8 @@ drm_mode_std(struct drm_connector *connector, struct edid *edid,  		mode = drm_cvt_mode(dev, 1366, 768, vrefresh_rate, 0, 0,  				    false);  		mode->hdisplay = 1366; -		mode->vsync_start = mode->vsync_start - 1; -		mode->vsync_end = mode->vsync_end - 1; +		mode->hsync_start = mode->hsync_start - 1; +		mode->hsync_end = mode->hsync_end - 1;  		return mode;  	} diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 08c4c926e65..719662034bb 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -146,7 +146,7 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_conn  				cvt = 1;  			break;  		case 'R': -			if (!cvt) +			if (cvt)  				rb = 1;  			break;  		case 'm': @@ -315,8 +315,9 @@ static void drm_fb_helper_on(struct fb_info *info)  	struct drm_device *dev = fb_helper->dev;  	struct drm_crtc *crtc;  	struct drm_crtc_helper_funcs *crtc_funcs; +	struct drm_connector *connector;  	struct drm_encoder *encoder; -	int i; +	int i, j;  	/*  	 * For each CRTC in this fb, turn the crtc on then, @@ -332,7 +333,14 @@ static void drm_fb_helper_on(struct fb_info *info)  		crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); - +		/* Walk the connectors & encoders on this fb turning them on */ +		for (j = 0; j < fb_helper->connector_count; j++) { +			connector = fb_helper->connector_info[j]->connector; +			connector->dpms = DRM_MODE_DPMS_ON; +			drm_connector_property_set_value(connector, +							 dev->mode_config.dpms_property, +							 DRM_MODE_DPMS_ON); +		}  		/* Found a CRTC on this fb, now find encoders */  		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {  			if (encoder->crtc == crtc) { @@ -352,8 +360,9 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)  	struct drm_device *dev = fb_helper->dev;  	struct drm_crtc *crtc;  	struct drm_crtc_helper_funcs *crtc_funcs; +	struct drm_connector *connector;  	struct drm_encoder *encoder; -	int i; +	int i, j;  	/*  	 * For each CRTC in this fb, find all associated encoders @@ -367,6 +376,14 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)  		if (!crtc->enabled)  			continue; +		/* Walk the connectors on this fb and mark them off */ +		for (j = 0; j < fb_helper->connector_count; j++) { +			connector = fb_helper->connector_info[j]->connector; +			connector->dpms = dpms_mode; +			drm_connector_property_set_value(connector, +							 dev->mode_config.dpms_property, +							 dpms_mode); +		}  		/* Found a CRTC on this fb, now find encoders */  		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {  			if (encoder->crtc == crtc) { @@ -1024,11 +1041,18 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_conne  	}  create_mode: -	mode = drm_cvt_mode(fb_helper_conn->connector->dev, cmdline_mode->xres, -			    cmdline_mode->yres, -			    cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60, -			    cmdline_mode->rb, cmdline_mode->interlace, -			    cmdline_mode->margins); +	if (cmdline_mode->cvt) +		mode = drm_cvt_mode(fb_helper_conn->connector->dev, +				    cmdline_mode->xres, cmdline_mode->yres, +				    cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60, +				    cmdline_mode->rb, cmdline_mode->interlace, +				    cmdline_mode->margins); +	else +		mode = drm_gtf_mode(fb_helper_conn->connector->dev, +				    cmdline_mode->xres, cmdline_mode->yres, +				    cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60, +				    cmdline_mode->interlace, +				    cmdline_mode->margins);  	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);  	list_add(&mode->head, &fb_helper_conn->connector->modes);  	return mode; diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c index 66c697bc9b2..56f66426207 100644 --- a/drivers/gpu/drm/i915/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/dvo_tfp410.c @@ -208,7 +208,7 @@ static enum drm_connector_status tfp410_detect(struct intel_dvo_device *dvo)  	uint8_t ctl2;  	if (tfp410_readb(dvo, TFP410_CTL_2, &ctl2)) { -		if (ctl2 & TFP410_CTL_2_HTPLG) +		if (ctl2 & TFP410_CTL_2_RSEN)  			ret = connector_status_connected;  		else  			ret = connector_status_disconnected; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 52510ad8b25..9214119c015 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -605,6 +605,9 @@ static int i915_fbc_status(struct seq_file *m, void *unused)  		case FBC_NOT_TILED:  			seq_printf(m, "scanout buffer not tiled");  			break; +		case FBC_MULTIPLE_PIPES: +			seq_printf(m, "multiple pipes are enabled"); +			break;  		default:  			seq_printf(m, "unknown reason");  		} @@ -620,7 +623,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)  	drm_i915_private_t *dev_priv = dev->dev_private;  	bool sr_enabled = false; -	if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev)) +	if (IS_I965GM(dev) || IS_I945G(dev) || IS_I945GM(dev))  		sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;  	else if (IS_I915GM(dev))  		sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 59a2bf8592e..2305a1234f1 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -128,9 +128,11 @@ static int i915_dma_cleanup(struct drm_device * dev)  	if (dev->irq_enabled)  		drm_irq_uninstall(dev); +	mutex_lock(&dev->struct_mutex);  	intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);  	if (HAS_BSD(dev))  		intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); +	mutex_unlock(&dev->struct_mutex);  	/* Clear the HWS virtual address at teardown */  	if (I915_NEED_GFX_HWS(dev)) @@ -1229,7 +1231,7 @@ static void i915_warn_stolen(struct drm_device *dev)  static void i915_setup_compression(struct drm_device *dev, int size)  {  	struct drm_i915_private *dev_priv = dev->dev_private; -	struct drm_mm_node *compressed_fb, *compressed_llb; +	struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);  	unsigned long cfb_base;  	unsigned long ll_base = 0; @@ -1298,7 +1300,7 @@ static void i915_cleanup_compression(struct drm_device *dev)  	struct drm_i915_private *dev_priv = dev->dev_private;  	drm_mm_put_block(dev_priv->compressed_fb); -	if (!IS_GM45(dev)) +	if (dev_priv->compressed_llb)  		drm_mm_put_block(dev_priv->compressed_llb);  } @@ -1410,6 +1412,10 @@ static int i915_load_modeset_init(struct drm_device *dev,  	if (ret)  		goto cleanup_vga_client; +	/* IIR "flip pending" bit means done if this bit is set */ +	if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE)) +		dev_priv->flip_pending_is_done = true; +  	intel_modeset_init(dev);  	ret = drm_irq_install(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 27658315984..2e1744d37ad 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -215,6 +215,7 @@ enum no_fbc_reason {  	FBC_MODE_TOO_LARGE, /* mode too large for compression */  	FBC_BAD_PLANE, /* fbc not supported on plane */  	FBC_NOT_TILED, /* buffer not tiled */ +	FBC_MULTIPLE_PIPES, /* more than one pipe active */  };  enum intel_pch { @@ -222,6 +223,8 @@ enum intel_pch {  	PCH_CPT,	/* Cougarpoint PCH */  }; +#define QUIRK_PIPEA_FORCE (1<<0) +  struct intel_fbdev;  typedef struct drm_i915_private { @@ -337,6 +340,8 @@ typedef struct drm_i915_private {  	/* PCH chipset type */  	enum intel_pch pch_type; +	unsigned long quirks; +  	/* Register state */  	bool modeset_on_lid;  	u8 saveLBB; @@ -596,6 +601,7 @@ typedef struct drm_i915_private {  	struct drm_crtc *plane_to_crtc_mapping[2];  	struct drm_crtc *pipe_to_crtc_mapping[2];  	wait_queue_head_t pending_flip_queue; +	bool flip_pending_is_done;  	/* Reclocking support */  	bool render_reclock_avail; @@ -1076,7 +1082,7 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);  	drm_i915_private_t *dev_priv = dev->dev_private;                \  	if (I915_VERBOSE)						\  		DRM_DEBUG("   BEGIN_LP_RING %x\n", (int)(n));		\ -	intel_ring_begin(dev, &dev_priv->render_ring, 4*(n));		\ +	intel_ring_begin(dev, &dev_priv->render_ring, (n));		\  } while (0) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9ded3dae6c8..5aa747fc25a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2239,8 +2239,9 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,  	mapping = inode->i_mapping;  	for (i = 0; i < page_count; i++) {  		page = read_cache_page_gfp(mapping, i, -					   mapping_gfp_mask (mapping) | +					   GFP_HIGHUSER |  					   __GFP_COLD | +					   __GFP_RECLAIMABLE |  					   gfpmask);  		if (IS_ERR(page))  			goto err_pages; @@ -3646,6 +3647,7 @@ i915_gem_wait_for_pending_flip(struct drm_device *dev,  	return ret;  } +  int  i915_gem_do_execbuffer(struct drm_device *dev, void *data,  		       struct drm_file *file_priv, @@ -3793,7 +3795,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,  				unsigned long long total_size = 0;  				int num_fences = 0;  				for (i = 0; i < args->buffer_count; i++) { -					obj_priv = object_list[i]->driver_private; +					obj_priv = to_intel_bo(object_list[i]);  					total_size += object_list[i]->size;  					num_fences += @@ -4741,6 +4743,16 @@ i915_gem_load(struct drm_device *dev)  	list_add(&dev_priv->mm.shrink_list, &shrink_list);  	spin_unlock(&shrink_list_lock); +	/* On GEN3 we really need to make sure the ARB C3 LP bit is set */ +	if (IS_GEN3(dev)) { +		u32 tmp = I915_READ(MI_ARB_STATE); +		if (!(tmp & MI_ARB_C3_LP_WRITE_ENABLE)) { +			/* arb state is a masked write, so set bit + bit in mask */ +			tmp = MI_ARB_C3_LP_WRITE_ENABLE | (MI_ARB_C3_LP_WRITE_ENABLE << MI_ARB_MASK_SHIFT); +			I915_WRITE(MI_ARB_STATE, tmp); +		} +	} +  	/* Old X drivers will take 0-2 for front, back, depth buffers */  	if (!drm_core_check_feature(dev, DRIVER_MODESET))  		dev_priv->fence_reg_start = 3; @@ -4977,7 +4989,7 @@ i915_gpu_is_active(struct drm_device *dev)  }  static int -i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask) +i915_gem_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)  {  	drm_i915_private_t *dev_priv, *next_dev;  	struct drm_i915_gem_object *obj_priv, *next_obj; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2479be001e4..dba53d4b9fb 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -940,22 +940,30 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)  		if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT))  			DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); -		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) +		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {  			intel_prepare_page_flip(dev, 0); +			if (dev_priv->flip_pending_is_done) +				intel_finish_page_flip_plane(dev, 0); +		} -		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) +		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {  			intel_prepare_page_flip(dev, 1); +			if (dev_priv->flip_pending_is_done) +				intel_finish_page_flip_plane(dev, 1); +		}  		if (pipea_stats & vblank_status) {  			vblank++;  			drm_handle_vblank(dev, 0); -			intel_finish_page_flip(dev, 0); +			if (!dev_priv->flip_pending_is_done) +				intel_finish_page_flip(dev, 0);  		}  		if (pipeb_stats & vblank_status) {  			vblank++;  			drm_handle_vblank(dev, 1); -			intel_finish_page_flip(dev, 1); +			if (!dev_priv->flip_pending_is_done) +				intel_finish_page_flip(dev, 1);  		}  		if ((pipea_stats & I915_LEGACY_BLC_EVENT_STATUS) || @@ -1387,29 +1395,10 @@ int i915_driver_irq_postinstall(struct drm_device *dev)  	dev_priv->pipestat[1] = 0;  	if (I915_HAS_HOTPLUG(dev)) { -		u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); - -		/* Note HDMI and DP share bits */ -		if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) -			hotplug_en |= HDMIB_HOTPLUG_INT_EN; -		if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) -			hotplug_en |= HDMIC_HOTPLUG_INT_EN; -		if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) -			hotplug_en |= HDMID_HOTPLUG_INT_EN; -		if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) -			hotplug_en |= SDVOC_HOTPLUG_INT_EN; -		if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) -			hotplug_en |= SDVOB_HOTPLUG_INT_EN; -		if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) -			hotplug_en |= CRT_HOTPLUG_INT_EN; -		/* Ignore TV since it's buggy */ - -		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); -  		/* Enable in IER... */  		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;  		/* and unmask in IMR */ -		i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT); +		dev_priv->irq_mask_reg &= ~I915_DISPLAY_PORT_INTERRUPT;  	}  	/* @@ -1427,16 +1416,41 @@ int i915_driver_irq_postinstall(struct drm_device *dev)  	}  	I915_WRITE(EMR, error_mask); -	/* Disable pipe interrupt enables, clear pending pipe status */ -	I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); -	I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); -	/* Clear pending interrupt status */ -	I915_WRITE(IIR, I915_READ(IIR)); - -	I915_WRITE(IER, enable_mask);  	I915_WRITE(IMR, dev_priv->irq_mask_reg); +	I915_WRITE(IER, enable_mask);  	(void) I915_READ(IER); +	if (I915_HAS_HOTPLUG(dev)) { +		u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); + +		/* Note HDMI and DP share bits */ +		if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) +			hotplug_en |= HDMIB_HOTPLUG_INT_EN; +		if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) +			hotplug_en |= HDMIC_HOTPLUG_INT_EN; +		if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) +			hotplug_en |= HDMID_HOTPLUG_INT_EN; +		if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) +			hotplug_en |= SDVOC_HOTPLUG_INT_EN; +		if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) +			hotplug_en |= SDVOB_HOTPLUG_INT_EN; +		if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { +			hotplug_en |= CRT_HOTPLUG_INT_EN; + +			/* Programming the CRT detection parameters tends +			   to generate a spurious hotplug event about three +			   seconds later.  So just do it once. +			*/ +			if (IS_G4X(dev)) +				hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; +			hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; +		} + +		/* Ignore TV since it's buggy */ + +		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); +	} +  	opregion_enable_asle(dev);  	return 0; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 64b0a3afd92..cf41c672def 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -178,6 +178,7 @@  #define   MI_OVERLAY_OFF	(0x2<<21)  #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)  #define MI_DISPLAY_FLIP		MI_INSTR(0x14, 2) +#define MI_DISPLAY_FLIP_I915	MI_INSTR(0x14, 1)  #define   MI_DISPLAY_FLIP_PLANE(n) ((n) << 20)  #define MI_STORE_DWORD_IMM	MI_INSTR(0x20, 1)  #define   MI_MEM_VIRTUAL	(1 << 22) /* 965+ only */ @@ -358,6 +359,70 @@  #define LM_BURST_LENGTH     0x00000700  #define LM_FIFO_WATERMARK   0x0000001F  #define MI_ARB_STATE	0x020e4 /* 915+ only */ +#define   MI_ARB_MASK_SHIFT	  16	/* shift for enable bits */ + +/* Make render/texture TLB fetches lower priorty than associated data + *   fetches. This is not turned on by default + */ +#define   MI_ARB_RENDER_TLB_LOW_PRIORITY	(1 << 15) + +/* Isoch request wait on GTT enable (Display A/B/C streams). + * Make isoch requests stall on the TLB update. May cause + * display underruns (test mode only) + */ +#define   MI_ARB_ISOCH_WAIT_GTT			(1 << 14) + +/* Block grant count for isoch requests when block count is + * set to a finite value. + */ +#define   MI_ARB_BLOCK_GRANT_MASK		(3 << 12) +#define   MI_ARB_BLOCK_GRANT_8			(0 << 12)	/* for 3 display planes */ +#define   MI_ARB_BLOCK_GRANT_4			(1 << 12)	/* for 2 display planes */ +#define   MI_ARB_BLOCK_GRANT_2			(2 << 12)	/* for 1 display plane */ +#define   MI_ARB_BLOCK_GRANT_0			(3 << 12)	/* don't use */ + +/* Enable render writes to complete in C2/C3/C4 power states. + * If this isn't enabled, render writes are prevented in low + * power states. That seems bad to me. + */ +#define   MI_ARB_C3_LP_WRITE_ENABLE		(1 << 11) + +/* This acknowledges an async flip immediately instead + * of waiting for 2TLB fetches. + */ +#define   MI_ARB_ASYNC_FLIP_ACK_IMMEDIATE	(1 << 10) + +/* Enables non-sequential data reads through arbiter + */ +#define   MI_ARB_DUAL_DATA_PHASE_DISABLE       	(1 << 9) + +/* Disable FSB snooping of cacheable write cycles from binner/render + * command stream + */ +#define   MI_ARB_CACHE_SNOOP_DISABLE		(1 << 8) + +/* Arbiter time slice for non-isoch streams */ +#define   MI_ARB_TIME_SLICE_MASK		(7 << 5) +#define   MI_ARB_TIME_SLICE_1			(0 << 5) +#define   MI_ARB_TIME_SLICE_2			(1 << 5) +#define   MI_ARB_TIME_SLICE_4			(2 << 5) +#define   MI_ARB_TIME_SLICE_6			(3 << 5) +#define   MI_ARB_TIME_SLICE_8			(4 << 5) +#define   MI_ARB_TIME_SLICE_10			(5 << 5) +#define   MI_ARB_TIME_SLICE_14			(6 << 5) +#define   MI_ARB_TIME_SLICE_16			(7 << 5) + +/* Low priority grace period page size */ +#define   MI_ARB_LOW_PRIORITY_GRACE_4KB		(0 << 4)	/* default */ +#define   MI_ARB_LOW_PRIORITY_GRACE_8KB		(1 << 4) + +/* Disable display A/B trickle feed */ +#define   MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE	(1 << 2) + +/* Set display plane priority */ +#define   MI_ARB_DISPLAY_PRIORITY_A_B		(0 << 0)	/* display A > display B */ +#define   MI_ARB_DISPLAY_PRIORITY_B_A		(1 << 0)	/* display B > display A */ +  #define CACHE_MODE_0	0x02120 /* 915+ only */  #define   CM0_MASK_SHIFT          16  #define   CM0_IZ_OPT_DISABLE      (1<<6) @@ -368,6 +433,9 @@  #define   CM0_RC_OP_FLUSH_DISABLE (1<<0)  #define BB_ADDR		0x02140 /* 8 bytes */  #define GFX_FLSH_CNTL	0x02170 /* 915+ only */ +#define ECOSKPD		0x021d0 +#define   ECO_GATING_CX_ONLY	(1<<3) +#define   ECO_FLIP_DONE		(1<<0)  /* GEN6 interrupt control */  #define GEN6_RENDER_HWSTAM	0x2098 @@ -1130,7 +1198,6 @@  #define CRT_HOTPLUG_DETECT_DELAY_2G		(1 << 4)  #define CRT_HOTPLUG_DETECT_VOLTAGE_325MV	(0 << 2)  #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV	(1 << 2) -#define CRT_HOTPLUG_MASK			(0x3fc) /* Bits 9-2 */  #define PORT_HOTPLUG_STAT	0x61114  #define   HDMIB_HOTPLUG_INT_STATUS		(1 << 29) @@ -2802,6 +2869,7 @@  #define PCH_PP_STATUS		0xc7200  #define PCH_PP_CONTROL		0xc7204 +#define  PANEL_UNLOCK_REGS	(0xabcd << 16)  #define  EDP_FORCE_VDD		(1 << 3)  #define  EDP_BLC_ENABLE		(1 << 2)  #define  PANEL_POWER_RESET	(1 << 1) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 22ff3845573..ee0732b222a 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -234,14 +234,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)  	else  		tries = 1;  	hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN); -	hotplug_en &= CRT_HOTPLUG_MASK;  	hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; -	if (IS_G4X(dev)) -		hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; - -	hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; -  	for (i = 0; i < tries ; i++) {  		unsigned long timeout;  		/* turn on the FORCE_DETECT */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cc8131ff319..5e21b311982 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -862,8 +862,8 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,  	intel_clock_t clock;  	int max_n;  	bool found; -	/* approximately equals target * 0.00488 */ -	int err_most = (target >> 8) + (target >> 10); +	/* approximately equals target * 0.00585 */ +	int err_most = (target >> 8) + (target >> 9);  	found = false;  	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { @@ -1180,8 +1180,12 @@ static void intel_update_fbc(struct drm_crtc *crtc,  	struct drm_framebuffer *fb = crtc->fb;  	struct intel_framebuffer *intel_fb;  	struct drm_i915_gem_object *obj_priv; +	struct drm_crtc *tmp_crtc;  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);  	int plane = intel_crtc->plane; +	int crtcs_enabled = 0; + +	DRM_DEBUG_KMS("\n");  	if (!i915_powersave)  		return; @@ -1199,10 +1203,21 @@ static void intel_update_fbc(struct drm_crtc *crtc,  	 * If FBC is already on, we just have to verify that we can  	 * keep it that way...  	 * Need to disable if: +	 *   - more than one pipe is active  	 *   - changing FBC params (stride, fence, mode)  	 *   - new fb is too large to fit in compressed buffer  	 *   - going to an unsupported config (interlace, pixel multiply, etc.)  	 */ +	list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { +		if (tmp_crtc->enabled) +			crtcs_enabled++; +	} +	DRM_DEBUG_KMS("%d pipes active\n", crtcs_enabled); +	if (crtcs_enabled > 1) { +		DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); +		dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; +		goto out_disable; +	}  	if (intel_fb->obj->size > dev_priv->cfb_size) {  		DRM_DEBUG_KMS("framebuffer too large, disabling "  				"compression\n"); @@ -1255,7 +1270,7 @@ out_disable:  	}  } -static int +int  intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj)  {  	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); @@ -2255,6 +2270,11 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)  			intel_wait_for_vblank(dev);  		} +		/* Don't disable pipe A or pipe A PLLs if needed */ +		if (pipeconf_reg == PIPEACONF && +		    (dev_priv->quirks & QUIRK_PIPEA_FORCE)) +			goto skip_pipe_off; +  		/* Next, disable display pipes */  		temp = I915_READ(pipeconf_reg);  		if ((temp & PIPEACONF_ENABLE) != 0) { @@ -2270,7 +2290,7 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)  			I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);  			I915_READ(dpll_reg);  		} - +	skip_pipe_off:  		/* Wait for the clocks to turn off. */  		udelay(150);  		break; @@ -2356,8 +2376,6 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,  		if (mode->clock * 3 > 27000 * 4)  			return MODE_CLOCK_HIGH;  	} - -	drm_mode_set_crtcinfo(adjusted_mode, 0);  	return true;  } @@ -2970,11 +2988,13 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,  		if (srwm < 0)  			srwm = 1;  		srwm &= 0x3f; -		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); +		if (IS_I965GM(dev)) +			I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);  	} else {  		/* Turn off self refresh if both pipes are enabled */ -		I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) -					& ~FW_BLC_SELF_EN); +		if (IS_I965GM(dev)) +			I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) +				   & ~FW_BLC_SELF_EN);  	}  	DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n", @@ -3734,6 +3754,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,  			if (dev_priv->lvds_dither) {  				if (HAS_PCH_SPLIT(dev)) {  					pipeconf |= PIPE_ENABLE_DITHER; +					pipeconf &= ~PIPE_DITHER_TYPE_MASK;  					pipeconf |= PIPE_DITHER_TYPE_ST01;  				} else  					lvds |= LVDS_ENABLE_DITHER; @@ -4410,7 +4431,8 @@ static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule)  		DRM_DEBUG_DRIVER("upclocking LVDS\n");  		/* Unlock panel regs */ -		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16)); +		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | +			   PANEL_UNLOCK_REGS);  		dpll &= ~DISPLAY_RATE_SELECT_FPA1;  		I915_WRITE(dpll_reg, dpll); @@ -4453,7 +4475,8 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)  		DRM_DEBUG_DRIVER("downclocking LVDS\n");  		/* Unlock panel regs */ -		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16)); +		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | +			   PANEL_UNLOCK_REGS);  		dpll |= DISPLAY_RATE_SELECT_FPA1;  		I915_WRITE(dpll_reg, dpll); @@ -4483,6 +4506,7 @@ static void intel_idle_update(struct work_struct *work)  	struct drm_device *dev = dev_priv->dev;  	struct drm_crtc *crtc;  	struct intel_crtc *intel_crtc; +	int enabled = 0;  	if (!i915_powersave)  		return; @@ -4491,21 +4515,22 @@ static void intel_idle_update(struct work_struct *work)  	i915_update_gfx_val(dev_priv); -	if (IS_I945G(dev) || IS_I945GM(dev)) { -		DRM_DEBUG_DRIVER("enable memory self refresh on 945\n"); -		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN); -	} -  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {  		/* Skip inactive CRTCs */  		if (!crtc->fb)  			continue; +		enabled++;  		intel_crtc = to_intel_crtc(crtc);  		if (!intel_crtc->busy)  			intel_decrease_pllclock(crtc);  	} +	if ((enabled == 1) && (IS_I945G(dev) || IS_I945GM(dev))) { +		DRM_DEBUG_DRIVER("enable memory self refresh on 945\n"); +		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN); +	} +  	mutex_unlock(&dev->struct_mutex);  } @@ -4601,10 +4626,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)  	kfree(work);  } -void intel_finish_page_flip(struct drm_device *dev, int pipe) +static void do_intel_finish_page_flip(struct drm_device *dev, +				      struct drm_crtc *crtc)  {  	drm_i915_private_t *dev_priv = dev->dev_private; -	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);  	struct intel_unpin_work *work;  	struct drm_i915_gem_object *obj_priv; @@ -4648,6 +4673,22 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)  	schedule_work(&work->work);  } +void intel_finish_page_flip(struct drm_device *dev, int pipe) +{ +	drm_i915_private_t *dev_priv = dev->dev_private; +	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + +	do_intel_finish_page_flip(dev, crtc); +} + +void intel_finish_page_flip_plane(struct drm_device *dev, int plane) +{ +	drm_i915_private_t *dev_priv = dev->dev_private; +	struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane]; + +	do_intel_finish_page_flip(dev, crtc); +} +  void intel_prepare_page_flip(struct drm_device *dev, int plane)  {  	drm_i915_private_t *dev_priv = dev->dev_private; @@ -4675,9 +4716,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,  	struct drm_gem_object *obj;  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);  	struct intel_unpin_work *work; -	unsigned long flags; +	unsigned long flags, offset;  	int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;  	int ret, pipesrc; +	u32 flip_mask;  	work = kzalloc(sizeof *work, GFP_KERNEL);  	if (work == NULL) @@ -4731,16 +4773,33 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,  	atomic_inc(&obj_priv->pending_flip);  	work->pending_flip_obj = obj; +	if (intel_crtc->plane) +		flip_mask = I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT; +	else +		flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT; + +	/* Wait for any previous flip to finish */ +	if (IS_GEN3(dev)) +		while (I915_READ(ISR) & flip_mask) +			; + +	/* Offset into the new buffer for cases of shared fbs between CRTCs */ +	offset = obj_priv->gtt_offset; +	offset += (crtc->y * fb->pitch) + (crtc->x * (fb->bits_per_pixel) / 8); +  	BEGIN_LP_RING(4); -	OUT_RING(MI_DISPLAY_FLIP | -		 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); -	OUT_RING(fb->pitch);  	if (IS_I965G(dev)) { -		OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); +		OUT_RING(MI_DISPLAY_FLIP | +			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); +		OUT_RING(fb->pitch); +		OUT_RING(offset | obj_priv->tiling_mode);  		pipesrc = I915_READ(pipesrc_reg);   		OUT_RING(pipesrc & 0x0fff0fff);  	} else { -		OUT_RING(obj_priv->gtt_offset); +		OUT_RING(MI_DISPLAY_FLIP_I915 | +			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); +		OUT_RING(fb->pitch); +		OUT_RING(offset);  		OUT_RING(MI_NOOP);  	}  	ADVANCE_LP_RING(); @@ -5472,6 +5531,66 @@ static void intel_init_display(struct drm_device *dev)  	}  } +/* + * Some BIOSes insist on assuming the GPU's pipe A is enabled at suspend, + * resume, or other times.  This quirk makes sure that's the case for + * affected systems. + */ +static void quirk_pipea_force (struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; + +	dev_priv->quirks |= QUIRK_PIPEA_FORCE; +	DRM_DEBUG_DRIVER("applying pipe a force quirk\n"); +} + +struct intel_quirk { +	int device; +	int subsystem_vendor; +	int subsystem_device; +	void (*hook)(struct drm_device *dev); +}; + +struct intel_quirk intel_quirks[] = { +	/* HP Compaq 2730p needs pipe A force quirk (LP: #291555) */ +	{ 0x2a42, 0x103c, 0x30eb, quirk_pipea_force }, +	/* HP Mini needs pipe A force quirk (LP: #322104) */ +	{ 0x27ae,0x103c, 0x361a, quirk_pipea_force }, + +	/* Thinkpad R31 needs pipe A force quirk */ +	{ 0x3577, 0x1014, 0x0505, quirk_pipea_force }, +	/* Toshiba Protege R-205, S-209 needs pipe A force quirk */ +	{ 0x2592, 0x1179, 0x0001, quirk_pipea_force }, + +	/* ThinkPad X30 needs pipe A force quirk (LP: #304614) */ +	{ 0x3577,  0x1014, 0x0513, quirk_pipea_force }, +	/* ThinkPad X40 needs pipe A force quirk */ + +	/* ThinkPad T60 needs pipe A force quirk (bug #16494) */ +	{ 0x2782, 0x17aa, 0x201a, quirk_pipea_force }, + +	/* 855 & before need to leave pipe A & dpll A up */ +	{ 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, +	{ 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, +}; + +static void intel_init_quirks(struct drm_device *dev) +{ +	struct pci_dev *d = dev->pdev; +	int i; + +	for (i = 0; i < ARRAY_SIZE(intel_quirks); i++) { +		struct intel_quirk *q = &intel_quirks[i]; + +		if (d->device == q->device && +		    (d->subsystem_vendor == q->subsystem_vendor || +		     q->subsystem_vendor == PCI_ANY_ID) && +		    (d->subsystem_device == q->subsystem_device || +		     q->subsystem_device == PCI_ANY_ID)) +			q->hook(dev); +	} +} +  void intel_modeset_init(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -5484,6 +5603,8 @@ void intel_modeset_init(struct drm_device *dev)  	dev->mode_config.funcs = (void *)&intel_mode_funcs; +	intel_init_quirks(dev); +  	intel_init_display(dev);  	if (IS_I965G(dev)) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 49b54f05d3c..5dde80f9e65 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -136,6 +136,12 @@ intel_dp_link_required(struct drm_device *dev,  }  static int +intel_dp_max_data_rate(int max_link_clock, int max_lanes) +{ +	return (max_link_clock * max_lanes * 8) / 10; +} + +static int  intel_dp_mode_valid(struct drm_connector *connector,  		    struct drm_display_mode *mode)  { @@ -144,8 +150,11 @@ intel_dp_mode_valid(struct drm_connector *connector,  	int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_encoder));  	int max_lanes = intel_dp_max_lane_count(intel_encoder); -	if (intel_dp_link_required(connector->dev, intel_encoder, mode->clock) -			> max_link_clock * max_lanes) +	/* only refuse the mode on non eDP since we have seen some wierd eDP panels +	   which are outside spec tolerances but somehow work by magic */ +	if (!IS_eDP(intel_encoder) && +	    (intel_dp_link_required(connector->dev, intel_encoder, mode->clock) +	     > intel_dp_max_data_rate(max_link_clock, max_lanes)))  		return MODE_CLOCK_HIGH;  	if (mode->clock < 10000) @@ -506,7 +515,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,  	for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {  		for (clock = 0; clock <= max_clock; clock++) { -			int link_avail = intel_dp_link_clock(bws[clock]) * lane_count; +			int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);  			if (intel_dp_link_required(encoder->dev, intel_encoder, mode->clock)  					<= link_avail) { @@ -521,6 +530,18 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,  			}  		}  	} + +	if (IS_eDP(intel_encoder)) { +		/* okay we failed just pick the highest */ +		dp_priv->lane_count = max_lane_count; +		dp_priv->link_bw = bws[max_clock]; +		adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); +		DRM_DEBUG_KMS("Force picking display port link bw %02x lane " +			      "count %d clock %d\n", +			      dp_priv->link_bw, dp_priv->lane_count, +			      adjusted_mode->clock); +		return true; +	}  	return false;  } @@ -696,6 +717,51 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,  	}  } +static void ironlake_edp_panel_on (struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	unsigned long timeout = jiffies + msecs_to_jiffies(5000); +	u32 pp, pp_status; + +	pp_status = I915_READ(PCH_PP_STATUS); +	if (pp_status & PP_ON) +		return; + +	pp = I915_READ(PCH_PP_CONTROL); +	pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON; +	I915_WRITE(PCH_PP_CONTROL, pp); +	do { +		pp_status = I915_READ(PCH_PP_STATUS); +	} while (((pp_status & PP_ON) == 0) && !time_after(jiffies, timeout)); + +	if (time_after(jiffies, timeout)) +		DRM_DEBUG_KMS("panel on wait timed out: 0x%08x\n", pp_status); + +	pp &= ~(PANEL_UNLOCK_REGS | EDP_FORCE_VDD); +	I915_WRITE(PCH_PP_CONTROL, pp); +} + +static void ironlake_edp_panel_off (struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	unsigned long timeout = jiffies + msecs_to_jiffies(5000); +	u32 pp, pp_status; + +	pp = I915_READ(PCH_PP_CONTROL); +	pp &= ~POWER_TARGET_ON; +	I915_WRITE(PCH_PP_CONTROL, pp); +	do { +		pp_status = I915_READ(PCH_PP_STATUS); +	} while ((pp_status & PP_ON) && !time_after(jiffies, timeout)); + +	if (time_after(jiffies, timeout)) +		DRM_DEBUG_KMS("panel off wait timed out\n"); + +	/* Make sure VDD is enabled so DP AUX will work */ +	pp |= EDP_FORCE_VDD; +	I915_WRITE(PCH_PP_CONTROL, pp); +} +  static void ironlake_edp_backlight_on (struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -730,14 +796,18 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)  	if (mode != DRM_MODE_DPMS_ON) {  		if (dp_reg & DP_PORT_EN) {  			intel_dp_link_down(intel_encoder, dp_priv->DP); -			if (IS_eDP(intel_encoder)) +			if (IS_eDP(intel_encoder)) {  				ironlake_edp_backlight_off(dev); +				ironlake_edp_panel_off(dev); +			}  		}  	} else {  		if (!(dp_reg & DP_PORT_EN)) {  			intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration); -			if (IS_eDP(intel_encoder)) +			if (IS_eDP(intel_encoder)) { +				ironlake_edp_panel_on(dev);  				ironlake_edp_backlight_on(dev); +			}  		}  	}  	dp_priv->dpms_mode = mode; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index df931f78766..2f7970be905 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -215,6 +215,9 @@ extern void intel_init_clock_gating(struct drm_device *dev);  extern void ironlake_enable_drps(struct drm_device *dev);  extern void ironlake_disable_drps(struct drm_device *dev); +extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, +				      struct drm_gem_object *obj); +  extern int intel_framebuffer_init(struct drm_device *dev,  				  struct intel_framebuffer *ifb,  				  struct drm_mode_fb_cmd *mode_cmd, @@ -224,6 +227,7 @@ extern void intel_fbdev_fini(struct drm_device *dev);  extern void intel_prepare_page_flip(struct drm_device *dev, int plane);  extern void intel_finish_page_flip(struct drm_device *dev, int pipe); +extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);  extern void intel_setup_overlay(struct drm_device *dev);  extern void intel_cleanup_overlay(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index c3c505244e0..3e18c9e7729 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -98,7 +98,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,  	mutex_lock(&dev->struct_mutex); -	ret = i915_gem_object_pin(fbo, 64*1024); +	ret = intel_pin_and_fence_fb_obj(dev, fbo);  	if (ret) {  		DRM_ERROR("failed to pin fb: %d\n", ret);  		goto out_unref; @@ -236,7 +236,7 @@ int intel_fbdev_destroy(struct drm_device *dev,  	drm_framebuffer_cleanup(&ifb->base);  	if (ifb->obj) -		drm_gem_object_unreference_unlocked(ifb->obj); +		drm_gem_object_unreference(ifb->obj);  	return 0;  } diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 6a1accd83ae..0eab8df5bf7 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -599,6 +599,26 @@ static int intel_lvds_get_modes(struct drm_connector *connector)  	return 0;  } +static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id) +{ +	DRM_DEBUG_KMS("Skipping forced modeset for %s\n", id->ident); +	return 1; +} + +/* The GPU hangs up on these systems if modeset is performed on LID open */ +static const struct dmi_system_id intel_no_modeset_on_lid[] = { +	{ +		.callback = intel_no_modeset_on_lid_dmi_callback, +		.ident = "Toshiba Tecra A11", +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), +			DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A11"), +		}, +	}, + +	{ }	/* terminating entry */ +}; +  /*   * Lid events. Note the use of 'modeset_on_lid':   *  - we set it on lid close, and reset it on open @@ -622,6 +642,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,  	 */  	if (connector)  		connector->status = connector->funcs->detect(connector); +	/* Don't force modeset on machines where it causes a GPU lockup */ +	if (dmi_check_system(intel_no_modeset_on_lid)) +		return NOTIFY_OK;  	if (!acpi_lid_open()) {  		dev_priv->modeset_on_lid = 1;  		return NOTIFY_OK; @@ -983,8 +1006,8 @@ void intel_lvds_init(struct drm_device *dev)  	drm_connector_attach_property(&intel_connector->base,  				      dev->mode_config.scaling_mode_property, -				      DRM_MODE_SCALE_FULLSCREEN); -	lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN; +				      DRM_MODE_SCALE_ASPECT); +	lvds_priv->fitting_mode = DRM_MODE_SCALE_ASPECT;  	/*  	 * LVDS discovery:  	 * 1) check for EDID on DDC diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index cea4f1a8709..26362f8495a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -94,7 +94,7 @@ render_ring_flush(struct drm_device *dev,  #if WATCH_EXEC  		DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);  #endif -		intel_ring_begin(dev, ring, 8); +		intel_ring_begin(dev, ring, 2);  		intel_ring_emit(dev, ring, cmd);  		intel_ring_emit(dev, ring, MI_NOOP);  		intel_ring_advance(dev, ring); @@ -358,7 +358,7 @@ bsd_ring_flush(struct drm_device *dev,  		u32     invalidate_domains,  		u32     flush_domains)  { -	intel_ring_begin(dev, ring, 8); +	intel_ring_begin(dev, ring, 2);  	intel_ring_emit(dev, ring, MI_FLUSH);  	intel_ring_emit(dev, ring, MI_NOOP);  	intel_ring_advance(dev, ring); @@ -687,6 +687,7 @@ int intel_wrap_ring_buffer(struct drm_device *dev,  		*virt++ = MI_NOOP;  	ring->tail = 0; +	ring->space = ring->head - 8;  	return 0;  } @@ -721,8 +722,9 @@ int intel_wait_ring_buffer(struct drm_device *dev,  }  void intel_ring_begin(struct drm_device *dev, -		struct intel_ring_buffer *ring, int n) +		struct intel_ring_buffer *ring, int num_dwords)  { +	int n = 4*num_dwords;  	if (unlikely(ring->tail + n > ring->size))  		intel_wrap_ring_buffer(dev, ring);  	if (unlikely(ring->space < n)) @@ -752,7 +754,7 @@ void intel_fill_struct(struct drm_device *dev,  {  	unsigned int *virt = ring->virtual_start + ring->tail;  	BUG_ON((len&~(4-1)) != 0); -	intel_ring_begin(dev, ring, len); +	intel_ring_begin(dev, ring, len/4);  	memcpy(virt, data, len);  	ring->tail += len;  	ring->tail &= ring->size - 1; diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index fc924b64919..e492919faf4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -203,36 +203,26 @@ struct methods {  	const bool rw;  }; -static struct methods nv04_methods[] = { -	{ "PROM", load_vbios_prom, false }, -	{ "PRAMIN", load_vbios_pramin, true }, -	{ "PCIROM", load_vbios_pci, true }, -}; - -static struct methods nv50_methods[] = { -	{ "ACPI", load_vbios_acpi, true }, +static struct methods shadow_methods[] = {  	{ "PRAMIN", load_vbios_pramin, true },  	{ "PROM", load_vbios_prom, false },  	{ "PCIROM", load_vbios_pci, true }, +	{ "ACPI", load_vbios_acpi, true },  }; -#define METHODCNT 3 -  static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data)  { -	struct drm_nouveau_private *dev_priv = dev->dev_private; -	struct methods *methods; -	int i; +	const int nr_methods = ARRAY_SIZE(shadow_methods); +	struct methods *methods = shadow_methods;  	int testscore = 3; -	int scores[METHODCNT]; +	int scores[nr_methods], i;  	if (nouveau_vbios) { -		methods = nv04_methods; -		for (i = 0; i < METHODCNT; i++) +		for (i = 0; i < nr_methods; i++)  			if (!strcasecmp(nouveau_vbios, methods[i].desc))  				break; -		if (i < METHODCNT) { +		if (i < nr_methods) {  			NV_INFO(dev, "Attempting to use BIOS image from %s\n",  				methods[i].desc); @@ -244,12 +234,7 @@ static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data)  		NV_ERROR(dev, "VBIOS source \'%s\' invalid\n", nouveau_vbios);  	} -	if (dev_priv->card_type < NV_50) -		methods = nv04_methods; -	else -		methods = nv50_methods; - -	for (i = 0; i < METHODCNT; i++) { +	for (i = 0; i < nr_methods; i++) {  		NV_TRACE(dev, "Attempting to load BIOS image from %s\n",  			 methods[i].desc);  		data[0] = data[1] = 0;	/* avoid reuse of previous image */ @@ -260,7 +245,7 @@ static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data)  	}  	while (--testscore > 0) { -		for (i = 0; i < METHODCNT; i++) { +		for (i = 0; i < nr_methods; i++) {  			if (scores[i] == testscore) {  				NV_TRACE(dev, "Using BIOS image from %s\n",  					 methods[i].desc); diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index c9a4a0d2a11..257ea130ae1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -387,7 +387,8 @@ int nouveau_fbcon_init(struct drm_device *dev)  	dev_priv->nfbdev = nfbdev;  	nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; -	ret = drm_fb_helper_init(dev, &nfbdev->helper, 2, 4); +	ret = drm_fb_helper_init(dev, &nfbdev->helper, +				 nv_two_heads(dev) ? 2 : 1, 4);  	if (ret) {  		kfree(nfbdev);  		return ret; diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index f3f2827017e..8c2d6478a22 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -498,7 +498,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,  		if ((rdev->family == CHIP_RS600) ||  		    (rdev->family == CHIP_RS690) ||  		    (rdev->family == CHIP_RS740)) -			pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV | +			pll->flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/  				       RADEON_PLL_PREFER_CLOSEST_LOWER);  		if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)	/* range limits??? */ diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 4b6623df3b9..1caf625e472 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -607,7 +607,7 @@ static void evergreen_mc_program(struct radeon_device *rdev)  	WREG32(MC_VM_FB_LOCATION, tmp);  	WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));  	WREG32(HDP_NONSURFACE_INFO, (2 << 7)); -	WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF); +	WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);  	if (rdev->flags & RADEON_IS_AGP) {  		WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);  		WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16); @@ -1222,11 +1222,11 @@ static void evergreen_gpu_init(struct radeon_device *rdev)  		ps_thread_count = 128;  	sq_thread_resource_mgmt = NUM_PS_THREADS(ps_thread_count); -	sq_thread_resource_mgmt |= NUM_VS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8; -	sq_thread_resource_mgmt |= NUM_GS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8; -	sq_thread_resource_mgmt |= NUM_ES_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8; -	sq_thread_resource_mgmt_2 = NUM_HS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8; -	sq_thread_resource_mgmt_2 |= NUM_LS_THREADS(((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8; +	sq_thread_resource_mgmt |= NUM_VS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); +	sq_thread_resource_mgmt |= NUM_GS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); +	sq_thread_resource_mgmt |= NUM_ES_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); +	sq_thread_resource_mgmt_2 = NUM_HS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); +	sq_thread_resource_mgmt_2 |= NUM_LS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8);  	sq_stack_resource_mgmt_1 = NUM_PS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6);  	sq_stack_resource_mgmt_1 |= NUM_VS_STACK_ENTRIES((rdev->config.evergreen.max_stack_entries * 1) / 6); @@ -1260,6 +1260,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev)  	WREG32(VGT_GS_VERTEX_REUSE, 16);  	WREG32(PA_SC_LINE_STIPPLE_STATE, 0); +	WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, 14); +	WREG32(VGT_OUT_DEALLOC_CNTL, 16); +  	WREG32(CB_PERF_CTR0_SEL_0, 0);  	WREG32(CB_PERF_CTR0_SEL_1, 0);  	WREG32(CB_PERF_CTR1_SEL_0, 0); @@ -1269,6 +1272,26 @@ static void evergreen_gpu_init(struct radeon_device *rdev)  	WREG32(CB_PERF_CTR3_SEL_0, 0);  	WREG32(CB_PERF_CTR3_SEL_1, 0); +	/* clear render buffer base addresses */ +	WREG32(CB_COLOR0_BASE, 0); +	WREG32(CB_COLOR1_BASE, 0); +	WREG32(CB_COLOR2_BASE, 0); +	WREG32(CB_COLOR3_BASE, 0); +	WREG32(CB_COLOR4_BASE, 0); +	WREG32(CB_COLOR5_BASE, 0); +	WREG32(CB_COLOR6_BASE, 0); +	WREG32(CB_COLOR7_BASE, 0); +	WREG32(CB_COLOR8_BASE, 0); +	WREG32(CB_COLOR9_BASE, 0); +	WREG32(CB_COLOR10_BASE, 0); +	WREG32(CB_COLOR11_BASE, 0); + +	/* set the shader const cache sizes to 0 */ +	for (i = SQ_ALU_CONST_BUFFER_SIZE_PS_0; i < 0x28200; i += 4) +		WREG32(i, 0); +	for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4) +		WREG32(i, 0); +  	hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);  	WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 64516b95089..345a75a03c9 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -333,7 +333,6 @@ static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)  	header = radeon_get_ib_value(p, h_idx);  	crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);  	reg = CP_PACKET0_GET_REG(header); -	mutex_lock(&p->rdev->ddev->mode_config.mutex);  	obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);  	if (!obj) {  		DRM_ERROR("cannot find crtc %d\n", crtc_id); @@ -368,7 +367,6 @@ static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)  		}  	}  out: -	mutex_unlock(&p->rdev->ddev->mode_config.mutex);  	return r;  } @@ -1197,7 +1195,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,  					DRM_ERROR("bad SET_RESOURCE (tex)\n");  					return -EINVAL;  				} -				ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); +				ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);  				if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)  					ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);  				else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) @@ -1209,7 +1207,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,  					DRM_ERROR("bad SET_RESOURCE (tex)\n");  					return -EINVAL;  				} -				ib[idx+1+(i*8)+4] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); +				ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);  				mipmap = reloc->robj;  				r = evergreen_check_texture_resource(p,  idx+1+(i*8),  						texture, mipmap); diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 79683f6b445..a1cd621780e 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -713,6 +713,9 @@  #define SQ_GSVS_RING_OFFSET_2				0x28930  #define SQ_GSVS_RING_OFFSET_3				0x28934 +#define SQ_ALU_CONST_BUFFER_SIZE_PS_0			0x28140 +#define SQ_ALU_CONST_BUFFER_SIZE_HS_0			0x28f80 +  #define SQ_ALU_CONST_CACHE_PS_0				0x28940  #define SQ_ALU_CONST_CACHE_PS_1				0x28944  #define SQ_ALU_CONST_CACHE_PS_2				0x28948 diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index cf89aa2eb28..a89a15ab524 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1230,7 +1230,6 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)  	header = radeon_get_ib_value(p, h_idx);  	crtc_id = radeon_get_ib_value(p, h_idx + 5);  	reg = CP_PACKET0_GET_REG(header); -	mutex_lock(&p->rdev->ddev->mode_config.mutex);  	obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);  	if (!obj) {  		DRM_ERROR("cannot find crtc %d\n", crtc_id); @@ -1264,7 +1263,6 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)  		ib[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1;  	}  out: -	mutex_unlock(&p->rdev->ddev->mode_config.mutex);  	return r;  } @@ -1628,6 +1626,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,  		case RADEON_TXFORMAT_RGB332:  		case RADEON_TXFORMAT_Y8:  			track->textures[i].cpp = 1; +			track->textures[i].compress_format = R100_TRACK_COMP_NONE;  			break;  		case RADEON_TXFORMAT_AI88:  		case RADEON_TXFORMAT_ARGB1555: @@ -1639,12 +1638,14 @@ static int r100_packet0_check(struct radeon_cs_parser *p,  		case RADEON_TXFORMAT_LDUDV655:  		case RADEON_TXFORMAT_DUDV88:  			track->textures[i].cpp = 2; +			track->textures[i].compress_format = R100_TRACK_COMP_NONE;  			break;  		case RADEON_TXFORMAT_ARGB8888:  		case RADEON_TXFORMAT_RGBA8888:  		case RADEON_TXFORMAT_SHADOW32:  		case RADEON_TXFORMAT_LDUDUV8888:  			track->textures[i].cpp = 4; +			track->textures[i].compress_format = R100_TRACK_COMP_NONE;  			break;  		case RADEON_TXFORMAT_DXT1:  			track->textures[i].cpp = 1; @@ -2351,6 +2352,7 @@ void r100_mc_init(struct radeon_device *rdev)  	if (rdev->flags & RADEON_IS_IGP)  		base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;  	radeon_vram_location(rdev, &rdev->mc, base); +	rdev->mc.gtt_base_align = 0;  	if (!(rdev->flags & RADEON_IS_AGP))  		radeon_gtt_location(rdev, &rdev->mc);  	radeon_update_bandwidth_info(rdev); @@ -2604,12 +2606,6 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,  	int surf_index = reg * 16;  	int flags = 0; -	/* r100/r200 divide by 16 */ -	if (rdev->family < CHIP_R300) -		flags = pitch / 16; -	else -		flags = pitch / 8; -  	if (rdev->family <= CHIP_RS200) {  		if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO))  				 == (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) @@ -2633,6 +2629,20 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,  	if (tiling_flags & RADEON_TILING_SWAP_32BIT)  		flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; +	/* when we aren't tiling the pitch seems to needs to be furtherdivided down. - tested on power5 + rn50 server */ +	if (tiling_flags & (RADEON_TILING_SWAP_16BIT | RADEON_TILING_SWAP_32BIT)) { +		if (!(tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) +			if (ASIC_IS_RN50(rdev)) +				pitch /= 16; +	} + +	/* r100/r200 divide by 16 */ +	if (rdev->family < CHIP_R300) +		flags |= pitch / 16; +	else +		flags |= pitch / 8; + +  	DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1);  	WREG32(RADEON_SURFACE0_INFO + surf_index, flags);  	WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset); @@ -3147,33 +3157,6 @@ static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t)  	DRM_ERROR("compress format            %d\n", t->compress_format);  } -static int r100_cs_track_cube(struct radeon_device *rdev, -			      struct r100_cs_track *track, unsigned idx) -{ -	unsigned face, w, h; -	struct radeon_bo *cube_robj; -	unsigned long size; - -	for (face = 0; face < 5; face++) { -		cube_robj = track->textures[idx].cube_info[face].robj; -		w = track->textures[idx].cube_info[face].width; -		h = track->textures[idx].cube_info[face].height; - -		size = w * h; -		size *= track->textures[idx].cpp; - -		size += track->textures[idx].cube_info[face].offset; - -		if (size > radeon_bo_size(cube_robj)) { -			DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", -				  size, radeon_bo_size(cube_robj)); -			r100_cs_track_texture_print(&track->textures[idx]); -			return -1; -		} -	} -	return 0; -} -  static int r100_track_compress_size(int compress_format, int w, int h)  {  	int block_width, block_height, block_bytes; @@ -3204,6 +3187,37 @@ static int r100_track_compress_size(int compress_format, int w, int h)  	return sz;  } +static int r100_cs_track_cube(struct radeon_device *rdev, +			      struct r100_cs_track *track, unsigned idx) +{ +	unsigned face, w, h; +	struct radeon_bo *cube_robj; +	unsigned long size; +	unsigned compress_format = track->textures[idx].compress_format; + +	for (face = 0; face < 5; face++) { +		cube_robj = track->textures[idx].cube_info[face].robj; +		w = track->textures[idx].cube_info[face].width; +		h = track->textures[idx].cube_info[face].height; + +		if (compress_format) { +			size = r100_track_compress_size(compress_format, w, h); +		} else +			size = w * h; +		size *= track->textures[idx].cpp; + +		size += track->textures[idx].cube_info[face].offset; + +		if (size > radeon_bo_size(cube_robj)) { +			DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", +				  size, radeon_bo_size(cube_robj)); +			r100_cs_track_texture_print(&track->textures[idx]); +			return -1; +		} +	} +	return 0; +} +  static int r100_cs_track_texture_check(struct radeon_device *rdev,  				       struct r100_cs_track *track)  { diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c index 85617c31121..0266d72e0a4 100644 --- a/drivers/gpu/drm/radeon/r200.c +++ b/drivers/gpu/drm/radeon/r200.c @@ -415,6 +415,8 @@ int r200_packet0_check(struct radeon_cs_parser *p,  		/* 2D, 3D, CUBE */  		switch (tmp) {  		case 0: +		case 3: +		case 4:  		case 5:  		case 6:  		case 7: @@ -450,6 +452,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,  		case R200_TXFORMAT_RGB332:  		case R200_TXFORMAT_Y8:  			track->textures[i].cpp = 1; +			track->textures[i].compress_format = R100_TRACK_COMP_NONE;  			break;  		case R200_TXFORMAT_AI88:  		case R200_TXFORMAT_ARGB1555: @@ -461,6 +464,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,  		case R200_TXFORMAT_DVDU88:  		case R200_TXFORMAT_AVYU4444:  			track->textures[i].cpp = 2; +			track->textures[i].compress_format = R100_TRACK_COMP_NONE;  			break;  		case R200_TXFORMAT_ARGB8888:  		case R200_TXFORMAT_RGBA8888: @@ -468,6 +472,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,  		case R200_TXFORMAT_BGR111110:  		case R200_TXFORMAT_LDVDU8888:  			track->textures[i].cpp = 4; +			track->textures[i].compress_format = R100_TRACK_COMP_NONE;  			break;  		case R200_TXFORMAT_DXT1:  			track->textures[i].cpp = 1; diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index b2f9efe2897..19a7ef7ee34 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -481,6 +481,7 @@ void r300_mc_init(struct radeon_device *rdev)  	if (rdev->flags & RADEON_IS_IGP)  		base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;  	radeon_vram_location(rdev, &rdev->mc, base); +	rdev->mc.gtt_base_align = 0;  	if (!(rdev->flags & RADEON_IS_AGP))  		radeon_gtt_location(rdev, &rdev->mc);  	radeon_update_bandwidth_info(rdev); @@ -881,6 +882,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,  		case R300_TX_FORMAT_Y4X4:  		case R300_TX_FORMAT_Z3Y3X2:  			track->textures[i].cpp = 1; +			track->textures[i].compress_format = R100_TRACK_COMP_NONE;  			break;  		case R300_TX_FORMAT_X16:  		case R300_TX_FORMAT_Y8X8: @@ -892,6 +894,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,  		case R300_TX_FORMAT_B8G8_B8G8:  		case R300_TX_FORMAT_G8R8_G8B8:  			track->textures[i].cpp = 2; +			track->textures[i].compress_format = R100_TRACK_COMP_NONE;  			break;  		case R300_TX_FORMAT_Y16X16:  		case R300_TX_FORMAT_Z11Y11X10: @@ -902,14 +905,17 @@ static int r300_packet0_check(struct radeon_cs_parser *p,  		case R300_TX_FORMAT_FL_I32:  		case 0x1e:  			track->textures[i].cpp = 4; +			track->textures[i].compress_format = R100_TRACK_COMP_NONE;  			break;  		case R300_TX_FORMAT_W16Z16Y16X16:  		case R300_TX_FORMAT_FL_R16G16B16A16:  		case R300_TX_FORMAT_FL_I32A32:  			track->textures[i].cpp = 8; +			track->textures[i].compress_format = R100_TRACK_COMP_NONE;  			break;  		case R300_TX_FORMAT_FL_R32G32B32A32:  			track->textures[i].cpp = 16; +			track->textures[i].compress_format = R100_TRACK_COMP_NONE;  			break;  		case R300_TX_FORMAT_DXT1:  			track->textures[i].cpp = 1; @@ -1171,6 +1177,8 @@ int r300_cs_parse(struct radeon_cs_parser *p)  	int r;  	track = kzalloc(sizeof(*track), GFP_KERNEL); +	if (track == NULL) +		return -ENOMEM;  	r100_cs_track_clear(p->rdev, track);  	p->track = track;  	do { diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 34330df2848..694af7cc23a 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -125,6 +125,7 @@ void r520_mc_init(struct radeon_device *rdev)  	r520_vram_get_type(rdev);  	r100_vram_init_sizes(rdev);  	radeon_vram_location(rdev, &rdev->mc, 0); +	rdev->mc.gtt_base_align = 0;  	if (!(rdev->flags & RADEON_IS_AGP))  		radeon_gtt_location(rdev, &rdev->mc);  	radeon_update_bandwidth_info(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 0e91871f45b..e100f69faee 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -130,9 +130,14 @@ void r600_pm_get_dynpm_state(struct radeon_device *rdev)  							break;  						}  					} -				} else -					rdev->pm.requested_power_state_index = -						rdev->pm.current_power_state_index - 1; +				} else { +					if (rdev->pm.current_power_state_index == 0) +						rdev->pm.requested_power_state_index = +							rdev->pm.num_power_states - 1; +					else +						rdev->pm.requested_power_state_index = +							rdev->pm.current_power_state_index - 1; +				}  			}  			rdev->pm.requested_clock_mode_index = 0;  			/* don't use the power state if crtcs are active and no display flag is set */ @@ -1097,7 +1102,7 @@ static void r600_mc_program(struct radeon_device *rdev)  	WREG32(MC_VM_FB_LOCATION, tmp);  	WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));  	WREG32(HDP_NONSURFACE_INFO, (2 << 7)); -	WREG32(HDP_NONSURFACE_SIZE, rdev->mc.mc_vram_size | 0x3FF); +	WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);  	if (rdev->flags & RADEON_IS_AGP) {  		WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22);  		WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22); @@ -1174,6 +1179,7 @@ void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)  		if (rdev->flags & RADEON_IS_IGP)  			base = (RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24;  		radeon_vram_location(rdev, &rdev->mc, base); +		rdev->mc.gtt_base_align = 0;  		radeon_gtt_location(rdev, mc);  	}  } @@ -1219,8 +1225,10 @@ int r600_mc_init(struct radeon_device *rdev)  	rdev->mc.visible_vram_size = rdev->mc.aper_size;  	r600_vram_gtt_location(rdev, &rdev->mc); -	if (rdev->flags & RADEON_IS_IGP) +	if (rdev->flags & RADEON_IS_IGP) { +		rs690_pm_info(rdev);  		rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); +	}  	radeon_update_bandwidth_info(rdev);  	return 0;  } diff --git a/drivers/gpu/drm/radeon/r600_blit.c b/drivers/gpu/drm/radeon/r600_blit.c index f4fb88ece2b..ca5c29f7077 100644 --- a/drivers/gpu/drm/radeon/r600_blit.c +++ b/drivers/gpu/drm/radeon/r600_blit.c @@ -538,9 +538,12 @@ int  r600_prepare_blit_copy(struct drm_device *dev, struct drm_file *file_priv)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; +	int ret;  	DRM_DEBUG("\n"); -	r600_nomm_get_vb(dev); +	ret = r600_nomm_get_vb(dev); +	if (ret) +		return ret;  	dev_priv->blit_vb->file_priv = file_priv; diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index c39c1bc1301..144c32d3713 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -585,7 +585,7 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)  	header = radeon_get_ib_value(p, h_idx);  	crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);  	reg = CP_PACKET0_GET_REG(header); -	mutex_lock(&p->rdev->ddev->mode_config.mutex); +  	obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);  	if (!obj) {  		DRM_ERROR("cannot find crtc %d\n", crtc_id); @@ -620,7 +620,6 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)  		ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2;  	}  out: -	mutex_unlock(&p->rdev->ddev->mode_config.mutex);  	return r;  } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 8e1d44ca26e..2f94dc66c18 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -177,6 +177,7 @@ void radeon_pm_resume(struct radeon_device *rdev);  void radeon_combios_get_power_modes(struct radeon_device *rdev);  void radeon_atombios_get_power_modes(struct radeon_device *rdev);  void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level); +void rs690_pm_info(struct radeon_device *rdev);  /*   * Fences. @@ -350,6 +351,7 @@ struct radeon_mc {  	int			vram_mtrr;  	bool			vram_is_ddr;  	bool			igp_sideport_enabled; +	u64                     gtt_base_align;  };  bool radeon_combios_sideport_present(struct radeon_device *rdev); @@ -619,7 +621,8 @@ enum radeon_dynpm_state {  	DYNPM_STATE_DISABLED,  	DYNPM_STATE_MINIMUM,  	DYNPM_STATE_PAUSED, -	DYNPM_STATE_ACTIVE +	DYNPM_STATE_ACTIVE, +	DYNPM_STATE_SUSPENDED,  };  enum radeon_dynpm_action {  	DYNPM_ACTION_NONE, diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 87f7e2cc52d..646f96f97c7 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -780,6 +780,13 @@ int radeon_asic_init(struct radeon_device *rdev)  	case CHIP_R423:  	case CHIP_RV410:  		rdev->asic = &r420_asic; +		/* handle macs */ +		if (rdev->bios == NULL) { +			rdev->asic->get_engine_clock = &radeon_legacy_get_engine_clock; +			rdev->asic->set_engine_clock = &radeon_legacy_set_engine_clock; +			rdev->asic->get_memory_clock = &radeon_legacy_get_memory_clock; +			rdev->asic->set_memory_clock = NULL; +		}  		break;  	case CHIP_RS400:  	case CHIP_RS480: diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 99bd8a9c56b..10673ae59cf 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -280,6 +280,15 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,  		}  	} +	/* ASUS HD 3600 board lists the DVI port as HDMI */ +	if ((dev->pdev->device == 0x9598) && +	    (dev->pdev->subsystem_vendor == 0x1043) && +	    (dev->pdev->subsystem_device == 0x01e4)) { +		if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) { +			*connector_type = DRM_MODE_CONNECTOR_DVII; +		} +	} +  	/* ASUS HD 3450 board lists the DVI port as HDMI */  	if ((dev->pdev->device == 0x95C5) &&  	    (dev->pdev->subsystem_vendor == 0x1043) && @@ -1029,8 +1038,15 @@ bool radeon_atombios_sideport_present(struct radeon_device *rdev)  				      data_offset);  		switch (crev) {  		case 1: -			if (igp_info->info.ucMemoryType & 0xf0) -				return true; +			/* AMD IGPS */ +			if ((rdev->family == CHIP_RS690) || +			    (rdev->family == CHIP_RS740)) { +				if (igp_info->info.ulBootUpMemoryClock) +					return true; +			} else { +				if (igp_info->info.ucMemoryType & 0xf0) +					return true; +			}  			break;  		case 2:  			if (igp_info->info_2.ucMemoryType & 0x0f) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index fbba938f804..2c921373999 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -48,6 +48,10 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev)  	resource_size_t vram_base;  	resource_size_t size = 256 * 1024; /* ??? */ +	if (!(rdev->flags & RADEON_IS_IGP)) +		if (!radeon_card_posted(rdev)) +			return false; +  	rdev->bios = NULL;  	vram_base = drm_get_resource_start(rdev->ddev, 0);  	bios = ioremap(vram_base, size); diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 1bee2f9e24a..2417d7b06fd 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -1411,6 +1411,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)  			rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT;  		} else  #endif /* CONFIG_PPC_PMAC */ +#ifdef CONFIG_PPC64 +		if (ASIC_IS_RN50(rdev)) +			rdev->mode_info.connector_table = CT_RN50_POWER; +		else +#endif  			rdev->mode_info.connector_table = CT_GENERIC;  	} @@ -1853,6 +1858,33 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)  					    CONNECTOR_OBJECT_ID_SVIDEO,  					    &hpd);  		break; +	case CT_RN50_POWER: +		DRM_INFO("Connector Table: %d (rn50-power)\n", +			 rdev->mode_info.connector_table); +		/* VGA - primary dac */ +		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC); +		hpd.hpd = RADEON_HPD_NONE; +		radeon_add_legacy_encoder(dev, +					  radeon_get_encoder_id(dev, +								ATOM_DEVICE_CRT1_SUPPORT, +								1), +					  ATOM_DEVICE_CRT1_SUPPORT); +		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT, +					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c, +					    CONNECTOR_OBJECT_ID_VGA, +					    &hpd); +		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); +		hpd.hpd = RADEON_HPD_NONE; +		radeon_add_legacy_encoder(dev, +					  radeon_get_encoder_id(dev, +								ATOM_DEVICE_CRT2_SUPPORT, +								2), +					  ATOM_DEVICE_CRT2_SUPPORT); +		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT, +					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c, +					    CONNECTOR_OBJECT_ID_VGA, +					    &hpd); +		break;  	default:  		DRM_INFO("Connector table: %d (invalid)\n",  			 rdev->mode_info.connector_table); @@ -1906,15 +1938,6 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev,  			return false;  	} -	/* Some RV100 cards with 2 VGA ports show up with DVI+VGA */ -	if (dev->pdev->device == 0x5159 && -	    dev->pdev->subsystem_vendor == 0x1002 && -	    dev->pdev->subsystem_device == 0x013a) { -		if (*legacy_connector == CONNECTOR_DVI_I_LEGACY) -			*legacy_connector = CONNECTOR_CRT_LEGACY; - -	} -  	/* X300 card with extra non-existent DVI port */  	if (dev->pdev->device == 0x5B60 &&  	    dev->pdev->subsystem_vendor == 0x17af && @@ -3019,6 +3042,22 @@ void radeon_combios_asic_init(struct drm_device *dev)  		combios_write_ram_size(dev);  	} +	/* quirk for rs4xx HP nx6125 laptop to make it resume +	 * - it hangs on resume inside the dynclk 1 table. +	 */ +	if (rdev->family == CHIP_RS480 && +	    rdev->pdev->subsystem_vendor == 0x103c && +	    rdev->pdev->subsystem_device == 0x308b) +		return; + +	/* quirk for rs4xx HP dv5000 laptop to make it resume +	 * - it hangs on resume inside the dynclk 1 table. +	 */ +	if (rdev->family == CHIP_RS480 && +	    rdev->pdev->subsystem_vendor == 0x103c && +	    rdev->pdev->subsystem_device == 0x30a4) +		return; +  	/* DYN CLK 1 */  	table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);  	if (table) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 0c7ccc6961a..adccbc2c202 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -771,30 +771,27 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect  			} else  				ret = connector_status_connected; -			/* multiple connectors on the same encoder with the same ddc line -			 * This tends to be HDMI and DVI on the same encoder with the -			 * same ddc line.  If the edid says HDMI, consider the HDMI port -			 * connected and the DVI port disconnected.  If the edid doesn't -			 * say HDMI, vice versa. +			/* This gets complicated.  We have boards with VGA + HDMI with a +			 * shared DDC line and we have boards with DVI-D + HDMI with a shared +			 * DDC line.  The latter is more complex because with DVI<->HDMI adapters +			 * you don't really know what's connected to which port as both are digital.  			 */  			if (radeon_connector->shared_ddc && (ret == connector_status_connected)) {  				struct drm_device *dev = connector->dev; +				struct radeon_device *rdev = dev->dev_private;  				struct drm_connector *list_connector;  				struct radeon_connector *list_radeon_connector;  				list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {  					if (connector == list_connector)  						continue;  					list_radeon_connector = to_radeon_connector(list_connector); -					if (radeon_connector->devices == list_radeon_connector->devices) { -						if (drm_detect_hdmi_monitor(radeon_connector->edid)) { -							if (connector->connector_type == DRM_MODE_CONNECTOR_DVID) { -								kfree(radeon_connector->edid); -								radeon_connector->edid = NULL; -								ret = connector_status_disconnected; -							} -						} else { -							if ((connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) || -							    (connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)) { +					if (list_radeon_connector->shared_ddc && +					    (list_radeon_connector->ddc_bus->rec.i2c_id == +					     radeon_connector->ddc_bus->rec.i2c_id)) { +						/* cases where both connectors are digital */ +						if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) { +							/* hpd is our only option in this case */ +							if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {  								kfree(radeon_connector->edid);  								radeon_connector->edid = NULL;  								ret = connector_status_disconnected; diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index b7023fff89e..4eb67c0e099 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -194,7 +194,7 @@ unpin:  fail:  	drm_gem_object_unreference_unlocked(obj); -	return 0; +	return ret;  }  int radeon_crtc_cursor_move(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index f10faed2156..dd279da9054 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -226,20 +226,20 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)  {  	u64 size_af, size_bf; -	size_af = 0xFFFFFFFF - mc->vram_end; -	size_bf = mc->vram_start; +	size_af = ((0xFFFFFFFF - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align; +	size_bf = mc->vram_start & ~mc->gtt_base_align;  	if (size_bf > size_af) {  		if (mc->gtt_size > size_bf) {  			dev_warn(rdev->dev, "limiting GTT\n");  			mc->gtt_size = size_bf;  		} -		mc->gtt_start = mc->vram_start - mc->gtt_size; +		mc->gtt_start = (mc->vram_start & ~mc->gtt_base_align) - mc->gtt_size;  	} else {  		if (mc->gtt_size > size_af) {  			dev_warn(rdev->dev, "limiting GTT\n");  			mc->gtt_size = size_af;  		} -		mc->gtt_start = mc->vram_end + 1; +		mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align;  	}  	mc->gtt_end = mc->gtt_start + mc->gtt_size - 1;  	dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n", @@ -779,6 +779,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)  int radeon_resume_kms(struct drm_device *dev)  { +	struct drm_connector *connector;  	struct radeon_device *rdev = dev->dev_private;  	if (rdev->powered_down) @@ -797,6 +798,12 @@ int radeon_resume_kms(struct drm_device *dev)  	radeon_resume(rdev);  	radeon_pm_resume(rdev);  	radeon_restore_bios_scratch_regs(rdev); + +	/* turn on display hw */ +	list_for_each_entry(connector, &dev->mode_config.connector_list, head) { +		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); +	} +  	radeon_fbdev_set_suspend(rdev, 0);  	release_console_sem(); diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 1ebb100015b..e0b30b264c2 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1072,6 +1072,8 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)  	if (is_dig) {  		switch (mode) {  		case DRM_MODE_DPMS_ON: +			if (!ASIC_IS_DCE4(rdev)) +				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);  			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {  				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); @@ -1079,8 +1081,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)  				if (ASIC_IS_DCE4(rdev))  					atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON);  			} -			if (!ASIC_IS_DCE4(rdev)) -				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);  			break;  		case DRM_MODE_DPMS_STANDBY:  		case DRM_MODE_DPMS_SUSPEND: diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 6a70c0dc7f9..ab389f89fa8 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -128,7 +128,8 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)  		for (i = 0, found = 0; i < rdev->num_crtc; i++) {  			crtc = (struct drm_crtc *)minfo->crtcs[i];  			if (crtc && crtc->base.id == value) { -				value = i; +				struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); +				value = radeon_crtc->crtc_id;  				found = 1;  				break;  			} diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 5b07b8848e0..5688a0cf6bb 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -108,6 +108,7 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)  		udelay(panel_pwr_delay * 1000);  		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);  		WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); +		udelay(panel_pwr_delay * 1000);  		break;  	} @@ -928,16 +929,14 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,  	if (ASIC_IS_R300(rdev)) {  		gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;  		disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); -	} - -	if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) -		disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL); -	else +	} else if (rdev->family != CHIP_R200)  		disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); - -	if (rdev->family == CHIP_R200) +	else if (rdev->family == CHIP_R200)  		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); +	if (rdev->family >= CHIP_R200) +		disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL); +  	if (is_tv) {  		uint32_t dac_cntl; @@ -1002,15 +1001,13 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,  	if (ASIC_IS_R300(rdev)) {  		WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);  		WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); -	} +	} else if (rdev->family != CHIP_R200) +		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); +	else if (rdev->family == CHIP_R200) +		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);  	if (rdev->family >= CHIP_R200)  		WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl); -	else -		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); - -	if (rdev->family == CHIP_R200) -		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);  	if (is_tv)  		radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode); diff --git a/drivers/gpu/drm/radeon/radeon_legacy_tv.c b/drivers/gpu/drm/radeon/radeon_legacy_tv.c index f2ed27c8055..03204039774 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_tv.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_tv.c @@ -642,8 +642,8 @@ void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,  	}  	flicker_removal = (tmp + 500) / 1000; -	if (flicker_removal < 2) -		flicker_removal = 2; +	if (flicker_removal < 3) +		flicker_removal = 3;  	for (i = 0; i < ARRAY_SIZE(SLOPE_limit); ++i) {  		if (flicker_removal == SLOPE_limit[i])  			break; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 67358baf28b..95696aa57ac 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -206,6 +206,7 @@ enum radeon_connector_table {  	CT_MINI_INTERNAL,  	CT_IMAC_G5_ISIGHT,  	CT_EMAC, +	CT_RN50_POWER,  };  enum radeon_dvo_chip { diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 63f679a04b2..3fa6984d989 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -333,6 +333,7 @@ static ssize_t radeon_get_pm_profile(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "%s\n",  			(cp == PM_PROFILE_AUTO) ? "auto" :  			(cp == PM_PROFILE_LOW) ? "low" : +			(cp == PM_PROFILE_MID) ? "mid" :  			(cp == PM_PROFILE_HIGH) ? "high" : "default");  } @@ -397,13 +398,20 @@ static ssize_t radeon_set_pm_method(struct device *dev,  		rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;  		mutex_unlock(&rdev->pm.mutex);  	} else if (strncmp("profile", buf, strlen("profile")) == 0) { +		bool flush_wq = false; +  		mutex_lock(&rdev->pm.mutex); -		rdev->pm.pm_method = PM_METHOD_PROFILE; +		if (rdev->pm.pm_method == PM_METHOD_DYNPM) { +			cancel_delayed_work(&rdev->pm.dynpm_idle_work); +			flush_wq = true; +		}  		/* disable dynpm */  		rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;  		rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; -		cancel_delayed_work(&rdev->pm.dynpm_idle_work); +		rdev->pm.pm_method = PM_METHOD_PROFILE;  		mutex_unlock(&rdev->pm.mutex); +		if (flush_wq) +			flush_workqueue(rdev->wq);  	} else {  		DRM_ERROR("invalid power method!\n");  		goto fail; @@ -418,9 +426,18 @@ static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon  void radeon_pm_suspend(struct radeon_device *rdev)  { +	bool flush_wq = false; +  	mutex_lock(&rdev->pm.mutex); -	cancel_delayed_work(&rdev->pm.dynpm_idle_work); +	if (rdev->pm.pm_method == PM_METHOD_DYNPM) { +		cancel_delayed_work(&rdev->pm.dynpm_idle_work); +		if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) +			rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED; +		flush_wq = true; +	}  	mutex_unlock(&rdev->pm.mutex); +	if (flush_wq) +		flush_workqueue(rdev->wq);  }  void radeon_pm_resume(struct radeon_device *rdev) @@ -432,6 +449,12 @@ void radeon_pm_resume(struct radeon_device *rdev)  	rdev->pm.current_sclk = rdev->clock.default_sclk;  	rdev->pm.current_mclk = rdev->clock.default_mclk;  	rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; +	if (rdev->pm.pm_method == PM_METHOD_DYNPM +	    && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) { +		rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; +		queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, +					msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); +	}  	mutex_unlock(&rdev->pm.mutex);  	radeon_pm_compute_clocks(rdev);  } @@ -486,6 +509,8 @@ int radeon_pm_init(struct radeon_device *rdev)  void radeon_pm_fini(struct radeon_device *rdev)  {  	if (rdev->pm.num_power_states > 1) { +		bool flush_wq = false; +  		mutex_lock(&rdev->pm.mutex);  		if (rdev->pm.pm_method == PM_METHOD_PROFILE) {  			rdev->pm.profile = PM_PROFILE_DEFAULT; @@ -493,13 +518,16 @@ void radeon_pm_fini(struct radeon_device *rdev)  			radeon_pm_set_clocks(rdev);  		} else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {  			/* cancel work */ -			cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work); +			cancel_delayed_work(&rdev->pm.dynpm_idle_work); +			flush_wq = true;  			/* reset default clocks */  			rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;  			rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;  			radeon_pm_set_clocks(rdev);  		}  		mutex_unlock(&rdev->pm.mutex); +		if (flush_wq) +			flush_workqueue(rdev->wq);  		device_remove_file(rdev->dev, &dev_attr_power_profile);  		device_remove_file(rdev->dev, &dev_attr_power_method); @@ -720,12 +748,12 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work)  			radeon_pm_get_dynpm_state(rdev);  			radeon_pm_set_clocks(rdev);  		} + +		queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, +					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));  	}  	mutex_unlock(&rdev->pm.mutex);  	ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); - -	queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, -					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));  }  /* diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index b5c757f68d3..f78fd592544 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -80,8 +80,8 @@ evergreen 0x9400  0x00028010 DB_RENDER_OVERRIDE2  0x00028028 DB_STENCIL_CLEAR  0x0002802C DB_DEPTH_CLEAR -0x00028034 PA_SC_SCREEN_SCISSOR_BR  0x00028030 PA_SC_SCREEN_SCISSOR_TL +0x00028034 PA_SC_SCREEN_SCISSOR_BR  0x0002805C DB_DEPTH_SLICE  0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0  0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1 @@ -460,8 +460,8 @@ evergreen 0x9400  0x00028844 SQ_PGM_RESOURCES_PS  0x00028848 SQ_PGM_RESOURCES_2_PS  0x0002884C SQ_PGM_EXPORTS_PS -0x0002885C SQ_PGM_RESOURCES_VS -0x00028860 SQ_PGM_RESOURCES_2_VS +0x00028860 SQ_PGM_RESOURCES_VS +0x00028864 SQ_PGM_RESOURCES_2_VS  0x00028878 SQ_PGM_RESOURCES_GS  0x0002887C SQ_PGM_RESOURCES_2_GS  0x00028890 SQ_PGM_RESOURCES_ES @@ -469,8 +469,8 @@ evergreen 0x9400  0x000288A8 SQ_PGM_RESOURCES_FS  0x000288BC SQ_PGM_RESOURCES_HS  0x000288C0 SQ_PGM_RESOURCES_2_HS -0x000288D0 SQ_PGM_RESOURCES_LS -0x000288D4 SQ_PGM_RESOURCES_2_LS +0x000288D4 SQ_PGM_RESOURCES_LS +0x000288D8 SQ_PGM_RESOURCES_2_LS  0x000288E8 SQ_LDS_ALLOC  0x000288EC SQ_LDS_ALLOC_PS  0x000288F0 SQ_VTX_SEMANTIC_CLEAR diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 9e4240b3bf0..f454c9a5e7f 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -57,7 +57,9 @@ void rs400_gart_adjust_size(struct radeon_device *rdev)  	}  	if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) {  		/* FIXME: RS400 & RS480 seems to have issue with GART size -		 * if 4G of system memory (needs more testing) */ +		 * if 4G of system memory (needs more testing) +		 */ +		/* XXX is this still an issue with proper alignment? */  		rdev->mc.gtt_size = 32 * 1024 * 1024;  		DRM_ERROR("Forcing to 32M GART size (because of ASIC bug ?)\n");  	} @@ -263,6 +265,7 @@ void rs400_mc_init(struct radeon_device *rdev)  	r100_vram_init_sizes(rdev);  	base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;  	radeon_vram_location(rdev, &rdev->mc, base); +	rdev->mc.gtt_base_align = rdev->mc.gtt_size - 1;  	radeon_gtt_location(rdev, &rdev->mc);  	radeon_update_bandwidth_info(rdev);  } diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 7bb4c3e52f3..6dc15ea8ba3 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -698,6 +698,7 @@ void rs600_mc_init(struct radeon_device *rdev)  	base = G_000004_MC_FB_START(base) << 16;  	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);  	radeon_vram_location(rdev, &rdev->mc, base); +	rdev->mc.gtt_base_align = 0;  	radeon_gtt_location(rdev, &rdev->mc);  	radeon_update_bandwidth_info(rdev);  } diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index bcc33195ebc..ce4ecbe1081 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -79,7 +79,13 @@ void rs690_pm_info(struct radeon_device *rdev)  			tmp.full = dfixed_const(100);  			rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info.ulBootUpMemoryClock);  			rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp); -			rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock)); +			if (info->info.usK8MemoryClock) +				rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock)); +			else if (rdev->clock.default_mclk) { +				rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk); +				rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp); +			} else +				rdev->pm.igp_system_mclk.full = dfixed_const(400);  			rdev->pm.igp_ht_link_clk.full = dfixed_const(le16_to_cpu(info->info.usFSBClock));  			rdev->pm.igp_ht_link_width.full = dfixed_const(info->info.ucHTLinkWidth);  			break; @@ -87,34 +93,31 @@ void rs690_pm_info(struct radeon_device *rdev)  			tmp.full = dfixed_const(100);  			rdev->pm.igp_sideport_mclk.full = dfixed_const(info->info_v2.ulBootUpSidePortClock);  			rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp); -			rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock); +			if (info->info_v2.ulBootUpUMAClock) +				rdev->pm.igp_system_mclk.full = dfixed_const(info->info_v2.ulBootUpUMAClock); +			else if (rdev->clock.default_mclk) +				rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk); +			else +				rdev->pm.igp_system_mclk.full = dfixed_const(66700);  			rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp);  			rdev->pm.igp_ht_link_clk.full = dfixed_const(info->info_v2.ulHTLinkFreq);  			rdev->pm.igp_ht_link_clk.full = dfixed_div(rdev->pm.igp_ht_link_clk, tmp);  			rdev->pm.igp_ht_link_width.full = dfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth));  			break;  		default: -			tmp.full = dfixed_const(100);  			/* We assume the slower possible clock ie worst case */ -			/* DDR 333Mhz */ -			rdev->pm.igp_sideport_mclk.full = dfixed_const(333); -			/* FIXME: system clock ? */ -			rdev->pm.igp_system_mclk.full = dfixed_const(100); -			rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp); -			rdev->pm.igp_ht_link_clk.full = dfixed_const(200); +			rdev->pm.igp_sideport_mclk.full = dfixed_const(200); +			rdev->pm.igp_system_mclk.full = dfixed_const(200); +			rdev->pm.igp_ht_link_clk.full = dfixed_const(1000);  			rdev->pm.igp_ht_link_width.full = dfixed_const(8);  			DRM_ERROR("No integrated system info for your GPU, using safe default\n");  			break;  		}  	} else { -		tmp.full = dfixed_const(100);  		/* We assume the slower possible clock ie worst case */ -		/* DDR 333Mhz */ -		rdev->pm.igp_sideport_mclk.full = dfixed_const(333); -		/* FIXME: system clock ? */ -		rdev->pm.igp_system_mclk.full = dfixed_const(100); -		rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp); -		rdev->pm.igp_ht_link_clk.full = dfixed_const(200); +		rdev->pm.igp_sideport_mclk.full = dfixed_const(200); +		rdev->pm.igp_system_mclk.full = dfixed_const(200); +		rdev->pm.igp_ht_link_clk.full = dfixed_const(1000);  		rdev->pm.igp_ht_link_width.full = dfixed_const(8);  		DRM_ERROR("No integrated system info for your GPU, using safe default\n");  	} @@ -159,6 +162,7 @@ void rs690_mc_init(struct radeon_device *rdev)  	rs690_pm_info(rdev);  	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);  	radeon_vram_location(rdev, &rdev->mc, base); +	rdev->mc.gtt_base_align = rdev->mc.gtt_size - 1;  	radeon_gtt_location(rdev, &rdev->mc);  	radeon_update_bandwidth_info(rdev);  } @@ -228,10 +232,6 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,  	fixed20_12 a, b, c;  	fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;  	fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; -	/* FIXME: detect IGP with sideport memory, i don't think there is any -	 * such product available -	 */ -	bool sideport = false;  	if (!crtc->base.enabled) {  		/* FIXME: wouldn't it better to set priority mark to maximum */ @@ -300,7 +300,7 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,  	/* Maximun bandwidth is the minimun bandwidth of all component */  	rdev->pm.max_bandwidth = rdev->pm.core_bandwidth; -	if (sideport) { +	if (rdev->mc.igp_sideport_enabled) {  		if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&  			rdev->pm.sideport_bandwidth.full)  			rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth; diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 7d9a7b0a180..0c9c169a685 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -195,6 +195,7 @@ void rv515_mc_init(struct radeon_device *rdev)  	rv515_vram_get_type(rdev);  	r100_vram_init_sizes(rdev);  	radeon_vram_location(rdev, &rdev->mc, 0); +	rdev->mc.gtt_base_align = 0;  	if (!(rdev->flags & RADEON_IS_AGP))  		radeon_gtt_location(rdev, &rdev->mc);  	radeon_update_bandwidth_info(rdev); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index cec536c222c..b7fd8206492 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -224,7 +224,7 @@ static void rv770_mc_program(struct radeon_device *rdev)  	WREG32(MC_VM_FB_LOCATION, tmp);  	WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));  	WREG32(HDP_NONSURFACE_INFO, (2 << 7)); -	WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF); +	WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);  	if (rdev->flags & RADEON_IS_AGP) {  		WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);  		WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16); diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index ef910694bd6..ca904799f01 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -40,11 +40,13 @@  #include <linux/slab.h>  #include <asm/atomic.h> -#include <asm/agp.h>  #include "ttm/ttm_bo_driver.h"  #include "ttm/ttm_page_alloc.h" +#ifdef TTM_HAS_AGP +#include <asm/agp.h> +#endif  #define NUM_PAGES_TO_ALLOC		(PAGE_SIZE/sizeof(struct page *))  #define SMALL_ALLOCATION		16 @@ -104,7 +106,6 @@ struct ttm_pool_opts {  struct ttm_pool_manager {  	struct kobject		kobj;  	struct shrinker		mm_shrink; -	atomic_t		page_alloc_inited;  	struct ttm_pool_opts	options;  	union { @@ -142,7 +143,7 @@ static void ttm_pool_kobj_release(struct kobject *kobj)  {  	struct ttm_pool_manager *m =  		container_of(kobj, struct ttm_pool_manager, kobj); -	(void)m; +	kfree(m);  }  static ssize_t ttm_pool_store(struct kobject *kobj, @@ -214,9 +215,7 @@ static struct kobj_type ttm_pool_kobj_type = {  	.default_attrs = ttm_pool_attrs,  }; -static struct ttm_pool_manager _manager = { -	.page_alloc_inited	= ATOMIC_INIT(0) -}; +static struct ttm_pool_manager *_manager;  #ifndef CONFIG_X86  static int set_pages_array_wb(struct page **pages, int addrinarray) @@ -271,7 +270,7 @@ static struct ttm_page_pool *ttm_get_pool(int flags,  	if (flags & TTM_PAGE_FLAG_DMA32)  		pool_index |= 0x2; -	return &_manager.pools[pool_index]; +	return &_manager->pools[pool_index];  }  /* set memory back to wb and free the pages. */ @@ -387,7 +386,7 @@ static int ttm_pool_get_num_unused_pages(void)  	unsigned i;  	int total = 0;  	for (i = 0; i < NUM_POOLS; ++i) -		total += _manager.pools[i].npages; +		total += _manager->pools[i].npages;  	return total;  } @@ -395,7 +394,7 @@ static int ttm_pool_get_num_unused_pages(void)  /**   * Callback for mm to request pool to reduce number of page held.   */ -static int ttm_pool_mm_shrink(int shrink_pages, gfp_t gfp_mask) +static int ttm_pool_mm_shrink(struct shrinker *shrink, int shrink_pages, gfp_t gfp_mask)  {  	static atomic_t start_pool = ATOMIC_INIT(0);  	unsigned i; @@ -408,7 +407,7 @@ static int ttm_pool_mm_shrink(int shrink_pages, gfp_t gfp_mask)  		unsigned nr_free = shrink_pages;  		if (shrink_pages == 0)  			break; -		pool = &_manager.pools[(i + pool_offset)%NUM_POOLS]; +		pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];  		shrink_pages = ttm_page_pool_free(pool, nr_free);  	}  	/* return estimated number of unused pages in pool */ @@ -576,10 +575,10 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,  	/* If allocation request is small and there is not enough  	 * pages in pool we fill the pool first */ -	if (count < _manager.options.small +	if (count < _manager->options.small  		&& count > pool->npages) {  		struct list_head new_pages; -		unsigned alloc_size = _manager.options.alloc_size; +		unsigned alloc_size = _manager->options.alloc_size;  		/**  		 * Can't change page caching if in irqsave context. We have to @@ -667,7 +666,7 @@ int ttm_get_pages(struct list_head *pages, int flags,  {  	struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);  	struct page *p = NULL; -	int gfp_flags = 0; +	int gfp_flags = GFP_USER;  	int r;  	/* set zero flag for page allocation if required */ @@ -759,8 +758,8 @@ void ttm_put_pages(struct list_head *pages, unsigned page_count, int flags,  	pool->npages += page_count;  	/* Check that we don't go over the pool limit */  	page_count = 0; -	if (pool->npages > _manager.options.max_size) { -		page_count = pool->npages - _manager.options.max_size; +	if (pool->npages > _manager->options.max_size) { +		page_count = pool->npages - _manager->options.max_size;  		/* free at least NUM_PAGES_TO_ALLOC number of pages  		 * to reduce calls to set_memory_wb */  		if (page_count < NUM_PAGES_TO_ALLOC) @@ -785,33 +784,36 @@ static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, int flags,  int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)  {  	int ret; -	if (atomic_add_return(1, &_manager.page_alloc_inited) > 1) -		return 0; + +	WARN_ON(_manager);  	printk(KERN_INFO TTM_PFX "Initializing pool allocator.\n"); -	ttm_page_pool_init_locked(&_manager.wc_pool, GFP_HIGHUSER, "wc"); +	_manager = kzalloc(sizeof(*_manager), GFP_KERNEL); + +	ttm_page_pool_init_locked(&_manager->wc_pool, GFP_HIGHUSER, "wc"); -	ttm_page_pool_init_locked(&_manager.uc_pool, GFP_HIGHUSER, "uc"); +	ttm_page_pool_init_locked(&_manager->uc_pool, GFP_HIGHUSER, "uc"); -	ttm_page_pool_init_locked(&_manager.wc_pool_dma32, GFP_USER | GFP_DMA32, -			"wc dma"); +	ttm_page_pool_init_locked(&_manager->wc_pool_dma32, +				  GFP_USER | GFP_DMA32, "wc dma"); -	ttm_page_pool_init_locked(&_manager.uc_pool_dma32, GFP_USER | GFP_DMA32, -			"uc dma"); +	ttm_page_pool_init_locked(&_manager->uc_pool_dma32, +				  GFP_USER | GFP_DMA32, "uc dma"); -	_manager.options.max_size = max_pages; -	_manager.options.small = SMALL_ALLOCATION; -	_manager.options.alloc_size = NUM_PAGES_TO_ALLOC; +	_manager->options.max_size = max_pages; +	_manager->options.small = SMALL_ALLOCATION; +	_manager->options.alloc_size = NUM_PAGES_TO_ALLOC; -	kobject_init(&_manager.kobj, &ttm_pool_kobj_type); -	ret = kobject_add(&_manager.kobj, &glob->kobj, "pool"); +	ret = kobject_init_and_add(&_manager->kobj, &ttm_pool_kobj_type, +				   &glob->kobj, "pool");  	if (unlikely(ret != 0)) { -		kobject_put(&_manager.kobj); +		kobject_put(&_manager->kobj); +		_manager = NULL;  		return ret;  	} -	ttm_pool_mm_shrink_init(&_manager); +	ttm_pool_mm_shrink_init(_manager);  	return 0;  } @@ -820,16 +822,14 @@ void ttm_page_alloc_fini()  {  	int i; -	if (atomic_sub_return(1, &_manager.page_alloc_inited) > 0) -		return; -  	printk(KERN_INFO TTM_PFX "Finalizing pool allocator.\n"); -	ttm_pool_mm_shrink_fini(&_manager); +	ttm_pool_mm_shrink_fini(_manager);  	for (i = 0; i < NUM_POOLS; ++i) -		ttm_page_pool_free(&_manager.pools[i], FREE_ALL_PAGES); +		ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES); -	kobject_put(&_manager.kobj); +	kobject_put(&_manager->kobj); +	_manager = NULL;  }  int ttm_page_alloc_debugfs(struct seq_file *m, void *data) @@ -837,14 +837,14 @@ int ttm_page_alloc_debugfs(struct seq_file *m, void *data)  	struct ttm_page_pool *p;  	unsigned i;  	char *h[] = {"pool", "refills", "pages freed", "size"}; -	if (atomic_read(&_manager.page_alloc_inited) == 0) { +	if (!_manager) {  		seq_printf(m, "No pool allocator running.\n");  		return 0;  	}  	seq_printf(m, "%6s %12s %13s %8s\n",  			h[0], h[1], h[2], h[3]);  	for (i = 0; i < NUM_POOLS; ++i) { -		p = &_manager.pools[i]; +		p = &_manager->pools[i];  		seq_printf(m, "%6s %12ld %13ld %8d\n",  				p->name, p->nrefills, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index f1d62611241..437ac786277 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -972,6 +972,7 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,  	ret = copy_from_user(rects, user_rects, rects_size);  	if (unlikely(ret != 0)) {  		DRM_ERROR("Failed to get rects.\n"); +		ret = -EFAULT;  		goto out_free;  	} diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 132278fa624..43409936905 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -358,6 +358,7 @@ config HID_ROCCAT  config HID_ROCCAT_KONE  	tristate "Roccat Kone Mouse support"  	depends on USB_HID +	select HID_ROCCAT  	---help---  	Support for Roccat Kone mouse. diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index aa0f7dcabcd..866e54ec5fb 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1337,6 +1337,24 @@ static const struct hid_device_id hid_blacklist[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_3) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_4) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_5) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_6) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_7) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_8) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_9) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_10) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_11) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_12) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_13) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_14) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_15) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, @@ -1760,7 +1778,8 @@ int hid_add_device(struct hid_device *hdev)  	/* we need to kill them here, otherwise they will stay allocated to  	 * wait for coming driver */ -	if (!(hdev->quirks & HID_QUIRK_NO_IGNORE) && hid_ignore(hdev)) +	if (!(hdev->quirks & HID_QUIRK_NO_IGNORE) +            && (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE)))  		return -ENODEV;  	/* XXX hack, any other cleaner solution after the driver core diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index c9402676857..850d02a7a92 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -949,8 +949,8 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,  	int ret = 0, len;  	DECLARE_WAITQUEUE(wait, current); +	mutex_lock(&list->read_mutex);  	while (ret == 0) { -		mutex_lock(&list->read_mutex);  		if (list->head == list->tail) {  			add_wait_queue(&list->hdev->debug_wait, &wait);  			set_current_state(TASK_INTERRUPTIBLE); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 6af77ed0b55..31601eef25d 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -134,6 +134,7 @@  #define USB_VENDOR_ID_CH		0x068e  #define USB_DEVICE_ID_CH_PRO_PEDALS	0x00f2  #define USB_DEVICE_ID_CH_COMBATSTICK	0x00f4 +#define USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE       0x0051  #define USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE	0x00ff  #define USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK	0x00d3 @@ -369,6 +370,8 @@  #define USB_DEVICE_ID_MS_PRESENTER_8K_BT	0x0701  #define USB_DEVICE_ID_MS_PRESENTER_8K_USB	0x0713 +#define USB_VENDOR_ID_MOJO		0x8282 +#define USB_DEVICE_ID_RETRO_ADAPTER	0x3201  #define USB_VENDOR_ID_MONTEREY		0x0566  #define USB_DEVICE_ID_GENIUS_KB29E	0x3004 @@ -391,6 +394,24 @@  #define USB_VENDOR_ID_NTRIG                0x1b96  #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN   0x0001 +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1   0x0003 +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2   0x0004 +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_3   0x0005 +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_4   0x0006 +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_5   0x0007 +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_6   0x0008 +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_7   0x0009 +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_8   0x000A +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_9   0x000B +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_10   0x000C +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_11   0x000D +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_12   0x000E +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_13   0x000F +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_14   0x0010 +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_15   0x0011 +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16   0x0012 +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17   0x0013 +#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18   0x0014  #define USB_VENDOR_ID_ONTRAK		0x0a07  #define USB_DEVICE_ID_ONTRAK_ADU100	0x0064 diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index b6b0caeeac5..fb69b8c4953 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -868,6 +868,42 @@ static void ntrig_remove(struct hid_device *hdev)  static const struct hid_device_id ntrig_devices[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),  		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_3), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_4), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_5), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_6), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_7), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_8), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_9), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_10), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_11), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_12), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_13), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_14), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_15), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17), +		.driver_data = NTRIG_DUPLICATE_USAGES }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18), +		.driver_data = NTRIG_DUPLICATE_USAGES },  	{ }  };  MODULE_DEVICE_TABLE(hid, ntrig_devices); diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 1ebd3244eb8..b729c028667 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -827,14 +827,21 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co  				ret++;  		}  	} else { +		int skipped_report_id = 0; +		if (buf[0] == 0x0) { +			/* Don't send the Report ID */ +			buf++; +			count--; +			skipped_report_id = 1; +		}  		ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),  			HID_REQ_SET_REPORT,  			USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,  			((report_type + 1) << 8) | *buf, -			interface->desc.bInterfaceNumber, buf + 1, count - 1, +			interface->desc.bInterfaceNumber, buf, count,  			USB_CTRL_SET_TIMEOUT); -		/* count also the report id */ -		if (ret > 0) +		/* count also the report id, if this was a numbered report. */ +		if (ret > 0 && skipped_report_id)  			ret++;  	} diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 5ff8d327f33..5f5aa39b398 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -34,6 +34,7 @@ static const struct hid_blacklist {  	{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },  	{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },  	{ USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, +	{ USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT },  	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },  	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },  	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, @@ -56,6 +57,7 @@ static const struct hid_blacklist {  	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },  	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },  	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET }, +	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET },  	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET },  	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET },  	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET }, diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 2988da150ed..05344af5073 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -53,6 +53,7 @@ struct coretemp_data {  	struct mutex update_lock;  	const char *name;  	u32 id; +	u16 core_id;  	char valid;		/* zero until following fields are valid */  	unsigned long last_updated;	/* in jiffies */  	int temp; @@ -75,7 +76,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute  	if (attr->index == SHOW_NAME)  		ret = sprintf(buf, "%s\n", data->name);  	else	/* show label */ -		ret = sprintf(buf, "Core %d\n", data->id); +		ret = sprintf(buf, "Core %d\n", data->core_id);  	return ret;  } @@ -304,6 +305,9 @@ static int __devinit coretemp_probe(struct platform_device *pdev)  	}  	data->id = pdev->id; +#ifdef CONFIG_SMP +	data->core_id = c->cpu_core_id; +#endif  	data->name = "coretemp";  	mutex_init(&data->update_lock); @@ -405,6 +409,10 @@ struct pdev_entry {  	struct list_head list;  	struct platform_device *pdev;  	unsigned int cpu; +#ifdef CONFIG_SMP +	u16 phys_proc_id; +	u16 cpu_core_id; +#endif  };  static LIST_HEAD(pdev_list); @@ -415,6 +423,22 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)  	int err;  	struct platform_device *pdev;  	struct pdev_entry *pdev_entry; +#ifdef CONFIG_SMP +	struct cpuinfo_x86 *c = &cpu_data(cpu); +#endif + +	mutex_lock(&pdev_list_mutex); + +#ifdef CONFIG_SMP +	/* Skip second HT entry of each core */ +	list_for_each_entry(pdev_entry, &pdev_list, list) { +		if (c->phys_proc_id == pdev_entry->phys_proc_id && +		    c->cpu_core_id == pdev_entry->cpu_core_id) { +			err = 0;	/* Not an error */ +			goto exit; +		} +	} +#endif  	pdev = platform_device_alloc(DRVNAME, cpu);  	if (!pdev) { @@ -438,7 +462,10 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)  	pdev_entry->pdev = pdev;  	pdev_entry->cpu = cpu; -	mutex_lock(&pdev_list_mutex); +#ifdef CONFIG_SMP +	pdev_entry->phys_proc_id = c->phys_proc_id; +	pdev_entry->cpu_core_id = c->cpu_core_id; +#endif  	list_add_tail(&pdev_entry->list, &pdev_list);  	mutex_unlock(&pdev_list_mutex); @@ -449,6 +476,7 @@ exit_device_free:  exit_device_put:  	platform_device_put(pdev);  exit: +	mutex_unlock(&pdev_list_mutex);  	return err;  } diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c index e880e2c3871..937983407e2 100644 --- a/drivers/hwmon/i5k_amb.c +++ b/drivers/hwmon/i5k_amb.c @@ -289,6 +289,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)  			iattr->s_attr.dev_attr.attr.mode = S_IRUGO;  			iattr->s_attr.dev_attr.show = show_label;  			iattr->s_attr.index = k; +			sysfs_attr_init(&iattr->s_attr.dev_attr.attr);  			res = device_create_file(&pdev->dev,  						 &iattr->s_attr.dev_attr);  			if (res) @@ -303,6 +304,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)  			iattr->s_attr.dev_attr.attr.mode = S_IRUGO;  			iattr->s_attr.dev_attr.show = show_amb_temp;  			iattr->s_attr.index = k; +			sysfs_attr_init(&iattr->s_attr.dev_attr.attr);  			res = device_create_file(&pdev->dev,  						 &iattr->s_attr.dev_attr);  			if (res) @@ -318,6 +320,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)  			iattr->s_attr.dev_attr.show = show_amb_min;  			iattr->s_attr.dev_attr.store = store_amb_min;  			iattr->s_attr.index = k; +			sysfs_attr_init(&iattr->s_attr.dev_attr.attr);  			res = device_create_file(&pdev->dev,  						 &iattr->s_attr.dev_attr);  			if (res) @@ -333,6 +336,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)  			iattr->s_attr.dev_attr.show = show_amb_mid;  			iattr->s_attr.dev_attr.store = store_amb_mid;  			iattr->s_attr.index = k; +			sysfs_attr_init(&iattr->s_attr.dev_attr.attr);  			res = device_create_file(&pdev->dev,  						 &iattr->s_attr.dev_attr);  			if (res) @@ -348,6 +352,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)  			iattr->s_attr.dev_attr.show = show_amb_max;  			iattr->s_attr.dev_attr.store = store_amb_max;  			iattr->s_attr.index = k; +			sysfs_attr_init(&iattr->s_attr.dev_attr.attr);  			res = device_create_file(&pdev->dev,  						 &iattr->s_attr.dev_attr);  			if (res) @@ -362,6 +367,7 @@ static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)  			iattr->s_attr.dev_attr.attr.mode = S_IRUGO;  			iattr->s_attr.dev_attr.show = show_amb_alarm;  			iattr->s_attr.index = k; +			sysfs_attr_init(&iattr->s_attr.dev_attr.attr);  			res = device_create_file(&pdev->dev,  						 &iattr->s_attr.dev_attr);  			if (res) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 5be09c048c5..25763d2223b 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -80,6 +80,13 @@ superio_inb(int reg)  	return inb(VAL);  } +static inline void +superio_outb(int reg, int val) +{ +	outb(reg, REG); +	outb(val, VAL); +} +  static int superio_inw(int reg)  {  	int val; @@ -1517,6 +1524,21 @@ static int __init it87_find(unsigned short *address,  			sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);  		reg = superio_inb(IT87_SIO_PINX2_REG); +		/* +		 * The IT8720F has no VIN7 pin, so VCCH should always be +		 * routed internally to VIN7 with an internal divider. +		 * Curiously, there still is a configuration bit to control +		 * this, which means it can be set incorrectly. And even +		 * more curiously, many boards out there are improperly +		 * configured, even though the IT8720F datasheet claims +		 * that the internal routing of VCCH to VIN7 is the default +		 * setting. So we force the internal routing in this case. +		 */ +		if (sio_data->type == it8720 && !(reg & (1 << 1))) { +			reg |= (1 << 1); +			superio_outb(IT87_SIO_PINX2_REG, reg); +			pr_notice("it87: Routing internal VCCH to in7\n"); +		}  		if (reg & (1 << 0))  			pr_info("it87: in3 is VCC (+5V)\n");  		if (reg & (1 << 1)) diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index 099a2138cdf..da5a2404cd3 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c @@ -112,11 +112,21 @@ static bool __devinit has_erratum_319(struct pci_dev *pdev)  	if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3)  		return false; -	/* Differentiate between AM2+ (bad) and AM3 (good) */ +	/* DDR3 memory implies socket AM3, which is good */  	pci_bus_read_config_dword(pdev->bus,  				  PCI_DEVFN(PCI_SLOT(pdev->devfn), 2),  				  REG_DCT0_CONFIG_HIGH, ®_dram_cfg); -	return !(reg_dram_cfg & DDR3_MODE); +	if (reg_dram_cfg & DDR3_MODE) +		return false; + +	/* +	 * Unfortunately it is possible to run a socket AM3 CPU with DDR2 +	 * memory. We blacklist all the cores which do exist in socket AM2+ +	 * format. It still isn't perfect, as RB-C2 cores exist in both AM2+ +	 * and AM3 formats, but that's the best we can do. +	 */ +	return boot_cpu_data.x86_model < 4 || +	       (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2);  }  static int __devinit k10temp_probe(struct pci_dev *pdev, diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index 0ceb6d6200a..8bdf80d9159 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c @@ -120,7 +120,7 @@ static ssize_t show_temp(struct device *dev,  	int temp;  	struct k8temp_data *data = k8temp_update_device(dev); -	if (data->swap_core_select) +	if (data->swap_core_select && (data->sensorsp & SEL_CORE))  		core = core ? 0 : 1;  	temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset; @@ -180,11 +180,13 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,  		}  		if ((model >= 0x69) && -		    !(model == 0xc1 || model == 0x6c || model == 0x7c)) { +		    !(model == 0xc1 || model == 0x6c || model == 0x7c || +		      model == 0x6b || model == 0x6f || model == 0x7f)) {  			/* -			 * RevG desktop CPUs (i.e. no socket S1G1 parts) -			 * need additional offset, otherwise reported -			 * temperature is below ambient temperature +			 * RevG desktop CPUs (i.e. no socket S1G1 or +			 * ASB1 parts) need additional offset, +			 * otherwise reported temperature is below +			 * ambient temperature  			 */  			data->temp_offset = 21000;  		} diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index f4b21f2bb8e..c60081169cc 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -655,7 +655,7 @@ static void __devinit dmi_check_onboard_device(u8 type, const char *name,  		/* & ~0x80, ignore enabled/disabled bit */  		if ((type & ~0x80) != dmi_devices[i].type)  			continue; -		if (strcmp(name, dmi_devices[i].name)) +		if (strcasecmp(name, dmi_devices[i].name))  			continue;  		memset(&info, 0, sizeof(struct i2c_board_info)); @@ -704,9 +704,6 @@ static int __devinit i801_probe(struct pci_dev *dev,  {  	unsigned char temp;  	int err, i; -#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE -	const char *vendor; -#endif  	I801_dev = dev;  	i801_features = 0; @@ -808,8 +805,7 @@ static int __devinit i801_probe(struct pci_dev *dev,  	}  #endif  #if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE -	vendor = dmi_get_system_info(DMI_BOARD_VENDOR); -	if (vendor && !strcmp(vendor, "FUJITSU SIEMENS")) +	if (dmi_name_in_vendors("FUJITSU"))  		dmi_walk(dmi_check_onboard_devices, &i801_adapter);  #endif diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c index 3d76a188e42..0fe505d7abe 100644 --- a/drivers/i2c/busses/i2c-sibyte.c +++ b/drivers/i2c/busses/i2c-sibyte.c @@ -94,7 +94,7 @@ static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,  		}  		break;  	default: -		return -1;      /* XXXKW better error code? */ +		return -EOPNOTSUPP;  	}  	while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY) @@ -104,7 +104,7 @@ static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,  	if (error & M_SMB_ERROR) {  		/* Clear error bit by writing a 1 */  		csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS)); -		return -1;      /* XXXKW better error code? */ +		return (error & M_SMB_ERROR_TYPE) ? -EIO : -ENXIO;  	}  	if (data_bytes == 1) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 1cca2631e5b..0815e10da7c 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1428,13 +1428,12 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)  	if (!(adapter->class & driver->class))  		goto exit_free; -	/* Stop here if we can't use SMBUS_QUICK */ -	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) { +	/* Stop here if the bus doesn't support probing */ +	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE)) {  		if (address_list[0] == I2C_CLIENT_END)  			goto exit_free; -		dev_warn(&adapter->dev, "SMBus Quick command not supported, " -			 "can't probe for chips\n"); +		dev_warn(&adapter->dev, "Probing not supported\n");  		err = -EOPNOTSUPP;  		goto exit_free;  	} diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 30ce0a8eca0..855ee44fdb5 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -969,7 +969,8 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)  		goto err;  	goto out;  err: -	abort_connection(ep, skb, GFP_KERNEL); +	state_set(&ep->com, ABORTING); +	send_abort(ep, skb, GFP_KERNEL);  out:  	connect_reply_upcall(ep, err);  	return; @@ -1372,7 +1373,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)  				    pdev, 0);  		mtu = pdev->mtu;  		tx_chan = cxgb4_port_chan(pdev); -		smac_idx = tx_chan << 1; +		smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;  		step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan;  		txq_idx = cxgb4_port_idx(pdev) * step;  		step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan; @@ -1383,7 +1384,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)  					dst->neighbour->dev, 0);  		mtu = dst_mtu(dst);  		tx_chan = cxgb4_port_chan(dst->neighbour->dev); -		smac_idx = tx_chan << 1; +		smac_idx = (cxgb4_port_viid(dst->neighbour->dev) & 0x7F) << 1;  		step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan;  		txq_idx = cxgb4_port_idx(dst->neighbour->dev) * step;  		step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan; @@ -1950,7 +1951,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  					pdev, 0);  		ep->mtu = pdev->mtu;  		ep->tx_chan = cxgb4_port_chan(pdev); -		ep->smac_idx = ep->tx_chan << 1; +		ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;  		step = ep->com.dev->rdev.lldi.ntxq /  		       ep->com.dev->rdev.lldi.nchan;  		ep->txq_idx = cxgb4_port_idx(pdev) * step; @@ -1965,7 +1966,8 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)  					ep->dst->neighbour->dev, 0);  		ep->mtu = dst_mtu(ep->dst);  		ep->tx_chan = cxgb4_port_chan(ep->dst->neighbour->dev); -		ep->smac_idx = ep->tx_chan << 1; +		ep->smac_idx = (cxgb4_port_viid(ep->dst->neighbour->dev) & +				0x7F) << 1;  		step = ep->com.dev->rdev.lldi.ntxq /  		       ep->com.dev->rdev.lldi.nchan;  		ep->txq_idx = cxgb4_port_idx(ep->dst->neighbour->dev) * step; diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index 2447f529548..fac5c6e6801 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c @@ -77,7 +77,7 @@ static int destroy_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,  	kfree(cq->sw_queue);  	dma_free_coherent(&(rdev->lldi.pdev->dev),  			  cq->memsize, cq->queue, -			  pci_unmap_addr(cq, mapping)); +			  dma_unmap_addr(cq, mapping));  	c4iw_put_cqid(rdev, cq->cqid, uctx);  	return ret;  } @@ -112,7 +112,7 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,  		ret = -ENOMEM;  		goto err3;  	} -	pci_unmap_addr_set(cq, mapping, cq->dma_addr); +	dma_unmap_addr_set(cq, mapping, cq->dma_addr);  	memset(cq->queue, 0, cq->memsize);  	/* build fw_ri_res_wr */ @@ -179,7 +179,7 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,  	return 0;  err4:  	dma_free_coherent(&rdev->lldi.pdev->dev, cq->memsize, cq->queue, -			  pci_unmap_addr(cq, mapping)); +			  dma_unmap_addr(cq, mapping));  err3:  	kfree(cq->sw_queue);  err2: @@ -764,7 +764,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,  	struct c4iw_create_cq_resp uresp;  	struct c4iw_ucontext *ucontext = NULL;  	int ret; -	size_t memsize; +	size_t memsize, hwentries;  	struct c4iw_mm_entry *mm, *mm2;  	PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries); @@ -788,14 +788,29 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,  	 * entries must be multiple of 16 for HW.  	 */  	entries = roundup(entries, 16); -	memsize = entries * sizeof *chp->cq.queue; + +	/* +	 * Make actual HW queue 2x to avoid cdix_inc overflows. +	 */ +	hwentries = entries * 2; + +	/* +	 * Make HW queue at least 64 entries so GTS updates aren't too +	 * frequent. +	 */ +	if (hwentries < 64) +		hwentries = 64; + +	memsize = hwentries * sizeof *chp->cq.queue;  	/*  	 * memsize must be a multiple of the page size if its a user cq.  	 */ -	if (ucontext) +	if (ucontext) {  		memsize = roundup(memsize, PAGE_SIZE); -	chp->cq.size = entries; +		hwentries = memsize / sizeof *chp->cq.queue; +	} +	chp->cq.size = hwentries;  	chp->cq.memsize = memsize;  	ret = create_cq(&rhp->rdev, &chp->cq, @@ -805,7 +820,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,  	chp->rhp = rhp;  	chp->cq.size--;				/* status page */ -	chp->ibcq.cqe = chp->cq.size - 1; +	chp->ibcq.cqe = entries - 2;  	spin_lock_init(&chp->lock);  	atomic_set(&chp->refcnt, 1);  	init_waitqueue_head(&chp->wait); diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 277ab589b44..d33e1a66881 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h @@ -261,7 +261,7 @@ static inline struct c4iw_mw *to_c4iw_mw(struct ib_mw *ibmw)  struct c4iw_fr_page_list {  	struct ib_fast_reg_page_list ibpl; -	DECLARE_PCI_UNMAP_ADDR(mapping); +	DEFINE_DMA_UNMAP_ADDR(mapping);  	dma_addr_t dma_addr;  	struct c4iw_dev *dev;  	int size; diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index 7f94da1a243..82b5703b894 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -764,7 +764,7 @@ struct ib_fast_reg_page_list *c4iw_alloc_fastreg_pbl(struct ib_device *device,  	if (!c4pl)  		return ERR_PTR(-ENOMEM); -	pci_unmap_addr_set(c4pl, mapping, dma_addr); +	dma_unmap_addr_set(c4pl, mapping, dma_addr);  	c4pl->dma_addr = dma_addr;  	c4pl->dev = dev;  	c4pl->size = size; @@ -779,7 +779,7 @@ void c4iw_free_fastreg_pbl(struct ib_fast_reg_page_list *ibpl)  	struct c4iw_fr_page_list *c4pl = to_c4iw_fr_page_list(ibpl);  	dma_free_coherent(&c4pl->dev->rdev.lldi.pdev->dev, c4pl->size, -			  c4pl, pci_unmap_addr(c4pl, mapping)); +			  c4pl, dma_unmap_addr(c4pl, mapping));  }  int c4iw_dereg_mr(struct ib_mr *ib_mr) diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 646a2a5711f..86b93f2ecca 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -40,10 +40,10 @@ static int destroy_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,  	 */  	dma_free_coherent(&(rdev->lldi.pdev->dev),  			  wq->rq.memsize, wq->rq.queue, -			  pci_unmap_addr(&wq->rq, mapping)); +			  dma_unmap_addr(&wq->rq, mapping));  	dma_free_coherent(&(rdev->lldi.pdev->dev),  			  wq->sq.memsize, wq->sq.queue, -			  pci_unmap_addr(&wq->sq, mapping)); +			  dma_unmap_addr(&wq->sq, mapping));  	c4iw_rqtpool_free(rdev, wq->rq.rqt_hwaddr, wq->rq.rqt_size);  	kfree(wq->rq.sw_rq);  	kfree(wq->sq.sw_sq); @@ -99,7 +99,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,  	if (!wq->sq.queue)  		goto err5;  	memset(wq->sq.queue, 0, wq->sq.memsize); -	pci_unmap_addr_set(&wq->sq, mapping, wq->sq.dma_addr); +	dma_unmap_addr_set(&wq->sq, mapping, wq->sq.dma_addr);  	wq->rq.queue = dma_alloc_coherent(&(rdev->lldi.pdev->dev),  					  wq->rq.memsize, &(wq->rq.dma_addr), @@ -112,7 +112,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,  		wq->rq.queue,  		(unsigned long long)virt_to_phys(wq->rq.queue));  	memset(wq->rq.queue, 0, wq->rq.memsize); -	pci_unmap_addr_set(&wq->rq, mapping, wq->rq.dma_addr); +	dma_unmap_addr_set(&wq->rq, mapping, wq->rq.dma_addr);  	wq->db = rdev->lldi.db_reg;  	wq->gts = rdev->lldi.gts_reg; @@ -217,11 +217,11 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,  err7:  	dma_free_coherent(&(rdev->lldi.pdev->dev),  			  wq->rq.memsize, wq->rq.queue, -			  pci_unmap_addr(&wq->rq, mapping)); +			  dma_unmap_addr(&wq->rq, mapping));  err6:  	dma_free_coherent(&(rdev->lldi.pdev->dev),  			  wq->sq.memsize, wq->sq.queue, -			  pci_unmap_addr(&wq->sq, mapping)); +			  dma_unmap_addr(&wq->sq, mapping));  err5:  	c4iw_rqtpool_free(rdev, wq->rq.rqt_hwaddr, wq->rq.rqt_size);  err4: diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h index 1057cb96302..9cf8d85bfcf 100644 --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h @@ -279,7 +279,7 @@ struct t4_swsqe {  struct t4_sq {  	union t4_wr *queue;  	dma_addr_t dma_addr; -	DECLARE_PCI_UNMAP_ADDR(mapping); +	DEFINE_DMA_UNMAP_ADDR(mapping);  	struct t4_swsqe *sw_sq;  	struct t4_swsqe *oldest_read;  	u64 udb; @@ -298,7 +298,7 @@ struct t4_swrqe {  struct t4_rq {  	union  t4_recv_wr *queue;  	dma_addr_t dma_addr; -	DECLARE_PCI_UNMAP_ADDR(mapping); +	DEFINE_DMA_UNMAP_ADDR(mapping);  	struct t4_swrqe *sw_rq;  	u64 udb;  	size_t memsize; @@ -429,7 +429,7 @@ static inline int t4_wq_db_enabled(struct t4_wq *wq)  struct t4_cq {  	struct t4_cqe *queue;  	dma_addr_t dma_addr; -	DECLARE_PCI_UNMAP_ADDR(mapping); +	DEFINE_DMA_UNMAP_ADDR(mapping);  	struct t4_cqe *sw_queue;  	void __iomem *gts;  	struct c4iw_rdev *rdev; diff --git a/drivers/infiniband/hw/qib/Makefile b/drivers/infiniband/hw/qib/Makefile index c6515a1b9a6..f12d7bb8b39 100644 --- a/drivers/infiniband/hw/qib/Makefile +++ b/drivers/infiniband/hw/qib/Makefile @@ -6,7 +6,7 @@ ib_qib-y := qib_cq.o qib_diag.o qib_dma.o qib_driver.o qib_eeprom.o \  	qib_qp.o qib_qsfp.o qib_rc.o qib_ruc.o qib_sdma.o qib_srq.o \  	qib_sysfs.o qib_twsi.o qib_tx.o qib_uc.o qib_ud.o \  	qib_user_pages.o qib_user_sdma.o qib_verbs_mcast.o qib_iba7220.o \ -	qib_sd7220.o qib_sd7220_img.o qib_iba7322.o qib_verbs.o +	qib_sd7220.o qib_iba7322.o qib_verbs.o  # 6120 has no fallback if no MSI interrupts, others can do INTx  ib_qib-$(CONFIG_PCI_MSI) += qib_iba6120.o diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index 32d9208efcf..3593983df7b 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -686,6 +686,7 @@ struct qib_devdata {  	void __iomem *piobase;  	/* mem-mapped pointer to base of user chip regs (if using WC PAT) */  	u64 __iomem *userbase; +	void __iomem *piovl15base; /* base of VL15 buffers, if not WC */  	/*  	 * points to area where PIOavail registers will be DMA'ed.  	 * Has to be on a page of it's own, because the page will be diff --git a/drivers/infiniband/hw/qib/qib_7220.h b/drivers/infiniband/hw/qib/qib_7220.h index ea0bfd896f9..21f374aa063 100644 --- a/drivers/infiniband/hw/qib/qib_7220.h +++ b/drivers/infiniband/hw/qib/qib_7220.h @@ -109,10 +109,6 @@ struct qib_chippport_specific {   */  int qib_sd7220_presets(struct qib_devdata *dd);  int qib_sd7220_init(struct qib_devdata *dd); -int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum, u8 *img, -		       int len, int offset); -int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum, const u8 *img, -			int len, int offset);  void qib_sd7220_clr_ibpar(struct qib_devdata *);  /*   * Below used for sdnum parameter, selecting one of the two sections @@ -121,9 +117,6 @@ void qib_sd7220_clr_ibpar(struct qib_devdata *);   */  #define IB_7220_SERDES 2 -int qib_sd7220_ib_load(struct qib_devdata *dd); -int qib_sd7220_ib_vfy(struct qib_devdata *dd); -  static inline u32 qib_read_kreg32(const struct qib_devdata *dd,  				  const u16 regno)  { diff --git a/drivers/infiniband/hw/qib/qib_7322_regs.h b/drivers/infiniband/hw/qib/qib_7322_regs.h index a97440ba924..32dc81ff8d4 100644 --- a/drivers/infiniband/hw/qib/qib_7322_regs.h +++ b/drivers/infiniband/hw/qib/qib_7322_regs.h @@ -742,15 +742,15 @@  #define QIB_7322_HwErrMask_IBCBusFromSPCParityErrMask_1_LSB 0xF  #define QIB_7322_HwErrMask_IBCBusFromSPCParityErrMask_1_MSB 0xF  #define QIB_7322_HwErrMask_IBCBusFromSPCParityErrMask_1_RMASK 0x1 -#define QIB_7322_HwErrMask_statusValidNoEopMask_1_LSB 0xE -#define QIB_7322_HwErrMask_statusValidNoEopMask_1_MSB 0xE -#define QIB_7322_HwErrMask_statusValidNoEopMask_1_RMASK 0x1 +#define QIB_7322_HwErrMask_IBCBusToSPCParityErrMask_1_LSB 0xE +#define QIB_7322_HwErrMask_IBCBusToSPCParityErrMask_1_MSB 0xE +#define QIB_7322_HwErrMask_IBCBusToSPCParityErrMask_1_RMASK 0x1  #define QIB_7322_HwErrMask_IBCBusFromSPCParityErrMask_0_LSB 0xD  #define QIB_7322_HwErrMask_IBCBusFromSPCParityErrMask_0_MSB 0xD  #define QIB_7322_HwErrMask_IBCBusFromSPCParityErrMask_0_RMASK 0x1 -#define QIB_7322_HwErrMask_statusValidNoEopMask_0_LSB 0xC -#define QIB_7322_HwErrMask_statusValidNoEopMask_0_MSB 0xC -#define QIB_7322_HwErrMask_statusValidNoEopMask_0_RMASK 0x1 +#define QIB_7322_HwErrMask_statusValidNoEopMask_LSB 0xC +#define QIB_7322_HwErrMask_statusValidNoEopMask_MSB 0xC +#define QIB_7322_HwErrMask_statusValidNoEopMask_RMASK 0x1  #define QIB_7322_HwErrMask_LATriggeredMask_LSB 0xB  #define QIB_7322_HwErrMask_LATriggeredMask_MSB 0xB  #define QIB_7322_HwErrMask_LATriggeredMask_RMASK 0x1 @@ -796,15 +796,15 @@  #define QIB_7322_HwErrStatus_IBCBusFromSPCParityErr_1_LSB 0xF  #define QIB_7322_HwErrStatus_IBCBusFromSPCParityErr_1_MSB 0xF  #define QIB_7322_HwErrStatus_IBCBusFromSPCParityErr_1_RMASK 0x1 -#define QIB_7322_HwErrStatus_statusValidNoEop_1_LSB 0xE -#define QIB_7322_HwErrStatus_statusValidNoEop_1_MSB 0xE -#define QIB_7322_HwErrStatus_statusValidNoEop_1_RMASK 0x1 +#define QIB_7322_HwErrStatus_IBCBusToSPCParityErr_1_LSB 0xE +#define QIB_7322_HwErrStatus_IBCBusToSPCParityErr_1_MSB 0xE +#define QIB_7322_HwErrStatus_IBCBusToSPCParityErr_1_RMASK 0x1  #define QIB_7322_HwErrStatus_IBCBusFromSPCParityErr_0_LSB 0xD  #define QIB_7322_HwErrStatus_IBCBusFromSPCParityErr_0_MSB 0xD  #define QIB_7322_HwErrStatus_IBCBusFromSPCParityErr_0_RMASK 0x1 -#define QIB_7322_HwErrStatus_statusValidNoEop_0_LSB 0xC -#define QIB_7322_HwErrStatus_statusValidNoEop_0_MSB 0xC -#define QIB_7322_HwErrStatus_statusValidNoEop_0_RMASK 0x1 +#define QIB_7322_HwErrStatus_statusValidNoEop_LSB 0xC +#define QIB_7322_HwErrStatus_statusValidNoEop_MSB 0xC +#define QIB_7322_HwErrStatus_statusValidNoEop_RMASK 0x1  #define QIB_7322_HwErrStatus_LATriggered_LSB 0xB  #define QIB_7322_HwErrStatus_LATriggered_MSB 0xB  #define QIB_7322_HwErrStatus_LATriggered_RMASK 0x1 @@ -850,15 +850,15 @@  #define QIB_7322_HwErrClear_IBCBusFromSPCParityErrClear_1_LSB 0xF  #define QIB_7322_HwErrClear_IBCBusFromSPCParityErrClear_1_MSB 0xF  #define QIB_7322_HwErrClear_IBCBusFromSPCParityErrClear_1_RMASK 0x1 -#define QIB_7322_HwErrClear_IBCBusToSPCparityErrClear_1_LSB 0xE -#define QIB_7322_HwErrClear_IBCBusToSPCparityErrClear_1_MSB 0xE -#define QIB_7322_HwErrClear_IBCBusToSPCparityErrClear_1_RMASK 0x1 +#define QIB_7322_HwErrClear_IBCBusToSPCParityErrClear_1_LSB 0xE +#define QIB_7322_HwErrClear_IBCBusToSPCParityErrClear_1_MSB 0xE +#define QIB_7322_HwErrClear_IBCBusToSPCParityErrClear_1_RMASK 0x1  #define QIB_7322_HwErrClear_IBCBusFromSPCParityErrClear_0_LSB 0xD  #define QIB_7322_HwErrClear_IBCBusFromSPCParityErrClear_0_MSB 0xD  #define QIB_7322_HwErrClear_IBCBusFromSPCParityErrClear_0_RMASK 0x1 -#define QIB_7322_HwErrClear_IBCBusToSPCparityErrClear_0_LSB 0xC -#define QIB_7322_HwErrClear_IBCBusToSPCparityErrClear_0_MSB 0xC -#define QIB_7322_HwErrClear_IBCBusToSPCparityErrClear_0_RMASK 0x1 +#define QIB_7322_HwErrClear_statusValidNoEopClear_LSB 0xC +#define QIB_7322_HwErrClear_statusValidNoEopClear_MSB 0xC +#define QIB_7322_HwErrClear_statusValidNoEopClear_RMASK 0x1  #define QIB_7322_HwErrClear_LATriggeredClear_LSB 0xB  #define QIB_7322_HwErrClear_LATriggeredClear_MSB 0xB  #define QIB_7322_HwErrClear_LATriggeredClear_RMASK 0x1 @@ -880,15 +880,15 @@  #define QIB_7322_HwDiagCtrl_ForceIBCBusFromSPCParityErr_1_LSB 0xF  #define QIB_7322_HwDiagCtrl_ForceIBCBusFromSPCParityErr_1_MSB 0xF  #define QIB_7322_HwDiagCtrl_ForceIBCBusFromSPCParityErr_1_RMASK 0x1 -#define QIB_7322_HwDiagCtrl_ForcestatusValidNoEop_1_LSB 0xE -#define QIB_7322_HwDiagCtrl_ForcestatusValidNoEop_1_MSB 0xE -#define QIB_7322_HwDiagCtrl_ForcestatusValidNoEop_1_RMASK 0x1 +#define QIB_7322_HwDiagCtrl_ForceIBCBusToSPCParityErr_1_LSB 0xE +#define QIB_7322_HwDiagCtrl_ForceIBCBusToSPCParityErr_1_MSB 0xE +#define QIB_7322_HwDiagCtrl_ForceIBCBusToSPCParityErr_1_RMASK 0x1  #define QIB_7322_HwDiagCtrl_ForceIBCBusFromSPCParityErr_0_LSB 0xD  #define QIB_7322_HwDiagCtrl_ForceIBCBusFromSPCParityErr_0_MSB 0xD  #define QIB_7322_HwDiagCtrl_ForceIBCBusFromSPCParityErr_0_RMASK 0x1 -#define QIB_7322_HwDiagCtrl_ForcestatusValidNoEop_0_LSB 0xC -#define QIB_7322_HwDiagCtrl_ForcestatusValidNoEop_0_MSB 0xC -#define QIB_7322_HwDiagCtrl_ForcestatusValidNoEop_0_RMASK 0x1 +#define QIB_7322_HwDiagCtrl_ForceIBCBusToSPCParityErr_0_LSB 0xC +#define QIB_7322_HwDiagCtrl_ForceIBCBusToSPCParityErr_0_MSB 0xC +#define QIB_7322_HwDiagCtrl_ForceIBCBusToSPCParityErr_0_RMASK 0x1  #define QIB_7322_EXTStatus_OFFS 0xC0  #define QIB_7322_EXTStatus_DEF 0x000000000000X000 diff --git a/drivers/infiniband/hw/qib/qib_diag.c b/drivers/infiniband/hw/qib/qib_diag.c index ca98dd52375..05dcf0d9a7d 100644 --- a/drivers/infiniband/hw/qib/qib_diag.c +++ b/drivers/infiniband/hw/qib/qib_diag.c @@ -233,6 +233,7 @@ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,  	u32 __iomem *krb32 = (u32 __iomem *)dd->kregbase;  	u32 __iomem *map = NULL;  	u32 cnt = 0; +	u32 tot4k, offs4k;  	/* First, simplest case, offset is within the first map. */  	kreglen = (dd->kregend - dd->kregbase) * sizeof(u64); @@ -250,7 +251,8 @@ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,  	if (dd->userbase) {  		/* If user regs mapped, they are after send, so set limit. */  		u32 ulim = (dd->cfgctxts * dd->ureg_align) + dd->uregbase; -		snd_lim = dd->uregbase; +		if (!dd->piovl15base) +			snd_lim = dd->uregbase;  		krb32 = (u32 __iomem *)dd->userbase;  		if (offset >= dd->uregbase && offset < ulim) {  			map = krb32 + (offset - dd->uregbase) / sizeof(u32); @@ -277,14 +279,14 @@ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,  	/* If 4k buffers exist, account for them by bumping  	 * appropriate limit.  	 */ +	tot4k = dd->piobcnt4k * dd->align4k; +	offs4k = dd->piobufbase >> 32;  	if (dd->piobcnt4k) { -		u32 tot4k = dd->piobcnt4k * dd->align4k; -		u32 offs4k = dd->piobufbase >> 32;  		if (snd_bottom > offs4k)  			snd_bottom = offs4k;  		else {  			/* 4k above 2k. Bump snd_lim, if needed*/ -			if (!dd->userbase) +			if (!dd->userbase || dd->piovl15base)  				snd_lim = offs4k + tot4k;  		}  	} @@ -298,6 +300,15 @@ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,  		cnt = snd_lim - offset;  	} +	if (!map && offs4k && dd->piovl15base) { +		snd_lim = offs4k + tot4k + 2 * dd->align4k; +		if (offset >= (offs4k + tot4k) && offset < snd_lim) { +			map = (u32 __iomem *)dd->piovl15base + +				((offset - (offs4k + tot4k)) / sizeof(u32)); +			cnt = snd_lim - offset; +		} +	} +  mapped:  	if (cntp)  		*cntp = cnt; diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 1eadadc13da..a5e29dbb953 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -1355,8 +1355,7 @@ static int qib_6120_bringup_serdes(struct qib_pportdata *ppd)  	hwstat = qib_read_kreg64(dd, kr_hwerrstatus);  	if (hwstat) {  		/* should just have PLL, clear all set, in an case */ -		if (hwstat & ~QLOGIC_IB_HWE_SERDESPLLFAILED) -			qib_write_kreg(dd, kr_hwerrclear, hwstat); +		qib_write_kreg(dd, kr_hwerrclear, hwstat);  		qib_write_kreg(dd, kr_errclear, ERR_MASK(HardwareErr));  	} diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 503992d9c5c..5eedf83e2c3 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -543,7 +543,7 @@ struct vendor_txdds_ent {  static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *);  #define TXDDS_TABLE_SZ 16 /* number of entries per speed in onchip table */ -#define TXDDS_EXTRA_SZ 11 /* number of extra tx settings entries */ +#define TXDDS_EXTRA_SZ 13 /* number of extra tx settings entries */  #define SERDES_CHANS 4 /* yes, it's obvious, but one less magic number */  #define H1_FORCE_VAL 8 @@ -1100,9 +1100,9 @@ static const struct qib_hwerror_msgs qib_7322_hwerror_msgs[] = {  	HWE_AUTO_P(SDmaMemReadErr, 1),  	HWE_AUTO_P(SDmaMemReadErr, 0),  	HWE_AUTO_P(IBCBusFromSPCParityErr, 1), +	HWE_AUTO_P(IBCBusToSPCParityErr, 1),  	HWE_AUTO_P(IBCBusFromSPCParityErr, 0), -	HWE_AUTO_P(statusValidNoEop, 1), -	HWE_AUTO_P(statusValidNoEop, 0), +	HWE_AUTO(statusValidNoEop),  	HWE_AUTO(LATriggered),  	{ .mask = 0 }  }; @@ -4763,6 +4763,8 @@ static void qib_7322_mini_pcs_reset(struct qib_pportdata *ppd)  		SYM_MASK(IBPCSConfig_0, tx_rx_reset);  	val = qib_read_kreg_port(ppd, krp_ib_pcsconfig); +	qib_write_kreg(dd, kr_hwerrmask, +		       dd->cspec->hwerrmask & ~HWE_MASK(statusValidNoEop));  	qib_write_kreg_port(ppd, krp_ibcctrl_a,  			    ppd->cpspec->ibcctrl_a &  			    ~SYM_MASK(IBCCtrlA_0, IBLinkEn)); @@ -4772,6 +4774,9 @@ static void qib_7322_mini_pcs_reset(struct qib_pportdata *ppd)  	qib_write_kreg_port(ppd, krp_ib_pcsconfig, val & ~reset_bits);  	qib_write_kreg_port(ppd, krp_ibcctrl_a, ppd->cpspec->ibcctrl_a);  	qib_write_kreg(dd, kr_scratch, 0ULL); +	qib_write_kreg(dd, kr_hwerrclear, +		       SYM_MASK(HwErrClear, statusValidNoEopClear)); +	qib_write_kreg(dd, kr_hwerrmask, dd->cspec->hwerrmask);  }  /* @@ -5624,6 +5629,8 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change)  			if (ppd->port != port || !ppd->link_speed_supported)  				continue;  			ppd->cpspec->no_eep = val; +			if (seth1) +				ppd->cpspec->h1_val = h1;  			/* now change the IBC and serdes, overriding generic */  			init_txdds_table(ppd, 1);  			any++; @@ -6064,9 +6071,9 @@ static int qib_init_7322_variables(struct qib_devdata *dd)  		 * the "cable info" setup here.  Can be overridden  		 * in adapter-specific routines.  		 */ -		if (!(ppd->dd->flags & QIB_HAS_QSFP)) { -			if (!IS_QMH(ppd->dd) && !IS_QME(ppd->dd)) -				qib_devinfo(ppd->dd->pcidev, "IB%u:%u: " +		if (!(dd->flags & QIB_HAS_QSFP)) { +			if (!IS_QMH(dd) && !IS_QME(dd)) +				qib_devinfo(dd->pcidev, "IB%u:%u: "  					    "Unknown mezzanine card type\n",  					    dd->unit, ppd->port);  			cp->h1_val = IS_QMH(dd) ? H1_FORCE_QMH : H1_FORCE_QME; @@ -6119,9 +6126,25 @@ static int qib_init_7322_variables(struct qib_devdata *dd)  	qib_set_ctxtcnt(dd);  	if (qib_wc_pat) { -		ret = init_chip_wc_pat(dd, NUM_VL15_BUFS * dd->align4k); +		resource_size_t vl15off; +		/* +		 * We do not set WC on the VL15 buffers to avoid +		 * a rare problem with unaligned writes from +		 * interrupt-flushed store buffers, so we need +		 * to map those separately here.  We can't solve +		 * this for the rarely used mtrr case. +		 */ +		ret = init_chip_wc_pat(dd, 0);  		if (ret)  			goto bail; + +		/* vl15 buffers start just after the 4k buffers */ +		vl15off = dd->physaddr + (dd->piobufbase >> 32) + +			dd->piobcnt4k * dd->align4k; +		dd->piovl15base	= ioremap_nocache(vl15off, +						  NUM_VL15_BUFS * dd->align4k); +		if (!dd->piovl15base) +			goto bail;  	}  	qib_7322_set_baseaddrs(dd); /* set chip access pointers now */ @@ -6932,6 +6955,8 @@ static const struct txdds_ent txdds_extra_sdr[TXDDS_EXTRA_SZ] = {  	{  0, 0, 0, 11 },	/* QME7342 backplane settings */  	{  0, 0, 0, 11 },	/* QME7342 backplane settings */  	{  0, 0, 0, 11 },	/* QME7342 backplane settings */ +	{  0, 0, 0,  3 },	/* QMH7342 backplane settings */ +	{  0, 0, 0,  4 },	/* QMH7342 backplane settings */  };  static const struct txdds_ent txdds_extra_ddr[TXDDS_EXTRA_SZ] = { @@ -6947,6 +6972,8 @@ static const struct txdds_ent txdds_extra_ddr[TXDDS_EXTRA_SZ] = {  	{  0, 0, 0, 13 },	/* QME7342 backplane settings */  	{  0, 0, 0, 13 },	/* QME7342 backplane settings */  	{  0, 0, 0, 13 },	/* QME7342 backplane settings */ +	{  0, 0, 0,  9 },	/* QMH7342 backplane settings */ +	{  0, 0, 0, 10 },	/* QMH7342 backplane settings */  };  static const struct txdds_ent txdds_extra_qdr[TXDDS_EXTRA_SZ] = { @@ -6962,6 +6989,8 @@ static const struct txdds_ent txdds_extra_qdr[TXDDS_EXTRA_SZ] = {  	{  0, 1, 12,  6 },	/* QME7342 backplane setting */  	{  0, 1, 12,  7 },	/* QME7342 backplane setting */  	{  0, 1, 12,  8 },	/* QME7342 backplane setting */ +	{  0, 1,  0, 10 },	/* QMH7342 backplane settings */ +	{  0, 1,  0, 12 },	/* QMH7342 backplane settings */  };  static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds, diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 9b40f345ac3..a873dd596e8 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -1059,7 +1059,7 @@ static int __init qlogic_ib_init(void)  		goto bail_dev;  	} -	qib_cq_wq = create_workqueue("qib_cq"); +	qib_cq_wq = create_singlethread_workqueue("qib_cq");  	if (!qib_cq_wq) {  		ret = -ENOMEM;  		goto bail_wq; @@ -1289,8 +1289,18 @@ static int __devinit qib_init_one(struct pci_dev *pdev,  	if (qib_mini_init || initfail || ret) {  		qib_stop_timers(dd); +		flush_scheduled_work();  		for (pidx = 0; pidx < dd->num_pports; ++pidx)  			dd->f_quiet_serdes(dd->pport + pidx); +		if (qib_mini_init) +			goto bail; +		if (!j) { +			(void) qibfs_remove(dd); +			qib_device_remove(dd); +		} +		if (!ret) +			qib_unregister_ib_device(dd); +		qib_postinit_cleanup(dd);  		if (initfail)  			ret = initfail;  		goto bail; @@ -1472,6 +1482,9 @@ int qib_setup_eagerbufs(struct qib_ctxtdata *rcd)  		dma_addr_t pa = rcd->rcvegrbuf_phys[chunk];  		unsigned i; +		/* clear for security and sanity on each use */ +		memset(rcd->rcvegrbuf[chunk], 0, size); +  		for (i = 0; e < egrcnt && i < egrperchunk; e++, i++) {  			dd->f_put_tid(dd, e + egroff +  					  (u64 __iomem *) @@ -1499,6 +1512,12 @@ bail:  	return -ENOMEM;  } +/* + * Note: Changes to this routine should be mirrored + * for the diagnostics routine qib_remap_ioaddr32(). + * There is also related code for VL15 buffers in qib_init_7322_variables(). + * The teardown code that unmaps is in qib_pcie_ddcleanup() + */  int init_chip_wc_pat(struct qib_devdata *dd, u32 vl15buflen)  {  	u64 __iomem *qib_kregbase = NULL; diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index c926bf4541d..7fa6e559263 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -179,6 +179,8 @@ void qib_pcie_ddcleanup(struct qib_devdata *dd)  		iounmap(dd->piobase);  	if (dd->userbase)  		iounmap(dd->userbase); +	if (dd->piovl15base) +		iounmap(dd->piovl15base);  	pci_disable_device(dd->pcidev);  	pci_release_regions(dd->pcidev); diff --git a/drivers/infiniband/hw/qib/qib_sd7220.c b/drivers/infiniband/hw/qib/qib_sd7220.c index 0aeed0e74cb..e9f9f8bc320 100644 --- a/drivers/infiniband/hw/qib/qib_sd7220.c +++ b/drivers/infiniband/hw/qib/qib_sd7220.c @@ -1,5 +1,6 @@  /* - * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved. + * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation. + * All rights reserved.   * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.   *   * This software is available to you under a choice of one of two @@ -37,10 +38,14 @@  #include <linux/pci.h>  #include <linux/delay.h> +#include <linux/firmware.h>  #include "qib.h"  #include "qib_7220.h" +#define SD7220_FW_NAME "qlogic/sd7220.fw" +MODULE_FIRMWARE(SD7220_FW_NAME); +  /*   * Same as in qib_iba7220.c, but just the registers needed here.   * Could move whole set to qib_7220.h, but decided better to keep @@ -102,6 +107,10 @@ static int qib_internal_presets(struct qib_devdata *dd);  /* Tweak the register (CMUCTRL5) that contains the TRIMSELF controls */  static int qib_sd_trimself(struct qib_devdata *dd, int val);  static int epb_access(struct qib_devdata *dd, int sdnum, int claim); +static int qib_sd7220_ib_load(struct qib_devdata *dd, +			      const struct firmware *fw); +static int qib_sd7220_ib_vfy(struct qib_devdata *dd, +			     const struct firmware *fw);  /*   * Below keeps track of whether the "once per power-on" initialization has @@ -110,10 +119,13 @@ static int epb_access(struct qib_devdata *dd, int sdnum, int claim);   * state of the reset "pin", is no longer valid. Instead, we check for the   * actual uC code having been loaded.   */ -static int qib_ibsd_ucode_loaded(struct qib_pportdata *ppd) +static int qib_ibsd_ucode_loaded(struct qib_pportdata *ppd, +				 const struct firmware *fw)  {  	struct qib_devdata *dd = ppd->dd; -	if (!dd->cspec->serdes_first_init_done && (qib_sd7220_ib_vfy(dd) > 0)) + +	if (!dd->cspec->serdes_first_init_done && +	    qib_sd7220_ib_vfy(dd, fw) > 0)  		dd->cspec->serdes_first_init_done = 1;  	return dd->cspec->serdes_first_init_done;  } @@ -377,6 +389,7 @@ static void qib_sd_trimdone_monitor(struct qib_devdata *dd,   */  int qib_sd7220_init(struct qib_devdata *dd)  { +	const struct firmware *fw;  	int ret = 1; /* default to failure */  	int first_reset, was_reset; @@ -387,8 +400,15 @@ int qib_sd7220_init(struct qib_devdata *dd)  		qib_ibsd_reset(dd, 1);  		qib_sd_trimdone_monitor(dd, "Driver-reload");  	} + +	ret = request_firmware(&fw, SD7220_FW_NAME, &dd->pcidev->dev); +	if (ret) { +		qib_dev_err(dd, "Failed to load IB SERDES image\n"); +		goto done; +	} +  	/* Substitute our deduced value for was_reset */ -	ret = qib_ibsd_ucode_loaded(dd->pport); +	ret = qib_ibsd_ucode_loaded(dd->pport, fw);  	if (ret < 0)  		goto bail; @@ -437,13 +457,13 @@ int qib_sd7220_init(struct qib_devdata *dd)  		int vfy;  		int trim_done; -		ret = qib_sd7220_ib_load(dd); +		ret = qib_sd7220_ib_load(dd, fw);  		if (ret < 0) {  			qib_dev_err(dd, "Failed to load IB SERDES image\n");  			goto bail;  		} else {  			/* Loaded image, try to verify */ -			vfy = qib_sd7220_ib_vfy(dd); +			vfy = qib_sd7220_ib_vfy(dd, fw);  			if (vfy != ret) {  				qib_dev_err(dd, "SERDES PRAM VFY failed\n");  				goto bail; @@ -506,6 +526,8 @@ bail:  done:  	/* start relock timer regardless, but start at 1 second */  	set_7220_relock_poll(dd, -1); + +	release_firmware(fw);  	return ret;  } @@ -829,8 +851,8 @@ static int qib_sd7220_ram_xfer(struct qib_devdata *dd, int sdnum, u32 loc,  #define PROG_CHUNK 64 -int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum, -		       u8 *img, int len, int offset) +static int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum, +			      const u8 *img, int len, int offset)  {  	int cnt, sofar, req; @@ -840,7 +862,7 @@ int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum,  		if (req > PROG_CHUNK)  			req = PROG_CHUNK;  		cnt = qib_sd7220_ram_xfer(dd, sdnum, offset + sofar, -					  img + sofar, req, 0); +					  (u8 *)img + sofar, req, 0);  		if (cnt < req) {  			sofar = -1;  			break; @@ -853,8 +875,8 @@ int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum,  #define VFY_CHUNK 64  #define SD_PRAM_ERROR_LIMIT 42 -int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum, -			const u8 *img, int len, int offset) +static int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum, +			       const u8 *img, int len, int offset)  {  	int cnt, sofar, req, idx, errors;  	unsigned char readback[VFY_CHUNK]; @@ -881,6 +903,18 @@ int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum,  	return errors ? -errors : sofar;  } +static int +qib_sd7220_ib_load(struct qib_devdata *dd, const struct firmware *fw) +{ +	return qib_sd7220_prog_ld(dd, IB_7220_SERDES, fw->data, fw->size, 0); +} + +static int +qib_sd7220_ib_vfy(struct qib_devdata *dd, const struct firmware *fw) +{ +	return qib_sd7220_prog_vfy(dd, IB_7220_SERDES, fw->data, fw->size, 0); +} +  /*   * IRQ not set up at this point in init, so we poll.   */ diff --git a/drivers/infiniband/hw/qib/qib_sd7220_img.c b/drivers/infiniband/hw/qib/qib_sd7220_img.c deleted file mode 100644 index a1118fbd237..00000000000 --- a/drivers/infiniband/hw/qib/qib_sd7220_img.c +++ /dev/null @@ -1,1081 +0,0 @@ -/* - * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses.  You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - *     Redistribution and use in source and binary forms, with or - *     without modification, are permitted provided that the following - *     conditions are met: - * - *      - Redistributions of source code must retain the above - *        copyright notice, this list of conditions and the following - *        disclaimer. - * - *      - Redistributions in binary form must reproduce the above - *        copyright notice, this list of conditions and the following - *        disclaimer in the documentation and/or other materials - *        provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * This file contains the memory image from the vendor, to be copied into - * the IB SERDES of the IBA7220 during initialization. - * The file also includes the two functions which use this image. - */ -#include <linux/pci.h> -#include <linux/delay.h> - -#include "qib.h" -#include "qib_7220.h" - -static unsigned char qib_sd7220_ib_img[] = { -/*0000*/0x02, 0x0A, 0x29, 0x02, 0x0A, 0x87, 0xE5, 0xE6, -	0x30, 0xE6, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, -/*0010*/0x00, 0xE5, 0xE2, 0x30, 0xE4, 0x04, 0x7E, 0x01, -	0x80, 0x02, 0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x08, -/*0020*/0x53, 0xF9, 0xF7, 0xE4, 0xF5, 0xFE, 0x80, 0x08, -	0x7F, 0x0A, 0x12, 0x17, 0x31, 0x12, 0x0E, 0xA2, -/*0030*/0x75, 0xFC, 0x08, 0xE4, 0xF5, 0xFD, 0xE5, 0xE7, -	0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0x22, 0x00, -/*0040*/0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x75, -	0x51, 0x01, 0xE4, 0xF5, 0x52, 0xF5, 0x53, 0xF5, -/*0050*/0x52, 0xF5, 0x7E, 0x7F, 0x04, 0x02, 0x04, 0x38, -	0xC2, 0x36, 0x05, 0x52, 0xE5, 0x52, 0xD3, 0x94, -/*0060*/0x0C, 0x40, 0x05, 0x75, 0x52, 0x01, 0xD2, 0x36, -	0x90, 0x07, 0x0C, 0x74, 0x07, 0xF0, 0xA3, 0x74, -/*0070*/0xFF, 0xF0, 0xE4, 0xF5, 0x0C, 0xA3, 0xF0, 0x90, -	0x07, 0x14, 0xF0, 0xA3, 0xF0, 0x75, 0x0B, 0x20, -/*0080*/0xF5, 0x09, 0xE4, 0xF5, 0x08, 0xE5, 0x08, 0xD3, -	0x94, 0x30, 0x40, 0x03, 0x02, 0x04, 0x04, 0x12, -/*0090*/0x00, 0x06, 0x15, 0x0B, 0xE5, 0x08, 0x70, 0x04, -	0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x09, -/*00A0*/0x70, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, -	0xEE, 0x5F, 0x60, 0x05, 0x12, 0x18, 0x71, 0xD2, -/*00B0*/0x35, 0x53, 0xE1, 0xF7, 0xE5, 0x08, 0x45, 0x09, -	0xFF, 0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24, -/*00C0*/0x83, 0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83, -	0xEF, 0xF0, 0x85, 0xE2, 0x20, 0xE5, 0x52, 0xD3, -/*00D0*/0x94, 0x01, 0x40, 0x0D, 0x12, 0x19, 0xF3, 0xE0, -	0x54, 0xA0, 0x64, 0x40, 0x70, 0x03, 0x02, 0x03, -/*00E0*/0xFB, 0x53, 0xF9, 0xF8, 0x90, 0x94, 0x70, 0xE4, -	0xF0, 0xE0, 0xF5, 0x10, 0xAF, 0x09, 0x12, 0x1E, -/*00F0*/0xB3, 0xAF, 0x08, 0xEF, 0x44, 0x08, 0xF5, 0x82, -	0x75, 0x83, 0x80, 0xE0, 0xF5, 0x29, 0xEF, 0x44, -/*0100*/0x07, 0x12, 0x1A, 0x3C, 0xF5, 0x22, 0x54, 0x40, -	0xD3, 0x94, 0x00, 0x40, 0x1E, 0xE5, 0x29, 0x54, -/*0110*/0xF0, 0x70, 0x21, 0x12, 0x19, 0xF3, 0xE0, 0x44, -	0x80, 0xF0, 0xE5, 0x22, 0x54, 0x30, 0x65, 0x08, -/*0120*/0x70, 0x09, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xBF, -	0xF0, 0x80, 0x09, 0x12, 0x19, 0xF3, 0x74, 0x40, -/*0130*/0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12, 0x75, -	0x83, 0xAE, 0x74, 0xFF, 0xF0, 0xAF, 0x08, 0x7E, -/*0140*/0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0xE0, 0xFD, -	0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x81, -/*0150*/0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83, 0xED, -	0xF0, 0x90, 0x07, 0x0E, 0xE0, 0x04, 0xF0, 0xEF, -/*0160*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0x98, 0xE0, -	0xF5, 0x28, 0x12, 0x1A, 0x23, 0x40, 0x0C, 0x12, -/*0170*/0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12, 0x1A, 0x32, -	0x02, 0x03, 0xF6, 0xAF, 0x08, 0x7E, 0x00, 0x74, -/*0180*/0x80, 0xCD, 0xEF, 0xCD, 0x8D, 0x82, 0xF5, 0x83, -	0xE0, 0x30, 0xE0, 0x0A, 0x12, 0x19, 0xF3, 0xE0, -/*0190*/0x44, 0x20, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x19, -	0xF3, 0xE0, 0x54, 0xDF, 0xF0, 0xEE, 0x44, 0xAE, -/*01A0*/0x12, 0x1A, 0x43, 0x30, 0xE4, 0x03, 0x02, 0x03, -	0xFB, 0x74, 0x9E, 0x12, 0x1A, 0x05, 0x20, 0xE0, -/*01B0*/0x03, 0x02, 0x03, 0xFB, 0x8F, 0x82, 0x8E, 0x83, -	0xE0, 0x20, 0xE0, 0x03, 0x02, 0x03, 0xFB, 0x12, -/*01C0*/0x19, 0xF3, 0xE0, 0x44, 0x10, 0xF0, 0xE5, 0xE3, -	0x20, 0xE7, 0x08, 0xE5, 0x08, 0x12, 0x1A, 0x3A, -/*01D0*/0x44, 0x04, 0xF0, 0xAF, 0x08, 0x7E, 0x00, 0xEF, -	0x12, 0x1A, 0x3A, 0x20, 0xE2, 0x34, 0x12, 0x19, -/*01E0*/0xF3, 0xE0, 0x44, 0x08, 0xF0, 0xE5, 0xE4, 0x30, -	0xE6, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, -/*01F0*/0xE5, 0x7E, 0xC3, 0x94, 0x04, 0x50, 0x04, 0x7C, -	0x01, 0x80, 0x02, 0x7C, 0x00, 0xEC, 0x4D, 0x60, -/*0200*/0x05, 0xC2, 0x35, 0x02, 0x03, 0xFB, 0xEE, 0x44, -	0xD2, 0x12, 0x1A, 0x43, 0x44, 0x40, 0xF0, 0x02, -/*0210*/0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xF7, -	0xF0, 0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0, -/*0220*/0x54, 0xBF, 0xF0, 0x90, 0x07, 0x14, 0xE0, 0x04, -	0xF0, 0xE5, 0x7E, 0x70, 0x03, 0x75, 0x7E, 0x01, -/*0230*/0xAF, 0x08, 0x7E, 0x00, 0x12, 0x1A, 0x23, 0x40, -	0x12, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12, -/*0240*/0x19, 0xF2, 0xE0, 0x54, 0x02, 0x12, 0x1A, 0x32, -	0x02, 0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x44, -/*0250*/0x02, 0x12, 0x19, 0xF2, 0xE0, 0x54, 0xFE, 0xF0, -	0xC2, 0x35, 0xEE, 0x44, 0x8A, 0x8F, 0x82, 0xF5, -/*0260*/0x83, 0xE0, 0xF5, 0x17, 0x54, 0x8F, 0x44, 0x40, -	0xF0, 0x74, 0x90, 0xFC, 0xE5, 0x08, 0x44, 0x07, -/*0270*/0xFD, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0x54, 0x3F, -	0x90, 0x07, 0x02, 0xF0, 0xE0, 0x54, 0xC0, 0x8D, -/*0280*/0x82, 0x8C, 0x83, 0xF0, 0x74, 0x92, 0x12, 0x1A, -	0x05, 0x90, 0x07, 0x03, 0x12, 0x1A, 0x19, 0x74, -/*0290*/0x82, 0x12, 0x1A, 0x05, 0x90, 0x07, 0x04, 0x12, -	0x1A, 0x19, 0x74, 0xB4, 0x12, 0x1A, 0x05, 0x90, -/*02A0*/0x07, 0x05, 0x12, 0x1A, 0x19, 0x74, 0x94, 0xFE, -	0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A, 0xF5, -/*02B0*/0x10, 0x30, 0xE0, 0x04, 0xD2, 0x37, 0x80, 0x02, -	0xC2, 0x37, 0xE5, 0x10, 0x54, 0x7F, 0x8F, 0x82, -/*02C0*/0x8E, 0x83, 0xF0, 0x30, 0x44, 0x30, 0x12, 0x1A, -	0x03, 0x54, 0x80, 0xD3, 0x94, 0x00, 0x40, 0x04, -/*02D0*/0xD2, 0x39, 0x80, 0x02, 0xC2, 0x39, 0x8F, 0x82, -	0x8E, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0x12, 0x1A, -/*02E0*/0x03, 0x54, 0x40, 0xD3, 0x94, 0x00, 0x40, 0x04, -	0xD2, 0x3A, 0x80, 0x02, 0xC2, 0x3A, 0x8F, 0x82, -/*02F0*/0x8E, 0x83, 0xE0, 0x44, 0x40, 0xF0, 0x74, 0x92, -	0xFE, 0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A, -/*0300*/0x30, 0xE7, 0x04, 0xD2, 0x38, 0x80, 0x02, 0xC2, -	0x38, 0x8F, 0x82, 0x8E, 0x83, 0xE0, 0x54, 0x7F, -/*0310*/0xF0, 0x12, 0x1E, 0x46, 0xE4, 0xF5, 0x0A, 0x20, -	0x03, 0x02, 0x80, 0x03, 0x30, 0x43, 0x03, 0x12, -/*0320*/0x19, 0x95, 0x20, 0x02, 0x02, 0x80, 0x03, 0x30, -	0x42, 0x03, 0x12, 0x0C, 0x8F, 0x30, 0x30, 0x06, -/*0330*/0x12, 0x19, 0x95, 0x12, 0x0C, 0x8F, 0x12, 0x0D, -	0x47, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xFB, 0xF0, -/*0340*/0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40, 0x46, 0x43, -	0xE1, 0x08, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x04, -/*0350*/0xF0, 0xE5, 0xE4, 0x20, 0xE7, 0x2A, 0x12, 0x1A, -	0x12, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3, -/*0360*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, -	0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40, -/*0370*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF, -	0x5E, 0x60, 0x05, 0x12, 0x1D, 0xD7, 0x80, 0x17, -/*0380*/0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0, 0x44, -	0x08, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12, -/*0390*/0x75, 0x83, 0xD2, 0xE0, 0x54, 0xF7, 0xF0, 0x12, -	0x1E, 0x46, 0x7F, 0x08, 0x12, 0x17, 0x31, 0x74, -/*03A0*/0x8E, 0xFE, 0x12, 0x1A, 0x12, 0x8E, 0x83, 0xE0, -	0xF5, 0x10, 0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44, -/*03B0*/0x01, 0xFF, 0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07, -	0xF5, 0x82, 0xEF, 0xF0, 0xE5, 0x10, 0x54, 0xFE, -/*03C0*/0xFF, 0xED, 0x44, 0x07, 0xF5, 0x82, 0xEF, 0x12, -	0x1A, 0x11, 0x75, 0x83, 0x86, 0xE0, 0x44, 0x10, -/*03D0*/0x12, 0x1A, 0x11, 0xE0, 0x44, 0x10, 0xF0, 0x12, -	0x19, 0xF3, 0xE0, 0x54, 0xFD, 0x44, 0x01, 0xFF, -/*03E0*/0x12, 0x19, 0xF3, 0xEF, 0x12, 0x1A, 0x32, 0x30, -	0x32, 0x0C, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82, -/*03F0*/0x75, 0x83, 0x82, 0x74, 0x05, 0xF0, 0xAF, 0x0B, -	0x12, 0x18, 0xD7, 0x74, 0x10, 0x25, 0x08, 0xF5, -/*0400*/0x08, 0x02, 0x00, 0x85, 0x05, 0x09, 0xE5, 0x09, -	0xD3, 0x94, 0x07, 0x50, 0x03, 0x02, 0x00, 0x82, -/*0410*/0xE5, 0x7E, 0xD3, 0x94, 0x00, 0x40, 0x04, 0x7F, -	0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x7E, 0xC3, -/*0420*/0x94, 0xFA, 0x50, 0x04, 0x7E, 0x01, 0x80, 0x02, -	0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x02, 0x05, 0x7E, -/*0430*/0x30, 0x35, 0x0B, 0x43, 0xE1, 0x01, 0x7F, 0x09, -	0x12, 0x17, 0x31, 0x02, 0x00, 0x58, 0x53, 0xE1, -/*0440*/0xFE, 0x02, 0x00, 0x58, 0x8E, 0x6A, 0x8F, 0x6B, -	0x8C, 0x6C, 0x8D, 0x6D, 0x75, 0x6E, 0x01, 0x75, -/*0450*/0x6F, 0x01, 0x75, 0x70, 0x01, 0xE4, 0xF5, 0x73, -	0xF5, 0x74, 0xF5, 0x75, 0x90, 0x07, 0x2F, 0xF0, -/*0460*/0xF5, 0x3C, 0xF5, 0x3E, 0xF5, 0x46, 0xF5, 0x47, -	0xF5, 0x3D, 0xF5, 0x3F, 0xF5, 0x6F, 0xE5, 0x6F, -/*0470*/0x70, 0x0F, 0xE5, 0x6B, 0x45, 0x6A, 0x12, 0x07, -	0x2A, 0x75, 0x83, 0x80, 0x74, 0x3A, 0xF0, 0x80, -/*0480*/0x09, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74, -	0x1A, 0xF0, 0xE4, 0xF5, 0x6E, 0xC3, 0x74, 0x3F, -/*0490*/0x95, 0x6E, 0xFF, 0x12, 0x08, 0x65, 0x75, 0x83, -	0x82, 0xEF, 0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x08, -/*04A0*/0xC6, 0xE5, 0x33, 0xF0, 0x12, 0x08, 0xFA, 0x12, -	0x08, 0xB1, 0x40, 0xE1, 0xE5, 0x6F, 0x70, 0x0B, -/*04B0*/0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74, 0x36, -	0xF0, 0x80, 0x09, 0x12, 0x07, 0x2A, 0x75, 0x83, -/*04C0*/0x80, 0x74, 0x16, 0xF0, 0x75, 0x6E, 0x01, 0x12, -	0x07, 0x2A, 0x75, 0x83, 0xB4, 0xE5, 0x6E, 0xF0, -/*04D0*/0x12, 0x1A, 0x4D, 0x74, 0x3F, 0x25, 0x6E, 0xF5, -	0x82, 0xE4, 0x34, 0x00, 0xF5, 0x83, 0xE5, 0x33, -/*04E0*/0xF0, 0x74, 0xBF, 0x25, 0x6E, 0xF5, 0x82, 0xE4, -	0x34, 0x00, 0x12, 0x08, 0xB1, 0x40, 0xD8, 0xE4, -/*04F0*/0xF5, 0x70, 0xF5, 0x46, 0xF5, 0x47, 0xF5, 0x6E, -	0x12, 0x08, 0xFA, 0xF5, 0x83, 0xE0, 0xFE, 0x12, -/*0500*/0x08, 0xC6, 0xE0, 0x7C, 0x00, 0x24, 0x00, 0xFF, -	0xEC, 0x3E, 0xFE, 0xAD, 0x3B, 0xD3, 0xEF, 0x9D, -/*0510*/0xEE, 0x9C, 0x50, 0x04, 0x7B, 0x01, 0x80, 0x02, -	0x7B, 0x00, 0xE5, 0x70, 0x70, 0x04, 0x7A, 0x01, -/*0520*/0x80, 0x02, 0x7A, 0x00, 0xEB, 0x5A, 0x60, 0x06, -	0x85, 0x6E, 0x46, 0x75, 0x70, 0x01, 0xD3, 0xEF, -/*0530*/0x9D, 0xEE, 0x9C, 0x50, 0x04, 0x7F, 0x01, 0x80, -	0x02, 0x7F, 0x00, 0xE5, 0x70, 0xB4, 0x01, 0x04, -/*0540*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF, 0x5E, -	0x60, 0x03, 0x85, 0x6E, 0x47, 0x05, 0x6E, 0xE5, -/*0550*/0x6E, 0x64, 0x7F, 0x70, 0xA3, 0xE5, 0x46, 0x60, -	0x05, 0xE5, 0x47, 0xB4, 0x7E, 0x03, 0x85, 0x46, -/*0560*/0x47, 0xE5, 0x6F, 0x70, 0x08, 0x85, 0x46, 0x76, -	0x85, 0x47, 0x77, 0x80, 0x0E, 0xC3, 0x74, 0x7F, -/*0570*/0x95, 0x46, 0xF5, 0x78, 0xC3, 0x74, 0x7F, 0x95, -	0x47, 0xF5, 0x79, 0xE5, 0x6F, 0x70, 0x37, 0xE5, -/*0580*/0x46, 0x65, 0x47, 0x70, 0x0C, 0x75, 0x73, 0x01, -	0x75, 0x74, 0x01, 0xF5, 0x3C, 0xF5, 0x3D, 0x80, -/*0590*/0x35, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5, 0x47, 0x95, -	0x46, 0xF5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25, -/*05A0*/0x46, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05, -	0xE4, 0xF5, 0x3D, 0x80, 0x40, 0xC3, 0x74, 0x3F, -/*05B0*/0x95, 0x72, 0xF5, 0x3D, 0x80, 0x37, 0xE5, 0x46, -	0x65, 0x47, 0x70, 0x0F, 0x75, 0x73, 0x01, 0x75, -/*05C0*/0x75, 0x01, 0xF5, 0x3E, 0xF5, 0x3F, 0x75, 0x4E, -	0x01, 0x80, 0x22, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5, -/*05D0*/0x47, 0x95, 0x46, 0xF5, 0x3E, 0xC3, 0x13, 0xF5, -	0x71, 0x25, 0x46, 0xF5, 0x72, 0xD3, 0x94, 0x3F, -/*05E0*/0x50, 0x05, 0xE4, 0xF5, 0x3F, 0x80, 0x06, 0xE5, -	0x72, 0x24, 0xC1, 0xF5, 0x3F, 0x05, 0x6F, 0xE5, -/*05F0*/0x6F, 0xC3, 0x94, 0x02, 0x50, 0x03, 0x02, 0x04, -	0x6E, 0xE5, 0x6D, 0x45, 0x6C, 0x70, 0x02, 0x80, -/*0600*/0x04, 0xE5, 0x74, 0x45, 0x75, 0x90, 0x07, 0x2F, -	0xF0, 0x7F, 0x01, 0xE5, 0x3E, 0x60, 0x04, 0xE5, -/*0610*/0x3C, 0x70, 0x14, 0xE4, 0xF5, 0x3C, 0xF5, 0x3D, -	0xF5, 0x3E, 0xF5, 0x3F, 0x12, 0x08, 0xD2, 0x70, -/*0620*/0x04, 0xF0, 0x02, 0x06, 0xA4, 0x80, 0x7A, 0xE5, -	0x3C, 0xC3, 0x95, 0x3E, 0x40, 0x07, 0xE5, 0x3C, -/*0630*/0x95, 0x3E, 0xFF, 0x80, 0x06, 0xC3, 0xE5, 0x3E, -	0x95, 0x3C, 0xFF, 0xE5, 0x76, 0xD3, 0x95, 0x79, -/*0640*/0x40, 0x05, 0x85, 0x76, 0x7A, 0x80, 0x03, 0x85, -	0x79, 0x7A, 0xE5, 0x77, 0xC3, 0x95, 0x78, 0x50, -/*0650*/0x05, 0x85, 0x77, 0x7B, 0x80, 0x03, 0x85, 0x78, -	0x7B, 0xE5, 0x7B, 0xD3, 0x95, 0x7A, 0x40, 0x30, -/*0660*/0xE5, 0x7B, 0x95, 0x7A, 0xF5, 0x3C, 0xF5, 0x3E, -	0xC3, 0xE5, 0x7B, 0x95, 0x7A, 0x90, 0x07, 0x19, -/*0670*/0xF0, 0xE5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25, -	0x7A, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05, -/*0680*/0xE4, 0xF5, 0x3D, 0x80, 0x1F, 0xC3, 0x74, 0x3F, -	0x95, 0x72, 0xF5, 0x3D, 0xF5, 0x3F, 0x80, 0x14, -/*0690*/0xE4, 0xF5, 0x3C, 0xF5, 0x3E, 0x90, 0x07, 0x19, -	0xF0, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80, -/*06A0*/0x03, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x65, 0x75, -	0x83, 0xD0, 0xE0, 0x54, 0x0F, 0xFE, 0xAD, 0x3C, -/*06B0*/0x70, 0x02, 0x7E, 0x07, 0xBE, 0x0F, 0x02, 0x7E, -	0x80, 0xEE, 0xFB, 0xEF, 0xD3, 0x9B, 0x74, 0x80, -/*06C0*/0xF8, 0x98, 0x40, 0x1F, 0xE4, 0xF5, 0x3C, 0xF5, -	0x3E, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80, -/*06D0*/0x12, 0x74, 0x01, 0xF0, 0xE5, 0x08, 0xFB, 0xEB, -	0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xD2, 0xE0, -/*06E0*/0x44, 0x10, 0xF0, 0xE5, 0x08, 0xFB, 0xEB, 0x44, -	0x09, 0xF5, 0x82, 0x75, 0x83, 0x9E, 0xED, 0xF0, -/*06F0*/0xEB, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xCA, -	0xED, 0xF0, 0x12, 0x08, 0x65, 0x75, 0x83, 0xCC, -/*0700*/0xEF, 0xF0, 0x22, 0xE5, 0x08, 0x44, 0x07, 0xF5, -	0x82, 0x75, 0x83, 0xBC, 0xE0, 0x54, 0xF0, 0xF0, -/*0710*/0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, -	0xBE, 0xE0, 0x54, 0xF0, 0xF0, 0xE5, 0x08, 0x44, -/*0720*/0x07, 0xF5, 0x82, 0x75, 0x83, 0xC0, 0xE0, 0x54, -	0xF0, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82, -/*0730*/0x22, 0xF0, 0x90, 0x07, 0x28, 0xE0, 0xFE, 0xA3, -	0xE0, 0xF5, 0x82, 0x8E, 0x83, 0x22, 0x85, 0x42, -/*0740*/0x42, 0x85, 0x41, 0x41, 0x85, 0x40, 0x40, 0x74, -	0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E, 0xF5, -/*0750*/0x83, 0xE5, 0x42, 0xF0, 0x74, 0xE0, 0x2F, 0xF5, -	0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xE5, -/*0760*/0x42, 0x29, 0xFD, 0xE4, 0x33, 0xFC, 0xE5, 0x3C, -	0xC3, 0x9D, 0xEC, 0x64, 0x80, 0xF8, 0x74, 0x80, -/*0770*/0x98, 0x22, 0xF5, 0x83, 0xE0, 0x90, 0x07, 0x22, -	0x54, 0x1F, 0xFD, 0xE0, 0xFA, 0xA3, 0xE0, 0xF5, -/*0780*/0x82, 0x8A, 0x83, 0xED, 0xF0, 0x22, 0x90, 0x07, -	0x22, 0xE0, 0xFC, 0xA3, 0xE0, 0xF5, 0x82, 0x8C, -/*0790*/0x83, 0x22, 0x90, 0x07, 0x24, 0xFF, 0xED, 0x44, -	0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22, 0x85, -/*07A0*/0x38, 0x38, 0x85, 0x39, 0x39, 0x85, 0x3A, 0x3A, -	0x74, 0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E, -/*07B0*/0xF5, 0x83, 0x22, 0x90, 0x07, 0x26, 0xFF, 0xED, -	0x44, 0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22, -/*07C0*/0xF0, 0x74, 0xA0, 0x2F, 0xF5, 0x82, 0x74, 0x02, -	0x3E, 0xF5, 0x83, 0x22, 0x74, 0xC0, 0x25, 0x11, -/*07D0*/0xF5, 0x82, 0xE4, 0x34, 0x01, 0xF5, 0x83, 0x22, -	0x74, 0x00, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34, -/*07E0*/0x02, 0xF5, 0x83, 0x22, 0x74, 0x60, 0x25, 0x11, -	0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22, -/*07F0*/0x74, 0x80, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34, -	0x03, 0xF5, 0x83, 0x22, 0x74, 0xE0, 0x25, 0x11, -/*0800*/0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22, -	0x74, 0x40, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34, -/*0810*/0x06, 0xF5, 0x83, 0x22, 0x74, 0x80, 0x2F, 0xF5, -	0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xAF, -/*0820*/0x08, 0x7E, 0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82, -	0x22, 0xF5, 0x83, 0xE5, 0x82, 0x44, 0x07, 0xF5, -/*0830*/0x82, 0xE5, 0x40, 0xF0, 0x22, 0x74, 0x40, 0x25, -	0x11, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83, -/*0840*/0x22, 0x74, 0xC0, 0x25, 0x11, 0xF5, 0x82, 0xE4, -	0x34, 0x03, 0xF5, 0x83, 0x22, 0x74, 0x00, 0x25, -/*0850*/0x11, 0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83, -	0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4, -/*0860*/0x34, 0x06, 0xF5, 0x83, 0x22, 0xE5, 0x08, 0xFD, -	0xED, 0x44, 0x07, 0xF5, 0x82, 0x22, 0xE5, 0x41, -/*0870*/0xF0, 0xE5, 0x65, 0x64, 0x01, 0x45, 0x64, 0x22, -	0x7E, 0x00, 0xFB, 0x7A, 0x00, 0xFD, 0x7C, 0x00, -/*0880*/0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4, -	0x34, 0x02, 0x22, 0x74, 0xA0, 0x25, 0x11, 0xF5, -/*0890*/0x82, 0xE4, 0x34, 0x03, 0x22, 0x85, 0x3E, 0x42, -	0x85, 0x3F, 0x41, 0x8F, 0x40, 0x22, 0x85, 0x3C, -/*08A0*/0x42, 0x85, 0x3D, 0x41, 0x8F, 0x40, 0x22, 0x75, -	0x45, 0x3F, 0x90, 0x07, 0x20, 0xE4, 0xF0, 0xA3, -/*08B0*/0x22, 0xF5, 0x83, 0xE5, 0x32, 0xF0, 0x05, 0x6E, -	0xE5, 0x6E, 0xC3, 0x94, 0x40, 0x22, 0xF0, 0xE5, -/*08C0*/0x08, 0x44, 0x06, 0xF5, 0x82, 0x22, 0x74, 0x00, -	0x25, 0x6E, 0xF5, 0x82, 0xE4, 0x34, 0x00, 0xF5, -/*08D0*/0x83, 0x22, 0xE5, 0x6D, 0x45, 0x6C, 0x90, 0x07, -	0x2F, 0x22, 0xE4, 0xF9, 0xE5, 0x3C, 0xD3, 0x95, -/*08E0*/0x3E, 0x22, 0x74, 0x80, 0x2E, 0xF5, 0x82, 0xE4, -	0x34, 0x02, 0xF5, 0x83, 0xE0, 0x22, 0x74, 0xA0, -/*08F0*/0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83, -	0xE0, 0x22, 0x74, 0x80, 0x25, 0x6E, 0xF5, 0x82, -/*0900*/0xE4, 0x34, 0x00, 0x22, 0x25, 0x42, 0xFD, 0xE4, -	0x33, 0xFC, 0x22, 0x85, 0x42, 0x42, 0x85, 0x41, -/*0910*/0x41, 0x85, 0x40, 0x40, 0x22, 0xED, 0x4C, 0x60, -	0x03, 0x02, 0x09, 0xE5, 0xEF, 0x4E, 0x70, 0x37, -/*0920*/0x90, 0x07, 0x26, 0x12, 0x07, 0x89, 0xE0, 0xFD, -	0x12, 0x07, 0xCC, 0xED, 0xF0, 0x90, 0x07, 0x28, -/*0930*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xD8, -	0xED, 0xF0, 0x12, 0x07, 0x86, 0xE0, 0x54, 0x1F, -/*0940*/0xFD, 0x12, 0x08, 0x81, 0xF5, 0x83, 0xED, 0xF0, -	0x90, 0x07, 0x24, 0x12, 0x07, 0x89, 0xE0, 0x54, -/*0950*/0x1F, 0xFD, 0x12, 0x08, 0x35, 0xED, 0xF0, 0xEF, -	0x64, 0x04, 0x4E, 0x70, 0x37, 0x90, 0x07, 0x26, -/*0960*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xE4, -	0xED, 0xF0, 0x90, 0x07, 0x28, 0x12, 0x07, 0x89, -/*0970*/0xE0, 0xFD, 0x12, 0x07, 0xF0, 0xED, 0xF0, 0x12, -	0x07, 0x86, 0xE0, 0x54, 0x1F, 0xFD, 0x12, 0x08, -/*0980*/0x8B, 0xF5, 0x83, 0xED, 0xF0, 0x90, 0x07, 0x24, -	0x12, 0x07, 0x89, 0xE0, 0x54, 0x1F, 0xFD, 0x12, -/*0990*/0x08, 0x41, 0xED, 0xF0, 0xEF, 0x64, 0x01, 0x4E, -	0x70, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, -/*09A0*/0xEF, 0x64, 0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01, -	0x80, 0x02, 0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x78, -/*09B0*/0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE0, 0xFF, -	0x12, 0x07, 0xFC, 0xEF, 0x12, 0x07, 0x31, 0xE0, -/*09C0*/0xFF, 0x12, 0x08, 0x08, 0xEF, 0xF0, 0x90, 0x07, -	0x22, 0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF, -/*09D0*/0x12, 0x08, 0x4D, 0xEF, 0xF0, 0x90, 0x07, 0x24, -	0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF, 0x12, -/*09E0*/0x08, 0x59, 0xEF, 0xF0, 0x22, 0x12, 0x07, 0xCC, -	0xE4, 0xF0, 0x12, 0x07, 0xD8, 0xE4, 0xF0, 0x12, -/*09F0*/0x08, 0x81, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08, -	0x35, 0x74, 0x14, 0xF0, 0x12, 0x07, 0xE4, 0xE4, -/*0A00*/0xF0, 0x12, 0x07, 0xF0, 0xE4, 0xF0, 0x12, 0x08, -	0x8B, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08, 0x41, -/*0A10*/0x74, 0x14, 0xF0, 0x12, 0x07, 0xFC, 0xE4, 0xF0, -	0x12, 0x08, 0x08, 0xE4, 0xF0, 0x12, 0x08, 0x4D, -/*0A20*/0xE4, 0xF0, 0x12, 0x08, 0x59, 0x74, 0x14, 0xF0, -	0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFC, 0x10, 0xE4, -/*0A30*/0xF5, 0xFD, 0x75, 0xFE, 0x30, 0xF5, 0xFF, 0xE5, -	0xE7, 0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0xE5, -/*0A40*/0xE6, 0x20, 0xE7, 0x0B, 0x78, 0xFF, 0xE4, 0xF6, -	0xD8, 0xFD, 0x53, 0xE6, 0xFE, 0x80, 0x09, 0x78, -/*0A50*/0x08, 0xE4, 0xF6, 0xD8, 0xFD, 0x53, 0xE6, 0xFE, -	0x75, 0x81, 0x80, 0xE4, 0xF5, 0xA8, 0xD2, 0xA8, -/*0A60*/0xC2, 0xA9, 0xD2, 0xAF, 0xE5, 0xE2, 0x20, 0xE5, -	0x05, 0x20, 0xE6, 0x02, 0x80, 0x03, 0x43, 0xE1, -/*0A70*/0x02, 0xE5, 0xE2, 0x20, 0xE0, 0x0E, 0x90, 0x00, -	0x00, 0x7F, 0x00, 0x7E, 0x08, 0xE4, 0xF0, 0xA3, -/*0A80*/0xDF, 0xFC, 0xDE, 0xFA, 0x02, 0x0A, 0xDB, 0x43, -	0xFA, 0x01, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83, -/*0A90*/0xC0, 0x82, 0xC0, 0xD0, 0x12, 0x1C, 0xE7, 0xD0, -	0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0, -/*0AA0*/0xE0, 0x53, 0xFA, 0xFE, 0x32, 0x02, 0x1B, 0x55, -	0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0xF6, -/*0AB0*/0x08, 0xDF, 0xF9, 0x80, 0x29, 0xE4, 0x93, 0xA3, -	0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, 0xC3, 0x33, -/*0AC0*/0xC4, 0x54, 0x0F, 0x44, 0x20, 0xC8, 0x83, 0x40, -	0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, 0xF6, 0xDF, -/*0AD0*/0xE4, 0x80, 0x0B, 0x01, 0x02, 0x04, 0x08, 0x10, -	0x20, 0x40, 0x80, 0x90, 0x00, 0x3F, 0xE4, 0x7E, -/*0AE0*/0x01, 0x93, 0x60, 0xC1, 0xA3, 0xFF, 0x54, 0x3F, -	0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, 0xE4, 0x93, -/*0AF0*/0xA3, 0x60, 0x01, 0x0E, 0xCF, 0x54, 0xC0, 0x25, -	0xE0, 0x60, 0xAD, 0x40, 0xB8, 0x80, 0xFE, 0x8C, -/*0B00*/0x64, 0x8D, 0x65, 0x8A, 0x66, 0x8B, 0x67, 0xE4, -	0xF5, 0x69, 0xEF, 0x4E, 0x70, 0x03, 0x02, 0x1D, -/*0B10*/0x55, 0xE4, 0xF5, 0x68, 0xE5, 0x67, 0x45, 0x66, -	0x70, 0x32, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90, -/*0B20*/0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE4, -	0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4, 0x12, -/*0B30*/0x08, 0x70, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75, -	0x83, 0x92, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, -/*0B40*/0xC6, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8, -	0xE4, 0xF0, 0x80, 0x11, 0x90, 0x07, 0x26, 0x12, -/*0B50*/0x07, 0x35, 0xE4, 0x12, 0x08, 0x70, 0x70, 0x05, -	0x12, 0x07, 0x32, 0xE4, 0xF0, 0x12, 0x1D, 0x55, -/*0B60*/0x12, 0x1E, 0xBF, 0xE5, 0x67, 0x45, 0x66, 0x70, -	0x33, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90, 0xE5, -/*0B70*/0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5, -	0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x12, -/*0B80*/0x08, 0x6E, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75, -	0x83, 0x92, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75, -/*0B90*/0x83, 0xC6, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75, -	0x83, 0xC8, 0x80, 0x0E, 0x90, 0x07, 0x26, 0x12, -/*0BA0*/0x07, 0x35, 0x12, 0x08, 0x6E, 0x70, 0x06, 0x12, -	0x07, 0x32, 0xE5, 0x40, 0xF0, 0xAF, 0x69, 0x7E, -/*0BB0*/0x00, 0xAD, 0x67, 0xAC, 0x66, 0x12, 0x04, 0x44, -	0x12, 0x07, 0x2A, 0x75, 0x83, 0xCA, 0xE0, 0xD3, -/*0BC0*/0x94, 0x00, 0x50, 0x0C, 0x05, 0x68, 0xE5, 0x68, -	0xC3, 0x94, 0x05, 0x50, 0x03, 0x02, 0x0B, 0x14, -/*0BD0*/0x22, 0x8C, 0x60, 0x8D, 0x61, 0x12, 0x08, 0xDA, -	0x74, 0x20, 0x40, 0x0D, 0x2F, 0xF5, 0x82, 0x74, -/*0BE0*/0x03, 0x3E, 0xF5, 0x83, 0xE5, 0x3E, 0xF0, 0x80, -	0x0B, 0x2F, 0xF5, 0x82, 0x74, 0x03, 0x3E, 0xF5, -/*0BF0*/0x83, 0xE5, 0x3C, 0xF0, 0xE5, 0x3C, 0xD3, 0x95, -	0x3E, 0x40, 0x3C, 0xE5, 0x61, 0x45, 0x60, 0x70, -/*0C00*/0x10, 0xE9, 0x12, 0x09, 0x04, 0xE5, 0x3E, 0x12, -	0x07, 0x68, 0x40, 0x3B, 0x12, 0x08, 0x95, 0x80, -/*0C10*/0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40, 0x1D, -	0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05, 0x85, -/*0C20*/0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39, 0x8F, -	0x3A, 0x12, 0x08, 0x14, 0xE5, 0x3E, 0x12, 0x07, -/*0C30*/0xC0, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x43, 0xE5, -	0x61, 0x45, 0x60, 0x70, 0x19, 0x12, 0x07, 0x5F, -/*0C40*/0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x27, 0x12, -	0x09, 0x0B, 0x12, 0x08, 0x14, 0xE5, 0x42, 0x12, -/*0C50*/0x07, 0xC0, 0xE5, 0x41, 0xF0, 0x22, 0xE5, 0x3C, -	0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C, 0x38, -/*0C60*/0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39, 0x80, -	0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x08, -/*0C70*/0x14, 0xE5, 0x3C, 0x12, 0x07, 0xC0, 0xE5, 0x3D, -	0xF0, 0x22, 0x85, 0x38, 0x38, 0x85, 0x39, 0x39, -/*0C80*/0x85, 0x3A, 0x3A, 0x12, 0x08, 0x14, 0xE5, 0x38, -	0x12, 0x07, 0xC0, 0xE5, 0x39, 0xF0, 0x22, 0x7F, -/*0C90*/0x06, 0x12, 0x17, 0x31, 0x12, 0x1D, 0x23, 0x12, -	0x0E, 0x04, 0x12, 0x0E, 0x33, 0xE0, 0x44, 0x0A, -/*0CA0*/0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E, 0x04, 0x12, -	0x0E, 0x0B, 0xEF, 0xF0, 0xE5, 0x28, 0x30, 0xE5, -/*0CB0*/0x03, 0xD3, 0x80, 0x01, 0xC3, 0x40, 0x05, 0x75, -	0x14, 0x20, 0x80, 0x03, 0x75, 0x14, 0x08, 0x12, -/*0CC0*/0x0E, 0x04, 0x75, 0x83, 0x8A, 0xE5, 0x14, 0xF0, -	0xB4, 0xFF, 0x05, 0x75, 0x12, 0x80, 0x80, 0x06, -/*0CD0*/0xE5, 0x14, 0xC3, 0x13, 0xF5, 0x12, 0xE4, 0xF5, -	0x16, 0xF5, 0x7F, 0x12, 0x19, 0x36, 0x12, 0x13, -/*0CE0*/0xA3, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x50, 0x09, -	0x05, 0x16, 0xE5, 0x16, 0xC3, 0x94, 0x14, 0x40, -/*0CF0*/0xEA, 0xE5, 0xE4, 0x20, 0xE7, 0x28, 0x12, 0x0E, -	0x04, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3, -/*0D00*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, -	0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40, -/*0D10*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF, -	0x5E, 0x60, 0x03, 0x12, 0x1D, 0xD7, 0xE5, 0x7F, -/*0D20*/0xC3, 0x94, 0x11, 0x40, 0x14, 0x12, 0x0E, 0x04, -	0x75, 0x83, 0xD2, 0xE0, 0x44, 0x80, 0xF0, 0xE5, -/*0D30*/0xE4, 0x20, 0xE7, 0x0F, 0x12, 0x1D, 0xD7, 0x80, -	0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0xD2, 0xE0, -/*0D40*/0x54, 0x7F, 0xF0, 0x12, 0x1D, 0x23, 0x22, 0x74, -	0x8A, 0x85, 0x08, 0x82, 0xF5, 0x83, 0xE5, 0x17, -/*0D50*/0xF0, 0x12, 0x0E, 0x3A, 0xE4, 0xF0, 0x90, 0x07, -	0x02, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x90, -/*0D60*/0xEF, 0xF0, 0x74, 0x92, 0xFE, 0xE5, 0x08, 0x44, -	0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0, 0x54, -/*0D70*/0xC0, 0xFD, 0x90, 0x07, 0x03, 0xE0, 0x54, 0x3F, -	0x4D, 0x8F, 0x82, 0x8E, 0x83, 0xF0, 0x90, 0x07, -/*0D80*/0x04, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x82, -	0xEF, 0xF0, 0x90, 0x07, 0x05, 0xE0, 0xFF, 0xED, -/*0D90*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xB4, 0xEF, -	0x12, 0x0E, 0x03, 0x75, 0x83, 0x80, 0xE0, 0x54, -/*0DA0*/0xBF, 0xF0, 0x30, 0x37, 0x0A, 0x12, 0x0E, 0x91, -	0x75, 0x83, 0x94, 0xE0, 0x44, 0x80, 0xF0, 0x30, -/*0DB0*/0x38, 0x0A, 0x12, 0x0E, 0x91, 0x75, 0x83, 0x92, -	0xE0, 0x44, 0x80, 0xF0, 0xE5, 0x28, 0x30, 0xE4, -/*0DC0*/0x1A, 0x20, 0x39, 0x0A, 0x12, 0x0E, 0x04, 0x75, -	0x83, 0x88, 0xE0, 0x54, 0x7F, 0xF0, 0x20, 0x3A, -/*0DD0*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x88, 0xE0, -	0x54, 0xBF, 0xF0, 0x74, 0x8C, 0xFE, 0x12, 0x0E, -/*0DE0*/0x04, 0x8E, 0x83, 0xE0, 0x54, 0x0F, 0x12, 0x0E, -	0x03, 0x75, 0x83, 0x86, 0xE0, 0x54, 0xBF, 0xF0, -/*0DF0*/0xE5, 0x08, 0x44, 0x06, 0x12, 0x0D, 0xFD, 0x75, -	0x83, 0x8A, 0xE4, 0xF0, 0x22, 0xF5, 0x82, 0x75, -/*0E00*/0x83, 0x82, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07, -	0xF5, 0x82, 0x22, 0x8E, 0x83, 0xE0, 0xF5, 0x10, -/*0E10*/0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44, 0x01, 0xFF, -	0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07, 0xF5, 0x82, -/*0E20*/0x22, 0xE5, 0x15, 0xC4, 0x54, 0x07, 0xFF, 0xE5, -	0x08, 0xFD, 0xED, 0x44, 0x08, 0xF5, 0x82, 0x75, -/*0E30*/0x83, 0x82, 0x22, 0x75, 0x83, 0x80, 0xE0, 0x44, -	0x40, 0xF0, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82, -/*0E40*/0x75, 0x83, 0x8A, 0x22, 0xE5, 0x16, 0x25, 0xE0, -	0x25, 0xE0, 0x24, 0xAF, 0xF5, 0x82, 0xE4, 0x34, -/*0E50*/0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0D, 0x22, -	0x43, 0xE1, 0x10, 0x43, 0xE1, 0x80, 0x53, 0xE1, -/*0E60*/0xFD, 0x85, 0xE1, 0x10, 0x22, 0xE5, 0x16, 0x25, -	0xE0, 0x25, 0xE0, 0x24, 0xB2, 0xF5, 0x82, 0xE4, -/*0E70*/0x34, 0x1A, 0xF5, 0x83, 0xE4, 0x93, 0x22, 0x85, -	0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15, 0xF0, -/*0E80*/0x22, 0xE5, 0xE2, 0x54, 0x20, 0xD3, 0x94, 0x00, -	0x22, 0xE5, 0xE2, 0x54, 0x40, 0xD3, 0x94, 0x00, -/*0E90*/0x22, 0xE5, 0x08, 0x44, 0x06, 0xF5, 0x82, 0x22, -	0xFD, 0xE5, 0x08, 0xFB, 0xEB, 0x44, 0x07, 0xF5, -/*0EA0*/0x82, 0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFE, 0x30, -	0x22, 0xEF, 0x4E, 0x70, 0x26, 0x12, 0x07, 0xCC, -/*0EB0*/0xE0, 0xFD, 0x90, 0x07, 0x26, 0x12, 0x07, 0x7B, -	0x12, 0x07, 0xD8, 0xE0, 0xFD, 0x90, 0x07, 0x28, -/*0EC0*/0x12, 0x07, 0x7B, 0x12, 0x08, 0x81, 0x12, 0x07, -	0x72, 0x12, 0x08, 0x35, 0xE0, 0x90, 0x07, 0x24, -/*0ED0*/0x12, 0x07, 0x78, 0xEF, 0x64, 0x04, 0x4E, 0x70, -	0x29, 0x12, 0x07, 0xE4, 0xE0, 0xFD, 0x90, 0x07, -/*0EE0*/0x26, 0x12, 0x07, 0x7B, 0x12, 0x07, 0xF0, 0xE0, -	0xFD, 0x90, 0x07, 0x28, 0x12, 0x07, 0x7B, 0x12, -/*0EF0*/0x08, 0x8B, 0x12, 0x07, 0x72, 0x12, 0x08, 0x41, -	0xE0, 0x54, 0x1F, 0xFD, 0x90, 0x07, 0x24, 0x12, -/*0F00*/0x07, 0x7B, 0xEF, 0x64, 0x01, 0x4E, 0x70, 0x04, -	0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0xEF, 0x64, -/*0F10*/0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02, -	0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x35, 0x12, 0x07, -/*0F20*/0xFC, 0xE0, 0xFF, 0x90, 0x07, 0x26, 0x12, 0x07, -	0x89, 0xEF, 0xF0, 0x12, 0x08, 0x08, 0xE0, 0xFF, -/*0F30*/0x90, 0x07, 0x28, 0x12, 0x07, 0x89, 0xEF, 0xF0, -	0x12, 0x08, 0x4D, 0xE0, 0x54, 0x1F, 0xFF, 0x12, -/*0F40*/0x07, 0x86, 0xEF, 0xF0, 0x12, 0x08, 0x59, 0xE0, -	0x54, 0x1F, 0xFF, 0x90, 0x07, 0x24, 0x12, 0x07, -/*0F50*/0x89, 0xEF, 0xF0, 0x22, 0xE4, 0xF5, 0x53, 0x12, -	0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, -/*0F60*/0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40, 0x04, 0x7E, -	0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x70, -/*0F70*/0x03, 0x02, 0x0F, 0xF6, 0x85, 0xE1, 0x10, 0x43, -	0xE1, 0x02, 0x53, 0xE1, 0x0F, 0x85, 0xE1, 0x10, -/*0F80*/0xE4, 0xF5, 0x51, 0xE5, 0xE3, 0x54, 0x3F, 0xF5, -	0x52, 0x12, 0x0E, 0x89, 0x40, 0x1D, 0xAD, 0x52, -/*0F90*/0xAF, 0x51, 0x12, 0x11, 0x18, 0xEF, 0x60, 0x08, -	0x85, 0xE1, 0x10, 0x43, 0xE1, 0x40, 0x80, 0x0B, -/*0FA0*/0x53, 0xE1, 0xBF, 0x12, 0x0E, 0x58, 0x12, 0x00, -	0x06, 0x80, 0xFB, 0xE5, 0xE3, 0x54, 0x3F, 0xF5, -/*0FB0*/0x51, 0xE5, 0xE4, 0x54, 0x3F, 0xF5, 0x52, 0x12, -	0x0E, 0x81, 0x40, 0x1D, 0xAD, 0x52, 0xAF, 0x51, -/*0FC0*/0x12, 0x11, 0x18, 0xEF, 0x60, 0x08, 0x85, 0xE1, -	0x10, 0x43, 0xE1, 0x20, 0x80, 0x0B, 0x53, 0xE1, -/*0FD0*/0xDF, 0x12, 0x0E, 0x58, 0x12, 0x00, 0x06, 0x80, -	0xFB, 0x12, 0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01, -/*0FE0*/0x80, 0x02, 0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40, -	0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, -/*0FF0*/0x4F, 0x60, 0x03, 0x12, 0x0E, 0x5B, 0x22, 0x12, -	0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x22, -/*1000*/0x02, 0x11, 0x00, 0x02, 0x10, 0x40, 0x02, 0x10, -	0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1010*/0x01, 0x20, 0x01, 0x20, 0xE4, 0xF5, 0x57, 0x12, -	0x16, 0xBD, 0x12, 0x16, 0x44, 0xE4, 0x12, 0x10, -/*1020*/0x56, 0x12, 0x14, 0xB7, 0x90, 0x07, 0x26, 0x12, -	0x07, 0x35, 0xE4, 0x12, 0x07, 0x31, 0xE4, 0xF0, -/*1030*/0x12, 0x10, 0x56, 0x12, 0x14, 0xB7, 0x90, 0x07, -	0x26, 0x12, 0x07, 0x35, 0xE5, 0x41, 0x12, 0x07, -/*1040*/0x31, 0xE5, 0x40, 0xF0, 0xAF, 0x57, 0x7E, 0x00, -	0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF, -/*1050*/0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xFF, 0x90, -	0x07, 0x20, 0xA3, 0xE0, 0xFD, 0xE4, 0xF5, 0x56, -/*1060*/0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x12, -	0x11, 0x51, 0x7F, 0x0F, 0x7D, 0x18, 0xE4, 0xF5, -/*1070*/0x56, 0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, -	0x12, 0x15, 0x41, 0xAF, 0x56, 0x7E, 0x00, 0x12, -/*1080*/0x1A, 0xFF, 0xE4, 0xFF, 0xF5, 0x56, 0x7D, 0x1F, -	0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x22, -/*1090*/0x22, 0xE4, 0xF5, 0x55, 0xE5, 0x08, 0xFD, 0x74, -	0xA0, 0xF5, 0x56, 0xED, 0x44, 0x07, 0xF5, 0x57, -/*10A0*/0xE5, 0x28, 0x30, 0xE5, 0x03, 0xD3, 0x80, 0x01, -	0xC3, 0x40, 0x05, 0x7F, 0x28, 0xEF, 0x80, 0x04, -/*10B0*/0x7F, 0x14, 0xEF, 0xC3, 0x13, 0xF5, 0x54, 0xE4, -	0xF9, 0x12, 0x0E, 0x18, 0x75, 0x83, 0x8E, 0xE0, -/*10C0*/0xF5, 0x10, 0xCE, 0xEF, 0xCE, 0xEE, 0xD3, 0x94, -	0x00, 0x40, 0x26, 0xE5, 0x10, 0x54, 0xFE, 0x12, -/*10D0*/0x0E, 0x98, 0x75, 0x83, 0x8E, 0xED, 0xF0, 0xE5, -	0x10, 0x44, 0x01, 0xFD, 0xEB, 0x44, 0x07, 0xF5, -/*10E0*/0x82, 0xED, 0xF0, 0x85, 0x57, 0x82, 0x85, 0x56, -	0x83, 0xE0, 0x30, 0xE3, 0x01, 0x09, 0x1E, 0x80, -/*10F0*/0xD4, 0xC2, 0x34, 0xE9, 0xC3, 0x95, 0x54, 0x40, -	0x02, 0xD2, 0x34, 0x22, 0x02, 0x00, 0x06, 0x22, -/*1100*/0x30, 0x30, 0x11, 0x90, 0x10, 0x00, 0xE4, 0x93, -	0xF5, 0x10, 0x90, 0x10, 0x10, 0xE4, 0x93, 0xF5, -/*1110*/0x10, 0x12, 0x10, 0x90, 0x12, 0x11, 0x50, 0x22, -	0xE4, 0xFC, 0xC3, 0xED, 0x9F, 0xFA, 0xEF, 0xF5, -/*1120*/0x83, 0x75, 0x82, 0x00, 0x79, 0xFF, 0xE4, 0x93, -	0xCC, 0x6C, 0xCC, 0xA3, 0xD9, 0xF8, 0xDA, 0xF6, -/*1130*/0xE5, 0xE2, 0x30, 0xE4, 0x02, 0x8C, 0xE5, 0xED, -	0x24, 0xFF, 0xFF, 0xEF, 0x75, 0x82, 0xFF, 0xF5, -/*1140*/0x83, 0xE4, 0x93, 0x6C, 0x70, 0x03, 0x7F, 0x01, -	0x22, 0x7F, 0x00, 0x22, 0x22, 0x11, 0x00, 0x00, -/*1150*/0x22, 0x8E, 0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D, -	0x5B, 0x8A, 0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01, -/*1160*/0xE4, 0xF5, 0x5F, 0xF5, 0x60, 0xF5, 0x62, 0x12, -	0x07, 0x2A, 0x75, 0x83, 0xD0, 0xE0, 0xFF, 0xC4, -/*1170*/0x54, 0x0F, 0xF5, 0x61, 0x12, 0x1E, 0xA5, 0x85, -	0x59, 0x5E, 0xD3, 0xE5, 0x5E, 0x95, 0x5B, 0xE5, -/*1180*/0x5A, 0x12, 0x07, 0x6B, 0x50, 0x4B, 0x12, 0x07, -	0x03, 0x75, 0x83, 0xBC, 0xE0, 0x45, 0x5E, 0x12, -/*1190*/0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x45, 0x5E, -	0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0, 0x45, -/*11A0*/0x5E, 0xF0, 0xAF, 0x5F, 0xE5, 0x60, 0x12, 0x08, -	0x78, 0x12, 0x0A, 0xFF, 0xAF, 0x62, 0x7E, 0x00, -/*11B0*/0xAD, 0x5D, 0xAC, 0x5C, 0x12, 0x04, 0x44, 0xE5, -	0x61, 0xAF, 0x5E, 0x7E, 0x00, 0xB4, 0x03, 0x05, -/*11C0*/0x12, 0x1E, 0x21, 0x80, 0x07, 0xAD, 0x5D, 0xAC, -	0x5C, 0x12, 0x13, 0x17, 0x05, 0x5E, 0x02, 0x11, -/*11D0*/0x7A, 0x12, 0x07, 0x03, 0x75, 0x83, 0xBC, 0xE0, -	0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBE, -/*11E0*/0xE0, 0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83, -	0xC0, 0xE0, 0x45, 0x40, 0xF0, 0x22, 0x8E, 0x58, -/*11F0*/0x8F, 0x59, 0x75, 0x5A, 0x01, 0x79, 0x01, 0x75, -	0x5B, 0x01, 0xE4, 0xFB, 0x12, 0x07, 0x2A, 0x75, -/*1200*/0x83, 0xAE, 0xE0, 0x54, 0x1A, 0xFF, 0x12, 0x08, -	0x65, 0xE0, 0xC4, 0x13, 0x54, 0x07, 0xFE, 0xEF, -/*1210*/0x70, 0x0C, 0xEE, 0x65, 0x35, 0x70, 0x07, 0x90, -	0x07, 0x2F, 0xE0, 0xB4, 0x01, 0x0D, 0xAF, 0x35, -/*1220*/0x7E, 0x00, 0x12, 0x0E, 0xA9, 0xCF, 0xEB, 0xCF, -	0x02, 0x1E, 0x60, 0xE5, 0x59, 0x64, 0x02, 0x45, -/*1230*/0x58, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, -	0x00, 0xE5, 0x59, 0x45, 0x58, 0x70, 0x04, 0x7E, -/*1240*/0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60, -	0x23, 0x85, 0x41, 0x49, 0x85, 0x40, 0x4B, 0xE5, -/*1250*/0x59, 0x45, 0x58, 0x70, 0x2C, 0xAF, 0x5A, 0xFE, -	0xCD, 0xE9, 0xCD, 0xFC, 0xAB, 0x59, 0xAA, 0x58, -/*1260*/0x12, 0x0A, 0xFF, 0xAF, 0x5B, 0x7E, 0x00, 0x12, -	0x1E, 0x60, 0x80, 0x15, 0xAF, 0x5B, 0x7E, 0x00, -/*1270*/0x12, 0x1E, 0x60, 0x90, 0x07, 0x26, 0x12, 0x07, -	0x35, 0xE5, 0x49, 0x12, 0x07, 0x31, 0xE5, 0x4B, -/*1280*/0xF0, 0xE4, 0xFD, 0xAF, 0x35, 0xFE, 0xFC, 0x12, -	0x09, 0x15, 0x22, 0x8C, 0x64, 0x8D, 0x65, 0x12, -/*1290*/0x08, 0xDA, 0x40, 0x3C, 0xE5, 0x65, 0x45, 0x64, -	0x70, 0x10, 0x12, 0x09, 0x04, 0xC3, 0xE5, 0x3E, -/*12A0*/0x12, 0x07, 0x69, 0x40, 0x3B, 0x12, 0x08, 0x95, -	0x80, 0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40, -/*12B0*/0x1D, 0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05, -	0x85, 0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39, -/*12C0*/0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3E, 0x12, -	0x07, 0x53, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x3B, -/*12D0*/0xE5, 0x65, 0x45, 0x64, 0x70, 0x11, 0x12, 0x07, -	0x5F, 0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x1F, -/*12E0*/0x12, 0x07, 0x3E, 0xE5, 0x41, 0xF0, 0x22, 0xE5, -	0x3C, 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C, -/*12F0*/0x38, 0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39, -	0x80, 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, -/*1300*/0x07, 0xA8, 0xE5, 0x3C, 0x12, 0x07, 0x53, 0xE5, -	0x3D, 0xF0, 0x22, 0x12, 0x07, 0x9F, 0xE5, 0x38, -/*1310*/0x12, 0x07, 0x53, 0xE5, 0x39, 0xF0, 0x22, 0x8C, -	0x63, 0x8D, 0x64, 0x12, 0x08, 0xDA, 0x40, 0x3C, -/*1320*/0xE5, 0x64, 0x45, 0x63, 0x70, 0x10, 0x12, 0x09, -	0x04, 0xC3, 0xE5, 0x3E, 0x12, 0x07, 0x69, 0x40, -/*1330*/0x3B, 0x12, 0x08, 0x95, 0x80, 0x18, 0xE5, 0x3E, -	0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3E, 0x38, -/*1340*/0xE5, 0x3E, 0x60, 0x05, 0x85, 0x3F, 0x39, 0x80, -	0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x07, -/*1350*/0xA8, 0xE5, 0x3E, 0x12, 0x07, 0x53, 0xE5, 0x3F, -	0xF0, 0x22, 0x80, 0x3B, 0xE5, 0x64, 0x45, 0x63, -/*1360*/0x70, 0x11, 0x12, 0x07, 0x5F, 0x40, 0x05, 0x12, -	0x08, 0x9E, 0x80, 0x1F, 0x12, 0x07, 0x3E, 0xE5, -/*1370*/0x41, 0xF0, 0x22, 0xE5, 0x3C, 0xC3, 0x95, 0x38, -	0x40, 0x1D, 0x85, 0x3C, 0x38, 0xE5, 0x3C, 0x60, -/*1380*/0x05, 0x85, 0x3D, 0x39, 0x80, 0x03, 0x85, 0x39, -	0x39, 0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3C, -/*1390*/0x12, 0x07, 0x53, 0xE5, 0x3D, 0xF0, 0x22, 0x12, -	0x07, 0x9F, 0xE5, 0x38, 0x12, 0x07, 0x53, 0xE5, -/*13A0*/0x39, 0xF0, 0x22, 0xE5, 0x0D, 0xFE, 0xE5, 0x08, -	0x8E, 0x54, 0x44, 0x05, 0xF5, 0x55, 0x75, 0x15, -/*13B0*/0x0F, 0xF5, 0x82, 0x12, 0x0E, 0x7A, 0x12, 0x17, -	0xA3, 0x20, 0x31, 0x05, 0x75, 0x15, 0x03, 0x80, -/*13C0*/0x03, 0x75, 0x15, 0x0B, 0xE5, 0x0A, 0xC3, 0x94, -	0x01, 0x50, 0x38, 0x12, 0x14, 0x20, 0x20, 0x31, -/*13D0*/0x06, 0x05, 0x15, 0x05, 0x15, 0x80, 0x04, 0x15, -	0x15, 0x15, 0x15, 0xE5, 0x0A, 0xC3, 0x94, 0x01, -/*13E0*/0x50, 0x21, 0x12, 0x14, 0x20, 0x20, 0x31, 0x04, -	0x05, 0x15, 0x80, 0x02, 0x15, 0x15, 0xE5, 0x0A, -/*13F0*/0xC3, 0x94, 0x01, 0x50, 0x0E, 0x12, 0x0E, 0x77, -	0x12, 0x17, 0xA3, 0x20, 0x31, 0x05, 0x05, 0x15, -/*1400*/0x12, 0x0E, 0x77, 0xE5, 0x15, 0xB4, 0x08, 0x04, -	0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x15, -/*1410*/0xB4, 0x07, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, -	0x00, 0xEE, 0x4F, 0x60, 0x02, 0x05, 0x7F, 0x22, -/*1420*/0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15, -	0xF0, 0x12, 0x17, 0xA3, 0x22, 0x12, 0x07, 0x2A, -/*1430*/0x75, 0x83, 0xAE, 0x74, 0xFF, 0x12, 0x07, 0x29, -	0xE0, 0x54, 0x1A, 0xF5, 0x34, 0xE0, 0xC4, 0x13, -/*1440*/0x54, 0x07, 0xF5, 0x35, 0x24, 0xFE, 0x60, 0x24, -	0x24, 0xFE, 0x60, 0x3C, 0x24, 0x04, 0x70, 0x63, -/*1450*/0x75, 0x31, 0x2D, 0xE5, 0x08, 0xFD, 0x74, 0xB6, -	0x12, 0x07, 0x92, 0x74, 0xBC, 0x90, 0x07, 0x22, -/*1460*/0x12, 0x07, 0x95, 0x74, 0x90, 0x12, 0x07, 0xB3, -	0x74, 0x92, 0x80, 0x3C, 0x75, 0x31, 0x3A, 0xE5, -/*1470*/0x08, 0xFD, 0x74, 0xBA, 0x12, 0x07, 0x92, 0x74, -	0xC0, 0x90, 0x07, 0x22, 0x12, 0x07, 0xB6, 0x74, -/*1480*/0xC4, 0x12, 0x07, 0xB3, 0x74, 0xC8, 0x80, 0x20, -	0x75, 0x31, 0x35, 0xE5, 0x08, 0xFD, 0x74, 0xB8, -/*1490*/0x12, 0x07, 0x92, 0x74, 0xBE, 0xFF, 0xED, 0x44, -	0x07, 0x90, 0x07, 0x22, 0xCF, 0xF0, 0xA3, 0xEF, -/*14A0*/0xF0, 0x74, 0xC2, 0x12, 0x07, 0xB3, 0x74, 0xC6, -	0xFF, 0xED, 0x44, 0x07, 0xA3, 0xCF, 0xF0, 0xA3, -/*14B0*/0xEF, 0xF0, 0x22, 0x75, 0x34, 0x01, 0x22, 0x8E, -	0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D, 0x5B, 0x8A, -/*14C0*/0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01, 0xE4, 0xF5, -	0x5F, 0x12, 0x1E, 0xA5, 0x85, 0x59, 0x5E, 0xD3, -/*14D0*/0xE5, 0x5E, 0x95, 0x5B, 0xE5, 0x5A, 0x12, 0x07, -	0x6B, 0x50, 0x57, 0xE5, 0x5D, 0x45, 0x5C, 0x70, -/*14E0*/0x30, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x92, 0xE5, -	0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC6, 0xE5, -/*14F0*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8, 0xE5, -	0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0x90, 0xE5, -/*1500*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5, -	0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x80, -/*1510*/0x03, 0x12, 0x07, 0x32, 0xE5, 0x5E, 0xF0, 0xAF, -	0x5F, 0x7E, 0x00, 0xAD, 0x5D, 0xAC, 0x5C, 0x12, -/*1520*/0x04, 0x44, 0xAF, 0x5E, 0x7E, 0x00, 0xAD, 0x5D, -	0xAC, 0x5C, 0x12, 0x0B, 0xD1, 0x05, 0x5E, 0x02, -/*1530*/0x14, 0xCF, 0xAB, 0x5D, 0xAA, 0x5C, 0xAD, 0x5B, -	0xAC, 0x5A, 0xAF, 0x59, 0xAE, 0x58, 0x02, 0x1B, -/*1540*/0xFB, 0x8C, 0x5C, 0x8D, 0x5D, 0x8A, 0x5E, 0x8B, -	0x5F, 0x75, 0x60, 0x01, 0xE4, 0xF5, 0x61, 0xF5, -/*1550*/0x62, 0xF5, 0x63, 0x12, 0x1E, 0xA5, 0x8F, 0x60, -	0xD3, 0xE5, 0x60, 0x95, 0x5D, 0xE5, 0x5C, 0x12, -/*1560*/0x07, 0x6B, 0x50, 0x61, 0xE5, 0x5F, 0x45, 0x5E, -	0x70, 0x27, 0x12, 0x07, 0x2A, 0x75, 0x83, 0xB6, -/*1570*/0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xB8, -	0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBA, -/*1580*/0xE5, 0x60, 0xF0, 0xAF, 0x61, 0x7E, 0x00, 0xE5, -	0x62, 0x12, 0x08, 0x7A, 0x12, 0x0A, 0xFF, 0x80, -/*1590*/0x19, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE5, -	0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0x8E, 0xE4, -/*15A0*/0x12, 0x07, 0x29, 0x74, 0x01, 0x12, 0x07, 0x29, -	0xE4, 0xF0, 0xAF, 0x63, 0x7E, 0x00, 0xAD, 0x5F, -/*15B0*/0xAC, 0x5E, 0x12, 0x04, 0x44, 0xAF, 0x60, 0x7E, -	0x00, 0xAD, 0x5F, 0xAC, 0x5E, 0x12, 0x12, 0x8B, -/*15C0*/0x05, 0x60, 0x02, 0x15, 0x58, 0x22, 0x90, 0x11, -	0x4D, 0xE4, 0x93, 0x90, 0x07, 0x2E, 0xF0, 0x12, -/*15D0*/0x08, 0x1F, 0x75, 0x83, 0xAE, 0xE0, 0x54, 0x1A, -	0xF5, 0x34, 0x70, 0x67, 0xEF, 0x44, 0x07, 0xF5, -/*15E0*/0x82, 0x75, 0x83, 0xCE, 0xE0, 0xFF, 0x13, 0x13, -	0x13, 0x54, 0x07, 0xF5, 0x36, 0x54, 0x0F, 0xD3, -/*15F0*/0x94, 0x00, 0x40, 0x06, 0x12, 0x14, 0x2D, 0x12, -	0x1B, 0xA9, 0xE5, 0x36, 0x54, 0x0F, 0x24, 0xFE, -/*1600*/0x60, 0x0C, 0x14, 0x60, 0x0C, 0x14, 0x60, 0x19, -	0x24, 0x03, 0x70, 0x37, 0x80, 0x10, 0x02, 0x1E, -/*1610*/0x91, 0x12, 0x1E, 0x91, 0x12, 0x07, 0x2A, 0x75, -	0x83, 0xCE, 0xE0, 0x54, 0xEF, 0xF0, 0x02, 0x1D, -/*1620*/0xAE, 0x12, 0x10, 0x14, 0xE4, 0xF5, 0x55, 0x12, -	0x1D, 0x85, 0x05, 0x55, 0xE5, 0x55, 0xC3, 0x94, -/*1630*/0x05, 0x40, 0xF4, 0x12, 0x07, 0x2A, 0x75, 0x83, -	0xCE, 0xE0, 0x54, 0xC7, 0x12, 0x07, 0x29, 0xE0, -/*1640*/0x44, 0x08, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5, -	0x59, 0xAF, 0x08, 0xEF, 0x44, 0x07, 0xF5, 0x82, -/*1650*/0x75, 0x83, 0xD0, 0xE0, 0xFD, 0xC4, 0x54, 0x0F, -	0xF5, 0x5A, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0x75, -/*1660*/0x83, 0x80, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x21, -	0x75, 0x83, 0x82, 0xE5, 0x45, 0xF0, 0xEF, 0x44, -/*1670*/0x07, 0xF5, 0x82, 0x75, 0x83, 0x8A, 0x74, 0xFF, -	0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x07, 0x2A, 0x75, -/*1680*/0x83, 0xBC, 0xE0, 0x54, 0xEF, 0x12, 0x07, 0x29, -	0x75, 0x83, 0xBE, 0xE0, 0x54, 0xEF, 0x12, 0x07, -/*1690*/0x29, 0x75, 0x83, 0xC0, 0xE0, 0x54, 0xEF, 0x12, -	0x07, 0x29, 0x75, 0x83, 0xBC, 0xE0, 0x44, 0x10, -/*16A0*/0x12, 0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x44, -	0x10, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0, -/*16B0*/0x44, 0x10, 0xF0, 0xAF, 0x58, 0xE5, 0x59, 0x12, -	0x08, 0x78, 0x02, 0x0A, 0xFF, 0xE4, 0xF5, 0x58, -/*16C0*/0x7D, 0x01, 0xF5, 0x59, 0xAF, 0x35, 0xFE, 0xFC, -	0x12, 0x09, 0x15, 0x12, 0x07, 0x2A, 0x75, 0x83, -/*16D0*/0xB6, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, -	0xB8, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, -/*16E0*/0xBA, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, -	0xBC, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, -/*16F0*/0xBE, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, -	0xC0, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, -/*1700*/0x90, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, -	0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4, -/*1710*/0x12, 0x07, 0x29, 0x75, 0x83, 0x92, 0xE4, 0x12, -	0x07, 0x29, 0x75, 0x83, 0xC6, 0xE4, 0x12, 0x07, -/*1720*/0x29, 0x75, 0x83, 0xC8, 0xE4, 0xF0, 0xAF, 0x58, -	0xFE, 0xE5, 0x59, 0x12, 0x08, 0x7A, 0x02, 0x0A, -/*1730*/0xFF, 0xE5, 0xE2, 0x30, 0xE4, 0x6C, 0xE5, 0xE7, -	0x54, 0xC0, 0x64, 0x40, 0x70, 0x64, 0xE5, 0x09, -/*1740*/0xC4, 0x54, 0x30, 0xFE, 0xE5, 0x08, 0x25, 0xE0, -	0x25, 0xE0, 0x54, 0xC0, 0x4E, 0xFE, 0xEF, 0x54, -/*1750*/0x3F, 0x4E, 0xFD, 0xE5, 0x2B, 0xAE, 0x2A, 0x78, -	0x02, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, -/*1760*/0xF5, 0x82, 0x8E, 0x83, 0xED, 0xF0, 0xE5, 0x2B, -	0xAE, 0x2A, 0x78, 0x02, 0xC3, 0x33, 0xCE, 0x33, -/*1770*/0xCE, 0xD8, 0xF9, 0xFF, 0xF5, 0x82, 0x8E, 0x83, -	0xA3, 0xE5, 0xFE, 0xF0, 0x8F, 0x82, 0x8E, 0x83, -/*1780*/0xA3, 0xA3, 0xE5, 0xFD, 0xF0, 0x8F, 0x82, 0x8E, -	0x83, 0xA3, 0xA3, 0xA3, 0xE5, 0xFC, 0xF0, 0xC3, -/*1790*/0xE5, 0x2B, 0x94, 0xFA, 0xE5, 0x2A, 0x94, 0x00, -	0x50, 0x08, 0x05, 0x2B, 0xE5, 0x2B, 0x70, 0x02, -/*17A0*/0x05, 0x2A, 0x22, 0xE4, 0xFF, 0xE4, 0xF5, 0x58, -	0xF5, 0x56, 0xF5, 0x57, 0x74, 0x82, 0xFC, 0x12, -/*17B0*/0x0E, 0x04, 0x8C, 0x83, 0xE0, 0xF5, 0x10, 0x54, -	0x7F, 0xF0, 0xE5, 0x10, 0x44, 0x80, 0x12, 0x0E, -/*17C0*/0x98, 0xED, 0xF0, 0x7E, 0x0A, 0x12, 0x0E, 0x04, -	0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0, 0x26, 0xDE, -/*17D0*/0xF4, 0x05, 0x57, 0xE5, 0x57, 0x70, 0x02, 0x05, -	0x56, 0xE5, 0x14, 0x24, 0x01, 0xFD, 0xE4, 0x33, -/*17E0*/0xFC, 0xD3, 0xE5, 0x57, 0x9D, 0xE5, 0x56, 0x9C, -	0x40, 0xD9, 0xE5, 0x0A, 0x94, 0x20, 0x50, 0x02, -/*17F0*/0x05, 0x0A, 0x43, 0xE1, 0x08, 0xC2, 0x31, 0x12, -	0x0E, 0x04, 0x75, 0x83, 0xA6, 0xE0, 0x55, 0x12, -/*1800*/0x65, 0x12, 0x70, 0x03, 0xD2, 0x31, 0x22, 0xC2, -	0x31, 0x22, 0x90, 0x07, 0x26, 0xE0, 0xFA, 0xA3, -/*1810*/0xE0, 0xF5, 0x82, 0x8A, 0x83, 0xE0, 0xF5, 0x41, -	0xE5, 0x39, 0xC3, 0x95, 0x41, 0x40, 0x26, 0xE5, -/*1820*/0x39, 0x95, 0x41, 0xC3, 0x9F, 0xEE, 0x12, 0x07, -	0x6B, 0x40, 0x04, 0x7C, 0x01, 0x80, 0x02, 0x7C, -/*1830*/0x00, 0xE5, 0x41, 0x64, 0x3F, 0x60, 0x04, 0x7B, -	0x01, 0x80, 0x02, 0x7B, 0x00, 0xEC, 0x5B, 0x60, -/*1840*/0x29, 0x05, 0x41, 0x80, 0x28, 0xC3, 0xE5, 0x41, -	0x95, 0x39, 0xC3, 0x9F, 0xEE, 0x12, 0x07, 0x6B, -/*1850*/0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, -	0xE5, 0x41, 0x60, 0x04, 0x7E, 0x01, 0x80, 0x02, -/*1860*/0x7E, 0x00, 0xEF, 0x5E, 0x60, 0x04, 0x15, 0x41, -	0x80, 0x03, 0x85, 0x39, 0x41, 0x85, 0x3A, 0x40, -/*1870*/0x22, 0xE5, 0xE2, 0x30, 0xE4, 0x60, 0xE5, 0xE1, -	0x30, 0xE2, 0x5B, 0xE5, 0x09, 0x70, 0x04, 0x7F, -/*1880*/0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x08, 0x70, -	0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, -/*1890*/0x5F, 0x60, 0x43, 0x53, 0xF9, 0xF8, 0xE5, 0xE2, -	0x30, 0xE4, 0x3B, 0xE5, 0xE1, 0x30, 0xE2, 0x2E, -/*18A0*/0x43, 0xFA, 0x02, 0x53, 0xFA, 0xFB, 0xE4, 0xF5, -	0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0xE5, -/*18B0*/0xE1, 0x30, 0xE2, 0xE7, 0x90, 0x94, 0x70, 0xE0, -	0x65, 0x10, 0x60, 0x03, 0x43, 0xFA, 0x04, 0x05, -/*18C0*/0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0x70, -	0xE6, 0x12, 0x00, 0x06, 0x80, 0xE1, 0x53, 0xFA, -/*18D0*/0xFD, 0x53, 0xFA, 0xFB, 0x80, 0xC0, 0x22, 0x8F, -	0x54, 0x12, 0x00, 0x06, 0xE5, 0xE1, 0x30, 0xE0, -/*18E0*/0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, -	0x7E, 0xD3, 0x94, 0x05, 0x40, 0x04, 0x7E, 0x01, -/*18F0*/0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60, 0x3D, -	0x85, 0x54, 0x11, 0xE5, 0xE2, 0x20, 0xE1, 0x32, -/*1900*/0x74, 0xCE, 0x12, 0x1A, 0x05, 0x30, 0xE7, 0x04, -	0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0x8F, 0x82, -/*1910*/0x8E, 0x83, 0xE0, 0x30, 0xE6, 0x04, 0x7F, 0x01, -	0x80, 0x02, 0x7F, 0x00, 0xEF, 0x5D, 0x70, 0x15, -/*1920*/0x12, 0x15, 0xC6, 0x74, 0xCE, 0x12, 0x1A, 0x05, -	0x30, 0xE6, 0x07, 0xE0, 0x44, 0x80, 0xF0, 0x43, -/*1930*/0xF9, 0x80, 0x12, 0x18, 0x71, 0x22, 0x12, 0x0E, -	0x44, 0xE5, 0x16, 0x25, 0xE0, 0x25, 0xE0, 0x24, -/*1940*/0xB0, 0xF5, 0x82, 0xE4, 0x34, 0x1A, 0xF5, 0x83, -	0xE4, 0x93, 0xF5, 0x0F, 0xE5, 0x16, 0x25, 0xE0, -/*1950*/0x25, 0xE0, 0x24, 0xB1, 0xF5, 0x82, 0xE4, 0x34, -	0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0E, 0x12, -/*1960*/0x0E, 0x65, 0xF5, 0x10, 0xE5, 0x0F, 0x54, 0xF0, -	0x12, 0x0E, 0x17, 0x75, 0x83, 0x8C, 0xEF, 0xF0, -/*1970*/0xE5, 0x0F, 0x30, 0xE0, 0x0C, 0x12, 0x0E, 0x04, -	0x75, 0x83, 0x86, 0xE0, 0x44, 0x40, 0xF0, 0x80, -/*1980*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x86, 0xE0, -	0x54, 0xBF, 0xF0, 0x12, 0x0E, 0x91, 0x75, 0x83, -/*1990*/0x82, 0xE5, 0x0E, 0xF0, 0x22, 0x7F, 0x05, 0x12, -	0x17, 0x31, 0x12, 0x0E, 0x04, 0x12, 0x0E, 0x33, -/*19A0*/0x74, 0x02, 0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E, -	0x04, 0x12, 0x0E, 0x0B, 0xEF, 0xF0, 0x75, 0x15, -/*19B0*/0x70, 0x12, 0x0F, 0xF7, 0x20, 0x34, 0x05, 0x75, -	0x15, 0x10, 0x80, 0x03, 0x75, 0x15, 0x50, 0x12, -/*19C0*/0x0F, 0xF7, 0x20, 0x34, 0x04, 0x74, 0x10, 0x80, -	0x02, 0x74, 0xF0, 0x25, 0x15, 0xF5, 0x15, 0x12, -/*19D0*/0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x20, -	0x34, 0x17, 0xE5, 0x15, 0x64, 0x30, 0x60, 0x0C, -/*19E0*/0x74, 0x10, 0x25, 0x15, 0xF5, 0x15, 0xB4, 0x80, -	0x03, 0xE4, 0xF5, 0x15, 0x12, 0x0E, 0x21, 0xEF, -/*19F0*/0xF0, 0x22, 0xF0, 0xE5, 0x0B, 0x25, 0xE0, 0x25, -	0xE0, 0x24, 0x82, 0xF5, 0x82, 0xE4, 0x34, 0x07, -/*1A00*/0xF5, 0x83, 0x22, 0x74, 0x88, 0xFE, 0xE5, 0x08, -	0x44, 0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0, -/*1A10*/0x22, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82, -	0x22, 0xF0, 0xE0, 0x54, 0xC0, 0x8F, 0x82, 0x8E, -/*1A20*/0x83, 0xF0, 0x22, 0xEF, 0x44, 0x07, 0xF5, 0x82, -	0x75, 0x83, 0x86, 0xE0, 0x54, 0x10, 0xD3, 0x94, -/*1A30*/0x00, 0x22, 0xF0, 0x90, 0x07, 0x15, 0xE0, 0x04, -	0xF0, 0x22, 0x44, 0x06, 0xF5, 0x82, 0x75, 0x83, -/*1A40*/0x9E, 0xE0, 0x22, 0xFE, 0xEF, 0x44, 0x07, 0xF5, -	0x82, 0x8E, 0x83, 0xE0, 0x22, 0xE4, 0x90, 0x07, -/*1A50*/0x2A, 0xF0, 0xA3, 0xF0, 0x12, 0x07, 0x2A, 0x75, -	0x83, 0x82, 0xE0, 0x54, 0x7F, 0x12, 0x07, 0x29, -/*1A60*/0xE0, 0x44, 0x80, 0xF0, 0x12, 0x10, 0xFC, 0x12, -	0x08, 0x1F, 0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0, -/*1A70*/0x1A, 0x90, 0x07, 0x2B, 0xE0, 0x04, 0xF0, 0x70, -	0x06, 0x90, 0x07, 0x2A, 0xE0, 0x04, 0xF0, 0x90, -/*1A80*/0x07, 0x2A, 0xE0, 0xB4, 0x10, 0xE1, 0xA3, 0xE0, -	0xB4, 0x00, 0xDC, 0xEE, 0x44, 0xA6, 0xFC, 0xEF, -/*1A90*/0x44, 0x07, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0xF5, -	0x32, 0xEE, 0x44, 0xA8, 0xFE, 0xEF, 0x44, 0x07, -/*1AA0*/0xF5, 0x82, 0x8E, 0x83, 0xE0, 0xF5, 0x33, 0x22, -	0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x90, -/*1AB0*/0x00, 0x20, 0x0F, 0x92, 0x00, 0x21, 0x0F, 0x94, -	0x00, 0x22, 0x0F, 0x96, 0x00, 0x23, 0x0F, 0x98, -/*1AC0*/0x00, 0x24, 0x0F, 0x9A, 0x00, 0x25, 0x0F, 0x9C, -	0x00, 0x26, 0x0F, 0x9E, 0x00, 0x27, 0x0F, 0xA0, -/*1AD0*/0x01, 0x20, 0x01, 0xA2, 0x01, 0x21, 0x01, 0xA4, -	0x01, 0x22, 0x01, 0xA6, 0x01, 0x23, 0x01, 0xA8, -/*1AE0*/0x01, 0x24, 0x01, 0xAA, 0x01, 0x25, 0x01, 0xAC, -	0x01, 0x26, 0x01, 0xAE, 0x01, 0x27, 0x01, 0xB0, -/*1AF0*/0x01, 0x28, 0x01, 0xB4, 0x00, 0x28, 0x0F, 0xB6, -	0x40, 0x28, 0x0F, 0xB8, 0x61, 0x28, 0x01, 0xCB, -/*1B00*/0xEF, 0xCB, 0xCA, 0xEE, 0xCA, 0x7F, 0x01, 0xE4, -	0xFD, 0xEB, 0x4A, 0x70, 0x24, 0xE5, 0x08, 0xF5, -/*1B10*/0x82, 0x74, 0xB6, 0x12, 0x08, 0x29, 0xE5, 0x08, -	0xF5, 0x82, 0x74, 0xB8, 0x12, 0x08, 0x29, 0xE5, -/*1B20*/0x08, 0xF5, 0x82, 0x74, 0xBA, 0x12, 0x08, 0x29, -	0x7E, 0x00, 0x7C, 0x00, 0x12, 0x0A, 0xFF, 0x80, -/*1B30*/0x12, 0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE5, -	0x41, 0xF0, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35, -/*1B40*/0xE5, 0x40, 0xF0, 0x12, 0x07, 0x2A, 0x75, 0x83, -	0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74, 0x01, 0x12, -/*1B50*/0x07, 0x29, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x26, -	0xF5, 0x27, 0x53, 0xE1, 0xFE, 0xF5, 0x2A, 0x75, -/*1B60*/0x2B, 0x01, 0xF5, 0x08, 0x7F, 0x01, 0x12, 0x17, -	0x31, 0x30, 0x30, 0x1C, 0x90, 0x1A, 0xA9, 0xE4, -/*1B70*/0x93, 0xF5, 0x10, 0x90, 0x1F, 0xF9, 0xE4, 0x93, -	0xF5, 0x10, 0x90, 0x00, 0x41, 0xE4, 0x93, 0xF5, -/*1B80*/0x10, 0x90, 0x1E, 0xCA, 0xE4, 0x93, 0xF5, 0x10, -	0x7F, 0x02, 0x12, 0x17, 0x31, 0x12, 0x0F, 0x54, -/*1B90*/0x7F, 0x03, 0x12, 0x17, 0x31, 0x12, 0x00, 0x06, -	0xE5, 0xE2, 0x30, 0xE7, 0x09, 0x12, 0x10, 0x00, -/*1BA0*/0x30, 0x30, 0x03, 0x12, 0x11, 0x00, 0x02, 0x00, -	0x47, 0x12, 0x08, 0x1F, 0x75, 0x83, 0xD0, 0xE0, -/*1BB0*/0xC4, 0x54, 0x0F, 0xFD, 0x75, 0x43, 0x01, 0x75, -	0x44, 0xFF, 0x12, 0x08, 0xAA, 0x74, 0x04, 0xF0, -/*1BC0*/0x75, 0x3B, 0x01, 0xED, 0x14, 0x60, 0x0C, 0x14, -	0x60, 0x0B, 0x14, 0x60, 0x0F, 0x24, 0x03, 0x70, -/*1BD0*/0x0B, 0x80, 0x09, 0x80, 0x00, 0x12, 0x08, 0xA7, -	0x04, 0xF0, 0x80, 0x06, 0x12, 0x08, 0xA7, 0x74, -/*1BE0*/0x04, 0xF0, 0xEE, 0x44, 0x82, 0xFE, 0xEF, 0x44, -	0x07, 0xF5, 0x82, 0x8E, 0x83, 0xE5, 0x45, 0x12, -/*1BF0*/0x08, 0xBE, 0x75, 0x83, 0x82, 0xE5, 0x31, 0xF0, -	0x02, 0x11, 0x4C, 0x8E, 0x60, 0x8F, 0x61, 0x12, -/*1C00*/0x1E, 0xA5, 0xE4, 0xFF, 0xCE, 0xED, 0xCE, 0xEE, -	0xD3, 0x95, 0x61, 0xE5, 0x60, 0x12, 0x07, 0x6B, -/*1C10*/0x40, 0x39, 0x74, 0x20, 0x2E, 0xF5, 0x82, 0xE4, -	0x34, 0x03, 0xF5, 0x83, 0xE0, 0x70, 0x03, 0xFF, -/*1C20*/0x80, 0x26, 0x12, 0x08, 0xE2, 0xFD, 0xC3, 0x9F, -	0x40, 0x1E, 0xCF, 0xED, 0xCF, 0xEB, 0x4A, 0x70, -/*1C30*/0x0B, 0x8D, 0x42, 0x12, 0x08, 0xEE, 0xF5, 0x41, -	0x8E, 0x40, 0x80, 0x0C, 0x12, 0x08, 0xE2, 0xF5, -/*1C40*/0x38, 0x12, 0x08, 0xEE, 0xF5, 0x39, 0x8E, 0x3A, -	0x1E, 0x80, 0xBC, 0x22, 0x75, 0x58, 0x01, 0xE5, -/*1C50*/0x35, 0x70, 0x0C, 0x12, 0x07, 0xCC, 0xE0, 0xF5, -	0x4A, 0x12, 0x07, 0xD8, 0xE0, 0xF5, 0x4C, 0xE5, -/*1C60*/0x35, 0xB4, 0x04, 0x0C, 0x12, 0x07, 0xE4, 0xE0, -	0xF5, 0x4A, 0x12, 0x07, 0xF0, 0xE0, 0xF5, 0x4C, -/*1C70*/0xE5, 0x35, 0xB4, 0x01, 0x04, 0x7F, 0x01, 0x80, -	0x02, 0x7F, 0x00, 0xE5, 0x35, 0xB4, 0x02, 0x04, -/*1C80*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, -	0x60, 0x0C, 0x12, 0x07, 0xFC, 0xE0, 0xF5, 0x4A, -/*1C90*/0x12, 0x08, 0x08, 0xE0, 0xF5, 0x4C, 0x85, 0x41, -	0x49, 0x85, 0x40, 0x4B, 0x22, 0x75, 0x5B, 0x01, -/*1CA0*/0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE0, 0x54, -	0x1F, 0xFF, 0xD3, 0x94, 0x02, 0x50, 0x04, 0x8F, -/*1CB0*/0x58, 0x80, 0x05, 0xEF, 0x24, 0xFE, 0xF5, 0x58, -	0xEF, 0xC3, 0x94, 0x18, 0x40, 0x05, 0x75, 0x59, -/*1CC0*/0x18, 0x80, 0x04, 0xEF, 0x04, 0xF5, 0x59, 0x85, -	0x43, 0x5A, 0xAF, 0x58, 0x7E, 0x00, 0xAD, 0x59, -/*1CD0*/0x7C, 0x00, 0xAB, 0x5B, 0x7A, 0x00, 0x12, 0x15, -	0x41, 0xAF, 0x5A, 0x7E, 0x00, 0x12, 0x18, 0x0A, -/*1CE0*/0xAF, 0x5B, 0x7E, 0x00, 0x02, 0x1A, 0xFF, 0xE5, -	0xE2, 0x30, 0xE7, 0x0E, 0x12, 0x10, 0x03, 0xC2, -/*1CF0*/0x30, 0x30, 0x30, 0x03, 0x12, 0x10, 0xFF, 0x20, -	0x33, 0x28, 0xE5, 0xE7, 0x30, 0xE7, 0x05, 0x12, -/*1D00*/0x0E, 0xA2, 0x80, 0x0D, 0xE5, 0xFE, 0xC3, 0x94, -	0x20, 0x50, 0x06, 0x12, 0x0E, 0xA2, 0x43, 0xF9, -/*1D10*/0x08, 0xE5, 0xF2, 0x30, 0xE7, 0x03, 0x53, 0xF9, -	0x7F, 0xE5, 0xF1, 0x54, 0x70, 0xD3, 0x94, 0x00, -/*1D20*/0x50, 0xD8, 0x22, 0x12, 0x0E, 0x04, 0x75, 0x83, -	0x80, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0x12, -/*1D30*/0x0D, 0xFD, 0x75, 0x83, 0x84, 0x12, 0x0E, 0x02, -	0x75, 0x83, 0x86, 0x12, 0x0E, 0x02, 0x75, 0x83, -/*1D40*/0x8C, 0xE0, 0x54, 0xF3, 0x12, 0x0E, 0x03, 0x75, -	0x83, 0x8E, 0x12, 0x0E, 0x02, 0x75, 0x83, 0x94, -/*1D50*/0xE0, 0x54, 0xFB, 0xF0, 0x22, 0x12, 0x07, 0x2A, -	0x75, 0x83, 0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74, -/*1D60*/0x01, 0x12, 0x07, 0x29, 0xE4, 0x12, 0x08, 0xBE, -	0x75, 0x83, 0x8C, 0xE0, 0x44, 0x20, 0x12, 0x08, -/*1D70*/0xBE, 0xE0, 0x54, 0xDF, 0xF0, 0x74, 0x84, 0x85, -	0x08, 0x82, 0xF5, 0x83, 0xE0, 0x54, 0x7F, 0xF0, -/*1D80*/0xE0, 0x44, 0x80, 0xF0, 0x22, 0x75, 0x56, 0x01, -	0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE, 0xFC, -/*1D90*/0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12, 0x1E, -	0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E, 0x00, -/*1DA0*/0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF, -	0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0x75, 0x56, -/*1DB0*/0x01, 0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE, -	0xFC, 0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12, -/*1DC0*/0x1E, 0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E, -	0x00, 0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, -/*1DD0*/0xAF, 0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xE4, -	0xF5, 0x16, 0x12, 0x0E, 0x44, 0xFE, 0xE5, 0x08, -/*1DE0*/0x44, 0x05, 0xFF, 0x12, 0x0E, 0x65, 0x8F, 0x82, -	0x8E, 0x83, 0xF0, 0x05, 0x16, 0xE5, 0x16, 0xC3, -/*1DF0*/0x94, 0x14, 0x40, 0xE6, 0xE5, 0x08, 0x12, 0x0E, -	0x2B, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5, -/*1E00*/0x59, 0xF5, 0x5A, 0xFF, 0xFE, 0xAD, 0x58, 0xFC, -	0x12, 0x09, 0x15, 0x7F, 0x04, 0x7E, 0x00, 0xAD, -/*1E10*/0x58, 0x7C, 0x00, 0x12, 0x09, 0x15, 0x7F, 0x02, -	0x7E, 0x00, 0xAD, 0x58, 0x7C, 0x00, 0x02, 0x09, -/*1E20*/0x15, 0xE5, 0x3C, 0x25, 0x3E, 0xFC, 0xE5, 0x42, -	0x24, 0x00, 0xFB, 0xE4, 0x33, 0xFA, 0xEC, 0xC3, -/*1E30*/0x9B, 0xEA, 0x12, 0x07, 0x6B, 0x40, 0x0B, 0x8C, -	0x42, 0xE5, 0x3D, 0x25, 0x3F, 0xF5, 0x41, 0x8F, -/*1E40*/0x40, 0x22, 0x12, 0x09, 0x0B, 0x22, 0x74, 0x84, -	0xF5, 0x18, 0x85, 0x08, 0x19, 0x85, 0x19, 0x82, -/*1E50*/0x85, 0x18, 0x83, 0xE0, 0x54, 0x7F, 0xF0, 0xE0, -	0x44, 0x80, 0xF0, 0xE0, 0x44, 0x80, 0xF0, 0x22, -/*1E60*/0xEF, 0x4E, 0x70, 0x0B, 0x12, 0x07, 0x2A, 0x75, -	0x83, 0xD2, 0xE0, 0x54, 0xDF, 0xF0, 0x22, 0x12, -/*1E70*/0x07, 0x2A, 0x75, 0x83, 0xD2, 0xE0, 0x44, 0x20, -	0xF0, 0x22, 0x75, 0x58, 0x01, 0x90, 0x07, 0x26, -/*1E80*/0x12, 0x07, 0x35, 0xE0, 0x54, 0x3F, 0xF5, 0x41, -	0x12, 0x07, 0x32, 0xE0, 0x54, 0x3F, 0xF5, 0x40, -/*1E90*/0x22, 0x75, 0x56, 0x02, 0xE4, 0xF5, 0x57, 0x12, -	0x1D, 0xFC, 0xAF, 0x57, 0x7E, 0x00, 0xAD, 0x56, -/*1EA0*/0x7C, 0x00, 0x02, 0x04, 0x44, 0xE4, 0xF5, 0x42, -	0xF5, 0x41, 0xF5, 0x40, 0xF5, 0x38, 0xF5, 0x39, -/*1EB0*/0xF5, 0x3A, 0x22, 0xEF, 0x54, 0x07, 0xFF, 0xE5, -	0xF9, 0x54, 0xF8, 0x4F, 0xF5, 0xF9, 0x22, 0x7F, -/*1EC0*/0x01, 0xE4, 0xFE, 0x0F, 0x0E, 0xBE, 0xFF, 0xFB, -	0x22, 0x01, 0x20, 0x00, 0x01, 0x04, 0x20, 0x00, -/*1ED0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1EE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1EF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1F00*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1F10*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1F20*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1F30*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1F40*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1F50*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1F60*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1F70*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1F80*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1F90*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1FA0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1FB0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1FC0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1FD0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1FE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/*1FF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -	0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x81 -}; - -int qib_sd7220_ib_load(struct qib_devdata *dd) -{ -	return qib_sd7220_prog_ld(dd, IB_7220_SERDES, qib_sd7220_ib_img, -		sizeof(qib_sd7220_ib_img), 0); -} - -int qib_sd7220_ib_vfy(struct qib_devdata *dd) -{ -	return qib_sd7220_prog_vfy(dd, IB_7220_SERDES, qib_sd7220_ib_img, -		sizeof(qib_sd7220_ib_img), 0); -} diff --git a/drivers/infiniband/hw/qib/qib_tx.c b/drivers/infiniband/hw/qib/qib_tx.c index f7eb1ddff5f..af30232b683 100644 --- a/drivers/infiniband/hw/qib/qib_tx.c +++ b/drivers/infiniband/hw/qib/qib_tx.c @@ -340,9 +340,13 @@ rescan:  		if (i < dd->piobcnt2k)  			buf = (u32 __iomem *)(dd->pio2kbase +  				i * dd->palign); -		else +		else if (i < dd->piobcnt2k + dd->piobcnt4k || !dd->piovl15base)  			buf = (u32 __iomem *)(dd->pio4kbase +  				(i - dd->piobcnt2k) * dd->align4k); +		else +			buf = (u32 __iomem *)(dd->piovl15base + +				(i - (dd->piobcnt2k + dd->piobcnt4k)) * +				dd->align4k);  		if (pbufnum)  			*pbufnum = i;  		dd->upd_pio_shadow = 0; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index df3eb8c9fd9..b4b22576f12 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1163,7 +1163,7 @@ static ssize_t create_child(struct device *dev,  	return ret ? ret : count;  } -static DEVICE_ATTR(create_child, S_IWUGO, NULL, create_child); +static DEVICE_ATTR(create_child, S_IWUSR, NULL, create_child);  static ssize_t delete_child(struct device *dev,  			    struct device_attribute *attr, @@ -1183,7 +1183,7 @@ static ssize_t delete_child(struct device *dev,  	return ret ? ret : count;  } -static DEVICE_ATTR(delete_child, S_IWUGO, NULL, delete_child); +static DEVICE_ATTR(delete_child, S_IWUSR, NULL, delete_child);  int ipoib_add_pkey_attr(struct net_device *dev)  { diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index fbd62abb66f..0ffaf2c77a1 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -89,7 +89,6 @@ struct gc_pad {  struct gc {  	struct pardevice *pd;  	struct gc_pad pads[GC_MAX_DEVICES]; -	struct input_dev *dev[GC_MAX_DEVICES];  	struct timer_list timer;  	int pad_count[GC_MAX];  	int used; @@ -387,7 +386,7 @@ static void gc_nes_process_packet(struct gc *gc)  	for (i = 0; i < GC_MAX_DEVICES; i++) {  		pad = &gc->pads[i]; -		dev = gc->dev[i]; +		dev = pad->dev;  		s = gc_status_bit[i];  		switch (pad->type) { @@ -579,7 +578,7 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char *data)  		read = parport_read_status(port) ^ 0x80;  		for (j = 0; j < GC_MAX_DEVICES; j++) { -			struct gc_pad *pad = &gc->pads[i]; +			struct gc_pad *pad = &gc->pads[j];  			if (pad->type == GC_PSX || pad->type == GC_DDR)  				data[j] |= (read & gc_status_bit[j]) ? (1 << i) : 0; diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index d8fa5d724c5..1ba25145b33 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -73,7 +73,7 @@ config KEYBOARD_ATKBD  	default y  	select SERIO  	select SERIO_LIBPS2 -	select SERIO_I8042 if X86 && !X86_MRST +	select SERIO_I8042 if X86  	select SERIO_GSCPS2 if GSC  	help  	  Say Y here if you want to use a standard AT or PS/2 keyboard. Usually @@ -124,7 +124,7 @@ config KEYBOARD_ATKBD_RDI_KEYCODES  	  right-hand column will be interpreted as the key shown in the  	  left-hand column. -config QT2160 +config KEYBOARD_QT2160  	tristate "Atmel AT42QT2160 Touch Sensor Chip"  	depends on I2C && EXPERIMENTAL  	help diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 7aa59e07b68..fb16b5e5ea1 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -51,8 +51,12 @@   */  #define TWL4030_MAX_ROWS	8	/* TWL4030 hard limit */  #define TWL4030_MAX_COLS	8 -#define TWL4030_ROW_SHIFT	3 -#define TWL4030_KEYMAP_SIZE	(TWL4030_MAX_ROWS * TWL4030_MAX_COLS) +/* + * Note that we add space for an extra column so that we can handle + * row lines connected to the gnd (see twl4030_col_xlate()). + */ +#define TWL4030_ROW_SHIFT	4 +#define TWL4030_KEYMAP_SIZE	(TWL4030_MAX_ROWS << TWL4030_ROW_SHIFT)  struct twl4030_keypad {  	unsigned short	keymap[TWL4030_KEYMAP_SIZE]; @@ -182,7 +186,7 @@ static int twl4030_read_kp_matrix_state(struct twl4030_keypad *kp, u16 *state)  	return ret;  } -static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state) +static bool twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)  {  	int i;  	u16 check = 0; @@ -191,12 +195,12 @@ static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)  		u16 col = key_state[i];  		if ((col & check) && hweight16(col) > 1) -			return 1; +			return true;  		check |= col;  	} -	return 0; +	return false;  }  static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all) @@ -225,7 +229,8 @@ static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)  		if (!changed)  			continue; -		for (col = 0; col < kp->n_cols; col++) { +		/* Extra column handles "all gnd" rows */ +		for (col = 0; col < kp->n_cols + 1; col++) {  			int code;  			if (!(changed & (1 << col))) diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index 4ef764cc493..ee2bf6bcf29 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c @@ -258,7 +258,7 @@ static struct platform_driver w90p910_keypad_driver = {  	.probe		= w90p910_keypad_probe,  	.remove		= __devexit_p(w90p910_keypad_remove),  	.driver		= { -		.name	= "nuc900-keypad", +		.name	= "nuc900-kpi",  		.owner	= THIS_MODULE,  	},  }; diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c index 0ac47d2898e..4b42ffc0532 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c @@ -69,7 +69,7 @@ static irqreturn_t pcf8574_kp_irq_handler(int irq, void *dev_id)  	unsigned char nextstate = read_state(lp);  	if (lp->laststate != nextstate) { -		int key_down = nextstate <= ARRAY_SIZE(lp->btncode); +		int key_down = nextstate < ARRAY_SIZE(lp->btncode);  		unsigned short keycode = key_down ?  			lp->btncode[nextstate] : lp->btncode[lp->laststate]; diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index eeb58c1cac1..c714ca2407f 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -17,7 +17,7 @@ config MOUSE_PS2  	default y  	select SERIO  	select SERIO_LIBPS2 -	select SERIO_I8042 if X86 && !X86_MRST +	select SERIO_I8042 if X86  	select SERIO_GSCPS2 if GSC  	help  	  Say Y here if you have a PS/2 mouse connected to your system. This diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 40cea334ad1..705589dc9ac 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -141,8 +141,13 @@ static int synaptics_capability(struct psmouse *psmouse)  	priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];  	priv->ext_cap = priv->ext_cap_0c = 0; -	if (!SYN_CAP_VALID(priv->capabilities)) +	/* +	 * Older firmwares had submodel ID fixed to 0x47 +	 */ +	if (SYN_ID_FULL(priv->identity) < 0x705 && +	    SYN_CAP_SUBMODEL_ID(priv->capabilities) != 0x47) {  		return -1; +	}  	/*  	 * Unless capExtended is set the rest of the flags should be ignored @@ -206,6 +211,7 @@ static int synaptics_resolution(struct psmouse *psmouse)  	unsigned char max[3];  	if (SYN_ID_MAJOR(priv->identity) < 4) +		return 0;  	if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res) == 0) {  		if (res[0] != 0 && (res[1] & 0x80) && res[2] != 0) { diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 7d4d5e12c0d..b6aa7d20d8a 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -47,7 +47,7 @@  #define SYN_CAP_FOUR_BUTTON(c)		((c) & (1 << 3))  #define SYN_CAP_MULTIFINGER(c)		((c) & (1 << 1))  #define SYN_CAP_PALMDETECT(c)		((c) & (1 << 0)) -#define SYN_CAP_VALID(c)		((((c) & 0x00ff00) >> 8) == 0x47) +#define SYN_CAP_SUBMODEL_ID(c)		(((c) & 0x00ff00) >> 8)  #define SYN_EXT_CAP_REQUESTS(c)		(((c) & 0x700000) >> 20)  #define SYN_CAP_MULTI_BUTTON_NO(ec)	(((ec) & 0x00f000) >> 12)  #define SYN_CAP_PRODUCT_ID(ec)		(((ec) & 0xff0000) >> 16) @@ -66,6 +66,7 @@  #define SYN_ID_MODEL(i)			(((i) >> 4) & 0x0f)  #define SYN_ID_MAJOR(i)			((i) & 0x0f)  #define SYN_ID_MINOR(i)			(((i) >> 16) & 0xff) +#define SYN_ID_FULL(i)			((SYN_ID_MAJOR(i) << 8) | SYN_ID_MINOR(i))  #define SYN_ID_IS_SYNAPTICS(i)		((((i) >> 8) & 0xff) == 0x47)  /* synaptics special commands */ diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 6168469ad1a..ed7ad7416b2 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -7,6 +7,10 @@   * the Free Software Foundation.   */ +#ifdef CONFIG_X86 +#include <asm/x86_init.h> +#endif +  /*   * Names.   */ @@ -166,6 +170,13 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {  		},  	},  	{ +		/* Gigabyte Spring Peak - defines wrong chassis type */ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"), +		}, +	}, +	{  		.matches = {  			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),  			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"), @@ -840,6 +851,12 @@ static int __init i8042_platform_init(void)  {  	int retval; +#ifdef CONFIG_X86 +	/* Just return if pre-detection shows no i8042 controller exist */ +	if (!x86_platform.i8042_detect()) +		return -ENODEV; +#endif +  /*   * On ix86 platforms touching the i8042 data register region can do really   * bad things. Because of this the region is always reserved on ix86 boxes. diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index d564af58175..415f6306105 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -284,12 +284,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)  			(data[4] << 20) + (data[5] << 12) +  			(data[6] << 4) + (data[7] >> 4); -		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4); +		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) | +			((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12); -		switch (wacom->id[idx]) { +		switch (wacom->id[idx] & 0xfffff) {  		case 0x812: /* Inking pen */  		case 0x801: /* Intuos3 Inking pen */ -		case 0x20802: /* Intuos4 Classic Pen */ +		case 0x20802: /* Intuos4 Inking Pen */  		case 0x012:  			wacom->tool[idx] = BTN_TOOL_PENCIL;  			break; @@ -513,7 +514,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)  			input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);  			input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); -			if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) | +			if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |  				data[2] | (data[3] & 0x1f) | data[4] | data[8] |  				(data[7] & 0x01)) {  				input_report_key(input, wacom->tool[1], 1); diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index 0d2d7e54b46..5f0221cffef 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -679,6 +679,13 @@ static int __devinit ad7877_probe(struct spi_device *spi)  		return -EINVAL;  	} +	spi->bits_per_word = 16; +	err = spi_setup(spi); +	if (err) { +		dev_dbg(&spi->dev, "spi master doesn't support 16 bits/word\n"); +		return err; +	} +  	ts = kzalloc(sizeof(struct ad7877), GFP_KERNEL);  	input_dev = input_allocate_device();  	if (!ts || !input_dev) { diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index cc18265be1a..7a45d68c351 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c @@ -233,7 +233,7 @@ static int __devinit w90x900ts_probe(struct platform_device *pdev)  	w90p910_ts->state = TS_IDLE;  	spin_lock_init(&w90p910_ts->lock);  	setup_timer(&w90p910_ts->timer, w90p910_check_pen_up, -		    (unsigned long)&w90p910_ts); +		    (unsigned long)w90p910_ts);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) { diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index c5016bd2d94..c3b1dc3a13a 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -126,26 +126,6 @@ static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf)  	return numbytes;  } -/* set up next receive skb for data mode - */ -static void new_rcv_skb(struct bc_state *bcs) -{ -	struct cardstate *cs = bcs->cs; -	unsigned short hw_hdr_len = cs->hw_hdr_len; - -	if (bcs->ignore) { -		bcs->skb = NULL; -		return; -	} - -	bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len); -	if (bcs->skb == NULL) { -		dev_warn(cs->dev, "could not allocate new skb\n"); -		return; -	} -	skb_reserve(bcs->skb, hw_hdr_len); -} -  /* process a block of received bytes in HDLC data mode   * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC)   * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. @@ -159,8 +139,8 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)  	struct cardstate *cs = inbuf->cs;  	struct bc_state *bcs = cs->bcs;  	int inputstate = bcs->inputstate; -	__u16 fcs = bcs->fcs; -	struct sk_buff *skb = bcs->skb; +	__u16 fcs = bcs->rx_fcs; +	struct sk_buff *skb = bcs->rx_skb;  	unsigned char *src = inbuf->data + inbuf->head;  	unsigned procbytes = 0;  	unsigned char c; @@ -245,8 +225,7 @@ byte_stuff:  				/* prepare reception of next frame */  				inputstate &= ~INS_have_data; -				new_rcv_skb(bcs); -				skb = bcs->skb; +				skb = gigaset_new_rx_skb(bcs);  			} else {  				/* empty frame (7E 7E) */  #ifdef CONFIG_GIGASET_DEBUG @@ -255,8 +234,7 @@ byte_stuff:  				if (!skb) {  					/* skipped (?) */  					gigaset_isdn_rcv_err(bcs); -					new_rcv_skb(bcs); -					skb = bcs->skb; +					skb = gigaset_new_rx_skb(bcs);  				}  			} @@ -279,11 +257,11 @@ byte_stuff:  #endif  		inputstate |= INS_have_data;  		if (skb) { -			if (skb->len == SBUFSIZE) { +			if (skb->len >= bcs->rx_bufsize) {  				dev_warn(cs->dev, "received packet too long\n");  				dev_kfree_skb_any(skb);  				/* skip remainder of packet */ -				bcs->skb = skb = NULL; +				bcs->rx_skb = skb = NULL;  			} else {  				*__skb_put(skb, 1) = c;  				fcs = crc_ccitt_byte(fcs, c); @@ -292,7 +270,7 @@ byte_stuff:  	}  	bcs->inputstate = inputstate; -	bcs->fcs = fcs; +	bcs->rx_fcs = fcs;  	return procbytes;  } @@ -308,18 +286,18 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)  	struct cardstate *cs = inbuf->cs;  	struct bc_state *bcs = cs->bcs;  	int inputstate = bcs->inputstate; -	struct sk_buff *skb = bcs->skb; +	struct sk_buff *skb = bcs->rx_skb;  	unsigned char *src = inbuf->data + inbuf->head;  	unsigned procbytes = 0;  	unsigned char c;  	if (!skb) {  		/* skip this block */ -		new_rcv_skb(bcs); +		gigaset_new_rx_skb(bcs);  		return numbytes;  	} -	while (procbytes < numbytes && skb->len < SBUFSIZE) { +	while (procbytes < numbytes && skb->len < bcs->rx_bufsize) {  		c = *src++;  		procbytes++; @@ -343,7 +321,7 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)  	if (inputstate & INS_have_data) {  		gigaset_skb_rcvd(bcs, skb);  		inputstate &= ~INS_have_data; -		new_rcv_skb(bcs); +		gigaset_new_rx_skb(bcs);  	}  	bcs->inputstate = inputstate; diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 8f78f15c8ef..6fbe8999c41 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -70,7 +70,7 @@  #define MAX_NUMBER_DIGITS 20  #define MAX_FMT_IE_LEN 20 -/* values for gigaset_capi_appl.connected */ +/* values for bcs->apconnstate */  #define APCONN_NONE	0	/* inactive/listening */  #define APCONN_SETUP	1	/* connecting */  #define APCONN_ACTIVE	2	/* B channel up */ @@ -80,10 +80,10 @@ struct gigaset_capi_appl {  	struct list_head ctrlist;  	struct gigaset_capi_appl *bcnext;  	u16 id; +	struct capi_register_params rp;  	u16 nextMessageNumber;  	u32 listenInfoMask;  	u32 listenCIPmask; -	int connected;  };  /* CAPI specific controller data structure */ @@ -319,6 +319,39 @@ static const char *format_ie(const char *ie)  	return result;  } +/* + * emit DATA_B3_CONF message + */ +static void send_data_b3_conf(struct cardstate *cs, struct capi_ctr *ctr, +			      u16 appl, u16 msgid, int channel, +			      u16 handle, u16 info) +{ +	struct sk_buff *cskb; +	u8 *msg; + +	cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC); +	if (!cskb) { +		dev_err(cs->dev, "%s: out of memory\n", __func__); +		return; +	} +	/* frequent message, avoid _cmsg overhead */ +	msg = __skb_put(cskb, CAPI_DATA_B3_CONF_LEN); +	CAPIMSG_SETLEN(msg, CAPI_DATA_B3_CONF_LEN); +	CAPIMSG_SETAPPID(msg, appl); +	CAPIMSG_SETCOMMAND(msg, CAPI_DATA_B3); +	CAPIMSG_SETSUBCOMMAND(msg,  CAPI_CONF); +	CAPIMSG_SETMSGID(msg, msgid); +	CAPIMSG_SETCONTROLLER(msg, ctr->cnr); +	CAPIMSG_SETPLCI_PART(msg, channel); +	CAPIMSG_SETNCCI_PART(msg, 1); +	CAPIMSG_SETHANDLE_CONF(msg, handle); +	CAPIMSG_SETINFO_CONF(msg, info); + +	/* emit message */ +	dump_rawmsg(DEBUG_MCMD, __func__, msg); +	capi_ctr_handle_message(ctr, appl, cskb); +} +  /*   * driver interface functions @@ -339,7 +372,6 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)  	struct gigaset_capi_ctr *iif = cs->iif;  	struct gigaset_capi_appl *ap = bcs->ap;  	unsigned char *req = skb_mac_header(dskb); -	struct sk_buff *cskb;  	u16 flags;  	/* update statistics */ @@ -351,39 +383,22 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)  	}  	/* don't send further B3 messages if disconnected */ -	if (ap->connected < APCONN_ACTIVE) { +	if (bcs->apconnstate < APCONN_ACTIVE) {  		gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack");  		return;  	} -	/* ToDo: honor unset "delivery confirmation" bit */ +	/* +	 * send DATA_B3_CONF if "delivery confirmation" bit was set in request; +	 * otherwise it has already been sent by do_data_b3_req() +	 */  	flags = CAPIMSG_FLAGS(req); - -	/* build DATA_B3_CONF message */ -	cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC); -	if (!cskb) { -		dev_err(cs->dev, "%s: out of memory\n", __func__); -		return; -	} -	/* frequent message, avoid _cmsg overhead */ -	CAPIMSG_SETLEN(cskb->data, CAPI_DATA_B3_CONF_LEN); -	CAPIMSG_SETAPPID(cskb->data, ap->id); -	CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3); -	CAPIMSG_SETSUBCOMMAND(cskb->data,  CAPI_CONF); -	CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req)); -	CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr); -	CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1); -	CAPIMSG_SETNCCI_PART(cskb->data, 1); -	CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req)); -	if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) -		CAPIMSG_SETINFO_CONF(cskb->data, -				     CapiFlagsNotSupportedByProtocol); -	else -		CAPIMSG_SETINFO_CONF(cskb->data, CAPI_NOERROR); - -	/* emit message */ -	dump_rawmsg(DEBUG_LLDATA, "DATA_B3_CONF", cskb->data); -	capi_ctr_handle_message(&iif->ctr, ap->id, cskb); +	if (flags & CAPI_FLAGS_DELIVERY_CONFIRMATION) +		send_data_b3_conf(cs, &iif->ctr, ap->id, CAPIMSG_MSGID(req), +				  bcs->channel + 1, CAPIMSG_HANDLE_REQ(req), +				  (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) ? +					CapiFlagsNotSupportedByProtocol : +					CAPI_NOERROR);  }  EXPORT_SYMBOL_GPL(gigaset_skb_sent); @@ -412,7 +427,7 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)  	}  	/* don't send further B3 messages if disconnected */ -	if (ap->connected < APCONN_ACTIVE) { +	if (bcs->apconnstate < APCONN_ACTIVE) {  		gig_dbg(DEBUG_LLDATA, "disconnected, discarding data");  		dev_kfree_skb_any(skb);  		return; @@ -484,6 +499,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state)  	u32 actCIPmask;  	struct sk_buff *skb;  	unsigned int msgsize; +	unsigned long flags;  	int i;  	/* @@ -608,7 +624,14 @@ int gigaset_isdn_icall(struct at_state_t *at_state)  		format_ie(iif->hcmsg.CalledPartyNumber));  	/* scan application list for matching listeners */ -	bcs->ap = NULL; +	spin_lock_irqsave(&bcs->aplock, flags); +	if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) { +		dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n", +			 __func__, bcs->ap, bcs->apconnstate); +		bcs->ap = NULL; +		bcs->apconnstate = APCONN_NONE; +	} +	spin_unlock_irqrestore(&bcs->aplock, flags);  	actCIPmask = 1 | (1 << iif->hcmsg.CIPValue);  	list_for_each_entry(ap, &iif->appls, ctrlist)  		if (actCIPmask & ap->listenCIPmask) { @@ -626,10 +649,12 @@ int gigaset_isdn_icall(struct at_state_t *at_state)  			dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);  			/* add to listeners on this B channel, update state */ +			spin_lock_irqsave(&bcs->aplock, flags);  			ap->bcnext = bcs->ap;  			bcs->ap = ap;  			bcs->chstate |= CHS_NOTIFY_LL; -			ap->connected = APCONN_SETUP; +			bcs->apconnstate = APCONN_SETUP; +			spin_unlock_irqrestore(&bcs->aplock, flags);  			/* emit message */  			capi_ctr_handle_message(&iif->ctr, ap->id, skb); @@ -654,7 +679,7 @@ static void send_disconnect_ind(struct bc_state *bcs,  	struct gigaset_capi_ctr *iif = cs->iif;  	struct sk_buff *skb; -	if (ap->connected == APCONN_NONE) +	if (bcs->apconnstate == APCONN_NONE)  		return;  	capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND, @@ -668,7 +693,6 @@ static void send_disconnect_ind(struct bc_state *bcs,  	}  	capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN));  	dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); -	ap->connected = APCONN_NONE;  	capi_ctr_handle_message(&iif->ctr, ap->id, skb);  } @@ -685,9 +709,9 @@ static void send_disconnect_b3_ind(struct bc_state *bcs,  	struct sk_buff *skb;  	/* nothing to do if no logical connection active */ -	if (ap->connected < APCONN_ACTIVE) +	if (bcs->apconnstate < APCONN_ACTIVE)  		return; -	ap->connected = APCONN_SETUP; +	bcs->apconnstate = APCONN_SETUP;  	capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND,  			 ap->nextMessageNumber++, @@ -714,14 +738,25 @@ void gigaset_isdn_connD(struct bc_state *bcs)  {  	struct cardstate *cs = bcs->cs;  	struct gigaset_capi_ctr *iif = cs->iif; -	struct gigaset_capi_appl *ap = bcs->ap; +	struct gigaset_capi_appl *ap;  	struct sk_buff *skb;  	unsigned int msgsize; +	unsigned long flags; +	spin_lock_irqsave(&bcs->aplock, flags); +	ap = bcs->ap;  	if (!ap) { +		spin_unlock_irqrestore(&bcs->aplock, flags);  		dev_err(cs->dev, "%s: no application\n", __func__);  		return;  	} +	if (bcs->apconnstate == APCONN_NONE) { +		spin_unlock_irqrestore(&bcs->aplock, flags); +		dev_warn(cs->dev, "%s: application %u not connected\n", +			 __func__, ap->id); +		return; +	} +	spin_unlock_irqrestore(&bcs->aplock, flags);  	while (ap->bcnext) {  		/* this should never happen */  		dev_warn(cs->dev, "%s: dropping extra application %u\n", @@ -730,11 +765,6 @@ void gigaset_isdn_connD(struct bc_state *bcs)  				    CapiCallGivenToOtherApplication);  		ap->bcnext = ap->bcnext->bcnext;  	} -	if (ap->connected == APCONN_NONE) { -		dev_warn(cs->dev, "%s: application %u not connected\n", -			 __func__, ap->id); -		return; -	}  	/* prepare CONNECT_ACTIVE_IND message  	 * Note: LLC not supported by device @@ -772,17 +802,24 @@ void gigaset_isdn_connD(struct bc_state *bcs)  void gigaset_isdn_hupD(struct bc_state *bcs)  {  	struct gigaset_capi_appl *ap; +	unsigned long flags;  	/*  	 * ToDo: pass on reason code reported by device  	 * (requires ev-layer state machine extension to collect  	 * ZCAU device reply)  	 */ -	for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) { +	spin_lock_irqsave(&bcs->aplock, flags); +	while (bcs->ap != NULL) { +		ap = bcs->ap; +		bcs->ap = ap->bcnext; +		spin_unlock_irqrestore(&bcs->aplock, flags);  		send_disconnect_b3_ind(bcs, ap);  		send_disconnect_ind(bcs, ap, 0); +		spin_lock_irqsave(&bcs->aplock, flags);  	} -	bcs->ap = NULL; +	bcs->apconnstate = APCONN_NONE; +	spin_unlock_irqrestore(&bcs->aplock, flags);  }  /** @@ -796,24 +833,21 @@ void gigaset_isdn_connB(struct bc_state *bcs)  {  	struct cardstate *cs = bcs->cs;  	struct gigaset_capi_ctr *iif = cs->iif; -	struct gigaset_capi_appl *ap = bcs->ap; +	struct gigaset_capi_appl *ap;  	struct sk_buff *skb; +	unsigned long flags;  	unsigned int msgsize;  	u8 command; +	spin_lock_irqsave(&bcs->aplock, flags); +	ap = bcs->ap;  	if (!ap) { +		spin_unlock_irqrestore(&bcs->aplock, flags);  		dev_err(cs->dev, "%s: no application\n", __func__);  		return;  	} -	while (ap->bcnext) { -		/* this should never happen */ -		dev_warn(cs->dev, "%s: dropping extra application %u\n", -			 __func__, ap->bcnext->id); -		send_disconnect_ind(bcs, ap->bcnext, -				    CapiCallGivenToOtherApplication); -		ap->bcnext = ap->bcnext->bcnext; -	} -	if (!ap->connected) { +	if (!bcs->apconnstate) { +		spin_unlock_irqrestore(&bcs->aplock, flags);  		dev_warn(cs->dev, "%s: application %u not connected\n",  			 __func__, ap->id);  		return; @@ -825,13 +859,26 @@ void gigaset_isdn_connB(struct bc_state *bcs)  	 * CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP  	 * Parameters in both cases always: NCCI = 1, NCPI empty  	 */ -	if (ap->connected >= APCONN_ACTIVE) { +	if (bcs->apconnstate >= APCONN_ACTIVE) {  		command = CAPI_CONNECT_B3_ACTIVE;  		msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN;  	} else {  		command = CAPI_CONNECT_B3;  		msgsize = CAPI_CONNECT_B3_IND_BASELEN;  	} +	bcs->apconnstate = APCONN_ACTIVE; + +	spin_unlock_irqrestore(&bcs->aplock, flags); + +	while (ap->bcnext) { +		/* this should never happen */ +		dev_warn(cs->dev, "%s: dropping extra application %u\n", +			 __func__, ap->bcnext->id); +		send_disconnect_ind(bcs, ap->bcnext, +				    CapiCallGivenToOtherApplication); +		ap->bcnext = ap->bcnext->bcnext; +	} +  	capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND,  			 ap->nextMessageNumber++,  			 iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); @@ -842,7 +889,6 @@ void gigaset_isdn_connB(struct bc_state *bcs)  	}  	capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize));  	dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); -	ap->connected = APCONN_ACTIVE;  	capi_ctr_handle_message(&iif->ctr, ap->id, skb);  } @@ -945,8 +991,64 @@ static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl,  		return;  	}  	ap->id = appl; +	ap->rp = *rp;  	list_add(&ap->ctrlist, &iif->appls); +	dev_info(cs->dev, "application %u registered\n", ap->id); +} + +/* + * remove CAPI application from channel + * helper function to keep indentation levels down and stay in 80 columns + */ + +static inline void remove_appl_from_channel(struct bc_state *bcs, +					    struct gigaset_capi_appl *ap) +{ +	struct cardstate *cs = bcs->cs; +	struct gigaset_capi_appl *bcap; +	unsigned long flags; +	int prevconnstate; + +	spin_lock_irqsave(&bcs->aplock, flags); +	bcap = bcs->ap; +	if (bcap == NULL) { +		spin_unlock_irqrestore(&bcs->aplock, flags); +		return; +	} + +	/* check first application on channel */ +	if (bcap == ap) { +		bcs->ap = ap->bcnext; +		if (bcs->ap != NULL) { +			spin_unlock_irqrestore(&bcs->aplock, flags); +			return; +		} + +		/* none left, clear channel state */ +		prevconnstate = bcs->apconnstate; +		bcs->apconnstate = APCONN_NONE; +		spin_unlock_irqrestore(&bcs->aplock, flags); + +		if (prevconnstate == APCONN_ACTIVE) { +			dev_notice(cs->dev, "%s: hanging up channel %u\n", +				   __func__, bcs->channel); +			gigaset_add_event(cs, &bcs->at_state, +					  EV_HUP, NULL, 0, NULL); +			gigaset_schedule_event(cs); +		} +		return; +	} + +	/* check remaining list */ +	do { +		if (bcap->bcnext == ap) { +			bcap->bcnext = bcap->bcnext->bcnext; +			return; +		} +		bcap = bcap->bcnext; +	} while (bcap != NULL); +	spin_unlock_irqrestore(&bcs->aplock, flags);  }  /* @@ -958,19 +1060,19 @@ static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl)  		= container_of(ctr, struct gigaset_capi_ctr, ctr);  	struct cardstate *cs = iif->ctr.driverdata;  	struct gigaset_capi_appl *ap, *tmp; +	unsigned ch;  	list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist)  		if (ap->id == appl) { -			if (ap->connected != APCONN_NONE) { -				dev_err(cs->dev, -					"%s: application %u still connected\n", -					__func__, ap->id); -				/* ToDo: clear active connection */ -			} +			/* remove from any channels */ +			for (ch = 0; ch < cs->channels; ch++) +				remove_appl_from_channel(&cs->bcs[ch], ap); + +			/* remove from registration list */  			list_del(&ap->ctrlist);  			kfree(ap); +			dev_info(cs->dev, "application %u released\n", appl);  		} -  }  /* @@ -1149,7 +1251,8 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,  	char **commands;  	char *s;  	u8 *pp; -	int i, l; +	unsigned long flags; +	int i, l, lbc, lhlc;  	u16 info;  	/* decode message */ @@ -1164,8 +1267,18 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,  		send_conf(iif, ap, skb, CapiNoPlciAvailable);  		return;  	} +	spin_lock_irqsave(&bcs->aplock, flags); +	if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) +		dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n", +			 __func__, bcs->ap, bcs->apconnstate);  	ap->bcnext = NULL;  	bcs->ap = ap; +	bcs->apconnstate = APCONN_SETUP; +	spin_unlock_irqrestore(&bcs->aplock, flags); + +	bcs->rx_bufsize = ap->rp.datablklen; +	dev_kfree_skb(bcs->rx_skb); +	gigaset_new_rx_skb(bcs);  	cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8;  	/* build command table */ @@ -1273,42 +1386,59 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,  		goto error;  	} -	/* check/encode parameter: BC */ -	if (cmsg->BC && cmsg->BC[0]) { -		/* explicit BC overrides CIP */ -		l = 2*cmsg->BC[0] + 7; +	/* +	 * check/encode parameters: BC & HLC +	 * must be encoded together as device doesn't accept HLC separately +	 * explicit parameters override values derived from CIP +	 */ + +	/* determine lengths */ +	if (cmsg->BC && cmsg->BC[0])		/* BC specified explicitly */ +		lbc = 2*cmsg->BC[0]; +	else if (cip2bchlc[cmsg->CIPValue].bc)	/* BC derived from CIP */ +		lbc = strlen(cip2bchlc[cmsg->CIPValue].bc); +	else					/* no BC */ +		lbc = 0; +	if (cmsg->HLC && cmsg->HLC[0])		/* HLC specified explicitly */ +		lhlc = 2*cmsg->HLC[0]; +	else if (cip2bchlc[cmsg->CIPValue].hlc)	/* HLC derived from CIP */ +		lhlc = strlen(cip2bchlc[cmsg->CIPValue].hlc); +	else					/* no HLC */ +		lhlc = 0; + +	if (lbc) { +		/* have BC: allocate and assemble command string */ +		l = lbc + 7;		/* "^SBC=" + value + "\r" + null byte */ +		if (lhlc) +			l += lhlc + 7;	/* ";^SHLC=" + value */  		commands[AT_BC] = kmalloc(l, GFP_KERNEL);  		if (!commands[AT_BC])  			goto oom;  		strcpy(commands[AT_BC], "^SBC="); -		decode_ie(cmsg->BC, commands[AT_BC]+5); +		if (cmsg->BC && cmsg->BC[0])	/* BC specified explicitly */ +			decode_ie(cmsg->BC, commands[AT_BC] + 5); +		else				/* BC derived from CIP */ +			strcpy(commands[AT_BC] + 5, +			       cip2bchlc[cmsg->CIPValue].bc); +		if (lhlc) { +			strcpy(commands[AT_BC] + lbc + 5, ";^SHLC="); +			if (cmsg->HLC && cmsg->HLC[0]) +				/* HLC specified explicitly */ +				decode_ie(cmsg->HLC, +					  commands[AT_BC] + lbc + 12); +			else	/* HLC derived from CIP */ +				strcpy(commands[AT_BC] + lbc + 12, +				       cip2bchlc[cmsg->CIPValue].hlc); +		}  		strcpy(commands[AT_BC] + l - 2, "\r"); -	} else if (cip2bchlc[cmsg->CIPValue].bc) { -		l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7; -		commands[AT_BC] = kmalloc(l, GFP_KERNEL); -		if (!commands[AT_BC]) -			goto oom; -		snprintf(commands[AT_BC], l, "^SBC=%s\r", -			 cip2bchlc[cmsg->CIPValue].bc); -	} - -	/* check/encode parameter: HLC */ -	if (cmsg->HLC && cmsg->HLC[0]) { -		/* explicit HLC overrides CIP */ -		l = 2*cmsg->HLC[0] + 7; -		commands[AT_HLC] = kmalloc(l, GFP_KERNEL); -		if (!commands[AT_HLC]) -			goto oom; -		strcpy(commands[AT_HLC], "^SHLC="); -		decode_ie(cmsg->HLC, commands[AT_HLC]+5); -		strcpy(commands[AT_HLC] + l - 2, "\r"); -	} else if (cip2bchlc[cmsg->CIPValue].hlc) { -		l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7; -		commands[AT_HLC] = kmalloc(l, GFP_KERNEL); -		if (!commands[AT_HLC]) -			goto oom; -		snprintf(commands[AT_HLC], l, "^SHLC=%s\r", -			 cip2bchlc[cmsg->CIPValue].hlc); +	} else { +		/* no BC */ +		if (lhlc) { +			dev_notice(cs->dev, "%s: cannot set HLC without BC\n", +				   "CONNECT_REQ"); +			info = CapiIllMessageParmCoding; /* ? */ +			goto error; +		}  	}  	/* check/encode parameter: B Protocol */ @@ -1322,13 +1452,13 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,  			bcs->proto2 = L2_HDLC;  			break;  		case 1: -			bcs->proto2 = L2_BITSYNC; +			bcs->proto2 = L2_VOICE;  			break;  		default:  			dev_warn(cs->dev,  			    "B1 Protocol %u unsupported, using Transparent\n",  				 cmsg->B1protocol); -			bcs->proto2 = L2_BITSYNC; +			bcs->proto2 = L2_VOICE;  		}  		if (cmsg->B2protocol != 1)  			dev_warn(cs->dev, @@ -1382,7 +1512,6 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,  		goto error;  	}  	gigaset_schedule_event(cs); -	ap->connected = APCONN_SETUP;  	send_conf(iif, ap, skb, CapiSuccess);  	return; @@ -1410,6 +1539,7 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,  	_cmsg *cmsg = &iif->acmsg;  	struct bc_state *bcs;  	struct gigaset_capi_appl *oap; +	unsigned long flags;  	int channel;  	/* decode message */ @@ -1429,12 +1559,24 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,  	switch (cmsg->Reject) {  	case 0:		/* Accept */  		/* drop all competing applications, keep only this one */ -		for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) -			if (oap != ap) +		spin_lock_irqsave(&bcs->aplock, flags); +		while (bcs->ap != NULL) { +			oap = bcs->ap; +			bcs->ap = oap->bcnext; +			if (oap != ap) { +				spin_unlock_irqrestore(&bcs->aplock, flags);  				send_disconnect_ind(bcs, oap,  					CapiCallGivenToOtherApplication); +				spin_lock_irqsave(&bcs->aplock, flags); +			} +		}  		ap->bcnext = NULL;  		bcs->ap = ap; +		spin_unlock_irqrestore(&bcs->aplock, flags); + +		bcs->rx_bufsize = ap->rp.datablklen; +		dev_kfree_skb(bcs->rx_skb); +		gigaset_new_rx_skb(bcs);  		bcs->chstate |= CHS_NOTIFY_LL;  		/* check/encode B channel protocol */ @@ -1448,13 +1590,13 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,  				bcs->proto2 = L2_HDLC;  				break;  			case 1: -				bcs->proto2 = L2_BITSYNC; +				bcs->proto2 = L2_VOICE;  				break;  			default:  				dev_warn(cs->dev,  			"B1 Protocol %u unsupported, using Transparent\n",  					 cmsg->B1protocol); -				bcs->proto2 = L2_BITSYNC; +				bcs->proto2 = L2_VOICE;  			}  			if (cmsg->B2protocol != 1)  				dev_warn(cs->dev, @@ -1502,31 +1644,45 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,  		send_disconnect_ind(bcs, ap, 0);  		/* remove it from the list of listening apps */ +		spin_lock_irqsave(&bcs->aplock, flags);  		if (bcs->ap == ap) {  			bcs->ap = ap->bcnext; -			if (bcs->ap == NULL) +			if (bcs->ap == NULL) {  				/* last one: stop ev-layer hupD notifications */ +				bcs->apconnstate = APCONN_NONE;  				bcs->chstate &= ~CHS_NOTIFY_LL; +			} +			spin_unlock_irqrestore(&bcs->aplock, flags);  			return;  		}  		for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) {  			if (oap->bcnext == ap) {  				oap->bcnext = oap->bcnext->bcnext; +				spin_unlock_irqrestore(&bcs->aplock, flags);  				return;  			}  		} +		spin_unlock_irqrestore(&bcs->aplock, flags);  		dev_err(cs->dev, "%s: application %u not found\n",  			__func__, ap->id);  		return;  	default:		/* Reject */  		/* drop all competing applications, keep only this one */ -		for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) -			if (oap != ap) +		spin_lock_irqsave(&bcs->aplock, flags); +		while (bcs->ap != NULL) { +			oap = bcs->ap; +			bcs->ap = oap->bcnext; +			if (oap != ap) { +				spin_unlock_irqrestore(&bcs->aplock, flags);  				send_disconnect_ind(bcs, oap,  					CapiCallGivenToOtherApplication); +				spin_lock_irqsave(&bcs->aplock, flags); +			} +		}  		ap->bcnext = NULL;  		bcs->ap = ap; +		spin_unlock_irqrestore(&bcs->aplock, flags);  		/* reject call - will trigger DISCONNECT_IND for this app */  		dev_info(cs->dev, "%s: Reject=%x\n", @@ -1549,6 +1705,7 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,  {  	struct cardstate *cs = iif->ctr.driverdata;  	_cmsg *cmsg = &iif->acmsg; +	struct bc_state *bcs;  	int channel;  	/* decode message */ @@ -1563,9 +1720,10 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,  		send_conf(iif, ap, skb, CapiIllContrPlciNcci);  		return;  	} +	bcs = &cs->bcs[channel-1];  	/* mark logical connection active */ -	ap->connected = APCONN_ACTIVE; +	bcs->apconnstate = APCONN_ACTIVE;  	/* build NCCI: always 1 (one B3 connection only) */  	cmsg->adr.adrNCCI |= 1 << 16; @@ -1611,7 +1769,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,  	if (cmsg->Reject) {  		/* Reject: clear B3 connect received flag */ -		ap->connected = APCONN_SETUP; +		bcs->apconnstate = APCONN_SETUP;  		/* trigger hangup, causing eventual DISCONNECT_IND */  		if (!gigaset_add_event(cs, &bcs->at_state, @@ -1683,11 +1841,11 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,  	}  	/* skip if DISCONNECT_IND already sent */ -	if (!ap->connected) +	if (!bcs->apconnstate)  		return;  	/* check for active logical connection */ -	if (ap->connected >= APCONN_ACTIVE) { +	if (bcs->apconnstate >= APCONN_ACTIVE) {  		/*  		 * emit DISCONNECT_B3_IND with cause 0x3301  		 * use separate cmsg structure, as the content of iif->acmsg @@ -1736,6 +1894,7 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,  {  	struct cardstate *cs = iif->ctr.driverdata;  	_cmsg *cmsg = &iif->acmsg; +	struct bc_state *bcs;  	int channel;  	/* decode message */ @@ -1751,17 +1910,17 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,  		send_conf(iif, ap, skb, CapiIllContrPlciNcci);  		return;  	} +	bcs = &cs->bcs[channel-1];  	/* reject if logical connection not active */ -	if (ap->connected < APCONN_ACTIVE) { +	if (bcs->apconnstate < APCONN_ACTIVE) {  		send_conf(iif, ap, skb,  			  CapiMessageNotSupportedInCurrentState);  		return;  	}  	/* trigger hangup, causing eventual DISCONNECT_B3_IND */ -	if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, -			       EV_HUP, NULL, 0, NULL)) { +	if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) {  		send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);  		return;  	} @@ -1782,11 +1941,14 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,  			   struct sk_buff *skb)  {  	struct cardstate *cs = iif->ctr.driverdata; +	struct bc_state *bcs;  	int channel = CAPIMSG_PLCI_PART(skb->data);  	u16 ncci = CAPIMSG_NCCI_PART(skb->data);  	u16 msglen = CAPIMSG_LEN(skb->data);  	u16 datalen = CAPIMSG_DATALEN(skb->data);  	u16 flags = CAPIMSG_FLAGS(skb->data); +	u16 msgid = CAPIMSG_MSGID(skb->data); +	u16 handle = CAPIMSG_HANDLE_REQ(skb->data);  	/* frequent message, avoid _cmsg overhead */  	dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data); @@ -1802,6 +1964,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,  		send_conf(iif, ap, skb, CapiIllContrPlciNcci);  		return;  	} +	bcs = &cs->bcs[channel-1];  	if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64)  		dev_notice(cs->dev, "%s: unexpected length %d\n",  			   "DATA_B3_REQ", msglen); @@ -1821,7 +1984,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,  	}  	/* reject if logical connection not active */ -	if (ap->connected < APCONN_ACTIVE) { +	if (bcs->apconnstate < APCONN_ACTIVE) {  		send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState);  		return;  	} @@ -1832,17 +1995,19 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,  	skb_pull(skb, msglen);  	/* pass to device-specific module */ -	if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) { +	if (cs->ops->send_skb(bcs, skb) < 0) {  		send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);  		return;  	} -	/* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */ -  	/* -	 * ToDo: honor unset "delivery confirmation" bit -	 * (send DATA_B3_CONF immediately?) +	 * DATA_B3_CONF will be sent by gigaset_skb_sent() only if "delivery +	 * confirmation" bit is set; otherwise we have to send it now  	 */ +	if (!(flags & CAPI_FLAGS_DELIVERY_CONFIRMATION)) +		send_data_b3_conf(cs, &iif->ctr, ap->id, msgid, channel, handle, +				  flags ? CapiFlagsNotSupportedByProtocol +					: CAPI_NOERROR);  }  /* diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index f6f45f22192..5d4befb8105 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -399,8 +399,8 @@ static void gigaset_freebcs(struct bc_state *bcs)  	gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);  	clear_at_state(&bcs->at_state);  	gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); -	dev_kfree_skb(bcs->skb); -	bcs->skb = NULL; +	dev_kfree_skb(bcs->rx_skb); +	bcs->rx_skb = NULL;  	for (i = 0; i < AT_NUM; ++i) {  		kfree(bcs->commands[i]); @@ -634,19 +634,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,  	bcs->emptycount = 0;  #endif -	gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel); -	bcs->fcs = PPP_INITFCS; +	bcs->rx_bufsize = 0; +	bcs->rx_skb = NULL; +	bcs->rx_fcs = PPP_INITFCS;  	bcs->inputstate = 0; -	if (cs->ignoreframes) { -		bcs->skb = NULL; -	} else { -		bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); -		if (bcs->skb != NULL) -			skb_reserve(bcs->skb, cs->hw_hdr_len); -		else -			pr_err("out of memory\n"); -	} -  	bcs->channel = channel;  	bcs->cs = cs; @@ -658,16 +649,15 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,  	for (i = 0; i < AT_NUM; ++i)  		bcs->commands[i] = NULL; +	spin_lock_init(&bcs->aplock); +	bcs->ap = NULL; +	bcs->apconnstate = 0; +  	gig_dbg(DEBUG_INIT, "  setting up bcs[%d]->hw", channel);  	if (cs->ops->initbcshw(bcs))  		return bcs;  	gig_dbg(DEBUG_INIT, "  failed"); - -	gig_dbg(DEBUG_INIT, "  freeing bcs[%d]->skb", channel); -	dev_kfree_skb(bcs->skb); -	bcs->skb = NULL; -  	return NULL;  } @@ -839,14 +829,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs)  	bcs->emptycount = 0;  #endif -	bcs->fcs = PPP_INITFCS; +	bcs->rx_fcs = PPP_INITFCS;  	bcs->chstate = 0;  	bcs->ignore = cs->ignoreframes; -	if (bcs->ignore) { -		dev_kfree_skb(bcs->skb); -		bcs->skb = NULL; -	} +	dev_kfree_skb(bcs->rx_skb); +	bcs->rx_skb = NULL;  	cs->ops->reinitbcshw(bcs);  } diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index 206c380c523..ceaef9a04a4 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -282,9 +282,7 @@ struct reply_t gigaset_tab_cid[] =  /* dial */  {EV_DIAL,	 -1,  -1, -1,			 -1, -1, {ACT_DIAL} },  {RSP_INIT,	  0,   0, SEQ_DIAL,		601,  5, {ACT_CMD+AT_BC} }, -{RSP_OK,	601, 601, -1,			602,  5, {ACT_CMD+AT_HLC} }, -{RSP_NULL,	602, 602, -1,			603,  5, {ACT_CMD+AT_PROTO} }, -{RSP_OK,	602, 602, -1,			603,  5, {ACT_CMD+AT_PROTO} }, +{RSP_OK,	601, 601, -1,			603,  5, {ACT_CMD+AT_PROTO} },  {RSP_OK,	603, 603, -1,			604,  5, {ACT_CMD+AT_TYPE} },  {RSP_OK,	604, 604, -1,			605,  5, {ACT_CMD+AT_MSN} },  {RSP_NULL,	605, 605, -1,			606,  5, {ACT_CMD+AT_CLIP} }, diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 05947f9c184..8738b0821fc 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -45,10 +45,6 @@  #define MAX_EVENTS 64		/* size of event queue */  #define RBUFSIZE 8192 -#define SBUFSIZE 4096		/* sk_buff payload size */ - -#define TRANSBUFSIZE 768	/* bytes per skb for transparent receive */ -#define MAX_BUF_SIZE (SBUFSIZE - 2)	/* Max. size of a data packet from LL */  /* compile time options */  #define GIG_MAJOR 0 @@ -190,10 +186,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,  #define AT_BC		3  #define AT_PROTO	4  #define AT_TYPE		5 -#define AT_HLC		6 -#define AT_CLIP		7 +#define AT_CLIP		6  /* total number */ -#define AT_NUM		8 +#define AT_NUM		7  /* variables in struct at_state_t */  #define VAR_ZSAU	0 @@ -380,8 +375,10 @@ struct bc_state {  	struct at_state_t at_state; -	__u16 fcs; -	struct sk_buff *skb; +	/* receive buffer */ +	unsigned rx_bufsize;		/* max size accepted by application */ +	struct sk_buff *rx_skb; +	__u16 rx_fcs;  	int inputstate;			/* see INS_XXXX */  	int channel; @@ -406,7 +403,9 @@ struct bc_state {  		struct bas_bc_state *bas;	/* usb hardware driver (base) */  	} hw; -	void *ap;			/* LL application structure */ +	void *ap;			/* associated LL application */ +	int apconnstate;		/* LL application connection state */ +	spinlock_t aplock;  };  struct cardstate { @@ -801,8 +800,23 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs)  	gigaset_schedule_event(bcs->cs);  } -/* handling routines for sk_buff */ -/* ============================= */ +/* set up next receive skb for data mode */ +static inline struct sk_buff *gigaset_new_rx_skb(struct bc_state *bcs) +{ +	struct cardstate *cs = bcs->cs; +	unsigned short hw_hdr_len = cs->hw_hdr_len; + +	if (bcs->ignore) { +		bcs->rx_skb = NULL; +	} else { +		bcs->rx_skb = dev_alloc_skb(bcs->rx_bufsize + hw_hdr_len); +		if (bcs->rx_skb == NULL) +			dev_warn(cs->dev, "could not allocate skb\n"); +		else +			skb_reserve(bcs->rx_skb, hw_hdr_len); +	} +	return bcs->rx_skb; +}  /* append received bytes to inbuf */  int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index c22e5ace827..f01c3c2e2e4 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -16,7 +16,10 @@  #include "gigaset.h"  #include <linux/isdnif.h> +#define SBUFSIZE	4096	/* sk_buff payload size */ +#define TRANSBUFSIZE	768	/* bytes per skb for transparent receive */  #define HW_HDR_LEN	2	/* Header size used to store ack info */ +#define MAX_BUF_SIZE	(SBUFSIZE - HW_HDR_LEN)	/* max data packet from LL */  /* == Handling of I4L IO =====================================================*/ @@ -231,6 +234,15 @@ static int command_from_LL(isdn_ctrl *cntrl)  			dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");  			return -EBUSY;  		} +		switch (bcs->proto2) { +		case L2_HDLC: +			bcs->rx_bufsize = SBUFSIZE; +			break; +		default:			/* assume transparent */ +			bcs->rx_bufsize = TRANSBUFSIZE; +		} +		dev_kfree_skb(bcs->rx_skb); +		gigaset_new_rx_skb(bcs);  		commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC);  		if (!commands) { @@ -314,6 +326,15 @@ static int command_from_LL(isdn_ctrl *cntrl)  			return -EINVAL;  		}  		bcs = cs->bcs + ch; +		switch (bcs->proto2) { +		case L2_HDLC: +			bcs->rx_bufsize = SBUFSIZE; +			break; +		default:			/* assume transparent */ +			bcs->rx_bufsize = TRANSBUFSIZE; +		} +		dev_kfree_skb(bcs->rx_skb); +		gigaset_new_rx_skb(bcs);  		if (!gigaset_add_event(cs, &bcs->at_state,  				       EV_ACCEPT, NULL, 0, NULL))  			return -ENOMEM; diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 16fd3bd4888..2dfd346fc88 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -500,19 +500,18 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len)   */  static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)  { -	bcs->fcs = crc_ccitt_byte(bcs->fcs, c); -	if (unlikely(bcs->skb == NULL)) { +	bcs->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c); +	if (bcs->rx_skb == NULL)  		/* skipping */  		return; -	} -	if (unlikely(bcs->skb->len == SBUFSIZE)) { +	if (bcs->rx_skb->len >= bcs->rx_bufsize) {  		dev_warn(bcs->cs->dev, "received oversized packet discarded\n");  		bcs->hw.bas->giants++; -		dev_kfree_skb_any(bcs->skb); -		bcs->skb = NULL; +		dev_kfree_skb_any(bcs->rx_skb); +		bcs->rx_skb = NULL;  		return;  	} -	*__skb_put(bcs->skb, 1) = c; +	*__skb_put(bcs->rx_skb, 1) = c;  }  /* hdlc_flush @@ -521,18 +520,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)  static inline void hdlc_flush(struct bc_state *bcs)  {  	/* clear skb or allocate new if not skipping */ -	if (likely(bcs->skb != NULL)) -		skb_trim(bcs->skb, 0); -	else if (!bcs->ignore) { -		bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len); -		if (bcs->skb) -			skb_reserve(bcs->skb, bcs->cs->hw_hdr_len); -		else -			dev_err(bcs->cs->dev, "could not allocate skb\n"); -	} +	if (bcs->rx_skb != NULL) +		skb_trim(bcs->rx_skb, 0); +	else +		gigaset_new_rx_skb(bcs);  	/* reset packet state */ -	bcs->fcs = PPP_INITFCS; +	bcs->rx_fcs = PPP_INITFCS;  }  /* hdlc_done @@ -549,7 +543,7 @@ static inline void hdlc_done(struct bc_state *bcs)  		hdlc_flush(bcs);  		return;  	} -	procskb = bcs->skb; +	procskb = bcs->rx_skb;  	if (procskb == NULL) {  		/* previous error */  		gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); @@ -560,8 +554,8 @@ static inline void hdlc_done(struct bc_state *bcs)  		bcs->hw.bas->runts++;  		dev_kfree_skb_any(procskb);  		gigaset_isdn_rcv_err(bcs); -	} else if (bcs->fcs != PPP_GOODFCS) { -		dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs); +	} else if (bcs->rx_fcs != PPP_GOODFCS) { +		dev_notice(cs->dev, "frame check error\n");  		bcs->hw.bas->fcserrs++;  		dev_kfree_skb_any(procskb);  		gigaset_isdn_rcv_err(bcs); @@ -574,13 +568,8 @@ static inline void hdlc_done(struct bc_state *bcs)  		bcs->hw.bas->goodbytes += len;  		gigaset_skb_rcvd(bcs, procskb);  	} - -	bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); -	if (bcs->skb) -		skb_reserve(bcs->skb, cs->hw_hdr_len); -	else -		dev_err(cs->dev, "could not allocate skb\n"); -	bcs->fcs = PPP_INITFCS; +	gigaset_new_rx_skb(bcs); +	bcs->rx_fcs = PPP_INITFCS;  }  /* hdlc_frag @@ -597,8 +586,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)  	dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);  	bcs->hw.bas->alignerrs++;  	gigaset_isdn_rcv_err(bcs); -	__skb_trim(bcs->skb, 0); -	bcs->fcs = PPP_INITFCS; +	__skb_trim(bcs->rx_skb, 0); +	bcs->rx_fcs = PPP_INITFCS;  }  /* bit counts lookup table for HDLC bit unstuffing @@ -847,7 +836,6 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,  static inline void trans_receive(unsigned char *src, unsigned count,  				 struct bc_state *bcs)  { -	struct cardstate *cs = bcs->cs;  	struct sk_buff *skb;  	int dobytes;  	unsigned char *dst; @@ -857,17 +845,11 @@ static inline void trans_receive(unsigned char *src, unsigned count,  		hdlc_flush(bcs);  		return;  	} -	skb = bcs->skb; -	if (unlikely(skb == NULL)) { -		bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); -		if (!skb) { -			dev_err(cs->dev, "could not allocate skb\n"); -			return; -		} -		skb_reserve(skb, cs->hw_hdr_len); -	} +	skb = bcs->rx_skb; +	if (skb == NULL) +		skb = gigaset_new_rx_skb(bcs);  	bcs->hw.bas->goodbytes += skb->len; -	dobytes = TRANSBUFSIZE - skb->len; +	dobytes = bcs->rx_bufsize - skb->len;  	while (count > 0) {  		dst = skb_put(skb, count < dobytes ? count : dobytes);  		while (count > 0 && dobytes > 0) { @@ -879,14 +861,10 @@ static inline void trans_receive(unsigned char *src, unsigned count,  			dump_bytes(DEBUG_STREAM_DUMP,  				   "rcv data", skb->data, skb->len);  			gigaset_skb_rcvd(bcs, skb); -			bcs->skb = skb = -				dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); -			if (!skb) { -				dev_err(cs->dev, "could not allocate skb\n"); +			skb = gigaset_new_rx_skb(bcs); +			if (skb == NULL)  				return; -			} -			skb_reserve(skb, cs->hw_hdr_len); -			dobytes = TRANSBUFSIZE; +			dobytes = bcs->rx_bufsize;  		}  	}  } diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c index 72eb92647c1..feec8d89d71 100644 --- a/drivers/isdn/hysdn/hysdn_net.c +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -187,12 +187,13 @@ void  hysdn_rx_netpkt(hysdn_card * card, unsigned char *buf, unsigned short len)  {  	struct net_local *lp = card->netif; -	struct net_device *dev = lp->dev; +	struct net_device *dev;  	struct sk_buff *skb;  	if (!lp)  		return;		/* non existing device */ +	dev = lp->dev;  	dev->stats.rx_bytes += len;  	skb = dev_alloc_skb(len); diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 81bf25e67ce..e4112622e5a 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -302,6 +302,15 @@ config LEDS_MC13783  	  This option enable support for on-chip LED drivers found  	  on Freescale Semiconductor MC13783 PMIC. +config LEDS_NS2 +	tristate "LED support for Network Space v2 GPIO LEDs" +	depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2 +	default y +	help +	  This option enable support for the dual-GPIO LED found on the +	  Network Space v2 board (and parents). This include Internet Space v2, +	  Network Space (Max) v2 and d2 Network v2 boards. +  config LEDS_TRIGGERS  	bool "LED Trigger support"  	help diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 2493de49937..7d6b95831f8 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_LEDS_LT3593)		+= leds-lt3593.o  obj-$(CONFIG_LEDS_ADP5520)		+= leds-adp5520.o  obj-$(CONFIG_LEDS_DELL_NETBOOKS)	+= dell-led.o  obj-$(CONFIG_LEDS_MC13783)		+= leds-mc13783.o +obj-$(CONFIG_LEDS_NS2)			+= leds-ns2.o  # LED SPI Drivers  obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c new file mode 100644 index 00000000000..74dce4ba026 --- /dev/null +++ b/drivers/leds/leds-ns2.c @@ -0,0 +1,338 @@ +/* + * leds-ns2.c - Driver for the Network Space v2 (and parents) dual-GPIO LED + * + * Copyright (C) 2010 LaCie + * + * Author: Simon Guinot <sguinot@lacie.com> + * + * Based on leds-gpio.c by Raphael Assenat <raph@8d.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/gpio.h> +#include <linux/leds.h> +#include <mach/leds-ns2.h> + +/* + * The Network Space v2 dual-GPIO LED is wired to a CPLD and can blink in + * relation with the SATA activity. This capability is exposed through the + * "sata" sysfs attribute. + * + * The following array detail the different LED registers and the combination + * of their possible values: + * + *  cmd_led   |  slow_led  | /SATA active | LED state + *            |            |              | + *     1      |     0      |      x       |  off + *     -      |     1      |      x       |  on + *     0      |     0      |      1       |  on + *     0      |     0      |      0       |  blink (rate 300ms) + */ + +enum ns2_led_modes { +	NS_V2_LED_OFF, +	NS_V2_LED_ON, +	NS_V2_LED_SATA, +}; + +struct ns2_led_mode_value { +	enum ns2_led_modes	mode; +	int			cmd_level; +	int			slow_level; +}; + +static struct ns2_led_mode_value ns2_led_modval[] = { +	{ NS_V2_LED_OFF	, 1, 0 }, +	{ NS_V2_LED_ON	, 0, 1 }, +	{ NS_V2_LED_ON	, 1, 1 }, +	{ NS_V2_LED_SATA, 0, 0 }, +}; + +struct ns2_led_data { +	struct led_classdev	cdev; +	unsigned		cmd; +	unsigned		slow; +	unsigned char		sata; /* True when SATA mode active. */ +	rwlock_t		rw_lock; /* Lock GPIOs. */ +}; + +static int ns2_led_get_mode(struct ns2_led_data *led_dat, +			    enum ns2_led_modes *mode) +{ +	int i; +	int ret = -EINVAL; +	int cmd_level; +	int slow_level; + +	read_lock(&led_dat->rw_lock); + +	cmd_level = gpio_get_value(led_dat->cmd); +	slow_level = gpio_get_value(led_dat->slow); + +	for (i = 0; i < ARRAY_SIZE(ns2_led_modval); i++) { +		if (cmd_level == ns2_led_modval[i].cmd_level && +		    slow_level == ns2_led_modval[i].slow_level) { +			*mode = ns2_led_modval[i].mode; +			ret = 0; +			break; +		} +	} + +	read_unlock(&led_dat->rw_lock); + +	return ret; +} + +static void ns2_led_set_mode(struct ns2_led_data *led_dat, +			     enum ns2_led_modes mode) +{ +	int i; + +	write_lock(&led_dat->rw_lock); + +	for (i = 0; i < ARRAY_SIZE(ns2_led_modval); i++) { +		if (mode == ns2_led_modval[i].mode) { +			gpio_set_value(led_dat->cmd, +				       ns2_led_modval[i].cmd_level); +			gpio_set_value(led_dat->slow, +				       ns2_led_modval[i].slow_level); +		} +	} + +	write_unlock(&led_dat->rw_lock); +} + +static void ns2_led_set(struct led_classdev *led_cdev, +			enum led_brightness value) +{ +	struct ns2_led_data *led_dat = +		container_of(led_cdev, struct ns2_led_data, cdev); +	enum ns2_led_modes mode; + +	if (value == LED_OFF) +		mode = NS_V2_LED_OFF; +	else if (led_dat->sata) +		mode = NS_V2_LED_SATA; +	else +		mode = NS_V2_LED_ON; + +	ns2_led_set_mode(led_dat, mode); +} + +static ssize_t ns2_led_sata_store(struct device *dev, +				  struct device_attribute *attr, +				  const char *buff, size_t count) +{ +	int ret; +	unsigned long enable; +	enum ns2_led_modes mode; +	struct ns2_led_data *led_dat = dev_get_drvdata(dev); + +	ret = strict_strtoul(buff, 10, &enable); +	if (ret < 0) +		return ret; + +	enable = !!enable; + +	if (led_dat->sata == enable) +		return count; + +	ret = ns2_led_get_mode(led_dat, &mode); +	if (ret < 0) +		return ret; + +	if (enable && mode == NS_V2_LED_ON) +		ns2_led_set_mode(led_dat, NS_V2_LED_SATA); +	if (!enable && mode == NS_V2_LED_SATA) +		ns2_led_set_mode(led_dat, NS_V2_LED_ON); + +	led_dat->sata = enable; + +	return count; +} + +static ssize_t ns2_led_sata_show(struct device *dev, +				 struct device_attribute *attr, char *buf) +{ +	struct ns2_led_data *led_dat = dev_get_drvdata(dev); + +	return sprintf(buf, "%d\n", led_dat->sata); +} + +static DEVICE_ATTR(sata, 0644, ns2_led_sata_show, ns2_led_sata_store); + +static int __devinit +create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat, +	       const struct ns2_led *template) +{ +	int ret; +	enum ns2_led_modes mode; + +	ret = gpio_request(template->cmd, template->name); +	if (ret == 0) { +		ret = gpio_direction_output(template->cmd, +					    gpio_get_value(template->cmd)); +		if (ret) +			gpio_free(template->cmd); +	} +	if (ret) { +		dev_err(&pdev->dev, "%s: failed to setup command GPIO\n", +			template->name); +	} + +	ret = gpio_request(template->slow, template->name); +	if (ret == 0) { +		ret = gpio_direction_output(template->slow, +					    gpio_get_value(template->slow)); +		if (ret) +			gpio_free(template->slow); +	} +	if (ret) { +		dev_err(&pdev->dev, "%s: failed to setup slow GPIO\n", +			template->name); +		goto err_free_cmd; +	} + +	rwlock_init(&led_dat->rw_lock); + +	led_dat->cdev.name = template->name; +	led_dat->cdev.default_trigger = template->default_trigger; +	led_dat->cdev.blink_set = NULL; +	led_dat->cdev.brightness_set = ns2_led_set; +	led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; +	led_dat->cmd = template->cmd; +	led_dat->slow = template->slow; + +	ret = ns2_led_get_mode(led_dat, &mode); +	if (ret < 0) +		goto err_free_slow; + +	/* Set LED initial state. */ +	led_dat->sata = (mode == NS_V2_LED_SATA) ? 1 : 0; +	led_dat->cdev.brightness = +		(mode == NS_V2_LED_OFF) ? LED_OFF : LED_FULL; + +	ret = led_classdev_register(&pdev->dev, &led_dat->cdev); +	if (ret < 0) +		goto err_free_slow; + +	dev_set_drvdata(led_dat->cdev.dev, led_dat); +	ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata); +	if (ret < 0) +		goto err_free_cdev; + +	return 0; + +err_free_cdev: +	led_classdev_unregister(&led_dat->cdev); +err_free_slow: +	gpio_free(led_dat->slow); +err_free_cmd: +	gpio_free(led_dat->cmd); + +	return ret; +} + +static void __devexit delete_ns2_led(struct ns2_led_data *led_dat) +{ +	device_remove_file(led_dat->cdev.dev, &dev_attr_sata); +	led_classdev_unregister(&led_dat->cdev); +	gpio_free(led_dat->cmd); +	gpio_free(led_dat->slow); +} + +static int __devinit ns2_led_probe(struct platform_device *pdev) +{ +	struct ns2_led_platform_data *pdata = pdev->dev.platform_data; +	struct ns2_led_data *leds_data; +	int i; +	int ret; + +	if (!pdata) +		return -EINVAL; + +	leds_data = kzalloc(sizeof(struct ns2_led_data) * +			    pdata->num_leds, GFP_KERNEL); +	if (!leds_data) +		return -ENOMEM; + +	for (i = 0; i < pdata->num_leds; i++) { +		ret = create_ns2_led(pdev, &leds_data[i], &pdata->leds[i]); +		if (ret < 0) +			goto err; + +	} + +	platform_set_drvdata(pdev, leds_data); + +	return 0; + +err: +	for (i = i - 1; i >= 0; i--) +		delete_ns2_led(&leds_data[i]); + +	kfree(leds_data); + +	return ret; +} + +static int __devexit ns2_led_remove(struct platform_device *pdev) +{ +	int i; +	struct ns2_led_platform_data *pdata = pdev->dev.platform_data; +	struct ns2_led_data *leds_data; + +	leds_data = platform_get_drvdata(pdev); + +	for (i = 0; i < pdata->num_leds; i++) +		delete_ns2_led(&leds_data[i]); + +	kfree(leds_data); +	platform_set_drvdata(pdev, NULL); + +	return 0; +} + +static struct platform_driver ns2_led_driver = { +	.probe		= ns2_led_probe, +	.remove		= __devexit_p(ns2_led_remove), +	.driver		= { +		.name	= "leds-ns2", +		.owner	= THIS_MODULE, +	}, +}; +MODULE_ALIAS("platform:leds-ns2"); + +static int __init ns2_led_init(void) +{ +	return platform_driver_register(&ns2_led_driver); +} + +static void __exit ns2_led_exit(void) +{ +	platform_driver_unregister(&ns2_led_driver); +} + +module_init(ns2_led_init); +module_exit(ns2_led_exit); + +MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); +MODULE_DESCRIPTION("Network Space v2 LED driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/md/md.c b/drivers/md/md.c index 46b3a044ead..cb20d0b0555 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2087,6 +2087,7 @@ static void sync_sbs(mddev_t * mddev, int nospares)  	/* First make sure individual recovery_offsets are correct */  	list_for_each_entry(rdev, &mddev->disks, same_set) {  		if (rdev->raid_disk >= 0 && +		    mddev->delta_disks >= 0 &&  		    !test_bit(In_sync, &rdev->flags) &&  		    mddev->curr_resync_completed > rdev->recovery_offset)  				rdev->recovery_offset = mddev->curr_resync_completed; @@ -3001,6 +3002,9 @@ level_store(mddev_t *mddev, const char *buf, size_t len)  		return -EINVAL;  	} +	list_for_each_entry(rdev, &mddev->disks, same_set) +		rdev->new_raid_disk = rdev->raid_disk; +  	/* ->takeover must set new_* and/or delta_disks  	 * if it succeeds, and may set them when it fails.  	 */ @@ -3051,13 +3055,35 @@ level_store(mddev_t *mddev, const char *buf, size_t len)  		mddev->safemode = 0;  	} -	module_put(mddev->pers->owner); -	/* Invalidate devices that are now superfluous */ -	list_for_each_entry(rdev, &mddev->disks, same_set) -		if (rdev->raid_disk >= mddev->raid_disks) { -			rdev->raid_disk = -1; +	list_for_each_entry(rdev, &mddev->disks, same_set) { +		char nm[20]; +		if (rdev->raid_disk < 0) +			continue; +		if (rdev->new_raid_disk > mddev->raid_disks) +			rdev->new_raid_disk = -1; +		if (rdev->new_raid_disk == rdev->raid_disk) +			continue; +		sprintf(nm, "rd%d", rdev->raid_disk); +		sysfs_remove_link(&mddev->kobj, nm); +	} +	list_for_each_entry(rdev, &mddev->disks, same_set) { +		if (rdev->raid_disk < 0) +			continue; +		if (rdev->new_raid_disk == rdev->raid_disk) +			continue; +		rdev->raid_disk = rdev->new_raid_disk; +		if (rdev->raid_disk < 0)  			clear_bit(In_sync, &rdev->flags); +		else { +			char nm[20]; +			sprintf(nm, "rd%d", rdev->raid_disk); +			if(sysfs_create_link(&mddev->kobj, &rdev->kobj, nm)) +				printk("md: cannot register %s for %s after level change\n", +				       nm, mdname(mddev));  		} +	} + +	module_put(mddev->pers->owner);  	mddev->pers = pers;  	mddev->private = priv;  	strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); @@ -5895,6 +5921,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)  	atomic_inc(&mddev->openers);  	mutex_unlock(&mddev->open_mutex); +	check_disk_size_change(mddev->gendisk, bdev);   out:  	return err;  } @@ -6846,6 +6873,7 @@ void md_do_sync(mddev_t *mddev)  			rcu_read_lock();  			list_for_each_entry_rcu(rdev, &mddev->disks, same_set)  				if (rdev->raid_disk >= 0 && +				    mddev->delta_disks >= 0 &&  				    !test_bit(Faulty, &rdev->flags) &&  				    !test_bit(In_sync, &rdev->flags) &&  				    rdev->recovery_offset < mddev->curr_resync) diff --git a/drivers/md/md.h b/drivers/md/md.h index 7ab5ea15545..10597bfec00 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -78,6 +78,9 @@ struct mdk_rdev_s  	int desc_nr;			/* descriptor index in the superblock */  	int raid_disk;			/* role of device in array */ +	int new_raid_disk;		/* role that the device will have in +					 * the array after a level-change completes. +					 */  	int saved_raid_disk;		/* role that device used to have in the  					 * array and could again if we did a partial  					 * resync from the bitmap diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index e70f004c99e..563abed5a2c 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -173,9 +173,11 @@ static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)  	list_for_each_entry(rdev1, &mddev->disks, same_set) {  		int j = rdev1->raid_disk; -		if (mddev->level == 10) +		if (mddev->level == 10) {  			/* taking over a raid10-n2 array */  			j /= 2; +			rdev1->new_raid_disk = j; +		}  		if (j < 0 || j >= mddev->raid_disks) {  			printk(KERN_ERR "md/raid0:%s: bad disk number %d - " @@ -361,12 +363,6 @@ static int raid0_run(mddev_t *mddev)  		mddev->private = conf;  	}  	conf = mddev->private; -	if (conf->scale_raid_disks) { -		int i; -		for (i=0; i < conf->strip_zone[0].nb_dev; i++) -			conf->devlist[i]->raid_disk /= conf->scale_raid_disks; -		/* FIXME update sysfs rd links */ -	}  	/* calculate array device size */  	md_set_array_sectors(mddev, raid0_size(mddev, 0, 0)); @@ -573,7 +569,7 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev)  	return;  } -static void *raid0_takeover_raid5(mddev_t *mddev) +static void *raid0_takeover_raid45(mddev_t *mddev)  {  	mdk_rdev_t *rdev;  	raid0_conf_t *priv_conf; @@ -596,6 +592,7 @@ static void *raid0_takeover_raid5(mddev_t *mddev)  	/* Set new parameters */  	mddev->new_level = 0; +	mddev->new_layout = 0;  	mddev->new_chunk_sectors = mddev->chunk_sectors;  	mddev->raid_disks--;  	mddev->delta_disks = -1; @@ -635,6 +632,7 @@ static void *raid0_takeover_raid10(mddev_t *mddev)  	/* Set new parameters */  	mddev->new_level = 0; +	mddev->new_layout = 0;  	mddev->new_chunk_sectors = mddev->chunk_sectors;  	mddev->delta_disks = - mddev->raid_disks / 2;  	mddev->raid_disks += mddev->delta_disks; @@ -643,19 +641,22 @@ static void *raid0_takeover_raid10(mddev_t *mddev)  	mddev->recovery_cp = MaxSector;  	create_strip_zones(mddev, &priv_conf); -	priv_conf->scale_raid_disks = 2;  	return priv_conf;  }  static void *raid0_takeover(mddev_t *mddev)  {  	/* raid0 can take over: +	 *  raid4 - if all data disks are active.  	 *  raid5 - providing it is Raid4 layout and one disk is faulty  	 *  raid10 - assuming we have all necessary active disks  	 */ +	if (mddev->level == 4) +		return raid0_takeover_raid45(mddev); +  	if (mddev->level == 5) {  		if (mddev->layout == ALGORITHM_PARITY_N) -			return raid0_takeover_raid5(mddev); +			return raid0_takeover_raid45(mddev);  		printk(KERN_ERR "md/raid0:%s: Raid can only takeover Raid5 with layout: %d\n",  		       mdname(mddev), ALGORITHM_PARITY_N); diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h index d724e664ca4..91f8e876ee6 100644 --- a/drivers/md/raid0.h +++ b/drivers/md/raid0.h @@ -13,9 +13,6 @@ struct raid0_private_data  	struct strip_zone *strip_zone;  	mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */  	int nr_strip_zones; -	int scale_raid_disks; /* divide rdev->raid_disks by this in run() -			       * to handle conversion from raid10 -			       */  };  typedef struct raid0_private_data raid0_conf_t; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 03724992cdf..42e64e4e5e2 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1482,14 +1482,14 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)  	int sectors = r10_bio->sectors;  	mdk_rdev_t*rdev;  	int max_read_errors = atomic_read(&mddev->max_corr_read_errors); +	int d = r10_bio->devs[r10_bio->read_slot].devnum;  	rcu_read_lock(); -	{ -		int d = r10_bio->devs[r10_bio->read_slot].devnum; +	rdev = rcu_dereference(conf->mirrors[d].rdev); +	if (rdev) { /* If rdev is not NULL */  		char b[BDEVNAME_SIZE];  		int cur_read_error_count = 0; -		rdev = rcu_dereference(conf->mirrors[d].rdev);  		bdevname(rdev->bdev, b);  		if (test_bit(Faulty, &rdev->flags)) { @@ -1530,7 +1530,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)  		rcu_read_lock();  		do { -			int d = r10_bio->devs[sl].devnum; +			d = r10_bio->devs[sl].devnum;  			rdev = rcu_dereference(conf->mirrors[d].rdev);  			if (rdev &&  			    test_bit(In_sync, &rdev->flags)) { @@ -1564,7 +1564,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)  		rcu_read_lock();  		while (sl != r10_bio->read_slot) {  			char b[BDEVNAME_SIZE]; -			int d; +  			if (sl==0)  				sl = conf->copies;  			sl--; @@ -1601,7 +1601,7 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)  		}  		sl = start;  		while (sl != r10_bio->read_slot) { -			int d; +  			if (sl==0)  				sl = conf->copies;  			sl--; @@ -2161,22 +2161,22 @@ static conf_t *setup_conf(mddev_t *mddev)  	sector_t stride, size;  	int err = -EINVAL; -	if (mddev->chunk_sectors < (PAGE_SIZE >> 9) || -	    !is_power_of_2(mddev->chunk_sectors)) { +	if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) || +	    !is_power_of_2(mddev->new_chunk_sectors)) {  		printk(KERN_ERR "md/raid10:%s: chunk size must be "  		       "at least PAGE_SIZE(%ld) and be a power of 2.\n",  		       mdname(mddev), PAGE_SIZE);  		goto out;  	} -	nc = mddev->layout & 255; -	fc = (mddev->layout >> 8) & 255; -	fo = mddev->layout & (1<<16); +	nc = mddev->new_layout & 255; +	fc = (mddev->new_layout >> 8) & 255; +	fo = mddev->new_layout & (1<<16);  	if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks || -	    (mddev->layout >> 17)) { +	    (mddev->new_layout >> 17)) {  		printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x\n", -		       mdname(mddev), mddev->layout); +		       mdname(mddev), mddev->new_layout);  		goto out;  	} @@ -2241,7 +2241,6 @@ static conf_t *setup_conf(mddev_t *mddev)  	if (!conf->thread)  		goto out; -	conf->scale_disks = 0;  	conf->mddev = mddev;  	return conf; @@ -2300,11 +2299,6 @@ static int run(mddev_t *mddev)  		if (disk_idx >= conf->raid_disks  		    || disk_idx < 0)  			continue; -		if (conf->scale_disks) { -			disk_idx *= conf->scale_disks; -			rdev->raid_disk = disk_idx; -			/* MOVE 'rd%d' link !! */ -		}  		disk = conf->mirrors + disk_idx;  		disk->rdev = rdev; @@ -2435,26 +2429,22 @@ static void *raid10_takeover_raid0(mddev_t *mddev)  		return ERR_PTR(-EINVAL);  	} -	/* Update slot numbers to obtain -	 * degraded raid10 with missing mirrors -	 */ -	list_for_each_entry(rdev, &mddev->disks, same_set) { -		rdev->raid_disk *= 2; -	} -  	/* Set new parameters */  	mddev->new_level = 10;  	/* new layout: far_copies = 1, near_copies = 2 */  	mddev->new_layout = (1<<8) + 2;  	mddev->new_chunk_sectors = mddev->chunk_sectors;  	mddev->delta_disks = mddev->raid_disks; -	mddev->degraded = mddev->raid_disks;  	mddev->raid_disks *= 2;  	/* make sure it will be not marked as dirty */  	mddev->recovery_cp = MaxSector;  	conf = setup_conf(mddev); -	conf->scale_disks = 2; +	if (!IS_ERR(conf)) +		list_for_each_entry(rdev, &mddev->disks, same_set) +			if (rdev->raid_disk >= 0) +				rdev->new_raid_disk = rdev->raid_disk * 2; +		  	return conf;  } diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index 3824a087e17..2316ac2e8e2 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h @@ -38,11 +38,6 @@ struct r10_private_data_s {  	int chunk_shift; /* shift from chunks to sectors */  	sector_t chunk_mask; -	int			scale_disks;  /* When starting array, multiply -					       * each ->raid_disk by this. -					       * Need for raid0->raid10 migration -					       */ -  	struct list_head	retry_list;  	/* queue pending writes and submit them on unplug */  	struct bio_list		pending_bio_list; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index d2c0f94fa37..96c690279fc 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -277,12 +277,13 @@ out:  	return sh;  } -static void shrink_buffers(struct stripe_head *sh, int num) +static void shrink_buffers(struct stripe_head *sh)  {  	struct page *p;  	int i; +	int num = sh->raid_conf->pool_size; -	for (i=0; i<num ; i++) { +	for (i = 0; i < num ; i++) {  		p = sh->dev[i].page;  		if (!p)  			continue; @@ -291,11 +292,12 @@ static void shrink_buffers(struct stripe_head *sh, int num)  	}  } -static int grow_buffers(struct stripe_head *sh, int num) +static int grow_buffers(struct stripe_head *sh)  {  	int i; +	int num = sh->raid_conf->pool_size; -	for (i=0; i<num; i++) { +	for (i = 0; i < num; i++) {  		struct page *page;  		if (!(page = alloc_page(GFP_KERNEL))) { @@ -364,6 +366,73 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector,  	return NULL;  } +/* + * Need to check if array has failed when deciding whether to: + *  - start an array + *  - remove non-faulty devices + *  - add a spare + *  - allow a reshape + * This determination is simple when no reshape is happening. + * However if there is a reshape, we need to carefully check + * both the before and after sections. + * This is because some failed devices may only affect one + * of the two sections, and some non-in_sync devices may + * be insync in the section most affected by failed devices. + */ +static int has_failed(raid5_conf_t *conf) +{ +	int degraded; +	int i; +	if (conf->mddev->reshape_position == MaxSector) +		return conf->mddev->degraded > conf->max_degraded; + +	rcu_read_lock(); +	degraded = 0; +	for (i = 0; i < conf->previous_raid_disks; i++) { +		mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); +		if (!rdev || test_bit(Faulty, &rdev->flags)) +			degraded++; +		else if (test_bit(In_sync, &rdev->flags)) +			; +		else +			/* not in-sync or faulty. +			 * If the reshape increases the number of devices, +			 * this is being recovered by the reshape, so +			 * this 'previous' section is not in_sync. +			 * If the number of devices is being reduced however, +			 * the device can only be part of the array if +			 * we are reverting a reshape, so this section will +			 * be in-sync. +			 */ +			if (conf->raid_disks >= conf->previous_raid_disks) +				degraded++; +	} +	rcu_read_unlock(); +	if (degraded > conf->max_degraded) +		return 1; +	rcu_read_lock(); +	degraded = 0; +	for (i = 0; i < conf->raid_disks; i++) { +		mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); +		if (!rdev || test_bit(Faulty, &rdev->flags)) +			degraded++; +		else if (test_bit(In_sync, &rdev->flags)) +			; +		else +			/* not in-sync or faulty. +			 * If reshape increases the number of devices, this +			 * section has already been recovered, else it +			 * almost certainly hasn't. +			 */ +			if (conf->raid_disks <= conf->previous_raid_disks) +				degraded++; +	} +	rcu_read_unlock(); +	if (degraded > conf->max_degraded) +		return 1; +	return 0; +} +  static void unplug_slaves(mddev_t *mddev);  static void raid5_unplug_device(struct request_queue *q); @@ -1240,19 +1309,18 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)  static int grow_one_stripe(raid5_conf_t *conf)  {  	struct stripe_head *sh; -	int disks = max(conf->raid_disks, conf->previous_raid_disks);  	sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);  	if (!sh)  		return 0; -	memset(sh, 0, sizeof(*sh) + (disks-1)*sizeof(struct r5dev)); +	memset(sh, 0, sizeof(*sh) + (conf->pool_size-1)*sizeof(struct r5dev));  	sh->raid_conf = conf;  	spin_lock_init(&sh->lock);  	#ifdef CONFIG_MULTICORE_RAID456  	init_waitqueue_head(&sh->ops.wait_for_ops);  	#endif -	if (grow_buffers(sh, disks)) { -		shrink_buffers(sh, disks); +	if (grow_buffers(sh)) { +		shrink_buffers(sh);  		kmem_cache_free(conf->slab_cache, sh);  		return 0;  	} @@ -1468,7 +1536,7 @@ static int drop_one_stripe(raid5_conf_t *conf)  	if (!sh)  		return 0;  	BUG_ON(atomic_read(&sh->count)); -	shrink_buffers(sh, conf->pool_size); +	shrink_buffers(sh);  	kmem_cache_free(conf->slab_cache, sh);  	atomic_dec(&conf->active_stripes);  	return 1; @@ -2963,7 +3031,6 @@ static void handle_stripe5(struct stripe_head *sh)  		mdk_rdev_t *rdev;  		dev = &sh->dev[i]; -		clear_bit(R5_Insync, &dev->flags);  		pr_debug("check %d: state 0x%lx toread %p read %p write %p "  			"written %p\n",	i, dev->flags, dev->toread, dev->read, @@ -3000,17 +3067,27 @@ static void handle_stripe5(struct stripe_head *sh)  			blocked_rdev = rdev;  			atomic_inc(&rdev->nr_pending);  		} -		if (!rdev || !test_bit(In_sync, &rdev->flags)) { +		clear_bit(R5_Insync, &dev->flags); +		if (!rdev) +			/* Not in-sync */; +		else if (test_bit(In_sync, &rdev->flags)) +			set_bit(R5_Insync, &dev->flags); +		else { +			/* could be in-sync depending on recovery/reshape status */ +			if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset) +				set_bit(R5_Insync, &dev->flags); +		} +		if (!test_bit(R5_Insync, &dev->flags)) {  			/* The ReadError flag will just be confusing now */  			clear_bit(R5_ReadError, &dev->flags);  			clear_bit(R5_ReWrite, &dev->flags);  		} -		if (!rdev || !test_bit(In_sync, &rdev->flags) -		    || test_bit(R5_ReadError, &dev->flags)) { +		if (test_bit(R5_ReadError, &dev->flags)) +			clear_bit(R5_Insync, &dev->flags); +		if (!test_bit(R5_Insync, &dev->flags)) {  			s.failed++;  			s.failed_num = i; -		} else -			set_bit(R5_Insync, &dev->flags); +		}  	}  	rcu_read_unlock(); @@ -3244,7 +3321,6 @@ static void handle_stripe6(struct stripe_head *sh)  	for (i=disks; i--; ) {  		mdk_rdev_t *rdev;  		dev = &sh->dev[i]; -		clear_bit(R5_Insync, &dev->flags);  		pr_debug("check %d: state 0x%lx read %p write %p written %p\n",  			i, dev->flags, dev->toread, dev->towrite, dev->written); @@ -3282,18 +3358,28 @@ static void handle_stripe6(struct stripe_head *sh)  			blocked_rdev = rdev;  			atomic_inc(&rdev->nr_pending);  		} -		if (!rdev || !test_bit(In_sync, &rdev->flags)) { +		clear_bit(R5_Insync, &dev->flags); +		if (!rdev) +			/* Not in-sync */; +		else if (test_bit(In_sync, &rdev->flags)) +			set_bit(R5_Insync, &dev->flags); +		else { +			/* in sync if before recovery_offset */ +			if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset) +				set_bit(R5_Insync, &dev->flags); +		} +		if (!test_bit(R5_Insync, &dev->flags)) {  			/* The ReadError flag will just be confusing now */  			clear_bit(R5_ReadError, &dev->flags);  			clear_bit(R5_ReWrite, &dev->flags);  		} -		if (!rdev || !test_bit(In_sync, &rdev->flags) -		    || test_bit(R5_ReadError, &dev->flags)) { +		if (test_bit(R5_ReadError, &dev->flags)) +			clear_bit(R5_Insync, &dev->flags); +		if (!test_bit(R5_Insync, &dev->flags)) {  			if (s.failed < 2)  				r6s.failed_num[s.failed] = i;  			s.failed++; -		} else -			set_bit(R5_Insync, &dev->flags); +		}  	}  	rcu_read_unlock(); @@ -4971,8 +5057,10 @@ static int run(mddev_t *mddev)  	list_for_each_entry(rdev, &mddev->disks, same_set) {  		if (rdev->raid_disk < 0)  			continue; -		if (test_bit(In_sync, &rdev->flags)) +		if (test_bit(In_sync, &rdev->flags)) {  			working_disks++; +			continue; +		}  		/* This disc is not fully in-sync.  However if it  		 * just stored parity (beyond the recovery_offset),  		 * when we don't need to be concerned about the @@ -5005,7 +5093,7 @@ static int run(mddev_t *mddev)  	mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks)  			   - working_disks); -	if (mddev->degraded > conf->max_degraded) { +	if (has_failed(conf)) {  		printk(KERN_ERR "md/raid:%s: not enough operational devices"  			" (%d/%d failed)\n",  			mdname(mddev), mddev->degraded, conf->raid_disks); @@ -5207,6 +5295,7 @@ static int raid5_spare_active(mddev_t *mddev)  	for (i = 0; i < conf->raid_disks; i++) {  		tmp = conf->disks + i;  		if (tmp->rdev +		    && tmp->rdev->recovery_offset == MaxSector  		    && !test_bit(Faulty, &tmp->rdev->flags)  		    && !test_and_set_bit(In_sync, &tmp->rdev->flags)) {  			unsigned long flags; @@ -5242,7 +5331,7 @@ static int raid5_remove_disk(mddev_t *mddev, int number)  		 * isn't possible.  		 */  		if (!test_bit(Faulty, &rdev->flags) && -		    mddev->degraded <= conf->max_degraded && +		    !has_failed(conf) &&  		    number < conf->raid_disks) {  			err = -EBUSY;  			goto abort; @@ -5270,7 +5359,7 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)  	int first = 0;  	int last = conf->raid_disks - 1; -	if (mddev->degraded > conf->max_degraded) +	if (has_failed(conf))  		/* no point adding a device */  		return -EINVAL; @@ -5362,7 +5451,7 @@ static int check_reshape(mddev_t *mddev)  	if (mddev->bitmap)  		/* Cannot grow a bitmap yet */  		return -EBUSY; -	if (mddev->degraded > conf->max_degraded) +	if (has_failed(conf))  		return -EINVAL;  	if (mddev->delta_disks < 0) {  		/* We might be able to shrink, but the devices must @@ -5437,8 +5526,13 @@ static int raid5_start_reshape(mddev_t *mddev)  	/* Add some new drives, as many as will fit.  	 * We know there are enough to make the newly sized array work. +	 * Don't add devices if we are reducing the number of +	 * devices in the array.  This is because it is not possible +	 * to correctly record the "partially reconstructed" state of +	 * such devices during the reshape and confusion could result.  	 */ -	list_for_each_entry(rdev, &mddev->disks, same_set) +	if (mddev->delta_disks >= 0) +	    list_for_each_entry(rdev, &mddev->disks, same_set)  		if (rdev->raid_disk < 0 &&  		    !test_bit(Faulty, &rdev->flags)) {  			if (raid5_add_disk(mddev, rdev) == 0) { @@ -5460,7 +5554,7 @@ static int raid5_start_reshape(mddev_t *mddev)  		}  	/* When a reshape changes the number of devices, ->degraded -	 * is measured against the large of the pre and post number of +	 * is measured against the larger of the pre and post number of  	 * devices.*/  	if (mddev->delta_disks > 0) {  		spin_lock_irqsave(&conf->device_lock, flags); diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c index 8abbcc5fcf9..8cf2ab609d5 100644 --- a/drivers/media/common/tuners/tuner-simple.c +++ b/drivers/media/common/tuners/tuner-simple.c @@ -524,6 +524,7 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)  		buffer[3] = 0x39;  		break;  	case TUNER_PHILIPS_FQ1216LME_MK3: +	case TUNER_PHILIPS_FQ1236_MK5:  		tuner_err("This tuner doesn't have FM\n");  		/* Set the low band for sanity, since it covers 88-108 MHz */  		buffer[3] = 0x01; diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/common/tuners/tuner-types.c index d9aaaca620c..58a513bcd74 100644 --- a/drivers/media/common/tuners/tuner-types.c +++ b/drivers/media/common/tuners/tuner-types.c @@ -1353,6 +1353,17 @@ static struct tuner_params tuner_sony_btf_pxn01z_params[] = {  	},  }; +/* ------------ TUNER_PHILIPS_FQ1236_MK5 - Philips NTSC ------------ */ + +static struct tuner_params tuner_philips_fq1236_mk5_params[] = { +	{ +		.type   = TUNER_PARAM_TYPE_NTSC, +		.ranges = tuner_fm1236_mk3_ntsc_ranges, +		.count  = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), +		.has_tda9887 = 1, /* TDA9885, no FM radio */ +	}, +}; +  /* --------------------------------------------------------------------- */  struct tunertype tuners[] = { @@ -1826,6 +1837,11 @@ struct tunertype tuners[] = {  		.params = tuner_sony_btf_pxn01z_params,  		.count  = ARRAY_SIZE(tuner_sony_btf_pxn01z_params),  	}, +	[TUNER_PHILIPS_FQ1236_MK5] = { /* NTSC, TDA9885, no FM radio */ +		.name   = "Philips FQ1236 MK5", +		.params = tuner_philips_fq1236_mk5_params, +		.count  = ARRAY_SIZE(tuner_philips_fq1236_mk5_params), +	},  };  EXPORT_SYMBOL(tuners); diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index bdbc9d30541..27e2acce3c3 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -969,6 +969,19 @@ config VIDEO_OMAP2  	---help---  	  This is a v4l2 driver for the TI OMAP2 camera capture interface +config VIDEO_MX2_HOSTSUPPORT +        bool + +config VIDEO_MX2 +	tristate "i.MX27/i.MX25 Camera Sensor Interface driver" +	depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || ARCH_MX25) +	select VIDEOBUF_DMA_CONTIG +	select VIDEO_MX2_HOSTSUPPORT +	---help--- +	  This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor +	  Interface + +  #  # USB Multimedia device configuration  # diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index cc93859d316..b08bd2b65cd 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -162,6 +162,7 @@ obj-$(CONFIG_SOC_CAMERA)		+= soc_camera.o soc_mediabus.o  obj-$(CONFIG_SOC_CAMERA_PLATFORM)	+= soc_camera_platform.o  # soc-camera host drivers have to be linked after camera drivers  obj-$(CONFIG_VIDEO_MX1)			+= mx1_camera.o +obj-$(CONFIG_VIDEO_MX2)			+= mx2_camera.o  obj-$(CONFIG_VIDEO_MX3)			+= mx3_camera.o  obj-$(CONFIG_VIDEO_PXA27x)		+= pxa_camera.o  obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)	+= sh_mobile_ceu_camera.o diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 9ecacab4b89..a937e2ff9b6 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -912,6 +912,9 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)  	clear_bit(IVTV_F_S_STREAMING, &s->s_flags);  	ivtv_flush_queues(s); +	/* decoder needs time to settle */ +	ivtv_msleep_timeout(40, 0); +  	/* decrement decoding */  	atomic_dec(&itv->decoding); diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index 554eaf14012..10ddeccc70e 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -988,6 +988,9 @@ static int m2mtest_probe(struct platform_device *pdev)  		goto err_m2m;  	} +	q_data[V4L2_M2M_SRC].fmt = &formats[0]; +	q_data[V4L2_M2M_DST].fmt = &formats[0]; +  	return 0;  err_m2m: diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c new file mode 100644 index 00000000000..026bef0ba40 --- /dev/null +++ b/drivers/media/video/mx2_camera.c @@ -0,0 +1,1513 @@ +/* + * V4L2 Driver for i.MX27/i.MX25 camera host + * + * Copyright (C) 2008, Sascha Hauer, Pengutronix + * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/dma-mapping.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/moduleparam.h> +#include <linux/time.h> +#include <linux/version.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/mutex.h> +#include <linux/clk.h> + +#include <media/v4l2-common.h> +#include <media/v4l2-dev.h> +#include <media/videobuf-dma-contig.h> +#include <media/soc_camera.h> +#include <media/soc_mediabus.h> + +#include <linux/videodev2.h> + +#include <mach/mx2_cam.h> +#ifdef CONFIG_MACH_MX27 +#include <mach/dma-mx1-mx2.h> +#endif +#include <mach/hardware.h> + +#include <asm/dma.h> + +#define MX2_CAM_DRV_NAME "mx2-camera" +#define MX2_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5) +#define MX2_CAM_DRIVER_DESCRIPTION "i.MX2x_Camera" + +/* reset values */ +#define CSICR1_RESET_VAL	0x40000800 +#define CSICR2_RESET_VAL	0x0 +#define CSICR3_RESET_VAL	0x0 + +/* csi control reg 1 */ +#define CSICR1_SWAP16_EN	(1 << 31) +#define CSICR1_EXT_VSYNC	(1 << 30) +#define CSICR1_EOF_INTEN	(1 << 29) +#define CSICR1_PRP_IF_EN	(1 << 28) +#define CSICR1_CCIR_MODE	(1 << 27) +#define CSICR1_COF_INTEN	(1 << 26) +#define CSICR1_SF_OR_INTEN	(1 << 25) +#define CSICR1_RF_OR_INTEN	(1 << 24) +#define CSICR1_STATFF_LEVEL	(3 << 22) +#define CSICR1_STATFF_INTEN	(1 << 21) +#define CSICR1_RXFF_LEVEL(l)	(((l) & 3) << 19)	/* MX27 */ +#define CSICR1_FB2_DMA_INTEN	(1 << 20)		/* MX25 */ +#define CSICR1_FB1_DMA_INTEN	(1 << 19)		/* MX25 */ +#define CSICR1_RXFF_INTEN	(1 << 18) +#define CSICR1_SOF_POL		(1 << 17) +#define CSICR1_SOF_INTEN	(1 << 16) +#define CSICR1_MCLKDIV(d)	(((d) & 0xF) << 12) +#define CSICR1_HSYNC_POL	(1 << 11) +#define CSICR1_CCIR_EN		(1 << 10) +#define CSICR1_MCLKEN		(1 << 9) +#define CSICR1_FCC		(1 << 8) +#define CSICR1_PACK_DIR		(1 << 7) +#define CSICR1_CLR_STATFIFO	(1 << 6) +#define CSICR1_CLR_RXFIFO	(1 << 5) +#define CSICR1_GCLK_MODE	(1 << 4) +#define CSICR1_INV_DATA		(1 << 3) +#define CSICR1_INV_PCLK		(1 << 2) +#define CSICR1_REDGE		(1 << 1) + +#define SHIFT_STATFF_LEVEL	22 +#define SHIFT_RXFF_LEVEL	19 +#define SHIFT_MCLKDIV		12 + +/* control reg 3 */ +#define CSICR3_FRMCNT		(0xFFFF << 16) +#define CSICR3_FRMCNT_RST	(1 << 15) +#define CSICR3_DMA_REFLASH_RFF	(1 << 14) +#define CSICR3_DMA_REFLASH_SFF	(1 << 13) +#define CSICR3_DMA_REQ_EN_RFF	(1 << 12) +#define CSICR3_DMA_REQ_EN_SFF	(1 << 11) +#define CSICR3_RXFF_LEVEL(l)	(((l) & 7) << 4)	/* MX25 */ +#define CSICR3_CSI_SUP		(1 << 3) +#define CSICR3_ZERO_PACK_EN	(1 << 2) +#define CSICR3_ECC_INT_EN	(1 << 1) +#define CSICR3_ECC_AUTO_EN	(1 << 0) + +#define SHIFT_FRMCNT		16 + +/* csi status reg */ +#define CSISR_SFF_OR_INT	(1 << 25) +#define CSISR_RFF_OR_INT	(1 << 24) +#define CSISR_STATFF_INT	(1 << 21) +#define CSISR_DMA_TSF_FB2_INT	(1 << 20)	/* MX25 */ +#define CSISR_DMA_TSF_FB1_INT	(1 << 19)	/* MX25 */ +#define CSISR_RXFF_INT		(1 << 18) +#define CSISR_EOF_INT		(1 << 17) +#define CSISR_SOF_INT		(1 << 16) +#define CSISR_F2_INT		(1 << 15) +#define CSISR_F1_INT		(1 << 14) +#define CSISR_COF_INT		(1 << 13) +#define CSISR_ECC_INT		(1 << 1) +#define CSISR_DRDY		(1 << 0) + +#define CSICR1			0x00 +#define CSICR2			0x04 +#define CSISR			(cpu_is_mx27() ? 0x08 : 0x18) +#define CSISTATFIFO		0x0c +#define CSIRFIFO		0x10 +#define CSIRXCNT		0x14 +#define CSICR3			(cpu_is_mx27() ? 0x1C : 0x08) +#define CSIDMASA_STATFIFO	0x20 +#define CSIDMATA_STATFIFO	0x24 +#define CSIDMASA_FB1		0x28 +#define CSIDMASA_FB2		0x2c +#define CSIFBUF_PARA		0x30 +#define CSIIMAG_PARA		0x34 + +/* EMMA PrP */ +#define PRP_CNTL			0x00 +#define PRP_INTR_CNTL			0x04 +#define PRP_INTRSTATUS			0x08 +#define PRP_SOURCE_Y_PTR		0x0c +#define PRP_SOURCE_CB_PTR		0x10 +#define PRP_SOURCE_CR_PTR		0x14 +#define PRP_DEST_RGB1_PTR		0x18 +#define PRP_DEST_RGB2_PTR		0x1c +#define PRP_DEST_Y_PTR			0x20 +#define PRP_DEST_CB_PTR			0x24 +#define PRP_DEST_CR_PTR			0x28 +#define PRP_SRC_FRAME_SIZE		0x2c +#define PRP_DEST_CH1_LINE_STRIDE	0x30 +#define PRP_SRC_PIXEL_FORMAT_CNTL	0x34 +#define PRP_CH1_PIXEL_FORMAT_CNTL	0x38 +#define PRP_CH1_OUT_IMAGE_SIZE		0x3c +#define PRP_CH2_OUT_IMAGE_SIZE		0x40 +#define PRP_SRC_LINE_STRIDE		0x44 +#define PRP_CSC_COEF_012		0x48 +#define PRP_CSC_COEF_345		0x4c +#define PRP_CSC_COEF_678		0x50 +#define PRP_CH1_RZ_HORI_COEF1		0x54 +#define PRP_CH1_RZ_HORI_COEF2		0x58 +#define PRP_CH1_RZ_HORI_VALID		0x5c +#define PRP_CH1_RZ_VERT_COEF1		0x60 +#define PRP_CH1_RZ_VERT_COEF2		0x64 +#define PRP_CH1_RZ_VERT_VALID		0x68 +#define PRP_CH2_RZ_HORI_COEF1		0x6c +#define PRP_CH2_RZ_HORI_COEF2		0x70 +#define PRP_CH2_RZ_HORI_VALID		0x74 +#define PRP_CH2_RZ_VERT_COEF1		0x78 +#define PRP_CH2_RZ_VERT_COEF2		0x7c +#define PRP_CH2_RZ_VERT_VALID		0x80 + +#define PRP_CNTL_CH1EN		(1 << 0) +#define PRP_CNTL_CH2EN		(1 << 1) +#define PRP_CNTL_CSIEN		(1 << 2) +#define PRP_CNTL_DATA_IN_YUV420	(0 << 3) +#define PRP_CNTL_DATA_IN_YUV422	(1 << 3) +#define PRP_CNTL_DATA_IN_RGB16	(2 << 3) +#define PRP_CNTL_DATA_IN_RGB32	(3 << 3) +#define PRP_CNTL_CH1_OUT_RGB8	(0 << 5) +#define PRP_CNTL_CH1_OUT_RGB16	(1 << 5) +#define PRP_CNTL_CH1_OUT_RGB32	(2 << 5) +#define PRP_CNTL_CH1_OUT_YUV422	(3 << 5) +#define PRP_CNTL_CH2_OUT_YUV420	(0 << 7) +#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7) +#define PRP_CNTL_CH2_OUT_YUV444	(2 << 7) +#define PRP_CNTL_CH1_LEN	(1 << 9) +#define PRP_CNTL_CH2_LEN	(1 << 10) +#define PRP_CNTL_SKIP_FRAME	(1 << 11) +#define PRP_CNTL_SWRST		(1 << 12) +#define PRP_CNTL_CLKEN		(1 << 13) +#define PRP_CNTL_WEN		(1 << 14) +#define PRP_CNTL_CH1BYP		(1 << 15) +#define PRP_CNTL_IN_TSKIP(x)	((x) << 16) +#define PRP_CNTL_CH1_TSKIP(x)	((x) << 19) +#define PRP_CNTL_CH2_TSKIP(x)	((x) << 22) +#define PRP_CNTL_INPUT_FIFO_LEVEL(x)	((x) << 25) +#define PRP_CNTL_RZ_FIFO_LEVEL(x)	((x) << 27) +#define PRP_CNTL_CH2B1EN	(1 << 29) +#define PRP_CNTL_CH2B2EN	(1 << 30) +#define PRP_CNTL_CH2FEN		(1 << 31) + +/* IRQ Enable and status register */ +#define PRP_INTR_RDERR		(1 << 0) +#define PRP_INTR_CH1WERR	(1 << 1) +#define PRP_INTR_CH2WERR	(1 << 2) +#define PRP_INTR_CH1FC		(1 << 3) +#define PRP_INTR_CH2FC		(1 << 5) +#define PRP_INTR_LBOVF		(1 << 7) +#define PRP_INTR_CH2OVF		(1 << 8) + +#define mx27_camera_emma(pcdev)	(cpu_is_mx27() && pcdev->use_emma) + +#define MAX_VIDEO_MEM	16 + +struct mx2_camera_dev { +	struct device		*dev; +	struct soc_camera_host	soc_host; +	struct soc_camera_device *icd; +	struct clk		*clk_csi, *clk_emma; + +	unsigned int		irq_csi, irq_emma; +	void __iomem		*base_csi, *base_emma; +	unsigned long		base_dma; + +	struct mx2_camera_platform_data *pdata; +	struct resource		*res_csi, *res_emma; +	unsigned long		platform_flags; + +	struct list_head	capture; +	struct list_head	active_bufs; + +	spinlock_t		lock; + +	int			dma; +	struct mx2_buffer	*active; +	struct mx2_buffer	*fb1_active; +	struct mx2_buffer	*fb2_active; + +	int			use_emma; + +	u32			csicr1; + +	void			*discard_buffer; +	dma_addr_t		discard_buffer_dma; +	size_t			discard_size; +}; + +/* buffer for one video frame */ +struct mx2_buffer { +	/* common v4l buffer stuff -- must be first */ +	struct videobuf_buffer		vb; + +	enum v4l2_mbus_pixelcode	code; + +	int bufnum; +}; + +static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) +{ +	unsigned long flags; + +	clk_disable(pcdev->clk_csi); +	writel(0, pcdev->base_csi + CSICR1); +	if (mx27_camera_emma(pcdev)) { +		writel(0, pcdev->base_emma + PRP_CNTL); +	} else if (cpu_is_mx25()) { +		spin_lock_irqsave(&pcdev->lock, flags); +		pcdev->fb1_active = NULL; +		pcdev->fb2_active = NULL; +		writel(0, pcdev->base_csi + CSIDMASA_FB1); +		writel(0, pcdev->base_csi + CSIDMASA_FB2); +		spin_unlock_irqrestore(&pcdev->lock, flags); +	} +} + +/* + * The following two functions absolutely depend on the fact, that + * there can be only one camera on mx2 camera sensor interface + */ +static int mx2_camera_add_device(struct soc_camera_device *icd) +{ +	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); +	struct mx2_camera_dev *pcdev = ici->priv; +	int ret; +	u32 csicr1; + +	if (pcdev->icd) +		return -EBUSY; + +	ret = clk_enable(pcdev->clk_csi); +	if (ret < 0) +		return ret; + +	csicr1 = CSICR1_MCLKEN; + +	if (mx27_camera_emma(pcdev)) { +		csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC | +			CSICR1_RXFF_LEVEL(0); +	} else if (cpu_is_mx27()) +		csicr1 |= CSICR1_SOF_INTEN | CSICR1_RXFF_LEVEL(2); + +	pcdev->csicr1 = csicr1; +	writel(pcdev->csicr1, pcdev->base_csi + CSICR1); + +	pcdev->icd = icd; + +	dev_info(icd->dev.parent, "Camera driver attached to camera %d\n", +		 icd->devnum); + +	return 0; +} + +static void mx2_camera_remove_device(struct soc_camera_device *icd) +{ +	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); +	struct mx2_camera_dev *pcdev = ici->priv; + +	BUG_ON(icd != pcdev->icd); + +	dev_info(icd->dev.parent, "Camera driver detached from camera %d\n", +		 icd->devnum); + +	mx2_camera_deactivate(pcdev); + +	if (pcdev->discard_buffer) { +		dma_free_coherent(ici->v4l2_dev.dev, pcdev->discard_size, +				pcdev->discard_buffer, +				pcdev->discard_buffer_dma); +		pcdev->discard_buffer = NULL; +	} + +	pcdev->icd = NULL; +} + +#ifdef CONFIG_MACH_MX27 +static void mx27_camera_dma_enable(struct mx2_camera_dev *pcdev) +{ +	u32 tmp; + +	imx_dma_enable(pcdev->dma); + +	tmp = readl(pcdev->base_csi + CSICR1); +	tmp |= CSICR1_RF_OR_INTEN; +	writel(tmp, pcdev->base_csi + CSICR1); +} + +static irqreturn_t mx27_camera_irq(int irq_csi, void *data) +{ +	struct mx2_camera_dev *pcdev = data; +	u32 status = readl(pcdev->base_csi + CSISR); + +	if (status & CSISR_SOF_INT && pcdev->active) { +		u32 tmp; + +		tmp = readl(pcdev->base_csi + CSICR1); +		writel(tmp | CSICR1_CLR_RXFIFO, pcdev->base_csi + CSICR1); +		mx27_camera_dma_enable(pcdev); +	} + +	writel(CSISR_SOF_INT | CSISR_RFF_OR_INT, pcdev->base_csi + CSISR); + +	return IRQ_HANDLED; +} +#else +static irqreturn_t mx27_camera_irq(int irq_csi, void *data) +{ +	return IRQ_NONE; +} +#endif /* CONFIG_MACH_MX27 */ + +static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, +		int state) +{ +	struct videobuf_buffer *vb; +	struct mx2_buffer *buf; +	struct mx2_buffer **fb_active = fb == 1 ? &pcdev->fb1_active : +		&pcdev->fb2_active; +	u32 fb_reg = fb == 1 ? CSIDMASA_FB1 : CSIDMASA_FB2; +	unsigned long flags; + +	spin_lock_irqsave(&pcdev->lock, flags); + +	vb = &(*fb_active)->vb; +	dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +		vb, vb->baddr, vb->bsize); + +	vb->state = state; +	do_gettimeofday(&vb->ts); +	vb->field_count++; + +	wake_up(&vb->done); + +	if (list_empty(&pcdev->capture)) { +		buf = NULL; +		writel(0, pcdev->base_csi + fb_reg); +	} else { +		buf = list_entry(pcdev->capture.next, struct mx2_buffer, +				vb.queue); +		vb = &buf->vb; +		list_del(&vb->queue); +		vb->state = VIDEOBUF_ACTIVE; +		writel(videobuf_to_dma_contig(vb), pcdev->base_csi + fb_reg); +	} + +	*fb_active = buf; + +	spin_unlock_irqrestore(&pcdev->lock, flags); +} + +static irqreturn_t mx25_camera_irq(int irq_csi, void *data) +{ +	struct mx2_camera_dev *pcdev = data; +	u32 status = readl(pcdev->base_csi + CSISR); + +	if (status & CSISR_DMA_TSF_FB1_INT) +		mx25_camera_frame_done(pcdev, 1, VIDEOBUF_DONE); +	else if (status & CSISR_DMA_TSF_FB2_INT) +		mx25_camera_frame_done(pcdev, 2, VIDEOBUF_DONE); + +	/* FIXME: handle CSISR_RFF_OR_INT */ + +	writel(status, pcdev->base_csi + CSISR); + +	return IRQ_HANDLED; +} + +/* + *  Videobuf operations + */ +static int mx2_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, +			      unsigned int *size) +{ +	struct soc_camera_device *icd = vq->priv_data; +	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, +			icd->current_fmt->host_fmt); + +	dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); + +	if (bytes_per_line < 0) +		return bytes_per_line; + +	*size = bytes_per_line * icd->user_height; + +	if (0 == *count) +		*count = 32; +	if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) +		*count = (MAX_VIDEO_MEM * 1024 * 1024) / *size; + +	return 0; +} + +static void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf) +{ +	struct soc_camera_device *icd = vq->priv_data; +	struct videobuf_buffer *vb = &buf->vb; + +	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +		vb, vb->baddr, vb->bsize); + +	/* +	 * This waits until this buffer is out of danger, i.e., until it is no +	 * longer in STATE_QUEUED or STATE_ACTIVE +	 */ +	videobuf_waiton(vb, 0, 0); + +	videobuf_dma_contig_free(vq, vb); +	dev_dbg(&icd->dev, "%s freed\n", __func__); + +	vb->state = VIDEOBUF_NEEDS_INIT; +} + +static int mx2_videobuf_prepare(struct videobuf_queue *vq, +		struct videobuf_buffer *vb, enum v4l2_field field) +{ +	struct soc_camera_device *icd = vq->priv_data; +	struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); +	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, +			icd->current_fmt->host_fmt); +	int ret = 0; + +	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +		vb, vb->baddr, vb->bsize); + +	if (bytes_per_line < 0) +		return bytes_per_line; + +#ifdef DEBUG +	/* +	 * This can be useful if you want to see if we actually fill +	 * the buffer with something +	 */ +	memset((void *)vb->baddr, 0xaa, vb->bsize); +#endif + +	if (buf->code	!= icd->current_fmt->code || +	    vb->width	!= icd->user_width || +	    vb->height	!= icd->user_height || +	    vb->field	!= field) { +		buf->code	= icd->current_fmt->code; +		vb->width	= icd->user_width; +		vb->height	= icd->user_height; +		vb->field	= field; +		vb->state	= VIDEOBUF_NEEDS_INIT; +	} + +	vb->size = bytes_per_line * vb->height; +	if (vb->baddr && vb->bsize < vb->size) { +		ret = -EINVAL; +		goto out; +	} + +	if (vb->state == VIDEOBUF_NEEDS_INIT) { +		ret = videobuf_iolock(vq, vb, NULL); +		if (ret) +			goto fail; + +		vb->state = VIDEOBUF_PREPARED; +	} + +	return 0; + +fail: +	free_buffer(vq, buf); +out: +	return ret; +} + +static void mx2_videobuf_queue(struct videobuf_queue *vq, +			       struct videobuf_buffer *vb) +{ +	struct soc_camera_device *icd = vq->priv_data; +	struct soc_camera_host *ici = +		to_soc_camera_host(icd->dev.parent); +	struct mx2_camera_dev *pcdev = ici->priv; +	struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); +	unsigned long flags; + +	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +		vb, vb->baddr, vb->bsize); + +	spin_lock_irqsave(&pcdev->lock, flags); + +	vb->state = VIDEOBUF_QUEUED; +	list_add_tail(&vb->queue, &pcdev->capture); + +	if (mx27_camera_emma(pcdev)) { +		goto out; +#ifdef CONFIG_MACH_MX27 +	} else if (cpu_is_mx27()) { +		int ret; + +		if (pcdev->active == NULL) { +			ret = imx_dma_setup_single(pcdev->dma, +					videobuf_to_dma_contig(vb), vb->size, +					(u32)pcdev->base_dma + 0x10, +					DMA_MODE_READ); +			if (ret) { +				vb->state = VIDEOBUF_ERROR; +				wake_up(&vb->done); +				goto out; +			} + +			vb->state = VIDEOBUF_ACTIVE; +			pcdev->active = buf; +		} +#endif +	} else { /* cpu_is_mx25() */ +		u32 csicr3, dma_inten = 0; + +		if (pcdev->fb1_active == NULL) { +			writel(videobuf_to_dma_contig(vb), +					pcdev->base_csi + CSIDMASA_FB1); +			pcdev->fb1_active = buf; +			dma_inten = CSICR1_FB1_DMA_INTEN; +		} else if (pcdev->fb2_active == NULL) { +			writel(videobuf_to_dma_contig(vb), +					pcdev->base_csi + CSIDMASA_FB2); +			pcdev->fb2_active = buf; +			dma_inten = CSICR1_FB2_DMA_INTEN; +		} + +		if (dma_inten) { +			list_del(&vb->queue); +			vb->state = VIDEOBUF_ACTIVE; + +			csicr3 = readl(pcdev->base_csi + CSICR3); + +			/* Reflash DMA */ +			writel(csicr3 | CSICR3_DMA_REFLASH_RFF, +					pcdev->base_csi + CSICR3); + +			/* clear & enable interrupts */ +			writel(dma_inten, pcdev->base_csi + CSISR); +			pcdev->csicr1 |= dma_inten; +			writel(pcdev->csicr1, pcdev->base_csi + CSICR1); + +			/* enable DMA */ +			csicr3 |= CSICR3_DMA_REQ_EN_RFF | CSICR3_RXFF_LEVEL(1); +			writel(csicr3, pcdev->base_csi + CSICR3); +		} +	} + +out: +	spin_unlock_irqrestore(&pcdev->lock, flags); +} + +static void mx2_videobuf_release(struct videobuf_queue *vq, +				 struct videobuf_buffer *vb) +{ +	struct soc_camera_device *icd = vq->priv_data; +	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); +	struct mx2_camera_dev *pcdev = ici->priv; +	struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); +	unsigned long flags; + +#ifdef DEBUG +	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +		vb, vb->baddr, vb->bsize); + +	switch (vb->state) { +	case VIDEOBUF_ACTIVE: +		dev_info(&icd->dev, "%s (active)\n", __func__); +		break; +	case VIDEOBUF_QUEUED: +		dev_info(&icd->dev, "%s (queued)\n", __func__); +		break; +	case VIDEOBUF_PREPARED: +		dev_info(&icd->dev, "%s (prepared)\n", __func__); +		break; +	default: +		dev_info(&icd->dev, "%s (unknown) %d\n", __func__, +				vb->state); +		break; +	} +#endif + +	/* +	 * Terminate only queued but inactive buffers. Active buffers are +	 * released when they become inactive after videobuf_waiton(). +	 * +	 * FIXME: implement forced termination of active buffers, so that the +	 * user won't get stuck in an uninterruptible state. This requires a +	 * specific handling for each of the three DMA types that this driver +	 * supports. +	 */ +	spin_lock_irqsave(&pcdev->lock, flags); +	if (vb->state == VIDEOBUF_QUEUED) { +		list_del(&vb->queue); +		vb->state = VIDEOBUF_ERROR; +	} +	spin_unlock_irqrestore(&pcdev->lock, flags); + +	free_buffer(vq, buf); +} + +static struct videobuf_queue_ops mx2_videobuf_ops = { +	.buf_setup      = mx2_videobuf_setup, +	.buf_prepare    = mx2_videobuf_prepare, +	.buf_queue      = mx2_videobuf_queue, +	.buf_release    = mx2_videobuf_release, +}; + +static void mx2_camera_init_videobuf(struct videobuf_queue *q, +			      struct soc_camera_device *icd) +{ +	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); +	struct mx2_camera_dev *pcdev = ici->priv; + +	videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev, +			&pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, +			V4L2_FIELD_NONE, sizeof(struct mx2_buffer), icd); +} + +#define MX2_BUS_FLAGS	(SOCAM_DATAWIDTH_8 | \ +			SOCAM_MASTER | \ +			SOCAM_VSYNC_ACTIVE_HIGH | \ +			SOCAM_VSYNC_ACTIVE_LOW | \ +			SOCAM_HSYNC_ACTIVE_HIGH | \ +			SOCAM_HSYNC_ACTIVE_LOW | \ +			SOCAM_PCLK_SAMPLE_RISING | \ +			SOCAM_PCLK_SAMPLE_FALLING | \ +			SOCAM_DATA_ACTIVE_HIGH | \ +			SOCAM_DATA_ACTIVE_LOW) + +static int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev) +{ +	u32 cntl; +	int count = 0; + +	cntl = readl(pcdev->base_emma + PRP_CNTL); +	writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL); +	while (count++ < 100) { +		if (!(readl(pcdev->base_emma + PRP_CNTL) & PRP_CNTL_SWRST)) +			return 0; +		barrier(); +		udelay(1); +	} + +	return -ETIMEDOUT; +} + +static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, +		int bytesperline) +{ +	struct soc_camera_host *ici = +		to_soc_camera_host(icd->dev.parent); +	struct mx2_camera_dev *pcdev = ici->priv; + +	writel(pcdev->discard_buffer_dma, +			pcdev->base_emma + PRP_DEST_RGB1_PTR); +	writel(pcdev->discard_buffer_dma, +			pcdev->base_emma + PRP_DEST_RGB2_PTR); + +	/* +	 * We only use the EMMA engine to get rid of the broken +	 * DMA Engine. No color space consversion at the moment. +	 * We adjust incoming and outgoing pixelformat to rgb16 +	 * and adjust the bytesperline accordingly. +	 */ +	writel(PRP_CNTL_CH1EN | +			PRP_CNTL_CSIEN | +			PRP_CNTL_DATA_IN_RGB16 | +			PRP_CNTL_CH1_OUT_RGB16 | +			PRP_CNTL_CH1_LEN | +			PRP_CNTL_CH1BYP | +			PRP_CNTL_CH1_TSKIP(0) | +			PRP_CNTL_IN_TSKIP(0), +			pcdev->base_emma + PRP_CNTL); + +	writel(((bytesperline >> 1) << 16) | icd->user_height, +			pcdev->base_emma + PRP_SRC_FRAME_SIZE); +	writel(((bytesperline >> 1) << 16) | icd->user_height, +			pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); +	writel(bytesperline, +			pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); +	writel(0x2ca00565, /* RGB565 */ +			pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); +	writel(0x2ca00565, /* RGB565 */ +			pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); + +	/* Enable interrupts */ +	writel(PRP_INTR_RDERR | +			PRP_INTR_CH1WERR | +			PRP_INTR_CH2WERR | +			PRP_INTR_CH1FC | +			PRP_INTR_CH2FC | +			PRP_INTR_LBOVF | +			PRP_INTR_CH2OVF, +			pcdev->base_emma + PRP_INTR_CNTL); +} + +static int mx2_camera_set_bus_param(struct soc_camera_device *icd, +		__u32 pixfmt) +{ +	struct soc_camera_host *ici = +		to_soc_camera_host(icd->dev.parent); +	struct mx2_camera_dev *pcdev = ici->priv; +	unsigned long camera_flags, common_flags; +	int ret = 0; +	int bytesperline; +	u32 csicr1 = pcdev->csicr1; + +	camera_flags = icd->ops->query_bus_param(icd); + +	common_flags = soc_camera_bus_param_compatible(camera_flags, +				MX2_BUS_FLAGS); +	if (!common_flags) +		return -EINVAL; + +	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && +	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { +		if (pcdev->platform_flags & MX2_CAMERA_HSYNC_HIGH) +			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; +		else +			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; +	} + +	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && +	    (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { +		if (pcdev->platform_flags & MX2_CAMERA_PCLK_SAMPLE_RISING) +			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; +		else +			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; +	} + +	ret = icd->ops->set_bus_param(icd, common_flags); +	if (ret < 0) +		return ret; + +	if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) +		csicr1 |= CSICR1_INV_PCLK; +	if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) +		csicr1 |= CSICR1_SOF_POL; +	if (common_flags & SOCAM_HSYNC_ACTIVE_HIGH) +		csicr1 |= CSICR1_HSYNC_POL; +	if (pcdev->platform_flags & MX2_CAMERA_SWAP16) +		csicr1 |= CSICR1_SWAP16_EN; +	if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC) +		csicr1 |= CSICR1_EXT_VSYNC; +	if (pcdev->platform_flags & MX2_CAMERA_CCIR) +		csicr1 |= CSICR1_CCIR_EN; +	if (pcdev->platform_flags & MX2_CAMERA_CCIR_INTERLACE) +		csicr1 |= CSICR1_CCIR_MODE; +	if (pcdev->platform_flags & MX2_CAMERA_GATED_CLOCK) +		csicr1 |= CSICR1_GCLK_MODE; +	if (pcdev->platform_flags & MX2_CAMERA_INV_DATA) +		csicr1 |= CSICR1_INV_DATA; +	if (pcdev->platform_flags & MX2_CAMERA_PACK_DIR_MSB) +		csicr1 |= CSICR1_PACK_DIR; + +	pcdev->csicr1 = csicr1; + +	bytesperline = soc_mbus_bytes_per_line(icd->user_width, +			icd->current_fmt->host_fmt); +	if (bytesperline < 0) +		return bytesperline; + +	if (mx27_camera_emma(pcdev)) { +		ret = mx27_camera_emma_prp_reset(pcdev); +		if (ret) +			return ret; + +		if (pcdev->discard_buffer) +			dma_free_coherent(ici->v4l2_dev.dev, +				pcdev->discard_size, pcdev->discard_buffer, +				pcdev->discard_buffer_dma); + +		/* +		 * I didn't manage to properly enable/disable the prp +		 * on a per frame basis during running transfers, +		 * thus we allocate a buffer here and use it to +		 * discard frames when no buffer is available. +		 * Feel free to work on this ;) +		 */ +		pcdev->discard_size = icd->user_height * bytesperline; +		pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, +				pcdev->discard_size, &pcdev->discard_buffer_dma, +				GFP_KERNEL); +		if (!pcdev->discard_buffer) +			return -ENOMEM; + +		mx27_camera_emma_buf_init(icd, bytesperline); +	} else if (cpu_is_mx25()) { +		writel((bytesperline * icd->user_height) >> 2, +				pcdev->base_csi + CSIRXCNT); +		writel((bytesperline << 16) | icd->user_height, +				pcdev->base_csi + CSIIMAG_PARA); +	} + +	writel(pcdev->csicr1, pcdev->base_csi + CSICR1); + +	return 0; +} + +static int mx2_camera_set_crop(struct soc_camera_device *icd, +				struct v4l2_crop *a) +{ +	struct v4l2_rect *rect = &a->c; +	struct v4l2_subdev *sd = soc_camera_to_subdev(icd); +	struct v4l2_mbus_framefmt mf; +	int ret; + +	soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); +	soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096); + +	ret = v4l2_subdev_call(sd, video, s_crop, a); +	if (ret < 0) +		return ret; + +	/* The capture device might have changed its output  */ +	ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); +	if (ret < 0) +		return ret; + +	dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", +		mf.width, mf.height); + +	icd->user_width		= mf.width; +	icd->user_height	= mf.height; + +	return ret; +} + +static int mx2_camera_set_fmt(struct soc_camera_device *icd, +			       struct v4l2_format *f) +{ +	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); +	struct mx2_camera_dev *pcdev = ici->priv; +	struct v4l2_subdev *sd = soc_camera_to_subdev(icd); +	const struct soc_camera_format_xlate *xlate; +	struct v4l2_pix_format *pix = &f->fmt.pix; +	struct v4l2_mbus_framefmt mf; +	int ret; + +	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); +	if (!xlate) { +		dev_warn(icd->dev.parent, "Format %x not found\n", +				pix->pixelformat); +		return -EINVAL; +	} + +	/* eMMA can only do RGB565 */ +	if (mx27_camera_emma(pcdev) && pix->pixelformat != V4L2_PIX_FMT_RGB565) +		return -EINVAL; + +	mf.width	= pix->width; +	mf.height	= pix->height; +	mf.field	= pix->field; +	mf.colorspace	= pix->colorspace; +	mf.code		= xlate->code; + +	ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); +	if (ret < 0 && ret != -ENOIOCTLCMD) +		return ret; + +	if (mf.code != xlate->code) +		return -EINVAL; + +	pix->width		= mf.width; +	pix->height		= mf.height; +	pix->field		= mf.field; +	pix->colorspace		= mf.colorspace; +	icd->current_fmt	= xlate; + +	return 0; +} + +static int mx2_camera_try_fmt(struct soc_camera_device *icd, +				  struct v4l2_format *f) +{ +	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); +	struct mx2_camera_dev *pcdev = ici->priv; +	struct v4l2_subdev *sd = soc_camera_to_subdev(icd); +	const struct soc_camera_format_xlate *xlate; +	struct v4l2_pix_format *pix = &f->fmt.pix; +	struct v4l2_mbus_framefmt mf; +	__u32 pixfmt = pix->pixelformat; +	unsigned int width_limit; +	int ret; + +	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); +	if (pixfmt && !xlate) { +		dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); +		return -EINVAL; +	} + +	/* FIXME: implement MX27 limits */ + +	/* eMMA can only do RGB565 */ +	if (mx27_camera_emma(pcdev) && pixfmt != V4L2_PIX_FMT_RGB565) +		return -EINVAL; + +	/* limit to MX25 hardware capabilities */ +	if (cpu_is_mx25()) { +		if (xlate->host_fmt->bits_per_sample <= 8) +			width_limit = 0xffff * 4; +		else +			width_limit = 0xffff * 2; +		/* CSIIMAG_PARA limit */ +		if (pix->width > width_limit) +			pix->width = width_limit; +		if (pix->height > 0xffff) +			pix->height = 0xffff; + +		pix->bytesperline = soc_mbus_bytes_per_line(pix->width, +				xlate->host_fmt); +		if (pix->bytesperline < 0) +			return pix->bytesperline; +		pix->sizeimage = pix->height * pix->bytesperline; +		if (pix->sizeimage > (4 * 0x3ffff)) { /* CSIRXCNT limit */ +			dev_warn(icd->dev.parent, +					"Image size (%u) above limit\n", +					pix->sizeimage); +			return -EINVAL; +		} +	} + +	/* limit to sensor capabilities */ +	mf.width	= pix->width; +	mf.height	= pix->height; +	mf.field	= pix->field; +	mf.colorspace	= pix->colorspace; +	mf.code		= xlate->code; + +	ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); +	if (ret < 0) +		return ret; + +	if (mf.field == V4L2_FIELD_ANY) +		mf.field = V4L2_FIELD_NONE; +	if (mf.field != V4L2_FIELD_NONE) { +		dev_err(icd->dev.parent, "Field type %d unsupported.\n", +				mf.field); +		return -EINVAL; +	} + +	pix->width	= mf.width; +	pix->height	= mf.height; +	pix->field	= mf.field; +	pix->colorspace	= mf.colorspace; + +	return 0; +} + +static int mx2_camera_querycap(struct soc_camera_host *ici, +			       struct v4l2_capability *cap) +{ +	/* cap->name is set by the friendly caller:-> */ +	strlcpy(cap->card, MX2_CAM_DRIVER_DESCRIPTION, sizeof(cap->card)); +	cap->version = MX2_CAM_VERSION_CODE; +	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + +	return 0; +} + +static int mx2_camera_reqbufs(struct soc_camera_file *icf, +			      struct v4l2_requestbuffers *p) +{ +	int i; + +	for (i = 0; i < p->count; i++) { +		struct mx2_buffer *buf = container_of(icf->vb_vidq.bufs[i], +						      struct mx2_buffer, vb); +		INIT_LIST_HEAD(&buf->vb.queue); +	} + +	return 0; +} + +#ifdef CONFIG_MACH_MX27 +static void mx27_camera_frame_done(struct mx2_camera_dev *pcdev, int state) +{ +	struct videobuf_buffer *vb; +	struct mx2_buffer *buf; +	unsigned long flags; +	int ret; + +	spin_lock_irqsave(&pcdev->lock, flags); + +	if (!pcdev->active) { +		dev_err(pcdev->dev, "%s called with no active buffer!\n", +				__func__); +		goto out; +	} + +	vb = &pcdev->active->vb; +	buf = container_of(vb, struct mx2_buffer, vb); +	WARN_ON(list_empty(&vb->queue)); +	dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, +		vb, vb->baddr, vb->bsize); + +	/* _init is used to debug races, see comment in pxa_camera_reqbufs() */ +	list_del_init(&vb->queue); +	vb->state = state; +	do_gettimeofday(&vb->ts); +	vb->field_count++; + +	wake_up(&vb->done); + +	if (list_empty(&pcdev->capture)) { +		pcdev->active = NULL; +		goto out; +	} + +	pcdev->active = list_entry(pcdev->capture.next, +			struct mx2_buffer, vb.queue); + +	vb = &pcdev->active->vb; +	vb->state = VIDEOBUF_ACTIVE; + +	ret = imx_dma_setup_single(pcdev->dma, videobuf_to_dma_contig(vb), +			vb->size, (u32)pcdev->base_dma + 0x10, DMA_MODE_READ); + +	if (ret) { +		vb->state = VIDEOBUF_ERROR; +		pcdev->active = NULL; +		wake_up(&vb->done); +	} + +out: +	spin_unlock_irqrestore(&pcdev->lock, flags); +} + +static void mx27_camera_dma_err_callback(int channel, void *data, int err) +{ +	struct mx2_camera_dev *pcdev = data; + +	mx27_camera_frame_done(pcdev, VIDEOBUF_ERROR); +} + +static void mx27_camera_dma_callback(int channel, void *data) +{ +	struct mx2_camera_dev *pcdev = data; + +	mx27_camera_frame_done(pcdev, VIDEOBUF_DONE); +} + +#define DMA_REQ_CSI_RX          31 /* FIXME: Add this to a resource */ + +static int __devinit mx27_camera_dma_init(struct platform_device *pdev, +		struct mx2_camera_dev *pcdev) +{ +	int err; + +	pcdev->dma = imx_dma_request_by_prio("CSI RX DMA", DMA_PRIO_HIGH); +	if (pcdev->dma < 0) { +		dev_err(&pdev->dev, "%s failed to request DMA channel\n", +				__func__); +		return pcdev->dma; +	} + +	err = imx_dma_setup_handlers(pcdev->dma, mx27_camera_dma_callback, +					mx27_camera_dma_err_callback, pcdev); +	if (err) { +		dev_err(&pdev->dev, "%s failed to set DMA callback\n", +				__func__); +		goto err_out; +	} + +	err = imx_dma_config_channel(pcdev->dma, +			IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO, +			IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, +			DMA_REQ_CSI_RX, 1); +	if (err) { +		dev_err(&pdev->dev, "%s failed to config DMA channel\n", +				__func__); +		goto err_out; +	} + +	imx_dma_config_burstlen(pcdev->dma, 64); + +	return 0; + +err_out: +	imx_dma_free(pcdev->dma); + +	return err; +} +#endif /* CONFIG_MACH_MX27 */ + +static unsigned int mx2_camera_poll(struct file *file, poll_table *pt) +{ +	struct soc_camera_file *icf = file->private_data; + +	return videobuf_poll_stream(file, &icf->vb_vidq, pt); +} + +static struct soc_camera_host_ops mx2_soc_camera_host_ops = { +	.owner		= THIS_MODULE, +	.add		= mx2_camera_add_device, +	.remove		= mx2_camera_remove_device, +	.set_fmt	= mx2_camera_set_fmt, +	.set_crop	= mx2_camera_set_crop, +	.try_fmt	= mx2_camera_try_fmt, +	.init_videobuf	= mx2_camera_init_videobuf, +	.reqbufs	= mx2_camera_reqbufs, +	.poll		= mx2_camera_poll, +	.querycap	= mx2_camera_querycap, +	.set_bus_param	= mx2_camera_set_bus_param, +}; + +static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, +		int bufnum, int state) +{ +	struct mx2_buffer *buf; +	struct videobuf_buffer *vb; +	unsigned long phys; + +	if (!list_empty(&pcdev->active_bufs)) { +		buf = list_entry(pcdev->active_bufs.next, +			struct mx2_buffer, vb.queue); + +		BUG_ON(buf->bufnum != bufnum); + +		vb = &buf->vb; +#ifdef DEBUG +		phys = videobuf_to_dma_contig(vb); +		if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum) +				!= phys) { +			dev_err(pcdev->dev, "%p != %p\n", phys, +					readl(pcdev->base_emma + +						PRP_DEST_RGB1_PTR + +						4 * bufnum)); +		} +#endif +		dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, +				vb->baddr, vb->bsize); + +		list_del(&vb->queue); +		vb->state = state; +		do_gettimeofday(&vb->ts); +		vb->field_count++; + +		wake_up(&vb->done); +	} + +	if (list_empty(&pcdev->capture)) { +		writel(pcdev->discard_buffer_dma, pcdev->base_emma + +				PRP_DEST_RGB1_PTR + 4 * bufnum); +		return; +	} + +	buf = list_entry(pcdev->capture.next, +			struct mx2_buffer, vb.queue); + +	buf->bufnum = bufnum; + +	list_move_tail(pcdev->capture.next, &pcdev->active_bufs); + +	vb = &buf->vb; +	vb->state = VIDEOBUF_ACTIVE; + +	phys = videobuf_to_dma_contig(vb); +	writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum); +} + +static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) +{ +	struct mx2_camera_dev *pcdev = data; +	unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS); +	struct mx2_buffer *buf; + +	if (status & (1 << 7)) { /* overflow */ +		u32 cntl; +		/* +		 * We only disable channel 1 here since this is the only +		 * enabled channel +		 * +		 * FIXME: the correct DMA overflow handling should be resetting +		 * the buffer, returning an error frame, and continuing with +		 * the next one. +		 */ +		cntl = readl(pcdev->base_emma + PRP_CNTL); +		writel(cntl & ~PRP_CNTL_CH1EN, pcdev->base_emma + PRP_CNTL); +		writel(cntl, pcdev->base_emma + PRP_CNTL); +	} +	if ((status & (3 << 5)) == (3 << 5) +			&& !list_empty(&pcdev->active_bufs)) { +		/* +		 * Both buffers have triggered, process the one we're expecting +		 * to first +		 */ +		buf = list_entry(pcdev->active_bufs.next, +			struct mx2_buffer, vb.queue); +		mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE); +		status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ +	} +	if (status & (1 << 6)) +		mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE); +	if (status & (1 << 5)) +		mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE); + +	writel(status, pcdev->base_emma + PRP_INTRSTATUS); + +	return IRQ_HANDLED; +} + +static int __devinit mx27_camera_emma_init(struct mx2_camera_dev *pcdev) +{ +	struct resource *res_emma = pcdev->res_emma; +	int err = 0; + +	if (!request_mem_region(res_emma->start, resource_size(res_emma), +				MX2_CAM_DRV_NAME)) { +		err = -EBUSY; +		goto out; +	} + +	pcdev->base_emma = ioremap(res_emma->start, resource_size(res_emma)); +	if (!pcdev->base_emma) { +		err = -ENOMEM; +		goto exit_release; +	} + +	err = request_irq(pcdev->irq_emma, mx27_camera_emma_irq, 0, +			MX2_CAM_DRV_NAME, pcdev); +	if (err) { +		dev_err(pcdev->dev, "Camera EMMA interrupt register failed \n"); +		goto exit_iounmap; +	} + +	pcdev->clk_emma = clk_get(NULL, "emma"); +	if (IS_ERR(pcdev->clk_emma)) { +		err = PTR_ERR(pcdev->clk_emma); +		goto exit_free_irq; +	} + +	clk_enable(pcdev->clk_emma); + +	err = mx27_camera_emma_prp_reset(pcdev); +	if (err) +		goto exit_clk_emma_put; + +	return err; + +exit_clk_emma_put: +	clk_disable(pcdev->clk_emma); +	clk_put(pcdev->clk_emma); +exit_free_irq: +	free_irq(pcdev->irq_emma, pcdev); +exit_iounmap: +	iounmap(pcdev->base_emma); +exit_release: +	release_mem_region(res_emma->start, resource_size(res_emma)); +out: +	return err; +} + +static int __devinit mx2_camera_probe(struct platform_device *pdev) +{ +	struct mx2_camera_dev *pcdev; +	struct resource *res_csi, *res_emma; +	void __iomem *base_csi; +	int irq_csi, irq_emma; +	irq_handler_t mx2_cam_irq_handler = cpu_is_mx25() ? mx25_camera_irq +		: mx27_camera_irq; +	int err = 0; + +	dev_dbg(&pdev->dev, "initialising\n"); + +	res_csi = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	irq_csi = platform_get_irq(pdev, 0); +	if (res_csi == NULL || irq_csi < 0) { +		dev_err(&pdev->dev, "Missing platform resources data\n"); +		err = -ENODEV; +		goto exit; +	} + +	pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL); +	if (!pcdev) { +		dev_err(&pdev->dev, "Could not allocate pcdev\n"); +		err = -ENOMEM; +		goto exit; +	} + +	pcdev->clk_csi = clk_get(&pdev->dev, NULL); +	if (IS_ERR(pcdev->clk_csi)) { +		err = PTR_ERR(pcdev->clk_csi); +		goto exit_kfree; +	} + +	dev_dbg(&pdev->dev, "Camera clock frequency: %ld\n", +			clk_get_rate(pcdev->clk_csi)); + +	/* Initialize DMA */ +#ifdef CONFIG_MACH_MX27 +	if (cpu_is_mx27()) { +		err = mx27_camera_dma_init(pdev, pcdev); +		if (err) +			goto exit_clk_put; +	} +#endif /* CONFIG_MACH_MX27 */ + +	pcdev->res_csi = res_csi; +	pcdev->pdata = pdev->dev.platform_data; +	if (pcdev->pdata) { +		long rate; + +		pcdev->platform_flags = pcdev->pdata->flags; + +		rate = clk_round_rate(pcdev->clk_csi, pcdev->pdata->clk * 2); +		if (rate <= 0) { +			err = -ENODEV; +			goto exit_dma_free; +		} +		err = clk_set_rate(pcdev->clk_csi, rate); +		if (err < 0) +			goto exit_dma_free; +	} + +	INIT_LIST_HEAD(&pcdev->capture); +	INIT_LIST_HEAD(&pcdev->active_bufs); +	spin_lock_init(&pcdev->lock); + +	/* +	 * Request the regions. +	 */ +	if (!request_mem_region(res_csi->start, resource_size(res_csi), +				MX2_CAM_DRV_NAME)) { +		err = -EBUSY; +		goto exit_dma_free; +	} + +	base_csi = ioremap(res_csi->start, resource_size(res_csi)); +	if (!base_csi) { +		err = -ENOMEM; +		goto exit_release; +	} +	pcdev->irq_csi = irq_csi; +	pcdev->base_csi = base_csi; +	pcdev->base_dma = res_csi->start; +	pcdev->dev = &pdev->dev; + +	err = request_irq(pcdev->irq_csi, mx2_cam_irq_handler, 0, +			MX2_CAM_DRV_NAME, pcdev); +	if (err) { +		dev_err(pcdev->dev, "Camera interrupt register failed \n"); +		goto exit_iounmap; +	} + +	if (cpu_is_mx27()) { +		/* EMMA support */ +		res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1); +		irq_emma = platform_get_irq(pdev, 1); + +		if (res_emma && irq_emma >= 0) { +			dev_info(&pdev->dev, "Using EMMA\n"); +			pcdev->use_emma = 1; +			pcdev->res_emma = res_emma; +			pcdev->irq_emma = irq_emma; +			if (mx27_camera_emma_init(pcdev)) +				goto exit_free_irq; +		} +	} + +	pcdev->soc_host.drv_name	= MX2_CAM_DRV_NAME, +	pcdev->soc_host.ops		= &mx2_soc_camera_host_ops, +	pcdev->soc_host.priv		= pcdev; +	pcdev->soc_host.v4l2_dev.dev	= &pdev->dev; +	pcdev->soc_host.nr		= pdev->id; +	err = soc_camera_host_register(&pcdev->soc_host); +	if (err) +		goto exit_free_emma; + +	return 0; + +exit_free_emma: +	if (mx27_camera_emma(pcdev)) { +		free_irq(pcdev->irq_emma, pcdev); +		clk_disable(pcdev->clk_emma); +		clk_put(pcdev->clk_emma); +		iounmap(pcdev->base_emma); +		release_mem_region(res_emma->start, resource_size(res_emma)); +	} +exit_free_irq: +	free_irq(pcdev->irq_csi, pcdev); +exit_iounmap: +	iounmap(base_csi); +exit_release: +	release_mem_region(res_csi->start, resource_size(res_csi)); +exit_dma_free: +#ifdef CONFIG_MACH_MX27 +	if (cpu_is_mx27()) +		imx_dma_free(pcdev->dma); +exit_clk_put: +	clk_put(pcdev->clk_csi); +#endif /* CONFIG_MACH_MX27 */ +exit_kfree: +	kfree(pcdev); +exit: +	return err; +} + +static int __devexit mx2_camera_remove(struct platform_device *pdev) +{ +	struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); +	struct mx2_camera_dev *pcdev = container_of(soc_host, +			struct mx2_camera_dev, soc_host); +	struct resource *res; + +	clk_put(pcdev->clk_csi); +#ifdef CONFIG_MACH_MX27 +	if (cpu_is_mx27()) +		imx_dma_free(pcdev->dma); +#endif /* CONFIG_MACH_MX27 */ +	free_irq(pcdev->irq_csi, pcdev); +	if (mx27_camera_emma(pcdev)) +		free_irq(pcdev->irq_emma, pcdev); + +	soc_camera_host_unregister(&pcdev->soc_host); + +	iounmap(pcdev->base_csi); + +	if (mx27_camera_emma(pcdev)) { +		clk_disable(pcdev->clk_emma); +		clk_put(pcdev->clk_emma); +		iounmap(pcdev->base_emma); +		res = pcdev->res_emma; +		release_mem_region(res->start, resource_size(res)); +	} + +	res = pcdev->res_csi; +	release_mem_region(res->start, resource_size(res)); + +	kfree(pcdev); + +	dev_info(&pdev->dev, "MX2 Camera driver unloaded\n"); + +	return 0; +} + +static struct platform_driver mx2_camera_driver = { +	.driver 	= { +		.name	= MX2_CAM_DRV_NAME, +	}, +	.remove		= __devexit_p(mx2_camera_remove), +}; + + +static int __init mx2_camera_init(void) +{ +	return platform_driver_probe(&mx2_camera_driver, &mx2_camera_probe); +} + +static void __exit mx2_camera_exit(void) +{ +	return platform_driver_unregister(&mx2_camera_driver); +} + +module_init(mx2_camera_init); +module_exit(mx2_camera_exit); + +MODULE_DESCRIPTION("i.MX27/i.MX25 SoC Camera Host driver"); +MODULE_AUTHOR("Sascha Hauer <sha@pengutronix.de>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/omap/Kconfig b/drivers/media/video/omap/Kconfig index 97c53949ca8..e63233fd2aa 100644 --- a/drivers/media/video/omap/Kconfig +++ b/drivers/media/video/omap/Kconfig @@ -1,8 +1,8 @@  config VIDEO_OMAP2_VOUT  	tristate "OMAP2/OMAP3 V4L2-Display driver" -	depends on ARCH_OMAP24XX || ARCH_OMAP34XX +	depends on ARCH_OMAP2 || ARCH_OMAP3  	select VIDEOBUF_GEN -	select VIDEOBUF_DMA_SG +	select VIDEOBUF_DMA_CONTIG  	select OMAP2_DSS  	select OMAP2_VRAM  	select OMAP2_VRFB diff --git a/drivers/media/video/omap/Makefile b/drivers/media/video/omap/Makefile index b8bab00ad01..b28788070ae 100644 --- a/drivers/media/video/omap/Makefile +++ b/drivers/media/video/omap/Makefile @@ -3,5 +3,5 @@  #  # OMAP2/3 Display driver -omap-vout-mod-objs := omap_vout.o omap_voutlib.o -obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout-mod.o +omap-vout-y := omap_vout.o omap_voutlib.o +obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout.o diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index e7db0554949..929073e792c 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -38,8 +38,9 @@  #include <linux/dma-mapping.h>  #include <linux/irq.h>  #include <linux/videodev2.h> +#include <linux/slab.h> -#include <media/videobuf-dma-sg.h> +#include <media/videobuf-dma-contig.h>  #include <media/v4l2-device.h>  #include <media/v4l2-ioctl.h> @@ -1053,9 +1054,9 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,  			    struct videobuf_buffer *vb,  			    enum v4l2_field field)  { +	dma_addr_t dmabuf;  	struct vid_vrfb_dma *tx;  	enum dss_rotation rotation; -	struct videobuf_dmabuf *dmabuf = NULL;  	struct omap_vout_device *vout = q->priv_data;  	u32 dest_frame_index = 0, src_element_index = 0;  	u32 dest_element_index = 0, src_frame_index = 0; @@ -1074,24 +1075,17 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,  	if (V4L2_MEMORY_USERPTR == vb->memory) {  		if (0 == vb->baddr)  			return -EINVAL; -		/* Virtual address */ -		/* priv points to struct videobuf_pci_sg_memory. But we went -		 * pointer to videobuf_dmabuf, which is member of -		 * videobuf_pci_sg_memory */ -		dmabuf = videobuf_to_dma(q->bufs[vb->i]); -		dmabuf->vmalloc = (void *) vb->baddr; -  		/* Physical address */ -		dmabuf->bus_addr = -			(dma_addr_t) omap_vout_uservirt_to_phys(vb->baddr); +		vout->queued_buf_addr[vb->i] = (u8 *) +			omap_vout_uservirt_to_phys(vb->baddr); +	} else { +		vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i];  	} -	if (!rotation_enabled(vout)) { -		dmabuf = videobuf_to_dma(q->bufs[vb->i]); -		vout->queued_buf_addr[vb->i] = (u8 *) dmabuf->bus_addr; +	if (!rotation_enabled(vout))  		return 0; -	} -	dmabuf = videobuf_to_dma(q->bufs[vb->i]); + +	dmabuf = vout->buf_phy_addr[vb->i];  	/* If rotation is enabled, copy input buffer into VRFB  	 * memory space using DMA. We are copying input buffer  	 * into VRFB memory space of desired angle and DSS will @@ -1120,7 +1114,7 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,  			tx->dev_id, 0x0);  	/* src_port required only for OMAP1 */  	omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, -			dmabuf->bus_addr, src_element_index, src_frame_index); +			dmabuf, src_element_index, src_frame_index);  	/*set dma source burst mode for VRFB */  	omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16);  	rotation = calc_rotation(vout); @@ -1211,7 +1205,6 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)  	void *pos;  	unsigned long start = vma->vm_start;  	unsigned long size = (vma->vm_end - vma->vm_start); -	struct videobuf_dmabuf *dmabuf = NULL;  	struct omap_vout_device *vout = file->private_data;  	struct videobuf_queue *q = &vout->vbq; @@ -1241,8 +1234,7 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)  	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);  	vma->vm_ops = &omap_vout_vm_ops;  	vma->vm_private_data = (void *) vout; -	dmabuf = videobuf_to_dma(q->bufs[i]); -	pos = dmabuf->vmalloc; +	pos = (void *)vout->buf_virt_addr[i];  	vma->vm_pgoff = virt_to_phys((void *)pos) >> PAGE_SHIFT;  	while (size > 0) {  		unsigned long pfn; @@ -1347,8 +1339,8 @@ static int omap_vout_open(struct file *file)  	video_vbq_ops.buf_queue = omap_vout_buffer_queue;  	spin_lock_init(&vout->vbq_lock); -	videobuf_queue_sg_init(q, &video_vbq_ops, NULL, &vout->vbq_lock, -			vout->type, V4L2_FIELD_NONE, +	videobuf_queue_dma_contig_init(q, &video_vbq_ops, q->dev, +			&vout->vbq_lock, vout->type, V4L2_FIELD_NONE,  			sizeof(struct videobuf_buffer), vout);  	v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__); @@ -1799,7 +1791,6 @@ static int vidioc_reqbufs(struct file *file, void *fh,  	unsigned int i, num_buffers = 0;  	struct omap_vout_device *vout = fh;  	struct videobuf_queue *q = &vout->vbq; -	struct videobuf_dmabuf *dmabuf = NULL;  	if ((req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) || (req->count < 0))  		return -EINVAL; @@ -1825,8 +1816,7 @@ static int vidioc_reqbufs(struct file *file, void *fh,  		num_buffers = (vout->vid == OMAP_VIDEO1) ?  			video1_numbuffers : video2_numbuffers;  		for (i = num_buffers; i < vout->buffer_allocated; i++) { -			dmabuf = videobuf_to_dma(q->bufs[i]); -			omap_vout_free_buffer((u32)dmabuf->vmalloc, +			omap_vout_free_buffer(vout->buf_virt_addr[i],  					vout->buffer_size);  			vout->buf_virt_addr[i] = 0;  			vout->buf_phy_addr[i] = 0; @@ -1855,12 +1845,7 @@ static int vidioc_reqbufs(struct file *file, void *fh,  		goto reqbuf_err;  	vout->buffer_allocated = req->count; -	for (i = 0; i < req->count; i++) { -		dmabuf = videobuf_to_dma(q->bufs[i]); -		dmabuf->vmalloc = (void *) vout->buf_virt_addr[i]; -		dmabuf->bus_addr = (dma_addr_t) vout->buf_phy_addr[i]; -		dmabuf->sglen = 1; -	} +  reqbuf_err:  	mutex_unlock(&vout->lock);  	return ret; @@ -2488,7 +2473,7 @@ static int omap_vout_remove(struct platform_device *pdev)  	for (k = 0; k < vid_dev->num_displays; k++) {  		if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED) -			vid_dev->displays[k]->disable(vid_dev->displays[k]); +			vid_dev->displays[k]->driver->disable(vid_dev->displays[k]);  		omap_dss_put_device(vid_dev->displays[k]);  	} @@ -2545,7 +2530,9 @@ static int __init omap_vout_probe(struct platform_device *pdev)  			def_display = NULL;  		}  		if (def_display) { -			ret = def_display->enable(def_display); +			struct omap_dss_driver *dssdrv = def_display->driver; + +			ret = dssdrv->enable(def_display);  			if (ret) {  				/* Here we are not considering a error  				 *  as display may be enabled by frame @@ -2559,21 +2546,21 @@ static int __init omap_vout_probe(struct platform_device *pdev)  			if (def_display->caps &  					OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {  #ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE -				if (def_display->enable_te) -					def_display->enable_te(def_display, 1); -				if (def_display->set_update_mode) -					def_display->set_update_mode(def_display, +				if (dssdrv->enable_te) +					dssdrv->enable_te(def_display, 1); +				if (dssdrv->set_update_mode) +					dssdrv->set_update_mode(def_display,  							OMAP_DSS_UPDATE_AUTO);  #else	/* MANUAL_UPDATE */ -				if (def_display->enable_te) -					def_display->enable_te(def_display, 0); -				if (def_display->set_update_mode) -					def_display->set_update_mode(def_display, +				if (dssdrv->enable_te) +					dssdrv->enable_te(def_display, 0); +				if (dssdrv->set_update_mode) +					dssdrv->set_update_mode(def_display,  							OMAP_DSS_UPDATE_MANUAL);  #endif  			} else { -				if (def_display->set_update_mode) -					def_display->set_update_mode(def_display, +				if (dssdrv->set_update_mode) +					dssdrv->set_update_mode(def_display,  							OMAP_DSS_UPDATE_AUTO);  			}  		} @@ -2592,8 +2579,8 @@ static int __init omap_vout_probe(struct platform_device *pdev)  	for (i = 0; i < vid_dev->num_displays; i++) {  		struct omap_dss_device *display = vid_dev->displays[i]; -		if (display->update) -			display->update(display, 0, 0, +		if (display->driver->update) +			display->driver->update(display, 0, 0,  					display->panel.timings.x_res,  					display->panel.timings.y_res);  	} @@ -2608,8 +2595,8 @@ probe_err1:  		if (ovl->manager && ovl->manager->device)  			def_display = ovl->manager->device; -		if (def_display) -			def_display->disable(def_display); +		if (def_display && def_display->driver) +			def_display->driver->disable(def_display);  	}  probe_err0:  	kfree(vid_dev); diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 0a877497b93..07fabdd9b46 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -267,6 +267,21 @@ hauppauge_tuner[] =  	{ TUNER_ABSENT,                 "Xceive XC4000"},  	{ TUNER_ABSENT,                 "Dibcom 7070"},  	{ TUNER_PHILIPS_TDA8290,        "NXP 18271C2"}, +	{ TUNER_ABSENT,			"unknown"}, +	{ TUNER_ABSENT,			"unknown"}, +	{ TUNER_ABSENT,			"unknown"}, +	{ TUNER_ABSENT,			"unknown"}, +	/* 160-169 */ +	{ TUNER_ABSENT,			"unknown"}, +	{ TUNER_ABSENT,			"unknown"}, +	{ TUNER_ABSENT,			"unknown"}, +	{ TUNER_ABSENT,			"unknown"}, +	{ TUNER_ABSENT,			"unknown"}, +	{ TUNER_ABSENT,			"unknown"}, +	{ TUNER_ABSENT,			"unknown"}, +	{ TUNER_ABSENT,			"unknown"}, +	{ TUNER_PHILIPS_FQ1236_MK5,	"TCL M30WTP-4N-E"}, +	{ TUNER_ABSENT,			"unknown"},  };  /* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index aa0720af07a..27a79f087b1 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -122,8 +122,8 @@ static struct uvc_control_info uvc_ctrls[] = {  		.selector	= UVC_PU_POWER_LINE_FREQUENCY_CONTROL,  		.index		= 10,  		.size		= 1, -		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE -				| UVC_CONTROL_RESTORE, +		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR +				| UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,  	},  	{  		.entity		= UVC_GUID_UVC_PROCESSING, diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 26386a92f5a..9b089dfb173 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -353,6 +353,16 @@ config VMWARE_BALLOON  	  To compile this driver as a module, choose M here: the  	  module will be called vmware_balloon. +config ARM_CHARLCD +	bool "ARM Ltd. Character LCD Driver" +	depends on PLAT_VERSATILE +	help +	  This is a driver for the character LCD found on the ARM Ltd. +	  Versatile and RealView Platform Baseboards. It doesn't do +	  very much more than display the text "ARM Linux" on the first +	  line and the Linux version on the second line, but that's +	  still useful. +  source "drivers/misc/c2port/Kconfig"  source "drivers/misc/eeprom/Kconfig"  source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 6ed06a19474..67552d6e932 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -31,3 +31,4 @@ obj-$(CONFIG_IWMC3200TOP)      += iwmc3200top/  obj-y				+= eeprom/  obj-y				+= cb710/  obj-$(CONFIG_VMWARE_BALLOON)	+= vmware_balloon.o +obj-$(CONFIG_ARM_CHARLCD)	+= arm-charlcd.o diff --git a/drivers/misc/arm-charlcd.c b/drivers/misc/arm-charlcd.c new file mode 100644 index 00000000000..9e3879ef58f --- /dev/null +++ b/drivers/misc/arm-charlcd.c @@ -0,0 +1,396 @@ +/* + * Driver for the on-board character LCD found on some ARM reference boards + * This is basically an Hitachi HD44780 LCD with a custom IP block to drive it + * http://en.wikipedia.org/wiki/HD44780_Character_LCD + * Currently it will just display the text "ARM Linux" and the linux version + * + * License terms: GNU General Public License (GPL) version 2 + * Author: Linus Walleij <triad@df.lth.se> + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/completion.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/workqueue.h> +#include <generated/utsrelease.h> + +#define DRIVERNAME "arm-charlcd" +#define CHARLCD_TIMEOUT (msecs_to_jiffies(1000)) + +/* Offsets to registers */ +#define CHAR_COM	0x00U +#define CHAR_DAT	0x04U +#define CHAR_RD		0x08U +#define CHAR_RAW	0x0CU +#define CHAR_MASK	0x10U +#define CHAR_STAT	0x14U + +#define CHAR_RAW_CLEAR	0x00000000U +#define CHAR_RAW_VALID	0x00000100U + +/* Hitachi HD44780 display commands */ +#define HD_CLEAR			0x01U +#define HD_HOME				0x02U +#define HD_ENTRYMODE			0x04U +#define HD_ENTRYMODE_INCREMENT		0x02U +#define HD_ENTRYMODE_SHIFT		0x01U +#define HD_DISPCTRL			0x08U +#define HD_DISPCTRL_ON			0x04U +#define HD_DISPCTRL_CURSOR_ON		0x02U +#define HD_DISPCTRL_CURSOR_BLINK	0x01U +#define HD_CRSR_SHIFT			0x10U +#define HD_CRSR_SHIFT_DISPLAY		0x08U +#define HD_CRSR_SHIFT_DISPLAY_RIGHT	0x04U +#define HD_FUNCSET			0x20U +#define HD_FUNCSET_8BIT			0x10U +#define HD_FUNCSET_2_LINES		0x08U +#define HD_FUNCSET_FONT_5X10		0x04U +#define HD_SET_CGRAM			0x40U +#define HD_SET_DDRAM			0x80U +#define HD_BUSY_FLAG			0x80U + +/** + * @dev: a pointer back to containing device + * @phybase: the offset to the controller in physical memory + * @physize: the size of the physical page + * @virtbase: the offset to the controller in virtual memory + * @irq: reserved interrupt number + * @complete: completion structure for the last LCD command + */ +struct charlcd { +	struct device *dev; +	u32 phybase; +	u32 physize; +	void __iomem *virtbase; +	int irq; +	struct completion complete; +	struct delayed_work init_work; +}; + +static irqreturn_t charlcd_interrupt(int irq, void *data) +{ +	struct charlcd *lcd = data; +	u8 status; + +	status = readl(lcd->virtbase + CHAR_STAT) & 0x01; +	/* Clear IRQ */ +	writel(CHAR_RAW_CLEAR, lcd->virtbase + CHAR_RAW); +	if (status) +		complete(&lcd->complete); +	else +		dev_info(lcd->dev, "Spurious IRQ (%02x)\n", status); +	return IRQ_HANDLED; +} + + +static void charlcd_wait_complete_irq(struct charlcd *lcd) +{ +	int ret; + +	ret = wait_for_completion_interruptible_timeout(&lcd->complete, +							CHARLCD_TIMEOUT); +	/* Disable IRQ after completion */ +	writel(0x00, lcd->virtbase + CHAR_MASK); + +	if (ret < 0) { +		dev_err(lcd->dev, +			"wait_for_completion_interruptible_timeout() " +			"returned %d waiting for ready\n", ret); +		return; +	} + +	if (ret == 0) { +		dev_err(lcd->dev, "charlcd controller timed out " +			"waiting for ready\n"); +		return; +	} +} + +static u8 charlcd_4bit_read_char(struct charlcd *lcd) +{ +	u8 data; +	u32 val; +	int i; + +	/* If we can, use an IRQ to wait for the data, else poll */ +	if (lcd->irq >= 0) +		charlcd_wait_complete_irq(lcd); +	else { +		i = 0; +		val = 0; +		while (!(val & CHAR_RAW_VALID) && i < 10) { +			udelay(100); +			val = readl(lcd->virtbase + CHAR_RAW); +			i++; +		} + +		writel(CHAR_RAW_CLEAR, lcd->virtbase + CHAR_RAW); +	} +	msleep(1); + +	/* Read the 4 high bits of the data */ +	data = readl(lcd->virtbase + CHAR_RD) & 0xf0; + +	/* +	 * The second read for the low bits does not trigger an IRQ +	 * so in this case we have to poll for the 4 lower bits +	 */ +	i = 0; +	val = 0; +	while (!(val & CHAR_RAW_VALID) && i < 10) { +		udelay(100); +		val = readl(lcd->virtbase + CHAR_RAW); +		i++; +	} +	writel(CHAR_RAW_CLEAR, lcd->virtbase + CHAR_RAW); +	msleep(1); + +	/* Read the 4 low bits of the data */ +	data |= (readl(lcd->virtbase + CHAR_RD) >> 4) & 0x0f; + +	return data; +} + +static bool charlcd_4bit_read_bf(struct charlcd *lcd) +{ +	if (lcd->irq >= 0) { +		/* +		 * If we'll use IRQs to wait for the busyflag, clear any +		 * pending flag and enable IRQ +		 */ +		writel(CHAR_RAW_CLEAR, lcd->virtbase + CHAR_RAW); +		init_completion(&lcd->complete); +		writel(0x01, lcd->virtbase + CHAR_MASK); +	} +	readl(lcd->virtbase + CHAR_COM); +	return charlcd_4bit_read_char(lcd) & HD_BUSY_FLAG ? true : false; +} + +static void charlcd_4bit_wait_busy(struct charlcd *lcd) +{ +	int retries = 50; + +	udelay(100); +	while (charlcd_4bit_read_bf(lcd) && retries) +		retries--; +	if (!retries) +		dev_err(lcd->dev, "timeout waiting for busyflag\n"); +} + +static void charlcd_4bit_command(struct charlcd *lcd, u8 cmd) +{ +	u32 cmdlo = (cmd << 4) & 0xf0; +	u32 cmdhi = (cmd & 0xf0); + +	writel(cmdhi, lcd->virtbase + CHAR_COM); +	udelay(10); +	writel(cmdlo, lcd->virtbase + CHAR_COM); +	charlcd_4bit_wait_busy(lcd); +} + +static void charlcd_4bit_char(struct charlcd *lcd, u8 ch) +{ +	u32 chlo = (ch << 4) & 0xf0; +	u32 chhi = (ch & 0xf0); + +	writel(chhi, lcd->virtbase + CHAR_DAT); +	udelay(10); +	writel(chlo, lcd->virtbase + CHAR_DAT); +	charlcd_4bit_wait_busy(lcd); +} + +static void charlcd_4bit_print(struct charlcd *lcd, int line, const char *str) +{ +	u8 offset; +	int i; + +	/* +	 * We support line 0, 1 +	 * Line 1 runs from 0x00..0x27 +	 * Line 2 runs from 0x28..0x4f +	 */ +	if (line == 0) +		offset = 0; +	else if (line == 1) +		offset = 0x28; +	else +		return; + +	/* Set offset */ +	charlcd_4bit_command(lcd, HD_SET_DDRAM | offset); + +	/* Send string */ +	for (i = 0; i < strlen(str) && i < 0x28; i++) +		charlcd_4bit_char(lcd, str[i]); +} + +static void charlcd_4bit_init(struct charlcd *lcd) +{ +	/* These commands cannot be checked with the busy flag */ +	writel(HD_FUNCSET | HD_FUNCSET_8BIT, lcd->virtbase + CHAR_COM); +	msleep(5); +	writel(HD_FUNCSET | HD_FUNCSET_8BIT, lcd->virtbase + CHAR_COM); +	udelay(100); +	writel(HD_FUNCSET | HD_FUNCSET_8BIT, lcd->virtbase + CHAR_COM); +	udelay(100); +	/* Go to 4bit mode */ +	writel(HD_FUNCSET, lcd->virtbase + CHAR_COM); +	udelay(100); +	/* +	 * 4bit mode, 2 lines, 5x8 font, after this the number of lines +	 * and the font cannot be changed until the next initialization sequence +	 */ +	charlcd_4bit_command(lcd, HD_FUNCSET | HD_FUNCSET_2_LINES); +	charlcd_4bit_command(lcd, HD_DISPCTRL | HD_DISPCTRL_ON); +	charlcd_4bit_command(lcd, HD_ENTRYMODE | HD_ENTRYMODE_INCREMENT); +	charlcd_4bit_command(lcd, HD_CLEAR); +	charlcd_4bit_command(lcd, HD_HOME); +	/* Put something useful in the display */ +	charlcd_4bit_print(lcd, 0, "ARM Linux"); +	charlcd_4bit_print(lcd, 1, UTS_RELEASE); +} + +static void charlcd_init_work(struct work_struct *work) +{ +	struct charlcd *lcd = +		container_of(work, struct charlcd, init_work.work); + +	charlcd_4bit_init(lcd); +} + +static int __init charlcd_probe(struct platform_device *pdev) +{ +	int ret; +	struct charlcd *lcd; +	struct resource *res; + +	lcd = kzalloc(sizeof(struct charlcd), GFP_KERNEL); +	if (!lcd) +		return -ENOMEM; + +	lcd->dev = &pdev->dev; + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!res) { +		ret = -ENOENT; +		goto out_no_resource; +	} +	lcd->phybase = res->start; +	lcd->physize = resource_size(res); + +	if (request_mem_region(lcd->phybase, lcd->physize, +			       DRIVERNAME) == NULL) { +		ret = -EBUSY; +		goto out_no_memregion; +	} + +	lcd->virtbase = ioremap(lcd->phybase, lcd->physize); +	if (!lcd->virtbase) { +		ret = -ENOMEM; +		goto out_no_remap; +	} + +	lcd->irq = platform_get_irq(pdev, 0); +	/* If no IRQ is supplied, we'll survive without it */ +	if (lcd->irq >= 0) { +		if (request_irq(lcd->irq, charlcd_interrupt, IRQF_DISABLED, +				DRIVERNAME, lcd)) { +			ret = -EIO; +			goto out_no_irq; +		} +	} + +	platform_set_drvdata(pdev, lcd); + +	/* +	 * Initialize the display in a delayed work, because +	 * it is VERY slow and would slow down the boot of the system. +	 */ +	INIT_DELAYED_WORK(&lcd->init_work, charlcd_init_work); +	schedule_delayed_work(&lcd->init_work, 0); + +	dev_info(&pdev->dev, "initalized ARM character LCD at %08x\n", +		lcd->phybase); + +	return 0; + +out_no_irq: +	iounmap(lcd->virtbase); +out_no_remap: +	platform_set_drvdata(pdev, NULL); +out_no_memregion: +	release_mem_region(lcd->phybase, SZ_4K); +out_no_resource: +	kfree(lcd); +	return ret; +} + +static int __exit charlcd_remove(struct platform_device *pdev) +{ +	struct charlcd *lcd = platform_get_drvdata(pdev); + +	if (lcd) { +		free_irq(lcd->irq, lcd); +		iounmap(lcd->virtbase); +		release_mem_region(lcd->phybase, lcd->physize); +		platform_set_drvdata(pdev, NULL); +		kfree(lcd); +	} + +	return 0; +} + +static int charlcd_suspend(struct device *dev) +{ +	struct platform_device *pdev = to_platform_device(dev); +	struct charlcd *lcd = platform_get_drvdata(pdev); + +	/* Power the display off */ +	charlcd_4bit_command(lcd, HD_DISPCTRL); +	return 0; +} + +static int charlcd_resume(struct device *dev) +{ +	struct platform_device *pdev = to_platform_device(dev); +	struct charlcd *lcd = platform_get_drvdata(pdev); + +	/* Turn the display back on */ +	charlcd_4bit_command(lcd, HD_DISPCTRL | HD_DISPCTRL_ON); +	return 0; +} + +static const struct dev_pm_ops charlcd_pm_ops = { +	.suspend = charlcd_suspend, +	.resume = charlcd_resume, +}; + +static struct platform_driver charlcd_driver = { +	.driver = { +		.name = DRIVERNAME, +		.owner = THIS_MODULE, +		.pm = &charlcd_pm_ops, +	}, +	.remove = __exit_p(charlcd_remove), +}; + +static int __init charlcd_init(void) +{ +	return platform_driver_probe(&charlcd_driver, charlcd_probe); +} + +static void __exit charlcd_exit(void) +{ +	platform_driver_unregister(&charlcd_driver); +} + +module_init(charlcd_init); +module_exit(charlcd_exit); + +MODULE_AUTHOR("Linus Walleij <triad@df.lth.se>"); +MODULE_DESCRIPTION("ARM Character LCD Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c index 9bec24db4d4..2d44b330010 100644 --- a/drivers/misc/cs5535-mfgpt.c +++ b/drivers/misc/cs5535-mfgpt.c @@ -366,6 +366,6 @@ static int __init cs5535_mfgpt_init(void)  module_init(cs5535_mfgpt_init); -MODULE_AUTHOR("Andres Salomon <dilinger@collabora.co.uk>"); +MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");  MODULE_DESCRIPTION("CS5535/CS5536 MFGPT timer driver");  MODULE_LICENSE("GPL"); diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 4917af96bae..840b301b567 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -26,7 +26,6 @@  #include <linux/amba/mmci.h>  #include <linux/regulator/consumer.h> -#include <asm/cacheflush.h>  #include <asm/div64.h>  #include <asm/io.h>  #include <asm/sizes.h> @@ -37,12 +36,39 @@  static unsigned int fmax = 515633; +/** + * struct variant_data - MMCI variant-specific quirks + * @clkreg: default value for MCICLOCK register + * @clkreg_enable: enable value for MMCICLOCK register + * @datalength_bits: number of bits in the MMCIDATALENGTH register + */ +struct variant_data { +	unsigned int		clkreg; +	unsigned int		clkreg_enable; +	unsigned int		datalength_bits; +}; + +static struct variant_data variant_arm = { +	.datalength_bits	= 16, +}; + +static struct variant_data variant_u300 = { +	.clkreg_enable		= 1 << 13, /* HWFCEN */ +	.datalength_bits	= 16, +}; + +static struct variant_data variant_ux500 = { +	.clkreg			= MCI_CLK_ENABLE, +	.clkreg_enable		= 1 << 14, /* HWFCEN */ +	.datalength_bits	= 24, +};  /*   * This must be called with host->lock held   */  static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired)  { -	u32 clk = 0; +	struct variant_data *variant = host->variant; +	u32 clk = variant->clkreg;  	if (desired) {  		if (desired >= host->mclk) { @@ -54,8 +80,8 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired)  				clk = 255;  			host->cclk = host->mclk / (2 * (clk + 1));  		} -		if (host->hw_designer == AMBA_VENDOR_ST) -			clk |= MCI_ST_FCEN; /* Bug fix in ST IP block */ + +		clk |= variant->clkreg_enable;  		clk |= MCI_CLK_ENABLE;  		/* This hasn't proven to be worthwhile */  		/* clk |= MCI_CLK_PWRSAVE; */ @@ -98,6 +124,18 @@ static void mmci_stop_data(struct mmci_host *host)  	host->data = NULL;  } +static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) +{ +	unsigned int flags = SG_MITER_ATOMIC; + +	if (data->flags & MMC_DATA_READ) +		flags |= SG_MITER_TO_SG; +	else +		flags |= SG_MITER_FROM_SG; + +	sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); +} +  static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)  {  	unsigned int datactrl, timeout, irqmask; @@ -109,7 +147,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)  		data->blksz, data->blocks, data->flags);  	host->data = data; -	host->size = data->blksz; +	host->size = data->blksz * data->blocks;  	host->data_xfered = 0;  	mmci_init_sg(host, data); @@ -210,8 +248,17 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,  		 * We hit an error condition.  Ensure that any data  		 * partially written to a page is properly coherent.  		 */ -		if (host->sg_len && data->flags & MMC_DATA_READ) -			flush_dcache_page(sg_page(host->sg_ptr)); +		if (data->flags & MMC_DATA_READ) { +			struct sg_mapping_iter *sg_miter = &host->sg_miter; +			unsigned long flags; + +			local_irq_save(flags); +			if (sg_miter_next(sg_miter)) { +				flush_dcache_page(sg_miter->page); +				sg_miter_stop(sg_miter); +			} +			local_irq_restore(flags); +		}  	}  	if (status & MCI_DATAEND) {  		mmci_stop_data(host); @@ -314,15 +361,18 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem  static irqreturn_t mmci_pio_irq(int irq, void *dev_id)  {  	struct mmci_host *host = dev_id; +	struct sg_mapping_iter *sg_miter = &host->sg_miter;  	void __iomem *base = host->base; +	unsigned long flags;  	u32 status;  	status = readl(base + MMCISTATUS);  	dev_dbg(mmc_dev(host->mmc), "irq1 (pio) %08x\n", status); +	local_irq_save(flags); +  	do { -		unsigned long flags;  		unsigned int remain, len;  		char *buffer; @@ -336,11 +386,11 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)  		if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL)))  			break; -		/* -		 * Map the current scatter buffer. -		 */ -		buffer = mmci_kmap_atomic(host, &flags) + host->sg_off; -		remain = host->sg_ptr->length - host->sg_off; +		if (!sg_miter_next(sg_miter)) +			break; + +		buffer = sg_miter->addr; +		remain = sg_miter->length;  		len = 0;  		if (status & MCI_RXACTIVE) @@ -348,31 +398,24 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)  		if (status & MCI_TXACTIVE)  			len = mmci_pio_write(host, buffer, remain, status); -		/* -		 * Unmap the buffer. -		 */ -		mmci_kunmap_atomic(host, buffer, &flags); +		sg_miter->consumed = len; -		host->sg_off += len;  		host->size -= len;  		remain -= len;  		if (remain)  			break; -		/* -		 * If we were reading, and we have completed this -		 * page, ensure that the data cache is coherent. -		 */  		if (status & MCI_RXACTIVE) -			flush_dcache_page(sg_page(host->sg_ptr)); - -		if (!mmci_next_sg(host)) -			break; +			flush_dcache_page(sg_miter->page);  		status = readl(base + MMCISTATUS);  	} while (1); +	sg_miter_stop(sg_miter); + +	local_irq_restore(flags); +  	/*  	 * If we're nearing the end of the read, switch to  	 * "any data available" mode. @@ -477,16 +520,9 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  			/* This implicitly enables the regulator */  			mmc_regulator_set_ocr(host->vcc, ios->vdd);  #endif -		/* -		 * The translate_vdd function is not used if you have -		 * an external regulator, or your design is really weird. -		 * Using it would mean sending in power control BOTH using -		 * a regulator AND the 4 MMCIPWR bits. If we don't have -		 * a regulator, we might have some other platform specific -		 * power control behind this translate function. -		 */ -		if (!host->vcc && host->plat->translate_vdd) -			pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd); +		if (host->plat->vdd_handler) +			pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd, +						       ios->power_mode);  		/* The ST version does not have this, fall through to POWER_ON */  		if (host->hw_designer != AMBA_VENDOR_ST) {  			pwr |= MCI_PWR_UP; @@ -539,9 +575,13 @@ static int mmci_get_cd(struct mmc_host *mmc)  	if (host->gpio_cd == -ENOSYS)  		status = host->plat->status(mmc_dev(host->mmc));  	else -		status = gpio_get_value(host->gpio_cd); +		status = !gpio_get_value(host->gpio_cd); -	return !status; +	/* +	 * Use positive logic throughout - status is zero for no card, +	 * non-zero for card inserted. +	 */ +	return status;  }  static const struct mmc_host_ops mmci_ops = { @@ -551,21 +591,10 @@ static const struct mmc_host_ops mmci_ops = {  	.get_cd		= mmci_get_cd,  }; -static void mmci_check_status(unsigned long data) -{ -	struct mmci_host *host = (struct mmci_host *)data; -	unsigned int status = mmci_get_cd(host->mmc); - -	if (status ^ host->oldstat) -		mmc_detect_change(host->mmc, 0); - -	host->oldstat = status; -	mod_timer(&host->timer, jiffies + HZ); -} -  static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)  {  	struct mmci_platform_data *plat = dev->dev.platform_data; +	struct variant_data *variant = id->data;  	struct mmci_host *host;  	struct mmc_host *mmc;  	int ret; @@ -609,6 +638,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)  		goto clk_free;  	host->plat = plat; +	host->variant = variant;  	host->mclk = clk_get_rate(host->clk);  	/*  	 * According to the spec, mclk is max 100 MHz, @@ -669,6 +699,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)  	if (host->vcc == NULL)  		mmc->ocr_avail = plat->ocr_mask;  	mmc->caps = plat->capabilities; +	mmc->caps |= MMC_CAP_NEEDS_POLL;  	/*  	 * We can do SGIO @@ -677,10 +708,11 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)  	mmc->max_phys_segs = NR_SG;  	/* -	 * Since we only have a 16-bit data length register, we must -	 * ensure that we don't exceed 2^16-1 bytes in a single request. +	 * Since only a certain number of bits are valid in the data length +	 * register, we must ensure that we don't exceed 2^num-1 bytes in a +	 * single request.  	 */ -	mmc->max_req_size = 65535; +	mmc->max_req_size = (1 << variant->datalength_bits) - 1;  	/*  	 * Set the maximum segment size.  Since we aren't doing DMA @@ -734,7 +766,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)  	writel(MCI_IRQENABLE, host->base + MMCIMASK0);  	amba_set_drvdata(dev, mmc); -	host->oldstat = mmci_get_cd(host->mmc);  	mmc_add_host(mmc); @@ -742,12 +773,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)  		mmc_hostname(mmc), amba_rev(dev), amba_config(dev),  		(unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]); -	init_timer(&host->timer); -	host->timer.data = (unsigned long)host; -	host->timer.function = mmci_check_status; -	host->timer.expires = jiffies + HZ; -	add_timer(&host->timer); -  	return 0;   irq0_free: @@ -781,8 +806,6 @@ static int __devexit mmci_remove(struct amba_device *dev)  	if (mmc) {  		struct mmci_host *host = mmc_priv(mmc); -		del_timer_sync(&host->timer); -  		mmc_remove_host(mmc);  		writel(0, host->base + MMCIMASK0); @@ -856,19 +879,28 @@ static struct amba_id mmci_ids[] = {  	{  		.id	= 0x00041180,  		.mask	= 0x000fffff, +		.data	= &variant_arm,  	},  	{  		.id	= 0x00041181,  		.mask	= 0x000fffff, +		.data	= &variant_arm,  	},  	/* ST Micro variants */  	{  		.id     = 0x00180180,  		.mask   = 0x00ffffff, +		.data	= &variant_u300,  	},  	{  		.id     = 0x00280180,  		.mask   = 0x00ffffff, +		.data	= &variant_u300, +	}, +	{ +		.id     = 0x00480180, +		.mask   = 0x00ffffff, +		.data	= &variant_ux500,  	},  	{ 0, 0 },  }; diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index d77062e5e3a..68970cfb81e 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -28,8 +28,6 @@  #define MCI_4BIT_BUS		(1 << 11)  /* 8bit wide buses supported in ST Micro versions */  #define MCI_ST_8BIT_BUS		(1 << 12) -/* HW flow control on the ST Micro version */ -#define MCI_ST_FCEN		(1 << 13)  #define MMCIARGUMENT		0x008  #define MMCICOMMAND		0x00c @@ -145,6 +143,7 @@  #define NR_SG		16  struct clk; +struct variant_data;  struct mmci_host {  	void __iomem		*base; @@ -164,6 +163,7 @@ struct mmci_host {  	unsigned int		cclk;  	u32			pwr;  	struct mmci_platform_data *plat; +	struct variant_data	*variant;  	u8			hw_designer;  	u8			hw_revision:4; @@ -171,42 +171,9 @@ struct mmci_host {  	struct timer_list	timer;  	unsigned int		oldstat; -	unsigned int		sg_len; -  	/* pio stuff */ -	struct scatterlist	*sg_ptr; -	unsigned int		sg_off; +	struct sg_mapping_iter	sg_miter;  	unsigned int		size;  	struct regulator	*vcc;  }; -static inline void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) -{ -	/* -	 * Ideally, we want the higher levels to pass us a scatter list. -	 */ -	host->sg_len = data->sg_len; -	host->sg_ptr = data->sg; -	host->sg_off = 0; -} - -static inline int mmci_next_sg(struct mmci_host *host) -{ -	host->sg_ptr++; -	host->sg_off = 0; -	return --host->sg_len; -} - -static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flags) -{ -	struct scatterlist *sg = host->sg_ptr; - -	local_irq_save(*flags); -	return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; -} - -static inline void mmci_kunmap_atomic(struct mmci_host *host, void *buffer, unsigned long *flags) -{ -	kunmap_atomic(buffer, KM_BIO_SRC_IRQ); -	local_irq_restore(*flags); -} diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index d9d4a72e0ec..350f78e8624 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -119,6 +119,7 @@ struct mxcmci_host {  	int			detect_irq;  	int			dma;  	int			do_dma; +	int			default_irq_mask;  	int			use_sdio;  	unsigned int		power_mode;  	struct imxmmc_platform_data *pdata; @@ -228,7 +229,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)  static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,  		unsigned int cmdat)  { -	u32 int_cntr; +	u32 int_cntr = host->default_irq_mask;  	unsigned long flags;  	WARN_ON(host->cmd != NULL); @@ -275,7 +276,7 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,  static void mxcmci_finish_request(struct mxcmci_host *host,  		struct mmc_request *req)  { -	u32 int_cntr = 0; +	u32 int_cntr = host->default_irq_mask;  	unsigned long flags;  	spin_lock_irqsave(&host->lock, flags); @@ -585,6 +586,9 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)  		  (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))  		mxcmci_data_done(host, stat);  #endif +	if (host->default_irq_mask && +		  (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL))) +		mmc_detect_change(host->mmc, msecs_to_jiffies(200));  	return IRQ_HANDLED;  } @@ -809,6 +813,12 @@ static int mxcmci_probe(struct platform_device *pdev)  	else  		mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; +	if (host->pdata && host->pdata->dat3_card_detect) +		host->default_irq_mask = +			INT_CARD_INSERTION_EN | INT_CARD_REMOVAL_EN; +	else +		host->default_irq_mask = 0; +  	host->res = r;  	host->irq = irq; @@ -835,7 +845,7 @@ static int mxcmci_probe(struct platform_device *pdev)  	/* recommended in data sheet */  	writew(0x2db4, host->base + MMC_REG_READ_TO); -	writel(0, host->base + MMC_REG_INT_CNTR); +	writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR);  #ifdef HAS_DMA  	host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW); @@ -926,43 +936,47 @@ static int mxcmci_remove(struct platform_device *pdev)  }  #ifdef CONFIG_PM -static int mxcmci_suspend(struct platform_device *dev, pm_message_t state) +static int mxcmci_suspend(struct device *dev)  { -	struct mmc_host *mmc = platform_get_drvdata(dev); +	struct mmc_host *mmc = dev_get_drvdata(dev); +	struct mxcmci_host *host = mmc_priv(mmc);  	int ret = 0;  	if (mmc)  		ret = mmc_suspend_host(mmc); +	clk_disable(host->clk);  	return ret;  } -static int mxcmci_resume(struct platform_device *dev) +static int mxcmci_resume(struct device *dev)  { -	struct mmc_host *mmc = platform_get_drvdata(dev); -	struct mxcmci_host *host; +	struct mmc_host *mmc = dev_get_drvdata(dev); +	struct mxcmci_host *host = mmc_priv(mmc);  	int ret = 0; -	if (mmc) { -		host = mmc_priv(mmc); +	clk_enable(host->clk); +	if (mmc)  		ret = mmc_resume_host(mmc); -	}  	return ret;  } -#else -#define mxcmci_suspend  NULL -#define mxcmci_resume   NULL -#endif /* CONFIG_PM */ + +static const struct dev_pm_ops mxcmci_pm_ops = { +	.suspend	= mxcmci_suspend, +	.resume		= mxcmci_resume, +}; +#endif  static struct platform_driver mxcmci_driver = {  	.probe		= mxcmci_probe,  	.remove		= mxcmci_remove, -	.suspend	= mxcmci_suspend, -	.resume		= mxcmci_resume,  	.driver		= {  		.name		= DRIVER_NAME,  		.owner		= THIS_MODULE, +#ifdef CONFIG_PM +		.pm	= &mxcmci_pm_ops, +#endif  	}  }; diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index af217924a76..ad30f074ee1 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -365,6 +365,26 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)  static int __devexit sdhci_s3c_remove(struct platform_device *pdev)  { +	struct sdhci_host *host =  platform_get_drvdata(pdev); +	struct sdhci_s3c *sc = sdhci_priv(host); +	int ptr; + +	sdhci_remove_host(host, 1); + +	for (ptr = 0; ptr < 3; ptr++) { +		clk_disable(sc->clk_bus[ptr]); +		clk_put(sc->clk_bus[ptr]); +	} +	clk_disable(sc->clk_io); +	clk_put(sc->clk_io); + +	iounmap(host->ioaddr); +	release_resource(sc->ioarea); +	kfree(sc->ioarea); + +	sdhci_free_host(host); +	platform_set_drvdata(pdev, NULL); +  	return 0;  } diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 82e94389824..0d76b169482 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -623,8 +623,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,  		else  			host->buf_start = column + mtd->writesize; -		if (mtd->writesize > 512) -			command = NAND_CMD_READ0; /* only READ0 is valid */ +		command = NAND_CMD_READ0; /* only READ0 is valid */  		send_cmd(host, command, false);  		mxc_do_addr_cycle(mtd, column, page_addr); @@ -639,31 +638,11 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,  		break;  	case NAND_CMD_SEQIN: -		if (column >= mtd->writesize) { -			/* -			 * FIXME: before send SEQIN command for write OOB, -			 * We must read one page out. -			 * For K9F1GXX has no READ1 command to set current HW -			 * pointer to spare area, we must write the whole page -			 * including OOB together. -			 */ -			if (mtd->writesize > 512) -				/* call ourself to read a page */ -				mxc_nand_command(mtd, NAND_CMD_READ0, 0, -						page_addr); - -			host->buf_start = column; - -			/* Set program pointer to spare region */ -			if (mtd->writesize == 512) -				send_cmd(host, NAND_CMD_READOOB, false); -		} else { -			host->buf_start = column; +		if (column >= mtd->writesize) +			/* call ourself to read a page */ +			mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr); -			/* Set program pointer to page start */ -			if (mtd->writesize == 512) -				send_cmd(host, NAND_CMD_READ0, false); -		} +		host->buf_start = column;  		send_cmd(host, command, false);  		mxc_do_addr_cycle(mtd, column, page_addr); @@ -853,6 +832,8 @@ static int __init mxcnd_probe(struct platform_device *pdev)  	    parse_mtd_partitions(mtd, part_probes, &host->parts, 0);  	if (nr_parts > 0)  		add_mtd_partitions(mtd, host->parts, nr_parts); +	else if (pdata->parts) +		add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);  	else  #endif  	{ diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 13b05cb33b0..78ae89488a4 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -593,6 +593,7 @@ static int attach_by_scanning(struct ubi_device *ubi)  	ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;  	ubi->max_ec = si->max_ec;  	ubi->mean_ec = si->mean_ec; +	ubi_msg("max. sequence number:       %llu", si->max_sqnum);  	err = ubi_read_volume_table(ubi, si);  	if (err) @@ -981,7 +982,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)  	ubi_msg("number of PEBs reserved for bad PEB handling: %d",  		ubi->beb_rsvd_pebs);  	ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); -	ubi_msg("image sequence number: %d", ubi->image_seq); +	ubi_msg("image sequence number:  %d", ubi->image_seq);  	/*  	 * The below lock makes sure we do not race with 'ubi_thread()' which diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 9f87c99189a..fe74749e0da 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -418,7 +418,8 @@ retry:  				 * may try to recover data. FIXME: but this is  				 * not implemented.  				 */ -				if (err == UBI_IO_BAD_VID_HDR) { +				if (err == UBI_IO_BAD_HDR_READ || +				    err == UBI_IO_BAD_HDR) {  					ubi_warn("corrupted VID header at PEB "  						 "%d, LEB %d:%d", pnum, vol_id,  						 lnum); @@ -961,8 +962,8 @@ write_error:   */  static int is_error_sane(int err)  { -	if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_VID_HDR || -	    err == -ETIMEDOUT) +	if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_HDR || +	    err == UBI_IO_BAD_HDR_READ || err == -ETIMEDOUT)  		return 0;  	return 1;  } @@ -1165,6 +1166,44 @@ out_unlock_leb:  }  /** + * print_rsvd_warning - warn about not having enough reserved PEBs. + * @ubi: UBI device description object + * + * This is a helper function for 'ubi_eba_init_scan()' which is called when UBI + * cannot reserve enough PEBs for bad block handling. This function makes a + * decision whether we have to print a warning or not. The algorithm is as + * follows: + *   o if this is a new UBI image, then just print the warning + *   o if this is an UBI image which has already been used for some time, print + *     a warning only if we can reserve less than 10% of the expected amount of + *     the reserved PEB. + * + * The idea is that when UBI is used, PEBs become bad, and the reserved pool + * of PEBs becomes smaller, which is normal and we do not want to scare users + * with a warning every time they attach the MTD device. This was an issue + * reported by real users. + */ +static void print_rsvd_warning(struct ubi_device *ubi, +			       struct ubi_scan_info *si) +{ +	/* +	 * The 1 << 18 (256KiB) number is picked randomly, just a reasonably +	 * large number to distinguish between newly flashed and used images. +	 */ +	if (si->max_sqnum > (1 << 18)) { +		int min = ubi->beb_rsvd_level / 10; + +		if (!min) +			min = 1; +		if (ubi->beb_rsvd_pebs > min) +			return; +	} + +	ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d," +		 " need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level); +} + +/**   * ubi_eba_init_scan - initialize the EBA sub-system using scanning information.   * @ubi: UBI device description object   * @si: scanning information @@ -1236,9 +1275,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)  		if (ubi->avail_pebs < ubi->beb_rsvd_level) {  			/* No enough free physical eraseblocks */  			ubi->beb_rsvd_pebs = ubi->avail_pebs; -			ubi_warn("cannot reserve enough PEBs for bad PEB " -				 "handling, reserved %d, need %d", -				 ubi->beb_rsvd_pebs, ubi->beb_rsvd_level); +			print_rsvd_warning(ubi, si);  		} else  			ubi->beb_rsvd_pebs = ubi->beb_rsvd_level; diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 4b979e34b15..332f992f13d 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -150,6 +150,8 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,  retry:  	err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);  	if (err) { +		const char *errstr = (err == -EBADMSG) ? " (ECC error)" : ""; +  		if (err == -EUCLEAN) {  			/*  			 * -EUCLEAN is reported if there was a bit-flip which @@ -165,15 +167,15 @@ retry:  		}  		if (read != len && retries++ < UBI_IO_RETRIES) { -			dbg_io("error %d while reading %d bytes from PEB %d:%d," +			dbg_io("error %d%s while reading %d bytes from PEB %d:%d,"  			       " read only %zd bytes, retry", -			       err, len, pnum, offset, read); +			       err, errstr, len, pnum, offset, read);  			yield();  			goto retry;  		} -		ubi_err("error %d while reading %d bytes from PEB %d:%d, " -			"read %zd bytes", err, len, pnum, offset, read); +		ubi_err("error %d%s while reading %d bytes from PEB %d:%d, " +			"read %zd bytes", err, errstr, len, pnum, offset, read);  		ubi_dbg_dump_stack();  		/* @@ -515,7 +517,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)  	 * In this case we probably anyway have garbage in this PEB.  	 */  	err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); -	if (err1 == UBI_IO_BAD_VID_HDR) +	if (err1 == UBI_IO_BAD_HDR_READ || err1 == UBI_IO_BAD_HDR)  		/*  		 * The VID header is corrupted, so we can safely erase this  		 * PEB and not afraid that it will be treated as a valid PEB in @@ -709,7 +711,7 @@ bad:   * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected   *   and corrected by the flash driver; this is harmless but may indicate that   *   this eraseblock may become bad soon (but may be not); - * o %UBI_IO_BAD_EC_HDR if the erase counter header is corrupted (a CRC error); + * o %UBI_IO_BAD_HDR if the erase counter header is corrupted (a CRC error);   * o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty;   * o a negative error code in case of failure.   */ @@ -736,23 +738,21 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,  		 * header is still OK, we just report this as there was a  		 * bit-flip.  		 */ -		read_err = err; +		if (err == -EBADMSG) +			read_err = UBI_IO_BAD_HDR_READ;  	}  	magic = be32_to_cpu(ec_hdr->magic);  	if (magic != UBI_EC_HDR_MAGIC) { +		if (read_err) +			return read_err; +  		/*  		 * The magic field is wrong. Let's check if we have read all  		 * 0xFF. If yes, this physical eraseblock is assumed to be  		 * empty. -		 * -		 * But if there was a read error, we do not test it for all -		 * 0xFFs. Even if it does contain all 0xFFs, this error -		 * indicates that something is still wrong with this physical -		 * eraseblock and we anyway cannot treat it as empty.  		 */ -		if (read_err != -EBADMSG && -		    check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { +		if (check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {  			/* The physical eraseblock is supposedly empty */  			if (verbose)  				ubi_warn("no EC header found at PEB %d, " @@ -774,7 +774,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,  		} else if (UBI_IO_DEBUG)  			dbg_msg("bad magic number at PEB %d: %08x instead of "  				"%08x", pnum, magic, UBI_EC_HDR_MAGIC); -		return UBI_IO_BAD_EC_HDR; +		return UBI_IO_BAD_HDR;  	}  	crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); @@ -788,7 +788,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,  		} else if (UBI_IO_DEBUG)  			dbg_msg("bad EC header CRC at PEB %d, calculated "  				"%#08x, read %#08x", pnum, crc, hdr_crc); -		return UBI_IO_BAD_EC_HDR; +		return read_err ?: UBI_IO_BAD_HDR;  	}  	/* And of course validate what has just been read from the media */ @@ -798,6 +798,10 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,  		return -EINVAL;  	} +	/* +	 * If there was %-EBADMSG, but the header CRC is still OK, report about +	 * a bit-flip to force scrubbing on this PEB. +	 */  	return read_err ? UBI_IO_BITFLIPS : 0;  } @@ -977,7 +981,7 @@ bad:   * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected   *   and corrected by the flash driver; this is harmless but may indicate that   *   this eraseblock may become bad soon; - * o %UBI_IO_BAD_VID_HDR if the volume identifier header is corrupted (a CRC + * o %UBI_IO_BAD_HDR if the volume identifier header is corrupted (a CRC   *   error detected);   * o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID   *   header there); @@ -1008,22 +1012,20 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,  		 * CRC check-sum and we will identify this. If the VID header is  		 * still OK, we just report this as there was a bit-flip.  		 */ -		read_err = err; +		if (err == -EBADMSG) +			read_err = UBI_IO_BAD_HDR_READ;  	}  	magic = be32_to_cpu(vid_hdr->magic);  	if (magic != UBI_VID_HDR_MAGIC) { +		if (read_err) +			return read_err; +  		/*  		 * If we have read all 0xFF bytes, the VID header probably does  		 * not exist and the physical eraseblock is assumed to be free. -		 * -		 * But if there was a read error, we do not test the data for -		 * 0xFFs. Even if it does contain all 0xFFs, this error -		 * indicates that something is still wrong with this physical -		 * eraseblock and it cannot be regarded as free.  		 */ -		if (read_err != -EBADMSG && -		    check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { +		if (check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {  			/* The physical eraseblock is supposedly free */  			if (verbose)  				ubi_warn("no VID header found at PEB %d, " @@ -1045,7 +1047,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,  		} else if (UBI_IO_DEBUG)  			dbg_msg("bad magic number at PEB %d: %08x instead of "  				"%08x", pnum, magic, UBI_VID_HDR_MAGIC); -		return UBI_IO_BAD_VID_HDR; +		return UBI_IO_BAD_HDR;  	}  	crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC); @@ -1059,7 +1061,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,  		} else if (UBI_IO_DEBUG)  			dbg_msg("bad CRC at PEB %d, calculated %#08x, "  				"read %#08x", pnum, crc, hdr_crc); -		return UBI_IO_BAD_VID_HDR; +		return read_err ?: UBI_IO_BAD_HDR;  	}  	/* Validate the VID header that we have just read */ @@ -1069,6 +1071,10 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,  		return -EINVAL;  	} +	/* +	 * If there was a read error (%-EBADMSG), but the header CRC is still +	 * OK, report about a bit-flip to force scrubbing on this PEB. +	 */  	return read_err ? UBI_IO_BITFLIPS : 0;  } diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index aed19f33b8f..372a15ac999 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -44,6 +44,7 @@  #include <linux/slab.h>  #include <linux/crc32.h>  #include <linux/math64.h> +#include <linux/random.h>  #include "ubi.h"  #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID @@ -72,16 +73,19 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,  {  	struct ubi_scan_leb *seb; -	if (list == &si->free) +	if (list == &si->free) {  		dbg_bld("add to free: PEB %d, EC %d", pnum, ec); -	else if (list == &si->erase) +		si->free_peb_count += 1; +	} else if (list == &si->erase) {  		dbg_bld("add to erase: PEB %d, EC %d", pnum, ec); -	else if (list == &si->corr) { +		si->erase_peb_count += 1; +	} else if (list == &si->corr) {  		dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec); -		si->corr_count += 1; -	} else if (list == &si->alien) +		si->corr_peb_count += 1; +	} else if (list == &si->alien) {  		dbg_bld("add to alien: PEB %d, EC %d", pnum, ec); -	else +		si->alien_peb_count += 1; +	} else  		BUG();  	seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); @@ -517,6 +521,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,  	sv->leb_count += 1;  	rb_link_node(&seb->u.rb, parent, p);  	rb_insert_color(&seb->u.rb, &sv->root); +	si->used_peb_count += 1;  	return 0;  } @@ -745,19 +750,17 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,  		bitflips = 1;  	else if (err == UBI_IO_PEB_EMPTY)  		return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase); -	else if (err == UBI_IO_BAD_EC_HDR) { +	else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) {  		/*  		 * We have to also look at the VID header, possibly it is not  		 * corrupted. Set %bitflips flag in order to make this PEB be  		 * moved and EC be re-created.  		 */ -		ec_corr = 1; +		ec_corr = err;  		ec = UBI_SCAN_UNKNOWN_EC;  		bitflips = 1;  	} -	si->is_empty = 0; -  	if (!ec_corr) {  		int image_seq; @@ -813,9 +816,12 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,  		return err;  	else if (err == UBI_IO_BITFLIPS)  		bitflips = 1; -	else if (err == UBI_IO_BAD_VID_HDR || +	else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR ||  		 (err == UBI_IO_PEB_FREE && ec_corr)) {  		/* VID header is corrupted */ +		if (err == UBI_IO_BAD_HDR_READ || +		    ec_corr == UBI_IO_BAD_HDR_READ) +			si->read_err_count += 1;  		err = add_to_list(si, pnum, ec, &si->corr);  		if (err)  			return err; @@ -836,11 +842,11 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,  		switch (vidh->compat) {  		case UBI_COMPAT_DELETE:  			ubi_msg("\"delete\" compatible internal volume %d:%d" -				" found, remove it", vol_id, lnum); +				" found, will remove it", vol_id, lnum);  			err = add_to_list(si, pnum, ec, &si->corr);  			if (err)  				return err; -			break; +			return 0;  		case UBI_COMPAT_RO:  			ubi_msg("read-only compatible internal volume %d:%d" @@ -855,7 +861,6 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,  			err = add_to_list(si, pnum, ec, &si->alien);  			if (err)  				return err; -			si->alien_peb_count += 1;  			return 0;  		case UBI_COMPAT_REJECT: @@ -886,6 +891,85 @@ adjust_mean_ec:  }  /** + * check_what_we_have - check what PEB were found by scanning. + * @ubi: UBI device description object + * @si: scanning information + * + * This is a helper function which takes a look what PEBs were found by + * scanning, and decides whether the flash is empty and should be formatted and + * whether there are too many corrupted PEBs and we should not attach this + * MTD device. Returns zero if we should proceed with attaching the MTD device, + * and %-EINVAL if we should not. + */ +static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si) +{ +	struct ubi_scan_leb *seb; +	int max_corr; + +	max_corr = ubi->peb_count - si->bad_peb_count - si->alien_peb_count; +	max_corr = max_corr / 20 ?: 8; + +	/* +	 * Few corrupted PEBs are not a problem and may be just a result of +	 * unclean reboots. However, many of them may indicate some problems +	 * with the flash HW or driver. +	 */ +	if (si->corr_peb_count >= 8) { +		ubi_warn("%d PEBs are corrupted", si->corr_peb_count); +		printk(KERN_WARNING "corrupted PEBs are:"); +		list_for_each_entry(seb, &si->corr, u.list) +			printk(KERN_CONT " %d", seb->pnum); +		printk(KERN_CONT "\n"); + +		/* +		 * If too many PEBs are corrupted, we refuse attaching, +		 * otherwise, only print a warning. +		 */ +		if (si->corr_peb_count >= max_corr) { +			ubi_err("too many corrupted PEBs, refusing this device"); +			return -EINVAL; +		} +	} + +	if (si->free_peb_count + si->used_peb_count + +	    si->alien_peb_count == 0) { +		/* No UBI-formatted eraseblocks were found */ +		if (si->corr_peb_count == si->read_err_count && +		    si->corr_peb_count < 8) { +			/* No or just few corrupted PEBs, and all of them had a +			 * read error. We assume that those are bad PEBs, which +			 * were just not marked as bad so far. +			 * +			 * This piece of code basically tries to distinguish +			 * between the following 2 situations: +			 * +			 * 1. Flash is empty, but there are few bad PEBs, which +			 *    are not marked as bad so far, and which were read +			 *    with error. We want to go ahead and format this +			 *    flash. While formating, the faulty PEBs will +			 *    probably be marked as bad. +			 * +			 * 2. Flash probably contains non-UBI data and we do +			 * not want to format it and destroy possibly needed +			 * data (e.g., consider the case when the bootloader +			 * MTD partition was accidentally fed to UBI). +			 */ +			si->is_empty = 1; +			ubi_msg("empty MTD device detected"); +			get_random_bytes(&ubi->image_seq, sizeof(ubi->image_seq)); +		} else { +			ubi_err("MTD device possibly contains non-UBI data, " +				"refusing it"); +			return -EINVAL; +		} +	} + +	if (si->corr_peb_count > 0) +		ubi_msg("corrupted PEBs will be formatted"); +	return 0; +} + +/**   * ubi_scan - scan an MTD device.   * @ubi: UBI device description object   * @@ -909,7 +993,6 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)  	INIT_LIST_HEAD(&si->erase);  	INIT_LIST_HEAD(&si->alien);  	si->volumes = RB_ROOT; -	si->is_empty = 1;  	err = -ENOMEM;  	ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); @@ -935,21 +1018,9 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)  	if (si->ec_count)  		si->mean_ec = div_u64(si->ec_sum, si->ec_count); -	if (si->is_empty) -		ubi_msg("empty MTD device detected"); - -	/* -	 * Few corrupted PEBs are not a problem and may be just a result of -	 * unclean reboots. However, many of them may indicate some problems -	 * with the flash HW or driver. Print a warning in this case. -	 */ -	if (si->corr_count >= 8 || si->corr_count >= ubi->peb_count / 4) { -		ubi_warn("%d PEBs are corrupted", si->corr_count); -		printk(KERN_WARNING "corrupted PEBs are:"); -		list_for_each_entry(seb, &si->corr, u.list) -			printk(KERN_CONT " %d", seb->pnum); -		printk(KERN_CONT "\n"); -	} +	err = check_what_we_have(ubi, si); +	if (err) +		goto out_vidh;  	/*  	 * In case of unknown erase counter we use the mean erase counter diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index ff179ad7ca5..2576a8d1532 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h @@ -91,10 +91,16 @@ struct ubi_scan_volume {   * @erase: list of physical eraseblocks which have to be erased   * @alien: list of physical eraseblocks which should not be used by UBI (e.g.,   *         those belonging to "preserve"-compatible internal volumes) + * @used_peb_count: count of used PEBs + * @corr_peb_count: count of PEBs in the @corr list + * @read_err_count: count of PEBs read with error (%UBI_IO_BAD_HDR_READ was + *                  returned) + * @free_peb_count: count of PEBs in the @free list + * @erase_peb_count: count of PEBs in the @erase list + * @alien_peb_count: count of PEBs in the @alien list   * @bad_peb_count: count of bad physical eraseblocks   * @vols_found: number of volumes found during scanning   * @highest_vol_id: highest volume ID - * @alien_peb_count: count of physical eraseblocks in the @alien list   * @is_empty: flag indicating whether the MTD device is empty or not   * @min_ec: lowest erase counter value   * @max_ec: highest erase counter value @@ -102,7 +108,6 @@ struct ubi_scan_volume {   * @mean_ec: mean erase counter value   * @ec_sum: a temporary variable used when calculating @mean_ec   * @ec_count: a temporary variable used when calculating @mean_ec - * @corr_count: count of corrupted PEBs   *   * This data structure contains the result of scanning and may be used by other   * UBI sub-systems to build final UBI data structures, further error-recovery @@ -114,10 +119,15 @@ struct ubi_scan_info {  	struct list_head free;  	struct list_head erase;  	struct list_head alien; +	int used_peb_count; +	int corr_peb_count; +	int read_err_count; +	int free_peb_count; +	int erase_peb_count; +	int alien_peb_count;  	int bad_peb_count;  	int vols_found;  	int highest_vol_id; -	int alien_peb_count;  	int is_empty;  	int min_ec;  	int max_ec; @@ -125,7 +135,6 @@ struct ubi_scan_info {  	int mean_ec;  	uint64_t ec_sum;  	int ec_count; -	int corr_count;  };  struct ubi_device; @@ -135,7 +144,7 @@ struct ubi_vid_hdr;   * ubi_scan_move_to_list - move a PEB from the volume tree to a list.   *   * @sv: volume scanning information - * @seb: scanning eraseblock infprmation + * @seb: scanning eraseblock information   * @list: the list to move to   */  static inline void ubi_scan_move_to_list(struct ubi_scan_volume *sv, diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index a637f0283ad..0359e0cce48 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -89,16 +89,16 @@   *                   %0xFF bytes   * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a   *                  valid erase counter header, and the rest are %0xFF bytes - * UBI_IO_BAD_EC_HDR: the erase counter header is corrupted (bad magic or CRC) - * UBI_IO_BAD_VID_HDR: the volume identifier header is corrupted (bad magic or - *                     CRC) + * UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC) + * UBI_IO_BAD_HDR_READ: the same as %UBI_IO_BAD_HDR, but also there was a read + * 			error reported by the flash driver   * UBI_IO_BITFLIPS: bit-flips were detected and corrected   */  enum {  	UBI_IO_PEB_EMPTY = 1,  	UBI_IO_PEB_FREE, -	UBI_IO_BAD_EC_HDR, -	UBI_IO_BAD_VID_HDR, +	UBI_IO_BAD_HDR, +	UBI_IO_BAD_HDR_READ,  	UBI_IO_BITFLIPS  }; diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2decc597bda..ce2fcdd4ab9 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2754,6 +2754,7 @@ config MYRI10GE_DCA  config NETXEN_NIC  	tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"  	depends on PCI +	select FW_LOADER  	help  	  This enables the support for NetXen's Gigabit Ethernet card. @@ -2819,6 +2820,7 @@ config BNX2X  config QLCNIC  	tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support"  	depends on PCI +	select FW_LOADER  	help  	  This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet  	  devices. diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 949d7a9dcf9..117432222a0 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3073,7 +3073,6 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)  	u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;  	struct l2_fhdr *rx_hdr;  	int rx_pkt = 0, pg_ring_used = 0; -	struct pci_dev *pdev = bp->pdev;  	hw_cons = bnx2_get_hw_rx_cons(bnapi);  	sw_cons = rxr->rx_cons; @@ -3099,12 +3098,10 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)  		skb = rx_buf->skb;  		prefetchw(skb); -		if (!get_dma_ops(&pdev->dev)->sync_single_for_cpu) { -			next_rx_buf = -				&rxr->rx_buf_ring[ -					RX_RING_IDX(NEXT_RX_BD(sw_cons))]; -			prefetch(next_rx_buf->desc); -		} +		next_rx_buf = +			&rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))]; +		prefetch(next_rx_buf->desc); +  		rx_buf->skb = NULL;  		dma_addr = dma_unmap_addr(rx_buf, mapping); diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 8bd23687c53..bb0872a6331 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -1062,6 +1062,10 @@ struct bnx2x {  	/* used to synchronize stats collecting */  	int			stats_state; + +	/* used for synchronization of concurrent threads statistics handling */ +	spinlock_t		stats_lock; +  	/* used by dmae command loader */  	struct dmae_command	stats_dmae;  	int			executer_idx; diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 57ff5b3bcce..46167c08172 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,8 +57,8 @@  #include "bnx2x_init_ops.h"  #include "bnx2x_dump.h" -#define DRV_MODULE_VERSION	"1.52.53-1" -#define DRV_MODULE_RELDATE	"2010/18/04" +#define DRV_MODULE_VERSION	"1.52.53-2" +#define DRV_MODULE_RELDATE	"2010/21/07"  #define BNX2X_BC_VER		0x040200  #include <linux/firmware.h> @@ -3789,6 +3789,8 @@ static void bnx2x_storm_stats_post(struct bnx2x *bp)  		struct eth_query_ramrod_data ramrod_data = {0};  		int i, rc; +		spin_lock_bh(&bp->stats_lock); +  		ramrod_data.drv_counter = bp->stats_counter++;  		ramrod_data.collect_port = bp->port.pmf ? 1 : 0;  		for_each_queue(bp, i) @@ -3802,6 +3804,8 @@ static void bnx2x_storm_stats_post(struct bnx2x *bp)  			bp->spq_left++;  			bp->stats_pending = 1;  		} + +		spin_unlock_bh(&bp->stats_lock);  	}  } @@ -4367,6 +4371,14 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)  	struct host_func_stats *fstats = bnx2x_sp(bp, func_stats);  	struct bnx2x_eth_stats *estats = &bp->eth_stats;  	int i; +	u16 cur_stats_counter; + +	/* Make sure we use the value of the counter +	 * used for sending the last stats ramrod. +	 */ +	spin_lock_bh(&bp->stats_lock); +	cur_stats_counter = bp->stats_counter - 1; +	spin_unlock_bh(&bp->stats_lock);  	memcpy(&(fstats->total_bytes_received_hi),  	       &(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi), @@ -4394,25 +4406,22 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)  		u32 diff;  		/* are storm stats valid? */ -		if ((u16)(le16_to_cpu(xclient->stats_counter) + 1) != -							bp->stats_counter) { +		if (le16_to_cpu(xclient->stats_counter) != cur_stats_counter) {  			DP(BNX2X_MSG_STATS, "[%d] stats not updated by xstorm"  			   "  xstorm counter (0x%x) != stats_counter (0x%x)\n", -			   i, xclient->stats_counter, bp->stats_counter); +			   i, xclient->stats_counter, cur_stats_counter + 1);  			return -1;  		} -		if ((u16)(le16_to_cpu(tclient->stats_counter) + 1) != -							bp->stats_counter) { +		if (le16_to_cpu(tclient->stats_counter) != cur_stats_counter) {  			DP(BNX2X_MSG_STATS, "[%d] stats not updated by tstorm"  			   "  tstorm counter (0x%x) != stats_counter (0x%x)\n", -			   i, tclient->stats_counter, bp->stats_counter); +			   i, tclient->stats_counter, cur_stats_counter + 1);  			return -2;  		} -		if ((u16)(le16_to_cpu(uclient->stats_counter) + 1) != -							bp->stats_counter) { +		if (le16_to_cpu(uclient->stats_counter) != cur_stats_counter) {  			DP(BNX2X_MSG_STATS, "[%d] stats not updated by ustorm"  			   "  ustorm counter (0x%x) != stats_counter (0x%x)\n", -			   i, uclient->stats_counter, bp->stats_counter); +			   i, uclient->stats_counter, cur_stats_counter + 1);  			return -4;  		} @@ -4849,16 +4858,18 @@ static const struct {  static void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)  { -	enum bnx2x_stats_state state = bp->stats_state; +	enum bnx2x_stats_state state;  	if (unlikely(bp->panic))  		return; -	bnx2x_stats_stm[state][event].action(bp); +	/* Protect a state change flow */ +	spin_lock_bh(&bp->stats_lock); +	state = bp->stats_state;  	bp->stats_state = bnx2x_stats_stm[state][event].next_state; +	spin_unlock_bh(&bp->stats_lock); -	/* Make sure the state has been "changed" */ -	smp_wmb(); +	bnx2x_stats_stm[state][event].action(bp);  	if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))  		DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n", @@ -9908,6 +9919,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)  	mutex_init(&bp->port.phy_mutex);  	mutex_init(&bp->fw_mb_mutex); +	spin_lock_init(&bp->stats_lock);  #ifdef BCM_CNIC  	mutex_init(&bp->cnic_mutex);  #endif diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 40fdc41446c..8d7dfd2f1e9 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -340,7 +340,8 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)  	if ((client_info->assigned) &&  	    (client_info->ip_src == arp->ip_dst) && -	    (client_info->ip_dst == arp->ip_src)) { +	    (client_info->ip_dst == arp->ip_src) && +	    (compare_ether_addr_64bits(client_info->mac_dst, arp->mac_src))) {  		/* update the clients MAC address */  		memcpy(client_info->mac_dst, arp->mac_src, ETH_ALEN);  		client_info->ntt = 1; @@ -821,7 +822,7 @@ static int rlb_initialize(struct bonding *bond)  	/*initialize packet type*/  	pk_type->type = cpu_to_be16(ETH_P_ARP); -	pk_type->dev = NULL; +	pk_type->dev = bond->dev;  	pk_type->func = rlb_arp_recv;  	/* register to receive ARPs */ diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 5e12462a9d5..c3d98dde2f8 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -168,7 +168,7 @@ static int arp_ip_count;  static int bond_mode	= BOND_MODE_ROUNDROBIN;  static int xmit_hashtype = BOND_XMIT_POLICY_LAYER2;  static int lacp_fast; - +static int disable_netpoll = 1;  const struct bond_parm_tbl bond_lacp_tbl[] = {  {	"slow",		AD_LACP_SLOW}, @@ -1742,15 +1742,23 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)  	bond_set_carrier(bond);  #ifdef CONFIG_NET_POLL_CONTROLLER -	if (slaves_support_netpoll(bond_dev)) { -		bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; -		if (bond_dev->npinfo) -			slave_dev->npinfo = bond_dev->npinfo; -	} else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) { +	/* +	 * Netpoll and bonding is broken, make sure it is not initialized +	 * until it is fixed. +	 */ +	if (disable_netpoll) {  		bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; -		pr_info("New slave device %s does not support netpoll\n", -			slave_dev->name); -		pr_info("Disabling netpoll support for %s\n", bond_dev->name); +	} else { +		if (slaves_support_netpoll(bond_dev)) { +			bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; +			if (bond_dev->npinfo) +				slave_dev->npinfo = bond_dev->npinfo; +		} else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) { +			bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; +			pr_info("New slave device %s does not support netpoll\n", +				slave_dev->name); +			pr_info("Disabling netpoll support for %s\n", bond_dev->name); +		}  	}  #endif  	read_unlock(&bond->lock); @@ -1950,8 +1958,11 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)  #ifdef CONFIG_NET_POLL_CONTROLLER  	read_lock_bh(&bond->lock); -	if (slaves_support_netpoll(bond_dev)) -		bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; + +	 /* Make sure netpoll over stays disabled until fixed. */ +	if (!disable_netpoll) +		if (slaves_support_netpoll(bond_dev)) +				bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;  	read_unlock_bh(&bond->lock);  	if (slave_dev->netdev_ops->ndo_netpoll_cleanup)  		slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev); diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index fe925663d39..80471269977 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -3919,8 +3919,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)  		HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS;  	context->cstorm_st_context.status_block_id = BNX2X_DEF_SB_ID; -	context->xstorm_st_context.statistics_data = (cli | -				XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE); +	if (cli < MAX_X_STAT_COUNTER_ID) +		context->xstorm_st_context.statistics_data = cli | +				XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE;  	context->xstorm_ag_context.cdu_reserved =  		CDU_RSRVD_VALUE_TYPE_A(BNX2X_HW_CID(BNX2X_ISCSI_L2_CID, func), @@ -3928,10 +3929,12 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)  					ETH_CONNECTION_TYPE);  	/* reset xstorm per client statistics */ -	val = BAR_XSTRORM_INTMEM + -	      XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); -	for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++) -		CNIC_WR(dev, val + i * 4, 0); +	if (cli < MAX_X_STAT_COUNTER_ID) { +		val = BAR_XSTRORM_INTMEM + +		      XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); +		for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++) +			CNIC_WR(dev, val + i * 4, 0); +	}  	cp->tx_cons_ptr =  		&cp->bnx2x_def_status_blk->c_def_status_block.index_values[ @@ -3978,9 +3981,11 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)  						BNX2X_ISCSI_RX_SB_INDEX_NUM;  	context->ustorm_st_context.common.clientId = cli;  	context->ustorm_st_context.common.status_block_id = BNX2X_DEF_SB_ID; -	context->ustorm_st_context.common.flags = -		USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS; -	context->ustorm_st_context.common.statistics_counter_id = cli; +	if (cli < MAX_U_STAT_COUNTER_ID) { +		context->ustorm_st_context.common.flags = +			USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS; +		context->ustorm_st_context.common.statistics_counter_id = cli; +	}  	context->ustorm_st_context.common.mc_alignment_log_size = 0;  	context->ustorm_st_context.common.bd_buff_size =  						cp->l2_single_buf_size; @@ -4011,10 +4016,13 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)  	/* client tstorm info */  	tstorm_client.mtu = cp->l2_single_buf_size - 14; -	tstorm_client.config_flags = -			(TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE | -			TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE); -	tstorm_client.statistics_counter_id = cli; +	tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE; + +	if (cli < MAX_T_STAT_COUNTER_ID) { +		tstorm_client.config_flags |= +				TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE; +		tstorm_client.statistics_counter_id = cli; +	}  	CNIC_WR(dev, BAR_TSTRORM_INTMEM +  		   TSTORM_CLIENT_CONFIG_OFFSET(port, cli), @@ -4024,16 +4032,21 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)  		   ((u32 *)&tstorm_client)[1]);  	/* reset tstorm per client statistics */ -	val = BAR_TSTRORM_INTMEM + -	      TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); -	for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++) -		CNIC_WR(dev, val + i * 4, 0); +	if (cli < MAX_T_STAT_COUNTER_ID) { + +		val = BAR_TSTRORM_INTMEM + +		      TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); +		for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++) +			CNIC_WR(dev, val + i * 4, 0); +	}  	/* reset ustorm per client statistics */ -	val = BAR_USTRORM_INTMEM + -	      USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); -	for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++) -		CNIC_WR(dev, val + i * 4, 0); +	if (cli < MAX_U_STAT_COUNTER_ID) { +		val = BAR_USTRORM_INTMEM + +		      USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli); +		for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++) +			CNIC_WR(dev, val + i * 4, 0); +	}  	cp->rx_cons_ptr =  		&cp->bnx2x_def_status_blk->u_def_status_block.index_values[ diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 3c58db59528..23786ee34be 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -1181,7 +1181,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev)  		if (netif_msg_drv(priv))  			printk(KERN_ERR "%s: Could not attach to PHY\n",  			       dev->name); -		return PTR_ERR(priv->phy); +		rc = PTR_ERR(priv->phy); +		goto fail;  	}  	if ((rc = register_netdev(dev))) { diff --git a/drivers/net/declance.c b/drivers/net/declance.c index 1d973db27c3..d7de376d717 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -1022,7 +1022,7 @@ static const struct net_device_ops lance_netdev_ops = {  	.ndo_set_mac_address	= eth_mac_addr,  }; -static int __init dec_lance_probe(struct device *bdev, const int type) +static int __devinit dec_lance_probe(struct device *bdev, const int type)  {  	static unsigned version_printed;  	static const char fmt[] = "declance%d"; @@ -1326,7 +1326,7 @@ static void __exit dec_lance_platform_remove(void)  }  #ifdef CONFIG_TC -static int __init dec_lance_tc_probe(struct device *dev); +static int __devinit dec_lance_tc_probe(struct device *dev);  static int __exit dec_lance_tc_remove(struct device *dev);  static const struct tc_device_id dec_lance_tc_table[] = { @@ -1345,7 +1345,7 @@ static struct tc_driver dec_lance_tc_driver = {  	},  }; -static int __init dec_lance_tc_probe(struct device *dev) +static int __devinit dec_lance_tc_probe(struct device *dev)  {          int status = dec_lance_probe(dev, PMAD_LANCE);          if (!status) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index ebdea089166..68a80893dce 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1047,15 +1047,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev,  		goto err_register;  	/* print bus type/speed/width info */ -	e_info("(PCI%s:%s:%s) ", -		((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""), -		((hw->bus_speed == e1000_bus_speed_133) ? "133MHz" : -		 (hw->bus_speed == e1000_bus_speed_120) ? "120MHz" : -		 (hw->bus_speed == e1000_bus_speed_100) ? "100MHz" : -		 (hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"), -		((hw->bus_width == e1000_bus_width_64) ? "64-bit" : "32-bit")); - -	e_info("%pM\n", netdev->dev_addr); +	e_info("(PCI%s:%dMHz:%d-bit) %pM\n", +	       ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""), +	       ((hw->bus_speed == e1000_bus_speed_133) ? 133 : +		(hw->bus_speed == e1000_bus_speed_120) ? 120 : +		(hw->bus_speed == e1000_bus_speed_100) ? 100 : +		(hw->bus_speed == e1000_bus_speed_66) ? 66 : 33), +	       ((hw->bus_width == e1000_bus_width_64) ? 64 : 32), +	       netdev->dev_addr);  	/* carrier off reporting is important to ethtool even BEFORE open */  	netif_carrier_off(netdev); diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 0630980a272..0060e422f17 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@  #include <asm/io.h>  #define DRV_NAME	"ehea" -#define DRV_VERSION	"EHEA_0103" +#define DRV_VERSION	"EHEA_0105"  /* eHEA capability flags */  #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index f547894ff48..8b92acb448c 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -867,6 +867,7 @@ static int ehea_poll(struct napi_struct *napi, int budget)  		ehea_reset_cq_ep(pr->send_cq);  		ehea_reset_cq_n1(pr->recv_cq);  		ehea_reset_cq_n1(pr->send_cq); +		rmb();  		cqe = ehea_poll_rq1(pr->qp, &wqe_index);  		cqe_skb = ehea_poll_cq(pr->send_cq); @@ -2859,6 +2860,7 @@ static void ehea_reset_port(struct work_struct *work)  		container_of(work, struct ehea_port, reset_task);  	struct net_device *dev = port->netdev; +	mutex_lock(&dlpar_mem_lock);  	port->resets++;  	mutex_lock(&port->port_lock);  	netif_stop_queue(dev); @@ -2881,6 +2883,7 @@ static void ehea_reset_port(struct work_struct *work)  	netif_wake_queue(dev);  out:  	mutex_unlock(&port->port_lock); +	mutex_unlock(&dlpar_mem_lock);  }  static void ehea_rereg_mrs(struct work_struct *work) @@ -3542,10 +3545,7 @@ static int ehea_mem_notifier(struct notifier_block *nb,  	int ret = NOTIFY_BAD;  	struct memory_notify *arg = data; -	if (!mutex_trylock(&dlpar_mem_lock)) { -		ehea_info("ehea_mem_notifier must not be called parallelized"); -		goto out; -	} +	mutex_lock(&dlpar_mem_lock);  	switch (action) {  	case MEM_CANCEL_OFFLINE: @@ -3574,7 +3574,6 @@ static int ehea_mem_notifier(struct notifier_block *nb,  out_unlock:  	mutex_unlock(&dlpar_mem_lock); -out:  	return ret;  } diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index 2b3e16db5c8..e0d33281ec9 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c @@ -709,7 +709,7 @@ int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len)  {  	u64 a0, a1 = len;  	int wait = 1000; -	u64 prov_pa; +	dma_addr_t prov_pa;  	void *prov_buf;  	int ret; diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index ba190376e03..efd4c70753d 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -381,10 +381,14 @@ static void gfar_init_mac(struct net_device *ndev)  	/* Insert receive time stamps into padding alignment bytes */  	if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) {  		rctrl &= ~RCTRL_PAL_MASK; -		rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE | RCTRL_PADDING(8); +		rctrl |= RCTRL_PADDING(8);  		priv->padding = 8;  	} +	/* Enable HW time stamping if requested from user space */ +	if (priv->hwts_rx_en) +		rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE; +  	/* keep vlan related bits if it's enabled */  	if (priv->vlgrp) {  		rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT; @@ -747,7 +751,8 @@ static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev)  			FSL_GIANFAR_DEV_HAS_CSUM |  			FSL_GIANFAR_DEV_HAS_VLAN |  			FSL_GIANFAR_DEV_HAS_MAGIC_PACKET | -			FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; +			FSL_GIANFAR_DEV_HAS_EXTENDED_HASH | +			FSL_GIANFAR_DEV_HAS_TIMER;  	ctype = of_get_property(np, "phy-connection-type", NULL); @@ -805,12 +810,20 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev,  	switch (config.rx_filter) {  	case HWTSTAMP_FILTER_NONE: -		priv->hwts_rx_en = 0; +		if (priv->hwts_rx_en) { +			stop_gfar(netdev); +			priv->hwts_rx_en = 0; +			startup_gfar(netdev); +		}  		break;  	default:  		if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))  			return -ERANGE; -		priv->hwts_rx_en = 1; +		if (!priv->hwts_rx_en) { +			stop_gfar(netdev); +			priv->hwts_rx_en = 1; +			startup_gfar(netdev); +		}  		config.rx_filter = HWTSTAMP_FILTER_ALL;  		break;  	} @@ -2642,6 +2655,10 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)  		dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,  				priv->rx_buffer_size, DMA_FROM_DEVICE); +		if (unlikely(!(bdp->status & RXBD_ERR) && +				bdp->length > priv->rx_buffer_size)) +			bdp->status = RXBD_LARGE; +  		/* We drop the frame if we failed to allocate a new buffer */  		if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||  				 bdp->status & RXBD_ERR)) { diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 7acb3edc47e..2602852cc55 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -677,7 +677,7 @@ static int ibmveth_close(struct net_device *netdev)  	if (!adapter->pool_config)  		netif_stop_queue(netdev); -	free_irq(netdev->irq, netdev); +	h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);  	do {  		lpar_rc = h_free_logical_lan(adapter->vdev->unit_address); @@ -689,6 +689,8 @@ static int ibmveth_close(struct net_device *netdev)  				     lpar_rc);  	} +	free_irq(netdev->irq, netdev); +  	adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);  	ibmveth_cleanup(adapter); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 3881918f538..cea37e0837f 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1722,6 +1722,15 @@ static int __devinit igb_probe(struct pci_dev *pdev,  	u16 eeprom_apme_mask = IGB_EEPROM_APME;  	u32 part_num; +	/* Catch broken hardware that put the wrong VF device ID in +	 * the PCIe SR-IOV capability. +	 */ +	if (pdev->is_virtfn) { +		WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n", +		     pci_name(pdev), pdev->vendor, pdev->device); +		return -EINVAL; +	} +  	err = pci_enable_device_mem(pdev);  	if (err)  		return err; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index c50a7541ffe..3a93a81872b 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -2077,25 +2077,6 @@ static int ixgbe_get_coalesce(struct net_device *netdev,  	return 0;  } -/* - * this function must be called before setting the new value of - * rx_itr_setting - */ -static bool ixgbe_reenable_rsc(struct ixgbe_adapter *adapter, -                               struct ethtool_coalesce *ec) -{ -	/* check the old value and enable RSC if necessary */ -	if ((adapter->rx_itr_setting == 0) && -	    (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) { -		adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; -		adapter->netdev->features |= NETIF_F_LRO; -		DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n", -		        ec->rx_coalesce_usecs); -		return true; -	} -	return false; -} -  static int ixgbe_set_coalesce(struct net_device *netdev,                                struct ethtool_coalesce *ec)  { @@ -2124,9 +2105,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,  		    (1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))  			return -EINVAL; -		/* check the old value and enable RSC if necessary */ -		need_reset = ixgbe_reenable_rsc(adapter, ec); -  		/* store the value in ints/second */  		adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs; @@ -2135,9 +2113,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,  		/* clear the lower bit as its used for dynamic state */  		adapter->rx_itr_setting &= ~1;  	} else if (ec->rx_coalesce_usecs == 1) { -		/* check the old value and enable RSC if necessary */ -		need_reset = ixgbe_reenable_rsc(adapter, ec); -  		/* 1 means dynamic mode */  		adapter->rx_eitr_param = 20000;  		adapter->rx_itr_setting = 1; @@ -2157,10 +2132,11 @@ static int ixgbe_set_coalesce(struct net_device *netdev,  		 */  		if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {  			adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED; -			netdev->features &= ~NETIF_F_LRO; -			DPRINTK(PROBE, INFO, -			        "rx-usecs set to 0, disabling RSC\n"); - +			if (netdev->features & NETIF_F_LRO) { +				netdev->features &= ~NETIF_F_LRO; +				DPRINTK(PROBE, INFO, "rx-usecs set to 0, " +					"disabling LRO/RSC\n"); +			}  			need_reset = true;  		}  	} @@ -2255,6 +2231,9 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)  			}  		} else if (!adapter->rx_itr_setting) {  			netdev->features &= ~ETH_FLAG_LRO; +			if (data & ETH_FLAG_LRO) +				DPRINTK(PROBE, INFO, "rx-usecs set to 0, " +					"LRO/RSC cannot be enabled.\n");  		}  	} diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index b2af2f67f60..74d9b6df302 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3684,10 +3684,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter)  	/* signal that we are down to the interrupt handler */  	set_bit(__IXGBE_DOWN, &adapter->state); -	/* power down the optics */ -	if (hw->phy.multispeed_fiber) -		hw->mac.ops.disable_tx_laser(hw); -  	/* disable receive for all VFs and wait one second */  	if (adapter->num_vfs) {  		/* ping all the active vfs to let them know we are going down */ @@ -3742,6 +3738,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)  		                (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &  		                 ~IXGBE_DMATXCTL_TE)); +	/* power down the optics */ +	if (hw->phy.multispeed_fiber) +		hw->mac.ops.disable_tx_laser(hw); +  	/* clear n-tuple filters that are cached */  	ethtool_ntuple_flush(netdev); @@ -4001,7 +4001,7 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)  done:  	/* Notify the stack of the (possibly) reduced Tx Queue count. */ -	adapter->netdev->real_num_tx_queues = adapter->num_tx_queues; +	netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);  }  static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, @@ -5195,7 +5195,6 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)  		ixgbe_free_all_tx_resources(adapter);  		ixgbe_free_all_rx_resources(adapter);  	} -	ixgbe_clear_interrupt_scheme(adapter);  #ifdef CONFIG_PM  	retval = pci_save_state(pdev); @@ -5230,6 +5229,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)  	*enable_wake = !!wufc; +	ixgbe_clear_interrupt_scheme(adapter); +  	ixgbe_release_hw_control(adapter);  	pci_disable_device(pdev); @@ -5282,6 +5283,10 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)  	u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;  	u64 non_eop_descs = 0, restart_queue = 0; +	if (test_bit(__IXGBE_DOWN, &adapter->state) || +	    test_bit(__IXGBE_RESETTING, &adapter->state)) +		return; +  	if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {  		u64 rsc_count = 0;  		u64 rsc_flush = 0; @@ -6019,7 +6024,6 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,  static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,  	              int queue, u32 tx_flags)  { -	/* Right now, we support IPv4 only */  	struct ixgbe_atr_input atr_input;  	struct tcphdr *th;  	struct iphdr *iph = ip_hdr(skb); @@ -6028,6 +6032,9 @@ static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,  	u32 src_ipv4_addr, dst_ipv4_addr;  	u8 l4type = 0; +	/* Right now, we support IPv4 only */ +	if (skb->protocol != htons(ETH_P_IP)) +		return;  	/* check if we're UDP or TCP */  	if (iph->protocol == IPPROTO_TCP) {  		th = tcp_hdr(skb); @@ -6485,6 +6492,15 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,  #endif  	u32 part_num, eec; +	/* Catch broken hardware that put the wrong VF device ID in +	 * the PCIe SR-IOV capability. +	 */ +	if (pdev->is_virtfn) { +		WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n", +		     pci_name(pdev), pdev->vendor, pdev->device); +		return -EINVAL; +	} +  	err = pci_enable_device_mem(pdev);  	if (err)  		return err; diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 09e1911ff51..48325a5beff 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -575,6 +575,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)  		 * 4    SFP_DA_CORE1 - 82599-specific  		 * 5    SFP_SR/LR_CORE0 - 82599-specific  		 * 6    SFP_SR/LR_CORE1 - 82599-specific +		 * 7    SFP_act_lmt_DA_CORE0 - 82599-specific +		 * 8    SFP_act_lmt_DA_CORE1 - 82599-specific  		 */  		if (hw->mac.type == ixgbe_mac_82598EB) {  			if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index ce5d6e90921..c27f4291b35 100644 --- a/drivers/net/lib82596.c +++ b/drivers/net/lib82596.c @@ -1343,7 +1343,7 @@ static void set_multicast_list(struct net_device *dev)  	DEB(DEB_MULTI,  	    printk(KERN_DEBUG  		   "%s: set multicast list, %d entries, promisc %s, allmulti %s\n", -		   dev->name, dev->mc_count, +		   dev->name, netdev_mc_count(dev),  		   dev->flags & IFF_PROMISC ? "ON" : "OFF",  		   dev->flags & IFF_ALLMULTI ? "ON" : "OFF")); diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 315eb4cdb58..dc6bf042579 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -964,7 +964,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)  	np = of_parse_phandle(op->dev.of_node, "llink-connected", 0);  	if (!np) {  		dev_err(&op->dev, "could not find DMA node\n"); -		goto nodev; +		goto err_iounmap;  	}  	/* Setup the DMA register accesses, could be DCR or memory mapped */ @@ -978,7 +978,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)  			dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs);  		} else {  			dev_err(&op->dev, "unable to map DMA registers\n"); -			goto nodev; +			goto err_iounmap;  		}  	} @@ -987,7 +987,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)  	if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {  		dev_err(&op->dev, "could not determine irqs\n");  		rc = -ENOMEM; -		goto nodev; +		goto err_iounmap_2;  	}  	of_node_put(np); /* Finished with the DMA node; drop the reference */ @@ -997,7 +997,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)  	if ((!addr) || (size != 6)) {  		dev_err(&op->dev, "could not find MAC address\n");  		rc = -ENODEV; -		goto nodev; +		goto err_iounmap_2;  	}  	temac_set_mac_address(ndev, (void *)addr); @@ -1013,7 +1013,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)  	rc = sysfs_create_group(&lp->dev->kobj, &temac_attr_group);  	if (rc) {  		dev_err(lp->dev, "Error creating sysfs files\n"); -		goto nodev; +		goto err_iounmap_2;  	}  	rc = register_netdev(lp->ndev); @@ -1026,6 +1026,11 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)   err_register_ndev:  	sysfs_remove_group(&lp->dev->kobj, &temac_attr_group); + err_iounmap_2: +	if (lp->sdma_regs) +		iounmap(lp->sdma_regs); + err_iounmap: +	iounmap(lp->regs);   nodev:  	free_netdev(ndev);  	ndev = NULL; @@ -1044,6 +1049,9 @@ static int __devexit temac_of_remove(struct of_device *op)  		of_node_put(lp->phy_node);  	lp->phy_node = NULL;  	dev_set_drvdata(&op->dev, NULL); +	iounmap(lp->regs); +	if (lp->sdma_regs) +		iounmap(lp->sdma_regs);  	free_netdev(ndev);  	return 0;  } diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 87e8d4cb405..f15fe2cf72a 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -499,7 +499,7 @@ static const struct net_device_ops macvlan_netdev_ops = {  	.ndo_validate_addr	= eth_validate_addr,  }; -static void macvlan_setup(struct net_device *dev) +void macvlan_common_setup(struct net_device *dev)  {  	ether_setup(dev); @@ -508,6 +508,12 @@ static void macvlan_setup(struct net_device *dev)  	dev->destructor		= free_netdev;  	dev->header_ops		= &macvlan_hard_header_ops,  	dev->ethtool_ops	= &macvlan_ethtool_ops; +} +EXPORT_SYMBOL_GPL(macvlan_common_setup); + +static void macvlan_setup(struct net_device *dev) +{ +	macvlan_common_setup(dev);  	dev->tx_queue_len	= 0;  } @@ -705,7 +711,6 @@ int macvlan_link_register(struct rtnl_link_ops *ops)  	/* common fields */  	ops->priv_size		= sizeof(struct macvlan_dev);  	ops->get_tx_queues	= macvlan_get_tx_queues; -	ops->setup		= macvlan_setup;  	ops->validate		= macvlan_validate;  	ops->maxtype		= IFLA_MACVLAN_MAX;  	ops->policy		= macvlan_policy; @@ -719,6 +724,7 @@ EXPORT_SYMBOL_GPL(macvlan_link_register);  static struct rtnl_link_ops macvlan_link_ops = {  	.kind		= "macvlan", +	.setup		= macvlan_setup,  	.newlink	= macvlan_newlink,  	.dellink	= macvlan_dellink,  }; diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index a8a94e2f6dd..ff02b836c3c 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -180,11 +180,18 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)  {  	struct macvtap_queue *q = macvtap_get_queue(dev, skb);  	if (!q) -		return -ENOLINK; +		goto drop; + +	if (skb_queue_len(&q->sk.sk_receive_queue) >= dev->tx_queue_len) +		goto drop;  	skb_queue_tail(&q->sk.sk_receive_queue, skb);  	wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND); -	return 0; +	return NET_RX_SUCCESS; + +drop: +	kfree_skb(skb); +	return NET_RX_DROP;  }  /* @@ -235,8 +242,15 @@ static void macvtap_dellink(struct net_device *dev,  	macvlan_dellink(dev, head);  } +static void macvtap_setup(struct net_device *dev) +{ +	macvlan_common_setup(dev); +	dev->tx_queue_len = TUN_READQ_SIZE; +} +  static struct rtnl_link_ops macvtap_link_ops __read_mostly = {  	.kind		= "macvtap", +	.setup		= macvtap_setup,  	.newlink	= macvtap_newlink,  	.dellink	= macvtap_dellink,  }; diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c index 8e9704f5c12..869f0ea43a5 100644 --- a/drivers/net/mipsnet.c +++ b/drivers/net/mipsnet.c @@ -247,7 +247,7 @@ static const struct net_device_ops mipsnet_netdev_ops = {  	.ndo_set_mac_address	= eth_mac_addr,  }; -static int __init mipsnet_probe(struct platform_device *dev) +static int __devinit mipsnet_probe(struct platform_device *dev)  {  	struct net_device *netdev;  	int err; diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index e345ec8cb47..73bb8ea6f54 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -289,6 +289,7 @@ struct mv643xx_eth_shared_private {  	unsigned int t_clk;  	int extended_rx_coal_limit;  	int tx_bw_control; +	int tx_csum_limit;  };  #define TX_BW_CONTROL_ABSENT		0 @@ -776,13 +777,16 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)  	l4i_chk = 0;  	if (skb->ip_summed == CHECKSUM_PARTIAL) { +		int hdr_len;  		int tag_bytes;  		BUG_ON(skb->protocol != htons(ETH_P_IP) &&  		       skb->protocol != htons(ETH_P_8021Q)); -		tag_bytes = (void *)ip_hdr(skb) - (void *)skb->data - ETH_HLEN; -		if (unlikely(tag_bytes & ~12)) { +		hdr_len = (void *)ip_hdr(skb) - (void *)skb->data; +		tag_bytes = hdr_len - ETH_HLEN; +		if (skb->len - hdr_len > mp->shared->tx_csum_limit || +		    unlikely(tag_bytes & ~12)) {  			if (skb_checksum_help(skb) == 0)  				goto no_csum;  			kfree_skb(skb); @@ -2666,6 +2670,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)  	 * Detect hardware parameters.  	 */  	msp->t_clk = (pd != NULL && pd->t_clk != 0) ? pd->t_clk : 133000000; +	msp->tx_csum_limit = pd->tx_csum_limit ? pd->tx_csum_limit : 9 * 1024;  	infer_hw_params(msp);  	platform_set_drvdata(pdev, msp); diff --git a/drivers/net/ne.c b/drivers/net/ne.c index b8e2923a1d6..1063093b3af 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -806,8 +806,10 @@ static int __init ne_drv_probe(struct platform_device *pdev)  		dev->base_addr = res->start;  		dev->irq = platform_get_irq(pdev, 0);  	} else { -		if (this_dev < 0 || this_dev >= MAX_NE_CARDS) +		if (this_dev < 0 || this_dev >= MAX_NE_CARDS) { +			free_netdev(dev);  			return -EINVAL; +		}  		dev->base_addr = io[this_dev];  		dev->irq = irq[this_dev];  		dev->mem_end = bad[this_dev]; diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index f26e54716c8..3a41b6a84a6 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -629,7 +629,8 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)  	if (addr == NULL) {  		dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n",  				netdev->name); -		return -ENOMEM; +		err = -ENOMEM; +		goto err_out_free;  	}  	tx_ring->desc_head = (struct cmd_desc_type0 *)addr; diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 5c496f8d7c4..29d7b93d049 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -1159,9 +1159,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)  	window = CRB_HI(off); -	if (adapter->ahw.crb_win == window) -		return; -  	writel(window, addr);  	if (readl(addr) != window) {  		if (printk_ratelimit()) @@ -1169,7 +1166,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)  				"failed to set CRB window to %d off 0x%lx\n",  				window, off);  	} -	adapter->ahw.crb_win = window;  }  static void __iomem * diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 045a7c8f5bd..c865dda2adf 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -218,7 +218,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)  	if (cmd_buf_arr == NULL) {  		dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",  		       netdev->name); -		return -ENOMEM; +		goto err_out;  	}  	memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));  	tx_ring->cmd_buf_arr = cmd_buf_arr; @@ -230,7 +230,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)  	if (rds_ring == NULL) {  		dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n",  		       netdev->name); -		return -ENOMEM; +		goto err_out;  	}  	recv_ctx->rds_rings = rds_ring; @@ -1805,9 +1805,10 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,  	netxen_ctx_msg msg = 0;  	struct list_head *head; +	spin_lock(&rds_ring->lock); +  	producer = rds_ring->producer; -	spin_lock(&rds_ring->lock);  	head = &rds_ring->free_list;  	while (!list_empty(head)) { @@ -1829,7 +1830,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,  		producer = get_next_index(producer, rds_ring->num_desc);  	} -	spin_unlock(&rds_ring->lock);  	if (count) {  		rds_ring->producer = producer; @@ -1853,6 +1853,8 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,  					NETXEN_RCV_PRODUCER_OFFSET), msg);  		}  	} + +	spin_unlock(&rds_ring->lock);  }  static void @@ -1864,10 +1866,11 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,  	int producer, count = 0;  	struct list_head *head; -	producer = rds_ring->producer;  	if (!spin_trylock(&rds_ring->lock))  		return; +	producer = rds_ring->producer; +  	head = &rds_ring->free_list;  	while (!list_empty(head)) { diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 5b3dfb4ab27..33525bf2a3d 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -1168,6 +1168,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)  	int interrupts, nr_serviced = 0, i;  	struct ei_device *ei_local;      	int handled = 0; +	unsigned long flags;  	e8390_base = dev->base_addr;  	ei_local = netdev_priv(dev); @@ -1176,7 +1177,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)  	 *	Protect the irq test too.  	 */ -	spin_lock(&ei_local->page_lock); +	spin_lock_irqsave(&ei_local->page_lock, flags);  	if (ei_local->irqlock)   	{ @@ -1188,7 +1189,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)  			   dev->name, inb_p(e8390_base + EN0_ISR),  			   inb_p(e8390_base + EN0_IMR));  #endif -		spin_unlock(&ei_local->page_lock); +		spin_unlock_irqrestore(&ei_local->page_lock, flags);  		return IRQ_NONE;  	} @@ -1261,7 +1262,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)  	ei_local->irqlock = 0;  	outb_p(ENISR_ALL, e8390_base + EN0_IMR); -	spin_unlock(&ei_local->page_lock); +	spin_unlock_irqrestore(&ei_local->page_lock, flags);  	return IRQ_RETVAL(handled);  } diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 6f77a768ba8..bfdef72c5d5 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = {  	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),  	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),  	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"), +	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),  	PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),  	PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),  	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"), diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 64e6a84bbbb..307cd1721e9 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1505,12 +1505,20 @@ irq_done:  	writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR);  	writeb(cor, smc->base + MOT_LAN + CISREG_COR);      } -#ifdef DOES_NOT_WORK -    if (smc->base != NULL) { /* Megahertz MFC's */ -	readb(smc->base+MEGAHERTZ_ISR); -	readb(smc->base+MEGAHERTZ_ISR); + +    if ((smc->base != NULL) &&  /* Megahertz MFC's */ +	(smc->manfid == MANFID_MEGAHERTZ) && +	(smc->cardid == PRODID_MEGAHERTZ_EM3288)) { + +	u_char tmp; +	tmp = readb(smc->base+MEGAHERTZ_ISR); +	tmp = readb(smc->base+MEGAHERTZ_ISR); + +	/* Retrigger interrupt if needed */ +	writeb(tmp, smc->base + MEGAHERTZ_ISR); +	writeb(tmp, smc->base + MEGAHERTZ_ISR);      } -#endif +      spin_unlock(&smc->lock);      return IRQ_RETVAL(handled);  } diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c index dbd00345373..29c39ff85de 100644 --- a/drivers/net/phy/lxt.c +++ b/drivers/net/phy/lxt.c @@ -226,6 +226,7 @@ module_exit(lxt_exit);  static struct mdio_device_id lxt_tbl[] = {  	{ 0x78100000, 0xfffffff0 },  	{ 0x001378e0, 0xfffffff0 }, +	{ 0x00137a10, 0xfffffff0 },  	{ }  }; diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 78b74e83ce5..5a1bd5db2a9 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -29,6 +29,7 @@  #include <linux/mii.h>  #include <linux/ethtool.h>  #include <linux/phy.h> +#include <linux/marvell_phy.h>  #include <asm/io.h>  #include <asm/irq.h> @@ -48,8 +49,6 @@  #define MII_M1145_RGMII_RX_DELAY	0x0080  #define MII_M1145_RGMII_TX_DELAY	0x0002 -#define M1145_DEV_FLAGS_RESISTANCE	0x00000001 -  #define MII_M1111_PHY_LED_CONTROL	0x18  #define MII_M1111_PHY_LED_DIRECT	0x4100  #define MII_M1111_PHY_LED_COMBINE	0x411c @@ -350,7 +349,10 @@ static int m88e1118_config_init(struct phy_device *phydev)  		return err;  	/* Adjust LED Control */ -	err = phy_write(phydev, 0x10, 0x021e); +	if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS) +		err = phy_write(phydev, 0x10, 0x1100); +	else +		err = phy_write(phydev, 0x10, 0x021e);  	if (err < 0)  		return err; @@ -398,7 +400,7 @@ static int m88e1145_config_init(struct phy_device *phydev)  		if (err < 0)  			return err; -		if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) { +		if (phydev->dev_flags & MARVELL_PHY_M1145_FLAGS_RESISTANCE) {  			err = phy_write(phydev, 0x1d, 0x0012);  			if (err < 0)  				return err; @@ -529,8 +531,8 @@ static int m88e1121_did_interrupt(struct phy_device *phydev)  static struct phy_driver marvell_drivers[] = {  	{ -		.phy_id = 0x01410c60, -		.phy_id_mask = 0xfffffff0, +		.phy_id = MARVELL_PHY_ID_88E1101, +		.phy_id_mask = MARVELL_PHY_ID_MASK,  		.name = "Marvell 88E1101",  		.features = PHY_GBIT_FEATURES,  		.flags = PHY_HAS_INTERRUPT, @@ -541,8 +543,8 @@ static struct phy_driver marvell_drivers[] = {  		.driver = { .owner = THIS_MODULE },  	},  	{ -		.phy_id = 0x01410c90, -		.phy_id_mask = 0xfffffff0, +		.phy_id = MARVELL_PHY_ID_88E1112, +		.phy_id_mask = MARVELL_PHY_ID_MASK,  		.name = "Marvell 88E1112",  		.features = PHY_GBIT_FEATURES,  		.flags = PHY_HAS_INTERRUPT, @@ -554,8 +556,8 @@ static struct phy_driver marvell_drivers[] = {  		.driver = { .owner = THIS_MODULE },  	},  	{ -		.phy_id = 0x01410cc0, -		.phy_id_mask = 0xfffffff0, +		.phy_id = MARVELL_PHY_ID_88E1111, +		.phy_id_mask = MARVELL_PHY_ID_MASK,  		.name = "Marvell 88E1111",  		.features = PHY_GBIT_FEATURES,  		.flags = PHY_HAS_INTERRUPT, @@ -567,8 +569,8 @@ static struct phy_driver marvell_drivers[] = {  		.driver = { .owner = THIS_MODULE },  	},  	{ -		.phy_id = 0x01410e10, -		.phy_id_mask = 0xfffffff0, +		.phy_id = MARVELL_PHY_ID_88E1118, +		.phy_id_mask = MARVELL_PHY_ID_MASK,  		.name = "Marvell 88E1118",  		.features = PHY_GBIT_FEATURES,  		.flags = PHY_HAS_INTERRUPT, @@ -580,8 +582,8 @@ static struct phy_driver marvell_drivers[] = {  		.driver = {.owner = THIS_MODULE,},  	},  	{ -		.phy_id = 0x01410cb0, -		.phy_id_mask = 0xfffffff0, +		.phy_id = MARVELL_PHY_ID_88E1121R, +		.phy_id_mask = MARVELL_PHY_ID_MASK,  		.name = "Marvell 88E1121R",  		.features = PHY_GBIT_FEATURES,  		.flags = PHY_HAS_INTERRUPT, @@ -593,8 +595,8 @@ static struct phy_driver marvell_drivers[] = {  		.driver = { .owner = THIS_MODULE },  	},  	{ -		.phy_id = 0x01410cd0, -		.phy_id_mask = 0xfffffff0, +		.phy_id = MARVELL_PHY_ID_88E1145, +		.phy_id_mask = MARVELL_PHY_ID_MASK,  		.name = "Marvell 88E1145",  		.features = PHY_GBIT_FEATURES,  		.flags = PHY_HAS_INTERRUPT, @@ -606,8 +608,8 @@ static struct phy_driver marvell_drivers[] = {  		.driver = { .owner = THIS_MODULE },  	},  	{ -		.phy_id = 0x01410e30, -		.phy_id_mask = 0xfffffff0, +		.phy_id = MARVELL_PHY_ID_88E1240, +		.phy_id_mask = MARVELL_PHY_ID_MASK,  		.name = "Marvell 88E1240",  		.features = PHY_GBIT_FEATURES,  		.flags = PHY_HAS_INTERRUPT, diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index fa4b24c49f4..d10bcefc0e4 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -4611,8 +4611,7 @@ static void ql_timer(unsigned long data)  		return;  	} -	qdev->timer.expires = jiffies + (5*HZ); -	add_timer(&qdev->timer); +	mod_timer(&qdev->timer, jiffies + (5*HZ));  }  static int __devinit qlge_probe(struct pci_dev *pdev, @@ -4713,6 +4712,8 @@ static void ql_eeh_close(struct net_device *ndev)  		netif_stop_queue(ndev);  	} +	/* Disabling the timer */ +	del_timer_sync(&qdev->timer);  	if (test_bit(QL_ADAPTER_UP, &qdev->flags))  		cancel_delayed_work_sync(&qdev->asic_reset_work);  	cancel_delayed_work_sync(&qdev->mpi_reset_work); @@ -4808,8 +4809,7 @@ static void qlge_io_resume(struct pci_dev *pdev)  		netif_err(qdev, ifup, qdev->ndev,  			  "Device was not running prior to EEH.\n");  	} -	qdev->timer.expires = jiffies + (5*HZ); -	add_timer(&qdev->timer); +	mod_timer(&qdev->timer, jiffies + (5*HZ));  	netif_device_attach(ndev);  } @@ -4871,8 +4871,7 @@ static int qlge_resume(struct pci_dev *pdev)  			return err;  	} -	qdev->timer.expires = jiffies + (5*HZ); -	add_timer(&qdev->timer); +	mod_timer(&qdev->timer, jiffies + (5*HZ));  	netif_device_attach(ndev);  	return 0; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 96b6cfbf0a3..cdc6a5c2e70 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1316,7 +1316,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,  		{ 0x7c800000, 0x28000000,	RTL_GIGA_MAC_VER_26 },  		/* 8168C family. */ -		{ 0x7cf00000, 0x3ca00000,	RTL_GIGA_MAC_VER_24 }, +		{ 0x7cf00000, 0x3cb00000,	RTL_GIGA_MAC_VER_24 },  		{ 0x7cf00000, 0x3c900000,	RTL_GIGA_MAC_VER_23 },  		{ 0x7cf00000, 0x3c800000,	RTL_GIGA_MAC_VER_18 },  		{ 0x7c800000, 0x3c800000,	RTL_GIGA_MAC_VER_24 }, diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 668327ccd8d..1d37f0c310c 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -3130,7 +3130,6 @@ static void tx_intr_handler(struct fifo_info *fifo_data)  		pkt_cnt++;  		/* Updating the statistics block */ -		nic->dev->stats.tx_bytes += skb->len;  		swstats->mem_freed += skb->truesize;  		dev_kfree_skb_irq(skb); @@ -4901,48 +4900,81 @@ static void s2io_updt_stats(struct s2io_nic *sp)   *  Return value:   *  pointer to the updated net_device_stats structure.   */ -  static struct net_device_stats *s2io_get_stats(struct net_device *dev)  {  	struct s2io_nic *sp = netdev_priv(dev); -	struct config_param *config = &sp->config;  	struct mac_info *mac_control = &sp->mac_control;  	struct stat_block *stats = mac_control->stats_info; -	int i; +	u64 delta;  	/* Configure Stats for immediate updt */  	s2io_updt_stats(sp); -	/* Using sp->stats as a staging area, because reset (due to mtu -	   change, for example) will clear some hardware counters */ -	dev->stats.tx_packets += le32_to_cpu(stats->tmac_frms) - -		sp->stats.tx_packets; -	sp->stats.tx_packets = le32_to_cpu(stats->tmac_frms); +	/* A device reset will cause the on-adapter statistics to be zero'ed. +	 * This can be done while running by changing the MTU.  To prevent the +	 * system from having the stats zero'ed, the driver keeps a copy of the +	 * last update to the system (which is also zero'ed on reset).  This +	 * enables the driver to accurately know the delta between the last +	 * update and the current update. +	 */ +	delta = ((u64) le32_to_cpu(stats->rmac_vld_frms_oflow) << 32 | +		le32_to_cpu(stats->rmac_vld_frms)) - sp->stats.rx_packets; +	sp->stats.rx_packets += delta; +	dev->stats.rx_packets += delta; -	dev->stats.tx_errors += le32_to_cpu(stats->tmac_any_err_frms) - -		sp->stats.tx_errors; -	sp->stats.tx_errors = le32_to_cpu(stats->tmac_any_err_frms); +	delta = ((u64) le32_to_cpu(stats->tmac_frms_oflow) << 32 | +		le32_to_cpu(stats->tmac_frms)) - sp->stats.tx_packets; +	sp->stats.tx_packets += delta; +	dev->stats.tx_packets += delta; -	dev->stats.rx_errors += le64_to_cpu(stats->rmac_drop_frms) - -		sp->stats.rx_errors; -	sp->stats.rx_errors = le64_to_cpu(stats->rmac_drop_frms); +	delta = ((u64) le32_to_cpu(stats->rmac_data_octets_oflow) << 32 | +		le32_to_cpu(stats->rmac_data_octets)) - sp->stats.rx_bytes; +	sp->stats.rx_bytes += delta; +	dev->stats.rx_bytes += delta; -	dev->stats.multicast = le32_to_cpu(stats->rmac_vld_mcst_frms) - -		sp->stats.multicast; -	sp->stats.multicast = le32_to_cpu(stats->rmac_vld_mcst_frms); +	delta = ((u64) le32_to_cpu(stats->tmac_data_octets_oflow) << 32 | +		le32_to_cpu(stats->tmac_data_octets)) - sp->stats.tx_bytes; +	sp->stats.tx_bytes += delta; +	dev->stats.tx_bytes += delta; -	dev->stats.rx_length_errors = le64_to_cpu(stats->rmac_long_frms) - -		sp->stats.rx_length_errors; -	sp->stats.rx_length_errors = le64_to_cpu(stats->rmac_long_frms); +	delta = le64_to_cpu(stats->rmac_drop_frms) - sp->stats.rx_errors; +	sp->stats.rx_errors += delta; +	dev->stats.rx_errors += delta; -	/* collect per-ring rx_packets and rx_bytes */ -	dev->stats.rx_packets = dev->stats.rx_bytes = 0; -	for (i = 0; i < config->rx_ring_num; i++) { -		struct ring_info *ring = &mac_control->rings[i]; +	delta = ((u64) le32_to_cpu(stats->tmac_any_err_frms_oflow) << 32 | +		le32_to_cpu(stats->tmac_any_err_frms)) - sp->stats.tx_errors; +	sp->stats.tx_errors += delta; +	dev->stats.tx_errors += delta; -		dev->stats.rx_packets += ring->rx_packets; -		dev->stats.rx_bytes += ring->rx_bytes; -	} +	delta = le64_to_cpu(stats->rmac_drop_frms) - sp->stats.rx_dropped; +	sp->stats.rx_dropped += delta; +	dev->stats.rx_dropped += delta; + +	delta = le64_to_cpu(stats->tmac_drop_frms) - sp->stats.tx_dropped; +	sp->stats.tx_dropped += delta; +	dev->stats.tx_dropped += delta; + +	/* The adapter MAC interprets pause frames as multicast packets, but +	 * does not pass them up.  This erroneously increases the multicast +	 * packet count and needs to be deducted when the multicast frame count +	 * is queried. +	 */ +	delta = (u64) le32_to_cpu(stats->rmac_vld_mcst_frms_oflow) << 32 | +		le32_to_cpu(stats->rmac_vld_mcst_frms); +	delta -= le64_to_cpu(stats->rmac_pause_ctrl_frms); +	delta -= sp->stats.multicast; +	sp->stats.multicast += delta; +	dev->stats.multicast += delta; + +	delta = ((u64) le32_to_cpu(stats->rmac_usized_frms_oflow) << 32 | +		le32_to_cpu(stats->rmac_usized_frms)) + +		le64_to_cpu(stats->rmac_long_frms) - sp->stats.rx_length_errors; +	sp->stats.rx_length_errors += delta; +	dev->stats.rx_length_errors += delta; + +	delta = le64_to_cpu(stats->rmac_fcs_err_frms) - sp->stats.rx_crc_errors; +	sp->stats.rx_crc_errors += delta; +	dev->stats.rx_crc_errors += delta;  	return &dev->stats;  } @@ -7455,15 +7487,11 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)  		}  	} -	/* Updating statistics */ -	ring_data->rx_packets++;  	rxdp->Host_Control = 0;  	if (sp->rxd_mode == RXD_MODE_1) {  		int len = RXD_GET_BUFFER0_SIZE_1(rxdp->Control_2); -		ring_data->rx_bytes += len;  		skb_put(skb, len); -  	} else if (sp->rxd_mode == RXD_MODE_3B) {  		int get_block = ring_data->rx_curr_get_info.block_index;  		int get_off = ring_data->rx_curr_get_info.offset; @@ -7472,7 +7500,6 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)  		unsigned char *buff = skb_push(skb, buf0_len);  		struct buffAdd *ba = &ring_data->ba[get_block][get_off]; -		ring_data->rx_bytes += buf0_len + buf2_len;  		memcpy(buff, ba->ba_0, buf0_len);  		skb_put(skb, buf2_len);  	} diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 47c36e0994f..7f3a53dcc6e 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -65,7 +65,7 @@ static int debug_level = ERR_DBG;  /* DEBUG message print. */  #define DBG_PRINT(dbg_level, fmt, args...) do {			\ -	if (dbg_level >= debug_level)				\ +	if (dbg_level <= debug_level)				\  		pr_info(fmt, ##args);				\  	} while (0) @@ -745,10 +745,6 @@ struct ring_info {  	/* Buffer Address store. */  	struct buffAdd **ba; - -	/* per-Ring statistics */ -	unsigned long rx_packets; -	unsigned long rx_bytes;  } ____cacheline_aligned;  /* Fifo specific structure */ diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 1f3acc3a5df..79eee306208 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2671,6 +2671,7 @@ static struct platform_driver sbmac_driver = {  	.remove = __exit_p(sbmac_remove),  	.driver = {  		.name = sbmac_string, +		.owner  = THIS_MODULE,  	},  }; diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 2111c7bbf57..7985165e84f 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -717,11 +717,24 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)  	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);  } +/* Enable Rx/Tx */ +static void sky2_enable_rx_tx(struct sky2_port *sky2) +{ +	struct sky2_hw *hw = sky2->hw; +	unsigned port = sky2->port; +	u16 reg; + +	reg = gma_read16(hw, port, GM_GP_CTRL); +	reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; +	gma_write16(hw, port, GM_GP_CTRL, reg); +} +  /* Force a renegotiation */  static void sky2_phy_reinit(struct sky2_port *sky2)  {  	spin_lock_bh(&sky2->phy_lock);  	sky2_phy_init(sky2->hw, sky2->port); +	sky2_enable_rx_tx(sky2);  	spin_unlock_bh(&sky2->phy_lock);  } @@ -2040,7 +2053,6 @@ static void sky2_link_up(struct sky2_port *sky2)  {  	struct sky2_hw *hw = sky2->hw;  	unsigned port = sky2->port; -	u16 reg;  	static const char *fc_name[] = {  		[FC_NONE]	= "none",  		[FC_TX]		= "tx", @@ -2048,10 +2060,7 @@ static void sky2_link_up(struct sky2_port *sky2)  		[FC_BOTH]	= "both",  	}; -	/* enable Rx/Tx */ -	reg = gma_read16(hw, port, GM_GP_CTRL); -	reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; -	gma_write16(hw, port, GM_GP_CTRL, reg); +	sky2_enable_rx_tx(sky2);  	gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index c0e70006374..06b552fca63 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -367,8 +367,8 @@ static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, };  static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; -#define dr32(reg)		readl(de->regs + (reg)) -#define dw32(reg,val)		writel((val), de->regs + (reg)) +#define dr32(reg)	ioread32(de->regs + (reg)) +#define dw32(reg, val)	iowrite32((val), de->regs + (reg))  static void de_rx_err_acct (struct de_private *de, unsigned rx_tail, @@ -1706,6 +1706,7 @@ static void __devinit de21040_get_mac_address (struct de_private *de)  		int value, boguscnt = 100000;  		do {  			value = dr32(ROMCmd); +			rmb();  		} while (value < 0 && --boguscnt > 0);  		de->dev->dev_addr[i] = value;  		udelay(1); diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 6ad6fe70631..63042596f0c 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -736,8 +736,18 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,  				gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;  			else if (sinfo->gso_type & SKB_GSO_UDP)  				gso.gso_type = VIRTIO_NET_HDR_GSO_UDP; -			else -				BUG(); +			else { +				printk(KERN_ERR "tun: unexpected GSO type: " +				       "0x%x, gso_size %d, hdr_len %d\n", +				       sinfo->gso_type, gso.gso_size, +				       gso.hdr_len); +				print_hex_dump(KERN_ERR, "tun: ", +					       DUMP_PREFIX_NONE, +					       16, 1, skb->head, +					       min((int)gso.hdr_len, 64), true); +				WARN_ON_ONCE(1); +				return -EINVAL; +			}  			if (sinfo->gso_type & SKB_GSO_TCP_ECN)  				gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN;  		} else diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 4a34833b85d..807470e156a 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3215,6 +3215,8 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit  					   __func__, __LINE__, (u32) skb);  			if (skb) {  				skb->data = skb->head + NET_SKB_PAD; +				skb->len = 0; +				skb_reset_tail_pointer(skb);  				__skb_queue_head(&ugeth->rx_recycle, skb);  			} diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 0a3c41faea9..4dd23513c5a 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1334,7 +1334,6 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)  	/* check for port already opened, if not set the termios */  	serial->open_count++;  	if (serial->open_count == 1) { -		tty->low_latency = 1;  		serial->rx_state = RX_IDLE;  		/* Force default termio settings */  		_hso_serial_set_termios(tty, NULL); diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 28d3ee175e7..dd8a4adf48c 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -104,10 +104,8 @@ static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg,  int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)  {  	struct cdc_state	*info = (void *) &dev->data; -	struct usb_cdc_notification notification;  	int			master_ifnum;  	int			retval; -	int			partial;  	unsigned		count;  	__le32			rsp;  	u32			xid = 0, msg_len, request_id; @@ -135,17 +133,13 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)  	if (unlikely(retval < 0 || xid == 0))  		return retval; -	/* Some devices don't respond on the control channel until -	 * polled on the status channel, so do that first. */ -	retval = usb_interrupt_msg( -		dev->udev, -		usb_rcvintpipe(dev->udev, dev->status->desc.bEndpointAddress), -		¬ification, sizeof(notification), &partial, -		RNDIS_CONTROL_TIMEOUT_MS); -	if (unlikely(retval < 0)) -		return retval; +	// FIXME Seems like some devices discard responses when +	// we time out and cancel our "get response" requests... +	// so, this is fragile.  Probably need to poll for status. -	/* Poll the control channel; the request probably completed immediately */ +	/* ignore status endpoint, just poll the control channel; +	 * the request probably completed immediately +	 */  	rsp = buf->msg_type | RNDIS_MSG_COMPLETION;  	for (count = 0; count < 10; count++) {  		memset(buf, 0, CONTROL_BUFFER_SIZE); diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index a95c73de582..81c76ada8e5 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1293,6 +1293,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)  		goto out;  	} +	/* netdev_printk() needs this so do it as early as possible */ +	SET_NETDEV_DEV(net, &udev->dev); +  	dev = netdev_priv(net);  	dev->udev = xdev;  	dev->intf = udev; @@ -1377,8 +1380,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)  		dev->rx_urb_size = dev->hard_mtu;  	dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1); -	SET_NETDEV_DEV(net, &udev->dev); -  	if ((dev->driver_info->flags & FLAG_WLAN) != 0)  		SET_NETDEV_DEVTYPE(net, &wlan_type);  	if ((dev->driver_info->flags & FLAG_WWAN) != 0) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 1edb7a61983..bb6b67f6b0c 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -415,7 +415,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)  static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)  {  	int err; -	bool oom = false; +	bool oom;  	do {  		if (vi->mergeable_rx_bufs) @@ -425,10 +425,9 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)  		else  			err = add_recvbuf_small(vi, gfp); -		if (err < 0) { -			oom = true; +		oom = err == -ENOMEM; +		if (err < 0)  			break; -		}  		++vi->num;  	} while (err > 0);  	if (unlikely(vi->num > vi->max)) @@ -563,7 +562,6 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)  	struct virtnet_info *vi = netdev_priv(dev);  	int capacity; -again:  	/* Free up any pending old buffers before queueing new ones. */  	free_old_xmit_skbs(vi); @@ -572,14 +570,20 @@ again:  	/* This can happen with OOM and indirect buffers. */  	if (unlikely(capacity < 0)) { -		netif_stop_queue(dev); -		dev_warn(&dev->dev, "Unexpected full queue\n"); -		if (unlikely(!virtqueue_enable_cb(vi->svq))) { -			virtqueue_disable_cb(vi->svq); -			netif_start_queue(dev); -			goto again; +		if (net_ratelimit()) { +			if (likely(capacity == -ENOMEM)) { +				dev_warn(&dev->dev, +					 "TX queue failure: out of memory\n"); +			} else { +				dev->stats.tx_fifo_errors++; +				dev_warn(&dev->dev, +					 "Unexpected TX queue failure: %d\n", +					 capacity); +			}  		} -		return NETDEV_TX_BUSY; +		dev->stats.tx_dropped++; +		kfree_skb(skb); +		return NETDEV_TX_OK;  	}  	virtqueue_kick(vi->svq); diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index b504bd56136..fc8b2d7a091 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -2262,7 +2262,8 @@ start:  		vxge_debug_init(VXGE_ERR,  			"%s: memory allocation failed",  			VXGE_DRIVER_NAME); -		return  -ENOMEM; +		ret = -ENOMEM; +		goto alloc_entries_failed;  	}  	vdev->vxge_entries = @@ -2271,8 +2272,8 @@ start:  	if (!vdev->vxge_entries) {  		vxge_debug_init(VXGE_ERR, "%s: memory allocation failed",  			VXGE_DRIVER_NAME); -		kfree(vdev->entries); -		return -ENOMEM; +		ret = -ENOMEM; +		goto alloc_vxge_entries_failed;  	}  	for (i = 0, j = 0; i < vdev->no_of_vpath; i++) { @@ -2303,22 +2304,32 @@ start:  		vxge_debug_init(VXGE_ERR,  			"%s: MSI-X enable failed for %d vectors, ret: %d",  			VXGE_DRIVER_NAME, vdev->intr_cnt, ret); +		if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3)) { +			ret = -ENODEV; +			goto enable_msix_failed; +		} +  		kfree(vdev->entries);  		kfree(vdev->vxge_entries);  		vdev->entries = NULL;  		vdev->vxge_entries = NULL; - -		if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3)) -			return -ENODEV;  		/* Try with less no of vector by reducing no of vpaths count */  		temp = (ret - 1)/2;  		vxge_close_vpaths(vdev, temp);  		vdev->no_of_vpath = temp;  		goto start; -	} else if (ret < 0) -		return -ENODEV; - +	} else if (ret < 0) { +		ret = -ENODEV; +		goto enable_msix_failed; +	}  	return 0; + +enable_msix_failed: +	kfree(vdev->vxge_entries); +alloc_vxge_entries_failed: +	kfree(vdev->entries); +alloc_entries_failed: +	return ret;  }  static int vxge_enable_msix(struct vxgedev *vdev) @@ -4506,9 +4517,9 @@ vxge_starter(void)  	char version[32];  	snprintf(version, 32, "%s", DRV_VERSION); -	printk(KERN_CRIT "%s: Copyright(c) 2002-2009 Neterion Inc\n", +	printk(KERN_INFO "%s: Copyright(c) 2002-2009 Neterion Inc\n",  		VXGE_DRIVER_NAME); -	printk(KERN_CRIT "%s: Driver version: %s\n", +	printk(KERN_INFO "%s: Driver version: %s\n",  			VXGE_DRIVER_NAME, version);  	verify_bandwidth(); diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h index 2d7c96d7e86..eb80243e22d 100644 --- a/drivers/net/wimax/i2400m/i2400m-usb.h +++ b/drivers/net/wimax/i2400m/i2400m-usb.h @@ -152,6 +152,7 @@ enum {  	/* Device IDs */  	USB_DEVICE_ID_I6050 = 0x0186,  	USB_DEVICE_ID_I6050_2 = 0x0188, +	USB_DEVICE_ID_I6250 = 0x0187,  }; diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 0d5081d77dc..d3365ac85dd 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -491,6 +491,7 @@ int i2400mu_probe(struct usb_interface *iface,  	switch (id->idProduct) {  	case USB_DEVICE_ID_I6050:  	case USB_DEVICE_ID_I6050_2: +	case USB_DEVICE_ID_I6250:  		i2400mu->i6050 = 1;  		break;  	default: @@ -739,6 +740,7 @@ static  struct usb_device_id i2400mu_id_table[] = {  	{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) },  	{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, +	{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) },  	{ USB_DEVICE(0x8086, 0x0181) },  	{ USB_DEVICE(0x8086, 0x1403) },  	{ USB_DEVICE(0x8086, 0x1405) }, diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index e0c244b02f0..31c008042bf 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -126,6 +126,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)  	ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;  	ah->ah_noise_floor = -95;	/* until first NF calibration is run */  	sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; +	ah->ah_current_channel = &sc->channels[0];  	/*  	 * Find the mac version diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index fbb7dec6dde..5ea87736a6a 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -445,6 +445,7 @@ void ath_deinit_leds(struct ath_softc *sc);  #define SC_OP_TSF_RESET              BIT(11)  #define SC_OP_BT_PRIORITY_DETECTED   BIT(12)  #define SC_OP_BT_SCAN		     BIT(13) +#define SC_OP_ANI_RUN		     BIT(14)  /* Powersave flags */  #define PS_WAIT_FOR_BEACON        BIT(0) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 77b359162d6..23c15aa9fbd 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -730,13 +730,17 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)  	/* RX */  	if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0) -		goto err; +		goto err_rx;  	/* Register Read */  	if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0) -		goto err; +		goto err_reg;  	return 0; +err_reg: +	ath9k_hif_usb_dealloc_rx_urbs(hif_dev); +err_rx: +	ath9k_hif_usb_dealloc_tx_urbs(hif_dev);  err:  	return -ENOMEM;  } diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index abfa0493236..1e2a68ea935 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -336,6 +336,10 @@ set_timer:  static void ath_start_ani(struct ath_common *common)  {  	unsigned long timestamp = jiffies_to_msecs(jiffies); +	struct ath_softc *sc = (struct ath_softc *) common->priv; + +	if (!(sc->sc_flags & SC_OP_ANI_RUN)) +		return;  	common->ani.longcal_timer = timestamp;  	common->ani.shortcal_timer = timestamp; @@ -872,11 +876,13 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,  		/* Reset rssi stats */  		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; +		sc->sc_flags |= SC_OP_ANI_RUN;  		ath_start_ani(common);  	} else {  		ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");  		common->curaid = 0;  		/* Stop ANI */ +		sc->sc_flags &= ~SC_OP_ANI_RUN;  		del_timer_sync(&common->ani.timer);  	}  } @@ -1478,8 +1484,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,  	if (vif->type == NL80211_IFTYPE_AP    ||  	    vif->type == NL80211_IFTYPE_ADHOC || -	    vif->type == NL80211_IFTYPE_MONITOR) +	    vif->type == NL80211_IFTYPE_MONITOR) { +		sc->sc_flags |= SC_OP_ANI_RUN;  		ath_start_ani(common); +	}  out:  	mutex_unlock(&sc->mutex); @@ -1500,6 +1508,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,  	mutex_lock(&sc->mutex);  	/* Stop ANI */ +	sc->sc_flags &= ~SC_OP_ANI_RUN;  	del_timer_sync(&common->ani.timer);  	/* Reclaim beacon resources */ diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ca6065b71b4..e3e52913d83 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -844,9 +844,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)  	int dma_type;  	if (edma) -		dma_type = DMA_FROM_DEVICE; -	else  		dma_type = DMA_BIDIRECTIONAL; +	else +		dma_type = DMA_FROM_DEVICE;  	qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;  	spin_lock_bh(&sc->rx.rxbuflock); diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index db72461c486..29b31a694b5 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -594,6 +594,7 @@ static int prism2_config(struct pcmcia_device *link)  	local_info_t *local;  	int ret = 1;  	struct hostap_cs_priv *hw_priv; +	unsigned long flags;  	PDEBUG(DEBUG_FLOW, "prism2_config()\n"); @@ -625,9 +626,15 @@ static int prism2_config(struct pcmcia_device *link)  	local->hw_priv = hw_priv;  	hw_priv->link = link; +	/* +	 * Make sure the IRQ handler cannot proceed until at least +	 * dev->base_addr is initialized. +	 */ +	spin_lock_irqsave(&local->irq_init_lock, flags); +  	ret = pcmcia_request_irq(link, prism2_interrupt);  	if (ret) -		goto failed; +		goto failed_unlock;  	/*  	 * This actually configures the PCMCIA socket -- setting up @@ -636,11 +643,13 @@ static int prism2_config(struct pcmcia_device *link)  	 */  	ret = pcmcia_request_configuration(link, &link->conf);  	if (ret) -		goto failed; +		goto failed_unlock;  	dev->irq = link->irq;  	dev->base_addr = link->io.BasePort1; +	spin_unlock_irqrestore(&local->irq_init_lock, flags); +  	/* Finally, report what we've done */  	printk(KERN_INFO "%s: index 0x%02x: ",  	       dev_info, link->conf.ConfigIndex); @@ -667,6 +676,8 @@ static int prism2_config(struct pcmcia_device *link)  	return ret; + failed_unlock: +	 spin_unlock_irqrestore(&local->irq_init_lock, flags);   failed:  	kfree(hw_priv);  	prism2_release((u_long)link); diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index 30c2976b362..e9d9d622a9b 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -2621,6 +2621,18 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)  	iface = netdev_priv(dev);  	local = iface->local; +	/* Detect early interrupt before driver is fully configued */ +	spin_lock(&local->irq_init_lock); +	if (!dev->base_addr) { +		if (net_ratelimit()) { +			printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n", +			       dev->name); +		} +		spin_unlock(&local->irq_init_lock); +		return IRQ_HANDLED; +	} +	spin_unlock(&local->irq_init_lock); +  	prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);  	if (local->func->card_present && !local->func->card_present(local)) { @@ -3138,6 +3150,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,  	spin_lock_init(&local->cmdlock);  	spin_lock_init(&local->baplock);  	spin_lock_init(&local->lock); +	spin_lock_init(&local->irq_init_lock);  	mutex_init(&local->rid_bap_mtx);  	if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES) diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index d24dc7dc072..972a9c3af39 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -330,6 +330,7 @@ static int prism2_pci_probe(struct pci_dev *pdev,          dev->irq = pdev->irq;          hw_priv->mem_start = mem; +	dev->base_addr = (unsigned long) mem;  	prism2_pci_cor_sreset(local); diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h index 3d238917af0..1ba33be98b2 100644 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h @@ -654,7 +654,7 @@ struct local_info {  	rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock  			      * when removing entries from the list.  			      * TX and RX paths can use read lock. */ -	spinlock_t cmdlock, baplock, lock; +	spinlock_t cmdlock, baplock, lock, irq_init_lock;  	struct mutex rid_bap_mtx;  	u16 infofid; /* MAC buffer id for info frame */  	/* txfid, intransmitfid, next_txtid, and next_alloc are protected by diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 44ef5d93bef..01658cf82d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -212,11 +212,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)  static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info,  			__le32 *tx_flags)  { -	if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || -	    (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) -		*tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; -	else -		*tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; +	*tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;  }  /* Calc max signal level (dBm) among 3 possible receivers */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index a732f1094e5..7d614c4d3c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1299,6 +1299,11 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,  	sta_id = ba_resp->sta_id;  	tid = ba_resp->tid;  	agg = &priv->stations[sta_id].tid[tid].agg; +	if (unlikely(agg->txq_id != scd_flow)) { +		IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n", +			scd_flow, agg->txq_id); +		return; +	}  	/* Find index just before block-ack window */  	index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7726e67044c..24aff654fa9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3391,10 +3391,12 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,  	int ret;  	u8 sta_id; -	sta_priv->common.sta_id = IWL_INVALID_STATION; -  	IWL_DEBUG_INFO(priv, "received request to add station %pM\n",  			sta->addr); +	mutex_lock(&priv->mutex); +	IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", +			sta->addr); +	sta_priv->common.sta_id = IWL_INVALID_STATION;  	atomic_set(&sta_priv->pending_frames, 0);  	if (vif->type == NL80211_IFTYPE_AP) @@ -3406,6 +3408,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,  		IWL_ERR(priv, "Unable to add station %pM (%d)\n",  			sta->addr, ret);  		/* Should we return success if return code is EEXIST ? */ +		mutex_unlock(&priv->mutex);  		return ret;  	} @@ -3415,6 +3418,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,  	IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",  		       sta->addr);  	iwl_rs_rate_init(priv, sta, sta_id); +	mutex_unlock(&priv->mutex);  	return 0;  } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 426e95567de..5bbc5298ef9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1314,7 +1314,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw,  			changed_flags, *total_flags);  	CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); -	CHK(FIF_ALLMULTI, RXON_FILTER_ACCEPT_GRP_MSK);  	CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);  	CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); @@ -1329,6 +1328,12 @@ void iwl_configure_filter(struct ieee80211_hw *hw,  	mutex_unlock(&priv->mutex); +	/* +	 * Receiving all multicast frames is always enabled by the +	 * default flags setup in iwl_connection_init_rx_config() +	 * since we currently do not support programming multicast +	 * filters into the device. +	 */  	*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |  			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;  } diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 5d3f51ff2f0..386c5f96eff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -491,6 +491,7 @@ void iwl_bg_abort_scan(struct work_struct *work)  	mutex_lock(&priv->mutex); +	cancel_delayed_work_sync(&priv->scan_check);  	set_bit(STATUS_SCAN_ABORTING, &priv->status);  	iwl_send_scan_abort(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 83a26361a9b..c27c13fbb1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1373,10 +1373,14 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,  	IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",  			sta->addr); +	mutex_lock(&priv->mutex); +	IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", +			sta->addr);  	ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);  	if (ret)  		IWL_ERR(priv, "Error removing station %pM\n",  			sta->addr); +	mutex_unlock(&priv->mutex);  	return ret;  }  EXPORT_SYMBOL(iwl_mac_sta_remove); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index c2a453a1a99..dc43ebd1f1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -97,6 +97,17 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv)  	spin_lock_irqsave(&priv->sta_lock, flags);  	memset(priv->stations, 0, sizeof(priv->stations));  	priv->num_stations = 0; + +	/* +	 * Remove all key information that is not stored as part of station +	 * information since mac80211 may not have had a +	 * chance to remove all the keys. When device is reconfigured by +	 * mac80211 after an error all keys will be reconfigured. +	 */ +	priv->ucode_key_table = 0; +	priv->key_mapping_key = 0; +	memset(priv->wep_keys, 0, sizeof(priv->wep_keys)); +  	spin_unlock_irqrestore(&priv->sta_lock, flags);  } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6c353cacc8d..a27872de410 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3437,10 +3437,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,  	bool is_ap = vif->type == NL80211_IFTYPE_STATION;  	u8 sta_id; -	sta_priv->common.sta_id = IWL_INVALID_STATION; -  	IWL_DEBUG_INFO(priv, "received request to add station %pM\n",  			sta->addr); +	mutex_lock(&priv->mutex); +	IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", +			sta->addr); +	sta_priv->common.sta_id = IWL_INVALID_STATION; +  	ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,  				     &sta_id); @@ -3448,6 +3451,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,  		IWL_ERR(priv, "Unable to add station %pM (%d)\n",  			sta->addr, ret);  		/* Should we return success if return code is EEXIST ? */ +		mutex_unlock(&priv->mutex);  		return ret;  	} @@ -3457,6 +3461,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,  	IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",  		       sta->addr);  	iwl3945_rs_rate_init(priv, sta, sta_id); +	mutex_unlock(&priv->mutex);  	return 0;  } diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 6a04c2157f7..817fffc0de4 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -549,7 +549,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)  	prxpd = (struct rxpd *) skb->data; -	stats.flag = 0; +	memset(&stats, 0, sizeof(stats));  	if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))  		stats.flag |= RX_FLAG_FAILED_FCS_CRC;  	stats.freq = priv->cur_freq; diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 07c4528f6e6..a5ea89cde8c 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -41,6 +41,8 @@ static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {  	{ PCI_DEVICE(0x1260, 0x3877) },  	/* Intersil PRISM Javelin/Xbow Wireless LAN adapter */  	{ PCI_DEVICE(0x1260, 0x3886) }, +	/* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */ +	{ PCI_DEVICE(0x1260, 0xffff) },  	{ },  }; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 3ae468c4d76..f20d3eeeea7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -854,6 +854,11 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)  		    BIT(NL80211_IFTYPE_WDS);  	/* +	 * Initialize configuration work. +	 */ +	INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); + +	/*  	 * Let the driver probe the device to detect the capabilities.  	 */  	retval = rt2x00dev->ops->lib->probe_hw(rt2x00dev); @@ -863,11 +868,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)  	}  	/* -	 * Initialize configuration work. -	 */ -	INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); - -	/*  	 * Allocate queue array.  	 */  	retval = rt2x00queue_allocate(rt2x00dev); diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 188bc8496a2..d02be78a413 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -176,16 +176,18 @@ static ssize_t led_proc_write(struct file *file, const char *buf,  	size_t count, loff_t *pos)  {  	void *data = PDE(file->f_path.dentry->d_inode)->data; -	char *cur, lbuf[count + 1]; +	char *cur, lbuf[32];  	int d;  	if (!capable(CAP_SYS_ADMIN))  		return -EACCES; -	memset(lbuf, 0, count + 1); +	if (count >= sizeof(lbuf)) +		count = sizeof(lbuf)-1;  	if (copy_from_user(lbuf, buf, count))  		return -EFAULT; +	lbuf[count] = 0;  	cur = lbuf; diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 796828fce34..c9171be7456 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -340,7 +340,7 @@ int dmar_disabled = 0;  int dmar_disabled = 1;  #endif /*CONFIG_DMAR_DEFAULT_ON*/ -static int __initdata dmar_map_gfx = 1; +static int dmar_map_gfx = 1;  static int dmar_forcedac;  static int intel_iommu_strict; @@ -1874,14 +1874,15 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)  			}  		}  		if (found) { +			spin_unlock_irqrestore(&device_domain_lock, flags);  			free_devinfo_mem(info);  			domain_exit(domain);  			domain = found;  		} else {  			list_add(&info->link, &domain->devices);  			list_add(&info->global, &device_domain_list); +			spin_unlock_irqrestore(&device_domain_lock, flags);  		} -		spin_unlock_irqrestore(&device_domain_lock, flags);  	}  found_domain: @@ -3603,7 +3604,8 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,  		pte = dmar_domain->pgd;  		if (dma_pte_present(pte)) {  			free_pgtable_page(dmar_domain->pgd); -			dmar_domain->pgd = (struct dma_pte *)dma_pte_addr(pte); +			dmar_domain->pgd = (struct dma_pte *) +				phys_to_virt(dma_pte_addr(pte));  		}  		dmar_domain->agaw--;  	} @@ -3719,6 +3721,12 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)  	 */  	printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");  	rwbf_quirk = 1; + +	/* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */ +	if (dev->revision == 0x07) { +		printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n"); +		dmar_map_gfx = 0; +	}  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 60f30e7f1c8..740fb4ea966 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2292,6 +2292,7 @@ void pci_msi_off(struct pci_dev *dev)  		pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);  	}  } +EXPORT_SYMBOL_GPL(pci_msi_off);  #ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE  int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size) diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme/pcie_pme.c index aac285a16b6..d672a0a6381 100644 --- a/drivers/pci/pcie/pme/pcie_pme.c +++ b/drivers/pci/pcie/pme/pcie_pme.c @@ -34,7 +34,7 @@   * being registered.  Consequently, the interrupt-based PCIe PME signaling will   * not be used by any PCIe root ports in that case.   */ -static bool pcie_pme_disabled; +static bool pcie_pme_disabled = true;  /*   * The PCI Express Base Specification 2.0, Section 6.1.8, states the following: @@ -64,12 +64,19 @@ bool pcie_pme_msi_disabled;  static int __init pcie_pme_setup(char *str)  { -	if (!strcmp(str, "off")) -		pcie_pme_disabled = true; -	else if (!strcmp(str, "force")) +	if (!strncmp(str, "auto", 4)) +		pcie_pme_disabled = false; +	else if (!strncmp(str, "force", 5))  		pcie_pme_force_enable = true; -	else if (!strcmp(str, "nomsi")) -		pcie_pme_msi_disabled = true; + +	str = strchr(str, ','); +	if (str) { +		str++; +		str += strspn(str, " \t"); +		if (*str && !strcmp(str, "nomsi")) +			pcie_pme_msi_disabled = true; +	} +  	return 1;  }  __setup("pcie_pme=", pcie_pme_setup); diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 92379e2d37e..2aaa13150de 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -156,6 +156,38 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,  					     pcibios_align_resource, dev);  	} +	if (ret < 0 && dev->fw_addr[resno]) { +		struct resource *root, *conflict; +		resource_size_t start, end; + +		/* +		 * If we failed to assign anything, let's try the address +		 * where firmware left it.  That at least has a chance of +		 * working, which is better than just leaving it disabled. +		 */ + +		if (res->flags & IORESOURCE_IO) +			root = &ioport_resource; +		else +			root = &iomem_resource; + +		start = res->start; +		end = res->end; +		res->start = dev->fw_addr[resno]; +		res->end = res->start + size - 1; +		dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n", +			 resno, res); +		conflict = request_resource_conflict(root, res); +		if (conflict) { +			dev_info(&dev->dev, +				 "BAR %d: %pR conflicts with %s %pR\n", resno, +				 res, conflict->name, conflict); +			res->start = start; +			res->end = end; +		} else +			ret = 0; +	} +  	if (!ret) {  		res->flags &= ~IORESOURCE_STARTALIGN;  		dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res); diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 9fc33984553..eac961463be 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -1356,6 +1356,7 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,  	INIT_LIST_HEAD(&socket->devices_list);  	memset(&socket->pcmcia_state, 0, sizeof(u8));  	socket->device_count = 0; +	atomic_set(&socket->present, 0);  	ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback);  	if (ret) { @@ -1364,8 +1365,6 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,  		return ret;  	} -	atomic_set(&socket->present, 0); -  	return 0;  } diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 29f91fac1df..a4cd9adfcbc 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -857,8 +857,10 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev)  {  	pcmcia_release_configuration(p_dev);  	pcmcia_release_io(p_dev, &p_dev->io); -	if (p_dev->_irq) +	if (p_dev->_irq) {  		free_irq(p_dev->irq, p_dev->priv); +		p_dev->_irq = 0; +	}  	if (p_dev->win)  		pcmcia_release_window(p_dev, p_dev->win);  } diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index df4532e91b1..f370476d541 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -178,7 +178,6 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,  			       unsigned long val,  			       struct cpufreq_freqs *freqs)  { -#warning "it's not clear if this is right since the core CPU (N) clock has no effect on the memory (L) clock"  	switch (val) {  	case CPUFREQ_PRECHANGE:  		if (freqs->new > freqs->old) { @@ -186,7 +185,7 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,  			       "pre-updating\n",  			       freqs->new / 1000, (freqs->new / 100) % 10,  			       freqs->old / 1000, (freqs->old / 100) % 10); -			pxa2xx_pcmcia_set_mcxx(skt, freqs->new); +			pxa2xx_pcmcia_set_timing(skt);  		}  		break; @@ -196,7 +195,7 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,  			       "post-updating\n",  			       freqs->new / 1000, (freqs->new / 100) % 10,  			       freqs->old / 1000, (freqs->old / 100) % 10); -			pxa2xx_pcmcia_set_mcxx(skt, freqs->new); +			pxa2xx_pcmcia_set_timing(skt);  		}  		break;  	} diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index 40658e3385b..bb2f1fba637 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -489,7 +489,7 @@ int intel_scu_ipc_simple_command(int cmd, int sub)  		mutex_unlock(&ipclock);  		return -ENODEV;  	} -	ipc_command(cmd << 12 | sub); +	ipc_command(sub << 12 | cmd);  	err = busy_loop();  	mutex_unlock(&ipclock);  	return err; @@ -501,9 +501,9 @@ EXPORT_SYMBOL(intel_scu_ipc_simple_command);   *	@cmd: command   *	@sub: sub type   *	@in: input data - *	@inlen: input length + *	@inlen: input length in dwords   *	@out: output data - *	@outlein: output length + *	@outlein: output length in dwords   *   *	Issue a command to the SCU which involves data transfers. Do the   *	data copies under the lock but leave it for the caller to interpret @@ -524,7 +524,7 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,  	for (i = 0; i < inlen; i++)  		ipc_data_writel(*in++, 4 * i); -	ipc_command((cmd << 12) | sub | (inlen << 18)); +	ipc_command((sub << 12) | cmd | (inlen << 18));  	err = busy_loop();  	for (i = 0; i < outlen; i++) @@ -556,6 +556,10 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)  	u32 cmd = 0;  	mutex_lock(&ipclock); +	if (ipcdev.pdev == NULL) { +		mutex_unlock(&ipclock); +		return -ENODEV; +	}  	cmd = (addr >> 24) & 0xFF;  	if (cmd == IPC_I2C_READ) {  		writel(addr, ipcdev.i2c_base + IPC_I2C_CNTRL_ADDR); diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index d762a0cbc6a..84d3c43cf2b 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c @@ -43,10 +43,9 @@  struct ds278x_info;  struct ds278x_battery_ops { -	int	(*get_current)(struct ds278x_info *info, int *current_uA); -	int	(*get_voltage)(struct ds278x_info *info, int *voltage_uA); -	int	(*get_capacity)(struct ds278x_info *info, int *capacity_uA); - +	int (*get_battery_current)(struct ds278x_info *info, int *current_uA); +	int (*get_battery_voltage)(struct ds278x_info *info, int *voltage_uA); +	int (*get_battery_capacity)(struct ds278x_info *info, int *capacity_uA);  };  #define to_ds278x_info(x) container_of(x, struct ds278x_info, battery) @@ -163,7 +162,7 @@ static int ds2782_get_capacity(struct ds278x_info *info, int *capacity)  	if (err)  		return err;  	*capacity = raw; -	return raw; +	return 0;  }  static int ds2786_get_current(struct ds278x_info *info, int *current_uA) @@ -213,11 +212,11 @@ static int ds278x_get_status(struct ds278x_info *info, int *status)  	int current_uA;  	int capacity; -	err = info->ops->get_current(info, ¤t_uA); +	err = info->ops->get_battery_current(info, ¤t_uA);  	if (err)  		return err; -	err = info->ops->get_capacity(info, &capacity); +	err = info->ops->get_battery_capacity(info, &capacity);  	if (err)  		return err; @@ -246,15 +245,15 @@ static int ds278x_battery_get_property(struct power_supply *psy,  		break;  	case POWER_SUPPLY_PROP_CAPACITY: -		ret = info->ops->get_capacity(info, &val->intval); +		ret = info->ops->get_battery_capacity(info, &val->intval);  		break;  	case POWER_SUPPLY_PROP_VOLTAGE_NOW: -		ret = info->ops->get_voltage(info, &val->intval); +		ret = info->ops->get_battery_voltage(info, &val->intval);  		break;  	case POWER_SUPPLY_PROP_CURRENT_NOW: -		ret = info->ops->get_current(info, &val->intval); +		ret = info->ops->get_battery_current(info, &val->intval);  		break;  	case POWER_SUPPLY_PROP_TEMP: @@ -307,14 +306,14 @@ enum ds278x_num_id {  static struct ds278x_battery_ops ds278x_ops[] = {  	[DS2782] = { -		.get_current  = ds2782_get_current, -		.get_voltage  = ds2782_get_voltage, -		.get_capacity = ds2782_get_capacity, +		.get_battery_current  = ds2782_get_current, +		.get_battery_voltage  = ds2782_get_voltage, +		.get_battery_capacity = ds2782_get_capacity,  	},  	[DS2786] = { -		.get_current  = ds2786_get_current, -		.get_voltage  = ds2786_get_voltage, -		.get_capacity = ds2786_get_capacity, +		.get_battery_current  = ds2786_get_current, +		.get_battery_voltage  = ds2786_get_voltage, +		.get_battery_capacity = ds2786_get_capacity,  	}  }; diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c index 9cca465436e..85064a9f649 100644 --- a/drivers/power/z2_battery.c +++ b/drivers/power/z2_battery.c @@ -9,19 +9,13 @@   *   */ -#include <linux/init.h> -#include <linux/kernel.h>  #include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/power_supply.h> -#include <linux/i2c.h> -#include <linux/spinlock.h> -#include <linux/interrupt.h>  #include <linux/gpio.h> +#include <linux/i2c.h>  #include <linux/interrupt.h>  #include <linux/irq.h> -#include <asm/irq.h> -#include <asm/mach/irq.h> +#include <linux/power_supply.h> +#include <linux/slab.h>  #include <linux/z2_battery.h>  #define	Z2_DEFAULT_NAME	"Z2" diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 7b14a67bdca..11790990277 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -286,7 +286,7 @@ static int ab3100_list_voltage_regulator(struct regulator_dev *reg,  {  	struct ab3100_regulator *abreg = reg->reg_data; -	if (selector > abreg->voltages_len) +	if (selector >= abreg->voltages_len)  		return -EINVAL;  	return abreg->typ_voltages[selector];  } @@ -318,7 +318,7 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg)  	regval &= 0xE0;  	regval >>= 5; -	if (regval > abreg->voltages_len) { +	if (regval >= abreg->voltages_len) {  		dev_err(®->dev,  			"regulator register %02x contains an illegal voltage setting\n",  			abreg->regreg); diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 14b4576281c..8152d65220f 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -22,6 +22,7 @@  #include <linux/platform_device.h>  #include <linux/regulator/driver.h>  #include <linux/regulator/machine.h> +#include <linux/regulator/tps6507x.h>  #include <linux/delay.h>  #include <linux/slab.h>  #include <linux/mfd/tps6507x.h> @@ -101,9 +102,12 @@ struct tps_info {  	unsigned max_uV;  	u8 table_len;  	const u16 *table; + +	/* Does DCDC high or the low register defines output voltage? */ +	bool defdcdc_default;  }; -static const struct tps_info tps6507x_pmic_regs[] = { +static struct tps_info tps6507x_pmic_regs[] = {  	{  		.name = "VDCDC1",  		.min_uV = 725000, @@ -145,7 +149,7 @@ struct tps6507x_pmic {  	struct regulator_desc desc[TPS6507X_NUM_REGULATOR];  	struct tps6507x_dev *mfd;  	struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR]; -	const struct tps_info *info[TPS6507X_NUM_REGULATOR]; +	struct tps_info *info[TPS6507X_NUM_REGULATOR];  	struct mutex io_lock;  };  static inline int tps6507x_pmic_read(struct tps6507x_pmic *tps, u8 reg) @@ -341,10 +345,16 @@ static int tps6507x_pmic_dcdc_get_voltage(struct regulator_dev *dev)  		reg = TPS6507X_REG_DEFDCDC1;  		break;  	case TPS6507X_DCDC_2: -		reg = TPS6507X_REG_DEFDCDC2_LOW; +		if (tps->info[dcdc]->defdcdc_default) +			reg = TPS6507X_REG_DEFDCDC2_HIGH; +		else +			reg = TPS6507X_REG_DEFDCDC2_LOW;  		break;  	case TPS6507X_DCDC_3: -		reg = TPS6507X_REG_DEFDCDC3_LOW; +		if (tps->info[dcdc]->defdcdc_default) +			reg = TPS6507X_REG_DEFDCDC3_HIGH; +		else +			reg = TPS6507X_REG_DEFDCDC3_LOW;  		break;  	default:  		return -EINVAL; @@ -370,10 +380,16 @@ static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev,  		reg = TPS6507X_REG_DEFDCDC1;  		break;  	case TPS6507X_DCDC_2: -		reg = TPS6507X_REG_DEFDCDC2_LOW; +		if (tps->info[dcdc]->defdcdc_default) +			reg = TPS6507X_REG_DEFDCDC2_HIGH; +		else +			reg = TPS6507X_REG_DEFDCDC2_LOW;  		break;  	case TPS6507X_DCDC_3: -		reg = TPS6507X_REG_DEFDCDC3_LOW; +		if (tps->info[dcdc]->defdcdc_default) +			reg = TPS6507X_REG_DEFDCDC3_HIGH; +		else +			reg = TPS6507X_REG_DEFDCDC3_LOW;  		break;  	default:  		return -EINVAL; @@ -532,7 +548,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev)  {  	struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);  	static int desc_id; -	const struct tps_info *info = &tps6507x_pmic_regs[0]; +	struct tps_info *info = &tps6507x_pmic_regs[0];  	struct regulator_init_data *init_data;  	struct regulator_dev *rdev;  	struct tps6507x_pmic *tps; @@ -569,6 +585,12 @@ int tps6507x_pmic_probe(struct platform_device *pdev)  	for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) {  		/* Register the regulators */  		tps->info[i] = info; +		if (init_data->driver_data) { +			struct tps6507x_reg_platform_data *data = +							init_data->driver_data; +			tps->info[i]->defdcdc_default = data->defdcdc_default; +		} +  		tps->desc[i].name = info->name;  		tps->desc[i].id = desc_id++;  		tps->desc[i].n_voltages = num_voltages[i]; diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 723cd1fb486..0e6ed7db936 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1495,7 +1495,7 @@ int wm8350_register_regulator(struct wm8350 *wm8350, int reg,  	if (ret != 0) {  		dev_err(wm8350->dev, "Failed to register regulator %d: %d\n",  			reg, ret); -		platform_device_del(pdev); +		platform_device_put(pdev);  		wm8350->pmic.pdev[reg] = NULL;  	} diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index 92a8f6cacda..34647fc1ee9 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c @@ -29,6 +29,7 @@  #include <linux/bcd.h>  #include <linux/platform_device.h>  #include <linux/io.h> +#include <linux/slab.h>  /*   * The DaVinci RTC is a simple RTC with the following diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index de033b7ac21..d827ce570a8 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -777,7 +777,7 @@ static int __devinit ds1307_probe(struct i2c_client *client,  read_rtc:  	/* read RTC registers */ -	tmp = ds1307->read_block_data(ds1307->client, 0, 8, buf); +	tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf);  	if (tmp != 8) {  		pr_debug("read error %d\n", tmp);  		err = -EIO; @@ -862,7 +862,7 @@ read_rtc:  		if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)  			tmp += 12;  		i2c_smbus_write_byte_data(client, -				DS1307_REG_HOUR, +				ds1307->offset + DS1307_REG_HOUR,  				bin2bcd(tmp));  	} diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 3587d9922f2..71bbefc3544 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -456,7 +456,7 @@ static struct rtc_class_ops stv2_pl031_ops = {  	.irq_set_freq = pl031_irq_set_freq,  }; -static struct amba_id pl031_ids[] __initdata = { +static struct amba_id pl031_ids[] = {  	{  		.id = 0x00041031,  		.mask = 0x000fffff, diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 9718aaaa821..600b890a3c1 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c @@ -168,7 +168,7 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm)  		return -EIO;  	} -	err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, +	err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL,  		(data | RX8581_CTRL_STOP));  	if (err < 0) {  		dev_err(&client->dev, "Unable to write control register\n"); @@ -182,6 +182,20 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm)  		return -EIO;  	} +	/* get VLF and clear it */ +	data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); +	if (data < 0) { +		dev_err(&client->dev, "Unable to read flag register\n"); +		return -EIO; +	} + +	err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, +		(data & ~(RX8581_FLAG_VLF))); +	if (err != 0) { +		dev_err(&client->dev, "Unable to write flag register\n"); +		return -EIO; +	} +  	/* Restart the clock */  	data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL);  	if (data < 0) { @@ -189,8 +203,8 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm)  		return -EIO;  	} -	err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, -		(data | ~(RX8581_CTRL_STOP))); +	err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL, +		(data & ~(RX8581_CTRL_STOP)));  	if (err != 0) {  		dev_err(&client->dev, "Unable to write control register\n");  		return -EIO; diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 34d51dd4c53..bed7b4634cc 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -948,8 +948,10 @@ static ssize_t dasd_alias_show(struct device *dev,  	if (device->discipline && device->discipline->get_uid &&  	    !device->discipline->get_uid(device, &uid)) {  		if (uid.type == UA_BASE_PAV_ALIAS || -		    uid.type == UA_HYPER_PAV_ALIAS) +		    uid.type == UA_HYPER_PAV_ALIAS) { +			dasd_put_device(device);  			return sprintf(buf, "1\n"); +		}  	}  	dasd_put_device(device); diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index ce7cb87479f..407d0e9adfa 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -713,7 +713,7 @@ int chsc_determine_base_channel_path_desc(struct chp_id chpid,  	ret = chsc_determine_channel_path_desc(chpid, 0, 0, 0, 0, chsc_resp);  	if (ret)  		goto out_free; -	memcpy(desc, &chsc_resp->data, chsc_resp->length); +	memcpy(desc, &chsc_resp->data, sizeof(*desc));  out_free:  	kfree(chsc_resp);  	return ret; diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index e3dbeda9717..fd068bc1bd0 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -714,6 +714,14 @@ static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act)  	if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED)  		return ZFCP_ERP_FAILED; +	if (mempool_resize(act->adapter->pool.status_read_data, +			   act->adapter->stat_read_buf_num, GFP_KERNEL)) +		return ZFCP_ERP_FAILED; + +	if (mempool_resize(act->adapter->pool.status_read_req, +			   act->adapter->stat_read_buf_num, GFP_KERNEL)) +		return ZFCP_ERP_FAILED; +  	atomic_set(&act->adapter->stat_miss, act->adapter->stat_read_buf_num);  	if (zfcp_status_read_refill(act->adapter))  		return ZFCP_ERP_FAILED; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 9ac6a6e4a60..71663fb7731 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -496,7 +496,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)  	adapter->hydra_version = bottom->adapter_type;  	adapter->timer_ticks = bottom->timer_interval; -	adapter->stat_read_buf_num = max(bottom->status_read_buf_num, (u16)16); +	adapter->stat_read_buf_num = max(bottom->status_read_buf_num, +					 (u16)FSF_STATUS_READS_RECOM);  	if (fc_host_permanent_port_name(shost) == -1)  		fc_host_permanent_port_name(shost) = fc_host_port_name(shost); @@ -719,11 +720,6 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,  	zfcp_qdio_req_init(adapter->qdio, &req->qdio_req, req->req_id, sbtype,  			   req->qtcb, sizeof(struct fsf_qtcb)); -	if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) { -		zfcp_fsf_req_free(req); -		return ERR_PTR(-EIO); -	} -  	return req;  } @@ -981,7 +977,7 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,  	}  	/* use single, unchained SBAL if it can hold the request */ -	if (zfcp_qdio_sg_one_sbale(sg_req) || zfcp_qdio_sg_one_sbale(sg_resp)) { +	if (zfcp_qdio_sg_one_sbale(sg_req) && zfcp_qdio_sg_one_sbale(sg_resp)) {  		zfcp_fsf_setup_ct_els_unchained(adapter->qdio, &req->qdio_req,  						sg_req, sg_resp);  		return 0; diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 28117e130e2..6fa5e045317 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -251,7 +251,8 @@ static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)  	struct zfcp_qdio_queue *req_q = &qdio->req_q;  	spin_lock_bh(&qdio->req_q_lock); -	if (atomic_read(&req_q->count)) +	if (atomic_read(&req_q->count) || +	    !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))  		return 1;  	spin_unlock_bh(&qdio->req_q_lock);  	return 0; @@ -274,8 +275,13 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)  	spin_unlock_bh(&qdio->req_q_lock);  	ret = wait_event_interruptible_timeout(qdio->req_q_wq,  			       zfcp_qdio_sbal_check(qdio), 5 * HZ); + +	if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) +		return -EIO; +  	if (ret > 0)  		return 0; +  	if (!ret) {  		atomic_inc(&qdio->req_q_full);  		/* assume hanging outbound queue, try queue recovery */ @@ -375,6 +381,8 @@ void zfcp_qdio_close(struct zfcp_qdio *qdio)  	atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);  	spin_unlock_bh(&qdio->req_q_lock); +	wake_up(&qdio->req_q_wq); +  	qdio_shutdown(qdio->adapter->ccw_device,  		      QDIO_FLAG_CLEANUP_USING_CLEAR); diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index d53e62ab09d..aacbe14e2e7 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -554,7 +554,7 @@ static int opiocgetnext(unsigned int cmd, void __user *argp)  static int openprom_bsd_ioctl(struct file * file,  			      unsigned int cmd, unsigned long arg)  { -	DATA *data = (DATA *) file->private_data; +	DATA *data = file->private_data;  	void __user *argp = (void __user *)arg;  	int err; @@ -601,7 +601,7 @@ static int openprom_bsd_ioctl(struct file * file,  static long openprom_ioctl(struct file * file,  			   unsigned int cmd, unsigned long arg)  { -	DATA *data = (DATA *) file->private_data; +	DATA *data = file->private_data;  	switch (cmd) {  	case OPROMGETOPT: diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c index a864ccc0a34..989b9a8ba72 100644 --- a/drivers/scsi/ibmvscsi/rpa_vscsi.c +++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c @@ -277,6 +277,12 @@ static int rpavscsi_init_crq_queue(struct crq_queue *queue,  		goto reg_crq_failed;  	} +	queue->cur = 0; +	spin_lock_init(&queue->lock); + +	tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task, +		     (unsigned long)hostdata); +  	if (request_irq(vdev->irq,  			rpavscsi_handle_event,  			0, "ibmvscsi", (void *)hostdata) != 0) { @@ -291,15 +297,10 @@ static int rpavscsi_init_crq_queue(struct crq_queue *queue,  		goto req_irq_failed;  	} -	queue->cur = 0; -	spin_lock_init(&queue->lock); - -	tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task, -		     (unsigned long)hostdata); -  	return retrc;        req_irq_failed: +	tasklet_kill(&hostdata->srp_task);  	do {  		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);  	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc))); diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 82ea4a8226b..f820cffb7f0 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -1129,20 +1129,22 @@ static int ipr_is_same_device(struct ipr_resource_entry *res,  }  /** - * ipr_format_resource_path - Format the resource path for printing. + * ipr_format_res_path - Format the resource path for printing.   * @res_path:	resource path   * @buf:	buffer   *   * Return value:   * 	pointer to buffer   **/ -static char *ipr_format_resource_path(u8 *res_path, char *buffer) +static char *ipr_format_res_path(u8 *res_path, char *buffer, int len)  {  	int i; +	char *p = buffer; -	sprintf(buffer, "%02X", res_path[0]); -	for (i=1; res_path[i] != 0xff; i++) -		sprintf(buffer, "%s-%02X", buffer, res_path[i]); +	res_path[0] = '\0'; +	p += snprintf(p, buffer + len - p, "%02X", res_path[0]); +	for (i = 1; res_path[i] != 0xff && ((i * 3) < len); i++) +		p += snprintf(p, buffer + len - p, "-%02X", res_path[i]);  	return buffer;  } @@ -1187,7 +1189,8 @@ static void ipr_update_res_entry(struct ipr_resource_entry *res,  		if (res->sdev && new_path)  			sdev_printk(KERN_INFO, res->sdev, "Resource path: %s\n", -				    ipr_format_resource_path(&res->res_path[0], &buffer[0])); +				    ipr_format_res_path(res->res_path, buffer, +							sizeof(buffer)));  	} else {  		res->flags = cfgtew->u.cfgte->flags;  		if (res->flags & IPR_IS_IOA_RESOURCE) @@ -1573,7 +1576,8 @@ static void ipr_log_sis64_config_error(struct ipr_ioa_cfg *ioa_cfg,  		ipr_err_separator;  		ipr_err("Device %d : %s", i + 1, -			 ipr_format_resource_path(&dev_entry->res_path[0], &buffer[0])); +			 ipr_format_res_path(dev_entry->res_path, buffer, +					     sizeof(buffer)));  		ipr_log_ext_vpd(&dev_entry->vpd);  		ipr_err("-----New Device Information-----\n"); @@ -1919,13 +1923,14 @@ static void ipr_log64_fabric_path(struct ipr_hostrcb *hostrcb,  			ipr_hcam_err(hostrcb, "%s %s: Resource Path=%s\n",  				     path_active_desc[i].desc, path_state_desc[j].desc, -				     ipr_format_resource_path(&fabric->res_path[0], &buffer[0])); +				     ipr_format_res_path(fabric->res_path, buffer, +							 sizeof(buffer)));  			return;  		}  	}  	ipr_err("Path state=%02X Resource Path=%s\n", path_state, -		ipr_format_resource_path(&fabric->res_path[0], &buffer[0])); +		ipr_format_res_path(fabric->res_path, buffer, sizeof(buffer)));  }  static const struct { @@ -2066,7 +2071,8 @@ static void ipr_log64_path_elem(struct ipr_hostrcb *hostrcb,  			ipr_hcam_err(hostrcb, "%s %s: Resource Path=%s, Link rate=%s, WWN=%08X%08X\n",  				     path_status_desc[j].desc, path_type_desc[i].desc, -				     ipr_format_resource_path(&cfg->res_path[0], &buffer[0]), +				     ipr_format_res_path(cfg->res_path, buffer, +							 sizeof(buffer)),  				     link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],  				     be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));  			return; @@ -2074,7 +2080,7 @@ static void ipr_log64_path_elem(struct ipr_hostrcb *hostrcb,  	}  	ipr_hcam_err(hostrcb, "Path element=%02X: Resource Path=%s, Link rate=%s "  		     "WWN=%08X%08X\n", cfg->type_status, -		     ipr_format_resource_path(&cfg->res_path[0], &buffer[0]), +		     ipr_format_res_path(cfg->res_path, buffer, sizeof(buffer)),  		     link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],  		     be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));  } @@ -2139,7 +2145,7 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg,  	ipr_err("RAID %s Array Configuration: %s\n",  		error->protection_level, -		ipr_format_resource_path(&error->last_res_path[0], &buffer[0])); +		ipr_format_res_path(error->last_res_path, buffer, sizeof(buffer)));  	ipr_err_separator; @@ -2160,9 +2166,11 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg,  		ipr_err("Array Member %d:\n", i);  		ipr_log_ext_vpd(&array_entry->vpd);  		ipr_err("Current Location: %s", -			 ipr_format_resource_path(&array_entry->res_path[0], &buffer[0])); +			 ipr_format_res_path(array_entry->res_path, buffer, +					     sizeof(buffer)));  		ipr_err("Expected Location: %s", -			 ipr_format_resource_path(&array_entry->expected_res_path[0], &buffer[0])); +			 ipr_format_res_path(array_entry->expected_res_path, +					     buffer, sizeof(buffer)));  		ipr_err_separator;  	} @@ -4079,7 +4087,8 @@ static struct device_attribute ipr_adapter_handle_attr = {  };  /** - * ipr_show_resource_path - Show the resource path for this device. + * ipr_show_resource_path - Show the resource path or the resource address for + *			    this device.   * @dev:	device struct   * @buf:	buffer   * @@ -4097,9 +4106,14 @@ static ssize_t ipr_show_resource_path(struct device *dev, struct device_attribut  	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);  	res = (struct ipr_resource_entry *)sdev->hostdata; -	if (res) +	if (res && ioa_cfg->sis64)  		len = snprintf(buf, PAGE_SIZE, "%s\n", -			       ipr_format_resource_path(&res->res_path[0], &buffer[0])); +			       ipr_format_res_path(res->res_path, buffer, +						   sizeof(buffer))); +	else if (res) +		len = snprintf(buf, PAGE_SIZE, "%d:%d:%d:%d\n", ioa_cfg->host->host_no, +			       res->bus, res->target, res->lun); +  	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);  	return len;  } @@ -4351,7 +4365,8 @@ static int ipr_slave_configure(struct scsi_device *sdev)  			scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);  		if (ioa_cfg->sis64)  			sdev_printk(KERN_INFO, sdev, "Resource path: %s\n", -			            ipr_format_resource_path(&res->res_path[0], &buffer[0])); +				    ipr_format_res_path(res->res_path, buffer, +							sizeof(buffer)));  		return 0;  	}  	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 9ecd2259eb3..b965f3587c9 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1684,8 +1684,9 @@ struct ipr_ucode_image_header {  	if (ipr_is_device(hostrcb)) {					\  		if ((hostrcb)->ioa_cfg->sis64) {			\  			printk(KERN_ERR IPR_NAME ": %s: " fmt, 		\ -				ipr_format_resource_path(&hostrcb->hcam.u.error64.fd_res_path[0], \ -					&hostrcb->rp_buffer[0]),	\ +				ipr_format_res_path(hostrcb->hcam.u.error64.fd_res_path, \ +					hostrcb->rp_buffer,		\ +					sizeof(hostrcb->rp_buffer)),	\  				__VA_ARGS__);				\  		} else {						\  			ipr_ra_err((hostrcb)->ioa_cfg,			\ diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index b09a638d051..50441ffe8e3 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -782,7 +782,7 @@ static int pl010_resume(struct amba_device *dev)  	return 0;  } -static struct amba_id pl010_ids[] __initdata = { +static struct amba_id pl010_ids[] = {  	{  		.id	= 0x00041010,  		.mask	= 0x000fffff, diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index eb4cb480b93..6ca7a44f29c 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -69,9 +69,12 @@  struct uart_amba_port {  	struct uart_port	port;  	struct clk		*clk; -	unsigned int		im;	/* interrupt mask */ +	unsigned int		im;		/* interrupt mask */  	unsigned int		old_status; -	unsigned int		ifls;	/* vendor-specific */ +	unsigned int		ifls;		/* vendor-specific */ +	unsigned int		lcrh_tx;	/* vendor-specific */ +	unsigned int		lcrh_rx;	/* vendor-specific */ +	bool			oversampling;   /* vendor-specific */  	bool			autorts;  }; @@ -79,16 +82,25 @@ struct uart_amba_port {  struct vendor_data {  	unsigned int		ifls;  	unsigned int		fifosize; +	unsigned int		lcrh_tx; +	unsigned int		lcrh_rx; +	bool			oversampling;  };  static struct vendor_data vendor_arm = {  	.ifls			= UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,  	.fifosize		= 16, +	.lcrh_tx		= UART011_LCRH, +	.lcrh_rx		= UART011_LCRH, +	.oversampling		= false,  };  static struct vendor_data vendor_st = {  	.ifls			= UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,  	.fifosize		= 64, +	.lcrh_tx		= ST_UART011_LCRH_TX, +	.lcrh_rx		= ST_UART011_LCRH_RX, +	.oversampling		= true,  };  static void pl011_stop_tx(struct uart_port *port) @@ -327,12 +339,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)  	unsigned int lcr_h;  	spin_lock_irqsave(&uap->port.lock, flags); -	lcr_h = readw(uap->port.membase + UART011_LCRH); +	lcr_h = readw(uap->port.membase + uap->lcrh_tx);  	if (break_state == -1)  		lcr_h |= UART01x_LCRH_BRK;  	else  		lcr_h &= ~UART01x_LCRH_BRK; -	writew(lcr_h, uap->port.membase + UART011_LCRH); +	writew(lcr_h, uap->port.membase + uap->lcrh_tx);  	spin_unlock_irqrestore(&uap->port.lock, flags);  } @@ -393,7 +405,17 @@ static int pl011_startup(struct uart_port *port)  	writew(cr, uap->port.membase + UART011_CR);  	writew(0, uap->port.membase + UART011_FBRD);  	writew(1, uap->port.membase + UART011_IBRD); -	writew(0, uap->port.membase + UART011_LCRH); +	writew(0, uap->port.membase + uap->lcrh_rx); +	if (uap->lcrh_tx != uap->lcrh_rx) { +		int i; +		/* +		 * Wait 10 PCLKs before writing LCRH_TX register, +		 * to get this delay write read only register 10 times +		 */ +		for (i = 0; i < 10; ++i) +			writew(0xff, uap->port.membase + UART011_MIS); +		writew(0, uap->port.membase + uap->lcrh_tx); +	}  	writew(0, uap->port.membase + UART01x_DR);  	while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)  		barrier(); @@ -422,10 +444,19 @@ static int pl011_startup(struct uart_port *port)  	return retval;  } +static void pl011_shutdown_channel(struct uart_amba_port *uap, +					unsigned int lcrh) +{ +      unsigned long val; + +      val = readw(uap->port.membase + lcrh); +      val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN); +      writew(val, uap->port.membase + lcrh); +} +  static void pl011_shutdown(struct uart_port *port)  {  	struct uart_amba_port *uap = (struct uart_amba_port *)port; -	unsigned long val;  	/*  	 * disable all interrupts @@ -450,9 +481,9 @@ static void pl011_shutdown(struct uart_port *port)  	/*  	 * disable break condition and fifos  	 */ -	val = readw(uap->port.membase + UART011_LCRH); -	val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN); -	writew(val, uap->port.membase + UART011_LCRH); +	pl011_shutdown_channel(uap, uap->lcrh_rx); +	if (uap->lcrh_rx != uap->lcrh_tx) +		pl011_shutdown_channel(uap, uap->lcrh_tx);  	/*  	 * Shut down the clock producer @@ -472,8 +503,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,  	/*  	 * Ask the core to calculate the divisor for us.  	 */ -	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); -	quot = port->uartclk * 4 / baud; +	baud = uart_get_baud_rate(port, termios, old, 0, +				  port->uartclk/(uap->oversampling ? 8 : 16)); + +	if (baud > port->uartclk/16) +		quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud); +	else +		quot = DIV_ROUND_CLOSEST(port->uartclk * 4, baud);  	switch (termios->c_cflag & CSIZE) {  	case CS5: @@ -552,6 +588,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,  		uap->autorts = false;  	} +	if (uap->oversampling) { +		if (baud > port->uartclk/16) +			old_cr |= ST_UART011_CR_OVSFACT; +		else +			old_cr &= ~ST_UART011_CR_OVSFACT; +	} +  	/* Set baud rate */  	writew(quot & 0x3f, port->membase + UART011_FBRD);  	writew(quot >> 6, port->membase + UART011_IBRD); @@ -561,7 +604,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,  	 * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L  	 * ----------^----------^----------^----------^-----  	 */ -	writew(lcr_h, port->membase + UART011_LCRH); +	writew(lcr_h, port->membase + uap->lcrh_rx); +	if (uap->lcrh_rx != uap->lcrh_tx) { +		int i; +		/* +		 * Wait 10 PCLKs before writing LCRH_TX register, +		 * to get this delay write read only register 10 times +		 */ +		for (i = 0; i < 10; ++i) +			writew(0xff, uap->port.membase + UART011_MIS); +		writew(lcr_h, port->membase + uap->lcrh_tx); +	}  	writew(old_cr, port->membase + UART011_CR);  	spin_unlock_irqrestore(&port->lock, flags); @@ -688,7 +741,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,  	if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) {  		unsigned int lcr_h, ibrd, fbrd; -		lcr_h = readw(uap->port.membase + UART011_LCRH); +		lcr_h = readw(uap->port.membase + uap->lcrh_tx);  		*parity = 'n';  		if (lcr_h & UART01x_LCRH_PEN) { @@ -707,6 +760,12 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,  		fbrd = readw(uap->port.membase + UART011_FBRD);  		*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); + +		if (uap->oversampling) { +			if (readw(uap->port.membase + UART011_CR) +				  & ST_UART011_CR_OVSFACT) +				*baud *= 2; +		}  	}  } @@ -800,6 +859,9 @@ static int pl011_probe(struct amba_device *dev, struct amba_id *id)  	}  	uap->ifls = vendor->ifls; +	uap->lcrh_rx = vendor->lcrh_rx; +	uap->lcrh_tx = vendor->lcrh_tx; +	uap->oversampling = vendor->oversampling;  	uap->port.dev = &dev->dev;  	uap->port.mapbase = dev->res.start;  	uap->port.membase = base; @@ -868,7 +930,7 @@ static int pl011_resume(struct amba_device *dev)  }  #endif -static struct amba_id pl011_ids[] __initdata = { +static struct amba_id pl011_ids[] = {  	{  		.id	= 0x00041011,  		.mask	= 0x000fffff, diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index eed3c2d8dd1..a182def7007 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -41,6 +41,7 @@  #include <linux/uaccess.h>  #include <asm/io.h> +#include <asm/ioctls.h>  #include <asm/mach/serial_at91.h>  #include <mach/board.h> diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 9259e849f46..6016179db53 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -930,6 +930,83 @@ static void cpm_uart_config_port(struct uart_port *port, int flags)  	}  } +#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_CPM_CONSOLE) +/* + * Write a string to the serial port + * Note that this is called with interrupts already disabled + */ +static void cpm_uart_early_write(struct uart_cpm_port *pinfo, +		const char *string, u_int count) +{ +	unsigned int i; +	cbd_t __iomem *bdp, *bdbase; +	unsigned char *cpm_outp_addr; + +	/* Get the address of the host memory buffer. +	 */ +	bdp = pinfo->tx_cur; +	bdbase = pinfo->tx_bd_base; + +	/* +	 * Now, do each character.  This is not as bad as it looks +	 * since this is a holding FIFO and not a transmitting FIFO. +	 * We could add the complexity of filling the entire transmit +	 * buffer, but we would just wait longer between accesses...... +	 */ +	for (i = 0; i < count; i++, string++) { +		/* Wait for transmitter fifo to empty. +		 * Ready indicates output is ready, and xmt is doing +		 * that, not that it is ready for us to send. +		 */ +		while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) +			; + +		/* Send the character out. +		 * If the buffer address is in the CPM DPRAM, don't +		 * convert it. +		 */ +		cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), +					pinfo); +		*cpm_outp_addr = *string; + +		out_be16(&bdp->cbd_datlen, 1); +		setbits16(&bdp->cbd_sc, BD_SC_READY); + +		if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) +			bdp = bdbase; +		else +			bdp++; + +		/* if a LF, also do CR... */ +		if (*string == 10) { +			while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) +				; + +			cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), +						pinfo); +			*cpm_outp_addr = 13; + +			out_be16(&bdp->cbd_datlen, 1); +			setbits16(&bdp->cbd_sc, BD_SC_READY); + +			if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) +				bdp = bdbase; +			else +				bdp++; +		} +	} + +	/* +	 * Finally, Wait for transmitter & holding register to empty +	 *  and restore the IER +	 */ +	while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) +		; + +	pinfo->tx_cur = bdp; +} +#endif +  #ifdef CONFIG_CONSOLE_POLL  /* Serial polling routines for writing and reading from the uart while   * in an interrupt or debug context. @@ -999,7 +1076,7 @@ static void cpm_put_poll_char(struct uart_port *port,  	static char ch[2];  	ch[0] = (char)c; -	cpm_uart_early_write(pinfo->port.line, ch, 1); +	cpm_uart_early_write(pinfo, ch, 1);  }  #endif /* CONFIG_CONSOLE_POLL */ @@ -1130,9 +1207,6 @@ static void cpm_uart_console_write(struct console *co, const char *s,  				   u_int count)  {  	struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index]; -	unsigned int i; -	cbd_t __iomem *bdp, *bdbase; -	unsigned char *cp;  	unsigned long flags;  	int nolock = oops_in_progress; @@ -1142,66 +1216,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,  		spin_lock_irqsave(&pinfo->port.lock, flags);  	} -	/* Get the address of the host memory buffer. -	 */ -	bdp = pinfo->tx_cur; -	bdbase = pinfo->tx_bd_base; - -	/* -	 * Now, do each character.  This is not as bad as it looks -	 * since this is a holding FIFO and not a transmitting FIFO. -	 * We could add the complexity of filling the entire transmit -	 * buffer, but we would just wait longer between accesses...... -	 */ -	for (i = 0; i < count; i++, s++) { -		/* Wait for transmitter fifo to empty. -		 * Ready indicates output is ready, and xmt is doing -		 * that, not that it is ready for us to send. -		 */ -		while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) -			; - -		/* Send the character out. -		 * If the buffer address is in the CPM DPRAM, don't -		 * convert it. -		 */ -		cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo); -		*cp = *s; - -		out_be16(&bdp->cbd_datlen, 1); -		setbits16(&bdp->cbd_sc, BD_SC_READY); - -		if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) -			bdp = bdbase; -		else -			bdp++; - -		/* if a LF, also do CR... */ -		if (*s == 10) { -			while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) -				; - -			cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo); -			*cp = 13; - -			out_be16(&bdp->cbd_datlen, 1); -			setbits16(&bdp->cbd_sc, BD_SC_READY); - -			if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) -				bdp = bdbase; -			else -				bdp++; -		} -	} - -	/* -	 * Finally, Wait for transmitter & holding register to empty -	 *  and restore the IER -	 */ -	while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0) -		; - -	pinfo->tx_cur = bdp; +	cpm_uart_early_write(pinfo, s, count);  	if (unlikely(nolock)) {  		local_irq_restore(flags); diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 526307368f8..ab17c08ddc0 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -821,6 +821,7 @@ static struct pcmcia_device_id serial_ids[] = {  	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),  	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),  	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"), +	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),  	PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),  	PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),  	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"), diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c index ed7d958b0a0..544f2e25d0e 100644 --- a/drivers/serial/suncore.c +++ b/drivers/serial/suncore.c @@ -71,7 +71,9 @@ int sunserial_console_match(struct console *con, struct device_node *dp,  	con->index = line;  	drv->cons = con; -	add_preferred_console(con->name, line, NULL); + +	if (!console_set_on_cmdline) +		add_preferred_console(con->name, line, NULL);  	return 1;  } diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 234459c2f01..ffbf4553f66 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1500,20 +1500,25 @@ out_unmap:  static int __devexit su_remove(struct of_device *op)  {  	struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); +	bool kbdms = false;  	if (up->su_type == SU_PORT_MS || -	    up->su_type == SU_PORT_KBD) { +	    up->su_type == SU_PORT_KBD) +		kbdms = true; + +	if (kbdms) {  #ifdef CONFIG_SERIO  		serio_unregister_port(&up->serio);  #endif -		kfree(up); -	} else if (up->port.type != PORT_UNKNOWN) { +	} else if (up->port.type != PORT_UNKNOWN)  		uart_remove_one_port(&sunsu_reg, &up->port); -	}  	if (up->port.membase)  		of_iounmap(&op->resource[0], up->port.membase, up->reg_size); +	if (kbdms) +		kfree(up); +  	dev_set_drvdata(&op->dev, NULL);  	return 0; diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index ffa111a7e9d..97ab0a81338 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c @@ -66,28 +66,6 @@ struct mpc8xxx_spi_reg {  	__be32 receive;  }; -/* SPI Parameter RAM */ -struct spi_pram { -	__be16	rbase;	/* Rx Buffer descriptor base address */ -	__be16	tbase;	/* Tx Buffer descriptor base address */ -	u8	rfcr;	/* Rx function code */ -	u8	tfcr;	/* Tx function code */ -	__be16	mrblr;	/* Max receive buffer length */ -	__be32	rstate;	/* Internal */ -	__be32	rdp;	/* Internal */ -	__be16	rbptr;	/* Internal */ -	__be16	rbc;	/* Internal */ -	__be32	rxtmp;	/* Internal */ -	__be32	tstate;	/* Internal */ -	__be32	tdp;	/* Internal */ -	__be16	tbptr;	/* Internal */ -	__be16	tbc;	/* Internal */ -	__be32	txtmp;	/* Internal */ -	__be32	res;	/* Tx temp. */ -	__be16  rpbase;	/* Relocation pointer (CPM1 only) */ -	__be16	res1;	/* Reserved */ -}; -  /* SPI Controller mode register definitions */  #define	SPMODE_LOOP		(1 << 30)  #define	SPMODE_CI_INACTIVEHIGH	(1 << 29) diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index e2c000b80ca..212bc21e6d6 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -225,9 +225,9 @@ static struct bat_attribute *mesh_attrs[] = {  	NULL,  }; -static ssize_t transtable_local_read(struct kobject *kobj, -			       struct bin_attribute *bin_attr, -			       char *buff, loff_t off, size_t count) +static ssize_t transtable_local_read(struct file *filp, struct kobject *kobj, +				  struct bin_attribute *bin_attr, +				  char *buff, loff_t off, size_t count)  {  	struct device *dev = to_dev(kobj->parent);  	struct net_device *net_dev = to_net_dev(dev); @@ -235,9 +235,9 @@ static ssize_t transtable_local_read(struct kobject *kobj,  	return hna_local_fill_buffer_text(net_dev, buff, count, off);  } -static ssize_t transtable_global_read(struct kobject *kobj, -			       struct bin_attribute *bin_attr, -			       char *buff, loff_t off, size_t count) +static ssize_t transtable_global_read(struct file *filp, struct kobject *kobj, +				  struct bin_attribute *bin_attr, +				  char *buff, loff_t off, size_t count)  {  	struct device *dev = to_dev(kobj->parent);  	struct net_device *net_dev = to_net_dev(dev); @@ -245,9 +245,9 @@ static ssize_t transtable_global_read(struct kobject *kobj,  	return hna_global_fill_buffer_text(net_dev, buff, count, off);  } -static ssize_t originators_read(struct kobject *kobj, -			       struct bin_attribute *bin_attr, -			       char *buff, loff_t off, size_t count) +static ssize_t originators_read(struct file *filp, struct kobject *kobj, +				  struct bin_attribute *bin_attr, +				  char *buff, loff_t off, size_t count)  {  	struct device *dev = to_dev(kobj->parent);  	struct net_device *net_dev = to_net_dev(dev); @@ -255,9 +255,9 @@ static ssize_t originators_read(struct kobject *kobj,  	return orig_fill_buffer_text(net_dev, buff, count, off);  } -static ssize_t vis_data_read(struct kobject *kobj, -			     struct bin_attribute *bin_attr, -			     char *buff, loff_t off, size_t count) +static ssize_t vis_data_read(struct file *filp, struct kobject *kobj, +				  struct bin_attribute *bin_attr, +				  char *buff, loff_t off, size_t count)  {  	struct device *dev = to_dev(kobj->parent);  	struct net_device *net_dev = to_net_dev(dev); diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c index 7eb6559e031..32204b5572d 100644 --- a/drivers/staging/batman-adv/device.c +++ b/drivers/staging/batman-adv/device.c @@ -196,7 +196,7 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,  	kfree(device_packet);  	if (error) -		return error; +		return -EFAULT;  	return sizeof(struct icmp_packet);  } diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 36a254cd441..39d112b708e 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -824,9 +824,12 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,  		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,  					  false, true, true); -		dev_private->scan_delay = -		    (async_cmd->scan_begin_arg / (async_cmd->convert_arg * -						  async_cmd->chanlist_len)) - 1; +		if (async_cmd->scan_begin_src == TRIG_TIMER) { +			dev_private->scan_delay = +				(async_cmd->scan_begin_arg / +				 (async_cmd->convert_arg * +				  async_cmd->chanlist_len)) - 1; +		}  		break; diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 81829d6fd28..c374bee2506 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -52,7 +52,6 @@ Please report success/failure with other different cards to  #include "8255.h"  #define PCI_VENDOR_ID_CB	0x1307	/*  PCI vendor number of ComputerBoards */ -#define N_BOARDS	10	/*  Number of boards in cb_pcidda_boards */  #define EEPROM_SIZE	128	/*  number of entries in eeprom */  #define MAX_AO_CHANNELS 8	/*  maximum number of ao channels for supported boards */ @@ -307,7 +306,7 @@ static int cb_pcidda_attach(struct comedi_device *dev,  					continue;  				}  			} -			for (index = 0; index < N_BOARDS; index++) { +			for (index = 0; index < ARRAY_SIZE(cb_pcidda_boards); index++) {  				if (cb_pcidda_boards[index].device_id ==  				    pcidev->device) {  					goto found; diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index 3f53b4d1e4c..12db555a3a5 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -23,6 +23,7 @@  #include <linux/slab.h>  #include <linux/list.h>  #include <linux/module.h> +#include <linux/completion.h>  #include "osd.h"  #include "logging.h"  #include "vmbus_private.h" @@ -293,6 +294,25 @@ void FreeVmbusChannel(struct vmbus_channel *Channel)  			      Channel);  } + +DECLARE_COMPLETION(hv_channel_ready); + +/* + * Count initialized channels, and ensure all channels are ready when hv_vmbus + * module loading completes. + */ +static void count_hv_channel(void) +{ +	static int counter; +	unsigned long flags; + +	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags); +	if (++counter == MAX_MSG_TYPES) +		complete(&hv_channel_ready); +	spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags); +} + +  /*   * VmbusChannelProcessOffer - Process the offer by creating a channel/device   * associated with this offer @@ -373,22 +393,21 @@ static void VmbusChannelProcessOffer(void *context)  		 * can cleanup properly  		 */  		newChannel->State = CHANNEL_OPEN_STATE; -		cnt = 0; -		while (cnt != MAX_MSG_TYPES) { +		/* Open IC channels */ +		for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {  			if (memcmp(&newChannel->OfferMsg.Offer.InterfaceType,  				   &hv_cb_utils[cnt].data, -				   sizeof(struct hv_guid)) == 0) { +				   sizeof(struct hv_guid)) == 0 && +				VmbusChannelOpen(newChannel, 2 * PAGE_SIZE, +						 2 * PAGE_SIZE, NULL, 0, +						 hv_cb_utils[cnt].callback, +						 newChannel) == 0) { +				hv_cb_utils[cnt].channel = newChannel;  				DPRINT_INFO(VMBUS, "%s", -					    hv_cb_utils[cnt].log_msg); - -				if (VmbusChannelOpen(newChannel, 2 * PAGE_SIZE, -						    2 * PAGE_SIZE, NULL, 0, -						    hv_cb_utils[cnt].callback, -						    newChannel) == 0) -					hv_cb_utils[cnt].channel = newChannel; +						hv_cb_utils[cnt].log_msg); +				count_hv_channel();  			} -			cnt++;  		}  	}  	DPRINT_EXIT(VMBUS); diff --git a/drivers/staging/hv/hv_utils.c b/drivers/staging/hv/hv_utils.c index 8a49aafea37..2adc9b48ca9 100644 --- a/drivers/staging/hv/hv_utils.c +++ b/drivers/staging/hv/hv_utils.c @@ -24,6 +24,8 @@  #include <linux/slab.h>  #include <linux/sysctl.h>  #include <linux/reboot.h> +#include <linux/dmi.h> +#include <linux/pci.h>  #include "logging.h"  #include "osd.h" @@ -251,10 +253,36 @@ static void heartbeat_onchannelcallback(void *context)  	DPRINT_EXIT(VMBUS);  } +static const struct pci_device_id __initconst +hv_utils_pci_table[] __maybe_unused = { +	{ PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */ +	{ 0 } +}; +MODULE_DEVICE_TABLE(pci, hv_utils_pci_table); + + +static const struct dmi_system_id __initconst +hv_utils_dmi_table[] __maybe_unused  = { +	{ +		.ident = "Hyper-V", +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), +			DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"), +		}, +	}, +	{ }, +}; +MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table); + +  static int __init init_hyperv_utils(void)  {  	printk(KERN_INFO "Registering HyperV Utility Driver\n"); +	if (!dmi_check_system(hv_utils_dmi_table)) +		return -ENODEV; +  	hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback =  		&shutdown_onchannelcallback;  	hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback; diff --git a/drivers/staging/hv/vmbus.h b/drivers/staging/hv/vmbus.h index 0c6ee0f487f..3c14b2926e0 100644 --- a/drivers/staging/hv/vmbus.h +++ b/drivers/staging/hv/vmbus.h @@ -74,4 +74,6 @@ int vmbus_child_driver_register(struct driver_context *driver_ctx);  void vmbus_child_driver_unregister(struct driver_context *driver_ctx);  void vmbus_get_interface(struct vmbus_channel_interface *interface); +extern struct completion hv_channel_ready; +  #endif /* _VMBUS_H_ */ diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index c21731a12ca..22c80ece638 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -27,6 +27,7 @@  #include <linux/pci.h>  #include <linux/dmi.h>  #include <linux/slab.h> +#include <linux/completion.h>  #include "version_info.h"  #include "osd.h"  #include "logging.h" @@ -356,6 +357,8 @@ static int vmbus_bus_init(int (*drv_init)(struct hv_driver *drv))  	vmbus_drv_obj->GetChannelOffers(); +	wait_for_completion(&hv_channel_ready); +  cleanup:  	DPRINT_EXIT(VMBUS_DRV); diff --git a/drivers/staging/mrst-touchscreen/intel-mid-touch.c b/drivers/staging/mrst-touchscreen/intel-mid-touch.c index 1db00975a59..abba22f921b 100644 --- a/drivers/staging/mrst-touchscreen/intel-mid-touch.c +++ b/drivers/staging/mrst-touchscreen/intel-mid-touch.c @@ -817,9 +817,9 @@ static int mrstouch_remove(struct spi_device *spi)  	free_irq(mrstouchdevp->irq, mrstouchdevp);  	input_unregister_device(mrstouchdevp->input);  	input_free_device(mrstouchdevp->input); -	kfree(mrstouchdevp);  	if (mrstouchdevp->pendet_thrd)  		kthread_stop(mrstouchdevp->pendet_thrd); +	kfree(mrstouchdevp);  	return 0;  } diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c index b740662d095..674769d2b59 100644 --- a/drivers/staging/rt2860/usb_main_dev.c +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -77,6 +77,7 @@ struct usb_device_id rtusb_usb_id[] = {  	{USB_DEVICE(0x083A, 0x7522)},	/* Arcadyan */  	{USB_DEVICE(0x0CDE, 0x0022)},	/* ZCOM */  	{USB_DEVICE(0x0586, 0x3416)},	/* Zyxel */ +	{USB_DEVICE(0x0586, 0x341a)},	/* Zyxel NWD-270N */  	{USB_DEVICE(0x0CDE, 0x0025)},	/* Zyxel */  	{USB_DEVICE(0x1740, 0x9701)},	/* EnGenius */  	{USB_DEVICE(0x1740, 0x9702)},	/* EnGenius */ diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index dacefea7811..49ab9fa9ffa 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -66,8 +66,6 @@ static int hwseqnum = 0;  static int hwwep = 0;  static int channels = 0x3fff; -#define eqMacAddr(a, b)		(((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1 : 0) -#define cpMacAddr(des, src)		((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5])  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl);  MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 447d6474a70..1b6890611fb 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -112,28 +112,29 @@ u32 rt_global_debug_component = \  #define CAM_CONTENT_COUNT 8  static const struct usb_device_id rtl8192_usb_id_tbl[] = { -	/* Realtek */ -	{USB_DEVICE(0x0bda, 0x8171)}, -	{USB_DEVICE(0x0bda, 0x8192)}, -	{USB_DEVICE(0x0bda, 0x8709)}, -	/* Corega */ -	{USB_DEVICE(0x07aa, 0x0043)}, -	/* Belkin */ -	{USB_DEVICE(0x050d, 0x805E)}, -	{USB_DEVICE(0x050d, 0x815F)}, /* Belkin F5D8053 v6 */ -	/* Sitecom */ -	{USB_DEVICE(0x0df6, 0x0031)}, -	{USB_DEVICE(0x0df6, 0x004b)},	/* WL-349 */ -	/* EnGenius */ -	{USB_DEVICE(0x1740, 0x9201)}, -	/* Dlink */ -	{USB_DEVICE(0x2001, 0x3301)}, -	/* Zinwell */ -	{USB_DEVICE(0x5a57, 0x0290)}, -	/* Guillemot */ -	{USB_DEVICE(0x06f8, 0xe031)}, -	//92SU +	{USB_DEVICE(0x0bda, 0x8171)}, /* Realtek */  	{USB_DEVICE(0x0bda, 0x8172)}, +	{USB_DEVICE(0x0bda, 0x8173)}, +	{USB_DEVICE(0x0bda, 0x8174)}, +	{USB_DEVICE(0x0bda, 0x8712)}, +	{USB_DEVICE(0x0bda, 0x8713)}, +	{USB_DEVICE(0x07aa, 0x0047)}, +	{USB_DEVICE(0x07d1, 0x3303)}, +	{USB_DEVICE(0x07d1, 0x3302)}, +	{USB_DEVICE(0x07d1, 0x3300)}, +	{USB_DEVICE(0x1740, 0x9603)}, +	{USB_DEVICE(0x1740, 0x9605)}, +	{USB_DEVICE(0x050d, 0x815F)}, +	{USB_DEVICE(0x06f8, 0xe031)}, +	{USB_DEVICE(0x7392, 0x7611)}, +	{USB_DEVICE(0x7392, 0x7612)}, +	{USB_DEVICE(0x7392, 0x7622)}, +	{USB_DEVICE(0x0DF6, 0x0045)}, +	{USB_DEVICE(0x0E66, 0x0015)}, +	{USB_DEVICE(0x0E66, 0x0016)}, +	{USB_DEVICE(0x0b05, 0x1786)}, +	/* these are not in the official list */ +	{USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */  	{}  }; diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 2bede271a2f..f38472c2e75 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -121,6 +121,8 @@ static const struct usb_device_id rtl8192_usb_id_tbl[] = {  	{USB_DEVICE(0x2001, 0x3301)},  	/* Zinwell */  	{USB_DEVICE(0x5a57, 0x0290)}, +	/* LG */ +	{USB_DEVICE(0x043e, 0x7a01)},  	{}  }; diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/staging/tm6000/tm6000-alsa.c index ce081cd44ad..273e26ede65 100644 --- a/drivers/staging/tm6000/tm6000-alsa.c +++ b/drivers/staging/tm6000/tm6000-alsa.c @@ -15,6 +15,7 @@  #include <linux/device.h>  #include <linux/interrupt.h>  #include <linux/usb.h> +#include <linux/slab.h>  #include <asm/delay.h>  #include <sound/core.h> diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c index cedd9044022..6a9ae40c7c6 100644 --- a/drivers/staging/tm6000/tm6000-cards.c +++ b/drivers/staging/tm6000/tm6000-cards.c @@ -24,6 +24,7 @@  #include <linux/i2c.h>  #include <linux/usb.h>  #include <linux/version.h> +#include <linux/slab.h>  #include <media/v4l2-common.h>  #include <media/tuner.h>  #include <media/tvaudio.h> diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c index 27f3f551b54..c3690e3580d 100644 --- a/drivers/staging/tm6000/tm6000-core.c +++ b/drivers/staging/tm6000/tm6000-core.c @@ -22,6 +22,7 @@  #include <linux/module.h>  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/usb.h>  #include <linux/i2c.h>  #include "tm6000.h" diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c index 261e66acbe4..86c1c8b5f25 100644 --- a/drivers/staging/tm6000/tm6000-dvb.c +++ b/drivers/staging/tm6000/tm6000-dvb.c @@ -18,6 +18,7 @@   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/usb.h>  #include "tm6000.h" diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index 52408164036..6a499f0eb59 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -378,47 +378,67 @@ int usbip_thread(void *param)  	complete_and_exit(&ut->thread_done, 0);  } +static void stop_rx_thread(struct usbip_device *ud) +{ +	if (ud->tcp_rx.thread != NULL) { +		send_sig(SIGKILL, ud->tcp_rx.thread, 1); +		wait_for_completion(&ud->tcp_rx.thread_done); +		usbip_udbg("rx_thread for ud %p has finished\n", ud); +	} +} + +static void stop_tx_thread(struct usbip_device *ud) +{ +	if (ud->tcp_tx.thread != NULL) { +		send_sig(SIGKILL, ud->tcp_tx.thread, 1); +		wait_for_completion(&ud->tcp_tx.thread_done); +		usbip_udbg("tx_thread for ud %p has finished\n", ud); +	} +} +  int usbip_start_threads(struct usbip_device *ud)  {  	/*  	 * threads are invoked per one device (per one connection).  	 */  	struct task_struct *th; +	int err = 0;  	th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip");  	if (IS_ERR(th)) {  		printk(KERN_WARNING  			"Unable to start control thread\n"); -		return PTR_ERR(th); +		err = PTR_ERR(th); +		goto ust_exit;  	} +  	th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip");  	if (IS_ERR(th)) {  		printk(KERN_WARNING  			"Unable to start control thread\n"); -		return PTR_ERR(th); +		err = PTR_ERR(th); +		goto tx_thread_err;  	}  	/* confirm threads are starting */  	wait_for_completion(&ud->tcp_rx.thread_done);  	wait_for_completion(&ud->tcp_tx.thread_done); +  	return 0; + +tx_thread_err: +	stop_rx_thread(ud); + +ust_exit: +	return err;  }  EXPORT_SYMBOL_GPL(usbip_start_threads);  void usbip_stop_threads(struct usbip_device *ud)  {  	/* kill threads related to this sdev, if v.c. exists */ -	if (ud->tcp_rx.thread != NULL) { -		send_sig(SIGKILL, ud->tcp_rx.thread, 1); -		wait_for_completion(&ud->tcp_rx.thread_done); -		usbip_udbg("rx_thread for ud %p has finished\n", ud); -	} - -	if (ud->tcp_tx.thread != NULL) { -		send_sig(SIGKILL, ud->tcp_tx.thread, 1); -		wait_for_completion(&ud->tcp_tx.thread_done); -		usbip_udbg("tx_thread for ud %p has finished\n", ud); -	} +	stop_rx_thread(ud); +	stop_tx_thread(ud);  }  EXPORT_SYMBOL_GPL(usbip_stop_threads); diff --git a/drivers/staging/wlags49_h2/wl_enc.c b/drivers/staging/wlags49_h2/wl_enc.c index 48c44c8fdb2..26cf5486edd 100644 --- a/drivers/staging/wlags49_h2/wl_enc.c +++ b/drivers/staging/wlags49_h2/wl_enc.c @@ -62,6 +62,7 @@  /*******************************************************************************   *  include files   ******************************************************************************/ +#include <linux/string.h>  #include <wl_version.h>  #include <debug.h> diff --git a/drivers/staging/wlags49_h2/wl_sysfs.h b/drivers/staging/wlags49_h2/wl_sysfs.h index 6d96d03cf49..fa658c38001 100644 --- a/drivers/staging/wlags49_h2/wl_sysfs.h +++ b/drivers/staging/wlags49_h2/wl_sysfs.h @@ -2,6 +2,6 @@  extern void register_wlags_sysfs(struct net_device *);  extern void unregister_wlags_sysfs(struct net_device *);  #else -static void register_wlags_sysfs(struct net_device *) { return; }; -static void unregister_wlags_sysfs(struct net_device *) { return; }; +static inline void register_wlags_sysfs(struct net_device *net) { } +static inline void unregister_wlags_sysfs(struct net_device *net) { }  #endif diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 8413a567c12..89d260d6b03 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1596,6 +1596,7 @@ static const struct usb_device_id acm_ids[] = {  	{ NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */  	{ NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */  	{ NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */ +	{ NOKIA_PCSUITE_ACM_INFO(0x02e3), }, /* Nokia 5230, RM-588 */  	/* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index de98a94d185..a6bd53ace03 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1272,8 +1272,7 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)  static void choose_wakeup(struct usb_device *udev, pm_message_t msg)  { -	int			w, i; -	struct usb_interface	*intf; +	int	w;  	/* Remote wakeup is needed only when we actually go to sleep.  	 * For things like FREEZE and QUIESCE, if the device is already @@ -1285,16 +1284,10 @@ static void choose_wakeup(struct usb_device *udev, pm_message_t msg)  		return;  	} -	/* If remote wakeup is permitted, see whether any interface drivers +	/* Enable remote wakeup if it is allowed, even if no interface drivers  	 * actually want it.  	 */ -	w = 0; -	if (device_may_wakeup(&udev->dev) && udev->actconfig) { -		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { -			intf = udev->actconfig->interface[i]; -			w |= intf->needs_remote_wakeup; -		} -	} +	w = device_may_wakeup(&udev->dev);  	/* If the device is autosuspended with the wrong wakeup setting,  	 * autoresume now so the setting can be changed. diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 83e7bbbe97f..70cccc75a36 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1982,6 +1982,8 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,  		    (portstatus & USB_PORT_STAT_ENABLE)) {  			if (hub_is_wusb(hub))  				udev->speed = USB_SPEED_WIRELESS; +			else if (portstatus & USB_PORT_STAT_SUPER_SPEED) +				udev->speed = USB_SPEED_SUPER;  			else if (portstatus & USB_PORT_STAT_HIGH_SPEED)  				udev->speed = USB_SPEED_HIGH;  			else if (portstatus & USB_PORT_STAT_LOW_SPEED) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index a73e08fdab3..fd4c36ea5e4 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -416,8 +416,11 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,  			/* A length of zero means transfer the whole sg list */  			len = length;  			if (len == 0) { -				for_each_sg(sg, sg, nents, i) -					len += sg->length; +				struct scatterlist	*sg2; +				int			j; + +				for_each_sg(sg, sg2, nents, j) +					len += sg2->length;  			}  		} else {  			/* diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index f22d03df8b1..db99c084df9 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -41,6 +41,10 @@ static const struct usb_device_id usb_quirk_list[] = {  	/* Philips PSC805 audio device */  	{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, +	/* Artisman Watchdog Dongle */ +	{ USB_DEVICE(0x04b4, 0x0526), .driver_info = +			USB_QUIRK_CONFIG_INTF_STRINGS }, +  	/* Roland SC-8820 */  	{ USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME }, @@ -64,6 +68,9 @@ static const struct usb_device_id usb_quirk_list[] = {  	/* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */  	{ USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF }, +	/* Broadcom BCM92035DGROM BT dongle */ +	{ USB_DEVICE(0x0a5c, 0x2021), .driver_info = USB_QUIRK_RESET_RESUME }, +  	/* Action Semiconductor flash disk */  	{ USB_DEVICE(0x10d6, 0x2200), .driver_info =  			USB_QUIRK_STRING_FETCH_255 }, diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index eaa79c8a9b8..93ead19507b 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -76,11 +76,12 @@  static const char driver_name [] = "at91_udc";  static const char ep0name[] = "ep0"; +#define VBUS_POLL_TIMEOUT	msecs_to_jiffies(1000) -#define at91_udp_read(dev, reg) \ -	__raw_readl((dev)->udp_baseaddr + (reg)) -#define at91_udp_write(dev, reg, val) \ -	__raw_writel((val), (dev)->udp_baseaddr + (reg)) +#define at91_udp_read(udc, reg) \ +	__raw_readl((udc)->udp_baseaddr + (reg)) +#define at91_udp_write(udc, reg, val) \ +	__raw_writel((val), (udc)->udp_baseaddr + (reg))  /*-------------------------------------------------------------------------*/ @@ -102,8 +103,9 @@ static void proc_ep_show(struct seq_file *s, struct at91_ep *ep)  	u32			csr;  	struct at91_request	*req;  	unsigned long	flags; +	struct at91_udc	*udc = ep->udc; -	local_irq_save(flags); +	spin_lock_irqsave(&udc->lock, flags);  	csr = __raw_readl(ep->creg); @@ -147,7 +149,7 @@ static void proc_ep_show(struct seq_file *s, struct at91_ep *ep)  				&req->req, length,  				req->req.length, req->req.buf);  	} -	local_irq_restore(flags); +	spin_unlock_irqrestore(&udc->lock, flags);  }  static void proc_irq_show(struct seq_file *s, const char *label, u32 mask) @@ -272,7 +274,9 @@ static void done(struct at91_ep *ep, struct at91_request *req, int status)  		VDBG("%s done %p, status %d\n", ep->ep.name, req, status);  	ep->stopped = 1; +	spin_unlock(&udc->lock);  	req->req.complete(&ep->ep, &req->req); +	spin_lock(&udc->lock);  	ep->stopped = stopped;  	/* ep0 is always ready; other endpoints need a non-empty queue */ @@ -472,7 +476,7 @@ static int at91_ep_enable(struct usb_ep *_ep,  				const struct usb_endpoint_descriptor *desc)  {  	struct at91_ep	*ep = container_of(_ep, struct at91_ep, ep); -	struct at91_udc	*dev = ep->udc; +	struct at91_udc	*udc = ep->udc;  	u16		maxpacket;  	u32		tmp;  	unsigned long	flags; @@ -487,7 +491,7 @@ static int at91_ep_enable(struct usb_ep *_ep,  		return -EINVAL;  	} -	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { +	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {  		DBG("bogus device state\n");  		return -ESHUTDOWN;  	} @@ -521,7 +525,7 @@ bogus_max:  	}  ok: -	local_irq_save(flags); +	spin_lock_irqsave(&udc->lock, flags);  	/* initialize endpoint to match this descriptor */  	ep->is_in = usb_endpoint_dir_in(desc); @@ -540,10 +544,10 @@ ok:  	 * reset/init endpoint fifo.  NOTE:  leaves fifo_bank alone,  	 * since endpoint resets don't reset hw pingpong state.  	 */ -	at91_udp_write(dev, AT91_UDP_RST_EP, ep->int_mask); -	at91_udp_write(dev, AT91_UDP_RST_EP, 0); +	at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask); +	at91_udp_write(udc, AT91_UDP_RST_EP, 0); -	local_irq_restore(flags); +	spin_unlock_irqrestore(&udc->lock, flags);  	return 0;  } @@ -556,7 +560,7 @@ static int at91_ep_disable (struct usb_ep * _ep)  	if (ep == &ep->udc->ep[0])  		return -EINVAL; -	local_irq_save(flags); +	spin_lock_irqsave(&udc->lock, flags);  	nuke(ep, -ESHUTDOWN); @@ -571,7 +575,7 @@ static int at91_ep_disable (struct usb_ep * _ep)  		__raw_writel(0, ep->creg);  	} -	local_irq_restore(flags); +	spin_unlock_irqrestore(&udc->lock, flags);  	return 0;  } @@ -607,7 +611,7 @@ static int at91_ep_queue(struct usb_ep *_ep,  {  	struct at91_request	*req;  	struct at91_ep		*ep; -	struct at91_udc		*dev; +	struct at91_udc		*udc;  	int			status;  	unsigned long		flags; @@ -625,9 +629,9 @@ static int at91_ep_queue(struct usb_ep *_ep,  		return -EINVAL;  	} -	dev = ep->udc; +	udc = ep->udc; -	if (!dev || !dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { +	if (!udc || !udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {  		DBG("invalid device\n");  		return -EINVAL;  	} @@ -635,7 +639,7 @@ static int at91_ep_queue(struct usb_ep *_ep,  	_req->status = -EINPROGRESS;  	_req->actual = 0; -	local_irq_save(flags); +	spin_lock_irqsave(&udc->lock, flags);  	/* try to kickstart any empty and idle queue */  	if (list_empty(&ep->queue) && !ep->stopped) { @@ -653,7 +657,7 @@ static int at91_ep_queue(struct usb_ep *_ep,  		if (is_ep0) {  			u32	tmp; -			if (!dev->req_pending) { +			if (!udc->req_pending) {  				status = -EINVAL;  				goto done;  			} @@ -662,11 +666,11 @@ static int at91_ep_queue(struct usb_ep *_ep,  			 * defer changing CONFG until after the gadget driver  			 * reconfigures the endpoints.  			 */ -			if (dev->wait_for_config_ack) { -				tmp = at91_udp_read(dev, AT91_UDP_GLB_STAT); +			if (udc->wait_for_config_ack) { +				tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);  				tmp ^= AT91_UDP_CONFG;  				VDBG("toggle config\n"); -				at91_udp_write(dev, AT91_UDP_GLB_STAT, tmp); +				at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);  			}  			if (req->req.length == 0) {  ep0_in_status: @@ -676,7 +680,7 @@ ep0_in_status:  				tmp &= ~SET_FX;  				tmp |= CLR_FX | AT91_UDP_TXPKTRDY;  				__raw_writel(tmp, ep->creg); -				dev->req_pending = 0; +				udc->req_pending = 0;  				goto done;  			}  		} @@ -695,31 +699,40 @@ ep0_in_status:  	if (req && !status) {  		list_add_tail (&req->queue, &ep->queue); -		at91_udp_write(dev, AT91_UDP_IER, ep->int_mask); +		at91_udp_write(udc, AT91_UDP_IER, ep->int_mask);  	}  done: -	local_irq_restore(flags); +	spin_unlock_irqrestore(&udc->lock, flags);  	return (status < 0) ? status : 0;  }  static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)  { -	struct at91_ep	*ep; +	struct at91_ep		*ep;  	struct at91_request	*req; +	unsigned long		flags; +	struct at91_udc		*udc;  	ep = container_of(_ep, struct at91_ep, ep);  	if (!_ep || ep->ep.name == ep0name)  		return -EINVAL; +	udc = ep->udc; + +	spin_lock_irqsave(&udc->lock, flags); +  	/* make sure it's actually queued on this endpoint */  	list_for_each_entry (req, &ep->queue, queue) {  		if (&req->req == _req)  			break;  	} -	if (&req->req != _req) +	if (&req->req != _req) { +		spin_unlock_irqrestore(&udc->lock, flags);  		return -EINVAL; +	}  	done(ep, req, -ECONNRESET); +	spin_unlock_irqrestore(&udc->lock, flags);  	return 0;  } @@ -736,7 +749,7 @@ static int at91_ep_set_halt(struct usb_ep *_ep, int value)  		return -EINVAL;  	creg = ep->creg; -	local_irq_save(flags); +	spin_lock_irqsave(&udc->lock, flags);  	csr = __raw_readl(creg); @@ -761,7 +774,7 @@ static int at91_ep_set_halt(struct usb_ep *_ep, int value)  		__raw_writel(csr, creg);  	} -	local_irq_restore(flags); +	spin_unlock_irqrestore(&udc->lock, flags);  	return status;  } @@ -795,7 +808,7 @@ static int at91_wakeup(struct usb_gadget *gadget)  	unsigned long	flags;  	DBG("%s\n", __func__ ); -	local_irq_save(flags); +	spin_lock_irqsave(&udc->lock, flags);  	if (!udc->clocked || !udc->suspended)  		goto done; @@ -809,7 +822,7 @@ static int at91_wakeup(struct usb_gadget *gadget)  	at91_udp_write(udc, AT91_UDP_GLB_STAT, glbstate);  done: -	local_irq_restore(flags); +	spin_unlock_irqrestore(&udc->lock, flags);  	return status;  } @@ -851,8 +864,11 @@ static void stop_activity(struct at91_udc *udc)  		ep->stopped = 1;  		nuke(ep, -ESHUTDOWN);  	} -	if (driver) +	if (driver) { +		spin_unlock(&udc->lock);  		driver->disconnect(&udc->gadget); +		spin_lock(&udc->lock); +	}  	udc_reinit(udc);  } @@ -935,13 +951,13 @@ static int at91_vbus_session(struct usb_gadget *gadget, int is_active)  	unsigned long	flags;  	// VDBG("vbus %s\n", is_active ? "on" : "off"); -	local_irq_save(flags); +	spin_lock_irqsave(&udc->lock, flags);  	udc->vbus = (is_active != 0);  	if (udc->driver)  		pullup(udc, is_active);  	else  		pullup(udc, 0); -	local_irq_restore(flags); +	spin_unlock_irqrestore(&udc->lock, flags);  	return 0;  } @@ -950,10 +966,10 @@ static int at91_pullup(struct usb_gadget *gadget, int is_on)  	struct at91_udc	*udc = to_udc(gadget);  	unsigned long	flags; -	local_irq_save(flags); +	spin_lock_irqsave(&udc->lock, flags);  	udc->enabled = is_on = !!is_on;  	pullup(udc, is_on); -	local_irq_restore(flags); +	spin_unlock_irqrestore(&udc->lock, flags);  	return 0;  } @@ -962,9 +978,9 @@ static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on)  	struct at91_udc	*udc = to_udc(gadget);  	unsigned long	flags; -	local_irq_save(flags); +	spin_lock_irqsave(&udc->lock, flags);  	udc->selfpowered = (is_on != 0); -	local_irq_restore(flags); +	spin_unlock_irqrestore(&udc->lock, flags);  	return 0;  } @@ -1226,8 +1242,11 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)  #undef w_length  	/* pass request up to the gadget driver */ -	if (udc->driver) +	if (udc->driver) { +		spin_unlock(&udc->lock);  		status = udc->driver->setup(&udc->gadget, &pkt.r); +		spin_lock(&udc->lock); +	}  	else  		status = -ENODEV;  	if (status < 0) { @@ -1378,6 +1397,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)  	struct at91_udc		*udc = _udc;  	u32			rescans = 5;  	int			disable_clock = 0; +	unsigned long		flags; + +	spin_lock_irqsave(&udc->lock, flags);  	if (!udc->clocked) {  		clk_on(udc); @@ -1433,8 +1455,11 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)  			 * and then into standby to avoid drawing more than  			 * 500uA power (2500uA for some high-power configs).  			 */ -			if (udc->driver && udc->driver->suspend) +			if (udc->driver && udc->driver->suspend) { +				spin_unlock(&udc->lock);  				udc->driver->suspend(&udc->gadget); +				spin_lock(&udc->lock); +			}  		/* host initiated resume */  		} else if (status & AT91_UDP_RXRSM) { @@ -1451,8 +1476,11 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)  			 * would normally want to switch out of slow clock  			 * mode into normal mode.  			 */ -			if (udc->driver && udc->driver->resume) +			if (udc->driver && udc->driver->resume) { +				spin_unlock(&udc->lock);  				udc->driver->resume(&udc->gadget); +				spin_lock(&udc->lock); +			}  		/* endpoint IRQs are cleared by handling them */  		} else { @@ -1474,6 +1502,8 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)  	if (disable_clock)  		clk_off(udc); +	spin_unlock_irqrestore(&udc->lock, flags); +  	return IRQ_HANDLED;  } @@ -1556,24 +1586,53 @@ static struct at91_udc controller = {  	/* ep6 and ep7 are also reserved (custom silicon might use them) */  }; +static void at91_vbus_update(struct at91_udc *udc, unsigned value) +{ +	value ^= udc->board.vbus_active_low; +	if (value != udc->vbus) +		at91_vbus_session(&udc->gadget, value); +} +  static irqreturn_t at91_vbus_irq(int irq, void *_udc)  {  	struct at91_udc	*udc = _udc; -	unsigned	value;  	/* vbus needs at least brief debouncing */  	udelay(10); -	value = gpio_get_value(udc->board.vbus_pin); -	if (value != udc->vbus) -		at91_vbus_session(&udc->gadget, value); +	at91_vbus_update(udc, gpio_get_value(udc->board.vbus_pin));  	return IRQ_HANDLED;  } +static void at91_vbus_timer_work(struct work_struct *work) +{ +	struct at91_udc *udc = container_of(work, struct at91_udc, +					    vbus_timer_work); + +	at91_vbus_update(udc, gpio_get_value_cansleep(udc->board.vbus_pin)); + +	if (!timer_pending(&udc->vbus_timer)) +		mod_timer(&udc->vbus_timer, jiffies + VBUS_POLL_TIMEOUT); +} + +static void at91_vbus_timer(unsigned long data) +{ +	struct at91_udc *udc = (struct at91_udc *)data; + +	/* +	 * If we are polling vbus it is likely that the gpio is on an +	 * bus such as i2c or spi which may sleep, so schedule some work +	 * to read the vbus gpio +	 */ +	if (!work_pending(&udc->vbus_timer_work)) +		schedule_work(&udc->vbus_timer_work); +} +  int usb_gadget_register_driver (struct usb_gadget_driver *driver)  {  	struct at91_udc	*udc = &controller;  	int		retval; +	unsigned long	flags;  	if (!driver  			|| driver->speed < USB_SPEED_FULL @@ -1605,9 +1664,9 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)  		return retval;  	} -	local_irq_disable(); +	spin_lock_irqsave(&udc->lock, flags);  	pullup(udc, 1); -	local_irq_enable(); +	spin_unlock_irqrestore(&udc->lock, flags);  	DBG("bound to %s\n", driver->driver.name);  	return 0; @@ -1617,15 +1676,16 @@ EXPORT_SYMBOL (usb_gadget_register_driver);  int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)  {  	struct at91_udc *udc = &controller; +	unsigned long	flags;  	if (!driver || driver != udc->driver || !driver->unbind)  		return -EINVAL; -	local_irq_disable(); +	spin_lock_irqsave(&udc->lock, flags);  	udc->enabled = 0;  	at91_udp_write(udc, AT91_UDP_IDR, ~0);  	pullup(udc, 0); -	local_irq_enable(); +	spin_unlock_irqrestore(&udc->lock, flags);  	driver->unbind(&udc->gadget);  	udc->gadget.dev.driver = NULL; @@ -1641,8 +1701,13 @@ EXPORT_SYMBOL (usb_gadget_unregister_driver);  static void at91udc_shutdown(struct platform_device *dev)  { +	struct at91_udc *udc = platform_get_drvdata(dev); +	unsigned long	flags; +  	/* force disconnect on reboot */ +	spin_lock_irqsave(&udc->lock, flags);  	pullup(platform_get_drvdata(dev), 0); +	spin_unlock_irqrestore(&udc->lock, flags);  }  static int __init at91udc_probe(struct platform_device *pdev) @@ -1683,6 +1748,7 @@ static int __init at91udc_probe(struct platform_device *pdev)  	udc->board = *(struct at91_udc_data *) dev->platform_data;  	udc->pdev = pdev;  	udc->enabled = 0; +	spin_lock_init(&udc->lock);  	/* rm9200 needs manual D+ pullup; off by default */  	if (cpu_is_at91rm9200()) { @@ -1763,13 +1829,23 @@ static int __init at91udc_probe(struct platform_device *pdev)  		 * Get the initial state of VBUS - we cannot expect  		 * a pending interrupt.  		 */ -		udc->vbus = gpio_get_value(udc->board.vbus_pin); -		if (request_irq(udc->board.vbus_pin, at91_vbus_irq, -				IRQF_DISABLED, driver_name, udc)) { -			DBG("request vbus irq %d failed\n", -					udc->board.vbus_pin); -			retval = -EBUSY; -			goto fail3; +		udc->vbus = gpio_get_value_cansleep(udc->board.vbus_pin) ^ +			udc->board.vbus_active_low; + +		if (udc->board.vbus_polled) { +			INIT_WORK(&udc->vbus_timer_work, at91_vbus_timer_work); +			setup_timer(&udc->vbus_timer, at91_vbus_timer, +				    (unsigned long)udc); +			mod_timer(&udc->vbus_timer, +				  jiffies + VBUS_POLL_TIMEOUT); +		} else { +			if (request_irq(udc->board.vbus_pin, at91_vbus_irq, +					IRQF_DISABLED, driver_name, udc)) { +				DBG("request vbus irq %d failed\n", +				    udc->board.vbus_pin); +				retval = -EBUSY; +				goto fail3; +			}  		}  	} else {  		DBG("no VBUS detection, assuming always-on\n"); @@ -1804,13 +1880,16 @@ static int __exit at91udc_remove(struct platform_device *pdev)  {  	struct at91_udc *udc = platform_get_drvdata(pdev);  	struct resource *res; +	unsigned long	flags;  	DBG("remove\n");  	if (udc->driver)  		return -EBUSY; +	spin_lock_irqsave(&udc->lock, flags);  	pullup(udc, 0); +	spin_unlock_irqrestore(&udc->lock, flags);  	device_init_wakeup(&pdev->dev, 0);  	remove_debug_file(udc); @@ -1840,6 +1919,7 @@ static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg)  {  	struct at91_udc *udc = platform_get_drvdata(pdev);  	int		wake = udc->driver && device_may_wakeup(&pdev->dev); +	unsigned long	flags;  	/* Unless we can act normally to the host (letting it wake us up  	 * whenever it has work for us) force disconnect.  Wakeup requires @@ -1849,13 +1929,15 @@ static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg)  	if ((!udc->suspended && udc->addr)  			|| !wake  			|| at91_suspend_entering_slow_clock()) { +		spin_lock_irqsave(&udc->lock, flags);  		pullup(udc, 0);  		wake = 0; +		spin_unlock_irqrestore(&udc->lock, flags);  	} else  		enable_irq_wake(udc->udp_irq);  	udc->active_suspend = wake; -	if (udc->board.vbus_pin > 0 && wake) +	if (udc->board.vbus_pin > 0 && !udc->board.vbus_polled && wake)  		enable_irq_wake(udc->board.vbus_pin);  	return 0;  } @@ -1863,15 +1945,20 @@ static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg)  static int at91udc_resume(struct platform_device *pdev)  {  	struct at91_udc *udc = platform_get_drvdata(pdev); +	unsigned long	flags; -	if (udc->board.vbus_pin > 0 && udc->active_suspend) +	if (udc->board.vbus_pin > 0 && !udc->board.vbus_polled && +	    udc->active_suspend)  		disable_irq_wake(udc->board.vbus_pin);  	/* maybe reconnect to host; if so, clocks on */  	if (udc->active_suspend)  		disable_irq_wake(udc->udp_irq); -	else +	else { +		spin_lock_irqsave(&udc->lock, flags);  		pullup(udc, 1); +		spin_unlock_irqrestore(&udc->lock, flags); +	}  	return 0;  }  #else diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h index c65d6229589..108ca54f909 100644 --- a/drivers/usb/gadget/at91_udc.h +++ b/drivers/usb/gadget/at91_udc.h @@ -144,6 +144,9 @@ struct at91_udc {  	struct proc_dir_entry		*pde;  	void __iomem			*udp_baseaddr;  	int				udp_irq; +	spinlock_t			lock; +	struct timer_list		vbus_timer; +	struct work_struct		vbus_timer_work;  };  static inline struct at91_udc *to_udc(struct usb_gadget *g) diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index 38226e9a371..95dd4662d6a 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c @@ -469,8 +469,7 @@ static int eem_unwrap(struct gether *port,  				crc = get_unaligned_le32(skb->data + len  							- ETH_FCS_LEN);  				crc2 = ~crc32_le(~0, -						skb->data, -						skb->len - ETH_FCS_LEN); +						skb->data, len - ETH_FCS_LEN);  			} else {  				crc = get_unaligned_be32(skb->data + len  							- ETH_FCS_LEN); diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index d69eccf5f19..2aaa0f75c6c 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -136,7 +136,7 @@ struct ffs_data {  	 * handling setup requests immidiatelly user space may be so  	 * slow that another setup will be sent to the gadget but this  	 * time not to us but another function and then there could be -	 * a race.  Is taht the case? Or maybe we can use cdev->req +	 * a race.  Is that the case? Or maybe we can use cdev->req  	 * after all, maybe we just need some spinlock for that? */  	struct usb_request		*ep0req;		/* P: mutex */  	struct completion		ep0req_completion;	/* P: mutex */ diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 7d05a0be5c6..4ce899c9b16 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -321,8 +321,8 @@ struct fsg_dev;  /* Data shared by all the FSG instances. */  struct fsg_common {  	struct usb_gadget	*gadget; -	struct fsg_dev		*fsg; -	struct fsg_dev		*prev_fsg; +	struct fsg_dev		*fsg, *new_fsg; +	wait_queue_head_t	fsg_wait;  	/* filesem protects: backing files in use */  	struct rw_semaphore	filesem; @@ -351,7 +351,6 @@ struct fsg_common {  	enum fsg_state		state;		/* For exception handling */  	unsigned int		exception_req_tag; -	u8			config, new_config;  	enum data_direction	data_dir;  	u32			data_size;  	u32			data_size_from_cmnd; @@ -595,7 +594,7 @@ static int fsg_setup(struct usb_function *f,  	u16			w_value = le16_to_cpu(ctrl->wValue);  	u16			w_length = le16_to_cpu(ctrl->wLength); -	if (!fsg->common->config) +	if (!fsg_is_set(fsg->common))  		return -EOPNOTSUPP;  	switch (ctrl->bRequest) { @@ -2303,24 +2302,20 @@ static int alloc_request(struct fsg_common *common, struct usb_ep *ep,  	return -ENOMEM;  } -/* - * Reset interface setting and re-init endpoint state (toggle etc). - * Call with altsetting < 0 to disable the interface.  The only other - * available altsetting is 0, which enables the interface. - */ -static int do_set_interface(struct fsg_common *common, int altsetting) +/* Reset interface setting and re-init endpoint state (toggle etc). */ +static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)  { -	int	rc = 0; -	int	i; -	const struct usb_endpoint_descriptor	*d; +	const struct usb_endpoint_descriptor *d; +	struct fsg_dev *fsg; +	int i, rc = 0;  	if (common->running)  		DBG(common, "reset interface\n");  reset:  	/* Deallocate the requests */ -	if (common->prev_fsg) { -		struct fsg_dev *fsg = common->prev_fsg; +	if (common->fsg) { +		fsg = common->fsg;  		for (i = 0; i < FSG_NUM_BUFFERS; ++i) {  			struct fsg_buffhd *bh = &common->buffhds[i]; @@ -2345,88 +2340,53 @@ reset:  			fsg->bulk_out_enabled = 0;  		} -		common->prev_fsg = 0; +		common->fsg = NULL; +		wake_up(&common->fsg_wait);  	}  	common->running = 0; -	if (altsetting < 0 || rc != 0) +	if (!new_fsg || rc)  		return rc; -	DBG(common, "set interface %d\n", altsetting); +	common->fsg = new_fsg; +	fsg = common->fsg; -	if (fsg_is_set(common)) { -		struct fsg_dev *fsg = common->fsg; -		common->prev_fsg = common->fsg; +	/* Enable the endpoints */ +	d = fsg_ep_desc(common->gadget, +			&fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); +	rc = enable_endpoint(common, fsg->bulk_in, d); +	if (rc) +		goto reset; +	fsg->bulk_in_enabled = 1; + +	d = fsg_ep_desc(common->gadget, +			&fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); +	rc = enable_endpoint(common, fsg->bulk_out, d); +	if (rc) +		goto reset; +	fsg->bulk_out_enabled = 1; +	common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); +	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); -		/* Enable the endpoints */ -		d = fsg_ep_desc(common->gadget, -				&fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); -		rc = enable_endpoint(common, fsg->bulk_in, d); +	/* Allocate the requests */ +	for (i = 0; i < FSG_NUM_BUFFERS; ++i) { +		struct fsg_buffhd	*bh = &common->buffhds[i]; + +		rc = alloc_request(common, fsg->bulk_in, &bh->inreq);  		if (rc)  			goto reset; -		fsg->bulk_in_enabled = 1; - -		d = fsg_ep_desc(common->gadget, -				&fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); -		rc = enable_endpoint(common, fsg->bulk_out, d); +		rc = alloc_request(common, fsg->bulk_out, &bh->outreq);  		if (rc)  			goto reset; -		fsg->bulk_out_enabled = 1; -		common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); -		clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); - -		/* Allocate the requests */ -		for (i = 0; i < FSG_NUM_BUFFERS; ++i) { -			struct fsg_buffhd	*bh = &common->buffhds[i]; - -			rc = alloc_request(common, fsg->bulk_in, &bh->inreq); -			if (rc) -				goto reset; -			rc = alloc_request(common, fsg->bulk_out, &bh->outreq); -			if (rc) -				goto reset; -			bh->inreq->buf = bh->outreq->buf = bh->buf; -			bh->inreq->context = bh->outreq->context = bh; -			bh->inreq->complete = bulk_in_complete; -			bh->outreq->complete = bulk_out_complete; -		} - -		common->running = 1; -		for (i = 0; i < common->nluns; ++i) -			common->luns[i].unit_attention_data = SS_RESET_OCCURRED; -		return rc; -	} else { -		return -EIO; -	} -} - - -/* - * Change our operational configuration.  This code must agree with the code - * that returns config descriptors, and with interface altsetting code. - * - * It's also responsible for power management interactions.  Some - * configurations might not work with our current power sources. - * For now we just assume the gadget is always self-powered. - */ -static int do_set_config(struct fsg_common *common, u8 new_config) -{ -	int	rc = 0; - -	/* Disable the single interface */ -	if (common->config != 0) { -		DBG(common, "reset config\n"); -		common->config = 0; -		rc = do_set_interface(common, -1); +		bh->inreq->buf = bh->outreq->buf = bh->buf; +		bh->inreq->context = bh->outreq->context = bh; +		bh->inreq->complete = bulk_in_complete; +		bh->outreq->complete = bulk_out_complete;  	} -	/* Enable the interface */ -	if (new_config != 0) { -		common->config = new_config; -		rc = do_set_interface(common, 0); -		if (rc != 0) -			common->config = 0;	/* Reset on errors */ -	} +	common->running = 1; +	for (i = 0; i < common->nluns; ++i) +		common->luns[i].unit_attention_data = SS_RESET_OCCURRED;  	return rc;  } @@ -2437,9 +2397,7 @@ static int do_set_config(struct fsg_common *common, u8 new_config)  static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)  {  	struct fsg_dev *fsg = fsg_from_func(f); -	fsg->common->prev_fsg = fsg->common->fsg; -	fsg->common->fsg = fsg; -	fsg->common->new_config = 1; +	fsg->common->new_fsg = fsg;  	raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);  	return 0;  } @@ -2447,9 +2405,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)  static void fsg_disable(struct usb_function *f)  {  	struct fsg_dev *fsg = fsg_from_func(f); -	fsg->common->prev_fsg = fsg->common->fsg; -	fsg->common->fsg = fsg; -	fsg->common->new_config = 0; +	fsg->common->new_fsg = NULL;  	raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);  } @@ -2459,19 +2415,17 @@ static void fsg_disable(struct usb_function *f)  static void handle_exception(struct fsg_common *common)  {  	siginfo_t		info; -	int			sig;  	int			i;  	struct fsg_buffhd	*bh;  	enum fsg_state		old_state; -	u8			new_config;  	struct fsg_lun		*curlun;  	unsigned int		exception_req_tag; -	int			rc;  	/* Clear the existing signals.  Anything but SIGUSR1 is converted  	 * into a high-priority EXIT exception. */  	for (;;) { -		sig = dequeue_signal_lock(current, ¤t->blocked, &info); +		int sig = +			dequeue_signal_lock(current, ¤t->blocked, &info);  		if (!sig)  			break;  		if (sig != SIGUSR1) { @@ -2482,7 +2436,7 @@ static void handle_exception(struct fsg_common *common)  	}  	/* Cancel all the pending transfers */ -	if (fsg_is_set(common)) { +	if (likely(common->fsg)) {  		for (i = 0; i < FSG_NUM_BUFFERS; ++i) {  			bh = &common->buffhds[i];  			if (bh->inreq_busy) @@ -2523,7 +2477,6 @@ static void handle_exception(struct fsg_common *common)  	common->next_buffhd_to_fill = &common->buffhds[0];  	common->next_buffhd_to_drain = &common->buffhds[0];  	exception_req_tag = common->exception_req_tag; -	new_config = common->new_config;  	old_state = common->state;  	if (old_state == FSG_STATE_ABORT_BULK_OUT) @@ -2573,12 +2526,12 @@ static void handle_exception(struct fsg_common *common)  		break;  	case FSG_STATE_CONFIG_CHANGE: -		rc = do_set_config(common, new_config); +		do_set_interface(common, common->new_fsg);  		break;  	case FSG_STATE_EXIT:  	case FSG_STATE_TERMINATED: -		do_set_config(common, 0);		/* Free resources */ +		do_set_interface(common, NULL);		/* Free resources */  		spin_lock_irq(&common->lock);  		common->state = FSG_STATE_TERMINATED;	/* Stop the thread */  		spin_unlock_irq(&common->lock); @@ -2863,6 +2816,7 @@ buffhds_first_it:  		goto error_release;  	}  	init_completion(&common->thread_notifier); +	init_waitqueue_head(&common->fsg_wait);  #undef OR @@ -2957,9 +2911,17 @@ static void fsg_common_release(struct kref *ref)  static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)  {  	struct fsg_dev		*fsg = fsg_from_func(f); +	struct fsg_common	*common = fsg->common;  	DBG(fsg, "unbind\n"); -	fsg_common_put(fsg->common); +	if (fsg->common->fsg == fsg) { +		fsg->common->new_fsg = NULL; +		raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); +		/* FIXME: make interruptible or killable somehow? */ +		wait_event(common->fsg_wait, common->fsg != fsg); +	} + +	fsg_common_put(common);  	usb_free_descriptors(fsg->function.descriptors);  	usb_free_descriptors(fsg->function.hs_descriptors);  	kfree(fsg); @@ -2970,7 +2932,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)  {  	struct fsg_dev		*fsg = fsg_from_func(f);  	struct usb_gadget	*gadget = c->cdev->gadget; -	int			rc;  	int			i;  	struct usb_ep		*ep; @@ -2996,6 +2957,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)  	ep->driver_data = fsg->common;	/* claim the endpoint */  	fsg->bulk_out = ep; +	/* Copy descriptors */ +	f->descriptors = usb_copy_descriptors(fsg_fs_function); +	if (unlikely(!f->descriptors)) +		return -ENOMEM; +  	if (gadget_is_dualspeed(gadget)) {  		/* Assume endpoint addresses are the same for both speeds */  		fsg_hs_bulk_in_desc.bEndpointAddress = @@ -3003,16 +2969,17 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)  		fsg_hs_bulk_out_desc.bEndpointAddress =  			fsg_fs_bulk_out_desc.bEndpointAddress;  		f->hs_descriptors = usb_copy_descriptors(fsg_hs_function); -		if (unlikely(!f->hs_descriptors)) +		if (unlikely(!f->hs_descriptors)) { +			usb_free_descriptors(f->descriptors);  			return -ENOMEM; +		}  	}  	return 0;  autoconf_fail:  	ERROR(fsg, "unable to autoconfigure all endpoints\n"); -	rc = -ENOTSUPP; -	return rc; +	return -ENOTSUPP;  } @@ -3036,11 +3003,6 @@ static int fsg_add(struct usb_composite_dev *cdev,  	fsg->function.name        = FSG_DRIVER_DESC;  	fsg->function.strings     = fsg_strings_array; -	fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function); -	if (unlikely(!fsg->function.descriptors)) { -		rc = -ENOMEM; -		goto error_free_fsg; -	}  	fsg->function.bind        = fsg_bind;  	fsg->function.unbind      = fsg_unbind;  	fsg->function.setup       = fsg_setup; @@ -3056,19 +3018,9 @@ static int fsg_add(struct usb_composite_dev *cdev,  	rc = usb_add_function(c, &fsg->function);  	if (unlikely(rc)) -		goto error_free_all; - -	fsg_common_get(fsg->common); -	return 0; - -error_free_all: -	usb_free_descriptors(fsg->function.descriptors); -	/* fsg_bind() might have copied those; or maybe not? who cares -	 * -- free it just in case. */ -	usb_free_descriptors(fsg->function.hs_descriptors); -error_free_fsg: -	kfree(fsg); - +		kfree(fsg); +	else +		fsg_common_get(fsg->common);  	return rc;  } diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index fc2611f8b32..dbe6db0184f 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -28,7 +28,7 @@  #include "uvc.h" -unsigned int uvc_trace_param; +unsigned int uvc_gadget_trace_param;  /* --------------------------------------------------------------------------   * Function descriptors @@ -656,6 +656,6 @@ error:  	return ret;  } -module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); +module_param_named(trace, uvc_gadget_trace_param, uint, S_IRUGO|S_IWUSR);  MODULE_PARM_DESC(trace, "Trace level bitmask"); diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c index d0b8bde59e5..eafa6d2c5ed 100644 --- a/drivers/usb/gadget/fsl_mxc_udc.c +++ b/drivers/usb/gadget/fsl_mxc_udc.c @@ -30,7 +30,7 @@ int fsl_udc_clk_init(struct platform_device *pdev)  	pdata = pdev->dev.platform_data; -	if (!cpu_is_mx35()) { +	if (!cpu_is_mx35() && !cpu_is_mx25()) {  		mxc_ahb_clk = clk_get(&pdev->dev, "usb_ahb");  		if (IS_ERR(mxc_ahb_clk))  			return PTR_ERR(mxc_ahb_clk); diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 4b0e4a040d6..d1af253a910 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -392,6 +392,17 @@ static int __gfs_do_config(struct usb_configuration *c,  	if (unlikely(ret < 0))  		return ret; +	/* After previous do_configs there may be some invalid +	 * pointers in c->interface array.  This happens every time +	 * a user space function with fewer interfaces than a user +	 * space function that was run before the new one is run.  The +	 * compasit's set_config() assumes that if there is no more +	 * then MAX_CONFIG_INTERFACES interfaces in a configuration +	 * then there is a NULL pointer after the last interface in +	 * c->interface array.  We need to make sure this is true. */ +	if (c->next_interface_id < ARRAY_SIZE(c->interface)) +		c->interface[c->next_interface_id] = NULL; +  	return 0;  } diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 43abf55d8c6..4c3ac5c4223 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -82,7 +82,7 @@ static struct class *usb_gadget_class;  struct printer_dev {  	spinlock_t		lock;		/* lock this structure */  	/* lock buffer lists during read/write calls */ -	spinlock_t		lock_printer_io; +	struct mutex		lock_printer_io;  	struct usb_gadget	*gadget;  	struct usb_request	*req;		/* for control responses */  	u8			config; @@ -567,7 +567,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)  	DBG(dev, "printer_read trying to read %d bytes\n", (int)len); -	spin_lock(&dev->lock_printer_io); +	mutex_lock(&dev->lock_printer_io);  	spin_lock_irqsave(&dev->lock, flags);  	/* We will use this flag later to check if a printer reset happened @@ -601,7 +601,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)  		 * call or not.  		 */  		if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) { -			spin_unlock(&dev->lock_printer_io); +			mutex_unlock(&dev->lock_printer_io);  			return -EAGAIN;  		} @@ -648,7 +648,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)  		if (dev->reset_printer) {  			list_add(¤t_rx_req->list, &dev->rx_reqs);  			spin_unlock_irqrestore(&dev->lock, flags); -			spin_unlock(&dev->lock_printer_io); +			mutex_unlock(&dev->lock_printer_io);  			return -EAGAIN;  		} @@ -673,7 +673,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)  	dev->current_rx_buf = current_rx_buf;  	spin_unlock_irqrestore(&dev->lock, flags); -	spin_unlock(&dev->lock_printer_io); +	mutex_unlock(&dev->lock_printer_io);  	DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied); @@ -697,7 +697,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)  	if (len == 0)  		return -EINVAL; -	spin_lock(&dev->lock_printer_io); +	mutex_lock(&dev->lock_printer_io);  	spin_lock_irqsave(&dev->lock, flags);  	/* Check if a printer reset happens while we have interrupts on */ @@ -713,7 +713,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)  		 * a NON-Blocking call or not.  		 */  		if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) { -			spin_unlock(&dev->lock_printer_io); +			mutex_unlock(&dev->lock_printer_io);  			return -EAGAIN;  		} @@ -752,7 +752,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)  		if (copy_from_user(req->buf, buf, size)) {  			list_add(&req->list, &dev->tx_reqs); -			spin_unlock(&dev->lock_printer_io); +			mutex_unlock(&dev->lock_printer_io);  			return bytes_copied;  		} @@ -766,14 +766,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)  		if (dev->reset_printer) {  			list_add(&req->list, &dev->tx_reqs);  			spin_unlock_irqrestore(&dev->lock, flags); -			spin_unlock(&dev->lock_printer_io); +			mutex_unlock(&dev->lock_printer_io);  			return -EAGAIN;  		}  		if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {  			list_add(&req->list, &dev->tx_reqs);  			spin_unlock_irqrestore(&dev->lock, flags); -			spin_unlock(&dev->lock_printer_io); +			mutex_unlock(&dev->lock_printer_io);  			return -EAGAIN;  		} @@ -782,7 +782,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)  	}  	spin_unlock_irqrestore(&dev->lock, flags); -	spin_unlock(&dev->lock_printer_io); +	mutex_unlock(&dev->lock_printer_io);  	DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied); @@ -820,11 +820,11 @@ printer_poll(struct file *fd, poll_table *wait)  	unsigned long		flags;  	int			status = 0; -	spin_lock(&dev->lock_printer_io); +	mutex_lock(&dev->lock_printer_io);  	spin_lock_irqsave(&dev->lock, flags);  	setup_rx_reqs(dev);  	spin_unlock_irqrestore(&dev->lock, flags); -	spin_unlock(&dev->lock_printer_io); +	mutex_unlock(&dev->lock_printer_io);  	poll_wait(fd, &dev->rx_wait, wait);  	poll_wait(fd, &dev->tx_wait, wait); @@ -1461,7 +1461,7 @@ autoconf_fail:  	}  	spin_lock_init(&dev->lock); -	spin_lock_init(&dev->lock_printer_io); +	mutex_init(&dev->lock_printer_io);  	INIT_LIST_HEAD(&dev->tx_reqs);  	INIT_LIST_HEAD(&dev->tx_reqs_active);  	INIT_LIST_HEAD(&dev->rx_reqs); @@ -1594,7 +1594,7 @@ cleanup(void)  {  	int status; -	spin_lock(&usb_printer_gadget.lock_printer_io); +	mutex_lock(&usb_printer_gadget.lock_printer_io);  	class_destroy(usb_gadget_class);  	unregister_chrdev_region(g_printer_devno, 2); @@ -1602,6 +1602,6 @@ cleanup(void)  	if (status)  		ERROR(dev, "usb_gadget_unregister_driver %x\n", status); -	spin_unlock(&usb_printer_gadget.lock_printer_io); +	mutex_unlock(&usb_printer_gadget.lock_printer_io);  }  module_exit(cleanup); diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 85b0d8921ea..980762453a9 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -2561,7 +2561,7 @@ static void pxa_udc_shutdown(struct platform_device *_dev)  		udc_disable(udc);  } -#ifdef CONFIG_CPU_PXA27x +#ifdef CONFIG_PXA27x  extern void pxa27x_clear_otgph(void);  #else  #define pxa27x_clear_otgph()   do {} while (0) diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index d5f4c1d45c9..ea2b3c7ebee 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -735,6 +735,10 @@ static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,  	else  		dev->ep0state = EP0_OUT_DATA_PHASE; +	if (!dev->driver) +		return; + +	/* deliver the request to the gadget driver */  	ret = dev->driver->setup(&dev->gadget, crq);  	if (ret < 0) {  		if (dev->req_config) { @@ -1700,9 +1704,13 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)  	if (!driver || driver != udc->driver || !driver->unbind)  		return -EINVAL; -	dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n", +	dprintk(DEBUG_NORMAL, "usb_gadget_unregister_driver() '%s'\n",  		driver->driver.name); +	/* report disconnect */ +	if (driver->disconnect) +		driver->disconnect(&udc->gadget); +  	driver->unbind(&udc->gadget);  	device_del(&udc->gadget.dev); diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 16bdf77f582..3e8dcb5455e 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -536,17 +536,11 @@ recycle:  		list_move(&req->list, &port->read_pool);  	} -	/* Push from tty to ldisc; this is immediate with low_latency, and -	 * may trigger callbacks to this driver ... so drop the spinlock. +	/* Push from tty to ldisc; without low_latency set this is handled by +	 * a workqueue, so we won't get callbacks and can hold port_lock  	 */  	if (tty && do_push) { -		spin_unlock_irq(&port->port_lock);  		tty_flip_buffer_push(tty); -		wake_up_interruptible(&tty->read_wait); -		spin_lock_irq(&port->port_lock); - -		/* tty may have been closed */ -		tty = port->port_tty;  	} @@ -784,11 +778,6 @@ static int gs_open(struct tty_struct *tty, struct file *file)  	port->open_count = 1;  	port->openclose = false; -	/* low_latency means ldiscs work in tasklet context, without -	 * needing a workqueue schedule ... easier to keep up. -	 */ -	tty->low_latency = 1; -  	/* if connected, start the I/O stream */  	if (port->port_usb) {  		struct gserial	*gser = port->port_usb; @@ -1195,6 +1184,7 @@ void gserial_cleanup(void)  	n_ports = 0;  	tty_unregister_driver(gs_tty_driver); +	put_tty_driver(gs_tty_driver);  	gs_tty_driver = NULL;  	pr_debug("%s: cleaned up ttyGS* support\n", __func__); diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h index 0a705e63c93..e92454cddd7 100644 --- a/drivers/usb/gadget/uvc.h +++ b/drivers/usb/gadget/uvc.h @@ -107,11 +107,11 @@ struct uvc_streaming_control {  #define UVC_WARN_MINMAX				0  #define UVC_WARN_PROBE_DEF			1 -extern unsigned int uvc_trace_param; +extern unsigned int uvc_gadget_trace_param;  #define uvc_trace(flag, msg...) \  	do { \ -		if (uvc_trace_param & flag) \ +		if (uvc_gadget_trace_param & flag) \  			printk(KERN_DEBUG "uvcvideo: " msg); \  	} while (0) @@ -220,16 +220,10 @@ struct uvc_file_handle  #define to_uvc_file_handle(handle) \  	container_of(handle, struct uvc_file_handle, vfh) -extern struct v4l2_file_operations uvc_v4l2_fops; -  /* ------------------------------------------------------------------------   * Functions   */ -extern int uvc_video_enable(struct uvc_video *video, int enable); -extern int uvc_video_init(struct uvc_video *video); -extern int uvc_video_pump(struct uvc_video *video); -  extern void uvc_endpoint_stream(struct uvc_device *dev);  extern void uvc_function_connect(struct uvc_device *uvc); diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c index 43891991bf2..f7395ac5dc1 100644 --- a/drivers/usb/gadget/uvc_queue.c +++ b/drivers/usb/gadget/uvc_queue.c @@ -78,7 +78,8 @@   *   */ -void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) +static void +uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)  {  	mutex_init(&queue->mutex);  	spin_lock_init(&queue->irqlock); @@ -88,6 +89,28 @@ 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; +} + +/*   * Allocate the video buffers.   *   * Pages are reserved to make sure they will not be swapped, as they will be @@ -95,8 +118,9 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)   *   * Buffers will be individually mapped, so they must all be page aligned.   */ -int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, -		unsigned int buflength) +static int +uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, +		  unsigned int buflength)  {  	unsigned int bufsize = PAGE_ALIGN(buflength);  	unsigned int i; @@ -150,28 +174,6 @@ done:  	return ret;  } -/* - * 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; -} -  static void __uvc_query_buffer(struct uvc_buffer *buf,  		struct v4l2_buffer *v4l2_buf)  { @@ -195,8 +197,8 @@ static void __uvc_query_buffer(struct uvc_buffer *buf,  	}  } -int uvc_query_buffer(struct uvc_video_queue *queue, -		struct v4l2_buffer *v4l2_buf) +static int +uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)  {  	int ret = 0; @@ -217,8 +219,8 @@ done:   * Queue a video buffer. Attempting to queue a buffer that has already been   * queued will return -EINVAL.   */ -int uvc_queue_buffer(struct uvc_video_queue *queue, -	struct v4l2_buffer *v4l2_buf) +static int +uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)  {  	struct uvc_buffer *buf;  	unsigned long flags; @@ -298,8 +300,9 @@ static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)   * Dequeue a video buffer. If nonblocking is false, block until a buffer is   * available.   */ -int uvc_dequeue_buffer(struct uvc_video_queue *queue, -		struct v4l2_buffer *v4l2_buf, int nonblocking) +static int +uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf, +		   int nonblocking)  {  	struct uvc_buffer *buf;  	int ret = 0; @@ -359,8 +362,9 @@ done:   * This function implements video queue polling and is intended to be used by   * the device poll handler.   */ -unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, -		poll_table *wait) +static unsigned int +uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, +	       poll_table *wait)  {  	struct uvc_buffer *buf;  	unsigned int mask = 0; @@ -407,7 +411,8 @@ static struct vm_operations_struct uvc_vm_ops = {   * This function implements video buffer 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) +static int +uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)  {  	struct uvc_buffer *uninitialized_var(buffer);  	struct page *page; @@ -458,6 +463,42 @@ done:  }  /* + * Cancel the video buffers queue. + * + * Cancelling the queue marks all buffers on the irq queue as erroneous, + * wakes them up and removes them from the queue. + * + * If the disconnect parameter is set, further calls to uvc_queue_buffer will + * fail with -ENODEV. + * + * This function acquires the irq spinlock and can be called from interrupt + * context. + */ +static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) +{ +	struct uvc_buffer *buf; +	unsigned long flags; + +	spin_lock_irqsave(&queue->irqlock, flags); +	while (!list_empty(&queue->irqqueue)) { +		buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, +				       queue); +		list_del(&buf->queue); +		buf->state = UVC_BUF_STATE_ERROR; +		wake_up(&buf->wait); +	} +	/* This must be protected by the irqlock spinlock to avoid race +	 * conditions between uvc_queue_buffer and the disconnection event that +	 * could result in an interruptible wait in uvc_dequeue_buffer. Do not +	 * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED +	 * state outside the queue code. +	 */ +	if (disconnect) +		queue->flags |= UVC_QUEUE_DISCONNECTED; +	spin_unlock_irqrestore(&queue->irqlock, flags); +} + +/*   * Enable or disable the video buffers queue.   *   * The queue must be enabled before starting video acquisition and must be @@ -474,7 +515,7 @@ done:   * This function can't be called from interrupt context. Use   * uvc_queue_cancel() instead.   */ -int uvc_queue_enable(struct uvc_video_queue *queue, int enable) +static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)  {  	unsigned int i;  	int ret = 0; @@ -503,44 +544,8 @@ done:  	return ret;  } -/* - * Cancel the video buffers queue. - * - * Cancelling the queue marks all buffers on the irq queue as erroneous, - * wakes them up and removes them from the queue. - * - * If the disconnect parameter is set, further calls to uvc_queue_buffer will - * fail with -ENODEV. - * - * This function acquires the irq spinlock and can be called from interrupt - * context. - */ -void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) -{ -	struct uvc_buffer *buf; -	unsigned long flags; - -	spin_lock_irqsave(&queue->irqlock, flags); -	while (!list_empty(&queue->irqqueue)) { -		buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, -				       queue); -		list_del(&buf->queue); -		buf->state = UVC_BUF_STATE_ERROR; -		wake_up(&buf->wait); -	} -	/* This must be protected by the irqlock spinlock to avoid race -	 * conditions between uvc_queue_buffer and the disconnection event that -	 * could result in an interruptible wait in uvc_dequeue_buffer. Do not -	 * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED -	 * state outside the queue code. -	 */ -	if (disconnect) -		queue->flags |= UVC_QUEUE_DISCONNECTED; -	spin_unlock_irqrestore(&queue->irqlock, flags); -} - -struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, -		struct uvc_buffer *buf) +static struct uvc_buffer * +uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)  {  	struct uvc_buffer *nextbuf;  	unsigned long flags; @@ -568,7 +573,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,  	return nextbuf;  } -struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue) +static struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue)  {  	struct uvc_buffer *buf = NULL; diff --git a/drivers/usb/gadget/uvc_queue.h b/drivers/usb/gadget/uvc_queue.h index 7f5a33fe7ae..1812a8ecc5d 100644 --- a/drivers/usb/gadget/uvc_queue.h +++ b/drivers/usb/gadget/uvc_queue.h @@ -58,30 +58,10 @@ struct uvc_video_queue {  	struct list_head irqqueue;  }; -extern void uvc_queue_init(struct uvc_video_queue *queue, -		enum v4l2_buf_type type); -extern int uvc_alloc_buffers(struct uvc_video_queue *queue, -		unsigned int nbuffers, unsigned int buflength); -extern int uvc_free_buffers(struct uvc_video_queue *queue); -extern int uvc_query_buffer(struct uvc_video_queue *queue, -		struct v4l2_buffer *v4l2_buf); -extern int uvc_queue_buffer(struct uvc_video_queue *queue, -		struct v4l2_buffer *v4l2_buf); -extern int uvc_dequeue_buffer(struct uvc_video_queue *queue, -		struct v4l2_buffer *v4l2_buf, int nonblocking); -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 unsigned int uvc_queue_poll(struct uvc_video_queue *queue, -		struct file *file, poll_table *wait); -extern int uvc_queue_mmap(struct uvc_video_queue *queue, -		struct vm_area_struct *vma);  static inline int uvc_queue_streaming(struct uvc_video_queue *queue)  {  	return queue->flags & UVC_QUEUE_STREAMING;  } -extern struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue);  #endif /* __KERNEL__ */ diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c index a7989f29837..2dcffdac86d 100644 --- a/drivers/usb/gadget/uvc_v4l2.c +++ b/drivers/usb/gadget/uvc_v4l2.c @@ -363,7 +363,7 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)  	return mask;  } -struct v4l2_file_operations uvc_v4l2_fops = { +static struct v4l2_file_operations uvc_v4l2_fops = {  	.owner		= THIS_MODULE,  	.open		= uvc_v4l2_open,  	.release	= uvc_v4l2_release, diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/uvc_video.c index de8cbc46518..b08f35438d7 100644 --- a/drivers/usb/gadget/uvc_video.c +++ b/drivers/usb/gadget/uvc_video.c @@ -271,7 +271,7 @@ error:   * This function fills the available USB requests (listed in req_free) with   * video data from the queued buffers.   */ -int +static int  uvc_video_pump(struct uvc_video *video)  {  	struct usb_request *req; @@ -328,7 +328,7 @@ uvc_video_pump(struct uvc_video *video)  /*   * Enable or disable the video stream.   */ -int +static int  uvc_video_enable(struct uvc_video *video, int enable)  {  	unsigned int i; @@ -367,7 +367,7 @@ uvc_video_enable(struct uvc_video *video, int enable)  /*   * Initialize the UVC video stream.   */ -int +static int  uvc_video_init(struct uvc_video *video)  {  	INIT_LIST_HEAD(&video->req_free); diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index 417fd688769..f5f3030cc41 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -28,10 +28,10 @@  #include "config.c"  #include "epautoconf.c" -#include "f_uvc.c"  #include "uvc_queue.c" -#include "uvc_v4l2.c"  #include "uvc_video.c" +#include "uvc_v4l2.c" +#include "f_uvc.c"  /* --------------------------------------------------------------------------   * Device descriptor diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index 544ccfd7056..a8ad8ac120a 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -182,7 +182,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)  	}  	clk_enable(priv->usbclk); -	if (!cpu_is_mx35()) { +	if (!cpu_is_mx35() && !cpu_is_mx25()) {  		priv->ahbclk = clk_get(dev, "usb_ahb");  		if (IS_ERR(priv->ahbclk)) {  			ret = PTR_ERR(priv->ahbclk); @@ -207,10 +207,17 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)  	/* Initialize the transceiver */  	if (pdata->otg) {  		pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET; -		if (otg_init(pdata->otg) != 0) -			dev_err(dev, "unable to init transceiver\n"); -		else if (otg_set_vbus(pdata->otg, 1) != 0) +		ret = otg_init(pdata->otg); +		if (ret) { +			dev_err(dev, "unable to init transceiver, probably missing\n"); +			ret = -ENODEV; +			goto err_add; +		} +		ret = otg_set_vbus(pdata->otg, 1); +		if (ret) {  			dev_err(dev, "unable to enable vbus on transceiver\n"); +			goto err_add; +		}  	}  	priv->hcd = hcd; diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 20a0dfe0fe3..0587ad4ce5c 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2224,12 +2224,9 @@ static void remove_debug_file(struct isp1362_hcd *isp1362_hcd)  /*-------------------------------------------------------------------------*/ -static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd) +static void __isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)  {  	int tmp = 20; -	unsigned long flags; - -	spin_lock_irqsave(&isp1362_hcd->lock, flags);  	isp1362_write_reg16(isp1362_hcd, HCSWRES, HCSWRES_MAGIC);  	isp1362_write_reg32(isp1362_hcd, HCCMDSTAT, OHCI_HCR); @@ -2240,6 +2237,14 @@ static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)  	}  	if (!tmp)  		pr_err("Software reset timeout\n"); +} + +static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd) +{ +	unsigned long flags; + +	spin_lock_irqsave(&isp1362_hcd->lock, flags); +	__isp1362_sw_reset(isp1362_hcd);  	spin_unlock_irqrestore(&isp1362_hcd->lock, flags);  } @@ -2418,7 +2423,7 @@ static void isp1362_hc_stop(struct usb_hcd *hcd)  	if (isp1362_hcd->board && isp1362_hcd->board->reset)  		isp1362_hcd->board->reset(hcd->self.controller, 1);  	else -		isp1362_sw_reset(isp1362_hcd); +		__isp1362_sw_reset(isp1362_hcd);  	if (isp1362_hcd->board && isp1362_hcd->board->clock)  		isp1362_hcd->board->clock(hcd->self.controller, 0); diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index a18debdd79b..41816389477 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -203,7 +203,7 @@ static inline void pxa27x_reset_hc(struct pxa27x_ohci *ohci)  	__raw_writel(uhchr & ~UHCHR_FHR, ohci->mmio_base + UHCHR);  } -#ifdef CONFIG_CPU_PXA27x +#ifdef CONFIG_PXA27x  extern void pxa27x_clear_otgph(void);  #else  #define pxa27x_clear_otgph()	do {} while (0) diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 1a2bb4ce638..77be3c24a42 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1065,7 +1065,7 @@ static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port)  	else if (speed == LSMODE)  		rh->port |= USB_PORT_STAT_LOW_SPEED; -	rh->port &= USB_PORT_STAT_RESET; +	rh->port &= ~USB_PORT_STAT_RESET;  	rh->port |= USB_PORT_STAT_ENABLE;  } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index fd9e03afd91..2eb658d2639 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -835,6 +835,27 @@ fail:  	return 0;  } +void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, +		struct usb_device *udev) +{ +	struct xhci_virt_device *virt_dev; +	struct xhci_ep_ctx	*ep0_ctx; +	struct xhci_ring	*ep_ring; + +	virt_dev = xhci->devs[udev->slot_id]; +	ep0_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, 0); +	ep_ring = virt_dev->eps[0].ring; +	/* +	 * FIXME we don't keep track of the dequeue pointer very well after a +	 * Set TR dequeue pointer, so we're setting the dequeue pointer of the +	 * host to our enqueue pointer.  This should only be called after a +	 * configured device has reset, so all control transfers should have +	 * been completed or cancelled before the reset. +	 */ +	ep0_ctx->deq = xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue); +	ep0_ctx->deq |= ep_ring->cycle_state; +} +  /* Setup an xHCI virtual device for a Set Address command */  int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev)  { @@ -1002,7 +1023,7 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,  	return EP_INTERVAL(interval);  } -/* The "Mult" field in the endpoint context is only set for SuperSpeed devices. +/* The "Mult" field in the endpoint context is only set for SuperSpeed isoc eps.   * High speed endpoint descriptors can define "the number of additional   * transaction opportunities per microframe", but that goes in the Max Burst   * endpoint context field. @@ -1010,7 +1031,8 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,  static inline u32 xhci_get_endpoint_mult(struct usb_device *udev,  		struct usb_host_endpoint *ep)  { -	if (udev->speed != USB_SPEED_SUPER) +	if (udev->speed != USB_SPEED_SUPER || +			!usb_endpoint_xfer_isoc(&ep->desc))  		return 0;  	return ep->ss_ep_comp.bmAttributes;  } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 9012098add6..bfc99a93945 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -182,8 +182,12 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer   * set, but other sections talk about dealing with the chain bit set.  This was   * fixed in the 0.96 specification errata, but we have to assume that all 0.95   * xHCI hardware can't handle the chain bit being cleared on a link TRB. + * + * @more_trbs_coming:	Will you enqueue more TRBs before calling + *			prepare_transfer()?   */ -static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer) +static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, +		bool consumer, bool more_trbs_coming)  {  	u32 chain;  	union xhci_trb *next; @@ -199,15 +203,28 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer  	while (last_trb(xhci, ring, ring->enq_seg, next)) {  		if (!consumer) {  			if (ring != xhci->event_ring) { -				if (chain) { -					next->link.control |= TRB_CHAIN; - -					/* Give this link TRB to the hardware */ -					wmb(); -					next->link.control ^= TRB_CYCLE; -				} else { +				/* +				 * If the caller doesn't plan on enqueueing more +				 * TDs before ringing the doorbell, then we +				 * don't want to give the link TRB to the +				 * hardware just yet.  We'll give the link TRB +				 * back in prepare_ring() just before we enqueue +				 * the TD at the top of the ring. +				 */ +				if (!chain && !more_trbs_coming)  					break; + +				/* If we're not dealing with 0.95 hardware, +				 * carry over the chain bit of the previous TRB +				 * (which may mean the chain bit is cleared). +				 */ +				if (!xhci_link_trb_quirk(xhci)) { +					next->link.control &= ~TRB_CHAIN; +					next->link.control |= chain;  				} +				/* Give this link TRB to the hardware */ +				wmb(); +				next->link.control ^= TRB_CYCLE;  			}  			/* Toggle the cycle bit after the last ring segment. */  			if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) { @@ -1707,9 +1724,12 @@ void xhci_handle_event(struct xhci_hcd *xhci)  /*   * Generic function for queueing a TRB on a ring.   * The caller must have checked to make sure there's room on the ring. + * + * @more_trbs_coming:	Will you enqueue more TRBs before calling + *			prepare_transfer()?   */  static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring, -		bool consumer, +		bool consumer, bool more_trbs_coming,  		u32 field1, u32 field2, u32 field3, u32 field4)  {  	struct xhci_generic_trb *trb; @@ -1719,7 +1739,7 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,  	trb->field[1] = field2;  	trb->field[2] = field3;  	trb->field[3] = field4; -	inc_enq(xhci, ring, consumer); +	inc_enq(xhci, ring, consumer, more_trbs_coming);  }  /* @@ -1988,6 +2008,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  	int trb_buff_len, this_sg_len, running_total;  	bool first_trb;  	u64 addr; +	bool more_trbs_coming;  	struct xhci_generic_trb *start_trb;  	int start_cycle; @@ -2073,7 +2094,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  		length_field = TRB_LEN(trb_buff_len) |  			remainder |  			TRB_INTR_TARGET(0); -		queue_trb(xhci, ep_ring, false, +		if (num_trbs > 1) +			more_trbs_coming = true; +		else +			more_trbs_coming = false; +		queue_trb(xhci, ep_ring, false, more_trbs_coming,  				lower_32_bits(addr),  				upper_32_bits(addr),  				length_field, @@ -2124,6 +2149,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  	int num_trbs;  	struct xhci_generic_trb *start_trb;  	bool first_trb; +	bool more_trbs_coming;  	int start_cycle;  	u32 field, length_field; @@ -2212,7 +2238,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  		length_field = TRB_LEN(trb_buff_len) |  			remainder |  			TRB_INTR_TARGET(0); -		queue_trb(xhci, ep_ring, false, +		if (num_trbs > 1) +			more_trbs_coming = true; +		else +			more_trbs_coming = false; +		queue_trb(xhci, ep_ring, false, more_trbs_coming,  				lower_32_bits(addr),  				upper_32_bits(addr),  				length_field, @@ -2291,7 +2321,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  	/* Queue setup TRB - see section 6.4.1.2.1 */  	/* FIXME better way to translate setup_packet into two u32 fields? */  	setup = (struct usb_ctrlrequest *) urb->setup_packet; -	queue_trb(xhci, ep_ring, false, +	queue_trb(xhci, ep_ring, false, true,  			/* FIXME endianness is probably going to bite my ass here. */  			setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16,  			setup->wIndex | setup->wLength << 16, @@ -2307,7 +2337,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  	if (urb->transfer_buffer_length > 0) {  		if (setup->bRequestType & USB_DIR_IN)  			field |= TRB_DIR_IN; -		queue_trb(xhci, ep_ring, false, +		queue_trb(xhci, ep_ring, false, true,  				lower_32_bits(urb->transfer_dma),  				upper_32_bits(urb->transfer_dma),  				length_field, @@ -2324,7 +2354,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  		field = 0;  	else  		field = TRB_DIR_IN; -	queue_trb(xhci, ep_ring, false, +	queue_trb(xhci, ep_ring, false, false,  			0,  			0,  			TRB_INTR_TARGET(0), @@ -2350,18 +2380,21 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,  		u32 field3, u32 field4, bool command_must_succeed)  {  	int reserved_trbs = xhci->cmd_ring_reserved_trbs; +	int ret; +  	if (!command_must_succeed)  		reserved_trbs++; -	if (!room_on_ring(xhci, xhci->cmd_ring, reserved_trbs)) { -		if (!in_interrupt()) -			xhci_err(xhci, "ERR: No room for command on command ring\n"); +	ret = prepare_ring(xhci, xhci->cmd_ring, EP_STATE_RUNNING, +			reserved_trbs, GFP_ATOMIC); +	if (ret < 0) { +		xhci_err(xhci, "ERR: No room for command on command ring\n");  		if (command_must_succeed)  			xhci_err(xhci, "ERR: Reserved TRB counting for "  					"unfailable commands failed.\n"); -		return -ENOMEM; +		return ret;  	} -	queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3, +	queue_trb(xhci, xhci->cmd_ring, false, false, field1, field2, field3,  			field4 | xhci->cmd_ring->cycle_state);  	return 0;  } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 27345cd04da..3998f72cd0c 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2134,6 +2134,8 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)  	/* If this is a Set Address to an unconfigured device, setup ep 0 */  	if (!udev->config)  		xhci_setup_addressable_virt_dev(xhci, udev); +	else +		xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev);  	/* Otherwise, assume the core has the device configured how it wants */  	xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);  	xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 8b4b7d39f79..6c7e3430ec9 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1292,6 +1292,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags);  void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id);  int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags);  int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev); +void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, +		struct usb_device *udev);  unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc);  unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc);  unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index); diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 30d930386b6..d25814c172b 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -2436,7 +2436,8 @@ sisusb_open(struct inode *inode, struct file *file)  	}  	if (!sisusb->devinit) { -		if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { +		if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH || +		    sisusb->sisusb_dev->speed == USB_SPEED_SUPER) {  			if (sisusb_init_gfxdevice(sisusb, 0)) {  				mutex_unlock(&sisusb->lock);  				dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n"); @@ -3166,7 +3167,7 @@ static int sisusb_probe(struct usb_interface *intf,  	sisusb->present = 1; -	if (dev->speed == USB_SPEED_HIGH) { +	if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) {  		int initscreen = 1;  #ifdef INCL_SISUSB_CON  		if (sisusb_first_vc > 0 && diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index fad70bc8355..3b795c56221 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -219,8 +219,8 @@ static int musb_ulpi_write(struct otg_transceiver *otg,  	return 0;  }  #else -#define musb_ulpi_read(a, b)		NULL -#define musb_ulpi_write(a, b, c)	NULL +#define musb_ulpi_read		NULL +#define musb_ulpi_write		NULL  #endif  static struct otg_io_access_ops musb_ulpi_access = { @@ -451,10 +451,6 @@ void musb_hnp_stop(struct musb *musb)   * @param power   */ -#define STAGE0_MASK (MUSB_INTR_RESUME | MUSB_INTR_SESSREQ \ -		| MUSB_INTR_VBUSERROR | MUSB_INTR_CONNECT \ -		| MUSB_INTR_RESET) -  static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  				u8 devctl, u8 power)  { @@ -642,7 +638,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  		handled = IRQ_HANDLED;  	} - +#endif  	if (int_usb & MUSB_INTR_SUSPEND) {  		DBG(1, "SUSPEND (%s) devctl %02x power %02x\n",  				otg_state_string(musb), devctl, power); @@ -705,6 +701,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  		}  	} +#ifdef CONFIG_USB_MUSB_HDRC_HCD  	if (int_usb & MUSB_INTR_CONNECT) {  		struct usb_hcd *hcd = musb_to_hcd(musb);  		void __iomem *mbase = musb->mregs; @@ -1597,7 +1594,7 @@ irqreturn_t musb_interrupt(struct musb *musb)  	/* the core can interrupt us for multiple reasons; docs have  	 * a generic interrupt flowchart to follow  	 */ -	if (musb->int_usb & STAGE0_MASK) +	if (musb->int_usb)  		retval |= musb_stage0_irq(musb, musb->int_usb,  				devctl, power); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index b22d02dea7d..91d67794e35 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -470,7 +470,8 @@ struct musb_csr_regs {  struct musb_context_registers { -#ifdef CONFIG_PM +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ +    defined(CONFIG_ARCH_OMAP4)  	u32 otg_sysconfig, otg_forcestandby;  #endif  	u8 power; @@ -484,7 +485,8 @@ struct musb_context_registers {  	struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];  }; -#ifdef CONFIG_PM +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ +    defined(CONFIG_ARCH_OMAP4)  extern void musb_platform_save_context(struct musb *musb,  		struct musb_context_registers *musb_context);  extern void musb_platform_restore_context(struct musb *musb, diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 1008044a3bb..dc66e4376d4 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -132,18 +132,9 @@ static void configure_channel(struct dma_channel *channel,  	if (mode) {  		csr |= 1 << MUSB_HSDMA_MODE1_SHIFT;  		BUG_ON(len < packet_sz); - -		if (packet_sz >= 64) { -			csr |= MUSB_HSDMA_BURSTMODE_INCR16 -					<< MUSB_HSDMA_BURSTMODE_SHIFT; -		} else if (packet_sz >= 32) { -			csr |= MUSB_HSDMA_BURSTMODE_INCR8 -					<< MUSB_HSDMA_BURSTMODE_SHIFT; -		} else if (packet_sz >= 16) { -			csr |= MUSB_HSDMA_BURSTMODE_INCR4 -					<< MUSB_HSDMA_BURSTMODE_SHIFT; -		}  	} +	csr |= MUSB_HSDMA_BURSTMODE_INCR16 +				<< MUSB_HSDMA_BURSTMODE_SHIFT;  	csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)  		| (1 << MUSB_HSDMA_ENABLE_SHIFT) diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 05c077f8f9a..3c48e77a0aa 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -29,19 +29,6 @@ static void tusb_source_power(struct musb *musb, int is_on);  #define TUSB_REV_MAJOR(reg_val)		((reg_val >> 4) & 0xf)  #define TUSB_REV_MINOR(reg_val)		(reg_val & 0xf) -#ifdef CONFIG_PM -/* REVISIT: These should be only needed if somebody implements off idle */ -void musb_platform_save_context(struct musb *musb, -			struct musb_context_registers *musb_context) -{ -} - -void musb_platform_restore_context(struct musb *musb, -			struct musb_context_registers *musb_context) -{ -} -#endif -  /*   * Checks the revision. We need to use the DMA register as 3.0 does not   * have correct versions for TUSB_PRCM_REV or TUSB_INT_CTRL_REV. diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index b1b34693294..d331b222ad2 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c @@ -59,12 +59,17 @@ static int ulpi_set_flags(struct otg_transceiver *otg)  static int ulpi_init(struct otg_transceiver *otg)  { -	int i, vid, pid; +	int i, vid, pid, ret; +	u32 ulpi_id = 0; -	vid = (otg_io_read(otg, ULPI_VENDOR_ID_HIGH) << 8) | -	       otg_io_read(otg, ULPI_VENDOR_ID_LOW); -	pid = (otg_io_read(otg, ULPI_PRODUCT_ID_HIGH) << 8) | -	       otg_io_read(otg, ULPI_PRODUCT_ID_LOW); +	for (i = 0; i < 4; i++) { +		ret = otg_io_read(otg, ULPI_PRODUCT_ID_HIGH - i); +		if (ret < 0) +			return ret; +		ulpi_id = (ulpi_id << 8) | ret; +	} +	vid = ulpi_id & 0xffff; +	pid = ulpi_id >> 16;  	pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 79dd1ae195e..e298dc4baed 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -653,7 +653,6 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },  	{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },  	{ USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) }, -	{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) }, @@ -692,6 +691,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),  		.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },  	{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, +	{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },  	{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, @@ -738,6 +738,14 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) },  	{ USB_DEVICE(FTDI_VID, MJSG_HD_RADIO_PID) },  	{ USB_DEVICE(FTDI_VID, MJSG_XM_RADIO_PID) }, +	{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_ST_PID), +		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, +	{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SLITE_PID), +		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, +	{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH2_PID), +		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, +	{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID), +		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },  	{ },					/* Optional parameter entry */  	{ }					/* Terminating entry */  }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 94d86c3febc..d01946db8fa 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -501,13 +501,6 @@  #define CONTEC_COM1USBH_PID	0x8311	/* COM-1(USB)H */  /* - * Contec products (http://www.contec.com) - * Submitted by Daniel Sangorrin - */ -#define CONTEC_VID		0x06CE	/* Vendor ID */ -#define CONTEC_COM1USBH_PID	0x8311	/* COM-1(USB)H */ - -/*   * Definitions for B&B Electronics products.   */  #define BANDB_VID		0x0856	/* B&B Electronics Vendor ID */ @@ -703,6 +696,12 @@  #define TELLDUS_TELLSTICK_PID		0x0C30	/* RF control dongle 433 MHz using FT232RL */  /* + * RT Systems programming cables for various ham radios + */ +#define RTSYSTEMS_VID			0x2100	/* Vendor ID */ +#define RTSYSTEMS_SERIAL_VX7_PID	0x9e52	/* Serial converter for VX-7 Radios using FT232RL */ + +/*   * Bayer Ascensia Contour blood glucose meter USB-converter cable.   * http://winglucofacts.com/cables/   */ @@ -1024,3 +1023,12 @@  #define MJSG_SR_RADIO_PID	0x9379  #define MJSG_XM_RADIO_PID	0x937A  #define MJSG_HD_RADIO_PID	0x937C + +/* + * Xverve Signalyzer tools (http://www.signalyzer.com/) + */ +#define XVERVE_SIGNALYZER_ST_PID	0xBCA0 +#define XVERVE_SIGNALYZER_SLITE_PID	0xBCA1 +#define XVERVE_SIGNALYZER_SH2_PID	0xBCA2 +#define XVERVE_SIGNALYZER_SH4_PID	0xBCA4 + diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e280ad8e12f..5cd30e4345c 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -206,6 +206,7 @@ static void option_instat_callback(struct urb *urb);  #define AMOI_PRODUCT_H01			0x0800  #define AMOI_PRODUCT_H01A			0x7002  #define AMOI_PRODUCT_H02			0x0802 +#define AMOI_PRODUCT_SKYPEPHONE_S2		0x0407  #define DELL_VENDOR_ID				0x413C @@ -302,6 +303,7 @@ static void option_instat_callback(struct urb *urb);  #define QISDA_PRODUCT_H21_4512			0x4512  #define QISDA_PRODUCT_H21_4523			0x4523  #define QISDA_PRODUCT_H20_4515			0x4515 +#define QISDA_PRODUCT_H20_4518			0x4518  #define QISDA_PRODUCT_H20_4519			0x4519  /* TLAYTECH PRODUCTS */ @@ -516,6 +518,7 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },  	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },  	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H02) }, +	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_SKYPEPHONE_S2) },  	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5700_MINICARD) },		/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */  	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5500_MINICARD) },		/* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */ @@ -852,6 +855,7 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) },  	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },  	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) }, +	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4518) },  	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) },  	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },  	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 04bb759536b..cde67cacb2c 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -51,6 +51,8 @@ static const struct usb_device_id id_table[] = {  	{USB_DEVICE(0x1f45, 0x0001)},	/* Unknown Gobi QDL device */  	{USB_DEVICE(0x413c, 0x8185)},	/* Dell Gobi 2000 QDL device (N0218, VU936) */  	{USB_DEVICE(0x413c, 0x8186)},	/* Dell Gobi 2000 Modem device (N0218, VU936) */ +	{USB_DEVICE(0x05c6, 0x9208)},	/* Generic Gobi 2000 QDL device */ +	{USB_DEVICE(0x05c6, 0x920b)},	/* Generic Gobi 2000 Modem device */  	{USB_DEVICE(0x05c6, 0x9224)},	/* Sony Gobi 2000 QDL device (N0279, VU730) */  	{USB_DEVICE(0x05c6, 0x9225)},	/* Sony Gobi 2000 Modem device (N0279, VU730) */  	{USB_DEVICE(0x05c6, 0x9244)},	/* Samsung Gobi 2000 QDL device (VL176) */ @@ -139,6 +141,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)  					"Could not set interface, error %d\n",  					retval);  				retval = -ENODEV; +				kfree(data);  			}  			return retval;  		} @@ -155,6 +158,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)  					"Could not set interface, error %d\n",  					retval);  				retval = -ENODEV; +				kfree(data);  			}  			return retval;  		} @@ -163,6 +167,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)  	default:  		dev_err(&serial->dev->dev,  			"unknown number of interfaces: %d\n", nintf); +		kfree(data);  		return -ENODEV;  	} diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index ef0bdb08d78..d47b56e9e8c 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -245,6 +245,7 @@ static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(0x1199, 0x0021) },	/* Sierra Wireless AirCard 597E */  	{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */  	{ USB_DEVICE(0x1199, 0x0120) },	/* Sierra Wireless USB Dongle 595U */ +	{ USB_DEVICE(0x1199, 0x0301) },	/* Sierra Wireless USB Dongle 250U */  	/* Sierra Wireless C597 */  	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) },  	/* Sierra Wireless T598 */ diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 44716427c51..64ec073e89d 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -139,9 +139,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)  	/* fill the common fields in the URB */  	us->current_urb->context = &urb_done; -	us->current_urb->actual_length = 0; -	us->current_urb->error_count = 0; -	us->current_urb->status = 0; +	us->current_urb->transfer_flags = 0;  	/* we assume that if transfer_buffer isn't us->iobuf then it  	 * hasn't been mapped for DMA.  Yes, this is clunky, but it's diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index df5b6b971f2..d219070fed3 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -98,7 +98,8 @@ static void tx_poll_start(struct vhost_net *net, struct socket *sock)  static void handle_tx(struct vhost_net *net)  {  	struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX]; -	unsigned head, out, in, s; +	unsigned out, in, s; +	int head;  	struct msghdr msg = {  		.msg_name = NULL,  		.msg_namelen = 0, @@ -135,6 +136,9 @@ static void handle_tx(struct vhost_net *net)  					 ARRAY_SIZE(vq->iov),  					 &out, &in,  					 NULL, NULL); +		/* On error, stop handling until the next kick. */ +		if (unlikely(head < 0)) +			break;  		/* Nothing new?  Wait for eventfd to tell us they refilled. */  		if (head == vq->num) {  			wmem = atomic_read(&sock->sk->sk_wmem_alloc); @@ -173,8 +177,8 @@ static void handle_tx(struct vhost_net *net)  			break;  		}  		if (err != len) -			pr_err("Truncated TX packet: " -			       " len %d != %zd\n", err, len); +			pr_debug("Truncated TX packet: " +				 " len %d != %zd\n", err, len);  		vhost_add_used_and_signal(&net->dev, vq, head, 0);  		total_len += len;  		if (unlikely(total_len >= VHOST_NET_WEIGHT)) { @@ -192,7 +196,8 @@ static void handle_tx(struct vhost_net *net)  static void handle_rx(struct vhost_net *net)  {  	struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX]; -	unsigned head, out, in, log, s; +	unsigned out, in, log, s; +	int head;  	struct vhost_log *vq_log;  	struct msghdr msg = {  		.msg_name = NULL, @@ -228,6 +233,9 @@ static void handle_rx(struct vhost_net *net)  					 ARRAY_SIZE(vq->iov),  					 &out, &in,  					 vq_log, &log); +		/* On error, stop handling until the next kick. */ +		if (unlikely(head < 0)) +			break;  		/* OK, now we need to know about added descriptors. */  		if (head == vq->num) {  			if (unlikely(vhost_enable_notify(vq))) { @@ -267,8 +275,8 @@ static void handle_rx(struct vhost_net *net)  		}  		/* TODO: Should check and handle checksum. */  		if (err > len) { -			pr_err("Discarded truncated rx packet: " -			       " len %d > %zd\n", err, len); +			pr_debug("Discarded truncated rx packet: " +				 " len %d > %zd\n", err, len);  			vhost_discard_vq_desc(vq);  			continue;  		} @@ -526,11 +534,16 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)  	rcu_assign_pointer(vq->private_data, sock);  	vhost_net_enable_vq(n, vq);  done: +	mutex_unlock(&vq->mutex); +  	if (oldsock) {  		vhost_net_flush_vq(n, index);  		fput(oldsock->file);  	} +	mutex_unlock(&n->dev.mutex); +	return 0; +  err_vq:  	mutex_unlock(&vq->mutex);  err: diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 3b83382e06e..0b99783083f 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -736,12 +736,12 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,  	mem = rcu_dereference(dev->memory);  	while ((u64)len > s) {  		u64 size; -		if (ret >= iov_size) { +		if (unlikely(ret >= iov_size)) {  			ret = -ENOBUFS;  			break;  		}  		reg = find_region(mem, addr, len); -		if (!reg) { +		if (unlikely(!reg)) {  			ret = -EFAULT;  			break;  		} @@ -780,18 +780,18 @@ static unsigned next_desc(struct vring_desc *desc)  	return next;  } -static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq, -			     struct iovec iov[], unsigned int iov_size, -			     unsigned int *out_num, unsigned int *in_num, -			     struct vhost_log *log, unsigned int *log_num, -			     struct vring_desc *indirect) +static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq, +			struct iovec iov[], unsigned int iov_size, +			unsigned int *out_num, unsigned int *in_num, +			struct vhost_log *log, unsigned int *log_num, +			struct vring_desc *indirect)  {  	struct vring_desc desc;  	unsigned int i = 0, count, found = 0;  	int ret;  	/* Sanity check */ -	if (indirect->len % sizeof desc) { +	if (unlikely(indirect->len % sizeof desc)) {  		vq_err(vq, "Invalid length in indirect descriptor: "  		       "len 0x%llx not multiple of 0x%zx\n",  		       (unsigned long long)indirect->len, @@ -801,7 +801,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,  	ret = translate_desc(dev, indirect->addr, indirect->len, vq->indirect,  			     ARRAY_SIZE(vq->indirect)); -	if (ret < 0) { +	if (unlikely(ret < 0)) {  		vq_err(vq, "Translation failure %d in indirect.\n", ret);  		return ret;  	} @@ -813,7 +813,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,  	count = indirect->len / sizeof desc;  	/* Buffers are chained via a 16 bit next field, so  	 * we can have at most 2^16 of these. */ -	if (count > USHRT_MAX + 1) { +	if (unlikely(count > USHRT_MAX + 1)) {  		vq_err(vq, "Indirect buffer length too big: %d\n",  		       indirect->len);  		return -E2BIG; @@ -821,19 +821,19 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,  	do {  		unsigned iov_count = *in_num + *out_num; -		if (++found > count) { +		if (unlikely(++found > count)) {  			vq_err(vq, "Loop detected: last one at %u "  			       "indirect size %u\n",  			       i, count);  			return -EINVAL;  		} -		if (memcpy_fromiovec((unsigned char *)&desc, vq->indirect, -				     sizeof desc)) { +		if (unlikely(memcpy_fromiovec((unsigned char *)&desc, vq->indirect, +					      sizeof desc))) {  			vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n",  			       i, (size_t)indirect->addr + i * sizeof desc);  			return -EINVAL;  		} -		if (desc.flags & VRING_DESC_F_INDIRECT) { +		if (unlikely(desc.flags & VRING_DESC_F_INDIRECT)) {  			vq_err(vq, "Nested indirect descriptor: idx %d, %zx\n",  			       i, (size_t)indirect->addr + i * sizeof desc);  			return -EINVAL; @@ -841,7 +841,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,  		ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count,  				     iov_size - iov_count); -		if (ret < 0) { +		if (unlikely(ret < 0)) {  			vq_err(vq, "Translation failure %d indirect idx %d\n",  			       ret, i);  			return ret; @@ -857,7 +857,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,  		} else {  			/* If it's an output descriptor, they're all supposed  			 * to come before any input descriptors. */ -			if (*in_num) { +			if (unlikely(*in_num)) {  				vq_err(vq, "Indirect descriptor "  				       "has out after in: idx %d\n", i);  				return -EINVAL; @@ -873,12 +873,13 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,   * number of output then some number of input descriptors, it's actually two   * iovecs, but we pack them into one and note how many of each there were.   * - * This function returns the descriptor number found, or vq->num (which - * is never a valid descriptor number) if none was found. */ -unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, -			   struct iovec iov[], unsigned int iov_size, -			   unsigned int *out_num, unsigned int *in_num, -			   struct vhost_log *log, unsigned int *log_num) + * This function returns the descriptor number found, or vq->num (which is + * never a valid descriptor number) if none was found.  A negative code is + * returned on error. */ +int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, +		      struct iovec iov[], unsigned int iov_size, +		      unsigned int *out_num, unsigned int *in_num, +		      struct vhost_log *log, unsigned int *log_num)  {  	struct vring_desc desc;  	unsigned int i, head, found = 0; @@ -887,16 +888,16 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,  	/* Check it isn't doing very strange things with descriptor numbers. */  	last_avail_idx = vq->last_avail_idx; -	if (get_user(vq->avail_idx, &vq->avail->idx)) { +	if (unlikely(get_user(vq->avail_idx, &vq->avail->idx))) {  		vq_err(vq, "Failed to access avail idx at %p\n",  		       &vq->avail->idx); -		return vq->num; +		return -EFAULT;  	} -	if ((u16)(vq->avail_idx - last_avail_idx) > vq->num) { +	if (unlikely((u16)(vq->avail_idx - last_avail_idx) > vq->num)) {  		vq_err(vq, "Guest moved used index from %u to %u",  		       last_avail_idx, vq->avail_idx); -		return vq->num; +		return -EFAULT;  	}  	/* If there's nothing new since last we looked, return invalid. */ @@ -908,18 +909,19 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,  	/* Grab the next descriptor number they're advertising, and increment  	 * the index we've seen. */ -	if (get_user(head, &vq->avail->ring[last_avail_idx % vq->num])) { +	if (unlikely(get_user(head, +			      &vq->avail->ring[last_avail_idx % vq->num]))) {  		vq_err(vq, "Failed to read head: idx %d address %p\n",  		       last_avail_idx,  		       &vq->avail->ring[last_avail_idx % vq->num]); -		return vq->num; +		return -EFAULT;  	}  	/* If their number is silly, that's an error. */ -	if (head >= vq->num) { +	if (unlikely(head >= vq->num)) {  		vq_err(vq, "Guest says index %u > %u is available",  		       head, vq->num); -		return vq->num; +		return -EINVAL;  	}  	/* When we start there are none of either input nor output. */ @@ -930,41 +932,41 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,  	i = head;  	do {  		unsigned iov_count = *in_num + *out_num; -		if (i >= vq->num) { +		if (unlikely(i >= vq->num)) {  			vq_err(vq, "Desc index is %u > %u, head = %u",  			       i, vq->num, head); -			return vq->num; +			return -EINVAL;  		} -		if (++found > vq->num) { +		if (unlikely(++found > vq->num)) {  			vq_err(vq, "Loop detected: last one at %u "  			       "vq size %u head %u\n",  			       i, vq->num, head); -			return vq->num; +			return -EINVAL;  		}  		ret = copy_from_user(&desc, vq->desc + i, sizeof desc); -		if (ret) { +		if (unlikely(ret)) {  			vq_err(vq, "Failed to get descriptor: idx %d addr %p\n",  			       i, vq->desc + i); -			return vq->num; +			return -EFAULT;  		}  		if (desc.flags & VRING_DESC_F_INDIRECT) {  			ret = get_indirect(dev, vq, iov, iov_size,  					   out_num, in_num,  					   log, log_num, &desc); -			if (ret < 0) { +			if (unlikely(ret < 0)) {  				vq_err(vq, "Failure detected "  				       "in indirect descriptor at idx %d\n", i); -				return vq->num; +				return ret;  			}  			continue;  		}  		ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count,  				     iov_size - iov_count); -		if (ret < 0) { +		if (unlikely(ret < 0)) {  			vq_err(vq, "Translation failure %d descriptor idx %d\n",  			       ret, i); -			return vq->num; +			return ret;  		}  		if (desc.flags & VRING_DESC_F_WRITE) {  			/* If this is an input descriptor, @@ -978,10 +980,10 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,  		} else {  			/* If it's an output descriptor, they're all supposed  			 * to come before any input descriptors. */ -			if (*in_num) { +			if (unlikely(*in_num)) {  				vq_err(vq, "Descriptor has out after in: "  				       "idx %d\n", i); -				return vq->num; +				return -EINVAL;  			}  			*out_num += ret;  		} diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 44591ba9b07..11ee13dba0f 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -120,10 +120,10 @@ long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg);  int vhost_vq_access_ok(struct vhost_virtqueue *vq);  int vhost_log_access_ok(struct vhost_dev *); -unsigned vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *, -			   struct iovec iov[], unsigned int iov_count, -			   unsigned int *out_num, unsigned int *in_num, -			   struct vhost_log *log, unsigned int *log_num); +int vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *, +		      struct iovec iov[], unsigned int iov_count, +		      unsigned int *out_num, unsigned int *in_num, +		      struct vhost_log *log, unsigned int *log_num);  void vhost_discard_vq_desc(struct vhost_virtqueue *);  int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len); diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 515cf1978d1..c4e17642d9c 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -2872,7 +2872,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis  		}  #if 0 -		/* Power down TV DAC, taht saves a significant amount of power, +		/* Power down TV DAC, that saves a significant amount of power,  		 * we'll have something better once we actually have some TVOut  		 * support  		 */ diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index 40f61320ce1..34b2fc472fe 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -95,7 +95,7 @@ struct fb_bitfield rgb_bitfields[][4] =  	{ { 8, 4, 0 },  { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } },  }; -static struct fb_fix_screeninfo au1100fb_fix __initdata = { +static struct fb_fix_screeninfo au1100fb_fix __devinitdata = {  	.id		= "AU1100 FB",  	.xpanstep 	= 1,  	.ypanstep 	= 1, @@ -103,7 +103,7 @@ static struct fb_fix_screeninfo au1100fb_fix __initdata = {  	.accel		= FB_ACCEL_NONE,  }; -static struct fb_var_screeninfo au1100fb_var __initdata = { +static struct fb_var_screeninfo au1100fb_var __devinitdata = {  	.activate	= FB_ACTIVATE_NOW,  	.height		= -1,  	.width		= -1, @@ -458,7 +458,7 @@ static struct fb_ops au1100fb_ops =  /* AU1100 LCD controller device driver */ -static int __init au1100fb_drv_probe(struct platform_device *dev) +static int __devinit au1100fb_drv_probe(struct platform_device *dev)  {  	struct au1100fb_device *fbdev = NULL;  	struct resource *regs_res; diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 3a561df2e8a..0c1afd13ddd 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -388,6 +388,7 @@ cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,  		pseudo_val |= convert_bitfield(red, &var->red);  		pseudo_val |= convert_bitfield(green, &var->green);  		pseudo_val |= convert_bitfield(blue, &var->blue); +		ret = 0;  		break;  	} @@ -436,6 +437,8 @@ static void cyber2000fb_write_ramdac_ctrl(struct cfb_info *cfb)  	cyber2000fb_writeb(i | 4, 0x3cf, cfb);  	cyber2000fb_writeb(val, 0x3c6, cfb);  	cyber2000fb_writeb(i, 0x3cf, cfb); +	/* prevent card lock-up observed on x86 with CyberPro 2000 */ +	cyber2000fb_readb(0x3cf, cfb);  }  static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw) diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index 7d8c55d7fd2..ca3355e430b 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -91,10 +91,10 @@ static uint32_t pseudo_palette[16];  static uint32_t gbe_cmap[256];  static int gbe_turned_on; /* 0 turned off, 1 turned on */ -static char *mode_option __initdata = NULL; +static char *mode_option __devinitdata = NULL;  /* default CRT mode */ -static struct fb_var_screeninfo default_var_CRT __initdata = { +static struct fb_var_screeninfo default_var_CRT __devinitdata = {  	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */  	.xres		= 640,  	.yres		= 480, @@ -125,7 +125,7 @@ static struct fb_var_screeninfo default_var_CRT __initdata = {  };  /* default LCD mode */ -static struct fb_var_screeninfo default_var_LCD __initdata = { +static struct fb_var_screeninfo default_var_LCD __devinitdata = {  	/* 1600x1024, 8 bpp */  	.xres		= 1600,  	.yres		= 1024, @@ -157,7 +157,7 @@ static struct fb_var_screeninfo default_var_LCD __initdata = {  /* default modedb mode */  /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */ -static struct fb_videomode default_mode_CRT __initdata = { +static struct fb_videomode default_mode_CRT __devinitdata = {  	.refresh	= 60,  	.xres		= 640,  	.yres		= 480, @@ -172,7 +172,7 @@ static struct fb_videomode default_mode_CRT __initdata = {  	.vmode		= FB_VMODE_NONINTERLACED,  };  /* 1600x1024 SGI flatpanel 1600sw */ -static struct fb_videomode default_mode_LCD __initdata = { +static struct fb_videomode default_mode_LCD __devinitdata = {  	/* 1600x1024, 8 bpp */  	.xres		= 1600,  	.yres		= 1024, @@ -186,8 +186,8 @@ static struct fb_videomode default_mode_LCD __initdata = {  	.vmode		= FB_VMODE_NONINTERLACED,  }; -static struct fb_videomode *default_mode __initdata = &default_mode_CRT; -static struct fb_var_screeninfo *default_var __initdata = &default_var_CRT; +static struct fb_videomode *default_mode __devinitdata = &default_mode_CRT; +static struct fb_var_screeninfo *default_var __devinitdata = &default_var_CRT;  static int flat_panel_enabled = 0; @@ -1098,7 +1098,7 @@ static void gbefb_create_sysfs(struct device *dev)   * Initialization   */ -static int __init gbefb_setup(char *options) +static int __devinit gbefb_setup(char *options)  {  	char *this_opt; diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c index 76e7dac6f25..70b1d9d51c9 100644 --- a/drivers/video/geode/gxfb_core.c +++ b/drivers/video/geode/gxfb_core.c @@ -40,7 +40,7 @@ static int vram;  static int vt_switch;  /* Modes relevant to the GX (taken from modedb.c) */ -static struct fb_videomode gx_modedb[] __initdata = { +static struct fb_videomode gx_modedb[] __devinitdata = {  	/* 640x480-60 VESA */  	{ NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,  	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, @@ -110,14 +110,15 @@ static struct fb_videomode gx_modedb[] __initdata = {  #ifdef CONFIG_OLPC  #include <asm/olpc.h> -static struct fb_videomode gx_dcon_modedb[] __initdata = { +static struct fb_videomode gx_dcon_modedb[] __devinitdata = {  	/* The only mode the DCON has is 1200x900 */  	{ NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,  	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,  	  FB_VMODE_NONINTERLACED, 0 }  }; -static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) +static void __devinit get_modedb(struct fb_videomode **modedb, +		unsigned int *size)  {  	if (olpc_has_dcon()) {  		*modedb = (struct fb_videomode *) gx_dcon_modedb; @@ -129,7 +130,8 @@ static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)  }  #else -static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) +static void __devinit get_modedb(struct fb_videomode **modedb, +		unsigned int *size)  {  	*modedb = (struct fb_videomode *) gx_modedb;  	*size = ARRAY_SIZE(gx_modedb); @@ -226,7 +228,8 @@ static int gxfb_blank(int blank_mode, struct fb_info *info)  	return gx_blank_display(info, blank_mode);  } -static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev) +static int __devinit gxfb_map_video_memory(struct fb_info *info, +		struct pci_dev *dev)  {  	struct gxfb_par *par = info->par;  	int ret; @@ -290,7 +293,7 @@ static struct fb_ops gxfb_ops = {  	.fb_imageblit	= cfb_imageblit,  }; -static struct fb_info * __init gxfb_init_fbinfo(struct device *dev) +static struct fb_info *__devinit gxfb_init_fbinfo(struct device *dev)  {  	struct gxfb_par *par;  	struct fb_info *info; @@ -371,7 +374,8 @@ static int gxfb_resume(struct pci_dev *pdev)  }  #endif -static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) +static int __devinit gxfb_probe(struct pci_dev *pdev, +		const struct pci_device_id *id)  {  	struct gxfb_par *par;  	struct fb_info *info; @@ -451,7 +455,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i  	return ret;  } -static void gxfb_remove(struct pci_dev *pdev) +static void __devexit gxfb_remove(struct pci_dev *pdev)  {  	struct fb_info *info = pci_get_drvdata(pdev);  	struct gxfb_par *par = info->par; diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c index 1a18da86d3f..39bdbedf43b 100644 --- a/drivers/video/geode/lxfb_core.c +++ b/drivers/video/geode/lxfb_core.c @@ -35,7 +35,7 @@ static int vt_switch;   * we try to make it something sane - 640x480-60 is sane   */ -static struct fb_videomode geode_modedb[] __initdata = { +static struct fb_videomode geode_modedb[] __devinitdata = {  	/* 640x480-60 */  	{ NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,  	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, @@ -219,14 +219,15 @@ static struct fb_videomode geode_modedb[] __initdata = {  #ifdef CONFIG_OLPC  #include <asm/olpc.h> -static struct fb_videomode olpc_dcon_modedb[] __initdata = { +static struct fb_videomode olpc_dcon_modedb[] __devinitdata = {  	/* The only mode the DCON has is 1200x900 */  	{ NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,  	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,  	  FB_VMODE_NONINTERLACED, 0 }  }; -static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) +static void __devinit get_modedb(struct fb_videomode **modedb, +		unsigned int *size)  {  	if (olpc_has_dcon()) {  		*modedb = (struct fb_videomode *) olpc_dcon_modedb; @@ -238,7 +239,8 @@ static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size)  }  #else -static void __init get_modedb(struct fb_videomode **modedb, unsigned int *size) +static void __devinit get_modedb(struct fb_videomode **modedb, +		unsigned int *size)  {  	*modedb = (struct fb_videomode *) geode_modedb;  	*size = ARRAY_SIZE(geode_modedb); @@ -334,7 +336,7 @@ static int lxfb_blank(int blank_mode, struct fb_info *info)  } -static int __init lxfb_map_video_memory(struct fb_info *info, +static int __devinit lxfb_map_video_memory(struct fb_info *info,  					struct pci_dev *dev)  {  	struct lxfb_par *par = info->par; @@ -412,7 +414,7 @@ static struct fb_ops lxfb_ops = {  	.fb_imageblit	= cfb_imageblit,  }; -static struct fb_info * __init lxfb_init_fbinfo(struct device *dev) +static struct fb_info * __devinit lxfb_init_fbinfo(struct device *dev)  {  	struct lxfb_par *par;  	struct fb_info *info; @@ -496,7 +498,7 @@ static int lxfb_resume(struct pci_dev *pdev)  #define lxfb_resume NULL  #endif -static int __init lxfb_probe(struct pci_dev *pdev, +static int __devinit lxfb_probe(struct pci_dev *pdev,  			     const struct pci_device_id *id)  {  	struct lxfb_par *par; @@ -588,7 +590,7 @@ err:  	return ret;  } -static void lxfb_remove(struct pci_dev *pdev) +static void __devexit lxfb_remove(struct pci_dev *pdev)  {  	struct fb_info *info = pci_get_drvdata(pdev);  	struct lxfb_par *par = info->par; diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index b4b6deceed1..43f0639b1c1 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -175,6 +175,7 @@ struct imxfb_info {  	struct imx_fb_videomode *mode;  	int			num_modes; +	struct backlight_device *bl;  	void (*lcd_power)(int);  	void (*backlight_power)(int); @@ -449,6 +450,73 @@ static int imxfb_set_par(struct fb_info *info)  	return 0;  } + + +static int imxfb_bl_get_brightness(struct backlight_device *bl) +{ +	struct imxfb_info *fbi = bl_get_data(bl); + +	return readl(fbi->regs + LCDC_PWMR) & 0xFF; +} + +static int imxfb_bl_update_status(struct backlight_device *bl) +{ +	struct imxfb_info *fbi = bl_get_data(bl); +	int brightness = bl->props.brightness; + +	if (bl->props.power != FB_BLANK_UNBLANK) +		brightness = 0; +	if (bl->props.fb_blank != FB_BLANK_UNBLANK) +		brightness = 0; + +	fbi->pwmr = (fbi->pwmr & ~0xFF) | brightness; + +	if (bl->props.fb_blank != FB_BLANK_UNBLANK) +		clk_enable(fbi->clk); +	writel(fbi->pwmr, fbi->regs + LCDC_PWMR); +	if (bl->props.fb_blank != FB_BLANK_UNBLANK) +		clk_disable(fbi->clk); + +	return 0; +} + +static const struct backlight_ops imxfb_lcdc_bl_ops = { +	.update_status = imxfb_bl_update_status, +	.get_brightness = imxfb_bl_get_brightness, +}; + +static void imxfb_init_backlight(struct imxfb_info *fbi) +{ +	struct backlight_properties props; +	struct backlight_device	*bl; + +	if (fbi->bl) +		return; + +	memset(&props, 0, sizeof(struct backlight_properties)); +	props.max_brightness = 0xff; +	writel(fbi->pwmr, fbi->regs + LCDC_PWMR); + +	bl = backlight_device_register("imxfb-bl", &fbi->pdev->dev, fbi, +				       &imxfb_lcdc_bl_ops, &props); +	if (IS_ERR(bl)) { +		dev_err(&fbi->pdev->dev, "error %ld on backlight register\n", +				PTR_ERR(bl)); +		return; +	} + +	fbi->bl = bl; +	bl->props.power = FB_BLANK_UNBLANK; +	bl->props.fb_blank = FB_BLANK_UNBLANK; +	bl->props.brightness = imxfb_bl_get_brightness(bl); +} + +static void imxfb_exit_backlight(struct imxfb_info *fbi) +{ +	if (fbi->bl) +		backlight_device_unregister(fbi->bl); +} +  static void imxfb_enable_controller(struct imxfb_info *fbi)  {  	pr_debug("Enabling LCD controller\n"); @@ -579,7 +647,6 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf  			fbi->regs + LCDC_SIZE);  	writel(fbi->pcr, fbi->regs + LCDC_PCR); -	writel(fbi->pwmr, fbi->regs + LCDC_PWMR);  	writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);  	writel(fbi->dmacr, fbi->regs + LCDC_DMACR); @@ -779,6 +846,8 @@ static int __init imxfb_probe(struct platform_device *pdev)  	}  	imxfb_enable_controller(fbi); +	fbi->pdev = pdev; +	imxfb_init_backlight(fbi);  	return 0; @@ -816,6 +885,7 @@ static int __devexit imxfb_remove(struct platform_device *pdev)  	imxfb_disable_controller(fbi); +	imxfb_exit_backlight(fbi);  	unregister_framebuffer(info);  	pdata = pdev->dev.platform_data; diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c index d4cde79ea15..81687ed26ba 100644 --- a/drivers/video/nuc900fb.c +++ b/drivers/video/nuc900fb.c @@ -596,8 +596,6 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev)  		goto release_regs;  	} -	nuc900_driver_clksrc_div(&pdev->dev, "ext", 0x2); -  	fbi->clk = clk_get(&pdev->dev, NULL);  	if (!fbi->clk || IS_ERR(fbi->clk)) {  		printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n"); diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c index 43ab7d8b66b..7767338f8b1 100644 --- a/drivers/video/omap/lcdc.c +++ b/drivers/video/omap/lcdc.c @@ -572,22 +572,12 @@ static enum omapfb_update_mode omap_lcdc_get_update_mode(void)  /* PM code called only in internal controller mode */  static void omap_lcdc_suspend(void)  { -	if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) { -		disable_controller(); -		omap_stop_lcd_dma(); -	} +	omap_lcdc_set_update_mode(OMAPFB_UPDATE_DISABLED);  }  static void omap_lcdc_resume(void)  { -	if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) { -		setup_regs(); -		load_palette(); -		setup_lcd_dma(); -		set_load_mode(OMAP_LCDC_LOAD_FRAME); -		enable_irqs(OMAP_LCDC_IRQ_DONE); -		enable_controller(); -	} +	omap_lcdc_set_update_mode(OMAPFB_AUTO_UPDATE);  }  static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps) diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c index 1162603c72e..eada9f12efc 100644 --- a/drivers/video/omap/rfbi.c +++ b/drivers/video/omap/rfbi.c @@ -26,6 +26,7 @@  #include <linux/interrupt.h>  #include <linux/clk.h>  #include <linux/io.h> +#include <linux/platform_device.h>  #include "omapfb.h"  #include "dispc.h" @@ -83,13 +84,13 @@ static inline u32 rfbi_read_reg(int idx)  static int rfbi_get_clocks(void)  { -	rfbi.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick"); +	rfbi.dss_ick = clk_get(&rfbi.fbdev->dssdev->dev, "ick");  	if (IS_ERR(rfbi.dss_ick)) {  		dev_err(rfbi.fbdev->dev, "can't get ick\n");  		return PTR_ERR(rfbi.dss_ick);  	} -	rfbi.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck"); +	rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "dss1_fck");  	if (IS_ERR(rfbi.dss1_fck)) {  		dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n");  		clk_put(rfbi.dss_ick); diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c index 3b1237ad85e..f6fdc2085f3 100644 --- a/drivers/video/omap2/vram.c +++ b/drivers/video/omap2/vram.c @@ -25,7 +25,7 @@  #include <linux/list.h>  #include <linux/slab.h>  #include <linux/seq_file.h> -#include <linux/bootmem.h> +#include <linux/memblock.h>  #include <linux/completion.h>  #include <linux/debugfs.h>  #include <linux/jiffies.h> @@ -525,10 +525,8 @@ early_param("vram", omap_vram_early_vram);   * Called from map_io. We need to call to this early enough so that we   * can reserve the fixed SDRAM regions before VM could get hold of them.   */ -void __init omap_vram_reserve_sdram(void) +void __init omap_vram_reserve_sdram_memblock(void)  { -	struct bootmem_data	*bdata; -	unsigned long		sdram_start, sdram_size;  	u32 paddr;  	u32 size = 0; @@ -555,29 +553,28 @@ void __init omap_vram_reserve_sdram(void)  	size = PAGE_ALIGN(size); -	bdata = NODE_DATA(0)->bdata; -	sdram_start = bdata->node_min_pfn << PAGE_SHIFT; -	sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; -  	if (paddr) { -		if ((paddr & ~PAGE_MASK) || paddr < sdram_start || -				paddr + size > sdram_start + sdram_size) { +		struct memblock_property res; + +		res.base = paddr; +		res.size = size; +		if ((paddr & ~PAGE_MASK) || memblock_find(&res) || +		    res.base != paddr || res.size != size) {  			pr_err("Illegal SDRAM region for VRAM\n");  			return;  		} -		if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) { -			pr_err("FB: failed to reserve VRAM\n"); +		if (memblock_is_region_reserved(paddr, size)) { +			pr_err("FB: failed to reserve VRAM - busy\n");  			return;  		} -	} else { -		if (size > sdram_size) { -			pr_err("Illegal SDRAM size for VRAM\n"); + +		if (memblock_reserve(paddr, size) < 0) { +			pr_err("FB: failed to reserve VRAM - no memory\n");  			return;  		} - -		paddr = virt_to_phys(alloc_bootmem_pages(size)); -		BUG_ON(paddr & ~PAGE_MASK); +	} else { +		paddr = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_REAL_LIMIT);  	}  	omap_vram_add_region(paddr, size); diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index 0f361b6100d..0c69fa20251 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -44,7 +44,7 @@ struct pmagbafb_par {  }; -static struct fb_var_screeninfo pmagbafb_defined __initdata = { +static struct fb_var_screeninfo pmagbafb_defined __devinitdata = {  	.xres		= 1024,  	.yres		= 864,  	.xres_virtual	= 1024, @@ -68,7 +68,7 @@ static struct fb_var_screeninfo pmagbafb_defined __initdata = {  	.vmode		= FB_VMODE_NONINTERLACED,  }; -static struct fb_fix_screeninfo pmagbafb_fix __initdata = { +static struct fb_fix_screeninfo pmagbafb_fix __devinitdata = {  	.id		= "PMAG-BA",  	.smem_len	= (1024 * 1024),  	.type		= FB_TYPE_PACKED_PIXELS, @@ -142,7 +142,7 @@ static void __init pmagbafb_erase_cursor(struct fb_info *info)  } -static int __init pmagbafb_probe(struct device *dev) +static int __devinit pmagbafb_probe(struct device *dev)  {  	struct tc_dev *tdev = to_tc_dev(dev);  	resource_size_t start, len; diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index 2de0806421b..22fcb9a3d5c 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -45,7 +45,7 @@ struct pmagbbfb_par {  }; -static struct fb_var_screeninfo pmagbbfb_defined __initdata = { +static struct fb_var_screeninfo pmagbbfb_defined __devinitdata = {  	.bits_per_pixel	= 8,  	.red.length	= 8,  	.green.length	= 8, @@ -58,7 +58,7 @@ static struct fb_var_screeninfo pmagbbfb_defined __initdata = {  	.vmode		= FB_VMODE_NONINTERLACED,  }; -static struct fb_fix_screeninfo pmagbbfb_fix __initdata = { +static struct fb_fix_screeninfo pmagbbfb_fix __devinitdata = {  	.id		= "PMAGB-BA",  	.smem_len	= (2048 * 1024),  	.type		= FB_TYPE_PACKED_PIXELS, @@ -148,7 +148,7 @@ static void __init pmagbbfb_erase_cursor(struct fb_info *info)  /*   * Set up screen parameters.   */ -static void __init pmagbbfb_screen_setup(struct fb_info *info) +static void __devinit pmagbbfb_screen_setup(struct fb_info *info)  {  	struct pmagbbfb_par *par = info->par; @@ -180,9 +180,9 @@ static void __init pmagbbfb_screen_setup(struct fb_info *info)  /*   * Determine oscillator configuration.   */ -static void __init pmagbbfb_osc_setup(struct fb_info *info) +static void __devinit pmagbbfb_osc_setup(struct fb_info *info)  { -	static unsigned int pmagbbfb_freqs[] __initdata = { +	static unsigned int pmagbbfb_freqs[] __devinitdata = {  		130808, 119843, 104000, 92980, 74370, 72800,  		69197, 66000, 65000, 50350, 36000, 32000, 25175  	}; @@ -247,7 +247,7 @@ static void __init pmagbbfb_osc_setup(struct fb_info *info)  }; -static int __init pmagbbfb_probe(struct device *dev) +static int __devinit pmagbbfb_probe(struct device *dev)  {  	struct tc_dev *tdev = to_tc_dev(dev);  	resource_size_t start, len; diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 95896f38792..ef8d9d558fc 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -636,6 +636,9 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,  	INIT_LIST_HEAD(&vp_dev->virtqueues);  	spin_lock_init(&vp_dev->lock); +	/* Disable MSI/MSIX to bring device to a known good state. */ +	pci_msi_off(pci_dev); +  	/* enable the device */  	err = pci_enable_device(pci_dev);  	if (err) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 1ca88908723..1475ed6b575 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -119,7 +119,7 @@ static int vring_add_indirect(struct vring_virtqueue *vq,  	desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp);  	if (!desc) -		return vq->vring.num; +		return -ENOMEM;  	/* Transfer entries from the sg list into the indirect page */  	for (i = 0; i < out; i++) { @@ -164,7 +164,8 @@ int virtqueue_add_buf_gfp(struct virtqueue *_vq,  			  gfp_t gfp)  {  	struct vring_virtqueue *vq = to_vvq(_vq); -	unsigned int i, avail, head, uninitialized_var(prev); +	unsigned int i, avail, uninitialized_var(prev); +	int head;  	START_USE(vq); @@ -174,7 +175,7 @@ int virtqueue_add_buf_gfp(struct virtqueue *_vq,  	 * buffers, then go indirect. FIXME: tune this threshold */  	if (vq->indirect && (out + in) > 1 && vq->num_free) {  		head = vring_add_indirect(vq, sg, out, in, gfp); -		if (head != vq->vring.num) +		if (likely(head >= 0))  			goto add_head;  	} diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index 1cddf92cb9a..750bc5281d7 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c @@ -346,9 +346,13 @@ static int __init at32_wdt_probe(struct platform_device *pdev)  	} else {  		wdt->users = 0;  	} -	wdt->miscdev.minor = WATCHDOG_MINOR; -	wdt->miscdev.name = "watchdog"; -	wdt->miscdev.fops = &at32_wdt_fops; + +	wdt->miscdev.minor	= WATCHDOG_MINOR; +	wdt->miscdev.name	= "watchdog"; +	wdt->miscdev.fops	= &at32_wdt_fops; +	wdt->miscdev.parent	= &pdev->dev; + +	platform_set_drvdata(pdev, wdt);  	if (at32_wdt_settimeout(timeout)) {  		at32_wdt_settimeout(TIMEOUT_DEFAULT); @@ -360,17 +364,17 @@ static int __init at32_wdt_probe(struct platform_device *pdev)  	ret = misc_register(&wdt->miscdev);  	if (ret) {  		dev_dbg(&pdev->dev, "failed to register wdt miscdev\n"); -		goto err_iounmap; +		goto err_register;  	} -	platform_set_drvdata(pdev, wdt); -	wdt->miscdev.parent = &pdev->dev;  	dev_info(&pdev->dev,  		"AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n",  		wdt->regs, wdt->timeout, nowayout);  	return 0; +err_register: +	platform_set_drvdata(pdev, NULL);  err_iounmap:  	iounmap(wdt->regs);  err_free: diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index ea25885781b..2ee7dac55a3 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -330,7 +330,6 @@ static void imx2_wdt_shutdown(struct platform_device *pdev)  }  static struct platform_driver imx2_wdt_driver = { -	.probe		= imx2_wdt_probe,  	.remove		= __exit_p(imx2_wdt_remove),  	.shutdown	= imx2_wdt_shutdown,  	.driver		= {  |