diff options
151 files changed, 1552 insertions, 1100 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index a0c5c5f4fce..5e22c3f1f8b 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -315,8 +315,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.  			CPU-intensive style benchmark, and it can vary highly in  			a microbenchmark depending on workload and compiler. -			1: only for 32-bit processes -			2: only for 64-bit processes +			32: only for 32-bit processes +			64: only for 64-bit processes  			on: enable for both 32- and 64-bit processes  			off: disable for both 32- and 64-bit processes diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index cb2b1c6a2ce..ad3e80e17b4 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -295,11 +295,11 @@ tcp_max_ssthresh - INTEGER  	Default: 0 (off)  tcp_max_syn_backlog - INTEGER -	Maximal number of remembered connection requests, which are -	still did not receive an acknowledgment from connecting client. -	Default value is 1024 for systems with more than 128Mb of memory, -	and 128 for low memory machines. If server suffers of overload, -	try to increase this number. +	Maximal number of remembered connection requests, which have not +	received an acknowledgment from connecting client. +	The minimal value is 128 for low memory machines, and it will +	increase in proportion to the memory of machine. +	If server suffers from overload, try increasing this number.  tcp_max_tw_buckets - INTEGER  	Maximal number of timewait sockets held by system simultaneously. diff --git a/Documentation/usb/linux-cdc-acm.inf b/Documentation/usb/linux-cdc-acm.inf index 37a02ce5484..f0ffc27d4c0 100644 --- a/Documentation/usb/linux-cdc-acm.inf +++ b/Documentation/usb/linux-cdc-acm.inf @@ -90,10 +90,10 @@ ServiceBinary=%12%\USBSER.sys  [SourceDisksFiles]  [SourceDisksNames]  [DeviceList] -%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02 +%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00  [DeviceList.NTamd64] -%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02 +%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00  ;------------------------------------------------------------------------------ diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index c475379199b..8e9c98edc06 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -353,15 +353,15 @@ validate_group(struct perf_event *event)  	fake_pmu.used_mask = fake_used_mask;  	if (!validate_event(&fake_pmu, leader)) -		return -ENOSPC; +		return -EINVAL;  	list_for_each_entry(sibling, &leader->sibling_list, group_entry) {  		if (!validate_event(&fake_pmu, sibling)) -			return -ENOSPC; +			return -EINVAL;  	}  	if (!validate_event(&fake_pmu, event)) -		return -ENOSPC; +		return -EINVAL;  	return 0;  } diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 4f2971bcf8e..315fc0b250f 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -623,7 +623,7 @@ static int mipspmu_event_init(struct perf_event *event)  	if (!atomic_inc_not_zero(&active_events)) {  		if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) {  			atomic_dec(&active_events); -			return -ENOSPC; +			return -EINVAL;  		}  		mutex_lock(&pmu_reserve_mutex); @@ -732,15 +732,15 @@ static int validate_group(struct perf_event *event)  	memset(&fake_cpuc, 0, sizeof(fake_cpuc));  	if (!validate_event(&fake_cpuc, leader)) -		return -ENOSPC; +		return -EINVAL;  	list_for_each_entry(sibling, &leader->sibling_list, group_entry) {  		if (!validate_event(&fake_cpuc, sibling)) -			return -ENOSPC; +			return -EINVAL;  	}  	if (!validate_event(&fake_cpuc, event)) -		return -ENOSPC; +		return -EINVAL;  	return 0;  } diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 524d23b8610..4f289ff0b7f 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -599,10 +599,10 @@ static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste)  	skey = page_get_storage_key(address);  	bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);  	/* Clear page changed & referenced bit in the storage key */ -	if (bits) { -		skey ^= bits; -		page_set_storage_key(address, skey, 1); -	} +	if (bits & _PAGE_CHANGED) +		page_set_storage_key(address, skey ^ bits, 1); +	else if (bits) +		page_reset_referenced(address);  	/* Transfer page changed & referenced bit to guest bits in pgste */  	pgste_val(pgste) |= bits << 48;		/* RCP_GR_BIT & RCP_GC_BIT */  	/* Get host changed & referenced bits from pgste */ diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 450931a45b6..573bc29551e 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -296,13 +296,6 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)  		     ((data & PSW_MASK_EA) && !(data & PSW_MASK_BA))))  			/* Invalid psw mask. */  			return -EINVAL; -		if (addr == (addr_t) &dummy->regs.psw.addr) -			/* -			 * The debugger changed the instruction address, -			 * reset system call restart, see signal.c:do_signal -			 */ -			task_thread_info(child)->system_call = 0; -  		*(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data;  	} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) { @@ -614,11 +607,6 @@ static int __poke_user_compat(struct task_struct *child,  			/* Transfer 31 bit amode bit to psw mask. */  			regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) |  				(__u64)(tmp & PSW32_ADDR_AMODE); -			/* -			 * The debugger changed the instruction address, -			 * reset system call restart, see signal.c:do_signal -			 */ -			task_thread_info(child)->system_call = 0;  		} else {  			/* gpr 0-15 */  			*(__u32*)((addr_t) ®s->psw + addr*2 + 4) = tmp; @@ -905,6 +893,14 @@ static int s390_last_break_get(struct task_struct *target,  	return 0;  } +static int s390_last_break_set(struct task_struct *target, +			       const struct user_regset *regset, +			       unsigned int pos, unsigned int count, +			       const void *kbuf, const void __user *ubuf) +{ +	return 0; +} +  #endif  static int s390_system_call_get(struct task_struct *target, @@ -951,6 +947,7 @@ static const struct user_regset s390_regsets[] = {  		.size = sizeof(long),  		.align = sizeof(long),  		.get = s390_last_break_get, +		.set = s390_last_break_set,  	},  #endif  	[REGSET_SYSTEM_CALL] = { @@ -1116,6 +1113,14 @@ static int s390_compat_last_break_get(struct task_struct *target,  	return 0;  } +static int s390_compat_last_break_set(struct task_struct *target, +				      const struct user_regset *regset, +				      unsigned int pos, unsigned int count, +				      const void *kbuf, const void __user *ubuf) +{ +	return 0; +} +  static const struct user_regset s390_compat_regsets[] = {  	[REGSET_GENERAL] = {  		.core_note_type = NT_PRSTATUS, @@ -1139,6 +1144,7 @@ static const struct user_regset s390_compat_regsets[] = {  		.size = sizeof(long),  		.align = sizeof(long),  		.get = s390_compat_last_break_get, +		.set = s390_compat_last_break_set,  	},  	[REGSET_SYSTEM_CALL] = {  		.core_note_type = NT_S390_SYSTEM_CALL, diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index e58a462949b..e54c4ff8aba 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -579,7 +579,7 @@ static unsigned long __init find_crash_base(unsigned long crash_size,  		*msg = "first memory chunk must be at least crashkernel size";  		return 0;  	} -	if (is_kdump_kernel() && (crash_size == OLDMEM_SIZE)) +	if (OLDMEM_BASE && crash_size == OLDMEM_SIZE)  		return OLDMEM_BASE;  	for (i = MEMORY_CHUNKS - 1; i >= 0; i--) { diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 05a85bc14c9..7f6f9f35454 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -460,9 +460,9 @@ void do_signal(struct pt_regs *regs)  						     regs->svc_code >> 16);  				break;  			} -			/* No longer in a system call */ -			clear_thread_flag(TIF_SYSCALL);  		} +		/* No longer in a system call */ +		clear_thread_flag(TIF_SYSCALL);  		if ((is_compat_task() ?  		     handle_signal32(signr, &ka, &info, oldset, regs) : @@ -486,6 +486,7 @@ void do_signal(struct pt_regs *regs)  	}  	/* No handlers present - check for system call restart */ +	clear_thread_flag(TIF_SYSCALL);  	if (current_thread_info()->system_call) {  		regs->svc_code = current_thread_info()->system_call;  		switch (regs->gprs[2]) { @@ -500,9 +501,6 @@ void do_signal(struct pt_regs *regs)  			regs->gprs[2] = regs->orig_gpr2;  			set_thread_flag(TIF_SYSCALL);  			break; -		default: -			clear_thread_flag(TIF_SYSCALL); -			break;  		}  	} diff --git a/arch/x86/include/asm/intel_scu_ipc.h b/arch/x86/include/asm/intel_scu_ipc.h index 4420993acc4..925b605eb5c 100644 --- a/arch/x86/include/asm/intel_scu_ipc.h +++ b/arch/x86/include/asm/intel_scu_ipc.h @@ -3,11 +3,15 @@  #include <linux/notifier.h> -#define IPCMSG_VRTC	0xFA	 /* Set vRTC device */ +#define IPCMSG_WARM_RESET	0xF0 +#define IPCMSG_COLD_RESET	0xF1 +#define IPCMSG_SOFT_RESET	0xF2 +#define IPCMSG_COLD_BOOT	0xF3 -/* Command id associated with message IPCMSG_VRTC */ -#define IPC_CMD_VRTC_SETTIME      1 /* Set time */ -#define IPC_CMD_VRTC_SETALARM     2 /* Set alarm */ +#define IPCMSG_VRTC		0xFA	 /* Set vRTC device */ +	/* Command id associated with message IPCMSG_VRTC */ +	#define IPC_CMD_VRTC_SETTIME      1 /* Set time */ +	#define IPC_CMD_VRTC_SETALARM     2 /* Set alarm */  /* Read single register */  int intel_scu_ipc_ioread8(u16 addr, u8 *data); diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h index e6283129c82..93f79094c22 100644 --- a/arch/x86/include/asm/mrst.h +++ b/arch/x86/include/asm/mrst.h @@ -31,11 +31,20 @@ enum mrst_cpu_type {  };  extern enum mrst_cpu_type __mrst_cpu_chip; + +#ifdef CONFIG_X86_INTEL_MID +  static inline enum mrst_cpu_type mrst_identify_cpu(void)  {  	return __mrst_cpu_chip;  } +#else /* !CONFIG_X86_INTEL_MID */ + +#define mrst_identify_cpu()    (0) + +#endif /* !CONFIG_X86_INTEL_MID */ +  enum mrst_timer_options {  	MRST_TIMER_DEFAULT,  	MRST_TIMER_APBT_ONLY, diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 084ef95274c..95203d40ffd 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -169,7 +169,14 @@ static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)  	return native_write_msr_safe(msr, low, high);  } -/* rdmsr with exception handling */ +/* + * rdmsr with exception handling. + * + * Please note that the exception handling works only after we've + * switched to the "smart" #GP handler in trap_init() which knows about + * exception tables - using this macro earlier than that causes machine + * hangs on boxes which do not implement the @msr in the first argument. + */  #define rdmsr_safe(msr, p1, p2)					\  ({								\  	int __err;						\ diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index c2ff2a1d845..2d2f01ce6dc 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h @@ -401,6 +401,7 @@ extern unsigned long arch_align_stack(unsigned long sp);  extern void free_init_pages(char *what, unsigned long begin, unsigned long end);  void default_idle(void); +bool set_pm_idle_to_default(void);  void stop_this_cpu(void *dummy); diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h index fa7b9176b76..431793e5d48 100644 --- a/arch/x86/include/asm/timer.h +++ b/arch/x86/include/asm/timer.h @@ -32,6 +32,22 @@ extern int no_timer_check;   *  (mathieu.desnoyers@polymtl.ca)   *   *			-johnstul@us.ibm.com "math is hard, lets go shopping!" + * + * In: + * + * ns = cycles * cyc2ns_scale / SC + * + * Although we may still have enough bits to store the value of ns, + * in some cases, we may not have enough bits to store cycles * cyc2ns_scale, + * leading to an incorrect result. + * + * To avoid this, we can decompose 'cycles' into quotient and remainder + * of division by SC.  Then, + * + * ns = (quot * SC + rem) * cyc2ns_scale / SC + *    = quot * cyc2ns_scale + (rem * cyc2ns_scale) / SC + * + *			- sqazi@google.com   */  DECLARE_PER_CPU(unsigned long, cyc2ns); @@ -41,9 +57,14 @@ DECLARE_PER_CPU(unsigned long long, cyc2ns_offset);  static inline unsigned long long __cycles_2_ns(unsigned long long cyc)  { +	unsigned long long quot; +	unsigned long long rem;  	int cpu = smp_processor_id();  	unsigned long long ns = per_cpu(cyc2ns_offset, cpu); -	ns += cyc * per_cpu(cyc2ns, cpu) >> CYC2NS_SCALE_FACTOR; +	quot = (cyc >> CYC2NS_SCALE_FACTOR); +	rem = cyc & ((1ULL << CYC2NS_SCALE_FACTOR) - 1); +	ns += quot * per_cpu(cyc2ns, cpu) + +		((rem * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR);  	return ns;  } diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h index 10474fb1185..cf1d73643f6 100644 --- a/arch/x86/include/asm/uv/uv_mmrs.h +++ b/arch/x86/include/asm/uv/uv_mmrs.h @@ -57,6 +57,7 @@  #define UV1_HUB_PART_NUMBER	0x88a5  #define UV2_HUB_PART_NUMBER	0x8eb8 +#define UV2_HUB_PART_NUMBER_X	0x1111  /* Compat: if this #define is present, UV headers support UV2 */  #define UV2_HUB_IS_SUPPORTED	1 diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 62ae3001ae0..9d59bbacd4e 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -93,6 +93,8 @@ static int __init early_get_pnodeid(void)  	if (node_id.s.part_number == UV2_HUB_PART_NUMBER)  		uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1; +	if (node_id.s.part_number == UV2_HUB_PART_NUMBER_X) +		uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1;  	uv_hub_info->hub_revision = uv_min_hub_revision_id;  	pnode = (node_id.s.node_id >> 1) & ((1 << m_n_config.s.n_skt) - 1); diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index c7e46cb3532..0bab2b18bb2 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -442,8 +442,6 @@ static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c)  static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)  { -	u32 dummy; -  	early_init_amd_mc(c);  	/* @@ -473,12 +471,12 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)  			set_cpu_cap(c, X86_FEATURE_EXTD_APICID);  	}  #endif - -	rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);  }  static void __cpuinit init_amd(struct cpuinfo_x86 *c)  { +	u32 dummy; +  #ifdef CONFIG_SMP  	unsigned long long value; @@ -657,6 +655,8 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)  			checking_wrmsrl(MSR_AMD64_MCx_MASK(4), mask);  		}  	} + +	rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);  }  #ifdef CONFIG_X86_32 diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index a71efcdbb09..97b26356e9e 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -547,6 +547,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,  		if (tmp != mask_lo) {  			printk(KERN_WARNING "mtrr: your BIOS has configured an incorrect mask, fixing it.\n"); +			add_taint(TAINT_FIRMWARE_WORKAROUND);  			mask_lo = tmp;  		}  	} @@ -693,6 +694,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)  	/* Disable MTRRs, and set the default type to uncached */  	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi); +	wbinvd();  }  static void post_set(void) __releases(set_atomicity_lock) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 640891014b2..2bda212a001 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -312,12 +312,8 @@ int x86_setup_perfctr(struct perf_event *event)  			return -EOPNOTSUPP;  	} -	/* -	 * Do not allow config1 (extended registers) to propagate, -	 * there's no sane user-space generalization yet: -	 */  	if (attr->type == PERF_TYPE_RAW) -		return 0; +		return x86_pmu_extra_regs(event->attr.config, event);  	if (attr->type == PERF_TYPE_HW_CACHE)  		return set_ext_hw_attr(hwc, event); @@ -588,7 +584,7 @@ done:  				x86_pmu.put_event_constraints(cpuc, cpuc->event_list[i]);  		}  	} -	return num ? -ENOSPC : 0; +	return num ? -EINVAL : 0;  }  /* @@ -607,7 +603,7 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader,  	if (is_x86_event(leader)) {  		if (n >= max_count) -			return -ENOSPC; +			return -EINVAL;  		cpuc->event_list[n] = leader;  		n++;  	} @@ -620,7 +616,7 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader,  			continue;  		if (n >= max_count) -			return -ENOSPC; +			return -EINVAL;  		cpuc->event_list[n] = event;  		n++; @@ -1316,7 +1312,7 @@ static int validate_event(struct perf_event *event)  	c = x86_pmu.get_event_constraints(fake_cpuc, event);  	if (!c || !c->weight) -		ret = -ENOSPC; +		ret = -EINVAL;  	if (x86_pmu.put_event_constraints)  		x86_pmu.put_event_constraints(fake_cpuc, event); @@ -1341,7 +1337,7 @@ static int validate_group(struct perf_event *event)  {  	struct perf_event *leader = event->group_leader;  	struct cpu_hw_events *fake_cpuc; -	int ret = -ENOSPC, n; +	int ret = -EINVAL, n;  	fake_cpuc = allocate_fake_cpuc();  	if (IS_ERR(fake_cpuc)) diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index ab6343d2182..3b8a2d30d14 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -199,8 +199,7 @@ static int force_ibs_eilvt_setup(void)  		goto out;  	} -	pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset); -	pr_err(FW_BUG "workaround enabled for IBS LVT offset\n"); +	pr_info("IBS: LVT offset %d assigned\n", offset);  	return 0;  out: @@ -265,19 +264,23 @@ perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *h  static __init int amd_ibs_init(void)  {  	u32 caps; -	int ret; +	int ret = -EINVAL;  	caps = __get_ibs_caps();  	if (!caps)  		return -ENODEV;	/* ibs not supported by the cpu */ -	if (!ibs_eilvt_valid()) { -		ret = force_ibs_eilvt_setup(); -		if (ret) { -			pr_err("Failed to setup IBS, %d\n", ret); -			return ret; -		} -	} +	/* +	 * Force LVT offset assignment for family 10h: The offsets are +	 * not assigned by the BIOS for this family, so the OS is +	 * responsible for doing it. If the OS assignment fails, fall +	 * back to BIOS settings and try to setup this. +	 */ +	if (boot_cpu_data.x86 == 0x10) +		force_ibs_eilvt_setup(); + +	if (!ibs_eilvt_valid()) +		goto out;  	get_online_cpus();  	ibs_caps = caps; @@ -287,7 +290,11 @@ static __init int amd_ibs_init(void)  	smp_call_function(setup_APIC_ibs, NULL, 1);  	put_online_cpus(); -	return perf_event_ibs_init(); +	ret = perf_event_ibs_init(); +out: +	if (ret) +		pr_err("Failed to setup IBS, %d\n", ret); +	return ret;  }  /* Since we need the pci subsystem to init ibs we can't do this earlier: */ diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 2be5ebe9987..8d601b18bf9 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1545,6 +1545,13 @@ static void intel_clovertown_quirks(void)  	x86_pmu.pebs_constraints = NULL;  } +static void intel_sandybridge_quirks(void) +{ +	printk(KERN_WARNING "PEBS disabled due to CPU errata.\n"); +	x86_pmu.pebs = 0; +	x86_pmu.pebs_constraints = NULL; +} +  __init int intel_pmu_init(void)  {  	union cpuid10_edx edx; @@ -1694,6 +1701,7 @@ __init int intel_pmu_init(void)  		break;  	case 42: /* SandyBridge */ +		x86_pmu.quirks = intel_sandybridge_quirks;  	case 45: /* SandyBridge, "Romely-EP" */  		memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,  		       sizeof(hw_cache_event_ids)); diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index c0d238f49db..73da6b64f5b 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -493,6 +493,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)  	unsigned long from = cpuc->lbr_entries[0].from;  	unsigned long old_to, to = cpuc->lbr_entries[0].to;  	unsigned long ip = regs->ip; +	int is_64bit = 0;  	/*  	 * We don't need to fixup if the PEBS assist is fault like @@ -544,7 +545,10 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)  		} else  			kaddr = (void *)to; -		kernel_insn_init(&insn, kaddr); +#ifdef CONFIG_X86_64 +		is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32); +#endif +		insn_init(&insn, kaddr, is_64bit);  		insn_get_length(&insn);  		to += insn.length;  	} while (to < ip); diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 492bf1358a7..ef484d9d0a2 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -1268,7 +1268,7 @@ reserve:  	}  done: -	return num ? -ENOSPC : 0; +	return num ? -EINVAL : 0;  }  static __initconst const struct x86_pmu p4_pmu = { diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index acf8fbf8fbd..69bca468c47 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -38,6 +38,9 @@ static inline void stack_overflow_check(struct pt_regs *regs)  #ifdef CONFIG_DEBUG_STACKOVERFLOW  	u64 curbase = (u64)task_stack_page(current); +	if (user_mode_vm(regs)) +		return; +  	WARN_ONCE(regs->sp >= curbase &&  		  regs->sp <= curbase + THREAD_SIZE &&  		  regs->sp <  curbase + sizeof(struct thread_info) + diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index f2d2a664e79..9d46f5e43b5 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -256,7 +256,7 @@ static int __init microcode_dev_init(void)  	return 0;  } -static void microcode_dev_exit(void) +static void __exit microcode_dev_exit(void)  {  	misc_deregister(µcode_dev);  } @@ -519,10 +519,8 @@ static int __init microcode_init(void)  	microcode_pdev = platform_device_register_simple("microcode", -1,  							 NULL, 0); -	if (IS_ERR(microcode_pdev)) { -		microcode_dev_exit(); +	if (IS_ERR(microcode_pdev))  		return PTR_ERR(microcode_pdev); -	}  	get_online_cpus();  	mutex_lock(µcode_mutex); @@ -532,14 +530,12 @@ static int __init microcode_init(void)  	mutex_unlock(µcode_mutex);  	put_online_cpus(); -	if (error) { -		platform_device_unregister(microcode_pdev); -		return error; -	} +	if (error) +		goto out_pdev;  	error = microcode_dev_init();  	if (error) -		return error; +		goto out_sysdev_driver;  	register_syscore_ops(&mc_syscore_ops);  	register_hotcpu_notifier(&mc_cpu_notifier); @@ -548,6 +544,20 @@ static int __init microcode_init(void)  		" <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n");  	return 0; + +out_sysdev_driver: +	get_online_cpus(); +	mutex_lock(µcode_mutex); + +	sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); + +	mutex_unlock(µcode_mutex); +	put_online_cpus(); + +out_pdev: +	platform_device_unregister(microcode_pdev); +	return error; +  }  module_init(microcode_init); diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 9103b89c145..0741b062a30 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -95,8 +95,8 @@ static void __init MP_bus_info(struct mpc_bus *m)  	}  #endif +	set_bit(m->busid, mp_bus_not_pci);  	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) { -		set_bit(m->busid, mp_bus_not_pci);  #if defined(CONFIG_EISA) || defined(CONFIG_MCA)  		mp_bus_id_to_type[m->busid] = MP_BUS_ISA;  #endif diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index b9b3b1a5164..ee5d4fbd53b 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -403,6 +403,14 @@ void default_idle(void)  EXPORT_SYMBOL(default_idle);  #endif +bool set_pm_idle_to_default(void) +{ +	bool ret = !!pm_idle; + +	pm_idle = default_idle; + +	return ret; +}  void stop_this_cpu(void *dummy)  {  	local_irq_disable(); diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index b78643d0f9a..03920a15a63 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -553,4 +553,17 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC,  			quirk_amd_nb_node);  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_LINK,  			quirk_amd_nb_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F0, +			quirk_amd_nb_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F1, +			quirk_amd_nb_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F2, +			quirk_amd_nb_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3, +			quirk_amd_nb_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4, +			quirk_amd_nb_node); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F5, +			quirk_amd_nb_node); +  #endif diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index e334be1182b..37a458b521a 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -124,7 +124,7 @@ __setup("reboot=", reboot_setup);   */  /* - * Some machines require the "reboot=b"  commandline option, + * Some machines require the "reboot=b" or "reboot=k"  commandline options,   * this quirk makes that automatic.   */  static int __init set_bios_reboot(const struct dmi_system_id *d) @@ -136,6 +136,15 @@ static int __init set_bios_reboot(const struct dmi_system_id *d)  	return 0;  } +static int __init set_kbd_reboot(const struct dmi_system_id *d) +{ +	if (reboot_type != BOOT_KBD) { +		reboot_type = BOOT_KBD; +		printk(KERN_INFO "%s series board detected. Selecting KBD-method for reboot.\n", d->ident); +	} +	return 0; +} +  static struct dmi_system_id __initdata reboot_dmi_table[] = {  	{	/* Handle problems with rebooting on Dell E520's */  		.callback = set_bios_reboot, @@ -295,7 +304,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {  		},  	},  	{ /* Handle reboot issue on Acer Aspire one */ -		.callback = set_bios_reboot, +		.callback = set_kbd_reboot,  		.ident = "Acer Aspire One A110",  		.matches = {  			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), @@ -443,6 +452,14 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {  			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"),  		},  	}, +	{	/* Handle problems with rebooting on the OptiPlex 990. */ +		.callback = set_pci_reboot, +		.ident = "Dell OptiPlex 990", +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"), +		}, +	},  	{ }  }; diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index 348ce016a83..af6db6ec5b2 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c @@ -12,6 +12,7 @@  #include <asm/vsyscall.h>  #include <asm/x86_init.h>  #include <asm/time.h> +#include <asm/mrst.h>  #ifdef CONFIG_X86_32  /* @@ -242,6 +243,10 @@ static __init int add_rtc_cmos(void)  	if (of_have_populated_dt())  		return 0; +	/* Intel MID platforms don't have ioport rtc */ +	if (mrst_identify_cpu()) +		return -ENODEV; +  	platform_device_register(&rtc_device);  	dev_info(&rtc_device.dev,  		 "registered platform RTC device (no PNP device found)\n"); diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index b4996266210..f4f29b19fac 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c @@ -45,6 +45,7 @@ void *kmap_atomic_prot(struct page *page, pgprot_t prot)  	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);  	BUG_ON(!pte_none(*(kmap_pte-idx)));  	set_pte(kmap_pte-idx, mk_pte(page, prot)); +	arch_flush_lazy_mmu_mode();  	return (void *)vaddr;  } @@ -88,6 +89,7 @@ void __kunmap_atomic(void *kvaddr)  		 */  		kpte_clear_flush(kmap_pte-idx, vaddr);  		kmap_atomic_idx_pop(); +		arch_flush_lazy_mmu_mode();  	}  #ifdef CONFIG_DEBUG_HIGHMEM  	else { diff --git a/arch/x86/oprofile/init.c b/arch/x86/oprofile/init.c index cdfe4c54dec..f148cf65267 100644 --- a/arch/x86/oprofile/init.c +++ b/arch/x86/oprofile/init.c @@ -21,6 +21,7 @@ extern int op_nmi_timer_init(struct oprofile_operations *ops);  extern void op_nmi_exit(void);  extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth); +static int nmi_timer;  int __init oprofile_arch_init(struct oprofile_operations *ops)  { @@ -31,8 +32,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)  #ifdef CONFIG_X86_LOCAL_APIC  	ret = op_nmi_init(ops);  #endif +	nmi_timer = (ret != 0);  #ifdef CONFIG_X86_IO_APIC -	if (ret < 0) +	if (nmi_timer)  		ret = op_nmi_timer_init(ops);  #endif  	ops->backtrace = x86_backtrace; @@ -44,6 +46,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)  void oprofile_arch_exit(void)  {  #ifdef CONFIG_X86_LOCAL_APIC -	op_nmi_exit(); +	if (!nmi_timer) +		op_nmi_exit();  #endif  } diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index b1489a06a49..ad4ec1cb097 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c @@ -76,6 +76,20 @@ struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];  EXPORT_SYMBOL_GPL(sfi_mrtc_array);  int sfi_mrtc_num; +static void mrst_power_off(void) +{ +	if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) +		intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 1); +} + +static void mrst_reboot(void) +{ +	if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) +		intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 0); +	else +		intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0); +} +  /* parse all the mtimer info to a static mtimer array */  static int __init sfi_parse_mtmr(struct sfi_table_header *table)  { @@ -265,17 +279,6 @@ static int mrst_i8042_detect(void)  	return 0;  } -/* Reboot and power off are handled by the SCU on a MID device */ -static void mrst_power_off(void) -{ -	intel_scu_ipc_simple_command(0xf1, 1); -} - -static void mrst_reboot(void) -{ -	intel_scu_ipc_simple_command(0xf1, 0); -} -  /*   * Moorestown does not have external NMI source nor port 0x61 to report   * NMI status. The possible NMI sources are from pmu as a result of NMI @@ -484,6 +487,46 @@ static void __init *max7315_platform_data(void *info)  	return max7315;  } +static void *tca6416_platform_data(void *info) +{ +	static struct pca953x_platform_data tca6416; +	struct i2c_board_info *i2c_info = info; +	int gpio_base, intr; +	char base_pin_name[SFI_NAME_LEN + 1]; +	char intr_pin_name[SFI_NAME_LEN + 1]; + +	strcpy(i2c_info->type, "tca6416"); +	strcpy(base_pin_name, "tca6416_base"); +	strcpy(intr_pin_name, "tca6416_int"); + +	gpio_base = get_gpio_by_name(base_pin_name); +	intr = get_gpio_by_name(intr_pin_name); + +	if (gpio_base == -1) +		return NULL; +	tca6416.gpio_base = gpio_base; +	if (intr != -1) { +		i2c_info->irq = intr + MRST_IRQ_OFFSET; +		tca6416.irq_base = gpio_base + MRST_IRQ_OFFSET; +	} else { +		i2c_info->irq = -1; +		tca6416.irq_base = -1; +	} +	return &tca6416; +} + +static void *mpu3050_platform_data(void *info) +{ +	struct i2c_board_info *i2c_info = info; +	int intr = get_gpio_by_name("mpu3050_int"); + +	if (intr == -1) +		return NULL; + +	i2c_info->irq = intr + MRST_IRQ_OFFSET; +	return NULL; +} +  static void __init *emc1403_platform_data(void *info)  {  	static short intr2nd_pdata; @@ -646,12 +689,15 @@ static void *msic_ocd_platform_data(void *info)  static const struct devs_id __initconst device_ids[] = {  	{"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data},  	{"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, +	{"pmic_gpio", SFI_DEV_TYPE_IPC, 1, &pmic_gpio_platform_data},  	{"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data},  	{"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data},  	{"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, +	{"tca6416", SFI_DEV_TYPE_I2C, 1, &tca6416_platform_data},  	{"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data},  	{"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data},  	{"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, +	{"mpu3050", SFI_DEV_TYPE_I2C, 1, &mpu3050_platform_data},  	/* MSIC subdevices */  	{"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data}, diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 38d0af4fefe..1093f80c162 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -410,6 +410,6 @@ void __init xen_arch_setup(void)  #endif  	disable_cpuidle();  	boot_option_idle_override = IDLE_HALT; - +	WARN_ON(set_pm_idle_to_default());  	fiddle_vdso();  } diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c index f10fc521951..1eedb6f7fda 100644 --- a/drivers/firmware/sigma.c +++ b/drivers/firmware/sigma.c @@ -14,13 +14,34 @@  #include <linux/module.h>  #include <linux/sigma.h> -/* Return: 0==OK, <0==error, =1 ==no more actions */ +static size_t sigma_action_size(struct sigma_action *sa) +{ +	size_t payload = 0; + +	switch (sa->instr) { +	case SIGMA_ACTION_WRITEXBYTES: +	case SIGMA_ACTION_WRITESINGLE: +	case SIGMA_ACTION_WRITESAFELOAD: +		payload = sigma_action_len(sa); +		break; +	default: +		break; +	} + +	payload = ALIGN(payload, 2); + +	return payload + sizeof(struct sigma_action); +} + +/* + * Returns a negative error value in case of an error, 0 if processing of + * the firmware should be stopped after this action, 1 otherwise. + */  static int -process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw) +process_sigma_action(struct i2c_client *client, struct sigma_action *sa)  { -	struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos);  	size_t len = sigma_action_len(sa); -	int ret = 0; +	int ret;  	pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,  		sa->instr, sa->addr, len); @@ -29,44 +50,50 @@ process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw)  	case SIGMA_ACTION_WRITEXBYTES:  	case SIGMA_ACTION_WRITESINGLE:  	case SIGMA_ACTION_WRITESAFELOAD: -		if (ssfw->fw->size < ssfw->pos + len) -			return -EINVAL;  		ret = i2c_master_send(client, (void *)&sa->addr, len);  		if (ret < 0)  			return -EINVAL;  		break; -  	case SIGMA_ACTION_DELAY: -		ret = 0;  		udelay(len);  		len = 0;  		break; -  	case SIGMA_ACTION_END: -		return 1; - +		return 0;  	default:  		return -EINVAL;  	} -	/* when arrive here ret=0 or sent data */ -	ssfw->pos += sigma_action_size(sa, len); -	return ssfw->pos == ssfw->fw->size; +	return 1;  }  static int  process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)  { -	pr_debug("%s: processing %p\n", __func__, ssfw); +	struct sigma_action *sa; +	size_t size; +	int ret; + +	while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) { +		sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos); + +		size = sigma_action_size(sa); +		ssfw->pos += size; +		if (ssfw->pos > ssfw->fw->size || size == 0) +			break; + +		ret = process_sigma_action(client, sa); -	while (1) { -		int ret = process_sigma_action(client, ssfw);  		pr_debug("%s: action returned %i\n", __func__, ret); -		if (ret == 1) -			return 0; -		else if (ret) + +		if (ret <= 0)  			return ret;  	} + +	if (ssfw->pos != ssfw->fw->size) +		return -EINVAL; + +	return 0;  }  int process_sigma_firmware(struct i2c_client *client, const char *name) @@ -89,16 +116,24 @@ int process_sigma_firmware(struct i2c_client *client, const char *name)  	/* then verify the header */  	ret = -EINVAL; -	if (fw->size < sizeof(*ssfw_head)) + +	/* +	 * Reject too small or unreasonable large files. The upper limit has been +	 * chosen a bit arbitrarily, but it should be enough for all practical +	 * purposes and having the limit makes it easier to avoid integer +	 * overflows later in the loading process. +	 */ +	if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000)  		goto done;  	ssfw_head = (void *)fw->data;  	if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic)))  		goto done; -	crc = crc32(0, fw->data, fw->size); +	crc = crc32(0, fw->data + sizeof(*ssfw_head), +			fw->size - sizeof(*ssfw_head));  	pr_debug("%s: crc=%x\n", __func__, crc); -	if (crc != ssfw_head->crc) +	if (crc != le32_to_cpu(ssfw_head->crc))  		goto done;  	ssfw.pos = sizeof(*ssfw_head); diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index dbcb0bcfd8d..4e018d6a763 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_ARCH_DAVINCI)	+= gpio-davinci.o  obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o  obj-$(CONFIG_GPIO_IT8761E)	+= gpio-it8761e.o  obj-$(CONFIG_GPIO_JANZ_TTL)	+= gpio-janz-ttl.o -obj-$(CONFIG_MACH_KS8695)	+= gpio-ks8695.o +obj-$(CONFIG_ARCH_KS8695)	+= gpio-ks8695.o  obj-$(CONFIG_GPIO_LANGWELL)	+= gpio-langwell.o  obj-$(CONFIG_ARCH_LPC32XX)	+= gpio-lpc32xx.o  obj-$(CONFIG_GPIO_MAX730X)	+= gpio-max730x.o diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 3969f7553fe..d2619d72cec 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -456,6 +456,30 @@ done:  EXPORT_SYMBOL(drm_crtc_helper_set_mode); +static int +drm_crtc_helper_disable(struct drm_crtc *crtc) +{ +	struct drm_device *dev = crtc->dev; +	struct drm_connector *connector; +	struct drm_encoder *encoder; + +	/* Decouple all encoders and their attached connectors from this crtc */ +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { +		if (encoder->crtc != crtc) +			continue; + +		list_for_each_entry(connector, &dev->mode_config.connector_list, head) { +			if (connector->encoder != encoder) +				continue; + +			connector->encoder = NULL; +		} +	} + +	drm_helper_disable_unused_functions(dev); +	return 0; +} +  /**   * drm_crtc_helper_set_config - set a new config from userspace   * @crtc: CRTC to setup @@ -510,8 +534,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)  				(int)set->num_connectors, set->x, set->y);  	} else {  		DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); -		set->mode = NULL; -		set->num_connectors = 0; +		return drm_crtc_helper_disable(set->crtc);  	}  	dev = set->crtc->dev; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index ddbabefb427..b12fd2c8081 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -369,3 +369,48 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,  	spin_unlock_irqrestore(&dev->event_lock, flags);  	return 0;  } + +int +nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, +			    struct drm_mode_create_dumb *args) +{ +	struct nouveau_bo *bo; +	int ret; + +	args->pitch = roundup(args->width * (args->bpp / 8), 256); +	args->size = args->pitch * args->height; +	args->size = roundup(args->size, PAGE_SIZE); + +	ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo); +	if (ret) +		return ret; + +	ret = drm_gem_handle_create(file_priv, bo->gem, &args->handle); +	drm_gem_object_unreference_unlocked(bo->gem); +	return ret; +} + +int +nouveau_display_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev, +			     uint32_t handle) +{ +	return drm_gem_handle_delete(file_priv, handle); +} + +int +nouveau_display_dumb_map_offset(struct drm_file *file_priv, +				struct drm_device *dev, +				uint32_t handle, uint64_t *poffset) +{ +	struct drm_gem_object *gem; + +	gem = drm_gem_object_lookup(dev, file_priv, handle); +	if (gem) { +		struct nouveau_bo *bo = gem->driver_private; +		*poffset = bo->bo.addr_space_offset; +		drm_gem_object_unreference_unlocked(gem); +		return 0; +	} + +	return -ENOENT; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 9f7bb129526..9791d13c9e3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -433,6 +433,10 @@ static struct drm_driver driver = {  	.gem_open_object = nouveau_gem_object_open,  	.gem_close_object = nouveau_gem_object_close, +	.dumb_create = nouveau_display_dumb_create, +	.dumb_map_offset = nouveau_display_dumb_map_offset, +	.dumb_destroy = nouveau_display_dumb_destroy, +  	.name = DRIVER_NAME,  	.desc = DRIVER_DESC,  #ifdef GIT_REVISION diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 29837da1098..4c0be3a4ed8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1418,6 +1418,12 @@ int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,  			   struct drm_pending_vblank_event *event);  int nouveau_finish_page_flip(struct nouveau_channel *,  			     struct nouveau_page_flip_state *); +int nouveau_display_dumb_create(struct drm_file *, struct drm_device *, +				struct drm_mode_create_dumb *args); +int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *, +				    uint32_t handle, uint64_t *offset); +int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, +				 uint32_t handle);  /* nv10_gpio.c */  int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c index 02222c540ae..960c0ae0c0c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c @@ -680,7 +680,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)  		return ret;  	} -	ret = drm_mm_init(&chan->ramin_heap, base, size); +	ret = drm_mm_init(&chan->ramin_heap, base, size - base);  	if (ret) {  		NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret);  		nouveau_gpuobj_ref(NULL, &chan->ramin); diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index b75258a9fe4..c8a463b76c8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -67,7 +67,10 @@ nouveau_sgdma_clear(struct ttm_backend *be)  			pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],  				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);  		} +		nvbe->unmap_pages = false;  	} + +	nvbe->pages = NULL;  }  static void diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index d23ca00e7d6..06de250fe61 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -616,7 +616,7 @@ nv50_display_unk10_handler(struct drm_device *dev)  	struct drm_nouveau_private *dev_priv = dev->dev_private;  	struct nv50_display *disp = nv50_display(dev);  	u32 unk30 = nv_rd32(dev, 0x610030), mc; -	int i, crtc, or, type = OUTPUT_ANY; +	int i, crtc, or = 0, type = OUTPUT_ANY;  	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);  	disp->irq.dcb = NULL; @@ -708,7 +708,7 @@ nv50_display_unk20_handler(struct drm_device *dev)  	struct nv50_display *disp = nv50_display(dev);  	u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc = 0;  	struct dcb_entry *dcb; -	int i, crtc, or, type = OUTPUT_ANY; +	int i, crtc, or = 0, type = OUTPUT_ANY;  	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);  	dcb = disp->irq.dcb; diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c index a74e501afd2..ecfafd70cf0 100644 --- a/drivers/gpu/drm/nouveau/nvc0_graph.c +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c @@ -381,6 +381,8 @@ nvc0_graph_init_gpc_0(struct drm_device *dev)  	u8  tpnr[GPC_MAX];  	int i, gpc, tpc; +	nv_wr32(dev, TP_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */ +  	/*  	 *      TP      ROP UNKVAL(magic_not_rop_nr)  	 * 450: 4/0/0/0 2        3 diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 23d63b4b3d7..cb006a718e7 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -780,7 +780,7 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode)  			continue;  		if (nv_partner != nv_encoder && -		    nv_partner->dcb->or == nv_encoder->or) { +		    nv_partner->dcb->or == nv_encoder->dcb->or) {  			if (nv_partner->last_dpms == DRM_MODE_DPMS_ON)  				return;  			break; diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 87631fede1f..2b97262e3ab 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1107,9 +1107,40 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,  		return -EINVAL;  	} -	if (tiling_flags & RADEON_TILING_MACRO) +	if (tiling_flags & RADEON_TILING_MACRO) { +		if (rdev->family >= CHIP_CAYMAN) +			tmp = rdev->config.cayman.tile_config; +		else +			tmp = rdev->config.evergreen.tile_config; + +		switch ((tmp & 0xf0) >> 4) { +		case 0: /* 4 banks */ +			fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK); +			break; +		case 1: /* 8 banks */ +		default: +			fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK); +			break; +		case 2: /* 16 banks */ +			fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK); +			break; +		} + +		switch ((tmp & 0xf000) >> 12) { +		case 0: /* 1KB rows */ +		default: +			fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB); +			break; +		case 1: /* 2KB rows */ +			fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB); +			break; +		case 2: /* 4KB rows */ +			fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB); +			break; +		} +  		fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1); -	else if (tiling_flags & RADEON_TILING_MICRO) +	} else if (tiling_flags & RADEON_TILING_MICRO)  		fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);  	switch (radeon_crtc->crtc_id) { diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 1d603a3335d..5e00d1670aa 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -82,6 +82,7 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)  {  	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];  	u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); +	int i;  	/* Lock the graphics update lock */  	tmp |= EVERGREEN_GRPH_UPDATE_LOCK; @@ -99,7 +100,11 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)  	       (u32)crtc_base);  	/* Wait for update_pending to go high. */ -	while (!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)); +	for (i = 0; i < rdev->usec_timeout; i++) { +		if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) +			break; +		udelay(1); +	}  	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");  	/* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 38e1bda73d3..cd4590aae15 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -38,6 +38,7 @@ struct evergreen_cs_track {  	u32			group_size;  	u32			nbanks;  	u32			npipes; +	u32			row_size;  	/* value we track */  	u32			nsamples;  	u32			cb_color_base_last[12]; @@ -77,6 +78,44 @@ struct evergreen_cs_track {  	struct radeon_bo	*db_s_write_bo;  }; +static u32 evergreen_cs_get_aray_mode(u32 tiling_flags) +{ +	if (tiling_flags & RADEON_TILING_MACRO) +		return ARRAY_2D_TILED_THIN1; +	else if (tiling_flags & RADEON_TILING_MICRO) +		return ARRAY_1D_TILED_THIN1; +	else +		return ARRAY_LINEAR_GENERAL; +} + +static u32 evergreen_cs_get_num_banks(u32 nbanks) +{ +	switch (nbanks) { +	case 2: +		return ADDR_SURF_2_BANK; +	case 4: +		return ADDR_SURF_4_BANK; +	case 8: +	default: +		return ADDR_SURF_8_BANK; +	case 16: +		return ADDR_SURF_16_BANK; +	} +} + +static u32 evergreen_cs_get_tile_split(u32 row_size) +{ +	switch (row_size) { +	case 1: +	default: +		return ADDR_SURF_TILE_SPLIT_1KB; +	case 2: +		return ADDR_SURF_TILE_SPLIT_2KB; +	case 4: +		return ADDR_SURF_TILE_SPLIT_4KB; +	} +} +  static void evergreen_cs_track_init(struct evergreen_cs_track *track)  {  	int i; @@ -490,12 +529,11 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  			}  			ib[idx] &= ~Z_ARRAY_MODE(0xf);  			track->db_z_info &= ~Z_ARRAY_MODE(0xf); +			ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); +			track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));  			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { -				ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -				track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -			} else { -				ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); -				track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +				ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); +				ib[idx] |= DB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size));  			}  		}  		break; @@ -618,13 +656,8 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  						"0x%04X\n", reg);  				return -EINVAL;  			} -			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { -				ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -				track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -			} else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { -				ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); -				track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); -			} +			ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); +			track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));  		}  		break;  	case CB_COLOR8_INFO: @@ -640,13 +673,8 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  						"0x%04X\n", reg);  				return -EINVAL;  			} -			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { -				ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -				track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); -			} else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { -				ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); -				track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); -			} +			ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); +			track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags));  		}  		break;  	case CB_COLOR0_PITCH: @@ -701,6 +729,16 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  	case CB_COLOR9_ATTRIB:  	case CB_COLOR10_ATTRIB:  	case CB_COLOR11_ATTRIB: +		r = evergreen_cs_packet_next_reloc(p, &reloc); +		if (r) { +			dev_warn(p->dev, "bad SET_CONTEXT_REG " +					"0x%04X\n", reg); +			return -EINVAL; +		} +		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { +			ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); +			ib[idx] |= CB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size)); +		}  		break;  	case CB_COLOR0_DIM:  	case CB_COLOR1_DIM: @@ -1318,10 +1356,14 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,  				}  				ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);  				if (!p->keep_tiling_flags) { -					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) -						ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1); +					ib[idx+1+(i*8)+1] |= +						TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); +					if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { +						ib[idx+1+(i*8)+6] |= +							TEX_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size)); +						ib[idx+1+(i*8)+7] |= +							TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); +					}  				}  				texture = reloc->robj;  				/* tex mip base */ @@ -1422,6 +1464,7 @@ int evergreen_cs_parse(struct radeon_cs_parser *p)  {  	struct radeon_cs_packet pkt;  	struct evergreen_cs_track *track; +	u32 tmp;  	int r;  	if (p->track == NULL) { @@ -1430,9 +1473,63 @@ int evergreen_cs_parse(struct radeon_cs_parser *p)  		if (track == NULL)  			return -ENOMEM;  		evergreen_cs_track_init(track); -		track->npipes = p->rdev->config.evergreen.tiling_npipes; -		track->nbanks = p->rdev->config.evergreen.tiling_nbanks; -		track->group_size = p->rdev->config.evergreen.tiling_group_size; +		if (p->rdev->family >= CHIP_CAYMAN) +			tmp = p->rdev->config.cayman.tile_config; +		else +			tmp = p->rdev->config.evergreen.tile_config; + +		switch (tmp & 0xf) { +		case 0: +			track->npipes = 1; +			break; +		case 1: +		default: +			track->npipes = 2; +			break; +		case 2: +			track->npipes = 4; +			break; +		case 3: +			track->npipes = 8; +			break; +		} + +		switch ((tmp & 0xf0) >> 4) { +		case 0: +			track->nbanks = 4; +			break; +		case 1: +		default: +			track->nbanks = 8; +			break; +		case 2: +			track->nbanks = 16; +			break; +		} + +		switch ((tmp & 0xf00) >> 8) { +		case 0: +			track->group_size = 256; +			break; +		case 1: +		default: +			track->group_size = 512; +			break; +		} + +		switch ((tmp & 0xf000) >> 12) { +		case 0: +			track->row_size = 1; +			break; +		case 1: +		default: +			track->row_size = 2; +			break; +		case 2: +			track->row_size = 4; +			break; +		} +  		p->track = track;  	}  	do { diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h index c781c92c345..7d7f2155e34 100644 --- a/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/drivers/gpu/drm/radeon/evergreen_reg.h @@ -42,6 +42,17 @@  #       define EVERGREEN_GRPH_DEPTH_8BPP                0  #       define EVERGREEN_GRPH_DEPTH_16BPP               1  #       define EVERGREEN_GRPH_DEPTH_32BPP               2 +#       define EVERGREEN_GRPH_NUM_BANKS(x)              (((x) & 0x3) << 2) +#       define EVERGREEN_ADDR_SURF_2_BANK               0 +#       define EVERGREEN_ADDR_SURF_4_BANK               1 +#       define EVERGREEN_ADDR_SURF_8_BANK               2 +#       define EVERGREEN_ADDR_SURF_16_BANK              3 +#       define EVERGREEN_GRPH_Z(x)                      (((x) & 0x3) << 4) +#       define EVERGREEN_GRPH_BANK_WIDTH(x)             (((x) & 0x3) << 6) +#       define EVERGREEN_ADDR_SURF_BANK_WIDTH_1         0 +#       define EVERGREEN_ADDR_SURF_BANK_WIDTH_2         1 +#       define EVERGREEN_ADDR_SURF_BANK_WIDTH_4         2 +#       define EVERGREEN_ADDR_SURF_BANK_WIDTH_8         3  #       define EVERGREEN_GRPH_FORMAT(x)                 (((x) & 0x7) << 8)  /* 8 BPP */  #       define EVERGREEN_GRPH_FORMAT_INDEXED            0 @@ -61,6 +72,24 @@  #       define EVERGREEN_GRPH_FORMAT_8B_BGRA1010102     5  #       define EVERGREEN_GRPH_FORMAT_RGB111110          6  #       define EVERGREEN_GRPH_FORMAT_BGR101111          7 +#       define EVERGREEN_GRPH_BANK_HEIGHT(x)            (((x) & 0x3) << 11) +#       define EVERGREEN_ADDR_SURF_BANK_HEIGHT_1        0 +#       define EVERGREEN_ADDR_SURF_BANK_HEIGHT_2        1 +#       define EVERGREEN_ADDR_SURF_BANK_HEIGHT_4        2 +#       define EVERGREEN_ADDR_SURF_BANK_HEIGHT_8        3 +#       define EVERGREEN_GRPH_TILE_SPLIT(x)             (((x) & 0x7) << 13) +#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_64B       0 +#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_128B      1 +#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_256B      2 +#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_512B      3 +#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB       4 +#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB       5 +#       define EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB       6 +#       define EVERGREEN_GRPH_MACRO_TILE_ASPECT(x)      (((x) & 0x3) << 18) +#       define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1  0 +#       define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2  1 +#       define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4  2 +#       define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8  3  #       define EVERGREEN_GRPH_ARRAY_MODE(x)             (((x) & 0x7) << 20)  #       define EVERGREEN_GRPH_ARRAY_LINEAR_GENERAL      0  #       define EVERGREEN_GRPH_ARRAY_LINEAR_ALIGNED      1 diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index b937c49054d..e00039e59a7 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -899,6 +899,10 @@  #define DB_HTILE_DATA_BASE				0x28014  #define DB_Z_INFO					0x28040  #       define Z_ARRAY_MODE(x)                          ((x) << 4) +#       define DB_TILE_SPLIT(x)                         (((x) & 0x7) << 8) +#       define DB_NUM_BANKS(x)                          (((x) & 0x3) << 12) +#       define DB_BANK_WIDTH(x)                         (((x) & 0x3) << 16) +#       define DB_BANK_HEIGHT(x)                        (((x) & 0x3) << 20)  #define DB_STENCIL_INFO					0x28044  #define DB_Z_READ_BASE					0x28048  #define DB_STENCIL_READ_BASE				0x2804c @@ -951,6 +955,29 @@  #	define CB_SF_EXPORT_FULL			0  #	define CB_SF_EXPORT_NORM			1  #define	CB_COLOR0_ATTRIB				0x28c74 +#       define CB_TILE_SPLIT(x)                         (((x) & 0x7) << 5) +#       define ADDR_SURF_TILE_SPLIT_64B                 0 +#       define ADDR_SURF_TILE_SPLIT_128B                1 +#       define ADDR_SURF_TILE_SPLIT_256B                2 +#       define ADDR_SURF_TILE_SPLIT_512B                3 +#       define ADDR_SURF_TILE_SPLIT_1KB                 4 +#       define ADDR_SURF_TILE_SPLIT_2KB                 5 +#       define ADDR_SURF_TILE_SPLIT_4KB                 6 +#       define CB_NUM_BANKS(x)                          (((x) & 0x3) << 10) +#       define ADDR_SURF_2_BANK                         0 +#       define ADDR_SURF_4_BANK                         1 +#       define ADDR_SURF_8_BANK                         2 +#       define ADDR_SURF_16_BANK                        3 +#       define CB_BANK_WIDTH(x)                         (((x) & 0x3) << 13) +#       define ADDR_SURF_BANK_WIDTH_1                   0 +#       define ADDR_SURF_BANK_WIDTH_2                   1 +#       define ADDR_SURF_BANK_WIDTH_4                   2 +#       define ADDR_SURF_BANK_WIDTH_8                   3 +#       define CB_BANK_HEIGHT(x)                        (((x) & 0x3) << 16) +#       define ADDR_SURF_BANK_HEIGHT_1                  0 +#       define ADDR_SURF_BANK_HEIGHT_2                  1 +#       define ADDR_SURF_BANK_HEIGHT_4                  2 +#       define ADDR_SURF_BANK_HEIGHT_8                  3  #define	CB_COLOR0_DIM					0x28c78  /* only CB0-7 blocks have these regs */  #define	CB_COLOR0_CMASK					0x28c7c @@ -1137,7 +1164,11 @@  #	define SQ_SEL_1					5  #define SQ_TEX_RESOURCE_WORD5_0                         0x30014  #define SQ_TEX_RESOURCE_WORD6_0                         0x30018 +#       define TEX_TILE_SPLIT(x)                        (((x) & 0x7) << 29)  #define SQ_TEX_RESOURCE_WORD7_0                         0x3001c +#       define TEX_BANK_WIDTH(x)                        (((x) & 0x3) << 8) +#       define TEX_BANK_HEIGHT(x)                       (((x) & 0x3) << 10) +#       define TEX_NUM_BANKS(x)                         (((x) & 0x3) << 16)  #define SQ_VTX_CONSTANT_WORD0_0				0x30000  #define SQ_VTX_CONSTANT_WORD1_0				0x30004 diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index ad158ea4990..bfc08f6320f 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -187,13 +187,18 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)  {  	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];  	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; +	int i;  	/* Lock the graphics update lock */  	/* update the scanout addresses */  	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);  	/* Wait for update_pending to go high. */ -	while (!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)); +	for (i = 0; i < rdev->usec_timeout; i++) { +		if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET) +			break; +		udelay(1); +	}  	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");  	/* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c index 3f6636bb2d7..3516a6081dc 100644 --- a/drivers/gpu/drm/radeon/radeon_acpi.c +++ b/drivers/gpu/drm/radeon/radeon_acpi.c @@ -35,7 +35,8 @@ static int radeon_atif_call(acpi_handle handle)  	/* Fail only if calling the method fails and ATIF is supported */  	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { -		printk(KERN_DEBUG "failed to evaluate ATIF got %s\n", acpi_format_exception(status)); +		DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n", +				 acpi_format_exception(status));  		kfree(buffer.pointer);  		return 1;  	} @@ -50,13 +51,13 @@ int radeon_acpi_init(struct radeon_device *rdev)  	acpi_handle handle;  	int ret; -	/* No need to proceed if we're sure that ATIF is not supported */ -	if (!ASIC_IS_AVIVO(rdev) || !rdev->bios) -		return 0; -  	/* Get the device handle */  	handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev); +	/* No need to proceed if we're sure that ATIF is not supported */ +	if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle) +		return 0; +  	/* Call the ATIF method */  	ret = radeon_atif_call(handle);  	if (ret) diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 481b99e89f6..b1053d64042 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -62,6 +62,7 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)  {  	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];  	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); +	int i;  	/* Lock the graphics update lock */  	tmp |= AVIVO_D1GRPH_UPDATE_LOCK; @@ -74,7 +75,11 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)  	       (u32)crtc_base);  	/* Wait for update_pending to go high. */ -	while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); +	for (i = 0; i < rdev->usec_timeout; i++) { +		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) +			break; +		udelay(1); +	}  	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");  	/* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index a983f410ab8..23ae1c60ab3 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -47,6 +47,7 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)  {  	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];  	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); +	int i;  	/* Lock the graphics update lock */  	tmp |= AVIVO_D1GRPH_UPDATE_LOCK; @@ -66,7 +67,11 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)  	       (u32)crtc_base);  	/* Wait for update_pending to go high. */ -	while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); +	for (i = 0; i < rdev->usec_timeout; i++) { +		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) +			break; +		udelay(1); +	}  	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");  	/* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 880e285d757..37d40545ed7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1809,7 +1809,8 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,  	}  	rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect); -	rects = kzalloc(rects_size, GFP_KERNEL); +	rects = kcalloc(arg->num_outputs, sizeof(struct drm_vmw_rect), +			GFP_KERNEL);  	if (unlikely(!rects)) {  		ret = -ENOMEM;  		goto out_unlock; @@ -1824,10 +1825,10 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,  	}  	for (i = 0; i < arg->num_outputs; ++i) { -		if (rects->x < 0 || -		    rects->y < 0 || -		    rects->x + rects->w > mode_config->max_width || -		    rects->y + rects->h > mode_config->max_height) { +		if (rects[i].x < 0 || +		    rects[i].y < 0 || +		    rects[i].x + rects[i].w > mode_config->max_width || +		    rects[i].y + rects[i].h > mode_config->max_height) {  			DRM_ERROR("Invalid GUI layout.\n");  			ret = -EINVAL;  			goto out_free; diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 848a56c0279..af353842f75 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1771,8 +1771,8 @@ static const struct hid_device_id hid_ignore_list[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, -	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 06ce996b8b6..4a441a6f996 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -266,7 +266,7 @@  #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR	0x0002  #define USB_VENDOR_ID_GENERAL_TOUCH	0x0dfc -#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0001 +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003  #define USB_VENDOR_ID_GLAB		0x06c2  #define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038 diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index c0c7820d4c4..a004c3945c6 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3524,7 +3524,7 @@ found:  	return 0;  } -int dmar_parse_rmrr_atsr_dev(void) +int __init dmar_parse_rmrr_atsr_dev(void)  {  	struct dmar_rmrr_unit *rmrr, *rmrr_n;  	struct dmar_atsr_unit *atsr, *atsr_n; diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intr_remapping.c index 07c9f189f31..6777ca04947 100644 --- a/drivers/iommu/intr_remapping.c +++ b/drivers/iommu/intr_remapping.c @@ -773,7 +773,7 @@ int __init parse_ioapics_under_ir(void)  	return ir_supported;  } -int ir_dev_scope_init(void) +int __init ir_dev_scope_init(void)  {  	if (!intr_remapping_enabled)  		return 0; diff --git a/drivers/net/ethernet/pasemi/Makefile b/drivers/net/ethernet/pasemi/Makefile index 05db5434baf..90497ffb1ac 100644 --- a/drivers/net/ethernet/pasemi/Makefile +++ b/drivers/net/ethernet/pasemi/Makefile @@ -2,4 +2,5 @@  # Makefile for the A Semi network device drivers.  # -obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o pasemi_mac_ethtool.o +obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o +pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index e5a6d8e7050..36b2a4b1c35 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1180,11 +1180,13 @@ static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr)  	return value;  } -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) +static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)  { -	RTL_W16(IntrMask, 0x0000); +	void __iomem *ioaddr = tp->mmio_addr; -	RTL_W16(IntrStatus, 0xffff); +	RTL_W16(IntrMask, 0x0000); +	RTL_W16(IntrStatus, tp->intr_event); +	RTL_R8(ChipCmd);  }  static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp) @@ -3933,8 +3935,6 @@ static void rtl_hw_reset(struct rtl8169_private *tp)  			break;  		udelay(100);  	} - -	rtl8169_init_ring_indexes(tp);  }  static int __devinit @@ -4339,7 +4339,7 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)  	void __iomem *ioaddr = tp->mmio_addr;  	/* Disable interrupts */ -	rtl8169_irq_mask_and_ack(ioaddr); +	rtl8169_irq_mask_and_ack(tp);  	rtl_rx_close(tp); @@ -4885,8 +4885,7 @@ static void rtl_hw_start_8168(struct net_device *dev)  	RTL_W16(IntrMitigate, 0x5151);  	/* Work around for RxFIFO overflow. */ -	if (tp->mac_version == RTL_GIGA_MAC_VER_11 || -	    tp->mac_version == RTL_GIGA_MAC_VER_22) { +	if (tp->mac_version == RTL_GIGA_MAC_VER_11) {  		tp->intr_event |= RxFIFOOver | PCSTimeout;  		tp->intr_event &= ~RxOverflow;  	} @@ -5076,6 +5075,11 @@ static void rtl_hw_start_8101(struct net_device *dev)  	void __iomem *ioaddr = tp->mmio_addr;  	struct pci_dev *pdev = tp->pci_dev; +	if (tp->mac_version >= RTL_GIGA_MAC_VER_30) { +		tp->intr_event &= ~RxFIFOOver; +		tp->napi_event &= ~RxFIFOOver; +	} +  	if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||  	    tp->mac_version == RTL_GIGA_MAC_VER_16) {  		int cap = pci_pcie_cap(pdev); @@ -5342,7 +5346,7 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev)  	/* Wait for any pending NAPI task to complete */  	napi_disable(&tp->napi); -	rtl8169_irq_mask_and_ack(ioaddr); +	rtl8169_irq_mask_and_ack(tp);  	tp->intr_mask = 0xffff;  	RTL_W16(IntrMask, tp->intr_event); @@ -5389,14 +5393,16 @@ static void rtl8169_reset_task(struct work_struct *work)  	if (!netif_running(dev))  		goto out_unlock; +	rtl8169_hw_reset(tp); +  	rtl8169_wait_for_quiescence(dev);  	for (i = 0; i < NUM_RX_DESC; i++)  		rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz);  	rtl8169_tx_clear(tp); +	rtl8169_init_ring_indexes(tp); -	rtl8169_hw_reset(tp);  	rtl_hw_start(dev);  	netif_wake_queue(dev);  	rtl8169_check_link_status(dev, tp, tp->mmio_addr); @@ -5407,11 +5413,6 @@ out_unlock:  static void rtl8169_tx_timeout(struct net_device *dev)  { -	struct rtl8169_private *tp = netdev_priv(dev); - -	rtl8169_hw_reset(tp); - -	/* Let's wait a bit while any (async) irq lands on */  	rtl8169_schedule_work(dev, rtl8169_reset_task);  } @@ -5804,6 +5805,10 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)  	 */  	status = RTL_R16(IntrStatus);  	while (status && status != 0xffff) { +		status &= tp->intr_event; +		if (!status) +			break; +  		handled = 1;  		/* Handle all of the error cases first. These will reset @@ -5818,27 +5823,9 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)  			switch (tp->mac_version) {  			/* Work around for rx fifo overflow */  			case RTL_GIGA_MAC_VER_11: -			case RTL_GIGA_MAC_VER_22: -			case RTL_GIGA_MAC_VER_26:  				netif_stop_queue(dev);  				rtl8169_tx_timeout(dev);  				goto done; -			/* Testers needed. */ -			case RTL_GIGA_MAC_VER_17: -			case RTL_GIGA_MAC_VER_19: -			case RTL_GIGA_MAC_VER_20: -			case RTL_GIGA_MAC_VER_21: -			case RTL_GIGA_MAC_VER_23: -			case RTL_GIGA_MAC_VER_24: -			case RTL_GIGA_MAC_VER_27: -			case RTL_GIGA_MAC_VER_28: -			case RTL_GIGA_MAC_VER_31: -			/* Experimental science. Pktgen proof. */ -			case RTL_GIGA_MAC_VER_12: -			case RTL_GIGA_MAC_VER_25: -				if (status == RxFIFOOver) -					goto done; -				break;  			default:  				break;  			} diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index d2ffe9cd29c..639cf8ab62b 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1664,7 +1664,7 @@ static int __init netback_init(void)  					     "netback/%u", group);  		if (IS_ERR(netbk->task)) { -			printk(KERN_ALERT "kthread_run() fails at netback\n"); +			printk(KERN_ALERT "kthread_create() fails at netback\n");  			del_timer(&netbk->net_timer);  			rc = PTR_ERR(netbk->task);  			goto failed_init; diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index dccd8636095..f8c752e408a 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c @@ -239,26 +239,45 @@ int oprofile_set_ulong(unsigned long *addr, unsigned long val)  	return err;  } +static int timer_mode; +  static int __init oprofile_init(void)  {  	int err; +	/* always init architecture to setup backtrace support */  	err = oprofile_arch_init(&oprofile_ops); -	if (err < 0 || timer) { -		printk(KERN_INFO "oprofile: using timer interrupt.\n"); + +	timer_mode = err || timer;	/* fall back to timer mode on errors */ +	if (timer_mode) { +		if (!err) +			oprofile_arch_exit();  		err = oprofile_timer_init(&oprofile_ops);  		if (err)  			return err;  	} -	return oprofilefs_register(); + +	err = oprofilefs_register(); +	if (!err) +		return 0; + +	/* failed */ +	if (timer_mode) +		oprofile_timer_exit(); +	else +		oprofile_arch_exit(); + +	return err;  }  static void __exit oprofile_exit(void)  { -	oprofile_timer_exit();  	oprofilefs_unregister(); -	oprofile_arch_exit(); +	if (timer_mode) +		oprofile_timer_exit(); +	else +		oprofile_arch_exit();  } diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index 3ef44624f51..878fba12658 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c @@ -110,6 +110,7 @@ int oprofile_timer_init(struct oprofile_operations *ops)  	ops->start = oprofile_hrtimer_start;  	ops->stop = oprofile_hrtimer_stop;  	ops->cpu_type = "timer"; +	printk(KERN_INFO "oprofile: using timer interrupt.\n");  	return 0;  } diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 13ef8c37471..dcdc1f4a462 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -121,6 +121,7 @@ struct toshiba_acpi_dev {  	int illumination_supported:1;  	int video_supported:1;  	int fan_supported:1; +	int system_event_supported:1;  	struct mutex mutex;  }; @@ -724,7 +725,7 @@ static int keys_proc_show(struct seq_file *m, void *v)  	u32 hci_result;  	u32 value; -	if (!dev->key_event_valid) { +	if (!dev->key_event_valid && dev->system_event_supported) {  		hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);  		if (hci_result == HCI_SUCCESS) {  			dev->key_event_valid = 1; @@ -964,6 +965,8 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)  	/* enable event fifo */  	hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); +	if (hci_result == HCI_SUCCESS) +		dev->system_event_supported = 1;  	props.type = BACKLIGHT_PLATFORM;  	props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; @@ -1032,12 +1035,15 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)  {  	struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);  	u32 hci_result, value; +	int retries = 3; -	if (event != 0x80) +	if (!dev->system_event_supported || event != 0x80)  		return; +  	do {  		hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result); -		if (hci_result == HCI_SUCCESS) { +		switch (hci_result) { +		case HCI_SUCCESS:  			if (value == 0x100)  				continue;  			/* act on key press; ignore key release */ @@ -1049,14 +1055,19 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)  				pr_info("Unknown key %x\n",  				       value);  			} -		} else if (hci_result == HCI_NOT_SUPPORTED) { +			break; +		case HCI_NOT_SUPPORTED:  			/* This is a workaround for an unresolved issue on  			 * some machines where system events sporadically  			 * become disabled. */  			hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);  			pr_notice("Re-enabled hotkeys\n"); +			/* fall through */ +		default: +			retries--; +			break;  		} -	} while (hci_result != HCI_EMPTY); +	} while (retries && hci_result != HCI_EMPTY);  } diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c index cffcb7c00b0..01fa671ec97 100644 --- a/drivers/power/intel_mid_battery.c +++ b/drivers/power/intel_mid_battery.c @@ -61,7 +61,8 @@ MODULE_PARM_DESC(debug, "Flag to enable PMIC Battery debug messages.");  #define PMIC_BATT_CHR_SBATDET_MASK	(1 << 5)  #define PMIC_BATT_CHR_SDCLMT_MASK	(1 << 6)  #define PMIC_BATT_CHR_SUSBOVP_MASK	(1 << 7) -#define PMIC_BATT_CHR_EXCPT_MASK	0xC6 +#define PMIC_BATT_CHR_EXCPT_MASK	0x86 +  #define PMIC_BATT_ADC_ACCCHRG_MASK	(1 << 31)  #define PMIC_BATT_ADC_ACCCHRGVAL_MASK	0x7FFFFFFF @@ -304,11 +305,6 @@ static void pmic_battery_read_status(struct pmic_power_module_info *pbi)  			pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING;  			pmic_battery_log_event(BATT_EVENT_BATOVP_EXCPT);  			batt_exception = 1; -		} else if (r8 & PMIC_BATT_CHR_SDCLMT_MASK) { -			pbi->batt_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; -			pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; -			pmic_battery_log_event(BATT_EVENT_DCLMT_EXCPT); -			batt_exception = 1;  		} else if (r8 & PMIC_BATT_CHR_STEMP_MASK) {  			pbi->batt_health = POWER_SUPPLY_HEALTH_OVERHEAT;  			pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; @@ -316,6 +312,10 @@ static void pmic_battery_read_status(struct pmic_power_module_info *pbi)  			batt_exception = 1;  		} else {  			pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD; +			if (r8 & PMIC_BATT_CHR_SDCLMT_MASK) { +				/* PMIC will change charging current automatically */ +				pmic_battery_log_event(BATT_EVENT_DCLMT_EXCPT); +			}  		}  	} diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index e8326f26fa2..dc4c2748bbc 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -63,7 +63,7 @@ static int rtc_suspend(struct device *dev, pm_message_t mesg)  	 */  	delta = timespec_sub(old_system, old_rtc);  	delta_delta = timespec_sub(delta, old_delta); -	if (abs(delta_delta.tv_sec)  >= 2) { +	if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) {  		/*  		 * if delta_delta is too large, assume time correction  		 * has occured and set old_delta to the current delta. @@ -97,9 +97,8 @@ static int rtc_resume(struct device *dev)  	rtc_tm_to_time(&tm, &new_rtc.tv_sec);  	new_rtc.tv_nsec = 0; -	if (new_rtc.tv_sec <= old_rtc.tv_sec) { -		if (new_rtc.tv_sec < old_rtc.tv_sec) -			pr_debug("%s:  time travel!\n", dev_name(&rtc->dev)); +	if (new_rtc.tv_sec < old_rtc.tv_sec) { +		pr_debug("%s:  time travel!\n", dev_name(&rtc->dev));  		return 0;  	} @@ -116,7 +115,8 @@ static int rtc_resume(struct device *dev)  	sleep_time = timespec_sub(sleep_time,  			timespec_sub(new_system, old_system)); -	timekeeping_inject_sleeptime(&sleep_time); +	if (sleep_time.tv_sec >= 0) +		timekeeping_inject_sleeptime(&sleep_time);  	return 0;  } diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 8e286259a00..fa4d9f32418 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -319,6 +319,20 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)  }  EXPORT_SYMBOL_GPL(rtc_read_alarm); +static int ___rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) +{ +	int err; + +	if (!rtc->ops) +		err = -ENODEV; +	else if (!rtc->ops->set_alarm) +		err = -EINVAL; +	else +		err = rtc->ops->set_alarm(rtc->dev.parent, alarm); + +	return err; +} +  static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)  {  	struct rtc_time tm; @@ -342,14 +356,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)  	 * over right here, before we set the alarm.  	 */ -	if (!rtc->ops) -		err = -ENODEV; -	else if (!rtc->ops->set_alarm) -		err = -EINVAL; -	else -		err = rtc->ops->set_alarm(rtc->dev.parent, alarm); - -	return err; +	return ___rtc_set_alarm(rtc, alarm);  }  int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) @@ -763,6 +770,20 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)  	return 0;  } +static void rtc_alarm_disable(struct rtc_device *rtc) +{ +	struct rtc_wkalrm alarm; +	struct rtc_time tm; + +	__rtc_read_time(rtc, &tm); + +	alarm.time = rtc_ktime_to_tm(ktime_add(rtc_tm_to_ktime(tm), +				     ktime_set(300, 0))); +	alarm.enabled = 0; + +	___rtc_set_alarm(rtc, &alarm); +} +  /**   * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue   * @rtc rtc device @@ -784,8 +805,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)  		struct rtc_wkalrm alarm;  		int err;  		next = timerqueue_getnext(&rtc->timerqueue); -		if (!next) +		if (!next) { +			rtc_alarm_disable(rtc);  			return; +		}  		alarm.time = rtc_ktime_to_tm(next->expires);  		alarm.enabled = 1;  		err = __rtc_set_alarm(rtc, &alarm); @@ -847,7 +870,8 @@ again:  		err = __rtc_set_alarm(rtc, &alarm);  		if (err == -ETIME)  			goto again; -	} +	} else +		rtc_alarm_disable(rtc);  	mutex_unlock(&rtc->ops_lock);  } diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 75c3f1f8fd4..a84631a7391 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -529,10 +529,7 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data)  int chsc_chp_vary(struct chp_id chpid, int on)  {  	struct channel_path *chp = chpid_to_chp(chpid); -	struct chp_link link; -	memset(&link, 0, sizeof(struct chp_link)); -	link.chpid = chpid;  	/* Wait until previous actions have settled. */  	css_wait_for_slow_path();  	/* @@ -542,10 +539,10 @@ int chsc_chp_vary(struct chp_id chpid, int on)  		/* Try to update the channel path descritor. */  		chsc_determine_base_channel_path_desc(chpid, &chp->desc);  		for_each_subchannel_staged(s390_subchannel_vary_chpid_on, -					   __s390_vary_chpid_on, &link); +					   __s390_vary_chpid_on, &chpid);  	} else  		for_each_subchannel_staged(s390_subchannel_vary_chpid_off, -					   NULL, &link); +					   NULL, &chpid);  	return 0;  } diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index 155a82bcb9e..4a1ff5c2eb8 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -68,8 +68,13 @@ struct schib {  	__u8 mda[4];		 /* model dependent area */  } __attribute__ ((packed,aligned(4))); +/* + * When rescheduled, todo's with higher values will overwrite those + * with lower values. + */  enum sch_todo {  	SCH_TODO_NOTHING, +	SCH_TODO_EVAL,  	SCH_TODO_UNREG,  }; diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 92d7324acb1..21908e67bf6 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -195,51 +195,6 @@ void css_sch_device_unregister(struct subchannel *sch)  }  EXPORT_SYMBOL_GPL(css_sch_device_unregister); -static void css_sch_todo(struct work_struct *work) -{ -	struct subchannel *sch; -	enum sch_todo todo; - -	sch = container_of(work, struct subchannel, todo_work); -	/* Find out todo. */ -	spin_lock_irq(sch->lock); -	todo = sch->todo; -	CIO_MSG_EVENT(4, "sch_todo: sch=0.%x.%04x, todo=%d\n", sch->schid.ssid, -		      sch->schid.sch_no, todo); -	sch->todo = SCH_TODO_NOTHING; -	spin_unlock_irq(sch->lock); -	/* Perform todo. */ -	if (todo == SCH_TODO_UNREG) -		css_sch_device_unregister(sch); -	/* Release workqueue ref. */ -	put_device(&sch->dev); -} - -/** - * css_sched_sch_todo - schedule a subchannel operation - * @sch: subchannel - * @todo: todo - * - * Schedule the operation identified by @todo to be performed on the slow path - * workqueue. Do nothing if another operation with higher priority is already - * scheduled. Needs to be called with subchannel lock held. - */ -void css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo) -{ -	CIO_MSG_EVENT(4, "sch_todo: sched sch=0.%x.%04x todo=%d\n", -		      sch->schid.ssid, sch->schid.sch_no, todo); -	if (sch->todo >= todo) -		return; -	/* Get workqueue ref. */ -	if (!get_device(&sch->dev)) -		return; -	sch->todo = todo; -	if (!queue_work(cio_work_q, &sch->todo_work)) { -		/* Already queued, release workqueue ref. */ -		put_device(&sch->dev); -	} -} -  static void ssd_from_pmcw(struct chsc_ssd_info *ssd, struct pmcw *pmcw)  {  	int i; @@ -466,6 +421,65 @@ static void css_evaluate_subchannel(struct subchannel_id schid, int slow)  		css_schedule_eval(schid);  } +/** + * css_sched_sch_todo - schedule a subchannel operation + * @sch: subchannel + * @todo: todo + * + * Schedule the operation identified by @todo to be performed on the slow path + * workqueue. Do nothing if another operation with higher priority is already + * scheduled. Needs to be called with subchannel lock held. + */ +void css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo) +{ +	CIO_MSG_EVENT(4, "sch_todo: sched sch=0.%x.%04x todo=%d\n", +		      sch->schid.ssid, sch->schid.sch_no, todo); +	if (sch->todo >= todo) +		return; +	/* Get workqueue ref. */ +	if (!get_device(&sch->dev)) +		return; +	sch->todo = todo; +	if (!queue_work(cio_work_q, &sch->todo_work)) { +		/* Already queued, release workqueue ref. */ +		put_device(&sch->dev); +	} +} + +static void css_sch_todo(struct work_struct *work) +{ +	struct subchannel *sch; +	enum sch_todo todo; +	int ret; + +	sch = container_of(work, struct subchannel, todo_work); +	/* Find out todo. */ +	spin_lock_irq(sch->lock); +	todo = sch->todo; +	CIO_MSG_EVENT(4, "sch_todo: sch=0.%x.%04x, todo=%d\n", sch->schid.ssid, +		      sch->schid.sch_no, todo); +	sch->todo = SCH_TODO_NOTHING; +	spin_unlock_irq(sch->lock); +	/* Perform todo. */ +	switch (todo) { +	case SCH_TODO_NOTHING: +		break; +	case SCH_TODO_EVAL: +		ret = css_evaluate_known_subchannel(sch, 1); +		if (ret == -EAGAIN) { +			spin_lock_irq(sch->lock); +			css_sched_sch_todo(sch, todo); +			spin_unlock_irq(sch->lock); +		} +		break; +	case SCH_TODO_UNREG: +		css_sch_device_unregister(sch); +		break; +	} +	/* Release workqueue ref. */ +	put_device(&sch->dev); +} +  static struct idset *slow_subchannel_set;  static spinlock_t slow_subchannel_lock;  static wait_queue_head_t css_eval_wq; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index d734f4a0eca..47269858ecb 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1868,9 +1868,9 @@ static void __ccw_device_pm_restore(struct ccw_device *cdev)  	 */  	cdev->private->flags.resuming = 1;  	cdev->private->path_new_mask = LPM_ANYPATH; -	css_schedule_eval(sch->schid); +	css_sched_sch_todo(sch, SCH_TODO_EVAL);  	spin_unlock_irq(sch->lock); -	css_complete_work(); +	css_wait_for_slow_path();  	/* cdev may have been moved to a different subchannel. */  	sch = to_subchannel(cdev->dev.parent); diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 52c233fa2b1..1b853513c89 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -496,8 +496,26 @@ static void ccw_device_reset_path_events(struct ccw_device *cdev)  	cdev->private->pgid_reset_mask = 0;  } -void -ccw_device_verify_done(struct ccw_device *cdev, int err) +static void create_fake_irb(struct irb *irb, int type) +{ +	memset(irb, 0, sizeof(*irb)); +	if (type == FAKE_CMD_IRB) { +		struct cmd_scsw *scsw = &irb->scsw.cmd; +		scsw->cc = 1; +		scsw->fctl = SCSW_FCTL_START_FUNC; +		scsw->actl = SCSW_ACTL_START_PEND; +		scsw->stctl = SCSW_STCTL_STATUS_PEND; +	} else if (type == FAKE_TM_IRB) { +		struct tm_scsw *scsw = &irb->scsw.tm; +		scsw->x = 1; +		scsw->cc = 1; +		scsw->fctl = SCSW_FCTL_START_FUNC; +		scsw->actl = SCSW_ACTL_START_PEND; +		scsw->stctl = SCSW_STCTL_STATUS_PEND; +	} +} + +void ccw_device_verify_done(struct ccw_device *cdev, int err)  {  	struct subchannel *sch; @@ -520,12 +538,8 @@ callback:  		ccw_device_done(cdev, DEV_STATE_ONLINE);  		/* Deliver fake irb to device driver, if needed. */  		if (cdev->private->flags.fake_irb) { -			memset(&cdev->private->irb, 0, sizeof(struct irb)); -			cdev->private->irb.scsw.cmd.cc = 1; -			cdev->private->irb.scsw.cmd.fctl = SCSW_FCTL_START_FUNC; -			cdev->private->irb.scsw.cmd.actl = SCSW_ACTL_START_PEND; -			cdev->private->irb.scsw.cmd.stctl = -				SCSW_STCTL_STATUS_PEND; +			create_fake_irb(&cdev->private->irb, +					cdev->private->flags.fake_irb);  			cdev->private->flags.fake_irb = 0;  			if (cdev->handler)  				cdev->handler(cdev, cdev->private->intparm, diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index f98698d5735..ec7fb6d3b47 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -198,7 +198,7 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,  	if (cdev->private->state == DEV_STATE_VERIFY) {  		/* Remember to fake irb when finished. */  		if (!cdev->private->flags.fake_irb) { -			cdev->private->flags.fake_irb = 1; +			cdev->private->flags.fake_irb = FAKE_CMD_IRB;  			cdev->private->intparm = intparm;  			return 0;  		} else @@ -213,9 +213,9 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,  	ret = cio_set_options (sch, flags);  	if (ret)  		return ret; -	/* Adjust requested path mask to excluded varied off paths. */ +	/* Adjust requested path mask to exclude unusable paths. */  	if (lpm) { -		lpm &= sch->opm; +		lpm &= sch->lpm;  		if (lpm == 0)  			return -EACCES;  	} @@ -605,11 +605,21 @@ int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,  	sch = to_subchannel(cdev->dev.parent);  	if (!sch->schib.pmcw.ena)  		return -EINVAL; +	if (cdev->private->state == DEV_STATE_VERIFY) { +		/* Remember to fake irb when finished. */ +		if (!cdev->private->flags.fake_irb) { +			cdev->private->flags.fake_irb = FAKE_TM_IRB; +			cdev->private->intparm = intparm; +			return 0; +		} else +			/* There's already a fake I/O around. */ +			return -EBUSY; +	}  	if (cdev->private->state != DEV_STATE_ONLINE)  		return -EIO; -	/* Adjust requested path mask to excluded varied off paths. */ +	/* Adjust requested path mask to exclude unusable paths. */  	if (lpm) { -		lpm &= sch->opm; +		lpm &= sch->lpm;  		if (lpm == 0)  			return -EACCES;  	} diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h index 2ebb492a5c1..76253dfcc1b 100644 --- a/drivers/s390/cio/io_sch.h +++ b/drivers/s390/cio/io_sch.h @@ -111,6 +111,9 @@ enum cdev_todo {  	CDEV_TODO_UNREG_EVAL,  }; +#define FAKE_CMD_IRB	1 +#define FAKE_TM_IRB	2 +  struct ccw_device_private {  	struct ccw_device *cdev;  	struct subchannel *sch; @@ -138,7 +141,7 @@ struct ccw_device_private {  		unsigned int doverify:1;    /* delayed path verification */  		unsigned int donotify:1;    /* call notify function */  		unsigned int recog_done:1;  /* dev. recog. complete */ -		unsigned int fake_irb:1;    /* deliver faked irb */ +		unsigned int fake_irb:2;    /* deliver faked irb */  		unsigned int resuming:1;    /* recognition while resume */  		unsigned int pgroup:1;	    /* pathgroup is set up */  		unsigned int mpath:1;	    /* multipathing is set up */ diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index ec94f049e99..96bbe9d12a7 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -1552,6 +1552,8 @@ static void ap_reset(struct ap_device *ap_dev)  	rc = ap_init_queue(ap_dev->qid);  	if (rc == -ENODEV)  		ap_dev->unregistered = 1; +	else +		__ap_schedule_poll_timer();  }  static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 21d8c1c16cd..5e78c77d5a0 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -671,7 +671,7 @@ static int do_insnlist_ioctl(struct comedi_device *dev,  	}  	insns = -	    kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL); +	    kcalloc(insnlist.n_insns, sizeof(struct comedi_insn), GFP_KERNEL);  	if (!insns) {  		DPRINTK("kmalloc failed\n");  		ret = -ENOMEM; @@ -1432,7 +1432,21 @@ static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s)  	return ret;  } -static void comedi_unmap(struct vm_area_struct *area) + +static void comedi_vm_open(struct vm_area_struct *area) +{ +	struct comedi_async *async; +	struct comedi_device *dev; + +	async = area->vm_private_data; +	dev = async->subdevice->device; + +	mutex_lock(&dev->mutex); +	async->mmap_count++; +	mutex_unlock(&dev->mutex); +} + +static void comedi_vm_close(struct vm_area_struct *area)  {  	struct comedi_async *async;  	struct comedi_device *dev; @@ -1446,15 +1460,13 @@ static void comedi_unmap(struct vm_area_struct *area)  }  static struct vm_operations_struct comedi_vm_ops = { -	.close = comedi_unmap, +	.open = comedi_vm_open, +	.close = comedi_vm_close,  };  static int comedi_mmap(struct file *file, struct vm_area_struct *vma)  {  	const unsigned minor = iminor(file->f_dentry->d_inode); -	struct comedi_device_file_info *dev_file_info = -	    comedi_get_device_file_info(minor); -	struct comedi_device *dev = dev_file_info->device;  	struct comedi_async *async = NULL;  	unsigned long start = vma->vm_start;  	unsigned long size; @@ -1462,6 +1474,15 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)  	int i;  	int retval;  	struct comedi_subdevice *s; +	struct comedi_device_file_info *dev_file_info; +	struct comedi_device *dev; + +	dev_file_info = comedi_get_device_file_info(minor); +	if (dev_file_info == NULL) +	        return -ENODEV; +	dev = dev_file_info->device; +	if (dev == NULL) +	        return -ENODEV;  	mutex_lock(&dev->mutex);  	if (!dev->attached) { @@ -1528,11 +1549,17 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait)  {  	unsigned int mask = 0;  	const unsigned minor = iminor(file->f_dentry->d_inode); -	struct comedi_device_file_info *dev_file_info = -	    comedi_get_device_file_info(minor); -	struct comedi_device *dev = dev_file_info->device;  	struct comedi_subdevice *read_subdev;  	struct comedi_subdevice *write_subdev; +	struct comedi_device_file_info *dev_file_info; +	struct comedi_device *dev; +	dev_file_info = comedi_get_device_file_info(minor); + +	if (dev_file_info == NULL) +	        return -ENODEV; +	dev = dev_file_info->device; +	if (dev == NULL) +	        return -ENODEV;  	mutex_lock(&dev->mutex);  	if (!dev->attached) { @@ -1578,9 +1605,15 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,  	int n, m, count = 0, retval = 0;  	DECLARE_WAITQUEUE(wait, current);  	const unsigned minor = iminor(file->f_dentry->d_inode); -	struct comedi_device_file_info *dev_file_info = -	    comedi_get_device_file_info(minor); -	struct comedi_device *dev = dev_file_info->device; +	struct comedi_device_file_info *dev_file_info; +	struct comedi_device *dev; +	dev_file_info = comedi_get_device_file_info(minor); + +	if (dev_file_info == NULL) +	        return -ENODEV; +	dev = dev_file_info->device; +	if (dev == NULL) +	        return -ENODEV;  	if (!dev->attached) {  		DPRINTK("no driver configured on comedi%i\n", dev->minor); @@ -1640,11 +1673,11 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,  				retval = -EAGAIN;  				break;  			} +			schedule();  			if (signal_pending(current)) {  				retval = -ERESTARTSYS;  				break;  			} -			schedule();  			if (!s->busy)  				break;  			if (s->busy != file) { @@ -1683,9 +1716,15 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,  	int n, m, count = 0, retval = 0;  	DECLARE_WAITQUEUE(wait, current);  	const unsigned minor = iminor(file->f_dentry->d_inode); -	struct comedi_device_file_info *dev_file_info = -	    comedi_get_device_file_info(minor); -	struct comedi_device *dev = dev_file_info->device; +	struct comedi_device_file_info *dev_file_info; +	struct comedi_device *dev; +	dev_file_info = comedi_get_device_file_info(minor); + +	if (dev_file_info == NULL) +	        return -ENODEV; +	dev = dev_file_info->device; +	if (dev == NULL) +	        return -ENODEV;  	if (!dev->attached) {  		DPRINTK("no driver configured on comedi%i\n", dev->minor); @@ -1741,11 +1780,11 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,  				retval = -EAGAIN;  				break;  			} +			schedule();  			if (signal_pending(current)) {  				retval = -ERESTARTSYS;  				break;  			} -			schedule();  			if (!s->busy) {  				retval = 0;  				break; @@ -1885,11 +1924,17 @@ ok:  static int comedi_close(struct inode *inode, struct file *file)  {  	const unsigned minor = iminor(inode); -	struct comedi_device_file_info *dev_file_info = -	    comedi_get_device_file_info(minor); -	struct comedi_device *dev = dev_file_info->device;  	struct comedi_subdevice *s = NULL;  	int i; +	struct comedi_device_file_info *dev_file_info; +	struct comedi_device *dev; +	dev_file_info = comedi_get_device_file_info(minor); + +	if (dev_file_info == NULL) +	        return -ENODEV; +	dev = dev_file_info->device; +	if (dev == NULL) +	        return -ENODEV;  	mutex_lock(&dev->mutex); @@ -1923,10 +1968,15 @@ static int comedi_close(struct inode *inode, struct file *file)  static int comedi_fasync(int fd, struct file *file, int on)  {  	const unsigned minor = iminor(file->f_dentry->d_inode); -	struct comedi_device_file_info *dev_file_info = -	    comedi_get_device_file_info(minor); +	struct comedi_device_file_info *dev_file_info; +	struct comedi_device *dev; +	dev_file_info = comedi_get_device_file_info(minor); -	struct comedi_device *dev = dev_file_info->device; +	if (dev_file_info == NULL) +	        return -ENODEV; +	dev = dev_file_info->device; +	if (dev == NULL) +	        return -ENODEV;  	return fasync_helper(fd, file, on, &dev->async_queue);  } diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index a8fea9a9173..6144afb8cba 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1,4 +1,4 @@ -#define DRIVER_VERSION "v0.5" +#define DRIVER_VERSION "v0.6"  #define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com"  #define DRIVER_DESC "Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com"  /* @@ -25,7 +25,7 @@ Driver: usbduxsigma  Description: University of Stirling USB DAQ & INCITE Technology Limited  Devices: [ITL] USB-DUX (usbduxsigma.o)  Author: Bernd Porr <BerndPorr@f2s.com> -Updated: 21 Jul 2011 +Updated: 8 Nov 2011  Status: testing  */  /* @@ -44,6 +44,7 @@ Status: testing   *   0.3: proper vendor ID and driver name   *   0.4: fixed D/A voltage range   *   0.5: various bug fixes, health check at startup + *   0.6: corrected wrong input range   */  /* generates loads of debug info */ @@ -175,7 +176,7 @@ Status: testing  /* comedi constants */  static const struct comedi_lrange range_usbdux_ai_range = { 1, {  								BIP_RANGE -								(2.65) +								(2.65/2.0)  								}  }; diff --git a/drivers/staging/rts_pstor/rtsx.c b/drivers/staging/rts_pstor/rtsx.c index 480b0ed2e4d..115635f9502 100644 --- a/drivers/staging/rts_pstor/rtsx.c +++ b/drivers/staging/rts_pstor/rtsx.c @@ -1021,6 +1021,7 @@ static int __devinit rtsx_probe(struct pci_dev *pci,  	th = kthread_create(rtsx_scan_thread, dev, "rtsx-scan");  	if (IS_ERR(th)) {  		printk(KERN_ERR "Unable to start the device-scanning thread\n"); +		complete(&dev->scanning_done);  		quiesce_and_remove_host(dev);  		err = PTR_ERR(th);  		goto errout; diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index 09c44abb89e..3872b8cccdc 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -68,6 +68,7 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,  {  	struct usbip_device *ud = &vdev->ud;  	struct urb *urb; +	unsigned long flags;  	spin_lock(&vdev->priv_lock);  	urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); @@ -101,9 +102,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,  	usbip_dbg_vhci_rx("now giveback urb %p\n", urb); -	spin_lock(&the_controller->lock); +	spin_lock_irqsave(&the_controller->lock, flags);  	usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); -	spin_unlock(&the_controller->lock); +	spin_unlock_irqrestore(&the_controller->lock, flags);  	usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -141,6 +142,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,  {  	struct vhci_unlink *unlink;  	struct urb *urb; +	unsigned long flags;  	usbip_dump_header(pdu); @@ -170,9 +172,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,  		urb->status = pdu->u.ret_unlink.status;  		pr_info("urb->status %d\n", urb->status); -		spin_lock(&the_controller->lock); +		spin_lock_irqsave(&the_controller->lock, flags);  		usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); -		spin_unlock(&the_controller->lock); +		spin_unlock_irqrestore(&the_controller->lock, flags);  		usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,  				     urb->status); diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 4730016d7cd..45f422ac103 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -1959,7 +1959,7 @@ static int amd5536_start(struct usb_gadget_driver *driver,  	u32 tmp;  	if (!driver || !bind || !driver->setup -			|| driver->speed != USB_SPEED_HIGH) +			|| driver->speed < USB_SPEED_HIGH)  		return -EINVAL;  	if (!dev)  		return -ENODEV; diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index 91fdf790ed2..cf33a8d0fd5 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -131,8 +131,8 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)  	}  	if (!gser->port.in->desc || !gser->port.out->desc) {  		DBG(cdev, "activate generic ttyGS%d\n", gser->port_num); -		if (!config_ep_by_speed(cdev->gadget, f, gser->port.in) || -		    !config_ep_by_speed(cdev->gadget, f, gser->port.out)) { +		if (config_ep_by_speed(cdev->gadget, f, gser->port.in) || +		    config_ep_by_speed(cdev->gadget, f, gser->port.out)) {  			gser->port.in->desc = NULL;  			gser->port.out->desc = NULL;  			return -EINVAL; diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c index 43a49ecc1f3..dcbc0a2e48d 100644 --- a/drivers/usb/gadget/fsl_mxc_udc.c +++ b/drivers/usb/gadget/fsl_mxc_udc.c @@ -16,6 +16,7 @@  #include <linux/err.h>  #include <linux/fsl_devices.h>  #include <linux/platform_device.h> +#include <linux/io.h>  #include <mach/hardware.h> @@ -88,7 +89,6 @@ eenahb:  void fsl_udc_clk_finalize(struct platform_device *pdev)  {  	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; -#if defined(CONFIG_SOC_IMX35)  	if (cpu_is_mx35()) {  		unsigned int v; @@ -101,7 +101,6 @@ void fsl_udc_clk_finalize(struct platform_device *pdev)  					USBPHYCTRL_OTGBASE_OFFSET));  		}  	} -#endif  	/* ULPI transceivers don't need usbpll */  	if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 2a03e4de11c..e00cf92409c 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2336,8 +2336,7 @@ static int fsl_qe_start(struct usb_gadget_driver *driver,  	if (!udc_controller)  		return -ENODEV; -	if (!driver || (driver->speed != USB_SPEED_FULL -			&& driver->speed != USB_SPEED_HIGH) +	if (!driver || driver->speed < USB_SPEED_FULL  			|| !bind || !driver->disconnect || !driver->setup)  		return -EINVAL; diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index b3b3d83b7c3..dd28ef3def7 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -696,12 +696,31 @@ static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req)  		kfree(req);  } -/*-------------------------------------------------------------------------*/ +/* Actually add a dTD chain to an empty dQH and let go */ +static void fsl_prime_ep(struct fsl_ep *ep, struct ep_td_struct *td) +{ +	struct ep_queue_head *qh = get_qh_by_ep(ep); + +	/* Write dQH next pointer and terminate bit to 0 */ +	qh->next_dtd_ptr = cpu_to_hc32(td->td_dma +			& EP_QUEUE_HEAD_NEXT_POINTER_MASK); + +	/* Clear active and halt bit */ +	qh->size_ioc_int_sts &= cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE +					| EP_QUEUE_HEAD_STATUS_HALT)); + +	/* Ensure that updates to the QH will occur before priming. */ +	wmb(); + +	/* Prime endpoint by writing correct bit to ENDPTPRIME */ +	fsl_writel(ep_is_in(ep) ? (1 << (ep_index(ep) + 16)) +			: (1 << (ep_index(ep))), &dr_regs->endpointprime); +} + +/* Add dTD chain to the dQH of an EP */  static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)  { -	int i = ep_index(ep) * 2 + ep_is_in(ep);  	u32 temp, bitmask, tmp_stat; -	struct ep_queue_head *dQH = &ep->udc->ep_qh[i];  	/* VDBG("QH addr Register 0x%8x", dr_regs->endpointlistaddr);  	VDBG("ep_qh[%d] addr is 0x%8x", i, (u32)&(ep->udc->ep_qh[i])); */ @@ -719,7 +738,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)  			cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK);  		/* Read prime bit, if 1 goto done */  		if (fsl_readl(&dr_regs->endpointprime) & bitmask) -			goto out; +			return;  		do {  			/* Set ATDTW bit in USBCMD */ @@ -736,28 +755,10 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)  		fsl_writel(temp & ~USB_CMD_ATDTW, &dr_regs->usbcmd);  		if (tmp_stat) -			goto out; +			return;  	} -	/* Write dQH next pointer and terminate bit to 0 */ -	temp = req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK; -	dQH->next_dtd_ptr = cpu_to_hc32(temp); - -	/* Clear active and halt bit */ -	temp = cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE -			| EP_QUEUE_HEAD_STATUS_HALT)); -	dQH->size_ioc_int_sts &= temp; - -	/* Ensure that updates to the QH will occur before priming. */ -	wmb(); - -	/* Prime endpoint by writing 1 to ENDPTPRIME */ -	temp = ep_is_in(ep) -		? (1 << (ep_index(ep) + 16)) -		: (1 << (ep_index(ep))); -	fsl_writel(temp, &dr_regs->endpointprime); -out: -	return; +	fsl_prime_ep(ep, req->head);  }  /* Fill in the dTD structure @@ -877,7 +878,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)  		VDBG("%s, bad ep", __func__);  		return -EINVAL;  	} -	if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { +	if (usb_endpoint_xfer_isoc(ep->desc)) {  		if (req->req.length > ep->ep.maxpacket)  			return -EMSGSIZE;  	} @@ -973,25 +974,20 @@ static int fsl_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)  		/* The request isn't the last request in this ep queue */  		if (req->queue.next != &ep->queue) { -			struct ep_queue_head *qh;  			struct fsl_req *next_req; -			qh = ep->qh;  			next_req = list_entry(req->queue.next, struct fsl_req,  					queue); -			/* Point the QH to the first TD of next request */ -			fsl_writel((u32) next_req->head, &qh->curr_dtd_ptr); +			/* prime with dTD of next request */ +			fsl_prime_ep(ep, next_req->head);  		} - -		/* The request hasn't been processed, patch up the TD chain */ +	/* The request hasn't been processed, patch up the TD chain */  	} else {  		struct fsl_req *prev_req;  		prev_req = list_entry(req->queue.prev, struct fsl_req, queue); -		fsl_writel(fsl_readl(&req->tail->next_td_ptr), -				&prev_req->tail->next_td_ptr); - +		prev_req->tail->next_td_ptr = req->tail->next_td_ptr;  	}  	done(ep, req, -ECONNRESET); @@ -1032,7 +1028,7 @@ static int fsl_ep_set_halt(struct usb_ep *_ep, int value)  		goto out;  	} -	if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { +	if (usb_endpoint_xfer_isoc(ep->desc)) {  		status = -EOPNOTSUPP;  		goto out;  	} @@ -1068,7 +1064,7 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep)  	struct fsl_udc *udc;  	int size = 0;  	u32 bitmask; -	struct ep_queue_head *d_qh; +	struct ep_queue_head *qh;  	ep = container_of(_ep, struct fsl_ep, ep);  	if (!_ep || (!ep->desc && ep_index(ep) != 0)) @@ -1079,13 +1075,13 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep)  	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)  		return -ESHUTDOWN; -	d_qh = &ep->udc->ep_qh[ep_index(ep) * 2 + ep_is_in(ep)]; +	qh = get_qh_by_ep(ep);  	bitmask = (ep_is_in(ep)) ? (1 << (ep_index(ep) + 16)) :  	    (1 << (ep_index(ep)));  	if (fsl_readl(&dr_regs->endptstatus) & bitmask) -		size = (d_qh->size_ioc_int_sts & DTD_PACKET_SIZE) +		size = (qh->size_ioc_int_sts & DTD_PACKET_SIZE)  		    >> DTD_LENGTH_BIT_POS;  	pr_debug("%s %u\n", __func__, size); @@ -1938,8 +1934,7 @@ static int fsl_start(struct usb_gadget_driver *driver,  	if (!udc_controller)  		return -ENODEV; -	if (!driver || (driver->speed != USB_SPEED_FULL -				&& driver->speed != USB_SPEED_HIGH) +	if (!driver || driver->speed < USB_SPEED_FULL  			|| !bind || !driver->disconnect || !driver->setup)  		return -EINVAL; diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index 1d51be83fda..f781f5dec41 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -569,6 +569,16 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length)  					* 2 + ((windex & USB_DIR_IN) ? 1 : 0))  #define get_pipe_by_ep(EP)	(ep_index(EP) * 2 + ep_is_in(EP)) +static inline struct ep_queue_head *get_qh_by_ep(struct fsl_ep *ep) +{ +	/* we only have one ep0 structure but two queue heads */ +	if (ep_index(ep) != 0) +		return ep->qh; +	else +		return &ep->udc->ep_qh[(ep->udc->ep0_dir == +				USB_DIR_IN) ? 1 : 0]; +} +  struct platform_device;  #ifdef CONFIG_ARCH_MXC  int fsl_udc_clk_init(struct platform_device *pdev); diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 91d0af2a24a..9aa1cbbee45 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1472,7 +1472,7 @@ static int m66592_start(struct usb_gadget_driver *driver,  	int retval;  	if (!driver -			|| driver->speed != USB_SPEED_HIGH +			|| driver->speed < USB_SPEED_HIGH  			|| !bind  			|| !driver->setup)  		return -EINVAL; diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 7f1bc9a73cd..da2b9d0be3c 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -1881,7 +1881,7 @@ static int net2280_start(struct usb_gadget *_gadget,  	 * (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE)  	 * "must not be used in normal operation"  	 */ -	if (!driver || driver->speed != USB_SPEED_HIGH +	if (!driver || driver->speed < USB_SPEED_HIGH  			|| !driver->setup)  		return -EINVAL; diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 24f84b210ce..fc719a3f855 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1746,7 +1746,7 @@ static int r8a66597_start(struct usb_gadget *gadget,  	struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);  	if (!driver -			|| driver->speed != USB_SPEED_HIGH +			|| driver->speed < USB_SPEED_HIGH  			|| !driver->setup)  		return -EINVAL;  	if (!r8a66597) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index a552453dc94..b31448229f0 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2586,10 +2586,8 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver,  		return -EINVAL;  	} -	if (driver->speed != USB_SPEED_HIGH && -	    driver->speed != USB_SPEED_FULL) { +	if (driver->speed < USB_SPEED_FULL)  		dev_err(hsotg->dev, "%s: bad speed\n", __func__); -	}  	if (!bind || !driver->setup) {  		dev_err(hsotg->dev, "%s: missing entry points\n", __func__); diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 8d54f893cef..20a553b46ae 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -1142,8 +1142,7 @@ static int s3c_hsudc_start(struct usb_gadget_driver *driver,  	int ret;  	if (!driver -		|| (driver->speed != USB_SPEED_FULL && -			driver->speed != USB_SPEED_HIGH) +		|| driver->speed < USB_SPEED_FULL  		|| !bind  		|| !driver->unbind || !driver->disconnect || !driver->setup)  		return -EINVAL; diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 56a32033adb..a60679cbbf8 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1475,6 +1475,7 @@ iso_stream_schedule (  	 * jump until after the queue is primed.  	 */  	else { +		int done = 0;  		start = SCHEDULE_SLOP + (now & ~0x07);  		/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */ @@ -1492,18 +1493,18 @@ iso_stream_schedule (  			if (stream->highspeed) {  				if (itd_slot_ok(ehci, mod, start,  						stream->usecs, period)) -					break; +					done = 1;  			} else {  				if ((start % 8) >= 6)  					continue;  				if (sitd_slot_ok(ehci, mod, stream,  						start, sched, period)) -					break; +					done = 1;  			} -		} while (start > next); +		} while (start > next && !done);  		/* no room in the schedule */ -		if (start == next) { +		if (!done) {  			ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n",  				urb, now, now + mod);  			status = -ENOSPC; diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index d6e17542861..a403b53e86b 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -124,7 +124,7 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)  {  	qset->td_start = qset->td_end = qset->ntds = 0; -	qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); +	qset->qh.link = cpu_to_le64(QH_LINK_NTDS(8) | QH_LINK_T);  	qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK;  	qset->qh.err_count = 0;  	qset->qh.scratch[0] = 0; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index aa94c019579..a1afb7c39f7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -711,7 +711,10 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)  	ring = xhci->cmd_ring;  	seg = ring->deq_seg;  	do { -		memset(seg->trbs, 0, SEGMENT_SIZE); +		memset(seg->trbs, 0, +			sizeof(union xhci_trb) * (TRBS_PER_SEGMENT - 1)); +		seg->trbs[TRBS_PER_SEGMENT - 1].link.control &= +			cpu_to_le32(~TRB_CYCLE);  		seg = seg->next;  	} while (seg != ring->deq_seg); diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index c1fa12ec7a9..b63ab157010 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2301,18 +2301,12 @@ static int musb_suspend(struct device *dev)  		 */  	} -	musb_save_context(musb); -  	spin_unlock_irqrestore(&musb->lock, flags);  	return 0;  }  static int musb_resume_noirq(struct device *dev)  { -	struct musb	*musb = dev_to_musb(dev); - -	musb_restore_context(musb); -  	/* for static cmos like DaVinci, register values were preserved  	 * unless for some reason the whole soc powered down or the USB  	 * module got reset through the PSC (vs just being disabled). diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d51043acfe1..922148ff8d2 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1903,7 +1903,7 @@ static int musb_gadget_start(struct usb_gadget *g,  	unsigned long		flags;  	int			retval = -EINVAL; -	if (driver->speed != USB_SPEED_HIGH) +	if (driver->speed < USB_SPEED_HIGH)  		goto err0;  	pm_runtime_get_sync(musb->controller); diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index d9717e0bc1f..7f4e8033857 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -751,53 +751,32 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget,  		struct usb_gadget_driver *driver)  {  	struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); -	struct usbhs_priv *priv; -	struct device *dev; -	int ret; +	struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);  	if (!driver		||  	    !driver->setup	|| -	    driver->speed != USB_SPEED_HIGH) +	    driver->speed < USB_SPEED_FULL)  		return -EINVAL; -	dev  = usbhsg_gpriv_to_dev(gpriv); -	priv = usbhsg_gpriv_to_priv(gpriv); -  	/* first hook up the driver ... */  	gpriv->driver = driver;  	gpriv->gadget.dev.driver = &driver->driver; -	ret = device_add(&gpriv->gadget.dev); -	if (ret) { -		dev_err(dev, "device_add error %d\n", ret); -		goto add_fail; -	} -  	return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD); - -add_fail: -	gpriv->driver = NULL; -	gpriv->gadget.dev.driver = NULL; - -	return ret;  }  static int usbhsg_gadget_stop(struct usb_gadget *gadget,  		struct usb_gadget_driver *driver)  {  	struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); -	struct usbhs_priv *priv; -	struct device *dev; +	struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);  	if (!driver		||  	    !driver->unbind)  		return -EINVAL; -	dev  = usbhsg_gpriv_to_dev(gpriv); -	priv = usbhsg_gpriv_to_priv(gpriv); -  	usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD); -	device_del(&gpriv->gadget.dev); +	gpriv->gadget.dev.driver = NULL;  	gpriv->driver = NULL;  	return 0; @@ -827,6 +806,13 @@ static int usbhsg_start(struct usbhs_priv *priv)  static int usbhsg_stop(struct usbhs_priv *priv)  { +	struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); + +	/* cable disconnect */ +	if (gpriv->driver && +	    gpriv->driver->disconnect) +		gpriv->driver->disconnect(&gpriv->gadget); +  	return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);  } @@ -876,12 +862,14 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)  	/*  	 * init gadget  	 */ -	device_initialize(&gpriv->gadget.dev);  	dev_set_name(&gpriv->gadget.dev, "gadget");  	gpriv->gadget.dev.parent	= dev;  	gpriv->gadget.name		= "renesas_usbhs_udc";  	gpriv->gadget.ops		= &usbhsg_gadget_ops;  	gpriv->gadget.is_dualspeed	= 1; +	ret = device_register(&gpriv->gadget.dev); +	if (ret < 0) +		goto err_add_udc;  	INIT_LIST_HEAD(&gpriv->gadget.ep_list); @@ -912,12 +900,15 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)  	ret = usb_add_gadget_udc(dev, &gpriv->gadget);  	if (ret) -		goto err_add_udc; +		goto err_register;  	dev_info(dev, "gadget probed\n");  	return 0; + +err_register: +	device_unregister(&gpriv->gadget.dev);  err_add_udc:  	kfree(gpriv->uep); @@ -933,6 +924,8 @@ void usbhs_mod_gadget_remove(struct usbhs_priv *priv)  	usb_del_gadget_udc(&gpriv->gadget); +	device_unregister(&gpriv->gadget.dev); +  	usbhsg_controller_unregister(gpriv);  	kfree(gpriv->uep); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index bd4298bb675..ff3db5d056a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -736,6 +736,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, +	{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) },  	{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),  		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },  	{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 571fa96b49c..055b64ef0bb 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -112,6 +112,7 @@  /* Propox devices */  #define FTDI_PROPOX_JTAGCABLEII_PID	0xD738 +#define FTDI_PROPOX_ISPCABLEIII_PID	0xD739  /* Lenz LI-USB Computer Interface. */  #define FTDI_LENZ_LIUSB_PID	0xD780 diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index d865878c9f9..e3426602dc8 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -661,6 +661,9 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x08) },  	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },  	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },  	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, @@ -747,6 +750,7 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },  	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */  	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ +	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */  	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */  	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },  	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 3041a974faf..24caba79d72 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1854,6 +1854,13 @@ UNUSUAL_DEV(  0x1370, 0x6828, 0x0110, 0x0110,  		USB_SC_DEVICE, USB_PR_DEVICE, NULL,  		US_FL_IGNORE_RESIDUE ), +/* Reported by Qinglin Ye <yestyle@gmail.com> */ +UNUSUAL_DEV(  0x13fe, 0x3600, 0x0100, 0x0100, +		"Kingston", +		"DT 101 G2", +		USB_SC_DEVICE, USB_PR_DEVICE, NULL, +		US_FL_BULK_IGNORE_TAG ), +  /* Reported by Francesco Foresti <frafore@tiscali.it> */  UNUSUAL_DEV(  0x14cd, 0x6600, 0x0201, 0x0201,  		"Super Top", diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index b6c4b3795c4..76e4266d2e7 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -42,6 +42,8 @@ xfs_acl_from_disk(struct xfs_acl *aclp)  	int count, i;  	count = be32_to_cpu(aclp->acl_cnt); +	if (count > XFS_ACL_MAX_ENTRIES) +		return ERR_PTR(-EFSCORRUPTED);  	acl = posix_acl_alloc(count, GFP_KERNEL);  	if (!acl) diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index d4906e7c978..c1b55e59655 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -110,6 +110,7 @@ xfs_attr_namesp_match(int arg_flags, int ondisk_flags)  /*   * Query whether the requested number of additional bytes of extended   * attribute space will be able to fit inline. + *   * Returns zero if not, else the di_forkoff fork offset to be used in the   * literal area for attribute data once the new bytes have been added.   * @@ -122,7 +123,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)  	int offset;  	int minforkoff;	/* lower limit on valid forkoff locations */  	int maxforkoff;	/* upper limit on valid forkoff locations */ -	int dsize;	 +	int dsize;  	xfs_mount_t *mp = dp->i_mount;  	offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */ @@ -136,47 +137,60 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)  		return (offset >= minforkoff) ? minforkoff : 0;  	} -	if (!(mp->m_flags & XFS_MOUNT_ATTR2)) { -		if (bytes <= XFS_IFORK_ASIZE(dp)) -			return dp->i_d.di_forkoff; +	/* +	 * If the requested numbers of bytes is smaller or equal to the +	 * current attribute fork size we can always proceed. +	 * +	 * Note that if_bytes in the data fork might actually be larger than +	 * the current data fork size is due to delalloc extents. In that +	 * case either the extent count will go down when they are converted +	 * to real extents, or the delalloc conversion will take care of the +	 * literal area rebalancing. +	 */ +	if (bytes <= XFS_IFORK_ASIZE(dp)) +		return dp->i_d.di_forkoff; + +	/* +	 * For attr2 we can try to move the forkoff if there is space in the +	 * literal area, but for the old format we are done if there is no +	 * space in the fixed attribute fork. +	 */ +	if (!(mp->m_flags & XFS_MOUNT_ATTR2))  		return 0; -	}  	dsize = dp->i_df.if_bytes; -	 +  	switch (dp->i_d.di_format) {  	case XFS_DINODE_FMT_EXTENTS: -		/*  +		/*  		 * If there is no attr fork and the data fork is extents,  -		 * determine if creating the default attr fork will result  -		 * in the extents form migrating to btree. If so, the  -		 * minimum offset only needs to be the space required for  +		 * determine if creating the default attr fork will result +		 * in the extents form migrating to btree. If so, the +		 * minimum offset only needs to be the space required for  		 * the btree root. -		 */  +		 */  		if (!dp->i_d.di_forkoff && dp->i_df.if_bytes >  		    xfs_default_attroffset(dp))  			dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS);  		break; -		  	case XFS_DINODE_FMT_BTREE:  		/* -		 * If have data btree then keep forkoff if we have one, -		 * otherwise we are adding a new attr, so then we set  -		 * minforkoff to where the btree root can finish so we have  +		 * If we have a data btree then keep forkoff if we have one, +		 * otherwise we are adding a new attr, so then we set +		 * minforkoff to where the btree root can finish so we have  		 * plenty of room for attrs  		 */  		if (dp->i_d.di_forkoff) { -			if (offset < dp->i_d.di_forkoff)  +			if (offset < dp->i_d.di_forkoff)  				return 0; -			else  -				return dp->i_d.di_forkoff; -		} else -			dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot); +			return dp->i_d.di_forkoff; +		} +		dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot);  		break;  	} -	 -	/*  -	 * A data fork btree root must have space for at least  + +	/* +	 * A data fork btree root must have space for at least  	 * MINDBTPTRS key/ptr pairs if the data fork is small or empty.  	 */  	minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); @@ -186,10 +200,10 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)  	maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS);  	maxforkoff = maxforkoff >> 3;	/* rounded down */ -	if (offset >= minforkoff && offset < maxforkoff) -		return offset;  	if (offset >= maxforkoff)  		return maxforkoff; +	if (offset >= minforkoff) +		return offset;  	return 0;  } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c0237c602f1..755ee816488 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2835,6 +2835,27 @@ corrupt_out:  	return XFS_ERROR(EFSCORRUPTED);  } +void +xfs_promote_inode( +	struct xfs_inode	*ip) +{ +	struct xfs_buf		*bp; + +	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); + +	bp = xfs_incore(ip->i_mount->m_ddev_targp, ip->i_imap.im_blkno, +			ip->i_imap.im_len, XBF_TRYLOCK); +	if (!bp) +		return; + +	if (XFS_BUF_ISDELAYWRITE(bp)) { +		xfs_buf_delwri_promote(bp); +		wake_up_process(ip->i_mount->m_ddev_targp->bt_task); +	} + +	xfs_buf_relse(bp); +} +  /*   * Return a pointer to the extent record at file index idx.   */ diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 760140d1dd6..b4cd4739f98 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -498,6 +498,7 @@ int		xfs_iunlink(struct xfs_trans *, xfs_inode_t *);  void		xfs_iext_realloc(xfs_inode_t *, int, int);  void		xfs_iunpin_wait(xfs_inode_t *);  int		xfs_iflush(xfs_inode_t *, uint); +void		xfs_promote_inode(struct xfs_inode *);  void		xfs_lock_inodes(xfs_inode_t **, int, uint);  void		xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c index aa3dc1a4d53..be5c51d8f75 100644 --- a/fs/xfs/xfs_sync.c +++ b/fs/xfs/xfs_sync.c @@ -770,6 +770,17 @@ restart:  	if (!xfs_iflock_nowait(ip)) {  		if (!(sync_mode & SYNC_WAIT))  			goto out; + +		/* +		 * If we only have a single dirty inode in a cluster there is +		 * a fair chance that the AIL push may have pushed it into +		 * the buffer, but xfsbufd won't touch it until 30 seconds +		 * from now, and thus we will lock up here. +		 * +		 * Promote the inode buffer to the front of the delwri list +		 * and wake up xfsbufd now. +		 */ +		xfs_promote_inode(ip);  		xfs_iflock(ip);  	} diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index f81676f1b31..4e4fbb820e2 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -197,6 +197,14 @@  	{0x1002, 0x6770, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6778, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6779, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6841, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6842, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6843, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6849, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6858, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6859, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6888, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6889, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 96efa6794ea..c3da42dd22b 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h @@ -172,6 +172,7 @@ enum {  	TRACE_EVENT_FL_FILTERED_BIT,  	TRACE_EVENT_FL_RECORDED_CMD_BIT,  	TRACE_EVENT_FL_CAP_ANY_BIT, +	TRACE_EVENT_FL_NO_SET_FILTER_BIT,  };  enum { @@ -179,6 +180,7 @@ enum {  	TRACE_EVENT_FL_FILTERED		= (1 << TRACE_EVENT_FL_FILTERED_BIT),  	TRACE_EVENT_FL_RECORDED_CMD	= (1 << TRACE_EVENT_FL_RECORDED_CMD_BIT),  	TRACE_EVENT_FL_CAP_ANY		= (1 << TRACE_EVENT_FL_CAP_ANY_BIT), +	TRACE_EVENT_FL_NO_SET_FILTER	= (1 << TRACE_EVENT_FL_NO_SET_FILTER_BIT),  };  struct ftrace_event_call { diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 94b1e356c02..32574eef939 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -126,6 +126,8 @@ extern struct cred init_cred;  # define INIT_PERF_EVENTS(tsk)  #endif +#define INIT_TASK_COMM "swapper" +  /*   *  INIT_TASK is used to set up the first task table, touch at   * your own risk!. Base=0, limit=0x1fffff (=2MB) @@ -162,7 +164,7 @@ extern struct cred init_cred;  	.group_leader	= &tsk,						\  	RCU_INIT_POINTER(.real_cred, &init_cred),			\  	RCU_INIT_POINTER(.cred, &init_cred),				\ -	.comm		= "swapper",					\ +	.comm		= INIT_TASK_COMM,				\  	.thread		= INIT_THREAD,					\  	.fs		= &init_fs,					\  	.files		= &init_files,					\ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 172ba70306d..2aaee0ca9da 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -517,8 +517,12 @@  #define PCI_DEVICE_ID_AMD_11H_NB_DRAM	0x1302  #define PCI_DEVICE_ID_AMD_11H_NB_MISC	0x1303  #define PCI_DEVICE_ID_AMD_11H_NB_LINK	0x1304 +#define PCI_DEVICE_ID_AMD_15H_NB_F0	0x1600 +#define PCI_DEVICE_ID_AMD_15H_NB_F1	0x1601 +#define PCI_DEVICE_ID_AMD_15H_NB_F2	0x1602  #define PCI_DEVICE_ID_AMD_15H_NB_F3	0x1603  #define PCI_DEVICE_ID_AMD_15H_NB_F4	0x1604 +#define PCI_DEVICE_ID_AMD_15H_NB_F5	0x1605  #define PCI_DEVICE_ID_AMD_CNB17H_F3	0x1703  #define PCI_DEVICE_ID_AMD_LANCE		0x2000  #define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001 diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 1e9ebe5e009..b1f89122bf6 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -822,6 +822,7 @@ struct perf_event {  	int				mmap_locked;  	struct user_struct		*mmap_user;  	struct ring_buffer		*rb; +	struct list_head		rb_entry;  	/* poll related */  	wait_queue_head_t		waitq; diff --git a/include/linux/sigma.h b/include/linux/sigma.h index e2accb3164d..d0de882c0d9 100644 --- a/include/linux/sigma.h +++ b/include/linux/sigma.h @@ -24,7 +24,7 @@ struct sigma_firmware {  struct sigma_firmware_header {  	unsigned char magic[7];  	u8 version; -	u32 crc; +	__le32 crc;  };  enum { @@ -40,19 +40,14 @@ enum {  struct sigma_action {  	u8 instr;  	u8 len_hi; -	u16 len; -	u16 addr; +	__le16 len; +	__be16 addr;  	unsigned char payload[];  };  static inline u32 sigma_action_len(struct sigma_action *sa)  { -	return (sa->len_hi << 16) | sa->len; -} - -static inline size_t sigma_action_size(struct sigma_action *sa, u32 payload_len) -{ -	return sizeof(*sa) + payload_len + (payload_len % 2); +	return (sa->len_hi << 16) | le16_to_cpu(sa->len);  }  extern int process_sigma_firmware(struct i2c_client *client, const char *name); diff --git a/kernel/events/core.c b/kernel/events/core.c index 0e8457da6f9..600c1629b64 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -185,6 +185,9 @@ static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,  static void update_context_time(struct perf_event_context *ctx);  static u64 perf_event_time(struct perf_event *event); +static void ring_buffer_attach(struct perf_event *event, +			       struct ring_buffer *rb); +  void __weak perf_event_print_debug(void)	{ }  extern __weak const char *perf_pmu_name(void) @@ -2173,7 +2176,8 @@ static void perf_event_context_sched_in(struct perf_event_context *ctx,  	perf_event_sched_in(cpuctx, ctx, task); -	cpuctx->task_ctx = ctx; +	if (ctx->nr_events) +		cpuctx->task_ctx = ctx;  	perf_pmu_enable(ctx->pmu);  	perf_ctx_unlock(cpuctx, ctx); @@ -3190,12 +3194,33 @@ static unsigned int perf_poll(struct file *file, poll_table *wait)  	struct ring_buffer *rb;  	unsigned int events = POLL_HUP; +	/* +	 * Race between perf_event_set_output() and perf_poll(): perf_poll() +	 * grabs the rb reference but perf_event_set_output() overrides it. +	 * Here is the timeline for two threads T1, T2: +	 * t0: T1, rb = rcu_dereference(event->rb) +	 * t1: T2, old_rb = event->rb +	 * t2: T2, event->rb = new rb +	 * t3: T2, ring_buffer_detach(old_rb) +	 * t4: T1, ring_buffer_attach(rb1) +	 * t5: T1, poll_wait(event->waitq) +	 * +	 * To avoid this problem, we grab mmap_mutex in perf_poll() +	 * thereby ensuring that the assignment of the new ring buffer +	 * and the detachment of the old buffer appear atomic to perf_poll() +	 */ +	mutex_lock(&event->mmap_mutex); +  	rcu_read_lock();  	rb = rcu_dereference(event->rb); -	if (rb) +	if (rb) { +		ring_buffer_attach(event, rb);  		events = atomic_xchg(&rb->poll, 0); +	}  	rcu_read_unlock(); +	mutex_unlock(&event->mmap_mutex); +  	poll_wait(file, &event->waitq, wait);  	return events; @@ -3496,6 +3521,49 @@ unlock:  	return ret;  } +static void ring_buffer_attach(struct perf_event *event, +			       struct ring_buffer *rb) +{ +	unsigned long flags; + +	if (!list_empty(&event->rb_entry)) +		return; + +	spin_lock_irqsave(&rb->event_lock, flags); +	if (!list_empty(&event->rb_entry)) +		goto unlock; + +	list_add(&event->rb_entry, &rb->event_list); +unlock: +	spin_unlock_irqrestore(&rb->event_lock, flags); +} + +static void ring_buffer_detach(struct perf_event *event, +			       struct ring_buffer *rb) +{ +	unsigned long flags; + +	if (list_empty(&event->rb_entry)) +		return; + +	spin_lock_irqsave(&rb->event_lock, flags); +	list_del_init(&event->rb_entry); +	wake_up_all(&event->waitq); +	spin_unlock_irqrestore(&rb->event_lock, flags); +} + +static void ring_buffer_wakeup(struct perf_event *event) +{ +	struct ring_buffer *rb; + +	rcu_read_lock(); +	rb = rcu_dereference(event->rb); +	list_for_each_entry_rcu(event, &rb->event_list, rb_entry) { +		wake_up_all(&event->waitq); +	} +	rcu_read_unlock(); +} +  static void rb_free_rcu(struct rcu_head *rcu_head)  {  	struct ring_buffer *rb; @@ -3521,9 +3589,19 @@ static struct ring_buffer *ring_buffer_get(struct perf_event *event)  static void ring_buffer_put(struct ring_buffer *rb)  { +	struct perf_event *event, *n; +	unsigned long flags; +  	if (!atomic_dec_and_test(&rb->refcount))  		return; +	spin_lock_irqsave(&rb->event_lock, flags); +	list_for_each_entry_safe(event, n, &rb->event_list, rb_entry) { +		list_del_init(&event->rb_entry); +		wake_up_all(&event->waitq); +	} +	spin_unlock_irqrestore(&rb->event_lock, flags); +  	call_rcu(&rb->rcu_head, rb_free_rcu);  } @@ -3546,6 +3624,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)  		atomic_long_sub((size >> PAGE_SHIFT) + 1, &user->locked_vm);  		vma->vm_mm->pinned_vm -= event->mmap_locked;  		rcu_assign_pointer(event->rb, NULL); +		ring_buffer_detach(event, rb);  		mutex_unlock(&event->mmap_mutex);  		ring_buffer_put(rb); @@ -3700,7 +3779,7 @@ static const struct file_operations perf_fops = {  void perf_event_wakeup(struct perf_event *event)  { -	wake_up_all(&event->waitq); +	ring_buffer_wakeup(event);  	if (event->pending_kill) {  		kill_fasync(&event->fasync, SIGIO, event->pending_kill); @@ -5822,6 +5901,8 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,  	INIT_LIST_HEAD(&event->group_entry);  	INIT_LIST_HEAD(&event->event_entry);  	INIT_LIST_HEAD(&event->sibling_list); +	INIT_LIST_HEAD(&event->rb_entry); +  	init_waitqueue_head(&event->waitq);  	init_irq_work(&event->pending, perf_pending_event); @@ -6028,6 +6109,8 @@ set:  	old_rb = event->rb;  	rcu_assign_pointer(event->rb, rb); +	if (old_rb) +		ring_buffer_detach(event, old_rb);  	ret = 0;  unlock:  	mutex_unlock(&event->mmap_mutex); diff --git a/kernel/events/internal.h b/kernel/events/internal.h index 09097dd8116..64568a69937 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -22,6 +22,9 @@ struct ring_buffer {  	local_t				lost;		/* nr records lost   */  	long				watermark;	/* wakeup watermark  */ +	/* poll crap */ +	spinlock_t			event_lock; +	struct list_head		event_list;  	struct perf_event_mmap_page	*user_page;  	void				*data_pages[0]; diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index a2a29205cc0..7f3011c6b57 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -209,6 +209,9 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)  		rb->writable = 1;  	atomic_set(&rb->refcount, 1); + +	INIT_LIST_HEAD(&rb->event_list); +	spin_lock_init(&rb->event_lock);  }  #ifndef CONFIG_PERF_USE_VMALLOC diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0e2b179bc7b..1da999f5e74 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -623,8 +623,9 @@ static irqreturn_t irq_nested_primary_handler(int irq, void *dev_id)  static int irq_wait_for_interrupt(struct irqaction *action)  { +	set_current_state(TASK_INTERRUPTIBLE); +  	while (!kthread_should_stop()) { -		set_current_state(TASK_INTERRUPTIBLE);  		if (test_and_clear_bit(IRQTF_RUNTHREAD,  				       &action->thread_flags)) { @@ -632,7 +633,9 @@ static int irq_wait_for_interrupt(struct irqaction *action)  			return 0;  		}  		schedule(); +		set_current_state(TASK_INTERRUPTIBLE);  	} +	__set_current_state(TASK_RUNNING);  	return -1;  } diff --git a/kernel/jump_label.c b/kernel/jump_label.c index bbdfe2a462a..66ff7109f69 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -66,8 +66,9 @@ void jump_label_inc(struct jump_label_key *key)  		return;  	jump_label_lock(); -	if (atomic_add_return(1, &key->enabled) == 1) +	if (atomic_read(&key->enabled) == 0)  		jump_label_update(key, JUMP_LABEL_ENABLE); +	atomic_inc(&key->enabled);  	jump_label_unlock();  } diff --git a/kernel/sched.c b/kernel/sched.c index 0e9344a71be..d6b149ccf92 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -71,6 +71,7 @@  #include <linux/ctype.h>  #include <linux/ftrace.h>  #include <linux/slab.h> +#include <linux/init_task.h>  #include <asm/tlb.h>  #include <asm/irq_regs.h> @@ -4810,6 +4811,9 @@ EXPORT_SYMBOL(wait_for_completion);   * This waits for either a completion of a specific task to be signaled or for a   * specified timeout to expire. The timeout is in jiffies. It is not   * interruptible. + * + * The return value is 0 if timed out, and positive (at least 1, or number of + * jiffies left till timeout) if completed.   */  unsigned long __sched  wait_for_completion_timeout(struct completion *x, unsigned long timeout) @@ -4824,6 +4828,8 @@ EXPORT_SYMBOL(wait_for_completion_timeout);   *   * This waits for completion of a specific task to be signaled. It is   * interruptible. + * + * The return value is -ERESTARTSYS if interrupted, 0 if completed.   */  int __sched wait_for_completion_interruptible(struct completion *x)  { @@ -4841,6 +4847,9 @@ EXPORT_SYMBOL(wait_for_completion_interruptible);   *   * This waits for either a completion of a specific task to be signaled or for a   * specified timeout to expire. It is interruptible. The timeout is in jiffies. + * + * The return value is -ERESTARTSYS if interrupted, 0 if timed out, + * positive (at least 1, or number of jiffies left till timeout) if completed.   */  long __sched  wait_for_completion_interruptible_timeout(struct completion *x, @@ -4856,6 +4865,8 @@ EXPORT_SYMBOL(wait_for_completion_interruptible_timeout);   *   * This waits to be signaled for completion of a specific task. It can be   * interrupted by a kill signal. + * + * The return value is -ERESTARTSYS if interrupted, 0 if completed.   */  int __sched wait_for_completion_killable(struct completion *x)  { @@ -4874,6 +4885,9 @@ EXPORT_SYMBOL(wait_for_completion_killable);   * This waits for either a completion of a specific task to be   * signaled or for a specified timeout to expire. It can be   * interrupted by a kill signal. The timeout is in jiffies. + * + * The return value is -ERESTARTSYS if interrupted, 0 if timed out, + * positive (at least 1, or number of jiffies left till timeout) if completed.   */  long __sched  wait_for_completion_killable_timeout(struct completion *x, @@ -6099,6 +6113,9 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)  	 */  	idle->sched_class = &idle_sched_class;  	ftrace_graph_init_idle_task(idle, cpu); +#if defined(CONFIG_SMP) +	sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu); +#endif  }  /* diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 5c9e67923b7..a78ed2736ba 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -772,19 +772,32 @@ static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)  		list_del_leaf_cfs_rq(cfs_rq);  } +static inline long calc_tg_weight(struct task_group *tg, struct cfs_rq *cfs_rq) +{ +	long tg_weight; + +	/* +	 * Use this CPU's actual weight instead of the last load_contribution +	 * to gain a more accurate current total weight. See +	 * update_cfs_rq_load_contribution(). +	 */ +	tg_weight = atomic_read(&tg->load_weight); +	tg_weight -= cfs_rq->load_contribution; +	tg_weight += cfs_rq->load.weight; + +	return tg_weight; +} +  static long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg)  { -	long load_weight, load, shares; +	long tg_weight, load, shares; +	tg_weight = calc_tg_weight(tg, cfs_rq);  	load = cfs_rq->load.weight; -	load_weight = atomic_read(&tg->load_weight); -	load_weight += load; -	load_weight -= cfs_rq->load_contribution; -  	shares = (tg->shares * load); -	if (load_weight) -		shares /= load_weight; +	if (tg_weight) +		shares /= tg_weight;  	if (shares < MIN_SHARES)  		shares = MIN_SHARES; @@ -1743,7 +1756,7 @@ static void __return_cfs_rq_runtime(struct cfs_rq *cfs_rq)  static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq)  { -	if (!cfs_rq->runtime_enabled || !cfs_rq->nr_running) +	if (!cfs_rq->runtime_enabled || cfs_rq->nr_running)  		return;  	__return_cfs_rq_runtime(cfs_rq); @@ -2036,36 +2049,100 @@ static void task_waking_fair(struct task_struct *p)   * Adding load to a group doesn't make a group heavier, but can cause movement   * of group shares between cpus. Assuming the shares were perfectly aligned one   * can calculate the shift in shares. + * + * Calculate the effective load difference if @wl is added (subtracted) to @tg + * on this @cpu and results in a total addition (subtraction) of @wg to the + * total group weight. + * + * Given a runqueue weight distribution (rw_i) we can compute a shares + * distribution (s_i) using: + * + *   s_i = rw_i / \Sum rw_j						(1) + * + * Suppose we have 4 CPUs and our @tg is a direct child of the root group and + * has 7 equal weight tasks, distributed as below (rw_i), with the resulting + * shares distribution (s_i): + * + *   rw_i = {   2,   4,   1,   0 } + *   s_i  = { 2/7, 4/7, 1/7,   0 } + * + * As per wake_affine() we're interested in the load of two CPUs (the CPU the + * task used to run on and the CPU the waker is running on), we need to + * compute the effect of waking a task on either CPU and, in case of a sync + * wakeup, compute the effect of the current task going to sleep. + * + * So for a change of @wl to the local @cpu with an overall group weight change + * of @wl we can compute the new shares distribution (s'_i) using: + * + *   s'_i = (rw_i + @wl) / (@wg + \Sum rw_j)				(2) + * + * Suppose we're interested in CPUs 0 and 1, and want to compute the load + * differences in waking a task to CPU 0. The additional task changes the + * weight and shares distributions like: + * + *   rw'_i = {   3,   4,   1,   0 } + *   s'_i  = { 3/8, 4/8, 1/8,   0 } + * + * We can then compute the difference in effective weight by using: + * + *   dw_i = S * (s'_i - s_i)						(3) + * + * Where 'S' is the group weight as seen by its parent. + * + * Therefore the effective change in loads on CPU 0 would be 5/56 (3/8 - 2/7) + * times the weight of the group. The effect on CPU 1 would be -4/56 (4/8 - + * 4/7) times the weight of the group.   */  static long effective_load(struct task_group *tg, int cpu, long wl, long wg)  {  	struct sched_entity *se = tg->se[cpu]; -	if (!tg->parent) +	if (!tg->parent)	/* the trivial, non-cgroup case */  		return wl;  	for_each_sched_entity(se) { -		long lw, w; +		long w, W;  		tg = se->my_q->tg; -		w = se->my_q->load.weight; -		/* use this cpu's instantaneous contribution */ -		lw = atomic_read(&tg->load_weight); -		lw -= se->my_q->load_contribution; -		lw += w + wg; +		/* +		 * W = @wg + \Sum rw_j +		 */ +		W = wg + calc_tg_weight(tg, se->my_q); -		wl += w; +		/* +		 * w = rw_i + @wl +		 */ +		w = se->my_q->load.weight + wl; -		if (lw > 0 && wl < lw) -			wl = (wl * tg->shares) / lw; +		/* +		 * wl = S * s'_i; see (2) +		 */ +		if (W > 0 && w < W) +			wl = (w * tg->shares) / W;  		else  			wl = tg->shares; -		/* zero point is MIN_SHARES */ +		/* +		 * Per the above, wl is the new se->load.weight value; since +		 * those are clipped to [MIN_SHARES, ...) do so now. See +		 * calc_cfs_shares(). +		 */  		if (wl < MIN_SHARES)  			wl = MIN_SHARES; + +		/* +		 * wl = dw_i = S * (s'_i - s_i); see (3) +		 */  		wl -= se->load.weight; + +		/* +		 * Recursively apply this logic to all parent groups to compute +		 * the final effective load change on the root group. Since +		 * only the @tg group gets extra weight, all parent groups can +		 * only redistribute existing shares. @wl is the shift in shares +		 * resulting from this level per the above. +		 */  		wg = 0;  	} @@ -2249,7 +2326,8 @@ static int select_idle_sibling(struct task_struct *p, int target)  	int cpu = smp_processor_id();  	int prev_cpu = task_cpu(p);  	struct sched_domain *sd; -	int i; +	struct sched_group *sg; +	int i, smt = 0;  	/*  	 * If the task is going to be woken-up on this cpu and if it is @@ -2269,25 +2347,38 @@ static int select_idle_sibling(struct task_struct *p, int target)  	 * Otherwise, iterate the domains and find an elegible idle cpu.  	 */  	rcu_read_lock(); +again:  	for_each_domain(target, sd) { -		if (!(sd->flags & SD_SHARE_PKG_RESOURCES)) -			break; +		if (!smt && (sd->flags & SD_SHARE_CPUPOWER)) +			continue; -		for_each_cpu_and(i, sched_domain_span(sd), tsk_cpus_allowed(p)) { -			if (idle_cpu(i)) { -				target = i; -				break; +		if (!(sd->flags & SD_SHARE_PKG_RESOURCES)) { +			if (!smt) { +				smt = 1; +				goto again;  			} +			break;  		} -		/* -		 * Lets stop looking for an idle sibling when we reached -		 * the domain that spans the current cpu and prev_cpu. -		 */ -		if (cpumask_test_cpu(cpu, sched_domain_span(sd)) && -		    cpumask_test_cpu(prev_cpu, sched_domain_span(sd))) -			break; +		sg = sd->groups; +		do { +			if (!cpumask_intersects(sched_group_cpus(sg), +						tsk_cpus_allowed(p))) +				goto next; + +			for_each_cpu(i, sched_group_cpus(sg)) { +				if (!idle_cpu(i)) +					goto next; +			} + +			target = cpumask_first_and(sched_group_cpus(sg), +					tsk_cpus_allowed(p)); +			goto done; +next: +			sg = sg->next; +		} while (sg != sd->groups);  	} +done:  	rcu_read_unlock();  	return target; @@ -3511,7 +3602,7 @@ static bool update_sd_pick_busiest(struct sched_domain *sd,  }  /** - * update_sd_lb_stats - Update sched_group's statistics for load balancing. + * update_sd_lb_stats - Update sched_domain's statistics for load balancing.   * @sd: sched_domain whose statistics are to be updated.   * @this_cpu: Cpu for which load balance is currently performed.   * @idle: Idle status of this_cpu diff --git a/kernel/sched_features.h b/kernel/sched_features.h index efa0a7b75dd..84802245abd 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -67,3 +67,4 @@ SCHED_FEAT(NONTASK_POWER, 1)  SCHED_FEAT(TTWU_QUEUE, 1)  SCHED_FEAT(FORCE_SD_OVERLAP, 0) +SCHED_FEAT(RT_RUNTIME_SHARE, 1) diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 056cbd2e2a2..583a1368afe 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -560,6 +560,9 @@ static int balance_runtime(struct rt_rq *rt_rq)  {  	int more = 0; +	if (!sched_feat(RT_RUNTIME_SHARE)) +		return more; +  	if (rt_rq->rt_time > rt_rq->rt_runtime) {  		raw_spin_unlock(&rt_rq->rt_runtime_lock);  		more = do_balance_runtime(rt_rq); diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 1ecd6ba36d6..c4eb71c8b2e 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -387,6 +387,7 @@ void clockevents_exchange_device(struct clock_event_device *old,  	 * released list and do a notify add later.  	 */  	if (old) { +		old->event_handler = clockevents_handle_noop;  		clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED);  		list_del(&old->list);  		list_add(&old->list, &clockevents_released); diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index cfc65e1eb9f..da2f760e780 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -548,7 +548,7 @@ static u64 clocksource_max_deferment(struct clocksource *cs)  	 * note a margin of 12.5% is used because this can be computed with  	 * a shift, versus say 10% which would require division.  	 */ -	return max_nsecs - (max_nsecs >> 5); +	return max_nsecs - (max_nsecs >> 3);  }  #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET @@ -669,7 +669,7 @@ void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq)  	 * ~ 0.06ppm granularity for NTP. We apply the same 12.5%  	 * margin as we do in clocksource_max_deferment()  	 */ -	sec = (cs->mask - (cs->mask >> 5)); +	sec = (cs->mask - (cs->mask >> 3));  	do_div(sec, freq);  	do_div(sec, scale);  	if (!sec) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index f954282d9a8..fd4a7b1625a 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -71,7 +71,7 @@ int tick_check_broadcast_device(struct clock_event_device *dev)  	     (dev->features & CLOCK_EVT_FEAT_C3STOP))  		return 0; -	clockevents_exchange_device(NULL, dev); +	clockevents_exchange_device(tick_broadcast_device.evtdev, dev);  	tick_broadcast_device.evtdev = dev;  	if (!cpumask_empty(tick_get_broadcast_mask()))  		tick_broadcast_start_periodic(dev); diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 900b409543d..b1e8943fed1 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -152,7 +152,6 @@ void clear_ftrace_function(void)  	ftrace_pid_function = ftrace_stub;  } -#undef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST  #ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST  /*   * For those archs that do not test ftrace_trace_stop in their @@ -1212,7 +1211,9 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,  	if (!src->count) {  		free_ftrace_hash_rcu(*dst);  		rcu_assign_pointer(*dst, EMPTY_HASH); -		return 0; +		/* still need to update the function records */ +		ret = 0; +		goto out;  	}  	/* diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 581876f9f38..c212a7f934e 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1078,7 +1078,6 @@ event_subsystem_dir(const char *name, struct dentry *d_events)  	/* First see if we did not already create this dir */  	list_for_each_entry(system, &event_subsystems, list) {  		if (strcmp(system->name, name) == 0) { -			__get_system(system);  			system->nr_events++;  			return system->entry;  		} diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 816d3d07497..95dc31efd6d 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -1649,7 +1649,9 @@ static int replace_system_preds(struct event_subsystem *system,  		 */  		err = replace_preds(call, NULL, ps, filter_string, true);  		if (err) -			goto fail; +			call->flags |= TRACE_EVENT_FL_NO_SET_FILTER; +		else +			call->flags &= ~TRACE_EVENT_FL_NO_SET_FILTER;  	}  	list_for_each_entry(call, &ftrace_events, list) { @@ -1658,6 +1660,9 @@ static int replace_system_preds(struct event_subsystem *system,  		if (strcmp(call->class->system, system->name) != 0)  			continue; +		if (call->flags & TRACE_EVENT_FL_NO_SET_FILTER) +			continue; +  		filter_item = kzalloc(sizeof(*filter_item), GFP_KERNEL);  		if (!filter_item)  			goto fail_mem; @@ -1686,7 +1691,7 @@ static int replace_system_preds(struct event_subsystem *system,  		 * replace the filter for the call.  		 */  		filter = call->filter; -		call->filter = filter_item->filter; +		rcu_assign_pointer(call->filter, filter_item->filter);  		filter_item->filter = filter;  		fail = false; @@ -1741,7 +1746,7 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)  		filter = call->filter;  		if (!filter)  			goto out_unlock; -		call->filter = NULL; +		RCU_INIT_POINTER(call->filter, NULL);  		/* Make sure the filter is not being used */  		synchronize_sched();  		__free_filter(filter); @@ -1782,7 +1787,7 @@ out:  	 * string  	 */  	tmp = call->filter; -	call->filter = filter; +	rcu_assign_pointer(call->filter, filter);  	if (tmp) {  		/* Make sure the call is done with the filter */  		synchronize_sched(); diff --git a/mm/slab.c b/mm/slab.c index 708efe88615..83311c9aaf9 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -595,6 +595,7 @@ static enum {  	PARTIAL_AC,  	PARTIAL_L3,  	EARLY, +	LATE,  	FULL  } g_cpucache_up; @@ -671,7 +672,7 @@ static void init_node_lock_keys(int q)  {  	struct cache_sizes *s = malloc_sizes; -	if (g_cpucache_up != FULL) +	if (g_cpucache_up < LATE)  		return;  	for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) { @@ -1666,6 +1667,8 @@ void __init kmem_cache_init_late(void)  {  	struct kmem_cache *cachep; +	g_cpucache_up = LATE; +  	/* Annotate slab for lockdep -- annotate the malloc caches */  	init_lock_keys(); diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 182236b2510..9b570a6a33c 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c @@ -26,10 +26,11 @@   * but then some measure against one socket starving all other sockets   * would be needed.   * - * It was 128 by default. Experiments with real servers show, that + * The minimum value of it is 128. Experiments with real servers show that   * it is absolutely not enough even at 100conn/sec. 256 cures most - * of problems. This value is adjusted to 128 for very small machines - * (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb). + * of problems. + * This value is adjusted to 128 for low memory machines, + * and it will increase in proportion to the memory of machine.   * Note : Dont forget somaxconn that may limit backlog too.   */  int sysctl_max_syn_backlog = 256; diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c index 025233de25f..925991ae6f5 100644 --- a/net/core/secure_seq.c +++ b/net/core/secure_seq.c @@ -19,6 +19,7 @@ static int __init net_secret_init(void)  }  late_initcall(net_secret_init); +#ifdef CONFIG_INET  static u32 seq_scale(u32 seq)  {  	/* @@ -33,6 +34,7 @@ static u32 seq_scale(u32 seq)  	 */  	return seq + (ktime_to_ns(ktime_get_real()) >> 6);  } +#endif  #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)  __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr, diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 90402a2a26a..f30112f7559 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -111,7 +111,7 @@  #include <net/secure_seq.h>  #define RT_FL_TOS(oldflp4) \ -    ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))) +	((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))  #define IP_MAX_MTU	0xFFF0 @@ -1304,7 +1304,7 @@ static void rt_del(unsigned hash, struct rtable *rt)  	spin_unlock_bh(rt_hash_lock_addr(hash));  } -static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) +static void check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)  {  	struct rtable *rt = (struct rtable *) dst;  	__be32 orig_gw = rt->rt_gateway; @@ -1315,21 +1315,19 @@ static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)  	rt->rt_gateway = peer->redirect_learned.a4;  	n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); -	if (IS_ERR(n)) -		return PTR_ERR(n); +	if (IS_ERR(n)) { +		rt->rt_gateway = orig_gw; +		return; +	}  	old_n = xchg(&rt->dst._neighbour, n);  	if (old_n)  		neigh_release(old_n); -	if (!n || !(n->nud_state & NUD_VALID)) { -		if (n) -			neigh_event_send(n, NULL); -		rt->rt_gateway = orig_gw; -		return -EAGAIN; +	if (!(n->nud_state & NUD_VALID)) { +		neigh_event_send(n, NULL);  	} else {  		rt->rt_flags |= RTCF_REDIRECTED;  		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);  	} -	return 0;  }  /* called in rcu_read_lock() section */ @@ -1687,7 +1685,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)  } -static struct rtable *ipv4_validate_peer(struct rtable *rt) +static void ipv4_validate_peer(struct rtable *rt)  {  	if (rt->rt_peer_genid != rt_peer_genid()) {  		struct inet_peer *peer; @@ -1702,15 +1700,12 @@ static struct rtable *ipv4_validate_peer(struct rtable *rt)  			if (peer->redirect_genid != redirect_genid)  				peer->redirect_learned.a4 = 0;  			if (peer->redirect_learned.a4 && -			    peer->redirect_learned.a4 != rt->rt_gateway) { -				if (check_peer_redir(&rt->dst, peer)) -					return NULL; -			} +			    peer->redirect_learned.a4 != rt->rt_gateway) +				check_peer_redir(&rt->dst, peer);  		}  		rt->rt_peer_genid = rt_peer_genid();  	} -	return rt;  }  static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) @@ -1719,7 +1714,7 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)  	if (rt_is_expired(rt))  		return NULL; -	dst = (struct dst_entry *) ipv4_validate_peer(rt); +	ipv4_validate_peer(rt);  	return dst;  } @@ -2374,9 +2369,7 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr,  		    rth->rt_mark == skb->mark &&  		    net_eq(dev_net(rth->dst.dev), net) &&  		    !rt_is_expired(rth)) { -			rth = ipv4_validate_peer(rth); -			if (!rth) -				continue; +			ipv4_validate_peer(rth);  			if (noref) {  				dst_use_noref(&rth->dst, jiffies);  				skb_dst_set_noref(skb, &rth->dst); @@ -2435,11 +2428,11 @@ EXPORT_SYMBOL(ip_route_input_common);  static struct rtable *__mkroute_output(const struct fib_result *res,  				       const struct flowi4 *fl4,  				       __be32 orig_daddr, __be32 orig_saddr, -				       int orig_oif, struct net_device *dev_out, +				       int orig_oif, __u8 orig_rtos, +				       struct net_device *dev_out,  				       unsigned int flags)  {  	struct fib_info *fi = res->fi; -	u32 tos = RT_FL_TOS(fl4);  	struct in_device *in_dev;  	u16 type = res->type;  	struct rtable *rth; @@ -2490,7 +2483,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,  	rth->rt_genid = rt_genid(dev_net(dev_out));  	rth->rt_flags	= flags;  	rth->rt_type	= type; -	rth->rt_key_tos	= tos; +	rth->rt_key_tos	= orig_rtos;  	rth->rt_dst	= fl4->daddr;  	rth->rt_src	= fl4->saddr;  	rth->rt_route_iif = 0; @@ -2540,7 +2533,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,  static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4)  {  	struct net_device *dev_out = NULL; -	u32 tos	= RT_FL_TOS(fl4); +	__u8 tos = RT_FL_TOS(fl4);  	unsigned int flags = 0;  	struct fib_result res;  	struct rtable *rth; @@ -2716,7 +2709,7 @@ static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4)  make_route:  	rth = __mkroute_output(&res, fl4, orig_daddr, orig_saddr, orig_oif, -			       dev_out, flags); +			       tos, dev_out, flags);  	if (!IS_ERR(rth)) {  		unsigned int hash; @@ -2752,9 +2745,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4)  			    (IPTOS_RT_MASK | RTO_ONLINK)) &&  		    net_eq(dev_net(rth->dst.dev), net) &&  		    !rt_is_expired(rth)) { -			rth = ipv4_validate_peer(rth); -			if (!rth) -				continue; +			ipv4_validate_peer(rth);  			dst_use(&rth->dst, jiffies);  			RT_CACHE_STAT_INC(out_hit);  			rcu_read_unlock_bh(); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 096507d2ca9..7d98240def0 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2508,7 +2508,6 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {  	SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), -	SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f3658658548..d8d2f9dccd9 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4441,7 +4441,9 @@ static int stac92xx_init(struct hda_codec *codec)  		int pinctl, def_conf;  		/* power on when no jack detection is available */ -		if (!spec->hp_detect) { +		/* or when the VREF is used for controlling LED */ +		if (!spec->hp_detect || +		    (spec->gpio_led > 8 && spec->gpio_led == nid)) {  			stac_toggle_power_map(codec, nid, 1);  			continue;  		} @@ -5055,20 +5057,6 @@ static int stac92xx_pre_resume(struct hda_codec *codec)  	return 0;  } -static int stac92xx_post_suspend(struct hda_codec *codec) -{ -	struct sigmatel_spec *spec = codec->spec; -	if (spec->gpio_led > 8) { -		/* with vref-out pin used for mute led control -		 * codec AFG is prevented from D3 state, but on -		 * system suspend it can (and should) be used -		 */ -		snd_hda_codec_read(codec, codec->afg, 0, -				AC_VERB_SET_POWER_STATE, AC_PWRST_D3); -	} -	return 0; -} -  static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,  				unsigned int power_state)  { @@ -5668,8 +5656,6 @@ again:  		} else {  			codec->patch_ops.set_power_state =  					stac92xx_set_power_state; -			codec->patch_ops.post_suspend = -					stac92xx_post_suspend;  		}  		codec->patch_ops.pre_resume = stac92xx_pre_resume;  		codec->patch_ops.check_power_status = @@ -5983,8 +5969,6 @@ again:  		} else {  			codec->patch_ops.set_power_state =  					stac92xx_set_power_state; -			codec->patch_ops.post_suspend = -					stac92xx_post_suspend;  		}  		codec->patch_ops.pre_resume = stac92xx_pre_resume;  		codec->patch_ops.check_power_status = diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index bee3c94f58b..d1fcc816ce9 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -1,6 +1,6 @@  config SND_ATMEL_SOC  	tristate "SoC Audio for the Atmel System-on-Chip" -	depends on ARCH_AT91 || AVR32 +	depends on ARCH_AT91  	help  	  Say Y or M if you want to add support for codecs attached to  	  the ATMEL SSC interface. You will also need @@ -24,25 +24,6 @@ config SND_AT91_SOC_SAM9G20_WM8731  	  Say Y if you want to add support for SoC audio on WM8731-based  	  AT91sam9g20 evaluation board. -config SND_AT32_SOC_PLAYPAQ -        tristate "SoC Audio support for PlayPaq with WM8510" -        depends on SND_ATMEL_SOC && BOARD_PLAYPAQ && AT91_PROGRAMMABLE_CLOCKS -        select SND_ATMEL_SOC_SSC -        select SND_SOC_WM8510 -        help -          Say Y or M here if you want to add support for SoC audio -          on the LRS PlayPaq. - -config SND_AT32_SOC_PLAYPAQ_SLAVE -        bool "Run CODEC on PlayPaq in slave mode" -        depends on SND_AT32_SOC_PLAYPAQ -        default n -        help -          Say Y if you want to run with the AT32 SSC generating the BCLK -          and FRAME signals on the PlayPaq.  Unless you want to play -          with the AT32 as the SSC master, you probably want to say N here, -          as this will give you better sound quality. -  config SND_AT91_SOC_AFEB9260  	tristate "SoC Audio support for AFEB9260 board"  	depends on ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile index e7ea56bd5f8..a5c0bf19da7 100644 --- a/sound/soc/atmel/Makefile +++ b/sound/soc/atmel/Makefile @@ -8,9 +8,5 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o  # AT91 Machine Support  snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o -# AT32 Machine Support -snd-soc-playpaq-objs := playpaq_wm8510.o -  obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o -obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o  obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c deleted file mode 100644 index 73ae99ad457..00000000000 --- a/sound/soc/atmel/playpaq_wm8510.c +++ /dev/null @@ -1,473 +0,0 @@ -/* sound/soc/at32/playpaq_wm8510.c - * ASoC machine driver for PlayPaq using WM8510 codec - * - * Copyright (C) 2008 Long Range Systems - *    Geoffrey Wossum <gwossum@acm.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This code is largely inspired by sound/soc/at91/eti_b1_wm8731.c - * - * NOTE: If you don't have the AT32 enhanced portmux configured (which - * isn't currently in the mainline or Atmel patched kernel), you will - * need to set the MCLK pin (PA30) to peripheral A in your board initialization - * code.  Something like: - *	at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); - * - */ - -/* #define DEBUG */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/clk.h> -#include <linux/timer.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> - -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/soc.h> - -#include <mach/at32ap700x.h> -#include <mach/portmux.h> - -#include "../codecs/wm8510.h" -#include "atmel-pcm.h" -#include "atmel_ssc_dai.h" - - -/*-------------------------------------------------------------------------*\ - * constants -\*-------------------------------------------------------------------------*/ -#define MCLK_PIN		GPIO_PIN_PA(30) -#define MCLK_PERIPH		GPIO_PERIPH_A - - -/*-------------------------------------------------------------------------*\ - * data types -\*-------------------------------------------------------------------------*/ -/* SSC clocking data */ -struct ssc_clock_data { -	/* CMR div */ -	unsigned int cmr_div; - -	/* Frame period (as needed by xCMR.PERIOD) */ -	unsigned int period; - -	/* The SSC clock rate these settings where calculated for */ -	unsigned long ssc_rate; -}; - - -/*-------------------------------------------------------------------------*\ - * module data -\*-------------------------------------------------------------------------*/ -static struct clk *_gclk0; -static struct clk *_pll0; - -#define CODEC_CLK (_gclk0) - - -/*-------------------------------------------------------------------------*\ - * Sound SOC operations -\*-------------------------------------------------------------------------*/ -#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE -static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock( -	struct snd_pcm_hw_params *params, -	struct snd_soc_dai *cpu_dai) -{ -	struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); -	struct ssc_device *ssc = ssc_p->ssc; -	struct ssc_clock_data cd; -	unsigned int rate, width_bits, channels; -	unsigned int bitrate, ssc_div; -	unsigned actual_rate; - - -	/* -	 * Figure out required bitrate -	 */ -	rate = params_rate(params); -	channels = params_channels(params); -	width_bits = snd_pcm_format_physical_width(params_format(params)); -	bitrate = rate * width_bits * channels; - - -	/* -	 * Figure out required SSC divider and period for required bitrate -	 */ -	cd.ssc_rate = clk_get_rate(ssc->clk); -	ssc_div = cd.ssc_rate / bitrate; -	cd.cmr_div = ssc_div / 2; -	if (ssc_div & 1) { -		/* round cmr_div up */ -		cd.cmr_div++; -	} -	cd.period = width_bits - 1; - - -	/* -	 * Find actual rate, compare to requested rate -	 */ -	actual_rate = (cd.ssc_rate / (cd.cmr_div * 2)) / (2 * (cd.period + 1)); -	pr_debug("playpaq_wm8510: Request rate = %u, actual rate = %u\n", -		 rate, actual_rate); - - -	return cd; -} -#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ - - - -static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream, -				    struct snd_pcm_hw_params *params) -{ -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_dai *codec_dai = rtd->codec_dai; -	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -	struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); -	struct ssc_device *ssc = ssc_p->ssc; -	unsigned int pll_out = 0, bclk = 0, mclk_div = 0; -	int ret; - - -	/* Due to difficulties with getting the correct clocks from the AT32's -	 * PLL0, we're going to let the CODEC be in charge of all the clocks -	 */ -#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE -	const unsigned int fmt = (SND_SOC_DAIFMT_I2S | -				  SND_SOC_DAIFMT_NB_NF | -				  SND_SOC_DAIFMT_CBM_CFM); -#else -	struct ssc_clock_data cd; -	const unsigned int fmt = (SND_SOC_DAIFMT_I2S | -				  SND_SOC_DAIFMT_NB_NF | -				  SND_SOC_DAIFMT_CBS_CFS); -#endif - -	if (ssc == NULL) { -		pr_warning("playpaq_wm8510_hw_params: ssc is NULL!\n"); -		return -EINVAL; -	} - - -	/* -	 * Figure out PLL and BCLK dividers for WM8510 -	 */ -	switch (params_rate(params)) { -	case 48000: -		pll_out = 24576000; -		mclk_div = WM8510_MCLKDIV_2; -		bclk = WM8510_BCLKDIV_8; -		break; - -	case 44100: -		pll_out = 22579200; -		mclk_div = WM8510_MCLKDIV_2; -		bclk = WM8510_BCLKDIV_8; -		break; - -	case 22050: -		pll_out = 22579200; -		mclk_div = WM8510_MCLKDIV_4; -		bclk = WM8510_BCLKDIV_8; -		break; - -	case 16000: -		pll_out = 24576000; -		mclk_div = WM8510_MCLKDIV_6; -		bclk = WM8510_BCLKDIV_8; -		break; - -	case 11025: -		pll_out = 22579200; -		mclk_div = WM8510_MCLKDIV_8; -		bclk = WM8510_BCLKDIV_8; -		break; - -	case 8000: -		pll_out = 24576000; -		mclk_div = WM8510_MCLKDIV_12; -		bclk = WM8510_BCLKDIV_8; -		break; - -	default: -		pr_warning("playpaq_wm8510: Unsupported sample rate %d\n", -			   params_rate(params)); -		return -EINVAL; -	} - - -	/* -	 * set CPU and CODEC DAI configuration -	 */ -	ret = snd_soc_dai_set_fmt(codec_dai, fmt); -	if (ret < 0) { -		pr_warning("playpaq_wm8510: " -			   "Failed to set CODEC DAI format (%d)\n", -			   ret); -		return ret; -	} -	ret = snd_soc_dai_set_fmt(cpu_dai, fmt); -	if (ret < 0) { -		pr_warning("playpaq_wm8510: " -			   "Failed to set CPU DAI format (%d)\n", -			   ret); -		return ret; -	} - - -	/* -	 * Set CPU clock configuration -	 */ -#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE -	cd = playpaq_wm8510_calc_ssc_clock(params, cpu_dai); -	pr_debug("playpaq_wm8510: cmr_div = %d, period = %d\n", -		 cd.cmr_div, cd.period); -	ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_CMR_DIV, cd.cmr_div); -	if (ret < 0) { -		pr_warning("playpaq_wm8510: Failed to set CPU CMR_DIV (%d)\n", -			   ret); -		return ret; -	} -	ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_TCMR_PERIOD, -					  cd.period); -	if (ret < 0) { -		pr_warning("playpaq_wm8510: " -			   "Failed to set CPU transmit period (%d)\n", -			   ret); -		return ret; -	} -#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ - - -	/* -	 * Set CODEC clock configuration -	 */ -	pr_debug("playpaq_wm8510: " -		 "pll_in = %ld, pll_out = %u, bclk = %x, mclk = %x\n", -		 clk_get_rate(CODEC_CLK), pll_out, bclk, mclk_div); - - -#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE -	ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_BCLKDIV, bclk); -	if (ret < 0) { -		pr_warning -		    ("playpaq_wm8510: Failed to set CODEC DAI BCLKDIV (%d)\n", -		     ret); -		return ret; -	} -#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ - - -	ret = snd_soc_dai_set_pll(codec_dai, 0, 0, -					 clk_get_rate(CODEC_CLK), pll_out); -	if (ret < 0) { -		pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n", -			   ret); -		return ret; -	} - - -	ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_MCLKDIV, mclk_div); -	if (ret < 0) { -		pr_warning("playpaq_wm8510: Failed to set CODEC MCLKDIV (%d)\n", -			   ret); -		return ret; -	} - - -	return 0; -} - - - -static struct snd_soc_ops playpaq_wm8510_ops = { -	.hw_params = playpaq_wm8510_hw_params, -}; - - - -static const struct snd_soc_dapm_widget playpaq_dapm_widgets[] = { -	SND_SOC_DAPM_MIC("Int Mic", NULL), -	SND_SOC_DAPM_SPK("Ext Spk", NULL), -}; - - - -static const struct snd_soc_dapm_route intercon[] = { -	/* speaker connected to SPKOUT */ -	{"Ext Spk", NULL, "SPKOUTP"}, -	{"Ext Spk", NULL, "SPKOUTN"}, - -	{"Mic Bias", NULL, "Int Mic"}, -	{"MICN", NULL, "Mic Bias"}, -	{"MICP", NULL, "Mic Bias"}, -}; - - - -static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd) -{ -	struct snd_soc_codec *codec = rtd->codec; -	struct snd_soc_dapm_context *dapm = &codec->dapm; -	int i; - -	/* -	 * Add DAPM widgets -	 */ -	for (i = 0; i < ARRAY_SIZE(playpaq_dapm_widgets); i++) -		snd_soc_dapm_new_control(dapm, &playpaq_dapm_widgets[i]); - - - -	/* -	 * Setup audio path interconnects -	 */ -	snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - - - -	/* always connected pins */ -	snd_soc_dapm_enable_pin(dapm, "Int Mic"); -	snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - - - -	/* Make CSB show PLL rate */ -	snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV, -				       WM8510_OPCLKDIV_1 | 4); - -	return 0; -} - - - -static struct snd_soc_dai_link playpaq_wm8510_dai = { -	.name = "WM8510", -	.stream_name = "WM8510 PCM", -	.cpu_dai_name= "atmel-ssc-dai.0", -	.platform_name = "atmel-pcm-audio", -	.codec_name = "wm8510-codec.0-0x1a", -	.codec_dai_name = "wm8510-hifi", -	.init = playpaq_wm8510_init, -	.ops = &playpaq_wm8510_ops, -}; - - - -static struct snd_soc_card snd_soc_playpaq = { -	.name = "LRS_PlayPaq_WM8510", -	.dai_link = &playpaq_wm8510_dai, -	.num_links = 1, -}; - -static struct platform_device *playpaq_snd_device; - - -static int __init playpaq_asoc_init(void) -{ -	int ret = 0; - -	/* -	 * Configure MCLK for WM8510 -	 */ -	_gclk0 = clk_get(NULL, "gclk0"); -	if (IS_ERR(_gclk0)) { -		_gclk0 = NULL; -		ret = PTR_ERR(_gclk0); -		goto err_gclk0; -	} -	_pll0 = clk_get(NULL, "pll0"); -	if (IS_ERR(_pll0)) { -		_pll0 = NULL; -		ret = PTR_ERR(_pll0); -		goto err_pll0; -	} -	ret = clk_set_parent(_gclk0, _pll0); -	if (ret) { -		pr_warning("snd-soc-playpaq: " -			   "Failed to set PLL0 as parent for DAC clock\n"); -		goto err_set_clk; -	} -	clk_set_rate(CODEC_CLK, 12000000); -	clk_enable(CODEC_CLK); - -#if defined CONFIG_AT32_ENHANCED_PORTMUX -	at32_select_periph(MCLK_PIN, MCLK_PERIPH, 0); -#endif - - -	/* -	 * Create and register platform device -	 */ -	playpaq_snd_device = platform_device_alloc("soc-audio", 0); -	if (playpaq_snd_device == NULL) { -		ret = -ENOMEM; -		goto err_device_alloc; -	} - -	platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq); - -	ret = platform_device_add(playpaq_snd_device); -	if (ret) { -		pr_warning("playpaq_wm8510: platform_device_add failed (%d)\n", -			   ret); -		goto err_device_add; -	} - -	return 0; - - -err_device_add: -	if (playpaq_snd_device != NULL) { -		platform_device_put(playpaq_snd_device); -		playpaq_snd_device = NULL; -	} -err_device_alloc: -err_set_clk: -	if (_pll0 != NULL) { -		clk_put(_pll0); -		_pll0 = NULL; -	} -err_pll0: -	if (_gclk0 != NULL) { -		clk_put(_gclk0); -		_gclk0 = NULL; -	} -	return ret; -} - - -static void __exit playpaq_asoc_exit(void) -{ -	if (_gclk0 != NULL) { -		clk_put(_gclk0); -		_gclk0 = NULL; -	} -	if (_pll0 != NULL) { -		clk_put(_pll0); -		_pll0 = NULL; -	} - -#if defined CONFIG_AT32_ENHANCED_PORTMUX -	at32_free_pin(MCLK_PIN); -#endif - -	platform_device_unregister(playpaq_snd_device); -	playpaq_snd_device = NULL; -} - -module_init(playpaq_asoc_init); -module_exit(playpaq_asoc_exit); - -MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>"); -MODULE_DESCRIPTION("ASoC machine driver for LRS PlayPaq"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index 444747f0db2..dd7be0dbbc5 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h @@ -34,7 +34,7 @@  #define AD1836_ADC_CTRL2               13  #define AD1836_ADC_WORD_LEN_MASK       0x30 -#define AD1836_ADC_WORD_OFFSET         5 +#define AD1836_ADC_WORD_OFFSET         4  #define AD1836_ADC_SERFMT_MASK         (7 << 6)  #define AD1836_ADC_SERFMT_PCK256       (0x4 << 6)  #define AD1836_ADC_SERFMT_PCK128       (0x5 << 6) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index f1f237ecec2..73f46eb459f 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -601,7 +601,6 @@ static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)  static int cs4270_soc_resume(struct snd_soc_codec *codec)  {  	struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); -	struct i2c_client *i2c_client = to_i2c_client(codec->dev);  	int reg;  	regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), @@ -612,14 +611,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec)  	ndelay(500);  	/* first restore the entire register cache ... */ -	for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) { -		u8 val = snd_soc_read(codec, reg); - -		if (i2c_smbus_write_byte_data(i2c_client, reg, val)) { -			dev_err(codec->dev, "i2c write failed\n"); -			return -EIO; -		} -	} +	snd_soc_cache_sync(codec);  	/* ... then disable the power-down bits */  	reg = snd_soc_read(codec, CS4270_PWRCTL); diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 8c3c8205d19..1ee66361f61 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -555,7 +555,7 @@ static int cs42l51_probe(struct snd_soc_codec *codec)  static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {  	.probe =	cs42l51_probe, -	.reg_cache_size = CS42L51_NUMREGS, +	.reg_cache_size = CS42L51_NUMREGS + 1,  	.reg_word_size = sizeof(u8),  }; diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c index 9e7e964a5fa..dcf6f2a1600 100644 --- a/sound/soc/codecs/max9877.c +++ b/sound/soc/codecs/max9877.c @@ -106,13 +106,13 @@ static int max9877_set_2reg(struct snd_kcontrol *kcontrol,  	unsigned int mask = mc->max;  	unsigned int val = (ucontrol->value.integer.value[0] & mask);  	unsigned int val2 = (ucontrol->value.integer.value[1] & mask); -	unsigned int change = 1; +	unsigned int change = 0; -	if (((max9877_regs[reg] >> shift) & mask) == val) -		change = 0; +	if (((max9877_regs[reg] >> shift) & mask) != val) +		change = 1; -	if (((max9877_regs[reg2] >> shift) & mask) == val2) -		change = 0; +	if (((max9877_regs[reg2] >> shift) & mask) != val2) +		change = 1;  	if (change) {  		max9877_regs[reg] &= ~(mask << shift); diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 9c982e47eb9..6c298854900 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2357,6 +2357,11 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,  	bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT;  	lrclk = bclk_rate / params_rate(params); +	if (!lrclk) { +		dev_err(dai->dev, "Unable to generate LRCLK from %dHz BCLK\n", +			bclk_rate); +		return -EINVAL; +	}  	dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n",  		lrclk, bclk_rate / lrclk); @@ -3178,6 +3183,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)  		switch (wm8994->revision) {  		case 0:  		case 1: +		case 2: +		case 3:  			wm8994->hubs.dcs_codes_l = -9;  			wm8994->hubs.dcs_codes_r = -5;  			break; diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 31af405bda8..ae49f1c78c6 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -392,7 +392,8 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)  	}  	if (strcasecmp(sprop, "i2s-slave") == 0) { -		machine_data->dai_format = SND_SOC_DAIFMT_I2S; +		machine_data->dai_format = +			SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;  		machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;  		machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; @@ -409,31 +410,38 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)  		}  		machine_data->clk_frequency = be32_to_cpup(iprop);  	} else if (strcasecmp(sprop, "i2s-master") == 0) { -		machine_data->dai_format = SND_SOC_DAIFMT_I2S; +		machine_data->dai_format = +			SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;  		machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;  		machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;  	} else if (strcasecmp(sprop, "lj-slave") == 0) { -		machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J; +		machine_data->dai_format = +			SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM;  		machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;  		machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;  	} else if (strcasecmp(sprop, "lj-master") == 0) { -		machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J; +		machine_data->dai_format = +			SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS;  		machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;  		machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;  	} else if (strcasecmp(sprop, "rj-slave") == 0) { -		machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J; +		machine_data->dai_format = +			SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM;  		machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;  		machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;  	} else if (strcasecmp(sprop, "rj-master") == 0) { -		machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J; +		machine_data->dai_format = +			SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS;  		machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;  		machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;  	} else if (strcasecmp(sprop, "ac97-slave") == 0) { -		machine_data->dai_format = SND_SOC_DAIFMT_AC97; +		machine_data->dai_format = +			SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM;  		machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;  		machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;  	} else if (strcasecmp(sprop, "ac97-master") == 0) { -		machine_data->dai_format = SND_SOC_DAIFMT_AC97; +		machine_data->dai_format = +			SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS;  		machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;  		machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;  	} else { diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index f75e43997d5..ad9ac42522e 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -9,6 +9,7 @@  #include "../codecs/wm8994.h"  #include <sound/pcm_params.h> +#include <linux/module.h>   /*    * Default CFG switch settings to use this driver: diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 85bf541a771..4b8e35410eb 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -191,7 +191,7 @@ static int speyside_late_probe(struct snd_soc_card *card)  	snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic");  	snd_soc_dapm_ignore_suspend(&card->dapm, "Main AMIC");  	snd_soc_dapm_ignore_suspend(&card->dapm, "Main DMIC"); -	snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); +	snd_soc_dapm_ignore_suspend(&card->dapm, "Main Speaker");  	snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Output");  	snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Input"); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a5d3685a5d3..a25fa63ce9a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -709,6 +709,12 @@ int snd_soc_resume(struct device *dev)  	struct snd_soc_card *card = dev_get_drvdata(dev);  	int i, ac97_control = 0; +	/* If the initialization of this soc device failed, there is no codec +	 * associated with it. Just bail out in this case. +	 */ +	if (list_empty(&card->codec_dev_list)) +		return 0; +  	/* AC97 devices might have other drivers hanging off them so  	 * need to resume immediately.  Other drivers don't have that  	 * problem and may take a substantial amount of time to resume diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index b61945f3af9..32d2a21f2e3 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -1633,6 +1633,37 @@ YAMAHA_DEVICE(0x7010, "UB99"),  	}  },  { +	/* Roland GAIA SH-01 */ +	USB_DEVICE(0x0582, 0x0111), +	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +		.vendor_name = "Roland", +		.product_name = "GAIA", +		.ifnum = QUIRK_ANY_INTERFACE, +		.type = QUIRK_COMPOSITE, +		.data = (const struct snd_usb_audio_quirk[]) { +			{ +				.ifnum = 0, +				.type = QUIRK_AUDIO_STANDARD_INTERFACE +			}, +			{ +				.ifnum = 1, +				.type = QUIRK_AUDIO_STANDARD_INTERFACE +			}, +			{ +				.ifnum = 2, +				.type = QUIRK_MIDI_FIXED_ENDPOINT, +				.data = &(const struct snd_usb_midi_endpoint_info) { +				.out_cables = 0x0003, +				.in_cables  = 0x0003 +				} +			}, +			{ +				.ifnum = -1 +			} +		} +	} +}, +{  	USB_DEVICE(0x0582, 0x0113),  	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {  		/* .vendor_name = "BOSS", */ diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index e4262642258..d7915d4e77c 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -34,6 +34,16 @@ int __perf_evsel__sample_size(u64 sample_type)  	return size;  } +static void hists__init(struct hists *hists) +{ +	memset(hists, 0, sizeof(*hists)); +	hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; +	hists->entries_in = &hists->entries_in_array[0]; +	hists->entries_collapsed = RB_ROOT; +	hists->entries = RB_ROOT; +	pthread_mutex_init(&hists->lock, NULL); +} +  void perf_evsel__init(struct perf_evsel *evsel,  		      struct perf_event_attr *attr, int idx)  { diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index a36a3fa81ff..abef2703cd2 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1211,13 +1211,3 @@ size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp)  	return ret;  } - -void hists__init(struct hists *hists) -{ -	memset(hists, 0, sizeof(*hists)); -	hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; -	hists->entries_in = &hists->entries_in_array[0]; -	hists->entries_collapsed = RB_ROOT; -	hists->entries = RB_ROOT; -	pthread_mutex_init(&hists->lock, NULL); -} diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index c86c1d27bd1..89289c8e935 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -63,8 +63,6 @@ struct hists {  	struct callchain_cursor	callchain_cursor;  }; -void hists__init(struct hists *hists); -  struct hist_entry *__hists__add_entry(struct hists *self,  				      struct addr_location *al,  				      struct symbol *parent, u64 period); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 85c1e6b76f0..0f4555ce906 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1333,6 +1333,10 @@ int perf_session__cpu_bitmap(struct perf_session *session,  	}  	map = cpu_map__new(cpu_list); +	if (map == NULL) { +		pr_err("Invalid cpu_list\n"); +		return -1; +	}  	for (i = 0; i < map->nr; i++) {  		int cpu = map->map[i]; diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 0a7ed5b5e28..6c164dc9ee9 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -1537,6 +1537,8 @@ process_flags(struct event *event, struct print_arg *arg, char **tok)  	field = malloc_or_die(sizeof(*field));  	type = process_arg(event, field, &token); +	while (type == EVENT_OP) +		type = process_op(event, field, &token);  	if (test_type_token(type, token, EVENT_DELIM, ","))  		goto out_free;  |