diff options
148 files changed, 1831 insertions, 1085 deletions
diff --git a/Documentation/HOWTO b/Documentation/HOWTO index c2371c5a98f9..48a3955f05fc 100644 --- a/Documentation/HOWTO +++ b/Documentation/HOWTO @@ -77,7 +77,8 @@ documentation files are also added which explain how to use the feature.  When a kernel change causes the interface that the kernel exposes to  userspace to change, it is recommended that you send the information or  a patch to the manual pages explaining the change to the manual pages -maintainer at mtk.manpages@gmail.com. +maintainer at mtk.manpages@gmail.com, and CC the list +linux-api@vger.kernel.org.  Here is a list of files that are in the kernel source tree that are  required reading: diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist index da10e0714241..21f0795af20f 100644 --- a/Documentation/SubmitChecklist +++ b/Documentation/SubmitChecklist @@ -67,6 +67,8 @@ kernel patches.  19: All new userspace interfaces are documented in Documentation/ABI/.      See Documentation/ABI/README for more information. +    Patches that change userspace interfaces should be CCed to +    linux-api@vger.kernel.org.  20: Check that it all passes `make headers_check'. diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 89c7f32abf9f..53449cb99b17 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -46,7 +46,7 @@   45 -> Pinnacle PCTV DVB-T                      (em2870)   46 -> Compro, VideoMate U3                     (em2870)        [185b:2870]   47 -> KWorld DVB-T 305U                        (em2880)        [eb1a:e305] - 48 -> KWorld DVB-T 310U                        (em2880) + 48 -> KWorld DVB-T 310U                        (em2880)        [eb1a:e310]   49 -> MSI DigiVox A/D                          (em2880)        [eb1a:e310]   50 -> MSI DigiVox A/D II                       (em2880)        [eb1a:e320]   51 -> Terratec Hybrid XS Secam                 (em2880)        [0ccd:004c] diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 0f03900c48fb..9a3e4d797fa8 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -190,6 +190,7 @@ pac7311		093a:260f	SnakeCam  pac7311		093a:2621	PAC731x  pac7311		093a:2624	PAC7302  pac7311		093a:2626	Labtec 2200 +pac7311		093a:262a	Webcam 300k  zc3xx		0ac8:0302	Z-star Vimicro zc0302  vc032x		0ac8:0321	Vimicro generic vc0321  vc032x		0ac8:0323	Vimicro Vc0323 diff --git a/MAINTAINERS b/MAINTAINERS index 3596d1782264..8dae4555f10e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1198,9 +1198,7 @@ M:	hpa@zytor.com  S:	Maintained  CPUSETS -P:	Paul Jackson  P:	Paul Menage -M:	pj@sgi.com  M:	menage@google.com  L:	linux-kernel@vger.kernel.org  W:	http://www.bullopensource.org/cpuset/ @@ -2706,6 +2704,7 @@ MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7  P:	Michael Kerrisk  M:	mtk.manpages@gmail.com  W:	http://www.kernel.org/doc/man-pages +L:	linux-man@vger.kernel.org  S:	Supported  MARVELL LIBERTAS WIRELESS DRIVER @@ -1,7 +1,7 @@  VERSION = 2  PATCHLEVEL = 6  SUBLEVEL = 27 -EXTRAVERSION = -rc8 +EXTRAVERSION = -rc9  NAME = Rotary Wombat  # *DOCUMENTATION* diff --git a/arch/ia64/include/asm/sections.h b/arch/ia64/include/asm/sections.h index f66799891036..1a873b36a4a1 100644 --- a/arch/ia64/include/asm/sections.h +++ b/arch/ia64/include/asm/sections.h @@ -11,6 +11,9 @@  #include <asm-generic/sections.h>  extern char __per_cpu_start[], __per_cpu_end[], __phys_per_cpu_start[]; +#ifdef	CONFIG_SMP +extern char __cpu0_per_cpu[]; +#endif  extern char __start___vtop_patchlist[], __end___vtop_patchlist[];  extern char __start___rse_patchlist[], __end___rse_patchlist[];  extern char __start___mckinley_e9_bundles[], __end___mckinley_e9_bundles[]; diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index 8bdea8eb62e3..66e491d8baac 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -367,16 +367,17 @@ start_ap:  	;;  #else  (isAP)	br.few 2f -	mov r20=r19 -	sub r19=r19,r18 +	movl r20=__cpu0_per_cpu  	;;  	shr.u r18=r18,3  1: -	ld8 r21=[r20],8;; -	st8[r19]=r21,8 +	ld8 r21=[r19],8;; +	st8[r20]=r21,8  	adds r18=-1,r18;;  	cmp4.lt p7,p6=0,r18  (p7)	br.cond.dptk.few 1b +	mov r19=r20 +	;;  2:  #endif  	tpa r19=r19 diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index de71da811cd6..10a7d47e8510 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -215,9 +215,6 @@ SECTIONS    /* Per-cpu data: */    percpu : { } :percpu    . = ALIGN(PERCPU_PAGE_SIZE); -#ifdef	CONFIG_SMP -  . = . + PERCPU_PAGE_SIZE;	/* cpu0 per-cpu space */ -#endif    __phys_per_cpu_start = .;    .data.percpu PERCPU_ADDR : AT(__phys_per_cpu_start - LOAD_OFFSET)  	{ @@ -233,6 +230,11 @@ SECTIONS    data : { } :data    .data : AT(ADDR(.data) - LOAD_OFFSET)  	{ +#ifdef	CONFIG_SMP +  . = ALIGN(PERCPU_PAGE_SIZE); +		__cpu0_per_cpu = .; +  . = . + PERCPU_PAGE_SIZE;	/* cpu0 per-cpu space */ +#endif  		DATA_DATA  		*(.data1)  		*(.gnu.linkonce.d*) diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index e566ff43884a..0ee085efbe29 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -163,7 +163,7 @@ per_cpu_init (void)  	 * get_zeroed_page().  	 */  	if (first_time) { -		void *cpu0_data = __phys_per_cpu_start - PERCPU_PAGE_SIZE; +		void *cpu0_data = __cpu0_per_cpu;  		first_time=0; diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 78026aabaa7f..d8c5fcd89e5b 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -144,7 +144,7 @@ static void *per_cpu_node_setup(void *cpu_data, int node)  	for_each_possible_early_cpu(cpu) {  		if (cpu == 0) { -			void *cpu0_data = __phys_per_cpu_start - PERCPU_PAGE_SIZE; +			void *cpu0_data = __cpu0_per_cpu;  			__per_cpu_offset[cpu] = (char*)cpu0_data -  				__per_cpu_start;  		} else if (node == node_cpuid[cpu].nid) { diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 49896a2a1d72..1e06d233fa83 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -211,6 +211,7 @@ config MIPS_MALTA  	select SYS_SUPPORTS_64BIT_KERNEL  	select SYS_SUPPORTS_BIG_ENDIAN  	select SYS_SUPPORTS_LITTLE_ENDIAN +	select SYS_SUPPORTS_MIPS_CMP if BROKEN	# because SYNC_R4K is broken  	select SYS_SUPPORTS_MULTITHREADING  	select SYS_SUPPORTS_SMARTMIPS  	help @@ -1403,7 +1404,6 @@ config MIPS_MT_SMTC  	depends on CPU_MIPS32_R2  	#depends on CPU_MIPS64_R2		# once there is hardware ...  	depends on SYS_SUPPORTS_MULTITHREADING -	select GENERIC_CLOCKEVENTS_BROADCAST  	select CPU_MIPSR2_IRQ_VI  	select CPU_MIPSR2_IRQ_EI  	select MIPS_MT @@ -1451,32 +1451,17 @@ config MIPS_VPE_LOADER  	  Includes a loader for loading an elf relocatable object  	  onto another VPE and running it. -config MIPS_MT_SMTC_INSTANT_REPLAY -	bool "Low-latency Dispatch of Deferred SMTC IPIs" -	depends on MIPS_MT_SMTC && !PREEMPT -	default y -	help -	  SMTC pseudo-interrupts between TCs are deferred and queued -	  if the target TC is interrupt-inhibited (IXMT). In the first -	  SMTC prototypes, these queued IPIs were serviced on return -	  to user mode, or on entry into the kernel idle loop. The -	  INSTANT_REPLAY option dispatches them as part of local_irq_restore() -	  processing, which adds runtime overhead (hence the option to turn -	  it off), but ensures that IPIs are handled promptly even under -	  heavy I/O interrupt load. -  config MIPS_MT_SMTC_IM_BACKSTOP  	bool "Use per-TC register bits as backstop for inhibited IM bits"  	depends on MIPS_MT_SMTC -	default y +	default n  	help  	  To support multiple TC microthreads acting as "CPUs" within  	  a VPE, VPE-wide interrupt mask bits must be specially manipulated  	  during interrupt handling. To support legacy drivers and interrupt  	  controller management code, SMTC has a "backstop" to track and  	  if necessary restore the interrupt mask. This has some performance -	  impact on interrupt service overhead. Disable it only if you know -	  what you are doing. +	  impact on interrupt service overhead.  config MIPS_MT_SMTC_IRQAFF  	bool "Support IRQ affinity API" @@ -1486,10 +1471,8 @@ config MIPS_MT_SMTC_IRQAFF  	  Enables SMP IRQ affinity API (/proc/irq/*/smp_affinity, etc.)  	  for SMTC Linux kernel. Requires platform support, of which  	  an example can be found in the MIPS kernel i8259 and Malta -	  platform code.  It is recommended that MIPS_MT_SMTC_INSTANT_REPLAY -	  be enabled if MIPS_MT_SMTC_IRQAFF is used. Adds overhead to -	  interrupt dispatch, and should be used only if you know what -	  you are doing. +	  platform code.  Adds some overhead to interrupt dispatch, and +	  should be used only if you know what you are doing.  config MIPS_VPE_LOADER_TOM  	bool "Load VPE program into memory hidden from linux" @@ -1517,6 +1500,18 @@ config MIPS_APSP_KSPD  	  "exit" syscall notifying other kernel modules the SP program is  	  exiting.  You probably want to say yes here. +config MIPS_CMP +	bool "MIPS CMP framework support" +	depends on SYS_SUPPORTS_MIPS_CMP +	select SYNC_R4K if BROKEN +	select SYS_SUPPORTS_SMP +	select SYS_SUPPORTS_SCHED_SMT if SMP +	select WEAK_ORDERING +	default n +	help +	  This is a placeholder option for the GCMP work. It will need to +	  be handled differently... +  config SB1_PASS_1_WORKAROUNDS  	bool  	depends on CPU_SB1_PASS_1 @@ -1693,6 +1688,9 @@ config SMP  config SMP_UP  	bool +config SYS_SUPPORTS_MIPS_CMP +	bool +  config SYS_SUPPORTS_SMP  	bool @@ -1740,17 +1738,6 @@ config NR_CPUS  	  performance should round up your number of processors to the next  	  power of two. -config MIPS_CMP -	bool "MIPS CMP framework support" -	depends on SMP -	select SYNC_R4K -	select SYS_SUPPORTS_SCHED_SMT -	select WEAK_ORDERING -	default n -	help -	  This is a placeholder option for the GCMP work. It will need to -	  be handled differently... -  source "kernel/time/Kconfig"  # diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 706f93974797..25775cb54000 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -10,6 +10,7 @@ obj-y		+= cpu-probe.o branch.o entry.o genex.o irq.o process.o \  obj-$(CONFIG_CEVT_BCM1480)	+= cevt-bcm1480.o  obj-$(CONFIG_CEVT_R4K)		+= cevt-r4k.o +obj-$(CONFIG_MIPS_MT_SMTC)	+= cevt-smtc.o  obj-$(CONFIG_CEVT_DS1287)	+= cevt-ds1287.o  obj-$(CONFIG_CEVT_GT641XX)	+= cevt-gt641xx.o  obj-$(CONFIG_CEVT_SB1250)	+= cevt-sb1250.o diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 24a2d907aa0d..4a4c59f2737a 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -12,6 +12,14 @@  #include <asm/smtc_ipi.h>  #include <asm/time.h> +#include <asm/cevt-r4k.h> + +/* + * The SMTC Kernel for the 34K, 1004K, et. al. replaces several + * of these routines with SMTC-specific variants. + */ + +#ifndef CONFIG_MIPS_MT_SMTC  static int mips_next_event(unsigned long delta,                             struct clock_event_device *evt) @@ -19,60 +27,27 @@ static int mips_next_event(unsigned long delta,  	unsigned int cnt;  	int res; -#ifdef CONFIG_MIPS_MT_SMTC -	{ -	unsigned long flags, vpflags; -	local_irq_save(flags); -	vpflags = dvpe(); -#endif  	cnt = read_c0_count();  	cnt += delta;  	write_c0_compare(cnt);  	res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0; -#ifdef CONFIG_MIPS_MT_SMTC -	evpe(vpflags); -	local_irq_restore(flags); -	} -#endif  	return res;  } -static void mips_set_mode(enum clock_event_mode mode, -                          struct clock_event_device *evt) +#endif /* CONFIG_MIPS_MT_SMTC */ + +void mips_set_clock_mode(enum clock_event_mode mode, +				struct clock_event_device *evt)  {  	/* Nothing to do ...  */  } -static DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device); -static int cp0_timer_irq_installed; +DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device); +int cp0_timer_irq_installed; -/* - * Timer ack for an R4k-compatible timer of a known frequency. - */ -static void c0_timer_ack(void) -{ -	write_c0_compare(read_c0_compare()); -} +#ifndef CONFIG_MIPS_MT_SMTC -/* - * Possibly handle a performance counter interrupt. - * Return true if the timer interrupt should not be checked - */ -static inline int handle_perf_irq(int r2) -{ -	/* -	 * The performance counter overflow interrupt may be shared with the -	 * timer interrupt (cp0_perfcount_irq < 0). If it is and a -	 * performance counter has overflowed (perf_irq() == IRQ_HANDLED) -	 * and we can't reliably determine if a counter interrupt has also -	 * happened (!r2) then don't check for a timer interrupt. -	 */ -	return (cp0_perfcount_irq < 0) && -		perf_irq() == IRQ_HANDLED && -		!r2; -} - -static irqreturn_t c0_compare_interrupt(int irq, void *dev_id) +irqreturn_t c0_compare_interrupt(int irq, void *dev_id)  {  	const int r2 = cpu_has_mips_r2;  	struct clock_event_device *cd; @@ -93,12 +68,8 @@ static irqreturn_t c0_compare_interrupt(int irq, void *dev_id)  	 * interrupt.  Being the paranoiacs we are we check anyway.  	 */  	if (!r2 || (read_c0_cause() & (1 << 30))) { -		c0_timer_ack(); -#ifdef CONFIG_MIPS_MT_SMTC -		if (cpu_data[cpu].vpe_id) -			goto out; -		cpu = 0; -#endif +		/* Clear Count/Compare Interrupt */ +		write_c0_compare(read_c0_compare());  		cd = &per_cpu(mips_clockevent_device, cpu);  		cd->event_handler(cd);  	} @@ -107,65 +78,16 @@ out:  	return IRQ_HANDLED;  } -static struct irqaction c0_compare_irqaction = { +#endif /* Not CONFIG_MIPS_MT_SMTC */ + +struct irqaction c0_compare_irqaction = {  	.handler = c0_compare_interrupt, -#ifdef CONFIG_MIPS_MT_SMTC -	.flags = IRQF_DISABLED, -#else  	.flags = IRQF_DISABLED | IRQF_PERCPU, -#endif  	.name = "timer",  }; -#ifdef CONFIG_MIPS_MT_SMTC -DEFINE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device); - -static void smtc_set_mode(enum clock_event_mode mode, -                          struct clock_event_device *evt) -{ -} - -static void mips_broadcast(cpumask_t mask) -{ -	unsigned int cpu; - -	for_each_cpu_mask(cpu, mask) -		smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0); -} - -static void setup_smtc_dummy_clockevent_device(void) -{ -	//uint64_t mips_freq = mips_hpt_^frequency; -	unsigned int cpu = smp_processor_id(); -	struct clock_event_device *cd; -	cd = &per_cpu(smtc_dummy_clockevent_device, cpu); - -	cd->name		= "SMTC"; -	cd->features		= CLOCK_EVT_FEAT_DUMMY; - -	/* Calculate the min / max delta */ -	cd->mult	= 0; //div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32); -	cd->shift		= 0; //32; -	cd->max_delta_ns	= 0; //clockevent_delta2ns(0x7fffffff, cd); -	cd->min_delta_ns	= 0; //clockevent_delta2ns(0x30, cd); - -	cd->rating		= 200; -	cd->irq			= 17; //-1; -//	if (cpu) -//		cd->cpumask	= CPU_MASK_ALL; // cpumask_of_cpu(cpu); -//	else -		cd->cpumask	= cpumask_of_cpu(cpu); - -	cd->set_mode		= smtc_set_mode; - -	cd->broadcast		= mips_broadcast; - -	clockevents_register_device(cd); -} -#endif - -static void mips_event_handler(struct clock_event_device *dev) +void mips_event_handler(struct clock_event_device *dev)  {  } @@ -177,7 +99,23 @@ static int c0_compare_int_pending(void)  	return (read_c0_cause() >> cp0_compare_irq) & 0x100;  } -static int c0_compare_int_usable(void) +/* + * Compare interrupt can be routed and latched outside the core, + * so a single execution hazard barrier may not be enough to give + * it time to clear as seen in the Cause register.  4 time the + * pipeline depth seems reasonably conservative, and empirically + * works better in configurations with high CPU/bus clock ratios. + */ + +#define compare_change_hazard() \ +	do { \ +		irq_disable_hazard(); \ +		irq_disable_hazard(); \ +		irq_disable_hazard(); \ +		irq_disable_hazard(); \ +	} while (0) + +int c0_compare_int_usable(void)  {  	unsigned int delta;  	unsigned int cnt; @@ -187,7 +125,7 @@ static int c0_compare_int_usable(void)  	 */  	if (c0_compare_int_pending()) {  		write_c0_compare(read_c0_count()); -		irq_disable_hazard(); +		compare_change_hazard();  		if (c0_compare_int_pending())  			return 0;  	} @@ -196,7 +134,7 @@ static int c0_compare_int_usable(void)  		cnt = read_c0_count();  		cnt += delta;  		write_c0_compare(cnt); -		irq_disable_hazard(); +		compare_change_hazard();  		if ((int)(read_c0_count() - cnt) < 0)  		    break;  		/* increase delta if the timer was already expired */ @@ -205,11 +143,12 @@ static int c0_compare_int_usable(void)  	while ((int)(read_c0_count() - cnt) <= 0)  		;	/* Wait for expiry  */ +	compare_change_hazard();  	if (!c0_compare_int_pending())  		return 0;  	write_c0_compare(read_c0_count()); -	irq_disable_hazard(); +	compare_change_hazard();  	if (c0_compare_int_pending())  		return 0; @@ -219,6 +158,8 @@ static int c0_compare_int_usable(void)  	return 1;  } +#ifndef CONFIG_MIPS_MT_SMTC +  int __cpuinit mips_clockevent_init(void)  {  	uint64_t mips_freq = mips_hpt_frequency; @@ -229,17 +170,6 @@ int __cpuinit mips_clockevent_init(void)  	if (!cpu_has_counter || !mips_hpt_frequency)  		return -ENXIO; -#ifdef CONFIG_MIPS_MT_SMTC -	setup_smtc_dummy_clockevent_device(); - -	/* -	 * On SMTC we only register VPE0's compare interrupt as clockevent -	 * device. -	 */ -	if (cpu) -		return 0; -#endif -  	if (!c0_compare_int_usable())  		return -ENXIO; @@ -265,13 +195,9 @@ int __cpuinit mips_clockevent_init(void)  	cd->rating		= 300;  	cd->irq			= irq; -#ifdef CONFIG_MIPS_MT_SMTC -	cd->cpumask		= CPU_MASK_ALL; -#else  	cd->cpumask		= cpumask_of_cpu(cpu); -#endif  	cd->set_next_event	= mips_next_event; -	cd->set_mode		= mips_set_mode; +	cd->set_mode		= mips_set_clock_mode;  	cd->event_handler	= mips_event_handler;  	clockevents_register_device(cd); @@ -281,12 +207,9 @@ int __cpuinit mips_clockevent_init(void)  	cp0_timer_irq_installed = 1; -#ifdef CONFIG_MIPS_MT_SMTC -#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq) -	setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT); -#else  	setup_irq(irq, &c0_compare_irqaction); -#endif  	return 0;  } + +#endif /* Not CONFIG_MIPS_MT_SMTC */ diff --git a/arch/mips/kernel/cevt-smtc.c b/arch/mips/kernel/cevt-smtc.c new file mode 100644 index 000000000000..5162fe4b5952 --- /dev/null +++ b/arch/mips/kernel/cevt-smtc.c @@ -0,0 +1,321 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 MIPS Technologies, Inc. + * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org> + * Copyright (C) 2008 Kevin D. Kissell, Paralogos sarl + */ +#include <linux/clockchips.h> +#include <linux/interrupt.h> +#include <linux/percpu.h> + +#include <asm/smtc_ipi.h> +#include <asm/time.h> +#include <asm/cevt-r4k.h> + +/* + * Variant clock event timer support for SMTC on MIPS 34K, 1004K + * or other MIPS MT cores. + * + * Notes on SMTC Support: + * + * SMTC has multiple microthread TCs pretending to be Linux CPUs. + * But there's only one Count/Compare pair per VPE, and Compare + * interrupts are taken opportunisitically by available TCs + * bound to the VPE with the Count register.  The new timer + * framework provides for global broadcasts, but we really + * want VPE-level multicasts for best behavior. So instead + * of invoking the high-level clock-event broadcast code, + * this version of SMTC support uses the historical SMTC + * multicast mechanisms "under the hood", appearing to the + * generic clock layer as if the interrupts are per-CPU. + * + * The approach taken here is to maintain a set of NR_CPUS + * virtual timers, and track which "CPU" needs to be alerted + * at each event. + * + * It's unlikely that we'll see a MIPS MT core with more than + * 2 VPEs, but we *know* that we won't need to handle more + * VPEs than we have "CPUs".  So NCPUs arrays of NCPUs elements + * is always going to be overkill, but always going to be enough. + */ + +unsigned long smtc_nexttime[NR_CPUS][NR_CPUS]; +static int smtc_nextinvpe[NR_CPUS]; + +/* + * Timestamps stored are absolute values to be programmed + * into Count register.  Valid timestamps will never be zero. + * If a Zero Count value is actually calculated, it is converted + * to be a 1, which will introduce 1 or two CPU cycles of error + * roughly once every four billion events, which at 1000 HZ means + * about once every 50 days.  If that's actually a problem, one + * could alternate squashing 0 to 1 and to -1. + */ + +#define MAKEVALID(x) (((x) == 0L) ? 1L : (x)) +#define ISVALID(x) ((x) != 0L) + +/* + * Time comparison is subtle, as it's really truncated + * modular arithmetic. + */ + +#define IS_SOONER(a, b, reference) \ +    (((a) - (unsigned long)(reference)) < ((b) - (unsigned long)(reference))) + +/* + * CATCHUP_INCREMENT, used when the function falls behind the counter. + * Could be an increasing function instead of a constant; + */ + +#define CATCHUP_INCREMENT 64 + +static int mips_next_event(unsigned long delta, +				struct clock_event_device *evt) +{ +	unsigned long flags; +	unsigned int mtflags; +	unsigned long timestamp, reference, previous; +	unsigned long nextcomp = 0L; +	int vpe = current_cpu_data.vpe_id; +	int cpu = smp_processor_id(); +	local_irq_save(flags); +	mtflags = dmt(); + +	/* +	 * Maintain the per-TC virtual timer +	 * and program the per-VPE shared Count register +	 * as appropriate here... +	 */ +	reference = (unsigned long)read_c0_count(); +	timestamp = MAKEVALID(reference + delta); +	/* +	 * To really model the clock, we have to catch the case +	 * where the current next-in-VPE timestamp is the old +	 * timestamp for the calling CPE, but the new value is +	 * in fact later.  In that case, we have to do a full +	 * scan and discover the new next-in-VPE CPU id and +	 * timestamp. +	 */ +	previous = smtc_nexttime[vpe][cpu]; +	if (cpu == smtc_nextinvpe[vpe] && ISVALID(previous) +	    && IS_SOONER(previous, timestamp, reference)) { +		int i; +		int soonest = cpu; + +		/* +		 * Update timestamp array here, so that new +		 * value gets considered along with those of +		 * other virtual CPUs on the VPE. +		 */ +		smtc_nexttime[vpe][cpu] = timestamp; +		for_each_online_cpu(i) { +			if (ISVALID(smtc_nexttime[vpe][i]) +			    && IS_SOONER(smtc_nexttime[vpe][i], +				smtc_nexttime[vpe][soonest], reference)) { +				    soonest = i; +			} +		} +		smtc_nextinvpe[vpe] = soonest; +		nextcomp = smtc_nexttime[vpe][soonest]; +	/* +	 * Otherwise, we don't have to process the whole array rank, +	 * we just have to see if the event horizon has gotten closer. +	 */ +	} else { +		if (!ISVALID(smtc_nexttime[vpe][smtc_nextinvpe[vpe]]) || +		    IS_SOONER(timestamp, +			smtc_nexttime[vpe][smtc_nextinvpe[vpe]], reference)) { +			    smtc_nextinvpe[vpe] = cpu; +			    nextcomp = timestamp; +		} +		/* +		 * Since next-in-VPE may me the same as the executing +		 * virtual CPU, we update the array *after* checking +		 * its value. +		 */ +		smtc_nexttime[vpe][cpu] = timestamp; +	} + +	/* +	 * It may be that, in fact, we don't need to update Compare, +	 * but if we do, we want to make sure we didn't fall into +	 * a crack just behind Count. +	 */ +	if (ISVALID(nextcomp)) { +		write_c0_compare(nextcomp); +		ehb(); +		/* +		 * We never return an error, we just make sure +		 * that we trigger the handlers as quickly as +		 * we can if we fell behind. +		 */ +		while ((nextcomp - (unsigned long)read_c0_count()) +			> (unsigned long)LONG_MAX) { +			nextcomp += CATCHUP_INCREMENT; +			write_c0_compare(nextcomp); +			ehb(); +		} +	} +	emt(mtflags); +	local_irq_restore(flags); +	return 0; +} + + +void smtc_distribute_timer(int vpe) +{ +	unsigned long flags; +	unsigned int mtflags; +	int cpu; +	struct clock_event_device *cd; +	unsigned long nextstamp = 0L; +	unsigned long reference; + + +repeat: +	for_each_online_cpu(cpu) { +	    /* +	     * Find virtual CPUs within the current VPE who have +	     * unserviced timer requests whose time is now past. +	     */ +	    local_irq_save(flags); +	    mtflags = dmt(); +	    if (cpu_data[cpu].vpe_id == vpe && +		ISVALID(smtc_nexttime[vpe][cpu])) { +		reference = (unsigned long)read_c0_count(); +		if ((smtc_nexttime[vpe][cpu] - reference) +			 > (unsigned long)LONG_MAX) { +			    smtc_nexttime[vpe][cpu] = 0L; +			    emt(mtflags); +			    local_irq_restore(flags); +			    /* +			     * We don't send IPIs to ourself. +			     */ +			    if (cpu != smp_processor_id()) { +				smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0); +			    } else { +				cd = &per_cpu(mips_clockevent_device, cpu); +				cd->event_handler(cd); +			    } +		} else { +			/* Local to VPE but Valid Time not yet reached. */ +			if (!ISVALID(nextstamp) || +			    IS_SOONER(smtc_nexttime[vpe][cpu], nextstamp, +			    reference)) { +				smtc_nextinvpe[vpe] = cpu; +				nextstamp = smtc_nexttime[vpe][cpu]; +			} +			emt(mtflags); +			local_irq_restore(flags); +		} +	    } else { +		emt(mtflags); +		local_irq_restore(flags); + +	    } +	} +	/* Reprogram for interrupt at next soonest timestamp for VPE */ +	if (ISVALID(nextstamp)) { +		write_c0_compare(nextstamp); +		ehb(); +		if ((nextstamp - (unsigned long)read_c0_count()) +			> (unsigned long)LONG_MAX) +				goto repeat; +	} +} + + +irqreturn_t c0_compare_interrupt(int irq, void *dev_id) +{ +	int cpu = smp_processor_id(); + +	/* If we're running SMTC, we've got MIPS MT and therefore MIPS32R2 */ +	handle_perf_irq(1); + +	if (read_c0_cause() & (1 << 30)) { +		/* Clear Count/Compare Interrupt */ +		write_c0_compare(read_c0_compare()); +		smtc_distribute_timer(cpu_data[cpu].vpe_id); +	} +	return IRQ_HANDLED; +} + + +int __cpuinit mips_clockevent_init(void) +{ +	uint64_t mips_freq = mips_hpt_frequency; +	unsigned int cpu = smp_processor_id(); +	struct clock_event_device *cd; +	unsigned int irq; +	int i; +	int j; + +	if (!cpu_has_counter || !mips_hpt_frequency) +		return -ENXIO; +	if (cpu == 0) { +		for (i = 0; i < num_possible_cpus(); i++) { +			smtc_nextinvpe[i] = 0; +			for (j = 0; j < num_possible_cpus(); j++) +				smtc_nexttime[i][j] = 0L; +		} +		/* +		 * SMTC also can't have the usablility test +		 * run by secondary TCs once Compare is in use. +		 */ +		if (!c0_compare_int_usable()) +			return -ENXIO; +	} + +	/* +	 * With vectored interrupts things are getting platform specific. +	 * get_c0_compare_int is a hook to allow a platform to return the +	 * interrupt number of it's liking. +	 */ +	irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; +	if (get_c0_compare_int) +		irq = get_c0_compare_int(); + +	cd = &per_cpu(mips_clockevent_device, cpu); + +	cd->name		= "MIPS"; +	cd->features		= CLOCK_EVT_FEAT_ONESHOT; + +	/* Calculate the min / max delta */ +	cd->mult	= div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32); +	cd->shift		= 32; +	cd->max_delta_ns	= clockevent_delta2ns(0x7fffffff, cd); +	cd->min_delta_ns	= clockevent_delta2ns(0x300, cd); + +	cd->rating		= 300; +	cd->irq			= irq; +	cd->cpumask		= cpumask_of_cpu(cpu); +	cd->set_next_event	= mips_next_event; +	cd->set_mode		= mips_set_clock_mode; +	cd->event_handler	= mips_event_handler; + +	clockevents_register_device(cd); + +	/* +	 * On SMTC we only want to do the data structure +	 * initialization and IRQ setup once. +	 */ +	if (cpu) +		return 0; +	/* +	 * And we need the hwmask associated with the c0_compare +	 * vector to be initialized. +	 */ +	irq_hwmask[irq] = (0x100 << cp0_compare_irq); +	if (cp0_timer_irq_installed) +		return 0; + +	cp0_timer_irq_installed = 1; + +	setup_irq(irq, &c0_compare_irqaction); + +	return 0; +} diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 11c92dc53791..e621fda8ab37 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -54,14 +54,18 @@ extern void r4k_wait(void);   * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes   * using this version a gamble.   */ -static void r4k_wait_irqoff(void) +void r4k_wait_irqoff(void)  {  	local_irq_disable();  	if (!need_resched()) -		__asm__("	.set	mips3		\n" +		__asm__("	.set	push		\n" +			"	.set	mips3		\n"  			"	wait			\n" -			"	.set	mips0		\n"); +			"	.set	pop		\n");  	local_irq_enable(); +	__asm__(" 	.globl __pastwait	\n" +		"__pastwait:			\n"); +	return;  }  /* diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index e29598ae939d..ffa331029e08 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -79,11 +79,6 @@ FEXPORT(syscall_exit)  FEXPORT(restore_all)			# restore full frame  #ifdef CONFIG_MIPS_MT_SMTC -/* Detect and execute deferred IPI "interrupts" */ -	LONG_L	s0, TI_REGS($28) -	LONG_S	sp, TI_REGS($28) -	jal	deferred_smtc_ipi -	LONG_S	s0, TI_REGS($28)  #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP  /* Re-arm any temporarily masked interrupts not explicitly "acked" */  	mfc0	v0, CP0_TCSTATUS @@ -112,6 +107,11 @@ FEXPORT(restore_all)			# restore full frame  	xor	t0, t0, t3  	mtc0	t0, CP0_TCCONTEXT  #endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */ +/* Detect and execute deferred IPI "interrupts" */ +	LONG_L	s0, TI_REGS($28) +	LONG_S	sp, TI_REGS($28) +	jal	deferred_smtc_ipi +	LONG_S	s0, TI_REGS($28)  #endif /* CONFIG_MIPS_MT_SMTC */  	.set	noat  	RESTORE_TEMP diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index f886dd7f708e..01dcbe38fa01 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -282,8 +282,8 @@ NESTED(except_vec_vi_handler, 0, sp)  	and	t0, a0, t1  #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP  	mfc0	t2, CP0_TCCONTEXT -	or	t0, t0, t2 -	mtc0	t0, CP0_TCCONTEXT +	or	t2, t0, t2 +	mtc0	t2, CP0_TCCONTEXT  #endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */  	xor	t1, t1, t0  	mtc0	t1, CP0_STATUS diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 361364501d34..492a0a8d70fb 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -22,6 +22,7 @@  #include <asm/irqflags.h>  #include <asm/regdef.h>  #include <asm/page.h> +#include <asm/pgtable-bits.h>  #include <asm/mipsregs.h>  #include <asm/stackframe.h> diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c index df4d3f2f740c..dc9eb72ed9de 100644 --- a/arch/mips/kernel/mips-mt-fpaff.c +++ b/arch/mips/kernel/mips-mt-fpaff.c @@ -159,7 +159,7 @@ __setup("fpaff=", fpaff_thresh);  /*   * FPU Use Factor empirically derived from experiments on 34K   */ -#define FPUSEFACTOR 333 +#define FPUSEFACTOR 2000  static __init int mt_fp_affinity_init(void)  { diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index ce7684335a41..22fc19bbe87f 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -55,7 +55,7 @@ void __noreturn cpu_idle(void)  	while (1) {  		tick_nohz_stop_sched_tick(1);  		while (!need_resched()) { -#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG +#ifdef CONFIG_MIPS_MT_SMTC  			extern void smtc_idle_loop_hook(void);  			smtc_idle_loop_hook(); @@ -145,19 +145,18 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,  	 */  	p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);  	childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); + +#ifdef CONFIG_MIPS_MT_SMTC +	/* +	 * SMTC restores TCStatus after Status, and the CU bits +	 * are aliased there. +	 */ +	childregs->cp0_tcstatus &= ~(ST0_CU2|ST0_CU1); +#endif  	clear_tsk_thread_flag(p, TIF_USEDFPU);  #ifdef CONFIG_MIPS_MT_FPAFF  	clear_tsk_thread_flag(p, TIF_FPUBOUND); - -	/* -	 * FPU affinity support is cleaner if we track the -	 * user-visible CPU affinity from the very beginning. -	 * The generic cpus_allowed mask will already have -	 * been copied from the parent before copy_thread -	 * is invoked. -	 */ -	p->thread.user_cpus_allowed = p->cpus_allowed;  #endif /* CONFIG_MIPS_MT_FPAFF */  	if (clone_flags & CLONE_SETTLS) diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 35234b92b9a5..96ffc9c6d194 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -238,7 +238,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)  		case FPC_EIR: {	/* implementation / version register */  			unsigned int flags;  #ifdef CONFIG_MIPS_MT_SMTC -			unsigned int irqflags; +			unsigned long irqflags;  			unsigned int mtflags;  #endif /* CONFIG_MIPS_MT_SMTC */ diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index a516286532ab..897fb2b4751c 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -1,4 +1,21 @@ -/* Copyright (C) 2004 Mips Technologies, Inc */ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. + * + * Copyright (C) 2004 Mips Technologies, Inc + * Copyright (C) 2008 Kevin D. Kissell + */  #include <linux/clockchips.h>  #include <linux/kernel.h> @@ -21,7 +38,6 @@  #include <asm/time.h>  #include <asm/addrspace.h>  #include <asm/smtc.h> -#include <asm/smtc_ipi.h>  #include <asm/smtc_proc.h>  /* @@ -58,11 +74,6 @@ unsigned long irq_hwmask[NR_IRQS];  asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; -/* - * Clock interrupt "latch" buffers, per "CPU" - */ - -static atomic_t ipi_timer_latch[NR_CPUS];  /*   * Number of InterProcessor Interrupt (IPI) message buffers to allocate @@ -70,7 +81,7 @@ static atomic_t ipi_timer_latch[NR_CPUS];  #define IPIBUF_PER_CPU 4 -static struct smtc_ipi_q IPIQ[NR_CPUS]; +struct smtc_ipi_q IPIQ[NR_CPUS];  static struct smtc_ipi_q freeIPIq; @@ -282,7 +293,7 @@ static void smtc_configure_tlb(void)   * phys_cpu_present_map and the logical/physical mappings.   */ -int __init mipsmt_build_cpu_map(int start_cpu_slot) +int __init smtc_build_cpu_map(int start_cpu_slot)  {  	int i, ntcs; @@ -325,7 +336,12 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)  	write_tc_c0_tcstatus((read_tc_c0_tcstatus()  			& ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT))  			| TCSTATUS_A); -	write_tc_c0_tccontext(0); +	/* +	 * TCContext gets an offset from the base of the IPIQ array +	 * to be used in low-level code to detect the presence of +	 * an active IPI queue +	 */ +	write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16);  	/* Bind tc to vpe */  	write_tc_c0_tcbind(vpe);  	/* In general, all TCs should have the same cpu_data indications */ @@ -336,10 +352,18 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)  		cpu_data[cpu].options &= ~MIPS_CPU_FPU;  	cpu_data[cpu].vpe_id = vpe;  	cpu_data[cpu].tc_id = tc; +	/* Multi-core SMTC hasn't been tested, but be prepared */ +	cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff;  } +/* + * Tweak to get Count registes in as close a sync as possible. + * Value seems good for 34K-class cores. + */ + +#define CP0_SKEW 8 -void mipsmt_prepare_cpus(void) +void smtc_prepare_cpus(int cpus)  {  	int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu;  	unsigned long flags; @@ -363,13 +387,13 @@ void mipsmt_prepare_cpus(void)  		IPIQ[i].head = IPIQ[i].tail = NULL;  		spin_lock_init(&IPIQ[i].lock);  		IPIQ[i].depth = 0; -		atomic_set(&ipi_timer_latch[i], 0);  	}  	/* cpu_data index starts at zero */  	cpu = 0;  	cpu_data[cpu].vpe_id = 0;  	cpu_data[cpu].tc_id = 0; +	cpu_data[cpu].core = (read_c0_ebase() >> 1) & 0xff;  	cpu++;  	/* Report on boot-time options */ @@ -484,7 +508,8 @@ void mipsmt_prepare_cpus(void)  			write_vpe_c0_compare(0);  			/* Propagate Config7 */  			write_vpe_c0_config7(read_c0_config7()); -			write_vpe_c0_count(read_c0_count()); +			write_vpe_c0_count(read_c0_count() + CP0_SKEW); +			ehb();  		}  		/* enable multi-threading within VPE */  		write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE); @@ -556,7 +581,7 @@ void mipsmt_prepare_cpus(void)  void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle)  {  	extern u32 kernelsp[NR_CPUS]; -	long flags; +	unsigned long flags;  	int mtflags;  	LOCK_MT_PRA(); @@ -585,24 +610,22 @@ void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle)  void smtc_init_secondary(void)  { -	/* -	 * Start timer on secondary VPEs if necessary. -	 * plat_timer_setup has already have been invoked by init/main -	 * on "boot" TC.  Like per_cpu_trap_init() hack, this assumes that -	 * SMTC init code assigns TCs consdecutively and in ascending order -	 * to across available VPEs. -	 */ -	if (((read_c0_tcbind() & TCBIND_CURTC) != 0) && -	    ((read_c0_tcbind() & TCBIND_CURVPE) -	    != cpu_data[smp_processor_id() - 1].vpe_id)){ -		write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ); -	} -  	local_irq_enable();  }  void smtc_smp_finish(void)  { +	int cpu = smp_processor_id(); + +	/* +	 * Lowest-numbered CPU per VPE starts a clock tick. +	 * Like per_cpu_trap_init() hack, this assumes that +	 * SMTC init code assigns TCs consdecutively and +	 * in ascending order across available VPEs. +	 */ +	if (cpu > 0 && (cpu_data[cpu].vpe_id != cpu_data[cpu - 1].vpe_id)) +		write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ); +  	printk("TC %d going on-line as CPU %d\n",  		cpu_data[smp_processor_id()].tc_id, smp_processor_id());  } @@ -753,8 +776,10 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)  {  	int tcstatus;  	struct smtc_ipi *pipi; -	long flags; +	unsigned long flags;  	int mtflags; +	unsigned long tcrestart; +	extern void r4k_wait_irqoff(void), __pastwait(void);  	if (cpu == smp_processor_id()) {  		printk("Cannot Send IPI to self!\n"); @@ -771,8 +796,6 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)  	pipi->arg = (void *)action;  	pipi->dest = cpu;  	if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { -		if (type == SMTC_CLOCK_TICK) -			atomic_inc(&ipi_timer_latch[cpu]);  		/* If not on same VPE, enqueue and send cross-VPE interrupt */  		smtc_ipi_nq(&IPIQ[cpu], pipi);  		LOCK_CORE_PRA(); @@ -800,22 +823,29 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)  		if ((tcstatus & TCSTATUS_IXMT) != 0) {  			/* -			 * Spin-waiting here can deadlock, -			 * so we queue the message for the target TC. +			 * If we're in the the irq-off version of the wait +			 * loop, we need to force exit from the wait and +			 * do a direct post of the IPI. +			 */ +			if (cpu_wait == r4k_wait_irqoff) { +				tcrestart = read_tc_c0_tcrestart(); +				if (tcrestart >= (unsigned long)r4k_wait_irqoff +				    && tcrestart < (unsigned long)__pastwait) { +					write_tc_c0_tcrestart(__pastwait); +					tcstatus &= ~TCSTATUS_IXMT; +					write_tc_c0_tcstatus(tcstatus); +					goto postdirect; +				} +			} +			/* +			 * Otherwise we queue the message for the target TC +			 * to pick up when he does a local_irq_restore()  			 */  			write_tc_c0_tchalt(0);  			UNLOCK_CORE_PRA(); -			/* Try to reduce redundant timer interrupt messages */ -			if (type == SMTC_CLOCK_TICK) { -			    if (atomic_postincrement(&ipi_timer_latch[cpu])!=0){ -				smtc_ipi_nq(&freeIPIq, pipi); -				return; -			    } -			}  			smtc_ipi_nq(&IPIQ[cpu], pipi);  		} else { -			if (type == SMTC_CLOCK_TICK) -				atomic_inc(&ipi_timer_latch[cpu]); +postdirect:  			post_direct_ipi(cpu, pipi);  			write_tc_c0_tchalt(0);  			UNLOCK_CORE_PRA(); @@ -883,7 +913,7 @@ static void ipi_call_interrupt(void)  	smp_call_function_interrupt();  } -DECLARE_PER_CPU(struct clock_event_device, smtc_dummy_clockevent_device); +DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);  void ipi_decode(struct smtc_ipi *pipi)  { @@ -891,20 +921,13 @@ void ipi_decode(struct smtc_ipi *pipi)  	struct clock_event_device *cd;  	void *arg_copy = pipi->arg;  	int type_copy = pipi->type; -	int ticks; -  	smtc_ipi_nq(&freeIPIq, pipi);  	switch (type_copy) {  	case SMTC_CLOCK_TICK:  		irq_enter();  		kstat_this_cpu.irqs[MIPS_CPU_IRQ_BASE + 1]++; -		cd = &per_cpu(smtc_dummy_clockevent_device, cpu); -		ticks = atomic_read(&ipi_timer_latch[cpu]); -		atomic_sub(ticks, &ipi_timer_latch[cpu]); -		while (ticks) { -			cd->event_handler(cd); -			ticks--; -		} +		cd = &per_cpu(mips_clockevent_device, cpu); +		cd->event_handler(cd);  		irq_exit();  		break; @@ -937,24 +960,48 @@ void ipi_decode(struct smtc_ipi *pipi)  	}  } +/* + * Similar to smtc_ipi_replay(), but invoked from context restore, + * so it reuses the current exception frame rather than set up a + * new one with self_ipi. + */ +  void deferred_smtc_ipi(void)  { -	struct smtc_ipi *pipi; -	unsigned long flags; -/* DEBUG */ -	int q = smp_processor_id(); +	int cpu = smp_processor_id();  	/*  	 * Test is not atomic, but much faster than a dequeue,  	 * and the vast majority of invocations will have a null queue. +	 * If irq_disabled when this was called, then any IPIs queued +	 * after we test last will be taken on the next irq_enable/restore. +	 * If interrupts were enabled, then any IPIs added after the +	 * last test will be taken directly.  	 */ -	if (IPIQ[q].head != NULL) { -		while((pipi = smtc_ipi_dq(&IPIQ[q])) != NULL) { -			/* ipi_decode() should be called with interrupts off */ -			local_irq_save(flags); + +	while (IPIQ[cpu].head != NULL) { +		struct smtc_ipi_q *q = &IPIQ[cpu]; +		struct smtc_ipi *pipi; +		unsigned long flags; + +		/* +		 * It may be possible we'll come in with interrupts +		 * already enabled. +		 */ +		local_irq_save(flags); + +		spin_lock(&q->lock); +		pipi = __smtc_ipi_dq(q); +		spin_unlock(&q->lock); +		if (pipi != NULL)  			ipi_decode(pipi); -			local_irq_restore(flags); -		} +		/* +		 * The use of the __raw_local restore isn't +		 * as obviously necessary here as in smtc_ipi_replay(), +		 * but it's more efficient, given that we're already +		 * running down the IPI queue. +		 */ +		__raw_local_irq_restore(flags);  	}  } @@ -975,7 +1022,7 @@ static irqreturn_t ipi_interrupt(int irq, void *dev_idm)  	struct smtc_ipi *pipi;  	unsigned long tcstatus;  	int sent; -	long flags; +	unsigned long flags;  	unsigned int mtflags;  	unsigned int vpflags; @@ -1066,55 +1113,53 @@ static void setup_cross_vpe_interrupts(unsigned int nvpe)  /*   * SMTC-specific hacks invoked from elsewhere in the kernel. - * - * smtc_ipi_replay is called from raw_local_irq_restore which is only ever - * called with interrupts disabled.  We do rely on interrupts being disabled - * here because using spin_lock_irqsave()/spin_unlock_irqrestore() would - * result in a recursive call to raw_local_irq_restore().   */ -static void __smtc_ipi_replay(void) + /* +  * smtc_ipi_replay is called from raw_local_irq_restore +  */ + +void smtc_ipi_replay(void)  {  	unsigned int cpu = smp_processor_id();  	/*  	 * To the extent that we've ever turned interrupts off,  	 * we may have accumulated deferred IPIs.  This is subtle. -	 * If we use the smtc_ipi_qdepth() macro, we'll get an -	 * exact number - but we'll also disable interrupts -	 * and create a window of failure where a new IPI gets -	 * queued after we test the depth but before we re-enable -	 * interrupts. So long as IXMT never gets set, however,  	 * we should be OK:  If we pick up something and dispatch  	 * it here, that's great. If we see nothing, but concurrent  	 * with this operation, another TC sends us an IPI, IXMT  	 * is clear, and we'll handle it as a real pseudo-interrupt -	 * and not a pseudo-pseudo interrupt. +	 * and not a pseudo-pseudo interrupt.  The important thing +	 * is to do the last check for queued message *after* the +	 * re-enabling of interrupts.  	 */ -	if (IPIQ[cpu].depth > 0) { -		while (1) { -			struct smtc_ipi_q *q = &IPIQ[cpu]; -			struct smtc_ipi *pipi; -			extern void self_ipi(struct smtc_ipi *); - -			spin_lock(&q->lock); -			pipi = __smtc_ipi_dq(q); -			spin_unlock(&q->lock); -			if (!pipi) -				break; +	while (IPIQ[cpu].head != NULL) { +		struct smtc_ipi_q *q = &IPIQ[cpu]; +		struct smtc_ipi *pipi; +		unsigned long flags; + +		/* +		 * It's just possible we'll come in with interrupts +		 * already enabled. +		 */ +		local_irq_save(flags); + +		spin_lock(&q->lock); +		pipi = __smtc_ipi_dq(q); +		spin_unlock(&q->lock); +		/* +		 ** But use a raw restore here to avoid recursion. +		 */ +		__raw_local_irq_restore(flags); +		if (pipi) {  			self_ipi(pipi);  			smtc_cpu_stats[cpu].selfipis++;  		}  	}  } -void smtc_ipi_replay(void) -{ -	raw_local_irq_disable(); -	__smtc_ipi_replay(); -} -  EXPORT_SYMBOL(smtc_ipi_replay);  void smtc_idle_loop_hook(void) @@ -1193,40 +1238,13 @@ void smtc_idle_loop_hook(void)  		}  	} -	/* -	 * Now that we limit outstanding timer IPIs, check for hung TC -	 */ -	for (tc = 0; tc < NR_CPUS; tc++) { -		/* Don't check ourself - we'll dequeue IPIs just below */ -		if ((tc != smp_processor_id()) && -		    atomic_read(&ipi_timer_latch[tc]) > timerq_limit) { -		    if (clock_hang_reported[tc] == 0) { -			pdb_msg += sprintf(pdb_msg, -				"TC %d looks hung with timer latch at %d\n", -				tc, atomic_read(&ipi_timer_latch[tc])); -			clock_hang_reported[tc]++; -			} -		} -	}  	emt(mtflags);  	local_irq_restore(flags);  	if (pdb_msg != &id_ho_db_msg[0])  		printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);  #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ -	/* -	 * Replay any accumulated deferred IPIs. If "Instant Replay" -	 * is in use, there should never be any. -	 */ -#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY -	{ -		unsigned long flags; - -		local_irq_save(flags); -		__smtc_ipi_replay(); -		local_irq_restore(flags); -	} -#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ +	smtc_ipi_replay();  }  void smtc_soft_dump(void) @@ -1242,10 +1260,6 @@ void smtc_soft_dump(void)  		printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis);  	}  	smtc_ipi_qdump(); -	printk("Timer IPI Backlogs:\n"); -	for (i=0; i < NR_CPUS; i++) { -		printk("%d: %d\n", i, atomic_read(&ipi_timer_latch[i])); -	}  	printk("%d Recoveries of \"stolen\" FPU\n",  	       atomic_read(&smtc_fpu_recoveries));  } diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 5fd0cd020af5..b602ac6eb47d 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -825,8 +825,10 @@ static void mt_ase_fp_affinity(void)  		if (cpus_intersects(current->cpus_allowed, mt_fpu_cpumask)) {  			cpumask_t tmask; -			cpus_and(tmask, current->thread.user_cpus_allowed, -			         mt_fpu_cpumask); +			current->thread.user_cpus_allowed +				= current->cpus_allowed; +			cpus_and(tmask, current->cpus_allowed, +				mt_fpu_cpumask);  			set_cpus_allowed(current, tmask);  			set_thread_flag(TIF_FPUBOUND);  		} diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index 3b7dd722c32a..cef2db8d2225 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -15,6 +15,6 @@ obj-$(CONFIG_EARLY_PRINTK)	+= malta-console.o  obj-$(CONFIG_PCI)		+= malta-pci.o  # FIXME FIXME FIXME -obj-$(CONFIG_MIPS_MT_SMTC)	+= malta_smtc.o +obj-$(CONFIG_MIPS_MT_SMTC)	+= malta-smtc.o  EXTRA_CFLAGS += -Werror diff --git a/arch/mips/mti-malta/malta-smtc.c b/arch/mips/mti-malta/malta-smtc.c index 5ea705e49454..f84a46a8ae6e 100644 --- a/arch/mips/mti-malta/malta-smtc.c +++ b/arch/mips/mti-malta/malta-smtc.c @@ -84,12 +84,17 @@ static void msmtc_cpus_done(void)  static void __init msmtc_smp_setup(void)  { -	mipsmt_build_cpu_map(0); +	/* +	 * we won't get the definitive value until +	 * we've run smtc_prepare_cpus later, but +	 * we would appear to need an upper bound now. +	 */ +	smp_num_siblings = smtc_build_cpu_map(0);  }  static void __init msmtc_prepare_cpus(unsigned int max_cpus)  { -	mipsmt_prepare_cpus(); +	smtc_prepare_cpus(max_cpus);  }  struct plat_smp_ops msmtc_smp_ops = { diff --git a/arch/mips/sibyte/swarm/Makefile b/arch/mips/sibyte/swarm/Makefile index f18ba9201bbc..7b45f199d92a 100644 --- a/arch/mips/sibyte/swarm/Makefile +++ b/arch/mips/sibyte/swarm/Makefile @@ -1,3 +1,4 @@ -obj-y				:= setup.o rtc_xicor1241.o rtc_m41t81.o +obj-y				:= platform.o setup.o rtc_xicor1241.o \ +				   rtc_m41t81.o  obj-$(CONFIG_I2C_BOARDINFO)	+= swarm-i2c.o diff --git a/arch/mips/sibyte/swarm/platform.c b/arch/mips/sibyte/swarm/platform.c new file mode 100644 index 000000000000..54847fe1e564 --- /dev/null +++ b/arch/mips/sibyte/swarm/platform.c @@ -0,0 +1,85 @@ +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/ata_platform.h> + +#include <asm/sibyte/board.h> +#include <asm/sibyte/sb1250_genbus.h> +#include <asm/sibyte/sb1250_regs.h> + +#if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_LITTLESUR) + +#define DRV_NAME	"pata-swarm" + +#define SWARM_IDE_SHIFT	5 +#define SWARM_IDE_BASE	0x1f0 +#define SWARM_IDE_CTRL	0x3f6 + +static struct resource swarm_pata_resource[] = { +	{ +		.name	= "Swarm GenBus IDE", +		.flags	= IORESOURCE_MEM, +	}, { +		.name	= "Swarm GenBus IDE", +		.flags	= IORESOURCE_MEM, +	}, { +		.name	= "Swarm GenBus IDE", +		.flags	= IORESOURCE_IRQ, +		.start	= K_INT_GB_IDE, +		.end	= K_INT_GB_IDE, +	}, +}; + +static struct pata_platform_info pata_platform_data = { +	.ioport_shift	= SWARM_IDE_SHIFT, +}; + +static struct platform_device swarm_pata_device = { +	.name		= "pata_platform", +	.id		= -1, +	.resource	= swarm_pata_resource, +	.num_resources	= ARRAY_SIZE(swarm_pata_resource), +	.dev  = { +		.platform_data		= &pata_platform_data, +		.coherent_dma_mask	= ~0,	/* grumble */ +	}, +}; + +static int __init swarm_pata_init(void) +{ +	u8 __iomem *base; +	phys_t offset, size; +	struct resource *r; + +	if (!SIBYTE_HAVE_IDE) +		return -ENODEV; + +	base = ioremap(A_IO_EXT_BASE, 0x800); +	offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS)); +	size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS)); +	iounmap(base); + +	offset = G_IO_START_ADDR(offset) << S_IO_ADDRBASE; +	size = (G_IO_MULT_SIZE(size) + 1) << S_IO_REGSIZE; +	if (offset < A_PHYS_GENBUS || offset >= A_PHYS_GENBUS_END) { +		pr_info(DRV_NAME ": PATA interface at GenBus disabled\n"); + +		return -EBUSY; +	} + +	pr_info(DRV_NAME ": PATA interface at GenBus slot %i\n", IDE_CS); + +	r = swarm_pata_resource; +	r[0].start = offset + (SWARM_IDE_BASE << SWARM_IDE_SHIFT); +	r[0].end   = offset + ((SWARM_IDE_BASE + 8) << SWARM_IDE_SHIFT) - 1; +	r[1].start = offset + (SWARM_IDE_CTRL << SWARM_IDE_SHIFT); +	r[1].end   = offset + ((SWARM_IDE_CTRL + 1) << SWARM_IDE_SHIFT) - 1; + +	return platform_device_register(&swarm_pata_device); +} + +device_initcall(swarm_pata_init); + +#endif /* defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_LITTLESUR) */ diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index 761c434a2488..56c64ccc9c21 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c @@ -20,22 +20,8 @@ EXPORT_SYMBOL(__mn10300_irq_enabled_epsw);  atomic_t irq_err_count;  /* - * MN10300 INTC controller operations + * MN10300 interrupt controller operations   */ -static void mn10300_cpupic_disable(unsigned int irq) -{ -	u16 tmp = GxICR(irq); -	GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT; -	tmp = GxICR(irq); -} - -static void mn10300_cpupic_enable(unsigned int irq) -{ -	u16 tmp = GxICR(irq); -	GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE; -	tmp = GxICR(irq); -} -  static void mn10300_cpupic_ack(unsigned int irq)  {  	u16 tmp; @@ -60,26 +46,54 @@ static void mn10300_cpupic_mask_ack(unsigned int irq)  static void mn10300_cpupic_unmask(unsigned int irq)  {  	u16 tmp = GxICR(irq); -	GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT; +	GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;  	tmp = GxICR(irq);  } -static void mn10300_cpupic_end(unsigned int irq) +static void mn10300_cpupic_unmask_clear(unsigned int irq)  { +	/* the MN10300 PIC latches its interrupt request bit, even after the +	 * device has ceased to assert its interrupt line and the interrupt +	 * channel has been disabled in the PIC, so for level-triggered +	 * interrupts we need to clear the request bit when we re-enable */  	u16 tmp = GxICR(irq); -	GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE; +	GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;  	tmp = GxICR(irq);  } -static struct irq_chip mn10300_cpu_pic = { -	.name		= "cpu", -	.disable	= mn10300_cpupic_disable, -	.enable		= mn10300_cpupic_enable, +/* + * MN10300 PIC level-triggered IRQ handling. + * + * The PIC has no 'ACK' function per se.  It is possible to clear individual + * channel latches, but each latch relatches whether or not the channel is + * masked, so we need to clear the latch when we unmask the channel. + * + * Also for this reason, we don't supply an ack() op (it's unused anyway if + * mask_ack() is provided), and mask_ack() just masks. + */ +static struct irq_chip mn10300_cpu_pic_level = { +	.name		= "cpu_l", +	.disable	= mn10300_cpupic_mask, +	.enable		= mn10300_cpupic_unmask_clear, +	.ack		= NULL, +	.mask		= mn10300_cpupic_mask, +	.mask_ack	= mn10300_cpupic_mask, +	.unmask		= mn10300_cpupic_unmask_clear, +}; + +/* + * MN10300 PIC edge-triggered IRQ handling. + * + * We use the latch clearing function of the PIC as the 'ACK' function. + */ +static struct irq_chip mn10300_cpu_pic_edge = { +	.name		= "cpu_e", +	.disable	= mn10300_cpupic_mask, +	.enable		= mn10300_cpupic_unmask,  	.ack		= mn10300_cpupic_ack,  	.mask		= mn10300_cpupic_mask,  	.mask_ack	= mn10300_cpupic_mask_ack,  	.unmask		= mn10300_cpupic_unmask, -	.end		= mn10300_cpupic_end,  };  /* @@ -114,7 +128,8 @@ void set_intr_level(int irq, u16 level)   */  void set_intr_postackable(int irq)  { -	set_irq_handler(irq, handle_level_irq); +	set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level, +				 handle_level_irq);  }  /* @@ -126,8 +141,12 @@ void __init init_IRQ(void)  	for (irq = 0; irq < NR_IRQS; irq++)  		if (irq_desc[irq].chip == &no_irq_type) -			set_irq_chip_and_handler(irq, &mn10300_cpu_pic, -						 handle_edge_irq); +			/* due to the PIC latching interrupt requests, even +			 * when the IRQ is disabled, IRQ_PENDING is superfluous +			 * and we can use handle_level_irq() for edge-triggered +			 * interrupts */ +			set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge, +						 handle_level_irq);  	unit_init_IRQ();  } diff --git a/arch/mn10300/unit-asb2303/unit-init.c b/arch/mn10300/unit-asb2303/unit-init.c index 14b2c817cff8..70e8cb4ea266 100644 --- a/arch/mn10300/unit-asb2303/unit-init.c +++ b/arch/mn10300/unit-asb2303/unit-init.c @@ -51,7 +51,7 @@ void __init unit_init_IRQ(void)  		switch (GET_XIRQ_TRIGGER(extnum)) {  		case XIRQ_TRIGGER_HILEVEL:  		case XIRQ_TRIGGER_LOWLEVEL: -			set_irq_handler(XIRQ2IRQ(extnum), handle_level_irq); +			set_intr_postackable(XIRQ2IRQ(extnum));  			break;  		default:  			break; diff --git a/arch/mn10300/unit-asb2305/unit-init.c b/arch/mn10300/unit-asb2305/unit-init.c index 6a352414a358..72812a9439ac 100644 --- a/arch/mn10300/unit-asb2305/unit-init.c +++ b/arch/mn10300/unit-asb2305/unit-init.c @@ -52,7 +52,7 @@ void __init unit_init_IRQ(void)  		switch (GET_XIRQ_TRIGGER(extnum)) {  		case XIRQ_TRIGGER_HILEVEL:  		case XIRQ_TRIGGER_LOWLEVEL: -			set_irq_handler(XIRQ2IRQ(extnum), handle_level_irq); +			set_intr_postackable(XIRQ2IRQ(extnum));  			break;  		default:  			break; diff --git a/arch/powerpc/boot/dts/holly.dts b/arch/powerpc/boot/dts/holly.dts index f87fe7b9ced9..c6e11ebecebb 100644 --- a/arch/powerpc/boot/dts/holly.dts +++ b/arch/powerpc/boot/dts/holly.dts @@ -133,61 +133,61 @@  			reg = <0x00007400 0x00000400>;  			big-endian;  		}; +	}; -		pci@1000 { -			device_type = "pci"; -			compatible = "tsi109-pci", "tsi108-pci"; -			#interrupt-cells = <1>; -			#size-cells = <2>; -			#address-cells = <3>; -			reg = <0x00001000 0x00001000>; -			bus-range = <0x0 0x0>; -			/*----------------------------------------------------+ -			| PCI memory range. -			| 01 denotes I/O space -			| 02 denotes 32-bit memory space -			+----------------------------------------------------*/ -			ranges = <0x02000000 0x00000000 0x40000000 0x40000000 0x00000000 0x10000000 -				  0x01000000 0x00000000 0x00000000 0x7e000000 0x00000000 0x00010000>; -			clock-frequency = <133333332>; -			interrupt-parent = <&MPIC>; +	pci@c0001000 { +		device_type = "pci"; +		compatible = "tsi109-pci", "tsi108-pci"; +		#interrupt-cells = <1>; +		#size-cells = <2>; +		#address-cells = <3>; +		reg = <0xc0001000 0x00001000>; +		bus-range = <0x0 0x0>; +		/*----------------------------------------------------+ +		| PCI memory range. +		| 01 denotes I/O space +		| 02 denotes 32-bit memory space +		+----------------------------------------------------*/ +		ranges = <0x02000000 0x00000000 0x40000000 0x40000000 0x00000000 0x10000000 +			  0x01000000 0x00000000 0x00000000 0x7e000000 0x00000000 0x00010000>; +		clock-frequency = <133333332>; +		interrupt-parent = <&MPIC>; +		interrupts = <0x17 0x2>; +		interrupt-map-mask = <0xf800 0x0 0x0 0x7>; +		/*----------------------------------------------------+ +		| The INTA, INTB, INTC, INTD are shared. +		+----------------------------------------------------*/ +		interrupt-map = < +			0x800 0x0 0x0 0x1 &RT0 0x24 0x0 +			0x800 0x0 0x0 0x2 &RT0 0x25 0x0 +			0x800 0x0 0x0 0x3 &RT0 0x26 0x0 +			0x800 0x0 0x0 0x4 &RT0 0x27 0x0 + +			0x1000 0x0 0x0 0x1 &RT0 0x25 0x0 +			0x1000 0x0 0x0 0x2 &RT0 0x26 0x0 +			0x1000 0x0 0x0 0x3 &RT0 0x27 0x0 +			0x1000 0x0 0x0 0x4 &RT0 0x24 0x0 + +			0x1800 0x0 0x0 0x1 &RT0 0x26 0x0 +			0x1800 0x0 0x0 0x2 &RT0 0x27 0x0 +			0x1800 0x0 0x0 0x3 &RT0 0x24 0x0 +			0x1800 0x0 0x0 0x4 &RT0 0x25 0x0 + +			0x2000 0x0 0x0 0x1 &RT0 0x27 0x0 +			0x2000 0x0 0x0 0x2 &RT0 0x24 0x0 +			0x2000 0x0 0x0 0x3 &RT0 0x25 0x0 +			0x2000 0x0 0x0 0x4 &RT0 0x26 0x0 +			>; + +		RT0: router@1180 { +			device_type = "pic-router"; +			interrupt-controller; +			big-endian; +			clock-frequency = <0>; +			#address-cells = <0>; +			#interrupt-cells = <2>;  			interrupts = <0x17 0x2>; -			interrupt-map-mask = <0xf800 0x0 0x0 0x7>; -			/*----------------------------------------------------+ -			| The INTA, INTB, INTC, INTD are shared. -			+----------------------------------------------------*/ -			interrupt-map = < -				0x800 0x0 0x0 0x1 &RT0 0x24 0x0 -				0x800 0x0 0x0 0x2 &RT0 0x25 0x0 -				0x800 0x0 0x0 0x3 &RT0 0x26 0x0 -				0x800 0x0 0x0 0x4 &RT0 0x27 0x0 - -				0x1000 0x0 0x0 0x1 &RT0 0x25 0x0 -				0x1000 0x0 0x0 0x2 &RT0 0x26 0x0 -				0x1000 0x0 0x0 0x3 &RT0 0x27 0x0 -				0x1000 0x0 0x0 0x4 &RT0 0x24 0x0 - -				0x1800 0x0 0x0 0x1 &RT0 0x26 0x0 -				0x1800 0x0 0x0 0x2 &RT0 0x27 0x0 -				0x1800 0x0 0x0 0x3 &RT0 0x24 0x0 -				0x1800 0x0 0x0 0x4 &RT0 0x25 0x0 - -				0x2000 0x0 0x0 0x1 &RT0 0x27 0x0 -				0x2000 0x0 0x0 0x2 &RT0 0x24 0x0 -				0x2000 0x0 0x0 0x3 &RT0 0x25 0x0 -				0x2000 0x0 0x0 0x4 &RT0 0x26 0x0 -				>; - -			RT0: router@1180 { - 				device_type = "pic-router"; - 				interrupt-controller; - 				big-endian; - 				clock-frequency = <0>; - 				#address-cells = <0>; - 				#interrupt-cells = <2>; - 				interrupts = <0x17 0x2>; -				interrupt-parent = <&MPIC>; -			}; +			interrupt-parent = <&MPIC>;  		};  	}; diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index d308a9f70f1b..31982d05d81a 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -34,11 +34,7 @@  #include <asm/smp.h>  #ifdef CONFIG_HOTPLUG_CPU -/* this is used for software suspend, and that shuts down - * CPUs even while the system is still booting... */ -#define cpu_should_die()	(cpu_is_offline(smp_processor_id()) && \ -				   (system_state == SYSTEM_RUNNING     \ -				 || system_state == SYSTEM_BOOTING)) +#define cpu_should_die()	cpu_is_offline(smp_processor_id())  #else  #define cpu_should_die()	0  #endif diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c index ef74a0763ec1..8c619963becc 100644 --- a/arch/powerpc/platforms/fsl_uli1575.c +++ b/arch/powerpc/platforms/fsl_uli1575.c @@ -219,11 +219,21 @@ static void __devinit quirk_final_uli5249(struct pci_dev *dev)  	int i;  	u8 *dummy;  	struct pci_bus *bus = dev->bus; +	resource_size_t end = 0; + +	for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCES+3; i++) { +		unsigned long flags = pci_resource_flags(dev, i); +		if ((flags & (IORESOURCE_MEM|IORESOURCE_PREFETCH)) == IORESOURCE_MEM) +			end = pci_resource_end(dev, i); +	}  	for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {  		if ((bus->resource[i]) &&  			(bus->resource[i]->flags & IORESOURCE_MEM)) { -			dummy = ioremap(bus->resource[i]->end - 3, 0x4); +			if (bus->resource[i]->end == end) +				dummy = ioremap(bus->resource[i]->start, 0x4); +			else +				dummy = ioremap(bus->resource[i]->end - 3, 0x4);  			if (dummy) {  				in_8(dummy);  				iounmap(dummy); diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index ca114fe46ffb..06acb1a18bbc 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -169,6 +169,8 @@ void init_cpu_timer(void)  static void clock_comparator_interrupt(__u16 code)  { +	if (S390_lowcore.clock_comparator == -1ULL) +		set_clock_comparator(S390_lowcore.clock_comparator);  }  static void etr_timing_alert(struct etr_irq_parm *); diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index fc6ab6094df8..0953cee05efc 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c @@ -1,14 +1,9 @@  /* - *  arch/s390/lib/delay.c   *    Precise Delay Loops for S390   * - *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation - *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), - * - *  Derived from "arch/i386/lib/delay.c" - *    Copyright (C) 1993 Linus Torvalds - *    Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> + *    Copyright IBM Corp. 1999,2008 + *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>, + *		 Heiko Carstens <heiko.carstens@de.ibm.com>,   */  #include <linux/sched.h> @@ -29,30 +24,31 @@ void __delay(unsigned long loops)  	asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));  } -/* - * Waits for 'usecs' microseconds using the TOD clock comparator. - */ -void __udelay(unsigned long usecs) +static void __udelay_disabled(unsigned long usecs)  { -	u64 end, time, old_cc = 0; -	unsigned long flags, cr0, mask, dummy; -	int irq_context; +	unsigned long mask, cr0, cr0_saved; +	u64 clock_saved; -	irq_context = in_interrupt(); -	if (!irq_context) -		local_bh_disable(); -	local_irq_save(flags); -	if (raw_irqs_disabled_flags(flags)) { -		old_cc = local_tick_disable(); -		S390_lowcore.clock_comparator = -1ULL; -		__ctl_store(cr0, 0, 0); -		dummy = (cr0 & 0xffff00e0) | 0x00000800; -		__ctl_load(dummy , 0, 0); -		mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; -	} else -		mask = psw_kernel_bits | PSW_MASK_WAIT | -			PSW_MASK_EXT | PSW_MASK_IO; +	clock_saved = local_tick_disable(); +	set_clock_comparator(get_clock() + ((u64) usecs << 12)); +	__ctl_store(cr0_saved, 0, 0); +	cr0 = (cr0_saved & 0xffff00e0) | 0x00000800; +	__ctl_load(cr0 , 0, 0); +	mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; +	trace_hardirqs_on(); +	__load_psw_mask(mask); +	local_irq_disable(); +	__ctl_load(cr0_saved, 0, 0); +	local_tick_enable(clock_saved); +	set_clock_comparator(S390_lowcore.clock_comparator); +} +static void __udelay_enabled(unsigned long usecs) +{ +	unsigned long mask; +	u64 end, time; + +	mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT | PSW_MASK_IO;  	end = get_clock() + ((u64) usecs << 12);  	do {  		time = end < S390_lowcore.clock_comparator ? @@ -62,13 +58,37 @@ void __udelay(unsigned long usecs)  		__load_psw_mask(mask);  		local_irq_disable();  	} while (get_clock() < end); +	set_clock_comparator(S390_lowcore.clock_comparator); +} -	if (raw_irqs_disabled_flags(flags)) { -		__ctl_load(cr0, 0, 0); -		local_tick_enable(old_cc); +/* + * Waits for 'usecs' microseconds using the TOD clock comparator. + */ +void __udelay(unsigned long usecs) +{ +	unsigned long flags; + +	preempt_disable(); +	local_irq_save(flags); +	if (in_irq()) { +		__udelay_disabled(usecs); +		goto out; +	} +	if (in_softirq()) { +		if (raw_irqs_disabled_flags(flags)) +			__udelay_disabled(usecs); +		else +			__udelay_enabled(usecs); +		goto out;  	} -	if (!irq_context) +	if (raw_irqs_disabled_flags(flags)) { +		local_bh_disable(); +		__udelay_disabled(usecs);  		_local_bh_enable(); -	set_clock_comparator(S390_lowcore.clock_comparator); +		goto out; +	} +	__udelay_enabled(usecs); +out:  	local_irq_restore(flags); +	preempt_enable();  } diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/boot/compressed/relocs.c index a1310c52fc0c..857e492c571e 100644 --- a/arch/x86/boot/compressed/relocs.c +++ b/arch/x86/boot/compressed/relocs.c @@ -492,7 +492,7 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))  			continue;  		}  		sh_symtab = sec_symtab->symtab; -		sym_strtab = sec->link->strtab; +		sym_strtab = sec_symtab->link->strtab;  		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {  			Elf32_Rel *rel;  			Elf32_Sym *sym; diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index bfd10fd211cd..c102af85df9c 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1605,6 +1605,14 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {  	 */  	{  	 .callback = dmi_ignore_irq0_timer_override, +	 .ident = "HP nx6115 laptop", +	 .matches = { +		     DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), +		     DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6115"), +		     }, +	 }, +	{ +	 .callback = dmi_ignore_irq0_timer_override,  	 .ident = "HP NX6125 laptop",  	 .matches = {  		     DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), @@ -1619,6 +1627,14 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {  		     DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"),  		     },  	 }, +	{ +	 .callback = dmi_ignore_irq0_timer_override, +	 .ident = "HP 6715b laptop", +	 .matches = { +		     DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), +		     DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6715b"), +		     }, +	 },  	{}  }; diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index b117d7f8a564..885c8265e6b5 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -834,7 +834,7 @@ static int __init enable_mtrr_cleanup_setup(char *str)  		enable_mtrr_cleanup = 1;  	return 0;  } -early_param("enble_mtrr_cleanup", enable_mtrr_cleanup_setup); +early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup);  struct var_mtrr_state {  	unsigned long	range_startk; diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 8282a2139681..10435a120d22 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -455,12 +455,7 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)  		return NOTIFY_DONE;  	case DIE_NMI_IPI: -		if (atomic_read(&kgdb_active) != -1) { -			/* KGDB CPU roundup */ -			kgdb_nmicallback(raw_smp_processor_id(), regs); -			was_in_debug_nmi[raw_smp_processor_id()] = 1; -			touch_nmi_watchdog(); -		} +		/* Just ignore, we will handle the roundup on DIE_NMI. */  		return NOTIFY_DONE;  	case DIE_NMIUNKNOWN: diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 49285f8fd4d5..be33a5442d82 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -626,7 +626,6 @@ static __init int init_k8_gatt(struct agp_kern_info *info)  	struct pci_dev *dev;  	void *gatt;  	int i, error; -	unsigned long start_pfn, end_pfn;  	printk(KERN_INFO "PCI-DMA: Disabling AGP.\n");  	aper_size = aper_base = info->aper_size = 0; @@ -672,12 +671,6 @@ static __init int init_k8_gatt(struct agp_kern_info *info)  	printk(KERN_INFO "PCI-DMA: aperture base @ %x size %u KB\n",  	       aper_base, aper_size>>10); -	/* need to map that range */ -	end_pfn = (aper_base>>PAGE_SHIFT) + (aper_size>>PAGE_SHIFT); -	if (end_pfn > max_low_pfn_mapped) { -		start_pfn = (aper_base>>PAGE_SHIFT); -		init_memory_mapping(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); -	}  	return 0;   nommu: @@ -727,7 +720,8 @@ void __init gart_iommu_init(void)  {  	struct agp_kern_info info;  	unsigned long iommu_start; -	unsigned long aper_size; +	unsigned long aper_base, aper_size; +	unsigned long start_pfn, end_pfn;  	unsigned long scratch;  	long i; @@ -765,8 +759,16 @@ void __init gart_iommu_init(void)  		return;  	} +	/* need to map that range */ +	aper_size = info.aper_size << 20; +	aper_base = info.aper_base; +	end_pfn = (aper_base>>PAGE_SHIFT) + (aper_size>>PAGE_SHIFT); +	if (end_pfn > max_low_pfn_mapped) { +		start_pfn = (aper_base>>PAGE_SHIFT); +		init_memory_mapping(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); +	} +  	printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n"); -	aper_size = info.aper_size * 1024 * 1024;  	iommu_size = check_iommu_size(info.aper_base, aper_size);  	iommu_pages = iommu_size >> PAGE_SHIFT; diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c index 6ca515d6db54..edfb09f30479 100644 --- a/arch/x86/kernel/vmi_32.c +++ b/arch/x86/kernel/vmi_32.c @@ -235,7 +235,7 @@ static void vmi_write_ldt_entry(struct desc_struct *dt, int entry,  				const void *desc)  {  	u32 *ldt_entry = (u32 *)desc; -	vmi_ops.write_idt_entry(dt, entry, ldt_entry[0], ldt_entry[1]); +	vmi_ops.write_ldt_entry(dt, entry, ldt_entry[0], ldt_entry[1]);  }  static void vmi_load_sp0(struct tss_struct *tss, diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c index 0a5f6b2114c5..d672cfe7ca59 100644 --- a/drivers/accessibility/braille/braille_console.c +++ b/drivers/accessibility/braille/braille_console.c @@ -376,6 +376,8 @@ int braille_register_console(struct console *console, int index,  	console->flags |= CON_ENABLED;  	console->index = index;  	braille_co = console; +	register_keyboard_notifier(&keyboard_notifier_block); +	register_vt_notifier(&vt_notifier_block);  	return 0;  } @@ -383,15 +385,8 @@ int braille_unregister_console(struct console *console)  {  	if (braille_co != console)  		return -EINVAL; +	unregister_keyboard_notifier(&keyboard_notifier_block); +	unregister_vt_notifier(&vt_notifier_block);  	braille_co = NULL;  	return 0;  } - -static int __init braille_init(void) -{ -	register_keyboard_notifier(&keyboard_notifier_block); -	register_vt_notifier(&vt_notifier_block); -	return 0; -} - -console_initcall(braille_init); diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 084109507c9f..8dd3336efd7e 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -165,8 +165,11 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)  				"firmware_node");  		ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,  				"physical_node"); -		if (acpi_dev->wakeup.flags.valid) +		if (acpi_dev->wakeup.flags.valid) {  			device_set_wakeup_capable(dev, true); +			device_set_wakeup_enable(dev, +						acpi_dev->wakeup.state.enabled); +		}  	}  	return 0; diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 4ebbba2b6b19..bf5b04de02d1 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -377,6 +377,14 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)  	return 0;  } +static void physical_device_enable_wakeup(struct acpi_device *adev) +{ +	struct device *dev = acpi_get_physical_device(adev->handle); + +	if (dev && device_can_wakeup(dev)) +		device_set_wakeup_enable(dev, adev->wakeup.state.enabled); +} +  static ssize_t  acpi_system_write_wakeup_device(struct file *file,  				const char __user * buffer, @@ -411,6 +419,7 @@ acpi_system_write_wakeup_device(struct file *file,  		}  	}  	if (found_dev) { +		physical_device_enable_wakeup(found_dev);  		list_for_each_safe(node, next, &acpi_wakeup_device_list) {  			struct acpi_device *dev = container_of(node,  							       struct @@ -428,6 +437,7 @@ acpi_system_write_wakeup_device(struct file *file,  				       dev->pnp.bus_id, found_dev->pnp.bus_id);  				dev->wakeup.state.enabled =  				    found_dev->wakeup.state.enabled; +				physical_device_enable_wakeup(dev);  			}  		}  	} diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 1e55a658e6ce..32f3a8ed8d3d 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -256,7 +256,6 @@ static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)  		BT_ERR("%s urb %p submission failed (%d)",  						hdev->name, urb, -err);  		usb_unanchor_urb(urb); -		kfree(buf);  	}  	usb_free_urb(urb); @@ -298,7 +297,6 @@ static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)  		BT_ERR("%s urb %p submission failed (%d)",  						hdev->name, urb, -err);  		usb_unanchor_urb(urb); -		kfree(buf);  	}  	usb_free_urb(urb); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 29ae99817c60..af472e052732 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -102,6 +102,7 @@ static struct usb_device_id blacklist_table[] = {  	{ USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },  	/* Broadcom BCM2046 */ +	{ USB_DEVICE(0x0a5c, 0x2146), .driver_info = BTUSB_RESET },  	{ USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET },  	/* Apple MacBook Pro with Broadcom chip */ @@ -113,6 +114,7 @@ static struct usb_device_id blacklist_table[] = {  	/* Targus ACB10US */  	{ USB_DEVICE(0x0a5c, 0x2100), .driver_info = BTUSB_RESET }, +	{ USB_DEVICE(0x0a5c, 0x2154), .driver_info = BTUSB_RESET },  	/* ANYCOM Bluetooth USB-200 and USB-250 */  	{ USB_DEVICE(0x0a5c, 0x2111), .driver_info = BTUSB_RESET }, @@ -150,6 +152,9 @@ static struct usb_device_id blacklist_table[] = {  	{ USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },  	{ USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, +	/* Belkin F8T016 device */ +	{ USB_DEVICE(0x050d, 0x016a), .driver_info = BTUSB_RESET }, +  	/* Digianswer devices */  	{ USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },  	{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE }, @@ -271,7 +276,6 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev)  		BT_ERR("%s urb %p submission failed (%d)",  						hdev->name, urb, -err);  		usb_unanchor_urb(urb); -		kfree(buf);  	}  	usb_free_urb(urb); @@ -354,7 +358,6 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev)  		BT_ERR("%s urb %p submission failed (%d)",  						hdev->name, urb, -err);  		usb_unanchor_urb(urb); -		kfree(buf);  	}  	usb_free_urb(urb); @@ -475,7 +478,6 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev)  		BT_ERR("%s urb %p submission failed (%d)",  						hdev->name, urb, -err);  		usb_unanchor_urb(urb); -		kfree(buf);  	}  	usb_free_urb(urb); diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 94df91771243..0778d99aea7c 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -364,7 +364,7 @@ static void dw_dma_tasklet(unsigned long data)  	int i;  	status_block = dma_readl(dw, RAW.BLOCK); -	status_xfer = dma_readl(dw, RAW.BLOCK); +	status_xfer = dma_readl(dw, RAW.XFER);  	status_err = dma_readl(dw, RAW.ERROR);  	dev_vdbg(dw->dma.dev, "tasklet: status_block=%x status_err=%x\n", diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 8e93a797c93d..052879a6f853 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -780,10 +780,6 @@ config BLK_DEV_IDEDMA_PMAC  	  to transfer data to and from memory.  Saying Y is safe and improves  	  performance. -config BLK_DEV_IDE_SWARM -	tristate "IDE for Sibyte evaluation boards" -	depends on SIBYTE_SB1xxx_SOC -  config BLK_DEV_IDE_AU1XXX         bool "IDE for AMD Alchemy Au1200"         depends on SOC_AU1200 diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 49a8c589e346..f16bb4667238 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1661,7 +1661,9 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)  		cdi->mask &= ~CDC_PLAY_AUDIO;  	mechtype = buf[8 + 6] >> 5; -	if (mechtype == mechtype_caddy || mechtype == mechtype_popup) +	if (mechtype == mechtype_caddy || +	    mechtype == mechtype_popup || +	    (drive->atapi_flags & IDE_AFLAG_NO_AUTOCLOSE))  		cdi->mask |= CDC_CLOSE_TRAY;  	if (cdi->sanyo_slot > 0) { @@ -1859,6 +1861,8 @@ static const struct cd_list_entry ide_cd_quirks_list[] = {  	{ "MATSHITADVD-ROM SR-8176", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },  	{ "MATSHITADVD-ROM SR-8174", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },  	{ "Optiarc DVD RW AD-5200A", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     }, +	{ "Optiarc DVD RW AD-7200A", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     }, +	{ "Optiarc DVD RW AD-7543A", NULL,   IDE_AFLAG_NO_AUTOCLOSE	     },  	{ NULL, NULL, 0 }  }; diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index adc682755857..3fa07c0aeaa4 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -211,7 +211,7 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq)  				xcount = bcount & 0xffff;  				if (is_trm290)  					xcount = ((xcount >> 2) - 1) << 16; -				if (xcount == 0x0000) { +				else if (xcount == 0x0000) {  	/*   	 * Most chipsets correctly interpret a length of 0x0000 as 64KB,  	 * but at least one (e.g. CS5530) misinterprets it as zero (!). diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 994e41099b42..a51a30e9eab3 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1492,7 +1492,7 @@ static struct device_attribute *ide_port_attrs[] = {  static int ide_sysfs_register_port(ide_hwif_t *hwif)  { -	int i, rc; +	int i, uninitialized_var(rc);  	for (i = 0; ide_port_attrs[i]; i++) {  		rc = device_create_file(hwif->portdev, ide_port_attrs[i]); diff --git a/drivers/ide/mips/Makefile b/drivers/ide/mips/Makefile index 677c7b2bac92..5873fa0b8769 100644 --- a/drivers/ide/mips/Makefile +++ b/drivers/ide/mips/Makefile @@ -1,4 +1,3 @@ -obj-$(CONFIG_BLK_DEV_IDE_SWARM)		+= swarm.o  obj-$(CONFIG_BLK_DEV_IDE_AU1XXX)	+= au1xxx-ide.o  EXTRA_CFLAGS    := -Idrivers/ide diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c deleted file mode 100644 index 39c9ee995857..000000000000 --- a/drivers/ide/mips/swarm.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2001, 2002, 2003 Broadcom Corporation - * Copyright (C) 2004 MontaVista Software Inc. - *	Author:	Manish Lachwani, mlachwani@mvista.com - * Copyright (C) 2004  MIPS Technologies, Inc.  All rights reserved. - *	Author: Maciej W. Rozycki <macro@mips.com> - * Copyright (c) 2006, 2008  Maciej W. Rozycki - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. - */ - -/* - *  Derived loosely from ide-pmac.c, so: - *  Copyright (C) 1998 Paul Mackerras. - *  Copyright (C) 1995-1998 Mark Lord - */ - -/* - * Boards with SiByte processors so far have supported IDE devices via - * the Generic Bus, PCI bus, and built-in PCMCIA interface.  In all - * cases, byte-swapping must be avoided for these devices (whereas - * other PCI devices, for example, will require swapping).  Any - * SiByte-targetted kernel including IDE support will include this - * file.  Probing of a Generic Bus for an IDE device is controlled by - * the definition of "SIBYTE_HAVE_IDE", which is provided by - * <asm/sibyte/board.h> for Broadcom boards. - */ - -#include <linux/ide.h> -#include <linux/ioport.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/platform_device.h> - -#include <asm/io.h> - -#include <asm/sibyte/board.h> -#include <asm/sibyte/sb1250_genbus.h> -#include <asm/sibyte/sb1250_regs.h> - -#define DRV_NAME "ide-swarm" - -static char swarm_ide_string[] = DRV_NAME; - -static struct resource swarm_ide_resource = { -	.name	= "SWARM GenBus IDE", -	.flags	= IORESOURCE_MEM, -}; - -static struct platform_device *swarm_ide_dev; - -static const struct ide_port_info swarm_port_info = { -	.name			= DRV_NAME, -	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, -}; - -/* - * swarm_ide_probe - if the board header indicates the existence of - * Generic Bus IDE, allocate a HWIF for it. - */ -static int __devinit swarm_ide_probe(struct device *dev) -{ -	u8 __iomem *base; -	struct ide_host *host; -	phys_t offset, size; -	int i, rc; -	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; - -	if (!SIBYTE_HAVE_IDE) -		return -ENODEV; - -	base = ioremap(A_IO_EXT_BASE, 0x800); -	offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS)); -	size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS)); -	iounmap(base); - -	offset = G_IO_START_ADDR(offset) << S_IO_ADDRBASE; -	size = (G_IO_MULT_SIZE(size) + 1) << S_IO_REGSIZE; -	if (offset < A_PHYS_GENBUS || offset >= A_PHYS_GENBUS_END) { -		printk(KERN_INFO DRV_NAME -		       ": IDE interface at GenBus disabled\n"); -		return -EBUSY; -	} - -	printk(KERN_INFO DRV_NAME ": IDE interface at GenBus slot %i\n", -	       IDE_CS); - -	swarm_ide_resource.start = offset; -	swarm_ide_resource.end = offset + size - 1; -	if (request_resource(&iomem_resource, &swarm_ide_resource)) { -		printk(KERN_ERR DRV_NAME -		       ": can't request I/O memory resource\n"); -		return -EBUSY; -	} - -	base = ioremap(offset, size); - -	memset(&hw, 0, sizeof(hw)); -	for (i = 0; i <= 7; i++) -		hw.io_ports_array[i] = -				(unsigned long)(base + ((0x1f0 + i) << 5)); -	hw.io_ports.ctl_addr = -				(unsigned long)(base + (0x3f6 << 5)); -	hw.irq = K_INT_GB_IDE; -	hw.chipset = ide_generic; - -	rc = ide_host_add(&swarm_port_info, hws, &host); -	if (rc) -		goto err; - -	dev_set_drvdata(dev, host); - -	return 0; -err: -	release_resource(&swarm_ide_resource); -	iounmap(base); -	return rc; -} - -static struct device_driver swarm_ide_driver = { -	.name	= swarm_ide_string, -	.bus	= &platform_bus_type, -	.probe	= swarm_ide_probe, -}; - -static void swarm_ide_platform_release(struct device *device) -{ -	struct platform_device *pldev; - -	/* free device */ -	pldev = to_platform_device(device); -	kfree(pldev); -} - -static int __devinit swarm_ide_init_module(void) -{ -	struct platform_device *pldev; -	int err; - -	printk(KERN_INFO "SWARM IDE driver\n"); - -	if (driver_register(&swarm_ide_driver)) { -		printk(KERN_ERR "Driver registration failed\n"); -		err = -ENODEV; -		goto out; -	} - -        if (!(pldev = kzalloc(sizeof (*pldev), GFP_KERNEL))) { -		err = -ENOMEM; -		goto out_unregister_driver; -	} - -	pldev->name		= swarm_ide_string; -	pldev->id		= 0; -	pldev->dev.release	= swarm_ide_platform_release; - -	if (platform_device_register(pldev)) { -		err = -ENODEV; -		goto out_free_pldev; -	} - -        if (!pldev->dev.driver) { -		/* -		 * The driver was not bound to this device, there was -                 * no hardware at this address. Unregister it, as the -		 * release fuction will take care of freeing the -		 * allocated structure -		 */ -		platform_device_unregister (pldev); -	} - -	swarm_ide_dev = pldev; - -	return 0; - -out_free_pldev: -	kfree(pldev); - -out_unregister_driver: -	driver_unregister(&swarm_ide_driver); -out: -	return err; -} - -module_init(swarm_ide_init_module); diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c index be0e12144b8b..34935155c1c0 100644 --- a/drivers/leds/leds-fsg.c +++ b/drivers/leds/leds-fsg.c @@ -161,6 +161,16 @@ static int fsg_led_probe(struct platform_device *pdev)  {  	int ret; +	/* Map the LED chip select address space */ +	latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512); +	if (!latch_address) { +		ret = -ENOMEM; +		goto failremap; +	} + +	latch_value = 0xffff; +	*latch_address = latch_value; +  	ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);  	if (ret < 0)  		goto failwlan; @@ -185,20 +195,8 @@ static int fsg_led_probe(struct platform_device *pdev)  	if (ret < 0)  		goto failring; -	/* Map the LED chip select address space */ -	latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512); -	if (!latch_address) { -		ret = -ENOMEM; -		goto failremap; -	} - -	latch_value = 0xffff; -	*latch_address = latch_value; -  	return ret; - failremap: -	led_classdev_unregister(&fsg_ring_led);   failring:  	led_classdev_unregister(&fsg_sync_led);   failsync: @@ -210,14 +208,14 @@ static int fsg_led_probe(struct platform_device *pdev)   failwan:  	led_classdev_unregister(&fsg_wlan_led);   failwlan: +	iounmap(latch_address); + failremap:  	return ret;  }  static int fsg_led_remove(struct platform_device *pdev)  { -	iounmap(latch_address); -  	led_classdev_unregister(&fsg_wlan_led);  	led_classdev_unregister(&fsg_wan_led);  	led_classdev_unregister(&fsg_sata_led); @@ -225,6 +223,8 @@ static int fsg_led_remove(struct platform_device *pdev)  	led_classdev_unregister(&fsg_sync_led);  	led_classdev_unregister(&fsg_ring_led); +	iounmap(latch_address); +  	return 0;  } diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index 146c06972863..f508729123b5 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c @@ -248,11 +248,10 @@ static int __devinit pca955x_probe(struct i2c_client *client,  					const struct i2c_device_id *id)  {  	struct pca955x_led *pca955x; -	int i; -	int err = -ENODEV;  	struct pca955x_chipdef *chip;  	struct i2c_adapter *adapter;  	struct led_platform_data *pdata; +	int i, err;  	chip = &pca955x_chipdefs[id->driver_data];  	adapter = to_i2c_adapter(client->dev.parent); @@ -282,43 +281,41 @@ static int __devinit pca955x_probe(struct i2c_client *client,  		}  	} +	pca955x = kzalloc(sizeof(*pca955x) * chip->bits, GFP_KERNEL); +	if (!pca955x) +		return -ENOMEM; + +	i2c_set_clientdata(client, pca955x); +  	for (i = 0; i < chip->bits; i++) { -		pca955x = kzalloc(sizeof(struct pca955x_led), GFP_KERNEL); -		if (!pca955x) { -			err = -ENOMEM; -			goto exit; -		} +		pca955x[i].chipdef = chip; +		pca955x[i].client = client; +		pca955x[i].led_num = i; -		pca955x->chipdef = chip; -		pca955x->client = client; -		pca955x->led_num = i;  		/* Platform data can specify LED names and default triggers */  		if (pdata) {  			if (pdata->leds[i].name) -				snprintf(pca955x->name, 32, "pca955x:%s", -							pdata->leds[i].name); +				snprintf(pca955x[i].name, +					 sizeof(pca955x[i].name), "pca955x:%s", +					 pdata->leds[i].name);  			if (pdata->leds[i].default_trigger) -				pca955x->led_cdev.default_trigger = +				pca955x[i].led_cdev.default_trigger =  					pdata->leds[i].default_trigger;  		} else { -			snprintf(pca955x->name, 32, "pca955x:%d", i); +			snprintf(pca955x[i].name, sizeof(pca955x[i].name), +				 "pca955x:%d", i);  		} -		spin_lock_init(&pca955x->lock); -		pca955x->led_cdev.name = pca955x->name; -		pca955x->led_cdev.brightness_set = -				pca955x_led_set; +		spin_lock_init(&pca955x[i].lock); -		/* -		 * Client data is a pointer to the _first_ pca955x_led -		 * struct -		 */ -		if (i == 0) -			i2c_set_clientdata(client, pca955x); +		pca955x[i].led_cdev.name = pca955x[i].name; +		pca955x[i].led_cdev.brightness_set = pca955x_led_set; -		INIT_WORK(&(pca955x->work), pca955x_led_work); +		INIT_WORK(&pca955x[i].work, pca955x_led_work); -		led_classdev_register(&client->dev, &(pca955x->led_cdev)); +		err = led_classdev_register(&client->dev, &pca955x[i].led_cdev); +		if (err < 0) +			goto exit;  	}  	/* Turn off LEDs */ @@ -336,23 +333,32 @@ static int __devinit pca955x_probe(struct i2c_client *client,  	pca955x_write_psc(client, 1, 0);  	return 0; +  exit: +	while (i--) { +		led_classdev_unregister(&pca955x[i].led_cdev); +		cancel_work_sync(&pca955x[i].work); +	} + +	kfree(pca955x); +	i2c_set_clientdata(client, NULL); +  	return err;  }  static int __devexit pca955x_remove(struct i2c_client *client)  {  	struct pca955x_led *pca955x = i2c_get_clientdata(client); -	int leds = pca955x->chipdef->bits;  	int i; -	for (i = 0; i < leds; i++) { -		led_classdev_unregister(&(pca955x->led_cdev)); -		cancel_work_sync(&(pca955x->work)); -		kfree(pca955x); -		pca955x = pca955x + 1; +	for (i = 0; i < pca955x->chipdef->bits; i++) { +		led_classdev_unregister(&pca955x[i].led_cdev); +		cancel_work_sync(&pca955x[i].work);  	} +	kfree(pca955x); +	i2c_set_clientdata(client, NULL); +  	return 0;  } diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 71dd65aa31b6..c2fcf28b4c70 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -63,6 +63,7 @@ struct multipath {  	const char *hw_handler_name;  	struct work_struct activate_path; +	struct pgpath *pgpath_to_activate;  	unsigned nr_priority_groups;  	struct list_head priority_groups;  	unsigned pg_init_required;	/* pg_init needs calling? */ @@ -146,6 +147,7 @@ static struct priority_group *alloc_priority_group(void)  static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)  { +	unsigned long flags;  	struct pgpath *pgpath, *tmp;  	struct multipath *m = ti->private; @@ -154,6 +156,10 @@ static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)  		if (m->hw_handler_name)  			scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));  		dm_put_device(ti, pgpath->path.dev); +		spin_lock_irqsave(&m->lock, flags); +		if (m->pgpath_to_activate == pgpath) +			m->pgpath_to_activate = NULL; +		spin_unlock_irqrestore(&m->lock, flags);  		free_pgpath(pgpath);  	}  } @@ -421,6 +427,7 @@ static void process_queued_ios(struct work_struct *work)  		__choose_pgpath(m);  	pgpath = m->current_pgpath; +	m->pgpath_to_activate = m->current_pgpath;  	if ((pgpath && !m->queue_io) ||  	    (!pgpath && !m->queue_if_no_path)) @@ -1093,8 +1100,15 @@ static void activate_path(struct work_struct *work)  	int ret;  	struct multipath *m =  		container_of(work, struct multipath, activate_path); -	struct dm_path *path = &m->current_pgpath->path; +	struct dm_path *path; +	unsigned long flags; +	spin_lock_irqsave(&m->lock, flags); +	path = &m->pgpath_to_activate->path; +	m->pgpath_to_activate = NULL; +	spin_unlock_irqrestore(&m->lock, flags); +	if (!path) +		return;  	ret = scsi_dh_activate(bdev_get_queue(path->dev->bdev));  	pg_init_done(path, ret);  } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index bca448e11878..ace998ce59f6 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -837,12 +837,14 @@ static int dm_merge_bvec(struct request_queue *q,  	struct dm_table *map = dm_get_table(md);  	struct dm_target *ti;  	sector_t max_sectors; -	int max_size; +	int max_size = 0;  	if (unlikely(!map)) -		return 0; +		goto out;  	ti = dm_table_find_target(map, bvm->bi_sector); +	if (!dm_target_is_valid(ti)) +		goto out_table;  	/*  	 * Find maximum amount of I/O that won't need splitting @@ -861,14 +863,16 @@ static int dm_merge_bvec(struct request_queue *q,  	if (max_size && ti->type->merge)  		max_size = ti->type->merge(ti, bvm, biovec, max_size); +out_table: +	dm_table_put(map); + +out:  	/*  	 * Always allow an entire first page  	 */  	if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))  		max_size = biovec->bv_len; -	dm_table_put(map); -  	return max_size;  } diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/common/tuners/tuner-xc2028.h index 216025cf5d4b..2c5b6282b569 100644 --- a/drivers/media/common/tuners/tuner-xc2028.h +++ b/drivers/media/common/tuners/tuner-xc2028.h @@ -10,6 +10,7 @@  #include "dvb_frontend.h"  #define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw" +#define XC3028L_DEFAULT_FIRMWARE "xc3028L-v36.fw"  /*      Dmoduler		IF (kHz) */  #define	XC3028_FE_DEFAULT	0		/* Don't load SCODE */ diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 4eed783f4bce..a127a4175c40 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -491,6 +491,7 @@ static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {  	.demod_address = 0x53,  	.invert = 1,  	.repeated_start_workaround = 1, +	.serial_mpeg = 1,  };  static struct itd1000_config skystar2_rev2_7_itd1000_config = { diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 069d847ba887..0c733c66a441 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -364,15 +364,16 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,  				       enum dmx_success success)  {  	struct dmxdev_filter *dmxdevfilter = filter->priv; +	unsigned long flags;  	int ret;  	if (dmxdevfilter->buffer.error) {  		wake_up(&dmxdevfilter->buffer.queue);  		return 0;  	} -	spin_lock(&dmxdevfilter->dev->lock); +	spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);  	if (dmxdevfilter->state != DMXDEV_STATE_GO) { -		spin_unlock(&dmxdevfilter->dev->lock); +		spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);  		return 0;  	}  	del_timer(&dmxdevfilter->timer); @@ -391,7 +392,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,  	}  	if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)  		dmxdevfilter->state = DMXDEV_STATE_DONE; -	spin_unlock(&dmxdevfilter->dev->lock); +	spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);  	wake_up(&dmxdevfilter->buffer.queue);  	return 0;  } @@ -403,11 +404,12 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,  {  	struct dmxdev_filter *dmxdevfilter = feed->priv;  	struct dvb_ringbuffer *buffer; +	unsigned long flags;  	int ret; -	spin_lock(&dmxdevfilter->dev->lock); +	spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);  	if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) { -		spin_unlock(&dmxdevfilter->dev->lock); +		spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);  		return 0;  	} @@ -417,7 +419,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,  	else  		buffer = &dmxdevfilter->dev->dvr_buffer;  	if (buffer->error) { -		spin_unlock(&dmxdevfilter->dev->lock); +		spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);  		wake_up(&buffer->queue);  		return 0;  	} @@ -428,7 +430,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,  		dvb_ringbuffer_flush(buffer);  		buffer->error = ret;  	} -	spin_unlock(&dmxdevfilter->dev->lock); +	spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);  	wake_up(&buffer->queue);  	return 0;  } diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index e2eca0b1fe7c..a2c1fd5d2f67 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -399,7 +399,9 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)  void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,  			      size_t count)  { -	spin_lock(&demux->lock); +	unsigned long flags; + +	spin_lock_irqsave(&demux->lock, flags);  	while (count--) {  		if (buf[0] == 0x47) @@ -407,16 +409,17 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,  		buf += 188;  	} -	spin_unlock(&demux->lock); +	spin_unlock_irqrestore(&demux->lock, flags);  }  EXPORT_SYMBOL(dvb_dmx_swfilter_packets);  void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)  { +	unsigned long flags;  	int p = 0, i, j; -	spin_lock(&demux->lock); +	spin_lock_irqsave(&demux->lock, flags);  	if (demux->tsbufp) {  		i = demux->tsbufp; @@ -449,17 +452,18 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)  	}  bailout: -	spin_unlock(&demux->lock); +	spin_unlock_irqrestore(&demux->lock, flags);  }  EXPORT_SYMBOL(dvb_dmx_swfilter);  void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)  { +	unsigned long flags;  	int p = 0, i, j;  	u8 tmppack[188]; -	spin_lock(&demux->lock); +	spin_lock_irqsave(&demux->lock, flags);  	if (demux->tsbufp) {  		i = demux->tsbufp; @@ -500,7 +504,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)  	}  bailout: -	spin_unlock(&demux->lock); +	spin_unlock_irqrestore(&demux->lock, flags);  }  EXPORT_SYMBOL(dvb_dmx_swfilter_204); diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c index 747d3fa2e5e5..2e9fd2893ede 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb/frontends/s5h1420.c @@ -59,7 +59,7 @@ struct s5h1420_state {  	 * it does not support repeated-start, workaround: write addr-1  	 * and then read  	 */ -	u8 shadow[255]; +	u8 shadow[256];  };  static u32 s5h1420_getsymbolrate(struct s5h1420_state* state); @@ -94,8 +94,11 @@ static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)  		if (ret != 3)  			return ret;  	} else { -		ret = i2c_transfer(state->i2c, &msg[1], 2); -		if (ret != 2) +		ret = i2c_transfer(state->i2c, &msg[1], 1); +		if (ret != 1) +			return ret; +		ret = i2c_transfer(state->i2c, &msg[2], 1); +		if (ret != 1)  			return ret;  	} @@ -823,7 +826,7 @@ static int s5h1420_init (struct dvb_frontend* fe)  	struct s5h1420_state* state = fe->demodulator_priv;  	/* disable power down and do reset */ -	state->CON_1_val = 0x10; +	state->CON_1_val = state->config->serial_mpeg << 4;  	s5h1420_writereg(state, 0x02, state->CON_1_val);  	msleep(10);  	s5h1420_reset(state); diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h index 4c913f142bc4..ff308136d865 100644 --- a/drivers/media/dvb/frontends/s5h1420.h +++ b/drivers/media/dvb/frontends/s5h1420.h @@ -32,10 +32,12 @@ struct s5h1420_config  	u8 demod_address;  	/* does the inversion require inversion? */ -	u8 invert : 1; +	u8 invert:1; -	u8 repeated_start_workaround : 1; -	u8 cdclk_polarity : 1; /* 1 == falling edge, 0 == raising edge */ +	u8 repeated_start_workaround:1; +	u8 cdclk_polarity:1; /* 1 == falling edge, 0 == raising edge */ + +	u8 serial_mpeg:1;  };  #if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE)) diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c index cc5efb643f33..9da260fe3fd1 100644 --- a/drivers/media/dvb/siano/sms-cards.c +++ b/drivers/media/dvb/siano/sms-cards.c @@ -40,6 +40,8 @@ struct usb_device_id smsusb_id_table[] = {  		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },  	{ USB_DEVICE(0x2040, 0x5500),  		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, +	{ USB_DEVICE(0x2040, 0x5510), +		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },  	{ USB_DEVICE(0x2040, 0x5580),  		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },  	{ USB_DEVICE(0x2040, 0x5590), @@ -87,7 +89,7 @@ static struct sms_board sms_boards[] = {  		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",  	},  	[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = { -		.name	= "Hauppauge WinTV-Nova-T-MiniStick", +		.name	= "Hauppauge WinTV MiniStick",  		.type	= SMS_NOVA_B0,  		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw",  	}, diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 6ae4cc860efe..933eaef41ead 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3431,7 +3431,7 @@ static int radio_open(struct inode *inode, struct file *file)  	dprintk("bttv: open minor=%d\n",minor);  	for (i = 0; i < bttv_num; i++) { -		if (bttvs[i].radio_dev->minor == minor) { +		if (bttvs[i].radio_dev && bttvs[i].radio_dev->minor == minor) {  			btv = &bttvs[i];  			break;  		} diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index c149b7d712e5..5405c30dbb04 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -19,6 +19,7 @@  #include <linux/module.h>  #include <linux/init.h>  #include <linux/fs.h> +#include <linux/mm.h>  #include <linux/pci.h>  #include <linux/i2c.h>  #include <linux/interrupt.h> diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c index a4574740350d..a8a199047cbd 100644 --- a/drivers/media/video/cpia2/cpia2_usb.c +++ b/drivers/media/video/cpia2/cpia2_usb.c @@ -632,7 +632,7 @@ int cpia2_usb_transfer_cmd(struct camera_data *cam,  static int submit_urbs(struct camera_data *cam)  {  	struct urb *urb; -	int fx, err, i; +	int fx, err, i, j;  	for(i=0; i<NUM_SBUF; ++i) {  		if (cam->sbuf[i].data) @@ -657,6 +657,9 @@ static int submit_urbs(struct camera_data *cam)  		}  		urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);  		if (!urb) { +			ERR("%s: usb_alloc_urb error!\n", __func__); +			for (j = 0; j < i; j++) +				usb_free_urb(cam->sbuf[j].urb);  			return -ENOMEM;  		} diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 8fe5f38c4d7c..3cb9734ec07b 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -163,7 +163,7 @@ static const struct cx18_card cx18_card_h900 = {  	},  	.audio_inputs = {  		{ CX18_CARD_INPUT_AUD_TUNER, -		  CX18_AV_AUDIO8, 0 }, +		  CX18_AV_AUDIO5, 0 },  		{ CX18_CARD_INPUT_LINE_IN1,  		  CX18_AV_AUDIO_SERIAL1, 0 },  	}, diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 3c006103c1eb..ac3292d7646c 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -117,10 +117,10 @@ static void em28xx_audio_isocirq(struct urb *urb)  			if (oldptr + length >= runtime->buffer_size) {  				unsigned int cnt = -				    runtime->buffer_size - oldptr - 1; +				    runtime->buffer_size - oldptr;  				memcpy(runtime->dma_area + oldptr * stride, cp,  				       cnt * stride); -				memcpy(runtime->dma_area, cp + cnt, +				memcpy(runtime->dma_area, cp + cnt * stride,  				       length * stride - cnt * stride);  			} else {  				memcpy(runtime->dma_area + oldptr * stride, cp, @@ -161,8 +161,14 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)  		memset(dev->adev->transfer_buffer[i], 0x80, sb_size);  		urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); -		if (!urb) +		if (!urb) { +			em28xx_errdev("usb_alloc_urb failed!\n"); +			for (j = 0; j < i; j++) { +				usb_free_urb(dev->adev->urb[j]); +				kfree(dev->adev->transfer_buffer[j]); +			}  			return -ENOMEM; +		}  		urb->dev = dev->udev;  		urb->context = dev; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 452da70e719f..de943cf6c169 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -93,28 +93,6 @@ struct em28xx_board em28xx_boards[] = {  			.amux     = 0,  		} },  	}, -	[EM2800_BOARD_KWORLD_USB2800] = { -		.name         = "Kworld USB2800", -		.valid        = EM28XX_BOARD_NOT_VALIDATED, -		.is_em2800    = 1, -		.vchannels    = 3, -		.tuner_type   = TUNER_PHILIPS_FCV1236D, -		.tda9887_conf = TDA9887_PRESENT, -		.decoder      = EM28XX_SAA7113, -		.input          = { { -			.type     = EM28XX_VMUX_TELEVISION, -			.vmux     = SAA7115_COMPOSITE2, -			.amux     = 0, -		}, { -			.type     = EM28XX_VMUX_COMPOSITE1, -			.vmux     = SAA7115_COMPOSITE0, -			.amux     = 1, -		}, { -			.type     = EM28XX_VMUX_SVIDEO, -			.vmux     = SAA7115_SVIDEO3, -			.amux     = 1, -		} }, -	},  	[EM2820_BOARD_KWORLD_PVRTV2800RF] = {  		.name         = "Kworld PVR TV 2800 RF",  		.is_em2800    = 0, @@ -599,7 +577,7 @@ struct em28xx_board em28xx_boards[] = {  		}, {  			.type     = EM28XX_VMUX_COMPOSITE1,  			.vmux     = TVP5150_COMPOSITE1, -			.amux     = 1, +			.amux     = 3,  		}, {  			.type     = EM28XX_VMUX_SVIDEO,  			.vmux     = TVP5150_SVIDEO, @@ -952,22 +930,23 @@ struct em28xx_board em28xx_boards[] = {  	},  	[EM2880_BOARD_KWORLD_DVB_310U] = {  		.name	      = "KWorld DVB-T 310U", -		.valid        = EM28XX_BOARD_NOT_VALIDATED,  		.vchannels    = 3,  		.tuner_type   = TUNER_XC2028, +		.has_dvb      = 1, +		.mts_firmware = 1,  		.decoder      = EM28XX_TVP5150,  		.input          = { {  			.type     = EM28XX_VMUX_TELEVISION,  			.vmux     = TVP5150_COMPOSITE0, -			.amux     = 0, +			.amux     = EM28XX_AMUX_VIDEO,  		}, {  			.type     = EM28XX_VMUX_COMPOSITE1,  			.vmux     = TVP5150_COMPOSITE1, -			.amux     = 1, -		}, { +			.amux     = EM28XX_AMUX_AC97_LINE_IN, +		}, {	/* S-video has not been tested yet */  			.type     = EM28XX_VMUX_SVIDEO,  			.vmux     = TVP5150_SVIDEO, -			.amux     = 1, +			.amux     = EM28XX_AMUX_AC97_LINE_IN,  		} },  	},  	[EM2881_BOARD_DNT_DA2_HYBRID] = { @@ -1282,6 +1261,7 @@ static struct em28xx_reg_seq em2882_terratec_hybrid_xs_digital[] = {  static struct em28xx_hash_table em28xx_eeprom_hash [] = {  	/* P/N: SA 60002070465 Tuner: TVF7533-MF */  	{0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, +	{0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},  };  /* I2C devicelist hash table for devices with generic USB IDs */ @@ -1552,9 +1532,12 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)  		/* djh - Not sure which demod we need here */  		ctl->demod = XC3028_FE_DEFAULT;  		break; +	case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: +		ctl->demod = XC3028_FE_DEFAULT; +		ctl->fname = XC3028L_DEFAULT_FIRMWARE; +		break;  	case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:  	case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: -	case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:  		/* FIXME: Better to specify the needed IF */  		ctl->demod = XC3028_FE_DEFAULT;  		break; @@ -1764,6 +1747,20 @@ void em28xx_card_setup(struct em28xx *dev)  		break;  	case EM2820_BOARD_UNKNOWN:  	case EM2800_BOARD_UNKNOWN: +		/* +		 * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD. +		 * +		 * This occurs because they share identical USB vendor and +		 * product IDs. +		 * +		 * What we do here is look up the EEPROM hash of the K-WORLD +		 * and if it is found then we decide that we do not have +		 * a DIGIVOX and reset the device to the K-WORLD instead. +		 * +		 * This solution is only valid if they do not share eeprom +		 * hash identities which has not been determined as yet. +		 */ +	case EM2880_BOARD_MSI_DIGIVOX_AD:  		if (!em28xx_hint_board(dev))  			em28xx_set_model(dev);  		break; diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 4b992bc0083c..d2b1a1a52689 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -452,6 +452,15 @@ static int dvb_init(struct em28xx *dev)  			goto out_free;  		}  		break; +	case EM2880_BOARD_KWORLD_DVB_310U: +		dvb->frontend = dvb_attach(zl10353_attach, +						&em28xx_zl10353_with_xc3028, +						&dev->i2c_adap); +		if (attach_xc3028(0x61, dev) < 0) { +			result = -EINVAL; +			goto out_free; +		} +		break;  	default:  		printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"  				" isn't supported yet\n", diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 7be69284da03..ac95c55887df 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -459,6 +459,7 @@ static int create_urbs(struct gspca_dev *gspca_dev,  		urb = usb_alloc_urb(npkt, GFP_KERNEL);  		if (!urb) {  			err("usb_alloc_urb failed"); +			destroy_urbs(gspca_dev);  			return -ENOMEM;  		}  		urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev, @@ -468,8 +469,8 @@ static int create_urbs(struct gspca_dev *gspca_dev,  		if (urb->transfer_buffer == NULL) {  			usb_free_urb(urb); -			destroy_urbs(gspca_dev);  			err("usb_buffer_urb failed"); +			destroy_urbs(gspca_dev);  			return -ENOMEM;  		}  		gspca_dev->urb[n] = urb; diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index d4be51843286..ba865b7f1ed8 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -1063,6 +1063,7 @@ static __devinitdata struct usb_device_id device_table[] = {  	{USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},  	{USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},  	{USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302}, +	{USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302},  	{}  };  MODULE_DEVICE_TABLE(usb, device_table); diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 5dd78c6766ea..12b81ae526b7 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -232,7 +232,7 @@ static struct ctrl sd_ctrls[] = {  static struct v4l2_pix_format vga_mode[] = {  	{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,  		.bytesperline = 160, -		.sizeimage = 160 * 120 * 5 / 4, +		.sizeimage = 160 * 120,  		.colorspace = V4L2_COLORSPACE_SRGB,  		.priv = 2 | MODE_RAW},  	{160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, @@ -264,7 +264,7 @@ static struct v4l2_pix_format sif_mode[] = {  		.priv = 1 | MODE_REDUCED_SIF},  	{176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,  		.bytesperline = 176, -		.sizeimage = 176 * 144 * 5 / 4, +		.sizeimage = 176 * 144,  		.colorspace = V4L2_COLORSPACE_SRGB,  		.priv = 1 | MODE_RAW},  	{176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index d75b1d20b318..572b0f363b64 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -707,6 +707,7 @@ static void i2c_w8(struct gspca_dev *gspca_dev,  			0x08, 0,		/* value, index */  			gspca_dev->usb_buf, 8,  			500); +	msleep(2);  }  /* read 5 bytes in gspca_dev->usb_buf */ @@ -976,13 +977,13 @@ static int sd_init(struct gspca_dev *gspca_dev)  	case BRIDGE_SN9C105:  		if (regF1 != 0x11)  			return -ENODEV; -		reg_w(gspca_dev, 0x02, regGpio, 2); +		reg_w(gspca_dev, 0x01, regGpio, 2);  		break;  	case BRIDGE_SN9C120:  		if (regF1 != 0x12)  			return -ENODEV;  		regGpio[1] = 0x70; -		reg_w(gspca_dev, 0x02, regGpio, 2); +		reg_w(gspca_dev, 0x01, regGpio, 2);  		break;  	default:  /*	case BRIDGE_SN9C110: */ @@ -1183,7 +1184,7 @@ static void sd_start(struct gspca_dev *gspca_dev)  	static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };  	static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };	/* MI0360 */  	static const __u8 CE_ov76xx[] = -			{ 0x32, 0xdd, 0x32, 0xdd };	/* OV7630/48 */ +				{ 0x32, 0xdd, 0x32, 0xdd };  	sn9c1xx = sn_tb[(int) sd->sensor];  	configure_gpio(gspca_dev, sn9c1xx); @@ -1223,8 +1224,15 @@ static void sd_start(struct gspca_dev *gspca_dev)  	reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);  	for (i = 0; i < 8; i++)  		reg_w(gspca_dev, 0x84, reg84, sizeof reg84); +	switch (sd->sensor) { +	case SENSOR_OV7660: +		reg_w1(gspca_dev, 0x9a, 0x05); +		break; +	default:  		reg_w1(gspca_dev, 0x9a, 0x08);  		reg_w1(gspca_dev, 0x99, 0x59); +		break; +	}  	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;  	if (mode) @@ -1275,8 +1283,8 @@ static void sd_start(struct gspca_dev *gspca_dev)  /*			reg1 = 0x44; */  /*			reg1 = 0x46;	(done) */  		} else { -			reg17 = 0x22;	/* 640 MCKSIZE */ -			reg1 = 0x06; +			reg17 = 0xa2;	/* 640 */ +			reg1 = 0x44;  		}  		break;  	} @@ -1285,6 +1293,7 @@ static void sd_start(struct gspca_dev *gspca_dev)  	switch (sd->sensor) {  	case SENSOR_OV7630:  	case SENSOR_OV7648: +	case SENSOR_OV7660:  		reg_w(gspca_dev, 0xce, CE_ov76xx, 4);  		break;  	default: diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index cfbc9ebc5c5d..95fcfcb9e31b 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -225,7 +225,7 @@ static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)  	reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01));  	do {  		reg_r(gspca_dev, 0x8803, 1); -		if (!gspca_dev->usb_buf) +		if (!gspca_dev->usb_buf[0])  			break;  	} while (--retry);  	if (retry == 0) diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 8d7c27e6ac77..d61ef727e0c2 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -6576,8 +6576,8 @@ static int setlightfreq(struct gspca_dev *gspca_dev)  		 cs2102_60HZ, cs2102_60HZScale},  /* SENSOR_CS2102K 1 */  		{cs2102_NoFliker, cs2102_NoFlikerScale, -		 cs2102_50HZ, cs2102_50HZScale, -		 cs2102_60HZ, cs2102_60HZScale}, +		 NULL, NULL, /* currently disabled */ +		 NULL, NULL},  /* SENSOR_GC0305 2 */  		{gc0305_NoFliker, gc0305_NoFliker,  		 gc0305_50HZ, gc0305_50HZ, diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index 3d3c48db45d9..c6852402c5e9 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -3591,7 +3591,7 @@ static int  ov51x_init_isoc(struct usb_ov511 *ov)  {  	struct urb *urb; -	int fx, err, n, size; +	int fx, err, n, i, size;  	PDEBUG(3, "*** Initializing capture ***"); @@ -3662,6 +3662,8 @@ ov51x_init_isoc(struct usb_ov511 *ov)  		urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);  		if (!urb) {  			err("init isoc: usb_alloc_urb ret. NULL"); +			for (i = 0; i < n; i++) +				usb_free_urb(ov->sbuf[i].urb);  			return -ENOMEM;  		}  		ov->sbuf[n].urb = urb; @@ -5651,7 +5653,7 @@ static ssize_t show_exposure(struct device *cd,  	if (!ov->dev)  		return -ENODEV;  	sensor_get_exposure(ov, &exp); -	return sprintf(buf, "%d\n", exp >> 8); +	return sprintf(buf, "%d\n", exp);  }  static DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL); diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 88e175168438..cbe2a3417851 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -489,6 +489,8 @@ static const struct pvr2_device_desc pvr2_device_751xx = {  struct usb_device_id pvr2_device_table[] = {  	{ USB_DEVICE(0x2040, 0x2900),  	  .driver_info = (kernel_ulong_t)&pvr2_device_29xxx}, +	{ USB_DEVICE(0x2040, 0x2950), /* Logically identical to 2900 */ +	  .driver_info = (kernel_ulong_t)&pvr2_device_29xxx},  	{ USB_DEVICE(0x2040, 0x2400),  	  .driver_info = (kernel_ulong_t)&pvr2_device_24xxx},  	{ USB_DEVICE(0x1164, 0x0622), diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index b1d09d8e2b85..92b83feae366 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -669,7 +669,7 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,  		(unsigned long)vbuf, pos);  	/* tell v4l buffer was filled */ -	buf->vb.field_count++; +	buf->vb.field_count = dev->frame_count[chn] * 2;  	do_gettimeofday(&ts);  	buf->vb.ts = ts;  	buf->vb.state = VIDEOBUF_DONE; @@ -1268,6 +1268,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)  	dev->last_frame[chn] = -1;  	dev->bad_payload[chn] = 0;  	dev->cur_frame[chn] = 0; +	dev->frame_count[chn] = 0;  	for (j = 0; j < SYS_FRAMES; j++) {  		dev->buffer[chn].frame[j].ulState = 0;  		dev->buffer[chn].frame[j].cur_size = 0; diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 6ef3e5297de8..feab12aa2c7b 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -592,7 +592,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,  	if (ctrl == NULL)  		return -EINVAL; -	data = kmalloc(8, GFP_KERNEL); +	data = kmalloc(ctrl->info->size, GFP_KERNEL);  	if (data == NULL)  		return -ENOMEM; diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 168baabe4659..11edf79f57be 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -911,7 +911,6 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam)  	for (i = 0; i < W9968CF_URBS; i++) {  		urb = usb_alloc_urb(W9968CF_ISO_PACKETS, GFP_KERNEL); -		cam->urb[i] = urb;  		if (!urb) {  			for (j = 0; j < i; j++)  				usb_free_urb(cam->urb[j]); @@ -919,6 +918,7 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam)  			return -ENOMEM;  		} +		cam->urb[i] = urb;  		urb->dev = udev;  		urb->context = (void*)cam;  		urb->pipe = usb_rcvisocpipe(udev, 1); diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c index 95c79ad80487..54ac3fe26ec2 100644 --- a/drivers/media/video/wm8739.c +++ b/drivers/media/video/wm8739.c @@ -274,10 +274,8 @@ static int wm8739_probe(struct i2c_client *client,  			client->addr << 1, client->adapter->name);  	state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL); -	if (state == NULL) { -		kfree(client); +	if (state == NULL)  		return -ENOMEM; -	}  	state->vol_l = 0x17; /* 0dB */  	state->vol_r = 0x17; /* 0dB */  	state->muted = 0; diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index d842a7cb99d2..3282be730298 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c @@ -988,7 +988,7 @@ zoran_open_init_params (struct zoran *zr)  	zr->v4l_grab_seq = 0;  	zr->v4l_settings.width = 192;  	zr->v4l_settings.height = 144; -	zr->v4l_settings.format = &zoran_formats[4];	/* YUY2 - YUV-4:2:2 packed */ +	zr->v4l_settings.format = &zoran_formats[7];	/* YUY2 - YUV-4:2:2 packed */  	zr->v4l_settings.bytesperline =  	    zr->v4l_settings.width *  	    ((zr->v4l_settings.format->depth + 7) / 8); diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index ec6f59674b10..2dab9eea4def 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -134,7 +134,7 @@ const struct zoran_format zoran_formats[] = {  	}, {  		.name = "16-bit RGB BE",  		ZFMT(-1, -		     V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB), +		     V4L2_PIX_FMT_RGB565X, V4L2_COLORSPACE_SRGB),  		.depth = 16,  		.flags = ZORAN_FORMAT_CAPTURE |  			 ZORAN_FORMAT_OVERLAY, @@ -2737,7 +2737,8 @@ zoran_do_ioctl (struct inode *inode,  				    fh->v4l_settings.format->fourcc;  				fmt->fmt.pix.colorspace =  				    fh->v4l_settings.format->colorspace; -				fmt->fmt.pix.bytesperline = 0; +				fmt->fmt.pix.bytesperline = +				    fh->v4l_settings.bytesperline;  				if (BUZ_MAX_HEIGHT <  				    (fh->v4l_settings.height * 2))  					fmt->fmt.pix.field = @@ -2833,13 +2834,6 @@ zoran_do_ioctl (struct inode *inode,  				fmt->fmt.pix.pixelformat,  				(char *) &printformat); -			if (fmt->fmt.pix.bytesperline > 0) { -				dprintk(5, -					KERN_ERR "%s: bpl not supported\n", -					ZR_DEVNAME(zr)); -				return -EINVAL; -			} -  			/* we can be requested to do JPEG/raw playback/capture */  			if (!  			    (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || @@ -2923,6 +2917,7 @@ zoran_do_ioctl (struct inode *inode,  				fh->jpg_buffers.buffer_size =  				    zoran_v4l2_calc_bufsize(&fh->  							    jpg_settings); +				fmt->fmt.pix.bytesperline = 0;  				fmt->fmt.pix.sizeimage =  				    fh->jpg_buffers.buffer_size; @@ -2979,6 +2974,8 @@ zoran_do_ioctl (struct inode *inode,  				/* tell the user the  				 * results/missing stuff */ +				fmt->fmt.pix.bytesperline = +					fh->v4l_settings.bytesperline;  				fmt->fmt.pix.sizeimage =  					fh->v4l_settings.height *  					fh->v4l_settings.bytesperline; diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 10c44d3fe01a..68dc8d9eb24e 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -21,7 +21,7 @@ config MFD_SM501  config MFD_SM501_GPIO  	bool "Export GPIO via GPIO layer" -	depends on MFD_SM501 && HAVE_GPIO_LIB +	depends on MFD_SM501 && GPIOLIB  	 ---help---  	 This option uses the gpio library layer to export the 64 GPIO  	 lines on the SM501. The platform data is used to supply the @@ -29,7 +29,7 @@ config MFD_SM501_GPIO  config MFD_ASIC3  	bool "Support for Compaq ASIC3" -	depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM +	depends on GENERIC_HARDIRQS && GPIOLIB && ARM  	 ---help---  	  This driver supports the ASIC3 multifunction chip found on many  	  PDAs (mainly iPAQ and HTC based ones) diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index bc2a807f210d..ba5aa2008273 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -312,7 +312,6 @@ static int __init asic3_irq_probe(struct platform_device *pdev)  	struct asic3 *asic = platform_get_drvdata(pdev);  	unsigned long clksel = 0;  	unsigned int irq, irq_base; -	int map_size;  	int ret;  	ret = platform_get_irq(pdev, 0); @@ -534,6 +533,7 @@ static int __init asic3_probe(struct platform_device *pdev)  	struct asic3 *asic;  	struct resource *mem;  	unsigned long clksel; +	int map_size;  	int ret = 0;  	asic = kzalloc(sizeof(struct asic3), GFP_KERNEL); diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 917035e16da4..00008967ef7a 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -426,8 +426,6 @@ static u32 atmci_submit_data(struct mmc_host *mmc, struct mmc_data *data)  	host->sg = NULL;  	host->data = data; -	mci_writel(host, BLKR, MCI_BCNT(data->blocks) -			| MCI_BLKLEN(data->blksz));  	dev_vdbg(&mmc->class_dev, "BLKR=0x%08x\n",  			MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz)); @@ -483,6 +481,10 @@ static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)  		if (data->blocks > 1 && data->blksz & 3)  			goto fail;  		atmci_set_timeout(host, data); + +		/* Must set block count/size before sending command */ +		mci_writel(host, BLKR, MCI_BCNT(data->blocks) +				| MCI_BLKLEN(data->blksz));  	}  	iflags = MCI_CMDRDY; diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index ac4e506b4f88..5ea6b60fa377 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -257,7 +257,6 @@ struct e1000_adapter {  	struct net_device *netdev;  	struct pci_dev *pdev;  	struct net_device_stats net_stats; -	spinlock_t stats_lock;      /* prevent concurrent stats updates */  	/* structs defined in e1000_hw.h */  	struct e1000_hw hw; @@ -284,6 +283,8 @@ struct e1000_adapter {  	unsigned long led_status;  	unsigned int flags; +	struct work_struct downshift_task; +	struct work_struct update_phy_task;  };  struct e1000_info { @@ -305,6 +306,7 @@ struct e1000_info {  #define FLAG_HAS_CTRLEXT_ON_LOAD          (1 << 5)  #define FLAG_HAS_SWSM_ON_LOAD             (1 << 6)  #define FLAG_HAS_JUMBO_FRAMES             (1 << 7) +#define FLAG_READ_ONLY_NVM                (1 << 8)  #define FLAG_IS_ICH                       (1 << 9)  #define FLAG_HAS_SMART_POWER_DOWN         (1 << 11)  #define FLAG_IS_QUAD_PORT_A               (1 << 12) @@ -385,6 +387,7 @@ extern bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw);  extern bool e1000e_get_laa_state_82571(struct e1000_hw *hw);  extern void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state); +extern void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw);  extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,  						 bool state);  extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index e21c9e0f3738..33a3ff17b5d0 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -432,6 +432,10 @@ static void e1000_get_regs(struct net_device *netdev,  	regs_buff[11] = er32(TIDV);  	regs_buff[12] = adapter->hw.phy.type;  /* PHY type (IGP=1, M88=0) */ + +	/* ethtool doesn't use anything past this point, so all this +	 * code is likely legacy junk for apps that may or may not +	 * exist */  	if (hw->phy.type == e1000_phy_m88) {  		e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);  		regs_buff[13] = (u32)phy_data; /* cable length */ @@ -447,7 +451,7 @@ static void e1000_get_regs(struct net_device *netdev,  		regs_buff[22] = adapter->phy_stats.receive_errors;  		regs_buff[23] = regs_buff[13]; /* mdix mode */  	} -	regs_buff[21] = adapter->phy_stats.idle_errors;  /* phy idle errors */ +	regs_buff[21] = 0; /* was idle_errors */  	e1e_rphy(hw, PHY_1000T_STATUS, &phy_data);  	regs_buff[24] = (u32)phy_data;  /* phy local receiver status */  	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */ @@ -529,6 +533,9 @@ static int e1000_set_eeprom(struct net_device *netdev,  	if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16)))  		return -EFAULT; +	if (adapter->flags & FLAG_READ_ONLY_NVM) +		return -EINVAL; +  	max_len = hw->nvm.word_size * 2;  	first_word = eeprom->offset >> 1; diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 9e38452a738c..bcd2bc477af2 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -58,6 +58,7 @@  #define ICH_FLASH_HSFCTL		0x0006  #define ICH_FLASH_FADDR			0x0008  #define ICH_FLASH_FDATA0		0x0010 +#define ICH_FLASH_PR0			0x0074  #define ICH_FLASH_READ_COMMAND_TIMEOUT	500  #define ICH_FLASH_WRITE_COMMAND_TIMEOUT	500 @@ -150,6 +151,19 @@ union ich8_hws_flash_regacc {  	u16 regval;  }; +/* ICH Flash Protected Region */ +union ich8_flash_protected_range { +	struct ich8_pr { +		u32 base:13;     /* 0:12 Protected Range Base */ +		u32 reserved1:2; /* 13:14 Reserved */ +		u32 rpe:1;       /* 15 Read Protection Enable */ +		u32 limit:13;    /* 16:28 Protected Range Limit */ +		u32 reserved2:2; /* 29:30 Reserved */ +		u32 wpe:1;       /* 31 Write Protection Enable */ +	} range; +	u32 regval; +}; +  static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw);  static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw);  static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); @@ -366,6 +380,9 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)  	return 0;  } +static DEFINE_MUTEX(nvm_mutex); +static pid_t nvm_owner = -1; +  /**   *  e1000_acquire_swflag_ich8lan - Acquire software control flag   *  @hw: pointer to the HW structure @@ -379,6 +396,15 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)  	u32 extcnf_ctrl;  	u32 timeout = PHY_CFG_TIMEOUT; +	might_sleep(); + +	if (!mutex_trylock(&nvm_mutex)) { +		WARN(1, KERN_ERR "e1000e mutex contention. Owned by pid %d\n", +		     nvm_owner); +		mutex_lock(&nvm_mutex); +	} +	nvm_owner = current->pid; +  	while (timeout) {  		extcnf_ctrl = er32(EXTCNF_CTRL);  		extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; @@ -393,6 +419,8 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)  	if (!timeout) {  		hw_dbg(hw, "FW or HW has locked the resource for too long.\n"); +		nvm_owner = -1; +		mutex_unlock(&nvm_mutex);  		return -E1000_ERR_CONFIG;  	} @@ -414,6 +442,9 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)  	extcnf_ctrl = er32(EXTCNF_CTRL);  	extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;  	ew32(EXTCNF_CTRL, extcnf_ctrl); + +	nvm_owner = -1; +	mutex_unlock(&nvm_mutex);  }  /** @@ -1284,6 +1315,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)  	 * programming failed.  	 */  	if (ret_val) { +		/* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */  		hw_dbg(hw, "Flash commit failed.\n");  		e1000_release_swflag_ich8lan(hw);  		return ret_val; @@ -1374,6 +1406,49 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)  }  /** + *  e1000e_write_protect_nvm_ich8lan - Make the NVM read-only + *  @hw: pointer to the HW structure + * + *  To prevent malicious write/erase of the NVM, set it to be read-only + *  so that the hardware ignores all write/erase cycles of the NVM via + *  the flash control registers.  The shadow-ram copy of the NVM will + *  still be updated, however any updates to this copy will not stick + *  across driver reloads. + **/ +void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw) +{ +	union ich8_flash_protected_range pr0; +	union ich8_hws_flash_status hsfsts; +	u32 gfpreg; +	s32 ret_val; + +	ret_val = e1000_acquire_swflag_ich8lan(hw); +	if (ret_val) +		return; + +	gfpreg = er32flash(ICH_FLASH_GFPREG); + +	/* Write-protect GbE Sector of NVM */ +	pr0.regval = er32flash(ICH_FLASH_PR0); +	pr0.range.base = gfpreg & FLASH_GFPREG_BASE_MASK; +	pr0.range.limit = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK); +	pr0.range.wpe = true; +	ew32flash(ICH_FLASH_PR0, pr0.regval); + +	/* +	 * Lock down a subset of GbE Flash Control Registers, e.g. +	 * PR0 to prevent the write-protection from being lifted. +	 * Once FLOCKDN is set, the registers protected by it cannot +	 * be written until FLOCKDN is cleared by a hardware reset. +	 */ +	hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); +	hsfsts.hsf_status.flockdn = true; +	ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval); + +	e1000_release_swflag_ich8lan(hw); +} + +/**   *  e1000_write_flash_data_ich8lan - Writes bytes to the NVM   *  @hw: pointer to the HW structure   *  @offset: The offset (in bytes) of the byte/word to read. @@ -1720,6 +1795,9 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)  	ew32(CTRL, (ctrl | E1000_CTRL_RST));  	msleep(20); +	/* release the swflag because it is not reset by hardware reset */ +	e1000_release_swflag_ich8lan(hw); +  	ret_val = e1000e_get_auto_rd_done(hw);  	if (ret_val) {  		/* diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index d266510c8a94..b81c4237b5d3 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -47,7 +47,7 @@  #include "e1000.h" -#define DRV_VERSION "0.3.3.3-k2" +#define DRV_VERSION "0.3.3.3-k6"  char e1000e_driver_name[] = "e1000e";  const char e1000e_driver_version[] = DRV_VERSION; @@ -1115,6 +1115,14 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)  	writel(0, adapter->hw.hw_addr + rx_ring->tail);  } +static void e1000e_downshift_workaround(struct work_struct *work) +{ +	struct e1000_adapter *adapter = container_of(work, +					struct e1000_adapter, downshift_task); + +	e1000e_gig_downshift_workaround_ich8lan(&adapter->hw); +} +  /**   * e1000_intr_msi - Interrupt Handler   * @irq: interrupt number @@ -1139,7 +1147,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)  		 */  		if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&  		    (!(er32(STATUS) & E1000_STATUS_LU))) -			e1000e_gig_downshift_workaround_ich8lan(hw); +			schedule_work(&adapter->downshift_task);  		/*  		 * 80003ES2LAN workaround-- For packet buffer work-around on @@ -1205,7 +1213,7 @@ static irqreturn_t e1000_intr(int irq, void *data)  		 */  		if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&  		    (!(er32(STATUS) & E1000_STATUS_LU))) -			e1000e_gig_downshift_workaround_ich8lan(hw); +			schedule_work(&adapter->downshift_task);  		/*  		 * 80003ES2LAN workaround-- @@ -2592,8 +2600,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)  	/* Explicitly disable IRQ since the NIC can be in any state. */  	e1000_irq_disable(adapter); -	spin_lock_init(&adapter->stats_lock); -  	set_bit(__E1000_DOWN, &adapter->state);  	return 0; @@ -2912,6 +2918,21 @@ static int e1000_set_mac(struct net_device *netdev, void *p)  	return 0;  } +/** + * e1000e_update_phy_task - work thread to update phy + * @work: pointer to our work struct + * + * this worker thread exists because we must acquire a + * semaphore to read the phy, which we could msleep while + * waiting for it, and we can't msleep in a timer. + **/ +static void e1000e_update_phy_task(struct work_struct *work) +{ +	struct e1000_adapter *adapter = container_of(work, +					struct e1000_adapter, update_phy_task); +	e1000_get_phy_info(&adapter->hw); +} +  /*   * Need to wait a few seconds after link up to get diagnostic information from   * the phy @@ -2919,7 +2940,7 @@ static int e1000_set_mac(struct net_device *netdev, void *p)  static void e1000_update_phy_info(unsigned long data)  {  	struct e1000_adapter *adapter = (struct e1000_adapter *) data; -	e1000_get_phy_info(&adapter->hw); +	schedule_work(&adapter->update_phy_task);  }  /** @@ -2930,10 +2951,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)  {  	struct e1000_hw *hw = &adapter->hw;  	struct pci_dev *pdev = adapter->pdev; -	unsigned long irq_flags; -	u16 phy_tmp; - -#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF  	/*  	 * Prevent stats update while adapter is being reset, or if the pci @@ -2944,14 +2961,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)  	if (pci_channel_offline(pdev))  		return; -	spin_lock_irqsave(&adapter->stats_lock, irq_flags); - -	/* -	 * these counters are modified from e1000_adjust_tbi_stats, -	 * called from the interrupt context, so they must only -	 * be written while holding adapter->stats_lock -	 */ -  	adapter->stats.crcerrs += er32(CRCERRS);  	adapter->stats.gprc += er32(GPRC);  	adapter->stats.gorc += er32(GORCL); @@ -3022,21 +3031,10 @@ void e1000e_update_stats(struct e1000_adapter *adapter)  	/* Tx Dropped needs to be maintained elsewhere */ -	/* Phy Stats */ -	if (hw->phy.media_type == e1000_media_type_copper) { -		if ((adapter->link_speed == SPEED_1000) && -		   (!e1e_rphy(hw, PHY_1000T_STATUS, &phy_tmp))) { -			phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; -			adapter->phy_stats.idle_errors += phy_tmp; -		} -	} -  	/* Management Stats */  	adapter->stats.mgptc += er32(MGTPTC);  	adapter->stats.mgprc += er32(MGTPRC);  	adapter->stats.mgpdc += er32(MGTPDC); - -	spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);  }  /** @@ -3048,10 +3046,6 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)  	struct e1000_hw *hw = &adapter->hw;  	struct e1000_phy_regs *phy = &adapter->phy_regs;  	int ret_val; -	unsigned long irq_flags; - - -	spin_lock_irqsave(&adapter->stats_lock, irq_flags);  	if ((er32(STATUS) & E1000_STATUS_LU) &&  	    (adapter->hw.phy.media_type == e1000_media_type_copper)) { @@ -3082,8 +3076,6 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)  		phy->stat1000 = 0;  		phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF);  	} - -	spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);  }  static void e1000_print_link_info(struct e1000_adapter *adapter) @@ -4467,6 +4459,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,  	adapter->bd_number = cards_found++; +	e1000e_check_options(adapter); +  	/* setup adapter struct */  	err = e1000_sw_init(adapter);  	if (err) @@ -4482,6 +4476,10 @@ static int __devinit e1000_probe(struct pci_dev *pdev,  	if (err)  		goto err_hw_init; +	if ((adapter->flags & FLAG_IS_ICH) && +	    (adapter->flags & FLAG_READ_ONLY_NVM)) +		e1000e_write_protect_nvm_ich8lan(&adapter->hw); +  	hw->mac.ops.get_bus_info(&adapter->hw);  	adapter->hw.phy.autoneg_wait_to_complete = 0; @@ -4572,8 +4570,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,  	INIT_WORK(&adapter->reset_task, e1000_reset_task);  	INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task); - -	e1000e_check_options(adapter); +	INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround); +	INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);  	/* Initialize link parameters. User can change them with ethtool */  	adapter->hw.mac.autoneg = 1; diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index ed912e023a72..d91dbf7ba434 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c @@ -133,6 +133,15 @@ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");   */  E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); +/* + * Write Protect NVM + * + * Valid Range: 0, 1 + * + * Default Value: 1 (enabled) + */ +E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]"); +  struct e1000_option {  	enum { enable_option, range_option, list_option } type;  	const char *name; @@ -388,4 +397,25 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)  								       opt.def);  		}  	} +	{ /* Write-protect NVM */ +		const struct e1000_option opt = { +			.type = enable_option, +			.name = "Write-protect NVM", +			.err  = "defaulting to Enabled", +			.def  = OPTION_ENABLED +		}; + +		if (adapter->flags & FLAG_IS_ICH) { +			if (num_WriteProtectNVM > bd) { +				unsigned int write_protect_nvm = WriteProtectNVM[bd]; +				e1000_validate_option(&write_protect_nvm, &opt, +						      adapter); +				if (write_protect_nvm) +					adapter->flags |= FLAG_READ_ONLY_NVM; +			} else { +				if (opt.def) +					adapter->flags |= FLAG_READ_ONLY_NVM; +			} +		} +	}  } diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 9c718583a237..77baff022f71 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -16,6 +16,7 @@  #include <linux/kernel.h> +#include <linux/sched.h>  #include <linux/pci.h>  #include <linux/stat.h>  #include <linux/topology.h> @@ -484,6 +485,21 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,  #endif /* HAVE_PCI_LEGACY */  #ifdef HAVE_PCI_MMAP + +static int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma) +{ +	unsigned long nr, start, size; + +	nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; +	start = vma->vm_pgoff; +	size = pci_resource_len(pdev, resno) >> PAGE_SHIFT; +	if (start < size && size - start >= nr) +		return 1; +	WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n", +		current->comm, start, start+nr, pci_name(pdev), resno, size); +	return 0; +} +  /**   * pci_mmap_resource - map a PCI resource into user memory space   * @kobj: kobject for mapping @@ -510,6 +526,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,  	if (i >= PCI_ROM_RESOURCE)  		return -ENODEV; +	if (!pci_mmap_fits(pdev, i, vma)) +		return -EINVAL; +  	/* pci_mmap_page_range() expects the same kind of entry as coming  	 * from /proc/bus/pci/ which is a "user visible" value. If this is  	 * different from the resource itself, arch will do necessary fixup. diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index f118252f3a9f..52e2743b04ec 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -422,6 +422,12 @@ done:  	return err;  } +static int rtc_dev_fasync(int fd, struct file *file, int on) +{ +	struct rtc_device *rtc = file->private_data; +	return fasync_helper(fd, file, on, &rtc->async_queue); +} +  static int rtc_dev_release(struct inode *inode, struct file *file)  {  	struct rtc_device *rtc = file->private_data; @@ -434,16 +440,13 @@ static int rtc_dev_release(struct inode *inode, struct file *file)  	if (rtc->ops->release)  		rtc->ops->release(rtc->dev.parent); +	if (file->f_flags & FASYNC) +		rtc_dev_fasync(-1, file, 0); +  	clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);  	return 0;  } -static int rtc_dev_fasync(int fd, struct file *file, int on) -{ -	struct rtc_device *rtc = file->private_data; -	return fasync_helper(fd, file, on, &rtc->async_queue); -} -  static const struct file_operations rtc_dev_fops = {  	.owner		= THIS_MODULE,  	.llseek		= no_llseek, diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 1679e2f91c94..a0b6b46e7466 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -447,51 +447,36 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,  {  	char s[80]; -	sprintf(s, "%s sc:%x ", cdev->dev.bus_id, irq_ptr->schid.sch_no); - +	sprintf(s, "qdio: %s ", dev_name(&cdev->dev));  	switch (irq_ptr->qib.qfmt) {  	case QDIO_QETH_QFMT: -		sprintf(s + strlen(s), "OSADE "); +		sprintf(s + strlen(s), "OSA ");  		break;  	case QDIO_ZFCP_QFMT:  		sprintf(s + strlen(s), "ZFCP ");  		break;  	case QDIO_IQDIO_QFMT: -		sprintf(s + strlen(s), "HiperSockets "); +		sprintf(s + strlen(s), "HS ");  		break;  	} -	sprintf(s + strlen(s), "using: "); - -	if (!is_thinint_irq(irq_ptr)) -		sprintf(s + strlen(s), "no"); -	sprintf(s + strlen(s), "AdapterInterrupts "); -	if (!(irq_ptr->sch_token != 0)) -		sprintf(s + strlen(s), "no"); -	sprintf(s + strlen(s), "QEBSM "); -	if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)) -		sprintf(s + strlen(s), "no"); -	sprintf(s + strlen(s), "OutboundPCI "); -	if (!css_general_characteristics.aif_tdd) -		sprintf(s + strlen(s), "no"); -	sprintf(s + strlen(s), "TDD\n"); -	printk(KERN_INFO "qdio: %s", s); - -	memset(s, 0, sizeof(s)); -	sprintf(s, "%s SIGA required: ", cdev->dev.bus_id); -	if (irq_ptr->siga_flag.input) -		sprintf(s + strlen(s), "Read "); -	if (irq_ptr->siga_flag.output) -		sprintf(s + strlen(s), "Write "); -	if (irq_ptr->siga_flag.sync) -		sprintf(s + strlen(s), "Sync "); -	if (!irq_ptr->siga_flag.no_sync_ti) -		sprintf(s + strlen(s), "SyncAI "); -	if (!irq_ptr->siga_flag.no_sync_out_ti) -		sprintf(s + strlen(s), "SyncOutAI "); -	if (!irq_ptr->siga_flag.no_sync_out_pci) -		sprintf(s + strlen(s), "SyncOutPCI"); +	sprintf(s + strlen(s), "on SC %x using ", irq_ptr->schid.sch_no); +	sprintf(s + strlen(s), "AI:%d ", is_thinint_irq(irq_ptr)); +	sprintf(s + strlen(s), "QEBSM:%d ", (irq_ptr->sch_token) ? 1 : 0); +	sprintf(s + strlen(s), "PCI:%d ", +		(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) ? 1 : 0); +	sprintf(s + strlen(s), "TDD:%d ", css_general_characteristics.aif_tdd); +	sprintf(s + strlen(s), "SIGA:"); +	sprintf(s + strlen(s), "%s", (irq_ptr->siga_flag.input) ? "R" : " "); +	sprintf(s + strlen(s), "%s", (irq_ptr->siga_flag.output) ? "W" : " "); +	sprintf(s + strlen(s), "%s", (irq_ptr->siga_flag.sync) ? "S" : " "); +	sprintf(s + strlen(s), "%s", +		(!irq_ptr->siga_flag.no_sync_ti) ? "A" : " "); +	sprintf(s + strlen(s), "%s", +		(!irq_ptr->siga_flag.no_sync_out_ti) ? "O" : " "); +	sprintf(s + strlen(s), "%s", +		(!irq_ptr->siga_flag.no_sync_out_pci) ? "P" : " ");  	sprintf(s + strlen(s), "\n"); -	printk(KERN_INFO "qdio: %s", s); +	printk(KERN_INFO "%s", s);  }  int __init qdio_setup_init(void) diff --git a/drivers/spi/orion_spi.c b/drivers/spi/orion_spi.c index c4eaacd6e553..b872bfaf4bd2 100644 --- a/drivers/spi/orion_spi.c +++ b/drivers/spi/orion_spi.c @@ -427,7 +427,7 @@ static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m)  			goto msg_rejected;  		} -		if (t->speed_hz < orion_spi->min_speed) { +		if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {  			dev_err(&spi->dev,  				"message rejected : "  				"device min speed (%d Hz) exceeds " diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 0e53354c1cfe..d47d3636227f 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -49,7 +49,7 @@ MODULE_ALIAS("platform:pxa2xx-spi");  #define DMA_INT_MASK		(DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)  #define RESET_DMA_CHANNEL	(DCSR_NODESC | DMA_INT_MASK) -#define IS_DMA_ALIGNED(x)	(((x) & 0x07) == 0) +#define IS_DMA_ALIGNED(x)	((((u32)(x)) & 0x07) == 0)  #define MAX_DMA_LEN		8191  /* @@ -896,7 +896,7 @@ static void pump_transfers(unsigned long data)  				|| transfer->rx_dma || transfer->tx_dma) {  			dev_err(&drv_data->pdev->dev,  				"pump_transfers: mapped transfer length " -				"of %lu is greater than %d\n", +				"of %u is greater than %d\n",  				transfer->len, MAX_DMA_LEN);  			message->status = -EINVAL;  			giveback(drv_data); diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index c6299e8a041d..9cbff84b787d 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2400,11 +2400,15 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)   	if (!fbcon_is_inactive(vc, info)) {  		if (ops->blank_state != blank) { +			int ret = 1; +  			ops->blank_state = blank;  			fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);  			ops->cursor_flash = (!blank); -			if (fb_blank(info, blank)) +			if (info->fbops->fb_blank) +				ret = info->fbops->fb_blank(blank, info); +			if (ret)  				fbcon_generic_blank(vc, info, blank);  		} diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index a6e38e9ea73f..89a346880ec0 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -110,7 +110,7 @@ static inline int mono_col(const struct fb_info *info)  	__u32 max_len;  	max_len = max(info->var.green.length, info->var.red.length);  	max_len = max(info->var.blue.length, max_len); -	return ~(0xfff << (max_len & 0xff)); +	return (~(0xfff << max_len)) & 0xff;  }  static inline int attr_col_ec(int shift, struct vc_data *vc, diff --git a/fs/inotify_user.c b/fs/inotify_user.c index 60249429a253..d85c7d931cdf 100644 --- a/fs/inotify_user.c +++ b/fs/inotify_user.c @@ -323,7 +323,7 @@ out:  }  /* - * remove_kevent - cleans up and ultimately frees the given kevent + * remove_kevent - cleans up the given kevent   *   * Caller must hold dev->ev_mutex.   */ @@ -334,7 +334,13 @@ static void remove_kevent(struct inotify_device *dev,  	dev->event_count--;  	dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len; +} +/* + * free_kevent - frees the given kevent. + */ +static void free_kevent(struct inotify_kernel_event *kevent) +{  	kfree(kevent->name);  	kmem_cache_free(event_cachep, kevent);  } @@ -350,6 +356,7 @@ static void inotify_dev_event_dequeue(struct inotify_device *dev)  		struct inotify_kernel_event *kevent;  		kevent = inotify_dev_get_event(dev);  		remove_kevent(dev, kevent); +		free_kevent(kevent);  	}  } @@ -433,17 +440,15 @@ static ssize_t inotify_read(struct file *file, char __user *buf,  	dev = file->private_data;  	while (1) { -		int events;  		prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE);  		mutex_lock(&dev->ev_mutex); -		events = !list_empty(&dev->events); -		mutex_unlock(&dev->ev_mutex); -		if (events) { +		if (!list_empty(&dev->events)) {  			ret = 0;  			break;  		} +		mutex_unlock(&dev->ev_mutex);  		if (file->f_flags & O_NONBLOCK) {  			ret = -EAGAIN; @@ -462,7 +467,6 @@ static ssize_t inotify_read(struct file *file, char __user *buf,  	if (ret)  		return ret; -	mutex_lock(&dev->ev_mutex);  	while (1) {  		struct inotify_kernel_event *kevent; @@ -481,6 +485,13 @@ static ssize_t inotify_read(struct file *file, char __user *buf,  			}  			break;  		} +		remove_kevent(dev, kevent); + +		/* +		 * Must perform the copy_to_user outside the mutex in order +		 * to avoid a lock order reversal with mmap_sem. +		 */ +		mutex_unlock(&dev->ev_mutex);  		if (copy_to_user(buf, &kevent->event, event_size)) {  			ret = -EFAULT; @@ -498,7 +509,9 @@ static ssize_t inotify_read(struct file *file, char __user *buf,  			count -= kevent->event.len;  		} -		remove_kevent(dev, kevent); +		free_kevent(kevent); + +		mutex_lock(&dev->ev_mutex);  	}  	mutex_unlock(&dev->ev_mutex); diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 52312ec93ff4..5145cb9125af 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -58,7 +58,7 @@ const struct inode_operations ramfs_file_inode_operations = {   * size 0 on the assumption that it's going to be used for an mmap of shared   * memory   */ -static int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) +int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)  {  	struct pagevec lru_pvec;  	unsigned long npages, xpages, loop, limit; diff --git a/include/asm-mips/cevt-r4k.h b/include/asm-mips/cevt-r4k.h new file mode 100644 index 000000000000..fa4328f9124f --- /dev/null +++ b/include/asm-mips/cevt-r4k.h @@ -0,0 +1,46 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2008 Kevin D. Kissell + */ + +/* + * Definitions used for common event timer implementation + * for MIPS 4K-type processors and their MIPS MT variants. + * Avoids unsightly extern declarations in C files. + */ +#ifndef __ASM_CEVT_R4K_H +#define __ASM_CEVT_R4K_H + +DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device); + +void mips_event_handler(struct clock_event_device *dev); +int c0_compare_int_usable(void); +void mips_set_clock_mode(enum clock_event_mode, struct clock_event_device *); +irqreturn_t c0_compare_interrupt(int, void *); + +extern struct irqaction c0_compare_irqaction; +extern int cp0_timer_irq_installed; + +/* + * Possibly handle a performance counter interrupt. + * Return true if the timer interrupt should not be checked + */ + +static inline int handle_perf_irq(int r2) +{ +	/* +	 * The performance counter overflow interrupt may be shared with the +	 * timer interrupt (cp0_perfcount_irq < 0). If it is and a +	 * performance counter has overflowed (perf_irq() == IRQ_HANDLED) +	 * and we can't reliably determine if a counter interrupt has also +	 * happened (!r2) then don't check for a timer interrupt. +	 */ +	return (cp0_perfcount_irq < 0) && +		perf_irq() == IRQ_HANDLED && +		!r2; +} + +#endif /* __ASM_CEVT_R4K_H */ diff --git a/include/asm-mips/irqflags.h b/include/asm-mips/irqflags.h index 881e8866501d..701ec0ba8fa9 100644 --- a/include/asm-mips/irqflags.h +++ b/include/asm-mips/irqflags.h @@ -38,8 +38,17 @@ __asm__(  	"	.set	pop						\n"  	"	.endm"); +extern void smtc_ipi_replay(void); +  static inline void raw_local_irq_enable(void)  { +#ifdef CONFIG_MIPS_MT_SMTC +	/* +	 * SMTC kernel needs to do a software replay of queued +	 * IPIs, at the cost of call overhead on each local_irq_enable() +	 */ +	smtc_ipi_replay(); +#endif  	__asm__ __volatile__(  		"raw_local_irq_enable"  		: /* no outputs */ @@ -47,6 +56,7 @@ static inline void raw_local_irq_enable(void)  		: "memory");  } +  /*   * For cli() we have to insert nops to make sure that the new value   * has actually arrived in the status register before the end of this @@ -185,15 +195,14 @@ __asm__(  	"	.set	pop						\n"  	"	.endm							\n"); -extern void smtc_ipi_replay(void);  static inline void raw_local_irq_restore(unsigned long flags)  {  	unsigned long __tmp1; -#ifdef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY +#ifdef CONFIG_MIPS_MT_SMTC  	/* -	 * CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY does prompt replay of deferred +	 * SMTC kernel needs to do a software replay of queued  	 * IPIs, at the cost of branch and call overhead on each  	 * local_irq_restore()  	 */ @@ -208,6 +217,17 @@ static inline void raw_local_irq_restore(unsigned long flags)  		: "memory");  } +static inline void __raw_local_irq_restore(unsigned long flags) +{ +	unsigned long __tmp1; + +	__asm__ __volatile__( +		"raw_local_irq_restore\t%0" +		: "=r" (__tmp1) +		: "0" (flags) +		: "memory"); +} +  static inline int raw_irqs_disabled_flags(unsigned long flags)  {  #ifdef CONFIG_MIPS_MT_SMTC diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h index a46f8e258e6b..979866000da4 100644 --- a/include/asm-mips/mipsregs.h +++ b/include/asm-mips/mipsregs.h @@ -1462,7 +1462,7 @@ set_c0_##name(unsigned int set)					\  {								\  	unsigned int res;					\  	unsigned int omt;					\ -	unsigned int flags;					\ +	unsigned long flags;					\  								\  	local_irq_save(flags);					\  	omt = __dmt();						\ @@ -1480,7 +1480,7 @@ clear_c0_##name(unsigned int clear)				\  {								\  	unsigned int res;					\  	unsigned int omt;					\ -	unsigned int flags;					\ +	unsigned long flags;					\  								\  	local_irq_save(flags);					\  	omt = __dmt();						\ @@ -1498,7 +1498,7 @@ change_c0_##name(unsigned int change, unsigned int new)		\  {								\  	unsigned int res;					\  	unsigned int omt;					\ -	unsigned int flags;					\ +	unsigned long flags;					\  								\  	local_irq_save(flags);					\  								\ diff --git a/include/asm-mips/smtc.h b/include/asm-mips/smtc.h index 3639b28f80db..ea60bf08dcb0 100644 --- a/include/asm-mips/smtc.h +++ b/include/asm-mips/smtc.h @@ -6,6 +6,7 @@   */  #include <asm/mips_mt.h> +#include <asm/smtc_ipi.h>  /*   * System-wide SMTC status information @@ -38,14 +39,15 @@ struct mm_struct;  struct task_struct;  void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu); - +void self_ipi(struct smtc_ipi *);  void smtc_flush_tlb_asid(unsigned long asid); -extern int mipsmt_build_cpu_map(int startslot); -extern void mipsmt_prepare_cpus(void); +extern int smtc_build_cpu_map(int startslot); +extern void smtc_prepare_cpus(int cpus);  extern void smtc_smp_finish(void);  extern void smtc_boot_secondary(int cpu, struct task_struct *t);  extern void smtc_cpus_done(void); +  /*   * Sharing the TLB between multiple VPEs means that the   * "random" index selection function is not allowed to diff --git a/include/asm-mips/sn/mapped_kernel.h b/include/asm-mips/sn/mapped_kernel.h index c3dd5d0d525f..721496a0bb92 100644 --- a/include/asm-mips/sn/mapped_kernel.h +++ b/include/asm-mips/sn/mapped_kernel.h @@ -5,6 +5,8 @@  #ifndef __ASM_SN_MAPPED_KERNEL_H  #define __ASM_SN_MAPPED_KERNEL_H +#include <linux/mmzone.h> +  /*   * Note on how mapped kernels work: the text and data section is   * compiled at cksseg segment (LOADADDR = 0xc001c000), and the @@ -29,10 +31,8 @@  #define MAPPED_ADDR_RO_TO_PHYS(x)	(x - REP_BASE)  #define MAPPED_ADDR_RW_TO_PHYS(x)	(x - REP_BASE - 16777216) -#define MAPPED_KERN_RO_PHYSBASE(n) \ -			(PLAT_NODE_DATA(n)->kern_vars.kv_ro_baseaddr) -#define MAPPED_KERN_RW_PHYSBASE(n) \ -			(PLAT_NODE_DATA(n)->kern_vars.kv_rw_baseaddr) +#define MAPPED_KERN_RO_PHYSBASE(n) (hub_data(n)->kern_vars.kv_ro_baseaddr) +#define MAPPED_KERN_RW_PHYSBASE(n) (hub_data(n)->kern_vars.kv_rw_baseaddr)  #define MAPPED_KERN_RO_TO_PHYS(x) \  				((unsigned long)MAPPED_ADDR_RO_TO_PHYS(x) | \ diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h index 051e1af0bb95..4c37c4e5f72e 100644 --- a/include/asm-mips/stackframe.h +++ b/include/asm-mips/stackframe.h @@ -297,14 +297,31 @@  #ifdef CONFIG_MIPS_MT_SMTC  		.set	mips32r2  		/* -		 * This may not really be necessary if ints are already -		 * inhibited here. +		 * We need to make sure the read-modify-write +		 * of Status below isn't perturbed by an interrupt +		 * or cross-TC access, so we need to do at least a DMT, +		 * protected by an interrupt-inhibit. But setting IXMT +		 * also creates a few-cycle window where an IPI could +		 * be queued and not be detected before potentially +		 * returning to a WAIT or user-mode loop. It must be +		 * replayed. +		 * +		 * We're in the middle of a context switch, and +		 * we can't dispatch it directly without trashing +		 * some registers, so we'll try to detect this unlikely +		 * case and program a software interrupt in the VPE, +		 * as would be done for a cross-VPE IPI.  To accomodate +		 * the handling of that case, we're doing a DVPE instead +		 * of just a DMT here to protect against other threads. +		 * This is a lot of cruft to cover a tiny window. +		 * If you can find a better design, implement it! +		 *  		 */  		mfc0	v0, CP0_TCSTATUS  		ori	v0, TCSTATUS_IXMT  		mtc0	v0, CP0_TCSTATUS  		_ehb -		DMT	5				# dmt a1 +		DVPE	5				# dvpe a1  		jal	mips_ihb  #endif /* CONFIG_MIPS_MT_SMTC */  		mfc0	a0, CP0_STATUS @@ -325,17 +342,50 @@   */  		LONG_L	v1, PT_TCSTATUS(sp)  		_ehb -		mfc0	v0, CP0_TCSTATUS +		mfc0	a0, CP0_TCSTATUS  		andi	v1, TCSTATUS_IXMT -		/* We know that TCStatua.IXMT should be set from above */ -		xori	v0, v0, TCSTATUS_IXMT -		or	v0, v0, v1 -		mtc0	v0, CP0_TCSTATUS -		_ehb -		andi	a1, a1, VPECONTROL_TE +		bnez	v1, 0f + +/* + * We'd like to detect any IPIs queued in the tiny window + * above and request an software interrupt to service them + * when we ERET. + * + * Computing the offset into the IPIQ array of the executing + * TC's IPI queue in-line would be tedious.  We use part of + * the TCContext register to hold 16 bits of offset that we + * can add in-line to find the queue head. + */ +		mfc0	v0, CP0_TCCONTEXT +		la	a2, IPIQ +		srl	v0, v0, 16 +		addu	a2, a2, v0 +		LONG_L	v0, 0(a2) +		beqz	v0, 0f +/* + * If we have a queue, provoke dispatch within the VPE by setting C_SW1 + */ +		mfc0	v0, CP0_CAUSE +		ori	v0, v0, C_SW1 +		mtc0	v0, CP0_CAUSE +0: +		/* +		 * This test should really never branch but +		 * let's be prudent here.  Having atomized +		 * the shared register modifications, we can +		 * now EVPE, and must do so before interrupts +		 * are potentially re-enabled. +		 */ +		andi	a1, a1, MVPCONTROL_EVP  		beqz	a1, 1f -		emt +		evpe  1: +		/* We know that TCStatua.IXMT should be set from above */ +		xori	a0, a0, TCSTATUS_IXMT +		or	a0, a0, v1 +		mtc0	a0, CP0_TCSTATUS +		_ehb +  		.set	mips0  #endif /* CONFIG_MIPS_MT_SMTC */  		LONG_L	v1, PT_EPC(sp) diff --git a/include/asm-x86/uaccess_64.h b/include/asm-x86/uaccess_64.h index 515d4dce96b5..45806d60bcbe 100644 --- a/include/asm-x86/uaccess_64.h +++ b/include/asm-x86/uaccess_64.h @@ -7,6 +7,7 @@  #include <linux/compiler.h>  #include <linux/errno.h>  #include <linux/prefetch.h> +#include <linux/lockdep.h>  #include <asm/page.h>  /* diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 6d93dce61cbb..2f245fe63bda 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -47,14 +47,22 @@ enum hrtimer_restart {   *	HRTIMER_CB_IRQSAFE:		Callback may run in hardirq context   *	HRTIMER_CB_IRQSAFE_NO_RESTART:	Callback may run in hardirq context and   *					does not restart the timer - *	HRTIMER_CB_IRQSAFE_NO_SOFTIRQ:	Callback must run in hardirq context - *					Special mode for tick emultation + *	HRTIMER_CB_IRQSAFE_PERCPU:	Callback must run in hardirq context + *					Special mode for tick emulation and + *					scheduler timer. Such timers are per + *					cpu and not allowed to be migrated on + *					cpu unplug. + *	HRTIMER_CB_IRQSAFE_UNLOCKED:	Callback should run in hardirq context + *					with timer->base lock unlocked + *					used for timers which call wakeup to + *					avoid lock order problems with rq->lock   */  enum hrtimer_cb_mode {  	HRTIMER_CB_SOFTIRQ,  	HRTIMER_CB_IRQSAFE,  	HRTIMER_CB_IRQSAFE_NO_RESTART, -	HRTIMER_CB_IRQSAFE_NO_SOFTIRQ, +	HRTIMER_CB_IRQSAFE_PERCPU, +	HRTIMER_CB_IRQSAFE_UNLOCKED,  };  /* @@ -67,9 +75,10 @@ enum hrtimer_cb_mode {   * 0x02		callback function running   * 0x04		callback pending (high resolution mode)   * - * Special case: + * Special cases:   * 0x03		callback function running and enqueued   *		(was requeued on another CPU) + * 0x09		timer was migrated on CPU hotunplug   * The "callback function running and enqueued" status is only possible on   * SMP. It happens for example when a posix timer expired and the callback   * queued a signal. Between dropping the lock which protects the posix timer @@ -87,6 +96,7 @@ enum hrtimer_cb_mode {  #define HRTIMER_STATE_ENQUEUED	0x01  #define HRTIMER_STATE_CALLBACK	0x02  #define HRTIMER_STATE_PENDING	0x04 +#define HRTIMER_STATE_MIGRATE	0x08  /**   * struct hrtimer - the basic hrtimer structure diff --git a/include/linux/ide.h b/include/linux/ide.h index 1524829f73f2..6514db8fd2e4 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -366,7 +366,9 @@ enum {  	/* Currently on a filemark */  	IDE_AFLAG_FILEMARK		= (1 << 25),  	/* 0 = no tape is loaded, so we don't rewind after ejecting */ -	IDE_AFLAG_MEDIUM_PRESENT	= (1 << 26) +	IDE_AFLAG_MEDIUM_PRESENT	= (1 << 26), + +	IDE_AFLAG_NO_AUTOCLOSE		= (1 << 27),  };  struct ide_drive_s { diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h index b160fb18e8d6..37aaf2b39863 100644 --- a/include/linux/ramfs.h +++ b/include/linux/ramfs.h @@ -6,6 +6,7 @@ extern int ramfs_get_sb(struct file_system_type *fs_type,  	 int flags, const char *dev_name, void *data, struct vfsmount *mnt);  #ifndef CONFIG_MMU +extern int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize);  extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file,  						   unsigned long addr,  						   unsigned long len, diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h index 5da9794b2d78..b106fd8e0d5c 100644 --- a/include/linux/stacktrace.h +++ b/include/linux/stacktrace.h @@ -1,6 +1,8 @@  #ifndef __LINUX_STACKTRACE_H  #define __LINUX_STACKTRACE_H +struct task_struct; +  #ifdef CONFIG_STACKTRACE  struct stack_trace {  	unsigned int nr_entries, max_entries; diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 24811732bdb2..029a54a02396 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -227,6 +227,9 @@ struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,  				   const struct sctp_chunk *,  				   const __u8 *,  				   const size_t ); +struct sctp_chunk *sctp_make_violation_paramlen(const struct sctp_association *, +				   const struct sctp_chunk *, +				   struct sctp_paramhdr *);  struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,  				  const struct sctp_transport *,  				  const void *payload, diff --git a/init/main.c b/init/main.c index f6f7042331dc..3820323c4c84 100644 --- a/init/main.c +++ b/init/main.c @@ -708,7 +708,7 @@ int do_one_initcall(initcall_t fn)  	int result;  	if (initcall_debug) { -		print_fn_descriptor_symbol("calling  %s\n", fn); +		printk("calling  %pF\n", fn);  		t0 = ktime_get();  	} @@ -718,8 +718,8 @@ int do_one_initcall(initcall_t fn)  		t1 = ktime_get();  		delta = ktime_sub(t1, t0); -		print_fn_descriptor_symbol("initcall %s", fn); -		printk(" returned %d after %Ld msecs\n", result, +		printk("initcall %pF returned %d after %Ld msecs\n", +			fn, result,  			(unsigned long long) delta.tv64 >> 20);  	} @@ -737,8 +737,7 @@ int do_one_initcall(initcall_t fn)  		local_irq_enable();  	}  	if (msgbuf[0]) { -		print_fn_descriptor_symbol(KERN_WARNING "initcall %s", fn); -		printk(" returned with %s\n", msgbuf); +		printk("initcall %pF returned with %s\n", fn, msgbuf);  	}  	return result; diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index b8e4dce80a74..cdec83e722fa 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -672,13 +672,14 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,  			 */  			BUG_ON(timer->function(timer) != HRTIMER_NORESTART);  			return 1; -		case HRTIMER_CB_IRQSAFE_NO_SOFTIRQ: +		case HRTIMER_CB_IRQSAFE_PERCPU: +		case HRTIMER_CB_IRQSAFE_UNLOCKED:  			/*  			 * This is solely for the sched tick emulation with  			 * dynamic tick support to ensure that we do not  			 * restart the tick right on the edge and end up with  			 * the tick timer in the softirq ! The calling site -			 * takes care of this. +			 * takes care of this. Also used for hrtimer sleeper !  			 */  			debug_hrtimer_deactivate(timer);  			return 1; @@ -1245,7 +1246,8 @@ static void __run_hrtimer(struct hrtimer *timer)  	timer_stats_account_hrtimer(timer);  	fn = timer->function; -	if (timer->cb_mode == HRTIMER_CB_IRQSAFE_NO_SOFTIRQ) { +	if (timer->cb_mode == HRTIMER_CB_IRQSAFE_PERCPU || +	    timer->cb_mode == HRTIMER_CB_IRQSAFE_UNLOCKED) {  		/*  		 * Used for scheduler timers, avoid lock inversion with  		 * rq->lock and tasklist_lock. @@ -1452,7 +1454,7 @@ void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)  	sl->timer.function = hrtimer_wakeup;  	sl->task = task;  #ifdef CONFIG_HIGH_RES_TIMERS -	sl->timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ; +	sl->timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED;  #endif  } @@ -1591,29 +1593,95 @@ static void __cpuinit init_hrtimers_cpu(int cpu)  #ifdef CONFIG_HOTPLUG_CPU -static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base, -				struct hrtimer_clock_base *new_base) +static int migrate_hrtimer_list(struct hrtimer_clock_base *old_base, +				struct hrtimer_clock_base *new_base, int dcpu)  {  	struct hrtimer *timer;  	struct rb_node *node; +	int raise = 0;  	while ((node = rb_first(&old_base->active))) {  		timer = rb_entry(node, struct hrtimer, node);  		BUG_ON(hrtimer_callback_running(timer));  		debug_hrtimer_deactivate(timer); -		__remove_hrtimer(timer, old_base, HRTIMER_STATE_INACTIVE, 0); + +		/* +		 * Should not happen. Per CPU timers should be +		 * canceled _before_ the migration code is called +		 */ +		if (timer->cb_mode == HRTIMER_CB_IRQSAFE_PERCPU) { +			__remove_hrtimer(timer, old_base, +					 HRTIMER_STATE_INACTIVE, 0); +			WARN(1, "hrtimer (%p %p)active but cpu %d dead\n", +			     timer, timer->function, dcpu); +			continue; +		} + +		/* +		 * Mark it as STATE_MIGRATE not INACTIVE otherwise the +		 * timer could be seen as !active and just vanish away +		 * under us on another CPU +		 */ +		__remove_hrtimer(timer, old_base, HRTIMER_STATE_MIGRATE, 0);  		timer->base = new_base;  		/*  		 * Enqueue the timer. Allow reprogramming of the event device  		 */  		enqueue_hrtimer(timer, new_base, 1); + +#ifdef CONFIG_HIGH_RES_TIMERS +		/* +		 * Happens with high res enabled when the timer was +		 * already expired and the callback mode is +		 * HRTIMER_CB_IRQSAFE_UNLOCKED (hrtimer_sleeper). The +		 * enqueue code does not move them to the soft irq +		 * pending list for performance/latency reasons, but +		 * in the migration state, we need to do that +		 * otherwise we end up with a stale timer. +		 */ +		if (timer->state == HRTIMER_STATE_MIGRATE) { +			timer->state = HRTIMER_STATE_PENDING; +			list_add_tail(&timer->cb_entry, +				      &new_base->cpu_base->cb_pending); +			raise = 1; +		} +#endif +		/* Clear the migration state bit */ +		timer->state &= ~HRTIMER_STATE_MIGRATE; +	} +	return raise; +} + +#ifdef CONFIG_HIGH_RES_TIMERS +static int migrate_hrtimer_pending(struct hrtimer_cpu_base *old_base, +				   struct hrtimer_cpu_base *new_base) +{ +	struct hrtimer *timer; +	int raise = 0; + +	while (!list_empty(&old_base->cb_pending)) { +		timer = list_entry(old_base->cb_pending.next, +				   struct hrtimer, cb_entry); + +		__remove_hrtimer(timer, timer->base, HRTIMER_STATE_PENDING, 0); +		timer->base = &new_base->clock_base[timer->base->index]; +		list_add_tail(&timer->cb_entry, &new_base->cb_pending); +		raise = 1;  	} +	return raise; +} +#else +static int migrate_hrtimer_pending(struct hrtimer_cpu_base *old_base, +				   struct hrtimer_cpu_base *new_base) +{ +	return 0;  } +#endif  static void migrate_hrtimers(int cpu)  {  	struct hrtimer_cpu_base *old_base, *new_base; -	int i; +	int i, raise = 0;  	BUG_ON(cpu_online(cpu));  	old_base = &per_cpu(hrtimer_bases, cpu); @@ -1626,14 +1694,21 @@ static void migrate_hrtimers(int cpu)  	spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);  	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { -		migrate_hrtimer_list(&old_base->clock_base[i], -				     &new_base->clock_base[i]); +		if (migrate_hrtimer_list(&old_base->clock_base[i], +					 &new_base->clock_base[i], cpu)) +			raise = 1;  	} +	if (migrate_hrtimer_pending(old_base, new_base)) +		raise = 1; +  	spin_unlock(&old_base->lock);  	spin_unlock(&new_base->lock);  	local_irq_enable();  	put_cpu_var(hrtimer_bases); + +	if (raise) +		hrtimer_raise_softirq();  }  #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 25d955dbb989..e4dcfb2272a4 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -590,6 +590,7 @@ static void kgdb_wait(struct pt_regs *regs)  	/* Signal the primary CPU that we are done: */  	atomic_set(&cpu_in_kgdb[cpu], 0); +	touch_softlockup_watchdog();  	clocksource_touch_watchdog();  	local_irq_restore(flags);  } @@ -1432,6 +1433,7 @@ acquirelock:  	    atomic_read(&kgdb_cpu_doing_single_step) != cpu) {  		atomic_set(&kgdb_active, -1); +		touch_softlockup_watchdog();  		clocksource_touch_watchdog();  		local_irq_restore(flags); @@ -1524,6 +1526,7 @@ acquirelock:  kgdb_restore:  	/* Free kgdb_active */  	atomic_set(&kgdb_active, -1); +	touch_softlockup_watchdog();  	clocksource_touch_watchdog();  	local_irq_restore(flags); diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index e36d5798cbff..5131e5471169 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -441,7 +441,7 @@ static struct k_itimer * alloc_posix_timer(void)  		return tmr;  	if (unlikely(!(tmr->sigq = sigqueue_alloc()))) {  		kmem_cache_free(posix_timers_cache, tmr); -		tmr = NULL; +		return NULL;  	}  	memset(&tmr->sigq->info, 0, sizeof(siginfo_t));  	return tmr; diff --git a/kernel/sched.c b/kernel/sched.c index 13dd2db9fb2d..ad1962dc0aa2 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -201,7 +201,7 @@ void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime)  	hrtimer_init(&rt_b->rt_period_timer,  			CLOCK_MONOTONIC, HRTIMER_MODE_REL);  	rt_b->rt_period_timer.function = sched_rt_period_timer; -	rt_b->rt_period_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ; +	rt_b->rt_period_timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED;  }  static void start_rt_bandwidth(struct rt_bandwidth *rt_b) @@ -1119,7 +1119,7 @@ static void init_rq_hrtick(struct rq *rq)  	hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);  	rq->hrtick_timer.function = hrtick; -	rq->hrtick_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ; +	rq->hrtick_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU;  }  #else  static inline void hrtick_clear(struct rq *rq) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index bd7034542399..cb01cd8f919b 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -235,7 +235,8 @@ static void tick_do_broadcast_on_off(void *why)  	case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:  		if (!cpu_isset(cpu, tick_broadcast_mask)) {  			cpu_set(cpu, tick_broadcast_mask); -			if (bc->mode == TICKDEV_MODE_PERIODIC) +			if (tick_broadcast_device.mode == +			    TICKDEV_MODE_PERIODIC)  				clockevents_shutdown(dev);  		}  		if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE) @@ -245,7 +246,8 @@ static void tick_do_broadcast_on_off(void *why)  		if (!tick_broadcast_force &&  		    cpu_isset(cpu, tick_broadcast_mask)) {  			cpu_clear(cpu, tick_broadcast_mask); -			if (bc->mode == TICKDEV_MODE_PERIODIC) +			if (tick_broadcast_device.mode == +			    TICKDEV_MODE_PERIODIC)  				tick_setup_periodic(dev, 0);  		}  		break; diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 39019b3f7621..cb02324bdb88 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -625,7 +625,7 @@ void tick_setup_sched_timer(void)  	 */  	hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);  	ts->sched_timer.function = tick_sched_timer; -	ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ; +	ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU;  	/* Get the next period (per cpu) */  	ts->sched_timer.expires = tick_init_jiffy_update(); diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c index bb948e52ce20..db58fb66a135 100644 --- a/kernel/trace/trace_sysprof.c +++ b/kernel/trace/trace_sysprof.c @@ -202,7 +202,7 @@ static void start_stack_timer(int cpu)  	hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);  	hrtimer->function = stack_trace_timer_fn; -	hrtimer->cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ; +	hrtimer->cb_mode = HRTIMER_CB_IRQSAFE_PERCPU;  	hrtimer_start(hrtimer, ns_to_ktime(sample_period), HRTIMER_MODE_REL);  } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e293c58bea58..27b8681139fd 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -268,13 +268,14 @@ void prep_compound_page(struct page *page, unsigned long order)  {  	int i;  	int nr_pages = 1 << order; +	struct page *p = page + 1;  	set_compound_page_dtor(page, free_compound_page);  	set_compound_order(page, order);  	__SetPageHead(page); -	for (i = 1; i < nr_pages; i++) { -		struct page *p = page + i; - +	for (i = 1; i < nr_pages; i++, p++) { +		if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0)) +			p = pfn_to_page(page_to_pfn(page) + i);  		__SetPageTail(p);  		p->first_page = page;  	} @@ -284,6 +285,7 @@ static void destroy_compound_page(struct page *page, unsigned long order)  {  	int i;  	int nr_pages = 1 << order; +	struct page *p = page + 1;  	if (unlikely(compound_order(page) != order))  		bad_page(page); @@ -291,8 +293,9 @@ static void destroy_compound_page(struct page *page, unsigned long order)  	if (unlikely(!PageHead(page)))  			bad_page(page);  	__ClearPageHead(page); -	for (i = 1; i < nr_pages; i++) { -		struct page *p = page + i; +	for (i = 1; i < nr_pages; i++, p++) { +		if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0)) +			p = pfn_to_page(page_to_pfn(page) + i);  		if (unlikely(!PageTail(p) |  				(p->first_page != page))) diff --git a/mm/page_isolation.c b/mm/page_isolation.c index c69f84fe038d..b70a7fec1ff6 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c @@ -114,8 +114,10 @@ __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn)  int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)  { -	unsigned long pfn; +	unsigned long pfn, flags;  	struct page *page; +	struct zone *zone; +	int ret;  	pfn = start_pfn;  	/* @@ -131,7 +133,9 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)  	if (pfn < end_pfn)  		return -EBUSY;  	/* Check all pages are free or Marked as ISOLATED */ -	if (__test_page_isolated_in_pageblock(start_pfn, end_pfn)) -		return 0; -	return -EBUSY; +	zone = page_zone(pfn_to_page(pfn)); +	spin_lock_irqsave(&zone->lock, flags); +	ret = __test_page_isolated_in_pageblock(start_pfn, end_pfn); +	spin_unlock_irqrestore(&zone->lock, flags); +	return ret ? 0 : -EBUSY;  } diff --git a/mm/slob.c b/mm/slob.c index 4c82dd41f32e..62b679dc660f 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -515,7 +515,7 @@ size_t ksize(const void *block)  	sp = (struct slob_page *)virt_to_page(block);  	if (slob_page(sp)) -		return ((slob_t *)block - 1)->units + SLOB_UNIT; +		return (((slob_t *)block - 1)->units - 1) * SLOB_UNIT;  	else  		return sp->page.private;  } diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c index d17cb6f6ab10..8d7a27a6335c 100644 --- a/mm/tiny-shmem.c +++ b/mm/tiny-shmem.c @@ -80,6 +80,12 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)  	inode->i_nlink = 0;	/* It is unlinked */  	init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ,  			&ramfs_file_operations); + +#ifndef CONFIG_MMU +	error = ramfs_nommu_expand_for_mapping(inode, size); +	if (error) +		goto close_file; +#endif  	return file;  close_file: diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 01c83e2a4c19..28c71574a781 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -317,6 +317,9 @@ void ax25_destroy_socket(ax25_cb *ax25)  				/* Queue the unaccepted socket for death */  				sock_orphan(skb->sk); +				/* 9A4GL: hack to release unaccepted sockets */ +				skb->sk->sk_state = TCP_LISTEN; +  				ax25_start_heartbeat(sax25);  				sax25->state = AX25_STATE_0;  			} diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c index cdc7e751ef36..96e4b9273250 100644 --- a/net/ax25/ax25_std_timer.c +++ b/net/ax25/ax25_std_timer.c @@ -39,9 +39,11 @@ void ax25_std_heartbeat_expiry(ax25_cb *ax25)  	switch (ax25->state) {  	case AX25_STATE_0: -		if (!sk || -		    sock_flag(sk, SOCK_DESTROY) || -		    sock_flag(sk, SOCK_DEAD)) { +		/* Magic here: If we listen() and a new link dies before it +		   is accepted() it isn't 'dead' so doesn't get removed. */ +		if (!sk || sock_flag(sk, SOCK_DESTROY) || +		    (sk->sk_state == TCP_LISTEN && +		     sock_flag(sk, SOCK_DEAD))) {  			if (sk) {  				sock_hold(sk);  				ax25_destroy_socket(ax25); diff --git a/net/core/dev.c b/net/core/dev.c index e8eb2b478344..0ae08d3f57e7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2918,6 +2918,12 @@ int netdev_set_master(struct net_device *slave, struct net_device *master)  	return 0;  } +static void dev_change_rx_flags(struct net_device *dev, int flags) +{ +	if (dev->flags & IFF_UP && dev->change_rx_flags) +		dev->change_rx_flags(dev, flags); +} +  static int __dev_set_promiscuity(struct net_device *dev, int inc)  {  	unsigned short old_flags = dev->flags; @@ -2955,8 +2961,7 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc)  				current->uid, current->gid,  				audit_get_sessionid(current)); -		if (dev->change_rx_flags) -			dev->change_rx_flags(dev, IFF_PROMISC); +		dev_change_rx_flags(dev, IFF_PROMISC);  	}  	return 0;  } @@ -3022,8 +3027,7 @@ int dev_set_allmulti(struct net_device *dev, int inc)  		}  	}  	if (dev->flags ^ old_flags) { -		if (dev->change_rx_flags) -			dev->change_rx_flags(dev, IFF_ALLMULTI); +		dev_change_rx_flags(dev, IFF_ALLMULTI);  		dev_set_rx_mode(dev);  	}  	return 0; @@ -3347,8 +3351,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags)  	 *	Load in the correct multicast list now the flags have changed.  	 */ -	if (dev->change_rx_flags && (old_flags ^ flags) & IFF_MULTICAST) -		dev->change_rx_flags(dev, IFF_MULTICAST); +	if ((old_flags ^ flags) & IFF_MULTICAST) +		dev_change_rx_flags(dev, IFF_MULTICAST);  	dev_set_rx_mode(dev); @@ -3808,14 +3812,11 @@ static int dev_new_index(struct net *net)  }  /* Delayed registration/unregisteration */ -static DEFINE_SPINLOCK(net_todo_list_lock);  static LIST_HEAD(net_todo_list);  static void net_set_todo(struct net_device *dev)  { -	spin_lock(&net_todo_list_lock);  	list_add_tail(&dev->todo_list, &net_todo_list); -	spin_unlock(&net_todo_list_lock);  }  static void rollback_registered(struct net_device *dev) @@ -4142,33 +4143,24 @@ static void netdev_wait_allrefs(struct net_device *dev)   *	free_netdev(y1);   *	free_netdev(y2);   * - * We are invoked by rtnl_unlock() after it drops the semaphore. + * We are invoked by rtnl_unlock().   * This allows us to deal with problems:   * 1) We can delete sysfs objects which invoke hotplug   *    without deadlocking with linkwatch via keventd.   * 2) Since we run with the RTNL semaphore not held, we can sleep   *    safely in order to wait for the netdev refcnt to drop to zero. + * + * We must not return until all unregister events added during + * the interval the lock was held have been completed.   */ -static DEFINE_MUTEX(net_todo_run_mutex);  void netdev_run_todo(void)  {  	struct list_head list; -	/* Need to guard against multiple cpu's getting out of order. */ -	mutex_lock(&net_todo_run_mutex); - -	/* Not safe to do outside the semaphore.  We must not return -	 * until all unregister events invoked by the local processor -	 * have been completed (either by this todo run, or one on -	 * another cpu). -	 */ -	if (list_empty(&net_todo_list)) -		goto out; -  	/* Snapshot list, allow later requests */ -	spin_lock(&net_todo_list_lock);  	list_replace_init(&net_todo_list, &list); -	spin_unlock(&net_todo_list_lock); + +	__rtnl_unlock();  	while (!list_empty(&list)) {  		struct net_device *dev @@ -4200,9 +4192,6 @@ void netdev_run_todo(void)  		/* Free network device */  		kobject_put(&dev->dev.kobj);  	} - -out: -	mutex_unlock(&net_todo_run_mutex);  }  static struct net_device_stats *internal_stats(struct net_device *dev) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 71edb8b36341..d6381c2a4693 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -73,7 +73,7 @@ void __rtnl_unlock(void)  void rtnl_unlock(void)  { -	mutex_unlock(&rtnl_mutex); +	/* This fellow will unlock it for us. */  	netdev_run_todo();  } diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c index bfcbd148a89d..c209e054a634 100644 --- a/net/ipv4/tcp_hybla.c +++ b/net/ipv4/tcp_hybla.c @@ -150,7 +150,11 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)  		ca->snd_cwnd_cents -= 128;  		tp->snd_cwnd_cnt = 0;  	} - +	/* check when cwnd has not been incremented for a while */ +	if (increment == 0 && odd == 0 && tp->snd_cwnd_cnt >= tp->snd_cwnd) { +		tp->snd_cwnd++; +		tp->snd_cwnd_cnt = 0; +	}  	/* clamp down slowstart cwnd to ssthresh value. */  	if (is_slowstart)  		tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 67ccce2a96bd..7abc6b80d47d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4879,7 +4879,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,  					goto no_ack;  			} -			__tcp_ack_snd_check(sk, 0); +			if (!copied_early || tp->rcv_nxt != tp->rcv_wup) +				__tcp_ack_snd_check(sk, 0);  no_ack:  #ifdef CONFIG_NET_DMA  			if (copied_early) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1b4fee20fc93..011478e46c40 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -618,7 +618,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,  			];  	} rep;  	struct ip_reply_arg arg; -	struct net *net = dev_net(skb->dev); +	struct net *net = dev_net(skb->dst->dev);  	memset(&rep.th, 0, sizeof(struct tcphdr));  	memset(&arg, 0, sizeof(arg)); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9af6115f0f50..63442a1e741c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2688,6 +2688,8 @@ int __init ip6_route_init(void)  	if (ret)  		goto out_kmem_cache; +	ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; +  	/* Registering of the loopback is done before this portion of code,  	 * the loopback reference in rt6_info will not be taken, do it  	 * manually for init_net */ diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index b585c850a89a..10e22fd48222 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1050,7 +1050,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32  	struct tcphdr *th = tcp_hdr(skb), *t1;  	struct sk_buff *buff;  	struct flowi fl; -	struct net *net = dev_net(skb->dev); +	struct net *net = dev_net(skb->dst->dev);  	struct sock *ctl_sk = net->ipv6.tcp_sk;  	unsigned int tot_len = sizeof(struct tcphdr);  	__be32 *topt; diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 705959b31e24..d7b54b5bfa69 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -524,7 +524,6 @@ static int iucv_enable(void)  	get_online_cpus();  	for_each_online_cpu(cpu)  		smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); -	preempt_enable();  	if (cpus_empty(iucv_buffer_cpumask))  		/* No cpu could declare an iucv buffer. */  		goto out_path; @@ -547,7 +546,9 @@ out:   */  static void iucv_disable(void)  { +	get_online_cpus();  	on_each_cpu(iucv_retrieve_cpu, NULL, 1); +	put_online_cpus();  	kfree(iucv_path_table);  } diff --git a/net/key/af_key.c b/net/key/af_key.c index d628df97e02e..b7f5a1c353ee 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -73,22 +73,18 @@ static int pfkey_can_dump(struct sock *sk)  	return 0;  } -static int pfkey_do_dump(struct pfkey_sock *pfk) +static void pfkey_terminate_dump(struct pfkey_sock *pfk)  { -	int rc; - -	rc = pfk->dump.dump(pfk); -	if (rc == -ENOBUFS) -		return 0; - -	pfk->dump.done(pfk); -	pfk->dump.dump = NULL; -	pfk->dump.done = NULL; -	return rc; +	if (pfk->dump.dump) { +		pfk->dump.done(pfk); +		pfk->dump.dump = NULL; +		pfk->dump.done = NULL; +	}  }  static void pfkey_sock_destruct(struct sock *sk)  { +	pfkey_terminate_dump(pfkey_sk(sk));  	skb_queue_purge(&sk->sk_receive_queue);  	if (!sock_flag(sk, SOCK_DEAD)) { @@ -310,6 +306,18 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,  	return err;  } +static int pfkey_do_dump(struct pfkey_sock *pfk) +{ +	int rc; + +	rc = pfk->dump.dump(pfk); +	if (rc == -ENOBUFS) +		return 0; + +	pfkey_terminate_dump(pfk); +	return rc; +} +  static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig)  {  	*new = *orig; diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 532e4faa29f7..9f1ea4a27b35 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -525,6 +525,7 @@ static int nr_release(struct socket *sock)  	if (sk == NULL) return 0;  	sock_hold(sk); +	sock_orphan(sk);  	lock_sock(sk);  	nr = nr_sk(sk); @@ -548,7 +549,6 @@ static int nr_release(struct socket *sock)  		sk->sk_state    = TCP_CLOSE;  		sk->sk_shutdown |= SEND_SHUTDOWN;  		sk->sk_state_change(sk); -		sock_orphan(sk);  		sock_set_flag(sk, SOCK_DESTROY);  		break; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b599cbba4fbe..d68869f966c3 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1012,6 +1012,29 @@ end:  	return retval;  } +struct sctp_chunk *sctp_make_violation_paramlen( +	const struct sctp_association *asoc, +	const struct sctp_chunk *chunk, +	struct sctp_paramhdr *param) +{ +	struct sctp_chunk *retval; +	static const char error[] = "The following parameter had invalid length:"; +	size_t payload_len = sizeof(error) + sizeof(sctp_errhdr_t) + +				sizeof(sctp_paramhdr_t); + +	retval = sctp_make_abort(asoc, chunk, payload_len); +	if (!retval) +		goto nodata; + +	sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, +			sizeof(error) + sizeof(sctp_paramhdr_t)); +	sctp_addto_chunk(retval, sizeof(error), error); +	sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param); + +nodata: +	return retval; +} +  /* Make a HEARTBEAT chunk.  */  struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,  				  const struct sctp_transport *transport, @@ -1782,11 +1805,6 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,  					const struct sctp_chunk *chunk,  					struct sctp_chunk **errp)  { -	static const char error[] = "The following parameter had invalid length:"; -	size_t		payload_len = WORD_ROUND(sizeof(error)) + -						sizeof(sctp_paramhdr_t); - -  	/* This is a fatal error.  Any accumulated non-fatal errors are  	 * not reported.  	 */ @@ -1794,14 +1812,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,  		sctp_chunk_free(*errp);  	/* Create an error chunk and fill it in with our payload. */ -	*errp = sctp_make_op_error_space(asoc, chunk, payload_len); - -	if (*errp) { -		sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, -				sizeof(error) + sizeof(sctp_paramhdr_t)); -		sctp_addto_chunk(*errp, sizeof(error), error); -		sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param); -	} +	*errp = sctp_make_violation_paramlen(asoc, chunk, param);  	return 0;  } diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8848d329aa2c..7c622af2ce55 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -119,7 +119,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen(  				     const struct sctp_endpoint *ep,  				     const struct sctp_association *asoc,  				     const sctp_subtype_t type, -				     void *arg, +				     void *arg, void *ext,  				     sctp_cmd_seq_t *commands);  static sctp_disposition_t sctp_sf_violation_ctsn( @@ -3425,7 +3425,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,  	addr_param = (union sctp_addr_param *)hdr->params;  	length = ntohs(addr_param->p.length);  	if (length < sizeof(sctp_paramhdr_t)) -		return sctp_sf_violation_paramlen(ep, asoc, type, +		return sctp_sf_violation_paramlen(ep, asoc, type, arg,  			   (void *)addr_param, commands);  	/* Verify the ASCONF chunk before processing it. */ @@ -3433,8 +3433,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,  			    (sctp_paramhdr_t *)((void *)addr_param + length),  			    (void *)chunk->chunk_end,  			    &err_param)) -		return sctp_sf_violation_paramlen(ep, asoc, type, -						  (void *)&err_param, commands); +		return sctp_sf_violation_paramlen(ep, asoc, type, arg, +						  (void *)err_param, commands);  	/* ADDIP 5.2 E1) Compare the value of the serial number to the value  	 * the endpoint stored in a new association variable @@ -3542,8 +3542,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,  	    (sctp_paramhdr_t *)addip_hdr->params,  	    (void *)asconf_ack->chunk_end,  	    &err_param)) -		return sctp_sf_violation_paramlen(ep, asoc, type, -			   (void *)&err_param, commands); +		return sctp_sf_violation_paramlen(ep, asoc, type, arg, +			   (void *)err_param, commands);  	if (last_asconf) {  		addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; @@ -4240,12 +4240,38 @@ static sctp_disposition_t sctp_sf_violation_paramlen(  				     const struct sctp_endpoint *ep,  				     const struct sctp_association *asoc,  				     const sctp_subtype_t type, -				     void *arg, -				     sctp_cmd_seq_t *commands) { -	static const char err_str[] = "The following parameter had invalid length:"; +				     void *arg, void *ext, +				     sctp_cmd_seq_t *commands) +{ +	struct sctp_chunk *chunk =  arg; +	struct sctp_paramhdr *param = ext; +	struct sctp_chunk *abort = NULL; -	return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, -					sizeof(err_str)); +	if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) +		goto discard; + +	/* Make the abort chunk. */ +	abort = sctp_make_violation_paramlen(asoc, chunk, param); +	if (!abort) +		goto nomem; + +	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); +	SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); + +	sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, +			SCTP_ERROR(ECONNABORTED)); +	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, +			SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); +	SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); + +discard: +	sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); + +	SCTP_INC_STATS(SCTP_MIB_ABORTEDS); + +	return SCTP_DISPOSITION_ABORT; +nomem: +	return SCTP_DISPOSITION_NOMEM;  }  /* Handle a protocol violation when the peer trying to advance the diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index ac25b4c0e982..dc50f1e71f76 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -27,10 +27,14 @@ static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)  		- skb_headroom(skb);  	int ntail = dst->dev->needed_tailroom - skb_tailroom(skb); -	if (nhead > 0 || ntail > 0) -		return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC); - -	return 0; +	if (nhead <= 0) { +		if (ntail <= 0) +			return 0; +		nhead = 0; +	} else if (ntail < 0) +		ntail = 0; + +	return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC);  }  static int xfrm_output_one(struct sk_buff *skb, int err) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 418cd7dbbc93..8e0de6a5e18a 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1986,11 +1986,13 @@ static void read_markers(const char *fname)  		mod = find_module(modname);  		if (!mod) { -			if (is_vmlinux(modname)) -				have_vmlinux = 1;  			mod = new_module(NOFAIL(strdup(modname)));  			mod->skip = 1;  		} +		if (is_vmlinux(modname)) { +			have_vmlinux = 1; +			mod->skip = 0; +		}  		if (!mod->skip)  			add_marker(mod, marker, fmt); diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index d11a8154500f..8551952ef329 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2737,6 +2737,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,  		if (ctx == NULL)  			goto netlbl_secattr_to_sid_return; +		context_init(&ctx_new);  		ctx_new.user = ctx->user;  		ctx_new.role = ctx->role;  		ctx_new.type = ctx->type; @@ -2745,13 +2746,9 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,  			if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,  						  secattr->attr.mls.cat) != 0)  				goto netlbl_secattr_to_sid_return; -			ctx_new.range.level[1].cat.highbit = -				ctx_new.range.level[0].cat.highbit; -			ctx_new.range.level[1].cat.node = -				ctx_new.range.level[0].cat.node; -		} else { -			ebitmap_init(&ctx_new.range.level[0].cat); -			ebitmap_init(&ctx_new.range.level[1].cat); +			memcpy(&ctx_new.range.level[1].cat, +			       &ctx_new.range.level[0].cat, +			       sizeof(ctx_new.range.level[0].cat));  		}  		if (mls_context_isvalid(&policydb, &ctx_new) != 1)  			goto netlbl_secattr_to_sid_return_cleanup; diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index ad994fcab725..f3da621f25c5 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1683,8 +1683,8 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {  	/* Dell 3 stack systems with verb table in BIOS */  	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS),  	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0227, "Dell Vostro 1400  ", STAC_DELL_BIOS), -	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022f, "Dell     ", STAC_DELL_BIOS),  	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022e, "Dell     ", STAC_DELL_BIOS), +	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022f, "Dell Inspiron 1525", STAC_DELL_3ST),  	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0242, "Dell     ", STAC_DELL_BIOS),  	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0243, "Dell     ", STAC_DELL_BIOS),  	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x02ff, "Dell     ", STAC_DELL_BIOS), diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index 566a6d0daf4a..106c48225bba 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c @@ -621,6 +621,13 @@ static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = {  	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),  }; +static struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] __initdata = { +	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1), +	AWACS_VOLUME("Master Playback Volume", 5, 6, 1), +	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), +	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), +}; +  static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __initdata = {  	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),  	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), @@ -688,7 +695,10 @@ static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = {  static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata =  AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1); -static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac __initdata = +static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 __initdata = +AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 1); + +static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 __initdata =  AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 0); @@ -765,11 +775,12 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip)  #define IS_PM7500 (machine_is_compatible("AAPL,7500"))  #define IS_BEIGE (machine_is_compatible("AAPL,Gossamer")) -#define IS_IMAC (machine_is_compatible("PowerMac2,1") \ -		|| machine_is_compatible("PowerMac2,2") \ +#define IS_IMAC1 (machine_is_compatible("PowerMac2,1")) +#define IS_IMAC2 (machine_is_compatible("PowerMac2,2") \  		|| machine_is_compatible("PowerMac4,1")) +#define IS_G4AGP (machine_is_compatible("PowerMac3,1")) -static int imac; +static int imac1, imac2;  #ifdef PMAC_SUPPORT_AUTOMUTE  /* @@ -815,13 +826,18 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)  		{  			int reg = chip->awacs_reg[1]  				| (MASK_HDMUTE | MASK_SPKMUTE); -			if (imac) { +			if (imac1) { +				reg &= ~MASK_SPKMUTE; +				reg |= MASK_PAROUT1; +			} else if (imac2) {  				reg &= ~MASK_SPKMUTE;  				reg &= ~MASK_PAROUT1;  			}  			if (snd_pmac_awacs_detect_headphone(chip))  				reg &= ~MASK_HDMUTE; -			else if (imac) +			else if (imac1) +				reg &= ~MASK_PAROUT1; +			else if (imac2)  				reg |= MASK_PAROUT1;  			else  				reg &= ~MASK_SPKMUTE; @@ -850,9 +866,13 @@ snd_pmac_awacs_init(struct snd_pmac *chip)  {  	int pm7500 = IS_PM7500;  	int beige = IS_BEIGE; +	int g4agp = IS_G4AGP; +	int imac;  	int err, vol; -	imac = IS_IMAC; +	imac1 = IS_IMAC1; +	imac2 = IS_IMAC2; +	imac = imac1 || imac2;  	/* looks like MASK_GAINLINE triggers something, so we set here  	 * as start-up  	 */ @@ -939,7 +959,7 @@ snd_pmac_awacs_init(struct snd_pmac *chip)  				snd_pmac_awacs_mixers);  	if (err < 0)  		return err; -	if (beige) +	if (beige || g4agp)  		;  	else if (chip->model == PMAC_SCREAMER)  		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2), @@ -961,13 +981,17 @@ snd_pmac_awacs_init(struct snd_pmac *chip)  		err = build_mixers(chip,  				   ARRAY_SIZE(snd_pmac_screamer_mixers_imac),  				   snd_pmac_screamer_mixers_imac); +	else if (g4agp) +		err = build_mixers(chip, +				   ARRAY_SIZE(snd_pmac_screamer_mixers_g4agp), +				   snd_pmac_screamer_mixers_g4agp);  	else  		err = build_mixers(chip,  				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac),  				   snd_pmac_awacs_mixers_pmac);  	if (err < 0)  		return err; -	chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac) +	chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac || g4agp)  			? &snd_pmac_awacs_master_sw_imac  			: &snd_pmac_awacs_master_sw, chip);  	err = snd_ctl_add(chip->card, chip->master_sw_ctl); @@ -1004,15 +1028,17 @@ snd_pmac_awacs_init(struct snd_pmac *chip)  					snd_pmac_awacs_speaker_vol);  		if (err < 0)  			return err; -		chip->speaker_sw_ctl = snd_ctl_new1(imac -				? &snd_pmac_awacs_speaker_sw_imac +		chip->speaker_sw_ctl = snd_ctl_new1(imac1 +				? &snd_pmac_awacs_speaker_sw_imac1 +				: imac2 +				? &snd_pmac_awacs_speaker_sw_imac2  				: &snd_pmac_awacs_speaker_sw, chip);  		err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);  		if (err < 0)  			return err;  	} -	if (beige) +	if (beige || g4agp)  		err = build_mixers(chip,  				ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige),  				snd_pmac_screamer_mic_boost_beige); diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index d68650de39bc..0bbd94501d7e 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -681,7 +681,7 @@ static int cs4270_probe(struct platform_device *pdev)  	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);  	if (ret < 0) {  		printk(KERN_ERR "cs4270: failed to create PCMs\n"); -		return ret; +		goto error_free_codec;  	}  #ifdef USE_I2C @@ -690,8 +690,7 @@ static int cs4270_probe(struct platform_device *pdev)  	ret = i2c_add_driver(&cs4270_i2c_driver);  	if (ret) {  		printk(KERN_ERR "cs4270: failed to attach driver"); -		snd_soc_free_pcms(socdev); -		return ret; +		goto error_free_pcms;  	}  	/* Did we find a CS4270 on the I2C bus? */ @@ -713,10 +712,23 @@ static int cs4270_probe(struct platform_device *pdev)  	ret = snd_soc_register_card(socdev);  	if (ret < 0) {  		printk(KERN_ERR "cs4270: failed to register card\n"); -		snd_soc_free_pcms(socdev); -		return ret; +		goto error_del_driver;  	} +	return 0; + +error_del_driver: +#ifdef USE_I2C +	i2c_del_driver(&cs4270_i2c_driver); + +error_free_pcms: +#endif +	snd_soc_free_pcms(socdev); + +error_free_codec: +	kfree(socdev->codec); +	socdev->codec = NULL; +  	return ret;  } @@ -727,8 +739,7 @@ static int cs4270_remove(struct platform_device *pdev)  	snd_soc_free_pcms(socdev);  #ifdef USE_I2C -	if (socdev->codec->control_data) -		i2c_del_driver(&cs4270_i2c_driver); +	i2c_del_driver(&cs4270_i2c_driver);  #endif  	kfree(socdev->codec); diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 5761164fe16d..e873414840c8 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -583,7 +583,7 @@ static const struct snd_soc_dapm_route audio_map[] = {  	/* out 4 */  	{"Out4 Mux", "VREF", "VREF"}, -	{"Out4 Mux", "Capture ST", "Capture ST Mixer"}, +	{"Out4 Mux", "Capture ST", "Playback Mixer"},  	{"Out4 Mux", "LOUT2", "LOUT2"},  	{"Out 4", NULL, "Out4 Mux"},  	{"OUT4", NULL, "Out 4"}, @@ -607,7 +607,7 @@ static const struct snd_soc_dapm_route audio_map[] = {  	/* Capture Right Mux */  	{"Capture Right Mux", "PGA", "Right Capture Volume"},  	{"Capture Right Mux", "Line or RXP-RXN", "Line Right Mux"}, -	{"Capture Right Mux", "Sidetone", "Capture ST Mixer"}, +	{"Capture Right Mux", "Sidetone", "Playback Mixer"},  	/* Mono Capture mixer-mux */  	{"Capture Right Mixer", "Stereo", "Capture Right Mux"},  | 
