Browse Source

Merge branch 'linus' into core/rcu

Ingo Molnar 16 years ago
parent
commit
cdbb92b31d
100 changed files with 1325 additions and 908 deletions
  1. 2 1
      Documentation/HOWTO
  2. 2 0
      Documentation/SubmitChecklist
  3. 1 1
      Documentation/video4linux/CARDLIST.em28xx
  4. 1 0
      Documentation/video4linux/gspca.txt
  5. 1 2
      MAINTAINERS
  6. 1 1
      Makefile
  7. 3 0
      arch/ia64/include/asm/sections.h
  8. 5 4
      arch/ia64/kernel/head.S
  9. 5 3
      arch/ia64/kernel/vmlinux.lds.S
  10. 1 1
      arch/ia64/mm/contig.c
  11. 1 1
      arch/ia64/mm/discontig.c
  12. 20 33
      arch/mips/Kconfig
  13. 1 0
      arch/mips/kernel/Makefile
  14. 48 125
      arch/mips/kernel/cevt-r4k.c
  15. 321 0
      arch/mips/kernel/cevt-smtc.c
  16. 7 3
      arch/mips/kernel/cpu-probe.c
  17. 5 5
      arch/mips/kernel/entry.S
  18. 2 2
      arch/mips/kernel/genex.S
  19. 1 0
      arch/mips/kernel/head.S
  20. 1 1
      arch/mips/kernel/mips-mt-fpaff.c
  21. 9 10
      arch/mips/kernel/process.c
  22. 1 1
      arch/mips/kernel/ptrace.c
  23. 137 123
      arch/mips/kernel/smtc.c
  24. 4 2
      arch/mips/kernel/traps.c
  25. 1 1
      arch/mips/mti-malta/Makefile
  26. 7 2
      arch/mips/mti-malta/malta-smtc.c
  27. 2 1
      arch/mips/sibyte/swarm/Makefile
  28. 85 0
      arch/mips/sibyte/swarm/platform.c
  29. 45 26
      arch/mn10300/kernel/irq.c
  30. 1 1
      arch/mn10300/unit-asb2303/unit-init.c
  31. 1 1
      arch/mn10300/unit-asb2305/unit-init.c
  32. 53 53
      arch/powerpc/boot/dts/holly.dts
  33. 1 5
      arch/powerpc/kernel/idle.c
  34. 11 1
      arch/powerpc/platforms/fsl_uli1575.c
  35. 2 0
      arch/s390/kernel/time.c
  36. 54 34
      arch/s390/lib/delay.c
  37. 1 1
      arch/x86/boot/compressed/relocs.c
  38. 16 0
      arch/x86/kernel/acpi/boot.c
  39. 1 1
      arch/x86/kernel/cpu/mtrr/main.c
  40. 1 6
      arch/x86/kernel/kgdb.c
  41. 11 9
      arch/x86/kernel/pci-gart_64.c
  42. 1 1
      arch/x86/kernel/vmi_32.c
  43. 4 9
      drivers/accessibility/braille/braille_console.c
  44. 4 1
      drivers/acpi/glue.c
  45. 10 0
      drivers/acpi/sleep/proc.c
  46. 0 2
      drivers/bluetooth/bpa10x.c
  47. 5 3
      drivers/bluetooth/btusb.c
  48. 1 1
      drivers/dma/dw_dmac.c
  49. 0 4
      drivers/ide/Kconfig
  50. 5 1
      drivers/ide/ide-cd.c
  51. 1 1
      drivers/ide/ide-dma.c
  52. 1 1
      drivers/ide/ide-probe.c
  53. 0 1
      drivers/ide/mips/Makefile
  54. 0 197
      drivers/ide/mips/swarm.c
  55. 14 14
      drivers/leds/leds-fsg.c
  56. 38 32
      drivers/leds/leds-pca955x.c
  57. 15 1
      drivers/md/dm-mpath.c
  58. 8 4
      drivers/md/dm.c
  59. 1 0
      drivers/media/common/tuners/tuner-xc2028.h
  60. 1 0
      drivers/media/dvb/b2c2/flexcop-fe-tuner.c
  61. 9 7
      drivers/media/dvb/dvb-core/dmxdev.c
  62. 10 6
      drivers/media/dvb/dvb-core/dvb_demux.c
  63. 7 4
      drivers/media/dvb/frontends/s5h1420.c
  64. 5 3
      drivers/media/dvb/frontends/s5h1420.h
  65. 3 1
      drivers/media/dvb/siano/sms-cards.c
  66. 1 1
      drivers/media/video/bt8xx/bttv-driver.c
  67. 1 0
      drivers/media/video/cafe_ccic.c
  68. 4 1
      drivers/media/video/cpia2/cpia2_usb.c
  69. 1 1
      drivers/media/video/cx18/cx18-cards.c
  70. 9 3
      drivers/media/video/em28xx/em28xx-audio.c
  71. 26 29
      drivers/media/video/em28xx/em28xx-cards.c
  72. 9 0
      drivers/media/video/em28xx/em28xx-dvb.c
  73. 2 1
      drivers/media/video/gspca/gspca.c
  74. 1 0
      drivers/media/video/gspca/pac7311.c
  75. 2 2
      drivers/media/video/gspca/sonixb.c
  76. 14 5
      drivers/media/video/gspca/sonixj.c
  77. 1 1
      drivers/media/video/gspca/spca561.c
  78. 2 2
      drivers/media/video/gspca/zc3xx.c
  79. 4 2
      drivers/media/video/ov511.c
  80. 2 0
      drivers/media/video/pvrusb2/pvrusb2-devattr.c
  81. 2 1
      drivers/media/video/s2255drv.c
  82. 1 1
      drivers/media/video/uvc/uvc_ctrl.c
  83. 1 1
      drivers/media/video/w9968cf.c
  84. 1 3
      drivers/media/video/wm8739.c
  85. 1 1
      drivers/media/video/zoran_card.c
  86. 6 9
      drivers/media/video/zoran_driver.c
  87. 2 2
      drivers/mfd/Kconfig
  88. 1 1
      drivers/mfd/asic3.c
  89. 4 2
      drivers/mmc/host/atmel-mci.c
  90. 4 1
      drivers/net/e1000e/e1000.h
  91. 8 1
      drivers/net/e1000e/ethtool.c
  92. 78 0
      drivers/net/e1000e/ich8lan.c
  93. 35 37
      drivers/net/e1000e/netdev.c
  94. 30 0
      drivers/net/e1000e/param.c
  95. 19 0
      drivers/pci/pci-sysfs.c
  96. 9 6
      drivers/rtc/rtc-dev.c
  97. 20 35
      drivers/s390/cio/qdio_setup.c
  98. 1 1
      drivers/spi/orion_spi.c
  99. 2 2
      drivers/spi/pxa2xx_spi.c
  100. 5 1
      drivers/video/console/fbcon.c

+ 2 - 1
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
 When a kernel change causes the interface that the kernel exposes to
 userspace to change, it is recommended that you send the information or
 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
 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
 Here is a list of files that are in the kernel source tree that are
 required reading:
 required reading:

+ 2 - 0
Documentation/SubmitChecklist

@@ -67,6 +67,8 @@ kernel patches.
 
 
 19: All new userspace interfaces are documented in Documentation/ABI/.
 19: All new userspace interfaces are documented in Documentation/ABI/.
     See Documentation/ABI/README for more information.
     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'.
 20: Check that it all passes `make headers_check'.
 
 

+ 1 - 1
Documentation/video4linux/CARDLIST.em28xx

@@ -46,7 +46,7 @@
  45 -> Pinnacle PCTV DVB-T                      (em2870)
  45 -> Pinnacle PCTV DVB-T                      (em2870)
  46 -> Compro, VideoMate U3                     (em2870)        [185b:2870]
  46 -> Compro, VideoMate U3                     (em2870)        [185b:2870]
  47 -> KWorld DVB-T 305U                        (em2880)        [eb1a:e305]
  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]
  49 -> MSI DigiVox A/D                          (em2880)        [eb1a:e310]
  50 -> MSI DigiVox A/D II                       (em2880)        [eb1a:e320]
  50 -> MSI DigiVox A/D II                       (em2880)        [eb1a:e320]
  51 -> Terratec Hybrid XS Secam                 (em2880)        [0ccd:004c]
  51 -> Terratec Hybrid XS Secam                 (em2880)        [0ccd:004c]

+ 1 - 0
Documentation/video4linux/gspca.txt

@@ -190,6 +190,7 @@ pac7311		093a:260f	SnakeCam
 pac7311		093a:2621	PAC731x
 pac7311		093a:2621	PAC731x
 pac7311		093a:2624	PAC7302
 pac7311		093a:2624	PAC7302
 pac7311		093a:2626	Labtec 2200
 pac7311		093a:2626	Labtec 2200
+pac7311		093a:262a	Webcam 300k
 zc3xx		0ac8:0302	Z-star Vimicro zc0302
 zc3xx		0ac8:0302	Z-star Vimicro zc0302
 vc032x		0ac8:0321	Vimicro generic vc0321
 vc032x		0ac8:0321	Vimicro generic vc0321
 vc032x		0ac8:0323	Vimicro Vc0323
 vc032x		0ac8:0323	Vimicro Vc0323

+ 1 - 2
MAINTAINERS

@@ -1198,9 +1198,7 @@ M:	hpa@zytor.com
 S:	Maintained
 S:	Maintained
 
 
 CPUSETS
 CPUSETS
-P:	Paul Jackson
 P:	Paul Menage
 P:	Paul Menage
-M:	pj@sgi.com
 M:	menage@google.com
 M:	menage@google.com
 L:	linux-kernel@vger.kernel.org
 L:	linux-kernel@vger.kernel.org
 W:	http://www.bullopensource.org/cpuset/
 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
 P:	Michael Kerrisk
 M:	mtk.manpages@gmail.com
 M:	mtk.manpages@gmail.com
 W:	http://www.kernel.org/doc/man-pages
 W:	http://www.kernel.org/doc/man-pages
+L:	linux-man@vger.kernel.org
 S:	Supported
 S:	Supported
 
 
 MARVELL LIBERTAS WIRELESS DRIVER
 MARVELL LIBERTAS WIRELESS DRIVER

+ 1 - 1
Makefile

@@ -1,7 +1,7 @@
 VERSION = 2
 VERSION = 2
 PATCHLEVEL = 6
 PATCHLEVEL = 6
 SUBLEVEL = 27
 SUBLEVEL = 27
-EXTRAVERSION = -rc8
+EXTRAVERSION = -rc9
 NAME = Rotary Wombat
 NAME = Rotary Wombat
 
 
 # *DOCUMENTATION*
 # *DOCUMENTATION*

+ 3 - 0
arch/ia64/include/asm/sections.h

@@ -11,6 +11,9 @@
 #include <asm-generic/sections.h>
 #include <asm-generic/sections.h>
 
 
 extern char __per_cpu_start[], __per_cpu_end[], __phys_per_cpu_start[];
 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___vtop_patchlist[], __end___vtop_patchlist[];
 extern char __start___rse_patchlist[], __end___rse_patchlist[];
 extern char __start___rse_patchlist[], __end___rse_patchlist[];
 extern char __start___mckinley_e9_bundles[], __end___mckinley_e9_bundles[];
 extern char __start___mckinley_e9_bundles[], __end___mckinley_e9_bundles[];

+ 5 - 4
arch/ia64/kernel/head.S

@@ -367,16 +367,17 @@ start_ap:
 	;;
 	;;
 #else
 #else
 (isAP)	br.few 2f
 (isAP)	br.few 2f
-	mov r20=r19
-	sub r19=r19,r18
+	movl r20=__cpu0_per_cpu
 	;;
 	;;
 	shr.u r18=r18,3
 	shr.u r18=r18,3
 1:
 1:
-	ld8 r21=[r20],8;;
-	st8[r19]=r21,8
+	ld8 r21=[r19],8;;
+	st8[r20]=r21,8
 	adds r18=-1,r18;;
 	adds r18=-1,r18;;
 	cmp4.lt p7,p6=0,r18
 	cmp4.lt p7,p6=0,r18
 (p7)	br.cond.dptk.few 1b
 (p7)	br.cond.dptk.few 1b
+	mov r19=r20
+	;;
 2:
 2:
 #endif
 #endif
 	tpa r19=r19
 	tpa r19=r19

+ 5 - 3
arch/ia64/kernel/vmlinux.lds.S

@@ -215,9 +215,6 @@ SECTIONS
   /* Per-cpu data: */
   /* Per-cpu data: */
   percpu : { } :percpu
   percpu : { } :percpu
   . = ALIGN(PERCPU_PAGE_SIZE);
   . = ALIGN(PERCPU_PAGE_SIZE);
-#ifdef	CONFIG_SMP
-  . = . + PERCPU_PAGE_SIZE;	/* cpu0 per-cpu space */
-#endif
   __phys_per_cpu_start = .;
   __phys_per_cpu_start = .;
   .data.percpu PERCPU_ADDR : AT(__phys_per_cpu_start - LOAD_OFFSET)
   .data.percpu PERCPU_ADDR : AT(__phys_per_cpu_start - LOAD_OFFSET)
 	{
 	{
@@ -233,6 +230,11 @@ SECTIONS
   data : { } :data
   data : { } :data
   .data : AT(ADDR(.data) - LOAD_OFFSET)
   .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
 		DATA_DATA
 		*(.data1)
 		*(.data1)
 		*(.gnu.linkonce.d*)
 		*(.gnu.linkonce.d*)

+ 1 - 1
arch/ia64/mm/contig.c

@@ -163,7 +163,7 @@ per_cpu_init (void)
 	 * get_zeroed_page().
 	 * get_zeroed_page().
 	 */
 	 */
 	if (first_time) {
 	if (first_time) {
-		void *cpu0_data = __phys_per_cpu_start - PERCPU_PAGE_SIZE;
+		void *cpu0_data = __cpu0_per_cpu;
 
 
 		first_time=0;
 		first_time=0;
 
 

+ 1 - 1
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) {
 	for_each_possible_early_cpu(cpu) {
 		if (cpu == 0) {
 		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_offset[cpu] = (char*)cpu0_data -
 				__per_cpu_start;
 				__per_cpu_start;
 		} else if (node == node_cpuid[cpu].nid) {
 		} else if (node == node_cpuid[cpu].nid) {

+ 20 - 33
arch/mips/Kconfig

@@ -211,6 +211,7 @@ config MIPS_MALTA
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_LITTLE_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_MULTITHREADING
 	select SYS_SUPPORTS_SMARTMIPS
 	select SYS_SUPPORTS_SMARTMIPS
 	help
 	help
@@ -1403,7 +1404,6 @@ config MIPS_MT_SMTC
 	depends on CPU_MIPS32_R2
 	depends on CPU_MIPS32_R2
 	#depends on CPU_MIPS64_R2		# once there is hardware ...
 	#depends on CPU_MIPS64_R2		# once there is hardware ...
 	depends on SYS_SUPPORTS_MULTITHREADING
 	depends on SYS_SUPPORTS_MULTITHREADING
-	select GENERIC_CLOCKEVENTS_BROADCAST
 	select CPU_MIPSR2_IRQ_VI
 	select CPU_MIPSR2_IRQ_VI
 	select CPU_MIPSR2_IRQ_EI
 	select CPU_MIPSR2_IRQ_EI
 	select MIPS_MT
 	select MIPS_MT
@@ -1451,32 +1451,17 @@ config MIPS_VPE_LOADER
 	  Includes a loader for loading an elf relocatable object
 	  Includes a loader for loading an elf relocatable object
 	  onto another VPE and running it.
 	  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
 config MIPS_MT_SMTC_IM_BACKSTOP
 	bool "Use per-TC register bits as backstop for inhibited IM bits"
 	bool "Use per-TC register bits as backstop for inhibited IM bits"
 	depends on MIPS_MT_SMTC
 	depends on MIPS_MT_SMTC
-	default y
+	default n
 	help
 	help
 	  To support multiple TC microthreads acting as "CPUs" within
 	  To support multiple TC microthreads acting as "CPUs" within
 	  a VPE, VPE-wide interrupt mask bits must be specially manipulated
 	  a VPE, VPE-wide interrupt mask bits must be specially manipulated
 	  during interrupt handling. To support legacy drivers and interrupt
 	  during interrupt handling. To support legacy drivers and interrupt
 	  controller management code, SMTC has a "backstop" to track and
 	  controller management code, SMTC has a "backstop" to track and
 	  if necessary restore the interrupt mask. This has some performance
 	  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
 config MIPS_MT_SMTC_IRQAFF
 	bool "Support IRQ affinity API"
 	bool "Support IRQ affinity API"
@@ -1486,10 +1471,8 @@ config MIPS_MT_SMTC_IRQAFF
 	  Enables SMP IRQ affinity API (/proc/irq/*/smp_affinity, etc.)
 	  Enables SMP IRQ affinity API (/proc/irq/*/smp_affinity, etc.)
 	  for SMTC Linux kernel. Requires platform support, of which
 	  for SMTC Linux kernel. Requires platform support, of which
 	  an example can be found in the MIPS kernel i8259 and Malta
 	  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
 config MIPS_VPE_LOADER_TOM
 	bool "Load VPE program into memory hidden from linux"
 	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
 	  "exit" syscall notifying other kernel modules the SP program is
 	  exiting.  You probably want to say yes here.
 	  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
 config SB1_PASS_1_WORKAROUNDS
 	bool
 	bool
 	depends on CPU_SB1_PASS_1
 	depends on CPU_SB1_PASS_1
@@ -1693,6 +1688,9 @@ config SMP
 config SMP_UP
 config SMP_UP
 	bool
 	bool
 
 
+config SYS_SUPPORTS_MIPS_CMP
+	bool
+
 config SYS_SUPPORTS_SMP
 config SYS_SUPPORTS_SMP
 	bool
 	bool
 
 
@@ -1740,17 +1738,6 @@ config NR_CPUS
 	  performance should round up your number of processors to the next
 	  performance should round up your number of processors to the next
 	  power of two.
 	  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"
 source "kernel/time/Kconfig"
 
 
 #
 #

+ 1 - 0
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_BCM1480)	+= cevt-bcm1480.o
 obj-$(CONFIG_CEVT_R4K)		+= cevt-r4k.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_DS1287)	+= cevt-ds1287.o
 obj-$(CONFIG_CEVT_GT641XX)	+= cevt-gt641xx.o
 obj-$(CONFIG_CEVT_GT641XX)	+= cevt-gt641xx.o
 obj-$(CONFIG_CEVT_SB1250)	+= cevt-sb1250.o
 obj-$(CONFIG_CEVT_SB1250)	+= cevt-sb1250.o

+ 48 - 125
arch/mips/kernel/cevt-r4k.c

@@ -12,6 +12,14 @@
 
 
 #include <asm/smtc_ipi.h>
 #include <asm/smtc_ipi.h>
 #include <asm/time.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,
 static int mips_next_event(unsigned long delta,
                            struct clock_event_device *evt)
                            struct clock_event_device *evt)
@@ -19,60 +27,27 @@ static int mips_next_event(unsigned long delta,
 	unsigned int cnt;
 	unsigned int cnt;
 	int res;
 	int res;
 
 
-#ifdef CONFIG_MIPS_MT_SMTC
-	{
-	unsigned long flags, vpflags;
-	local_irq_save(flags);
-	vpflags = dvpe();
-#endif
 	cnt = read_c0_count();
 	cnt = read_c0_count();
 	cnt += delta;
 	cnt += delta;
 	write_c0_compare(cnt);
 	write_c0_compare(cnt);
 	res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
 	res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
-#ifdef CONFIG_MIPS_MT_SMTC
-	evpe(vpflags);
-	local_irq_restore(flags);
-	}
-#endif
 	return res;
 	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 ...  */
 	/* 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;
 	const int r2 = cpu_has_mips_r2;
 	struct clock_event_device *cd;
 	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.
 	 * interrupt.  Being the paranoiacs we are we check anyway.
 	 */
 	 */
 	if (!r2 || (read_c0_cause() & (1 << 30))) {
 	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 = &per_cpu(mips_clockevent_device, cpu);
 		cd->event_handler(cd);
 		cd->event_handler(cd);
 	}
 	}
@@ -107,65 +78,16 @@ out:
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
-static struct irqaction c0_compare_irqaction = {
+#endif /* Not CONFIG_MIPS_MT_SMTC */
+
+struct irqaction c0_compare_irqaction = {
 	.handler = c0_compare_interrupt,
 	.handler = c0_compare_interrupt,
-#ifdef CONFIG_MIPS_MT_SMTC
-	.flags = IRQF_DISABLED,
-#else
 	.flags = IRQF_DISABLED | IRQF_PERCPU,
 	.flags = IRQF_DISABLED | IRQF_PERCPU,
-#endif
 	.name = "timer",
 	.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;
 	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 delta;
 	unsigned int cnt;
 	unsigned int cnt;
@@ -187,7 +125,7 @@ static int c0_compare_int_usable(void)
 	 */
 	 */
 	if (c0_compare_int_pending()) {
 	if (c0_compare_int_pending()) {
 		write_c0_compare(read_c0_count());
 		write_c0_compare(read_c0_count());
-		irq_disable_hazard();
+		compare_change_hazard();
 		if (c0_compare_int_pending())
 		if (c0_compare_int_pending())
 			return 0;
 			return 0;
 	}
 	}
@@ -196,7 +134,7 @@ static int c0_compare_int_usable(void)
 		cnt = read_c0_count();
 		cnt = read_c0_count();
 		cnt += delta;
 		cnt += delta;
 		write_c0_compare(cnt);
 		write_c0_compare(cnt);
-		irq_disable_hazard();
+		compare_change_hazard();
 		if ((int)(read_c0_count() - cnt) < 0)
 		if ((int)(read_c0_count() - cnt) < 0)
 		    break;
 		    break;
 		/* increase delta if the timer was already expired */
 		/* 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)
 	while ((int)(read_c0_count() - cnt) <= 0)
 		;	/* Wait for expiry  */
 		;	/* Wait for expiry  */
 
 
+	compare_change_hazard();
 	if (!c0_compare_int_pending())
 	if (!c0_compare_int_pending())
 		return 0;
 		return 0;
 
 
 	write_c0_compare(read_c0_count());
 	write_c0_compare(read_c0_count());
-	irq_disable_hazard();
+	compare_change_hazard();
 	if (c0_compare_int_pending())
 	if (c0_compare_int_pending())
 		return 0;
 		return 0;
 
 
@@ -219,6 +158,8 @@ static int c0_compare_int_usable(void)
 	return 1;
 	return 1;
 }
 }
 
 
+#ifndef CONFIG_MIPS_MT_SMTC
+
 int __cpuinit mips_clockevent_init(void)
 int __cpuinit mips_clockevent_init(void)
 {
 {
 	uint64_t mips_freq = mips_hpt_frequency;
 	uint64_t mips_freq = mips_hpt_frequency;
@@ -229,17 +170,6 @@ int __cpuinit mips_clockevent_init(void)
 	if (!cpu_has_counter || !mips_hpt_frequency)
 	if (!cpu_has_counter || !mips_hpt_frequency)
 		return -ENXIO;
 		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())
 	if (!c0_compare_int_usable())
 		return -ENXIO;
 		return -ENXIO;
 
 
@@ -265,13 +195,9 @@ int __cpuinit mips_clockevent_init(void)
 
 
 	cd->rating		= 300;
 	cd->rating		= 300;
 	cd->irq			= irq;
 	cd->irq			= irq;
-#ifdef CONFIG_MIPS_MT_SMTC
-	cd->cpumask		= CPU_MASK_ALL;
-#else
 	cd->cpumask		= cpumask_of_cpu(cpu);
 	cd->cpumask		= cpumask_of_cpu(cpu);
-#endif
 	cd->set_next_event	= mips_next_event;
 	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;
 	cd->event_handler	= mips_event_handler;
 
 
 	clockevents_register_device(cd);
 	clockevents_register_device(cd);
@@ -281,12 +207,9 @@ int __cpuinit mips_clockevent_init(void)
 
 
 	cp0_timer_irq_installed = 1;
 	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);
 	setup_irq(irq, &c0_compare_irqaction);
-#endif
 
 
 	return 0;
 	return 0;
 }
 }
+
+#endif /* Not CONFIG_MIPS_MT_SMTC */

+ 321 - 0
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;
+}

+ 7 - 3
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
  * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes
  * using this version a gamble.
  * using this version a gamble.
  */
  */
-static void r4k_wait_irqoff(void)
+void r4k_wait_irqoff(void)
 {
 {
 	local_irq_disable();
 	local_irq_disable();
 	if (!need_resched())
 	if (!need_resched())
-		__asm__("	.set	mips3		\n"
+		__asm__("	.set	push		\n"
+			"	.set	mips3		\n"
 			"	wait			\n"
 			"	wait			\n"
-			"	.set	mips0		\n");
+			"	.set	pop		\n");
 	local_irq_enable();
 	local_irq_enable();
+	__asm__(" 	.globl __pastwait	\n"
+		"__pastwait:			\n");
+	return;
 }
 }
 
 
 /*
 /*

+ 5 - 5
arch/mips/kernel/entry.S

@@ -79,11 +79,6 @@ FEXPORT(syscall_exit)
 
 
 FEXPORT(restore_all)			# restore full frame
 FEXPORT(restore_all)			# restore full frame
 #ifdef CONFIG_MIPS_MT_SMTC
 #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
 #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
 /* Re-arm any temporarily masked interrupts not explicitly "acked" */
 /* Re-arm any temporarily masked interrupts not explicitly "acked" */
 	mfc0	v0, CP0_TCSTATUS
 	mfc0	v0, CP0_TCSTATUS
@@ -112,6 +107,11 @@ FEXPORT(restore_all)			# restore full frame
 	xor	t0, t0, t3
 	xor	t0, t0, t3
 	mtc0	t0, CP0_TCCONTEXT
 	mtc0	t0, CP0_TCCONTEXT
 #endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
 #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 */
 #endif /* CONFIG_MIPS_MT_SMTC */
 	.set	noat
 	.set	noat
 	RESTORE_TEMP
 	RESTORE_TEMP

+ 2 - 2
arch/mips/kernel/genex.S

@@ -282,8 +282,8 @@ NESTED(except_vec_vi_handler, 0, sp)
 	and	t0, a0, t1
 	and	t0, a0, t1
 #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
 #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
 	mfc0	t2, CP0_TCCONTEXT
 	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 */
 #endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
 	xor	t1, t1, t0
 	xor	t1, t1, t0
 	mtc0	t1, CP0_STATUS
 	mtc0	t1, CP0_STATUS

+ 1 - 0
arch/mips/kernel/head.S

@@ -22,6 +22,7 @@
 #include <asm/irqflags.h>
 #include <asm/irqflags.h>
 #include <asm/regdef.h>
 #include <asm/regdef.h>
 #include <asm/page.h>
 #include <asm/page.h>
+#include <asm/pgtable-bits.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
 #include <asm/stackframe.h>
 
 

+ 1 - 1
arch/mips/kernel/mips-mt-fpaff.c

@@ -159,7 +159,7 @@ __setup("fpaff=", fpaff_thresh);
 /*
 /*
  * FPU Use Factor empirically derived from experiments on 34K
  * FPU Use Factor empirically derived from experiments on 34K
  */
  */
-#define FPUSEFACTOR 333
+#define FPUSEFACTOR 2000
 
 
 static __init int mt_fp_affinity_init(void)
 static __init int mt_fp_affinity_init(void)
 {
 {

+ 9 - 10
arch/mips/kernel/process.c

@@ -55,7 +55,7 @@ void __noreturn cpu_idle(void)
 	while (1) {
 	while (1) {
 		tick_nohz_stop_sched_tick(1);
 		tick_nohz_stop_sched_tick(1);
 		while (!need_resched()) {
 		while (!need_resched()) {
-#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
+#ifdef CONFIG_MIPS_MT_SMTC
 			extern void smtc_idle_loop_hook(void);
 			extern void smtc_idle_loop_hook(void);
 
 
 			smtc_idle_loop_hook();
 			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);
 	p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
 	childregs->cp0_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);
 	clear_tsk_thread_flag(p, TIF_USEDFPU);
 
 
 #ifdef CONFIG_MIPS_MT_FPAFF
 #ifdef CONFIG_MIPS_MT_FPAFF
 	clear_tsk_thread_flag(p, TIF_FPUBOUND);
 	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 */
 #endif /* CONFIG_MIPS_MT_FPAFF */
 
 
 	if (clone_flags & CLONE_SETTLS)
 	if (clone_flags & CLONE_SETTLS)

+ 1 - 1
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 */
 		case FPC_EIR: {	/* implementation / version register */
 			unsigned int flags;
 			unsigned int flags;
 #ifdef CONFIG_MIPS_MT_SMTC
 #ifdef CONFIG_MIPS_MT_SMTC
-			unsigned int irqflags;
+			unsigned long irqflags;
 			unsigned int mtflags;
 			unsigned int mtflags;
 #endif /* CONFIG_MIPS_MT_SMTC */
 #endif /* CONFIG_MIPS_MT_SMTC */
 
 

+ 137 - 123
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/clockchips.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
@@ -21,7 +38,6 @@
 #include <asm/time.h>
 #include <asm/time.h>
 #include <asm/addrspace.h>
 #include <asm/addrspace.h>
 #include <asm/smtc.h>
 #include <asm/smtc.h>
-#include <asm/smtc_ipi.h>
 #include <asm/smtc_proc.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];
 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
  * 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
 #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;
 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.
  * 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;
 	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()
 	write_tc_c0_tcstatus((read_tc_c0_tcstatus()
 			& ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT))
 			& ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT))
 			| TCSTATUS_A);
 			| 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 */
 	/* Bind tc to vpe */
 	write_tc_c0_tcbind(vpe);
 	write_tc_c0_tcbind(vpe);
 	/* In general, all TCs should have the same cpu_data indications */
 	/* 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].options &= ~MIPS_CPU_FPU;
 	cpu_data[cpu].vpe_id = vpe;
 	cpu_data[cpu].vpe_id = vpe;
 	cpu_data[cpu].tc_id = tc;
 	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;
 	int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu;
 	unsigned long flags;
 	unsigned long flags;
@@ -363,13 +387,13 @@ void mipsmt_prepare_cpus(void)
 		IPIQ[i].head = IPIQ[i].tail = NULL;
 		IPIQ[i].head = IPIQ[i].tail = NULL;
 		spin_lock_init(&IPIQ[i].lock);
 		spin_lock_init(&IPIQ[i].lock);
 		IPIQ[i].depth = 0;
 		IPIQ[i].depth = 0;
-		atomic_set(&ipi_timer_latch[i], 0);
 	}
 	}
 
 
 	/* cpu_data index starts at zero */
 	/* cpu_data index starts at zero */
 	cpu = 0;
 	cpu = 0;
 	cpu_data[cpu].vpe_id = 0;
 	cpu_data[cpu].vpe_id = 0;
 	cpu_data[cpu].tc_id = 0;
 	cpu_data[cpu].tc_id = 0;
+	cpu_data[cpu].core = (read_c0_ebase() >> 1) & 0xff;
 	cpu++;
 	cpu++;
 
 
 	/* Report on boot-time options */
 	/* Report on boot-time options */
@@ -484,7 +508,8 @@ void mipsmt_prepare_cpus(void)
 			write_vpe_c0_compare(0);
 			write_vpe_c0_compare(0);
 			/* Propagate Config7 */
 			/* Propagate Config7 */
 			write_vpe_c0_config7(read_c0_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 */
 		/* enable multi-threading within VPE */
 		write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE);
 		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)
 void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle)
 {
 {
 	extern u32 kernelsp[NR_CPUS];
 	extern u32 kernelsp[NR_CPUS];
-	long flags;
+	unsigned long flags;
 	int mtflags;
 	int mtflags;
 
 
 	LOCK_MT_PRA();
 	LOCK_MT_PRA();
@@ -585,24 +610,22 @@ void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle)
 
 
 void smtc_init_secondary(void)
 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();
 	local_irq_enable();
 }
 }
 
 
 void smtc_smp_finish(void)
 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",
 	printk("TC %d going on-line as CPU %d\n",
 		cpu_data[smp_processor_id()].tc_id, smp_processor_id());
 		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;
 	int tcstatus;
 	struct smtc_ipi *pipi;
 	struct smtc_ipi *pipi;
-	long flags;
+	unsigned long flags;
 	int mtflags;
 	int mtflags;
+	unsigned long tcrestart;
+	extern void r4k_wait_irqoff(void), __pastwait(void);
 
 
 	if (cpu == smp_processor_id()) {
 	if (cpu == smp_processor_id()) {
 		printk("Cannot Send IPI to self!\n");
 		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->arg = (void *)action;
 	pipi->dest = cpu;
 	pipi->dest = cpu;
 	if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
 	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 */
 		/* If not on same VPE, enqueue and send cross-VPE interrupt */
 		smtc_ipi_nq(&IPIQ[cpu], pipi);
 		smtc_ipi_nq(&IPIQ[cpu], pipi);
 		LOCK_CORE_PRA();
 		LOCK_CORE_PRA();
@@ -800,22 +823,29 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
 
 
 		if ((tcstatus & TCSTATUS_IXMT) != 0) {
 		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);
 			write_tc_c0_tchalt(0);
 			UNLOCK_CORE_PRA();
 			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);
 			smtc_ipi_nq(&IPIQ[cpu], pipi);
 		} else {
 		} else {
-			if (type == SMTC_CLOCK_TICK)
-				atomic_inc(&ipi_timer_latch[cpu]);
+postdirect:
 			post_direct_ipi(cpu, pipi);
 			post_direct_ipi(cpu, pipi);
 			write_tc_c0_tchalt(0);
 			write_tc_c0_tchalt(0);
 			UNLOCK_CORE_PRA();
 			UNLOCK_CORE_PRA();
@@ -883,7 +913,7 @@ static void ipi_call_interrupt(void)
 	smp_call_function_interrupt();
 	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)
 void ipi_decode(struct smtc_ipi *pipi)
 {
 {
@@ -891,20 +921,13 @@ void ipi_decode(struct smtc_ipi *pipi)
 	struct clock_event_device *cd;
 	struct clock_event_device *cd;
 	void *arg_copy = pipi->arg;
 	void *arg_copy = pipi->arg;
 	int type_copy = pipi->type;
 	int type_copy = pipi->type;
-	int ticks;
-
 	smtc_ipi_nq(&freeIPIq, pipi);
 	smtc_ipi_nq(&freeIPIq, pipi);
 	switch (type_copy) {
 	switch (type_copy) {
 	case SMTC_CLOCK_TICK:
 	case SMTC_CLOCK_TICK:
 		irq_enter();
 		irq_enter();
 		kstat_this_cpu.irqs[MIPS_CPU_IRQ_BASE + 1]++;
 		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();
 		irq_exit();
 		break;
 		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)
 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,
 	 * Test is not atomic, but much faster than a dequeue,
 	 * and the vast majority of invocations will have a null queue.
 	 * 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);
 			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;
 	struct smtc_ipi *pipi;
 	unsigned long tcstatus;
 	unsigned long tcstatus;
 	int sent;
 	int sent;
-	long flags;
+	unsigned long flags;
 	unsigned int mtflags;
 	unsigned int mtflags;
 	unsigned int vpflags;
 	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-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();
 	unsigned int cpu = smp_processor_id();
 
 
 	/*
 	/*
 	 * To the extent that we've ever turned interrupts off,
 	 * To the extent that we've ever turned interrupts off,
 	 * we may have accumulated deferred IPIs.  This is subtle.
 	 * 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
 	 * we should be OK:  If we pick up something and dispatch
 	 * it here, that's great. If we see nothing, but concurrent
 	 * it here, that's great. If we see nothing, but concurrent
 	 * with this operation, another TC sends us an IPI, IXMT
 	 * with this operation, another TC sends us an IPI, IXMT
 	 * is clear, and we'll handle it as a real pseudo-interrupt
 	 * 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);
 			self_ipi(pipi);
 			smtc_cpu_stats[cpu].selfipis++;
 			smtc_cpu_stats[cpu].selfipis++;
 		}
 		}
 	}
 	}
 }
 }
 
 
-void smtc_ipi_replay(void)
-{
-	raw_local_irq_disable();
-	__smtc_ipi_replay();
-}
-
 EXPORT_SYMBOL(smtc_ipi_replay);
 EXPORT_SYMBOL(smtc_ipi_replay);
 
 
 void smtc_idle_loop_hook(void)
 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);
 	emt(mtflags);
 	local_irq_restore(flags);
 	local_irq_restore(flags);
 	if (pdb_msg != &id_ho_db_msg[0])
 	if (pdb_msg != &id_ho_db_msg[0])
 		printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
 		printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
 #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
 #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)
 void smtc_soft_dump(void)
@@ -1242,10 +1260,6 @@ void smtc_soft_dump(void)
 		printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
 		printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
 	}
 	}
 	smtc_ipi_qdump();
 	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",
 	printk("%d Recoveries of \"stolen\" FPU\n",
 	       atomic_read(&smtc_fpu_recoveries));
 	       atomic_read(&smtc_fpu_recoveries));
 }
 }

+ 4 - 2
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)) {
 		if (cpus_intersects(current->cpus_allowed, mt_fpu_cpumask)) {
 			cpumask_t tmask;
 			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_cpus_allowed(current, tmask);
 			set_thread_flag(TIF_FPUBOUND);
 			set_thread_flag(TIF_FPUBOUND);
 		}
 		}

+ 1 - 1
arch/mips/mti-malta/Makefile

@@ -15,6 +15,6 @@ obj-$(CONFIG_EARLY_PRINTK)	+= malta-console.o
 obj-$(CONFIG_PCI)		+= malta-pci.o
 obj-$(CONFIG_PCI)		+= malta-pci.o
 
 
 # FIXME FIXME FIXME
 # FIXME FIXME FIXME
-obj-$(CONFIG_MIPS_MT_SMTC)	+= malta_smtc.o
+obj-$(CONFIG_MIPS_MT_SMTC)	+= malta-smtc.o
 
 
 EXTRA_CFLAGS += -Werror
 EXTRA_CFLAGS += -Werror

+ 7 - 2
arch/mips/mti-malta/malta-smtc.c

@@ -84,12 +84,17 @@ static void msmtc_cpus_done(void)
 
 
 static void __init msmtc_smp_setup(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)
 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 = {
 struct plat_smp_ops msmtc_smp_ops = {

+ 2 - 1
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
 obj-$(CONFIG_I2C_BOARDINFO)	+= swarm-i2c.o

+ 85 - 0
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) */

+ 45 - 26
arch/mn10300/kernel/irq.c

@@ -20,22 +20,8 @@ EXPORT_SYMBOL(__mn10300_irq_enabled_epsw);
 atomic_t irq_err_count;
 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)
 static void mn10300_cpupic_ack(unsigned int irq)
 {
 {
 	u16 tmp;
 	u16 tmp;
@@ -60,26 +46,54 @@ static void mn10300_cpupic_mask_ack(unsigned int irq)
 static void mn10300_cpupic_unmask(unsigned int irq)
 static void mn10300_cpupic_unmask(unsigned int irq)
 {
 {
 	u16 tmp = GxICR(irq);
 	u16 tmp = GxICR(irq);
-	GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
+	GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
 	tmp = GxICR(irq);
 	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);
 	u16 tmp = GxICR(irq);
-	GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
+	GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
 	tmp = GxICR(irq);
 	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,
 	.ack		= mn10300_cpupic_ack,
 	.mask		= mn10300_cpupic_mask,
 	.mask		= mn10300_cpupic_mask,
 	.mask_ack	= mn10300_cpupic_mask_ack,
 	.mask_ack	= mn10300_cpupic_mask_ack,
 	.unmask		= mn10300_cpupic_unmask,
 	.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)
 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++)
 	for (irq = 0; irq < NR_IRQS; irq++)
 		if (irq_desc[irq].chip == &no_irq_type)
 		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();
 	unit_init_IRQ();
 }
 }
 
 

+ 1 - 1
arch/mn10300/unit-asb2303/unit-init.c

@@ -51,7 +51,7 @@ void __init unit_init_IRQ(void)
 		switch (GET_XIRQ_TRIGGER(extnum)) {
 		switch (GET_XIRQ_TRIGGER(extnum)) {
 		case XIRQ_TRIGGER_HILEVEL:
 		case XIRQ_TRIGGER_HILEVEL:
 		case XIRQ_TRIGGER_LOWLEVEL:
 		case XIRQ_TRIGGER_LOWLEVEL:
-			set_irq_handler(XIRQ2IRQ(extnum), handle_level_irq);
+			set_intr_postackable(XIRQ2IRQ(extnum));
 			break;
 			break;
 		default:
 		default:
 			break;
 			break;

+ 1 - 1
arch/mn10300/unit-asb2305/unit-init.c

@@ -52,7 +52,7 @@ void __init unit_init_IRQ(void)
 		switch (GET_XIRQ_TRIGGER(extnum)) {
 		switch (GET_XIRQ_TRIGGER(extnum)) {
 		case XIRQ_TRIGGER_HILEVEL:
 		case XIRQ_TRIGGER_HILEVEL:
 		case XIRQ_TRIGGER_LOWLEVEL:
 		case XIRQ_TRIGGER_LOWLEVEL:
-			set_irq_handler(XIRQ2IRQ(extnum), handle_level_irq);
+			set_intr_postackable(XIRQ2IRQ(extnum));
 			break;
 			break;
 		default:
 		default:
 			break;
 			break;

+ 53 - 53
arch/powerpc/boot/dts/holly.dts

@@ -133,61 +133,61 @@
 			reg = <0x00007400 0x00000400>;
 			reg = <0x00007400 0x00000400>;
 			big-endian;
 			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>;
 			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>;
 		};
 		};
 	};
 	};
 
 

+ 1 - 5
arch/powerpc/kernel/idle.c

@@ -34,11 +34,7 @@
 #include <asm/smp.h>
 #include <asm/smp.h>
 
 
 #ifdef CONFIG_HOTPLUG_CPU
 #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
 #else
 #define cpu_should_die()	0
 #define cpu_should_die()	0
 #endif
 #endif

+ 11 - 1
arch/powerpc/platforms/fsl_uli1575.c

@@ -219,11 +219,21 @@ static void __devinit quirk_final_uli5249(struct pci_dev *dev)
 	int i;
 	int i;
 	u8 *dummy;
 	u8 *dummy;
 	struct pci_bus *bus = dev->bus;
 	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++) {
 	for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
 		if ((bus->resource[i]) &&
 		if ((bus->resource[i]) &&
 			(bus->resource[i]->flags & IORESOURCE_MEM)) {
 			(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) {
 			if (dummy) {
 				in_8(dummy);
 				in_8(dummy);
 				iounmap(dummy);
 				iounmap(dummy);

+ 2 - 0
arch/s390/kernel/time.c

@@ -169,6 +169,8 @@ void init_cpu_timer(void)
 
 
 static void clock_comparator_interrupt(__u16 code)
 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 *);
 static void etr_timing_alert(struct etr_irq_parm *);

+ 54 - 34
arch/s390/lib/delay.c

@@ -1,14 +1,9 @@
 /*
 /*
- *  arch/s390/lib/delay.c
  *    Precise Delay Loops for S390
  *    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>
 #include <linux/sched.h>
@@ -29,30 +24,31 @@ void __delay(unsigned long loops)
 	asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
 	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);
 	end = get_clock() + ((u64) usecs << 12);
 	do {
 	do {
 		time = end < S390_lowcore.clock_comparator ?
 		time = end < S390_lowcore.clock_comparator ?
@@ -62,13 +58,37 @@ void __udelay(unsigned long usecs)
 		__load_psw_mask(mask);
 		__load_psw_mask(mask);
 		local_irq_disable();
 		local_irq_disable();
 	} while (get_clock() < end);
 	} 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();
 		_local_bh_enable();
-	set_clock_comparator(S390_lowcore.clock_comparator);
+		goto out;
+	}
+	__udelay_enabled(usecs);
+out:
 	local_irq_restore(flags);
 	local_irq_restore(flags);
+	preempt_enable();
 }
 }

+ 1 - 1
arch/x86/boot/compressed/relocs.c

@@ -492,7 +492,7 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
 			continue;
 			continue;
 		}
 		}
 		sh_symtab = sec_symtab->symtab;
 		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++) {
 		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
 			Elf32_Rel *rel;
 			Elf32_Rel *rel;
 			Elf32_Sym *sym;
 			Elf32_Sym *sym;

+ 16 - 0
arch/x86/kernel/acpi/boot.c

@@ -1603,6 +1603,14 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
 	 * is not connected at all.  Force ignoring BIOS IRQ0 pin2
 	 * is not connected at all.  Force ignoring BIOS IRQ0 pin2
 	 * override in that cases.
 	 * override in that cases.
 	 */
 	 */
+	{
+	 .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,
 	 .callback = dmi_ignore_irq0_timer_override,
 	 .ident = "HP NX6125 laptop",
 	 .ident = "HP NX6125 laptop",
@@ -1619,6 +1627,14 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
 		     DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"),
 		     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"),
+		     },
+	 },
 	{}
 	{}
 };
 };
 
 

+ 1 - 1
arch/x86/kernel/cpu/mtrr/main.c

@@ -834,7 +834,7 @@ static int __init enable_mtrr_cleanup_setup(char *str)
 		enable_mtrr_cleanup = 1;
 		enable_mtrr_cleanup = 1;
 	return 0;
 	return 0;
 }
 }
-early_param("enble_mtrr_cleanup", enable_mtrr_cleanup_setup);
+early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup);
 
 
 struct var_mtrr_state {
 struct var_mtrr_state {
 	unsigned long	range_startk;
 	unsigned long	range_startk;

+ 1 - 6
arch/x86/kernel/kgdb.c

@@ -455,12 +455,7 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
 		return NOTIFY_DONE;
 		return NOTIFY_DONE;
 
 
 	case DIE_NMI_IPI:
 	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;
 		return NOTIFY_DONE;
 
 
 	case DIE_NMIUNKNOWN:
 	case DIE_NMIUNKNOWN:

+ 11 - 9
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;
 	struct pci_dev *dev;
 	void *gatt;
 	void *gatt;
 	int i, error;
 	int i, error;
-	unsigned long start_pfn, end_pfn;
 
 
 	printk(KERN_INFO "PCI-DMA: Disabling AGP.\n");
 	printk(KERN_INFO "PCI-DMA: Disabling AGP.\n");
 	aper_size = aper_base = info->aper_size = 0;
 	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",
 	printk(KERN_INFO "PCI-DMA: aperture base @ %x size %u KB\n",
 	       aper_base, aper_size>>10);
 	       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;
 	return 0;
 
 
  nommu:
  nommu:
@@ -727,7 +720,8 @@ void __init gart_iommu_init(void)
 {
 {
 	struct agp_kern_info info;
 	struct agp_kern_info info;
 	unsigned long iommu_start;
 	unsigned long iommu_start;
-	unsigned long aper_size;
+	unsigned long aper_base, aper_size;
+	unsigned long start_pfn, end_pfn;
 	unsigned long scratch;
 	unsigned long scratch;
 	long i;
 	long i;
 
 
@@ -765,8 +759,16 @@ void __init gart_iommu_init(void)
 		return;
 		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");
 	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_size = check_iommu_size(info.aper_base, aper_size);
 	iommu_pages = iommu_size >> PAGE_SHIFT;
 	iommu_pages = iommu_size >> PAGE_SHIFT;
 
 

+ 1 - 1
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)
 				const void *desc)
 {
 {
 	u32 *ldt_entry = (u32 *)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,
 static void vmi_load_sp0(struct tss_struct *tss,

+ 4 - 9
drivers/accessibility/braille/braille_console.c

@@ -376,6 +376,8 @@ int braille_register_console(struct console *console, int index,
 	console->flags |= CON_ENABLED;
 	console->flags |= CON_ENABLED;
 	console->index = index;
 	console->index = index;
 	braille_co = console;
 	braille_co = console;
+	register_keyboard_notifier(&keyboard_notifier_block);
+	register_vt_notifier(&vt_notifier_block);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -383,15 +385,8 @@ int braille_unregister_console(struct console *console)
 {
 {
 	if (braille_co != console)
 	if (braille_co != console)
 		return -EINVAL;
 		return -EINVAL;
+	unregister_keyboard_notifier(&keyboard_notifier_block);
+	unregister_vt_notifier(&vt_notifier_block);
 	braille_co = NULL;
 	braille_co = NULL;
 	return 0;
 	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);

+ 4 - 1
drivers/acpi/glue.c

@@ -165,8 +165,11 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
 				"firmware_node");
 				"firmware_node");
 		ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
 		ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
 				"physical_node");
 				"physical_node");
-		if (acpi_dev->wakeup.flags.valid)
+		if (acpi_dev->wakeup.flags.valid) {
 			device_set_wakeup_capable(dev, true);
 			device_set_wakeup_capable(dev, true);
+			device_set_wakeup_enable(dev,
+						acpi_dev->wakeup.state.enabled);
+		}
 	}
 	}
 
 
 	return 0;
 	return 0;

+ 10 - 0
drivers/acpi/sleep/proc.c

@@ -377,6 +377,14 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
 	return 0;
 	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
 static ssize_t
 acpi_system_write_wakeup_device(struct file *file,
 acpi_system_write_wakeup_device(struct file *file,
 				const char __user * buffer,
 				const char __user * buffer,
@@ -411,6 +419,7 @@ acpi_system_write_wakeup_device(struct file *file,
 		}
 		}
 	}
 	}
 	if (found_dev) {
 	if (found_dev) {
+		physical_device_enable_wakeup(found_dev);
 		list_for_each_safe(node, next, &acpi_wakeup_device_list) {
 		list_for_each_safe(node, next, &acpi_wakeup_device_list) {
 			struct acpi_device *dev = container_of(node,
 			struct acpi_device *dev = container_of(node,
 							       struct
 							       struct
@@ -428,6 +437,7 @@ acpi_system_write_wakeup_device(struct file *file,
 				       dev->pnp.bus_id, found_dev->pnp.bus_id);
 				       dev->pnp.bus_id, found_dev->pnp.bus_id);
 				dev->wakeup.state.enabled =
 				dev->wakeup.state.enabled =
 				    found_dev->wakeup.state.enabled;
 				    found_dev->wakeup.state.enabled;
+				physical_device_enable_wakeup(dev);
 			}
 			}
 		}
 		}
 	}
 	}

+ 0 - 2
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)",
 		BT_ERR("%s urb %p submission failed (%d)",
 						hdev->name, urb, -err);
 						hdev->name, urb, -err);
 		usb_unanchor_urb(urb);
 		usb_unanchor_urb(urb);
-		kfree(buf);
 	}
 	}
 
 
 	usb_free_urb(urb);
 	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)",
 		BT_ERR("%s urb %p submission failed (%d)",
 						hdev->name, urb, -err);
 						hdev->name, urb, -err);
 		usb_unanchor_urb(urb);
 		usb_unanchor_urb(urb);
-		kfree(buf);
 	}
 	}
 
 
 	usb_free_urb(urb);
 	usb_free_urb(urb);

+ 5 - 3
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 },
 	{ USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
 
 
 	/* Broadcom BCM2046 */
 	/* Broadcom BCM2046 */
+	{ USB_DEVICE(0x0a5c, 0x2146), .driver_info = BTUSB_RESET },
 	{ USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET },
 	{ USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET },
 
 
 	/* Apple MacBook Pro with Broadcom chip */
 	/* Apple MacBook Pro with Broadcom chip */
@@ -113,6 +114,7 @@ static struct usb_device_id blacklist_table[] = {
 
 
 	/* Targus ACB10US */
 	/* Targus ACB10US */
 	{ USB_DEVICE(0x0a5c, 0x2100), .driver_info = BTUSB_RESET },
 	{ USB_DEVICE(0x0a5c, 0x2100), .driver_info = BTUSB_RESET },
+	{ USB_DEVICE(0x0a5c, 0x2154), .driver_info = BTUSB_RESET },
 
 
 	/* ANYCOM Bluetooth USB-200 and USB-250 */
 	/* ANYCOM Bluetooth USB-200 and USB-250 */
 	{ USB_DEVICE(0x0a5c, 0x2111), .driver_info = BTUSB_RESET },
 	{ 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, 0x0012), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU },
 	{ USB_DEVICE(0x050d, 0x0013), .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 */
 	/* Digianswer devices */
 	{ USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
 	{ USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
 	{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
 	{ 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)",
 		BT_ERR("%s urb %p submission failed (%d)",
 						hdev->name, urb, -err);
 						hdev->name, urb, -err);
 		usb_unanchor_urb(urb);
 		usb_unanchor_urb(urb);
-		kfree(buf);
 	}
 	}
 
 
 	usb_free_urb(urb);
 	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)",
 		BT_ERR("%s urb %p submission failed (%d)",
 						hdev->name, urb, -err);
 						hdev->name, urb, -err);
 		usb_unanchor_urb(urb);
 		usb_unanchor_urb(urb);
-		kfree(buf);
 	}
 	}
 
 
 	usb_free_urb(urb);
 	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)",
 		BT_ERR("%s urb %p submission failed (%d)",
 						hdev->name, urb, -err);
 						hdev->name, urb, -err);
 		usb_unanchor_urb(urb);
 		usb_unanchor_urb(urb);
-		kfree(buf);
 	}
 	}
 
 
 	usb_free_urb(urb);
 	usb_free_urb(urb);

+ 1 - 1
drivers/dma/dw_dmac.c

@@ -364,7 +364,7 @@ static void dw_dma_tasklet(unsigned long data)
 	int i;
 	int i;
 
 
 	status_block = dma_readl(dw, RAW.BLOCK);
 	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);
 	status_err = dma_readl(dw, RAW.ERROR);
 
 
 	dev_vdbg(dw->dma.dev, "tasklet: status_block=%x status_err=%x\n",
 	dev_vdbg(dw->dma.dev, "tasklet: status_block=%x status_err=%x\n",

+ 0 - 4
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
 	  to transfer data to and from memory.  Saying Y is safe and improves
 	  performance.
 	  performance.
 
 
-config BLK_DEV_IDE_SWARM
-	tristate "IDE for Sibyte evaluation boards"
-	depends on SIBYTE_SB1xxx_SOC
-
 config BLK_DEV_IDE_AU1XXX
 config BLK_DEV_IDE_AU1XXX
        bool "IDE for AMD Alchemy Au1200"
        bool "IDE for AMD Alchemy Au1200"
        depends on SOC_AU1200
        depends on SOC_AU1200

+ 5 - 1
drivers/ide/ide-cd.c

@@ -1661,7 +1661,9 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
 		cdi->mask &= ~CDC_PLAY_AUDIO;
 		cdi->mask &= ~CDC_PLAY_AUDIO;
 
 
 	mechtype = buf[8 + 6] >> 5;
 	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;
 		cdi->mask |= CDC_CLOSE_TRAY;
 
 
 	if (cdi->sanyo_slot > 0) {
 	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-8176", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },
 	{ "MATSHITADVD-ROM SR-8174", 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-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 }
 	{ NULL, NULL, 0 }
 };
 };
 
 

+ 1 - 1
drivers/ide/ide-dma.c

@@ -211,7 +211,7 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
 				xcount = bcount & 0xffff;
 				xcount = bcount & 0xffff;
 				if (is_trm290)
 				if (is_trm290)
 					xcount = ((xcount >> 2) - 1) << 16;
 					xcount = ((xcount >> 2) - 1) << 16;
-				if (xcount == 0x0000) {
+				else if (xcount == 0x0000) {
 	/* 
 	/* 
 	 * Most chipsets correctly interpret a length of 0x0000 as 64KB,
 	 * Most chipsets correctly interpret a length of 0x0000 as 64KB,
 	 * but at least one (e.g. CS5530) misinterprets it as zero (!).
 	 * but at least one (e.g. CS5530) misinterprets it as zero (!).

+ 1 - 1
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)
 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++) {
 	for (i = 0; ide_port_attrs[i]; i++) {
 		rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
 		rc = device_create_file(hwif->portdev, ide_port_attrs[i]);

+ 0 - 1
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
 obj-$(CONFIG_BLK_DEV_IDE_AU1XXX)	+= au1xxx-ide.o
 
 
 EXTRA_CFLAGS    := -Idrivers/ide
 EXTRA_CFLAGS    := -Idrivers/ide

+ 0 - 197
drivers/ide/mips/swarm.c

@@ -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);

+ 14 - 14
drivers/leds/leds-fsg.c

@@ -161,6 +161,16 @@ static int fsg_led_probe(struct platform_device *pdev)
 {
 {
 	int ret;
 	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);
 	ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
 	if (ret < 0)
 	if (ret < 0)
 		goto failwlan;
 		goto failwlan;
@@ -185,20 +195,8 @@ static int fsg_led_probe(struct platform_device *pdev)
 	if (ret < 0)
 	if (ret < 0)
 		goto failring;
 		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;
 	return ret;
 
 
- failremap:
-	led_classdev_unregister(&fsg_ring_led);
  failring:
  failring:
 	led_classdev_unregister(&fsg_sync_led);
 	led_classdev_unregister(&fsg_sync_led);
  failsync:
  failsync:
@@ -210,14 +208,14 @@ static int fsg_led_probe(struct platform_device *pdev)
  failwan:
  failwan:
 	led_classdev_unregister(&fsg_wlan_led);
 	led_classdev_unregister(&fsg_wlan_led);
  failwlan:
  failwlan:
+	iounmap(latch_address);
+ failremap:
 
 
 	return ret;
 	return ret;
 }
 }
 
 
 static int fsg_led_remove(struct platform_device *pdev)
 static int fsg_led_remove(struct platform_device *pdev)
 {
 {
-	iounmap(latch_address);
-
 	led_classdev_unregister(&fsg_wlan_led);
 	led_classdev_unregister(&fsg_wlan_led);
 	led_classdev_unregister(&fsg_wan_led);
 	led_classdev_unregister(&fsg_wan_led);
 	led_classdev_unregister(&fsg_sata_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_sync_led);
 	led_classdev_unregister(&fsg_ring_led);
 	led_classdev_unregister(&fsg_ring_led);
 
 
+	iounmap(latch_address);
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 38 - 32
drivers/leds/leds-pca955x.c

@@ -248,11 +248,10 @@ static int __devinit pca955x_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 					const struct i2c_device_id *id)
 {
 {
 	struct pca955x_led *pca955x;
 	struct pca955x_led *pca955x;
-	int i;
-	int err = -ENODEV;
 	struct pca955x_chipdef *chip;
 	struct pca955x_chipdef *chip;
 	struct i2c_adapter *adapter;
 	struct i2c_adapter *adapter;
 	struct led_platform_data *pdata;
 	struct led_platform_data *pdata;
+	int i, err;
 
 
 	chip = &pca955x_chipdefs[id->driver_data];
 	chip = &pca955x_chipdefs[id->driver_data];
 	adapter = to_i2c_adapter(client->dev.parent);
 	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++) {
 	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 */
 		/* Platform data can specify LED names and default triggers */
 		if (pdata) {
 		if (pdata) {
 			if (pdata->leds[i].name)
 			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)
 			if (pdata->leds[i].default_trigger)
-				pca955x->led_cdev.default_trigger =
+				pca955x[i].led_cdev.default_trigger =
 					pdata->leds[i].default_trigger;
 					pdata->leds[i].default_trigger;
 		} else {
 		} 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 */
 	/* Turn off LEDs */
@@ -336,23 +333,32 @@ static int __devinit pca955x_probe(struct i2c_client *client,
 	pca955x_write_psc(client, 1, 0);
 	pca955x_write_psc(client, 1, 0);
 
 
 	return 0;
 	return 0;
+
 exit:
 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;
 	return err;
 }
 }
 
 
 static int __devexit pca955x_remove(struct i2c_client *client)
 static int __devexit pca955x_remove(struct i2c_client *client)
 {
 {
 	struct pca955x_led *pca955x = i2c_get_clientdata(client);
 	struct pca955x_led *pca955x = i2c_get_clientdata(client);
-	int leds = pca955x->chipdef->bits;
 	int i;
 	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;
 	return 0;
 }
 }
 
 

+ 15 - 1
drivers/md/dm-mpath.c

@@ -63,6 +63,7 @@ struct multipath {
 
 
 	const char *hw_handler_name;
 	const char *hw_handler_name;
 	struct work_struct activate_path;
 	struct work_struct activate_path;
+	struct pgpath *pgpath_to_activate;
 	unsigned nr_priority_groups;
 	unsigned nr_priority_groups;
 	struct list_head priority_groups;
 	struct list_head priority_groups;
 	unsigned pg_init_required;	/* pg_init needs calling? */
 	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)
 static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
 {
 {
+	unsigned long flags;
 	struct pgpath *pgpath, *tmp;
 	struct pgpath *pgpath, *tmp;
 	struct multipath *m = ti->private;
 	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)
 		if (m->hw_handler_name)
 			scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
 			scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
 		dm_put_device(ti, pgpath->path.dev);
 		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);
 		free_pgpath(pgpath);
 	}
 	}
 }
 }
@@ -421,6 +427,7 @@ static void process_queued_ios(struct work_struct *work)
 		__choose_pgpath(m);
 		__choose_pgpath(m);
 
 
 	pgpath = m->current_pgpath;
 	pgpath = m->current_pgpath;
+	m->pgpath_to_activate = m->current_pgpath;
 
 
 	if ((pgpath && !m->queue_io) ||
 	if ((pgpath && !m->queue_io) ||
 	    (!pgpath && !m->queue_if_no_path))
 	    (!pgpath && !m->queue_if_no_path))
@@ -1093,8 +1100,15 @@ static void activate_path(struct work_struct *work)
 	int ret;
 	int ret;
 	struct multipath *m =
 	struct multipath *m =
 		container_of(work, struct multipath, activate_path);
 		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));
 	ret = scsi_dh_activate(bdev_get_queue(path->dev->bdev));
 	pg_init_done(path, ret);
 	pg_init_done(path, ret);
 }
 }

+ 8 - 4
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_table *map = dm_get_table(md);
 	struct dm_target *ti;
 	struct dm_target *ti;
 	sector_t max_sectors;
 	sector_t max_sectors;
-	int max_size;
+	int max_size = 0;
 
 
 	if (unlikely(!map))
 	if (unlikely(!map))
-		return 0;
+		goto out;
 
 
 	ti = dm_table_find_target(map, bvm->bi_sector);
 	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
 	 * 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)
 	if (max_size && ti->type->merge)
 		max_size = ti->type->merge(ti, bvm, biovec, max_size);
 		max_size = ti->type->merge(ti, bvm, biovec, max_size);
 
 
+out_table:
+	dm_table_put(map);
+
+out:
 	/*
 	/*
 	 * Always allow an entire first page
 	 * Always allow an entire first page
 	 */
 	 */
 	if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))
 	if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))
 		max_size = biovec->bv_len;
 		max_size = biovec->bv_len;
 
 
-	dm_table_put(map);
-
 	return max_size;
 	return max_size;
 }
 }
 
 

+ 1 - 0
drivers/media/common/tuners/tuner-xc2028.h

@@ -10,6 +10,7 @@
 #include "dvb_frontend.h"
 #include "dvb_frontend.h"
 
 
 #define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
 #define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
+#define XC3028L_DEFAULT_FIRMWARE "xc3028L-v36.fw"
 
 
 /*      Dmoduler		IF (kHz) */
 /*      Dmoduler		IF (kHz) */
 #define	XC3028_FE_DEFAULT	0		/* Don't load SCODE */
 #define	XC3028_FE_DEFAULT	0		/* Don't load SCODE */

+ 1 - 0
drivers/media/dvb/b2c2/flexcop-fe-tuner.c

@@ -491,6 +491,7 @@ static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
 	.demod_address = 0x53,
 	.demod_address = 0x53,
 	.invert = 1,
 	.invert = 1,
 	.repeated_start_workaround = 1,
 	.repeated_start_workaround = 1,
+	.serial_mpeg = 1,
 };
 };
 
 
 static struct itd1000_config skystar2_rev2_7_itd1000_config = {
 static struct itd1000_config skystar2_rev2_7_itd1000_config = {

+ 9 - 7
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)
 				       enum dmx_success success)
 {
 {
 	struct dmxdev_filter *dmxdevfilter = filter->priv;
 	struct dmxdev_filter *dmxdevfilter = filter->priv;
+	unsigned long flags;
 	int ret;
 	int ret;
 
 
 	if (dmxdevfilter->buffer.error) {
 	if (dmxdevfilter->buffer.error) {
 		wake_up(&dmxdevfilter->buffer.queue);
 		wake_up(&dmxdevfilter->buffer.queue);
 		return 0;
 		return 0;
 	}
 	}
-	spin_lock(&dmxdevfilter->dev->lock);
+	spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
 	if (dmxdevfilter->state != DMXDEV_STATE_GO) {
 	if (dmxdevfilter->state != DMXDEV_STATE_GO) {
-		spin_unlock(&dmxdevfilter->dev->lock);
+		spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
 		return 0;
 		return 0;
 	}
 	}
 	del_timer(&dmxdevfilter->timer);
 	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)
 	if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
 		dmxdevfilter->state = DMXDEV_STATE_DONE;
 		dmxdevfilter->state = DMXDEV_STATE_DONE;
-	spin_unlock(&dmxdevfilter->dev->lock);
+	spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
 	wake_up(&dmxdevfilter->buffer.queue);
 	wake_up(&dmxdevfilter->buffer.queue);
 	return 0;
 	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 dmxdev_filter *dmxdevfilter = feed->priv;
 	struct dvb_ringbuffer *buffer;
 	struct dvb_ringbuffer *buffer;
+	unsigned long flags;
 	int ret;
 	int ret;
 
 
-	spin_lock(&dmxdevfilter->dev->lock);
+	spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
 	if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
 	if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
-		spin_unlock(&dmxdevfilter->dev->lock);
+		spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -417,7 +419,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
 	else
 	else
 		buffer = &dmxdevfilter->dev->dvr_buffer;
 		buffer = &dmxdevfilter->dev->dvr_buffer;
 	if (buffer->error) {
 	if (buffer->error) {
-		spin_unlock(&dmxdevfilter->dev->lock);
+		spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
 		wake_up(&buffer->queue);
 		wake_up(&buffer->queue);
 		return 0;
 		return 0;
 	}
 	}
@@ -428,7 +430,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
 		dvb_ringbuffer_flush(buffer);
 		dvb_ringbuffer_flush(buffer);
 		buffer->error = ret;
 		buffer->error = ret;
 	}
 	}
-	spin_unlock(&dmxdevfilter->dev->lock);
+	spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
 	wake_up(&buffer->queue);
 	wake_up(&buffer->queue);
 	return 0;
 	return 0;
 }
 }

+ 10 - 6
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,
 void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
 			      size_t count)
 			      size_t count)
 {
 {
-	spin_lock(&demux->lock);
+	unsigned long flags;
+
+	spin_lock_irqsave(&demux->lock, flags);
 
 
 	while (count--) {
 	while (count--) {
 		if (buf[0] == 0x47)
 		if (buf[0] == 0x47)
@@ -407,16 +409,17 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
 		buf += 188;
 		buf += 188;
 	}
 	}
 
 
-	spin_unlock(&demux->lock);
+	spin_unlock_irqrestore(&demux->lock, flags);
 }
 }
 
 
 EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
 EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
 
 
 void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
 void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
 {
 {
+	unsigned long flags;
 	int p = 0, i, j;
 	int p = 0, i, j;
 
 
-	spin_lock(&demux->lock);
+	spin_lock_irqsave(&demux->lock, flags);
 
 
 	if (demux->tsbufp) {
 	if (demux->tsbufp) {
 		i = demux->tsbufp;
 		i = demux->tsbufp;
@@ -449,17 +452,18 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
 	}
 	}
 
 
 bailout:
 bailout:
-	spin_unlock(&demux->lock);
+	spin_unlock_irqrestore(&demux->lock, flags);
 }
 }
 
 
 EXPORT_SYMBOL(dvb_dmx_swfilter);
 EXPORT_SYMBOL(dvb_dmx_swfilter);
 
 
 void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
 void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
 {
 {
+	unsigned long flags;
 	int p = 0, i, j;
 	int p = 0, i, j;
 	u8 tmppack[188];
 	u8 tmppack[188];
 
 
-	spin_lock(&demux->lock);
+	spin_lock_irqsave(&demux->lock, flags);
 
 
 	if (demux->tsbufp) {
 	if (demux->tsbufp) {
 		i = 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:
 bailout:
-	spin_unlock(&demux->lock);
+	spin_unlock_irqrestore(&demux->lock, flags);
 }
 }
 
 
 EXPORT_SYMBOL(dvb_dmx_swfilter_204);
 EXPORT_SYMBOL(dvb_dmx_swfilter_204);

+ 7 - 4
drivers/media/dvb/frontends/s5h1420.c

@@ -59,7 +59,7 @@ struct s5h1420_state {
 	 * it does not support repeated-start, workaround: write addr-1
 	 * it does not support repeated-start, workaround: write addr-1
 	 * and then read
 	 * and then read
 	 */
 	 */
-	u8 shadow[255];
+	u8 shadow[256];
 };
 };
 
 
 static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
 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)
 		if (ret != 3)
 			return ret;
 			return ret;
 	} else {
 	} 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;
 			return ret;
 	}
 	}
 
 
@@ -823,7 +826,7 @@ static int s5h1420_init (struct dvb_frontend* fe)
 	struct s5h1420_state* state = fe->demodulator_priv;
 	struct s5h1420_state* state = fe->demodulator_priv;
 
 
 	/* disable power down and do reset */
 	/* 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);
 	s5h1420_writereg(state, 0x02, state->CON_1_val);
 	msleep(10);
 	msleep(10);
 	s5h1420_reset(state);
 	s5h1420_reset(state);

+ 5 - 3
drivers/media/dvb/frontends/s5h1420.h

@@ -32,10 +32,12 @@ struct s5h1420_config
 	u8 demod_address;
 	u8 demod_address;
 
 
 	/* does the inversion require inversion? */
 	/* 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))
 #if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE))

+ 3 - 1
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 },
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },
 	{ USB_DEVICE(0x2040, 0x5500),
 	{ USB_DEVICE(0x2040, 0x5500),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0x5510),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ USB_DEVICE(0x2040, 0x5580),
 	{ USB_DEVICE(0x2040, 0x5580),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ USB_DEVICE(0x2040, 0x5590),
 	{ 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",
 		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
 	},
 	},
 	[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
 	[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
-		.name	= "Hauppauge WinTV-Nova-T-MiniStick",
+		.name	= "Hauppauge WinTV MiniStick",
 		.type	= SMS_NOVA_B0,
 		.type	= SMS_NOVA_B0,
 		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw",
 		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw",
 	},
 	},

+ 1 - 1
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);
 	dprintk("bttv: open minor=%d\n",minor);
 
 
 	for (i = 0; i < bttv_num; i++) {
 	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];
 			btv = &bttvs[i];
 			break;
 			break;
 		}
 		}

+ 1 - 0
drivers/media/video/cafe_ccic.c

@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
+#include <linux/mm.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>

+ 4 - 1
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)
 static int submit_urbs(struct camera_data *cam)
 {
 {
 	struct urb *urb;
 	struct urb *urb;
-	int fx, err, i;
+	int fx, err, i, j;
 
 
 	for(i=0; i<NUM_SBUF; ++i) {
 	for(i=0; i<NUM_SBUF; ++i) {
 		if (cam->sbuf[i].data)
 		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);
 		urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
 		if (!urb) {
 		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;
 			return -ENOMEM;
 		}
 		}
 
 

+ 1 - 1
drivers/media/video/cx18/cx18-cards.c

@@ -163,7 +163,7 @@ static const struct cx18_card cx18_card_h900 = {
 	},
 	},
 	.audio_inputs = {
 	.audio_inputs = {
 		{ CX18_CARD_INPUT_AUD_TUNER,
 		{ CX18_CARD_INPUT_AUD_TUNER,
-		  CX18_AV_AUDIO8, 0 },
+		  CX18_AV_AUDIO5, 0 },
 		{ CX18_CARD_INPUT_LINE_IN1,
 		{ CX18_CARD_INPUT_LINE_IN1,
 		  CX18_AV_AUDIO_SERIAL1, 0 },
 		  CX18_AV_AUDIO_SERIAL1, 0 },
 	},
 	},

+ 9 - 3
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) {
 			if (oldptr + length >= runtime->buffer_size) {
 				unsigned int cnt =
 				unsigned int cnt =
-				    runtime->buffer_size - oldptr - 1;
+				    runtime->buffer_size - oldptr;
 				memcpy(runtime->dma_area + oldptr * stride, cp,
 				memcpy(runtime->dma_area + oldptr * stride, cp,
 				       cnt * stride);
 				       cnt * stride);
-				memcpy(runtime->dma_area, cp + cnt,
+				memcpy(runtime->dma_area, cp + cnt * stride,
 				       length * stride - cnt * stride);
 				       length * stride - cnt * stride);
 			} else {
 			} else {
 				memcpy(runtime->dma_area + oldptr * stride, cp,
 				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);
 		memset(dev->adev->transfer_buffer[i], 0x80, sb_size);
 		urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
 		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;
 			return -ENOMEM;
+		}
 
 
 		urb->dev = dev->udev;
 		urb->dev = dev->udev;
 		urb->context = dev;
 		urb->context = dev;

+ 26 - 29
drivers/media/video/em28xx/em28xx-cards.c

@@ -93,28 +93,6 @@ struct em28xx_board em28xx_boards[] = {
 			.amux     = 0,
 			.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] = {
 	[EM2820_BOARD_KWORLD_PVRTV2800RF] = {
 		.name         = "Kworld PVR TV 2800 RF",
 		.name         = "Kworld PVR TV 2800 RF",
 		.is_em2800    = 0,
 		.is_em2800    = 0,
@@ -599,7 +577,7 @@ struct em28xx_board em28xx_boards[] = {
 		}, {
 		}, {
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.vmux     = TVP5150_COMPOSITE1,
 			.vmux     = TVP5150_COMPOSITE1,
-			.amux     = 1,
+			.amux     = 3,
 		}, {
 		}, {
 			.type     = EM28XX_VMUX_SVIDEO,
 			.type     = EM28XX_VMUX_SVIDEO,
 			.vmux     = TVP5150_SVIDEO,
 			.vmux     = TVP5150_SVIDEO,
@@ -952,22 +930,23 @@ struct em28xx_board em28xx_boards[] = {
 	},
 	},
 	[EM2880_BOARD_KWORLD_DVB_310U] = {
 	[EM2880_BOARD_KWORLD_DVB_310U] = {
 		.name	      = "KWorld DVB-T 310U",
 		.name	      = "KWorld DVB-T 310U",
-		.valid        = EM28XX_BOARD_NOT_VALIDATED,
 		.vchannels    = 3,
 		.vchannels    = 3,
 		.tuner_type   = TUNER_XC2028,
 		.tuner_type   = TUNER_XC2028,
+		.has_dvb      = 1,
+		.mts_firmware = 1,
 		.decoder      = EM28XX_TVP5150,
 		.decoder      = EM28XX_TVP5150,
 		.input          = { {
 		.input          = { {
 			.type     = EM28XX_VMUX_TELEVISION,
 			.type     = EM28XX_VMUX_TELEVISION,
 			.vmux     = TVP5150_COMPOSITE0,
 			.vmux     = TVP5150_COMPOSITE0,
-			.amux     = 0,
+			.amux     = EM28XX_AMUX_VIDEO,
 		}, {
 		}, {
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.vmux     = TVP5150_COMPOSITE1,
 			.vmux     = TVP5150_COMPOSITE1,
-			.amux     = 1,
-		}, {
+			.amux     = EM28XX_AMUX_AC97_LINE_IN,
+		}, {	/* S-video has not been tested yet */
 			.type     = EM28XX_VMUX_SVIDEO,
 			.type     = EM28XX_VMUX_SVIDEO,
 			.vmux     = TVP5150_SVIDEO,
 			.vmux     = TVP5150_SVIDEO,
-			.amux     = 1,
+			.amux     = EM28XX_AMUX_AC97_LINE_IN,
 		} },
 		} },
 	},
 	},
 	[EM2881_BOARD_DNT_DA2_HYBRID] = {
 	[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 [] = {
 static struct em28xx_hash_table em28xx_eeprom_hash [] = {
 	/* P/N: SA 60002070465 Tuner: TVF7533-MF */
 	/* P/N: SA 60002070465 Tuner: TVF7533-MF */
 	{0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
 	{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 */
 /* 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 */
 		/* djh - Not sure which demod we need here */
 		ctl->demod = XC3028_FE_DEFAULT;
 		ctl->demod = XC3028_FE_DEFAULT;
 		break;
 		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 EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
 	case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
 	case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
-	case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
 		/* FIXME: Better to specify the needed IF */
 		/* FIXME: Better to specify the needed IF */
 		ctl->demod = XC3028_FE_DEFAULT;
 		ctl->demod = XC3028_FE_DEFAULT;
 		break;
 		break;
@@ -1764,6 +1747,20 @@ void em28xx_card_setup(struct em28xx *dev)
 		break;
 		break;
 	case EM2820_BOARD_UNKNOWN:
 	case EM2820_BOARD_UNKNOWN:
 	case EM2800_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))
 		if (!em28xx_hint_board(dev))
 			em28xx_set_model(dev);
 			em28xx_set_model(dev);
 		break;
 		break;

+ 9 - 0
drivers/media/video/em28xx/em28xx-dvb.c

@@ -452,6 +452,15 @@ static int dvb_init(struct em28xx *dev)
 			goto out_free;
 			goto out_free;
 		}
 		}
 		break;
 		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:
 	default:
 		printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
 		printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
 				" isn't supported yet\n",
 				" isn't supported yet\n",

+ 2 - 1
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);
 		urb = usb_alloc_urb(npkt, GFP_KERNEL);
 		if (!urb) {
 		if (!urb) {
 			err("usb_alloc_urb failed");
 			err("usb_alloc_urb failed");
+			destroy_urbs(gspca_dev);
 			return -ENOMEM;
 			return -ENOMEM;
 		}
 		}
 		urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
 		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) {
 		if (urb->transfer_buffer == NULL) {
 			usb_free_urb(urb);
 			usb_free_urb(urb);
-			destroy_urbs(gspca_dev);
 			err("usb_buffer_urb failed");
 			err("usb_buffer_urb failed");
+			destroy_urbs(gspca_dev);
 			return -ENOMEM;
 			return -ENOMEM;
 		}
 		}
 		gspca_dev->urb[n] = urb;
 		gspca_dev->urb[n] = urb;

+ 1 - 0
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, 0x2621), .driver_info = SENSOR_PAC7302},
 	{USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},
 	{USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},
 	{USB_DEVICE(0x093a, 0x2626), .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);
 MODULE_DEVICE_TABLE(usb, device_table);

+ 2 - 2
drivers/media/video/gspca/sonixb.c

@@ -232,7 +232,7 @@ static struct ctrl sd_ctrls[] = {
 static struct v4l2_pix_format vga_mode[] = {
 static struct v4l2_pix_format vga_mode[] = {
 	{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
 	{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
 		.bytesperline = 160,
 		.bytesperline = 160,
-		.sizeimage = 160 * 120 * 5 / 4,
+		.sizeimage = 160 * 120,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.priv = 2 | MODE_RAW},
 		.priv = 2 | MODE_RAW},
 	{160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
 	{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},
 		.priv = 1 | MODE_REDUCED_SIF},
 	{176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
 	{176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
 		.bytesperline = 176,
 		.bytesperline = 176,
-		.sizeimage = 176 * 144 * 5 / 4,
+		.sizeimage = 176 * 144,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.priv = 1 | MODE_RAW},
 		.priv = 1 | MODE_RAW},
 	{176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
 	{176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,

+ 14 - 5
drivers/media/video/gspca/sonixj.c

@@ -707,6 +707,7 @@ static void i2c_w8(struct gspca_dev *gspca_dev,
 			0x08, 0,		/* value, index */
 			0x08, 0,		/* value, index */
 			gspca_dev->usb_buf, 8,
 			gspca_dev->usb_buf, 8,
 			500);
 			500);
+	msleep(2);
 }
 }
 
 
 /* read 5 bytes in gspca_dev->usb_buf */
 /* read 5 bytes in gspca_dev->usb_buf */
@@ -976,13 +977,13 @@ static int sd_init(struct gspca_dev *gspca_dev)
 	case BRIDGE_SN9C105:
 	case BRIDGE_SN9C105:
 		if (regF1 != 0x11)
 		if (regF1 != 0x11)
 			return -ENODEV;
 			return -ENODEV;
-		reg_w(gspca_dev, 0x02, regGpio, 2);
+		reg_w(gspca_dev, 0x01, regGpio, 2);
 		break;
 		break;
 	case BRIDGE_SN9C120:
 	case BRIDGE_SN9C120:
 		if (regF1 != 0x12)
 		if (regF1 != 0x12)
 			return -ENODEV;
 			return -ENODEV;
 		regGpio[1] = 0x70;
 		regGpio[1] = 0x70;
-		reg_w(gspca_dev, 0x02, regGpio, 2);
+		reg_w(gspca_dev, 0x01, regGpio, 2);
 		break;
 		break;
 	default:
 	default:
 /*	case BRIDGE_SN9C110: */
 /*	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 CA[] = { 0x28, 0xd8, 0x14, 0xec };
 	static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };	/* MI0360 */
 	static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };	/* MI0360 */
 	static const __u8 CE_ov76xx[] =
 	static const __u8 CE_ov76xx[] =
-			{ 0x32, 0xdd, 0x32, 0xdd };	/* OV7630/48 */
+				{ 0x32, 0xdd, 0x32, 0xdd };
 
 
 	sn9c1xx = sn_tb[(int) sd->sensor];
 	sn9c1xx = sn_tb[(int) sd->sensor];
 	configure_gpio(gspca_dev, sn9c1xx);
 	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);
 	reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
 	for (i = 0; i < 8; i++)
 	for (i = 0; i < 8; i++)
 		reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
 		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, 0x9a, 0x08);
 		reg_w1(gspca_dev, 0x99, 0x59);
 		reg_w1(gspca_dev, 0x99, 0x59);
+		break;
+	}
 
 
 	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
 	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
 	if (mode)
 	if (mode)
@@ -1275,8 +1283,8 @@ static void sd_start(struct gspca_dev *gspca_dev)
 /*			reg1 = 0x44; */
 /*			reg1 = 0x44; */
 /*			reg1 = 0x46;	(done) */
 /*			reg1 = 0x46;	(done) */
 		} else {
 		} else {
-			reg17 = 0x22;	/* 640 MCKSIZE */
-			reg1 = 0x06;
+			reg17 = 0xa2;	/* 640 */
+			reg1 = 0x44;
 		}
 		}
 		break;
 		break;
 	}
 	}
@@ -1285,6 +1293,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
 	switch (sd->sensor) {
 	switch (sd->sensor) {
 	case SENSOR_OV7630:
 	case SENSOR_OV7630:
 	case SENSOR_OV7648:
 	case SENSOR_OV7648:
+	case SENSOR_OV7660:
 		reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
 		reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
 		break;
 		break;
 	default:
 	default:

+ 1 - 1
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));
 	reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01));
 	do {
 	do {
 		reg_r(gspca_dev, 0x8803, 1);
 		reg_r(gspca_dev, 0x8803, 1);
-		if (!gspca_dev->usb_buf)
+		if (!gspca_dev->usb_buf[0])
 			break;
 			break;
 	} while (--retry);
 	} while (--retry);
 	if (retry == 0)
 	if (retry == 0)

+ 2 - 2
drivers/media/video/gspca/zc3xx.c

@@ -6576,8 +6576,8 @@ static int setlightfreq(struct gspca_dev *gspca_dev)
 		 cs2102_60HZ, cs2102_60HZScale},
 		 cs2102_60HZ, cs2102_60HZScale},
 /* SENSOR_CS2102K 1 */
 /* SENSOR_CS2102K 1 */
 		{cs2102_NoFliker, cs2102_NoFlikerScale,
 		{cs2102_NoFliker, cs2102_NoFlikerScale,
-		 cs2102_50HZ, cs2102_50HZScale,
-		 cs2102_60HZ, cs2102_60HZScale},
+		 NULL, NULL, /* currently disabled */
+		 NULL, NULL},
 /* SENSOR_GC0305 2 */
 /* SENSOR_GC0305 2 */
 		{gc0305_NoFliker, gc0305_NoFliker,
 		{gc0305_NoFliker, gc0305_NoFliker,
 		 gc0305_50HZ, gc0305_50HZ,
 		 gc0305_50HZ, gc0305_50HZ,

+ 4 - 2
drivers/media/video/ov511.c

@@ -3591,7 +3591,7 @@ static int
 ov51x_init_isoc(struct usb_ov511 *ov)
 ov51x_init_isoc(struct usb_ov511 *ov)
 {
 {
 	struct urb *urb;
 	struct urb *urb;
-	int fx, err, n, size;
+	int fx, err, n, i, size;
 
 
 	PDEBUG(3, "*** Initializing capture ***");
 	PDEBUG(3, "*** Initializing capture ***");
 
 
@@ -3662,6 +3662,8 @@ ov51x_init_isoc(struct usb_ov511 *ov)
 		urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
 		urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
 		if (!urb) {
 		if (!urb) {
 			err("init isoc: usb_alloc_urb ret. NULL");
 			err("init isoc: usb_alloc_urb ret. NULL");
+			for (i = 0; i < n; i++)
+				usb_free_urb(ov->sbuf[i].urb);
 			return -ENOMEM;
 			return -ENOMEM;
 		}
 		}
 		ov->sbuf[n].urb = urb;
 		ov->sbuf[n].urb = urb;
@@ -5651,7 +5653,7 @@ static ssize_t show_exposure(struct device *cd,
 	if (!ov->dev)
 	if (!ov->dev)
 		return -ENODEV;
 		return -ENODEV;
 	sensor_get_exposure(ov, &exp);
 	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);
 static DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL);
 
 

+ 2 - 0
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[] = {
 struct usb_device_id pvr2_device_table[] = {
 	{ USB_DEVICE(0x2040, 0x2900),
 	{ USB_DEVICE(0x2040, 0x2900),
 	  .driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
 	  .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),
 	{ USB_DEVICE(0x2040, 0x2400),
 	  .driver_info = (kernel_ulong_t)&pvr2_device_24xxx},
 	  .driver_info = (kernel_ulong_t)&pvr2_device_24xxx},
 	{ USB_DEVICE(0x1164, 0x0622),
 	{ USB_DEVICE(0x1164, 0x0622),

+ 2 - 1
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);
 		(unsigned long)vbuf, pos);
 	/* tell v4l buffer was filled */
 	/* tell v4l buffer was filled */
 
 
-	buf->vb.field_count++;
+	buf->vb.field_count = dev->frame_count[chn] * 2;
 	do_gettimeofday(&ts);
 	do_gettimeofday(&ts);
 	buf->vb.ts = ts;
 	buf->vb.ts = ts;
 	buf->vb.state = VIDEOBUF_DONE;
 	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->last_frame[chn] = -1;
 	dev->bad_payload[chn] = 0;
 	dev->bad_payload[chn] = 0;
 	dev->cur_frame[chn] = 0;
 	dev->cur_frame[chn] = 0;
+	dev->frame_count[chn] = 0;
 	for (j = 0; j < SYS_FRAMES; j++) {
 	for (j = 0; j < SYS_FRAMES; j++) {
 		dev->buffer[chn].frame[j].ulState = 0;
 		dev->buffer[chn].frame[j].ulState = 0;
 		dev->buffer[chn].frame[j].cur_size = 0;
 		dev->buffer[chn].frame[j].cur_size = 0;

+ 1 - 1
drivers/media/video/uvc/uvc_ctrl.c

@@ -592,7 +592,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
 	if (ctrl == NULL)
 	if (ctrl == NULL)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	data = kmalloc(8, GFP_KERNEL);
+	data = kmalloc(ctrl->info->size, GFP_KERNEL);
 	if (data == NULL)
 	if (data == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
 
 

+ 1 - 1
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++) {
 	for (i = 0; i < W9968CF_URBS; i++) {
 		urb = usb_alloc_urb(W9968CF_ISO_PACKETS, GFP_KERNEL);
 		urb = usb_alloc_urb(W9968CF_ISO_PACKETS, GFP_KERNEL);
-		cam->urb[i] = urb;
 		if (!urb) {
 		if (!urb) {
 			for (j = 0; j < i; j++)
 			for (j = 0; j < i; j++)
 				usb_free_urb(cam->urb[j]);
 				usb_free_urb(cam->urb[j]);
@@ -919,6 +918,7 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam)
 			return -ENOMEM;
 			return -ENOMEM;
 		}
 		}
 
 
+		cam->urb[i] = urb;
 		urb->dev = udev;
 		urb->dev = udev;
 		urb->context = (void*)cam;
 		urb->context = (void*)cam;
 		urb->pipe = usb_rcvisocpipe(udev, 1);
 		urb->pipe = usb_rcvisocpipe(udev, 1);

+ 1 - 3
drivers/media/video/wm8739.c

@@ -274,10 +274,8 @@ static int wm8739_probe(struct i2c_client *client,
 			client->addr << 1, client->adapter->name);
 			client->addr << 1, client->adapter->name);
 
 
 	state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL);
 	state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL);
-	if (state == NULL) {
-		kfree(client);
+	if (state == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 	state->vol_l = 0x17; /* 0dB */
 	state->vol_l = 0x17; /* 0dB */
 	state->vol_r = 0x17; /* 0dB */
 	state->vol_r = 0x17; /* 0dB */
 	state->muted = 0;
 	state->muted = 0;

+ 1 - 1
drivers/media/video/zoran_card.c

@@ -988,7 +988,7 @@ zoran_open_init_params (struct zoran *zr)
 	zr->v4l_grab_seq = 0;
 	zr->v4l_grab_seq = 0;
 	zr->v4l_settings.width = 192;
 	zr->v4l_settings.width = 192;
 	zr->v4l_settings.height = 144;
 	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.bytesperline =
 	    zr->v4l_settings.width *
 	    zr->v4l_settings.width *
 	    ((zr->v4l_settings.format->depth + 7) / 8);
 	    ((zr->v4l_settings.format->depth + 7) / 8);

+ 6 - 9
drivers/media/video/zoran_driver.c

@@ -134,7 +134,7 @@ const struct zoran_format zoran_formats[] = {
 	}, {
 	}, {
 		.name = "16-bit RGB BE",
 		.name = "16-bit RGB BE",
 		ZFMT(-1,
 		ZFMT(-1,
-		     V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB),
+		     V4L2_PIX_FMT_RGB565X, V4L2_COLORSPACE_SRGB),
 		.depth = 16,
 		.depth = 16,
 		.flags = ZORAN_FORMAT_CAPTURE |
 		.flags = ZORAN_FORMAT_CAPTURE |
 			 ZORAN_FORMAT_OVERLAY,
 			 ZORAN_FORMAT_OVERLAY,
@@ -2737,7 +2737,8 @@ zoran_do_ioctl (struct inode *inode,
 				    fh->v4l_settings.format->fourcc;
 				    fh->v4l_settings.format->fourcc;
 				fmt->fmt.pix.colorspace =
 				fmt->fmt.pix.colorspace =
 				    fh->v4l_settings.format->colorspace;
 				    fh->v4l_settings.format->colorspace;
-				fmt->fmt.pix.bytesperline = 0;
+				fmt->fmt.pix.bytesperline =
+				    fh->v4l_settings.bytesperline;
 				if (BUZ_MAX_HEIGHT <
 				if (BUZ_MAX_HEIGHT <
 				    (fh->v4l_settings.height * 2))
 				    (fh->v4l_settings.height * 2))
 					fmt->fmt.pix.field =
 					fmt->fmt.pix.field =
@@ -2833,13 +2834,6 @@ zoran_do_ioctl (struct inode *inode,
 				fmt->fmt.pix.pixelformat,
 				fmt->fmt.pix.pixelformat,
 				(char *) &printformat);
 				(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 */
 			/* we can be requested to do JPEG/raw playback/capture */
 			if (!
 			if (!
 			    (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
 			    (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
@@ -2923,6 +2917,7 @@ zoran_do_ioctl (struct inode *inode,
 				fh->jpg_buffers.buffer_size =
 				fh->jpg_buffers.buffer_size =
 				    zoran_v4l2_calc_bufsize(&fh->
 				    zoran_v4l2_calc_bufsize(&fh->
 							    jpg_settings);
 							    jpg_settings);
+				fmt->fmt.pix.bytesperline = 0;
 				fmt->fmt.pix.sizeimage =
 				fmt->fmt.pix.sizeimage =
 				    fh->jpg_buffers.buffer_size;
 				    fh->jpg_buffers.buffer_size;
 
 
@@ -2979,6 +2974,8 @@ zoran_do_ioctl (struct inode *inode,
 
 
 				/* tell the user the
 				/* tell the user the
 				 * results/missing stuff */
 				 * results/missing stuff */
+				fmt->fmt.pix.bytesperline =
+					fh->v4l_settings.bytesperline;
 				fmt->fmt.pix.sizeimage =
 				fmt->fmt.pix.sizeimage =
 					fh->v4l_settings.height *
 					fh->v4l_settings.height *
 					fh->v4l_settings.bytesperline;
 					fh->v4l_settings.bytesperline;

+ 2 - 2
drivers/mfd/Kconfig

@@ -21,7 +21,7 @@ config MFD_SM501
 
 
 config MFD_SM501_GPIO
 config MFD_SM501_GPIO
 	bool "Export GPIO via GPIO layer"
 	bool "Export GPIO via GPIO layer"
-	depends on MFD_SM501 && HAVE_GPIO_LIB
+	depends on MFD_SM501 && GPIOLIB
 	 ---help---
 	 ---help---
 	 This option uses the gpio library layer to export the 64 GPIO
 	 This option uses the gpio library layer to export the 64 GPIO
 	 lines on the SM501. The platform data is used to supply the
 	 lines on the SM501. The platform data is used to supply the
@@ -29,7 +29,7 @@ config MFD_SM501_GPIO
 
 
 config MFD_ASIC3
 config MFD_ASIC3
 	bool "Support for Compaq ASIC3"
 	bool "Support for Compaq ASIC3"
-	depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM
+	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
 	 ---help---
 	 ---help---
 	  This driver supports the ASIC3 multifunction chip found on many
 	  This driver supports the ASIC3 multifunction chip found on many
 	  PDAs (mainly iPAQ and HTC based ones)
 	  PDAs (mainly iPAQ and HTC based ones)

+ 1 - 1
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);
 	struct asic3 *asic = platform_get_drvdata(pdev);
 	unsigned long clksel = 0;
 	unsigned long clksel = 0;
 	unsigned int irq, irq_base;
 	unsigned int irq, irq_base;
-	int map_size;
 	int ret;
 	int ret;
 
 
 	ret = platform_get_irq(pdev, 0);
 	ret = platform_get_irq(pdev, 0);
@@ -534,6 +533,7 @@ static int __init asic3_probe(struct platform_device *pdev)
 	struct asic3 *asic;
 	struct asic3 *asic;
 	struct resource *mem;
 	struct resource *mem;
 	unsigned long clksel;
 	unsigned long clksel;
+	int map_size;
 	int ret = 0;
 	int ret = 0;
 
 
 	asic = kzalloc(sizeof(struct asic3), GFP_KERNEL);
 	asic = kzalloc(sizeof(struct asic3), GFP_KERNEL);

+ 4 - 2
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->sg = NULL;
 	host->data = data;
 	host->data = data;
 
 
-	mci_writel(host, BLKR, MCI_BCNT(data->blocks)
-			| MCI_BLKLEN(data->blksz));
 	dev_vdbg(&mmc->class_dev, "BLKR=0x%08x\n",
 	dev_vdbg(&mmc->class_dev, "BLKR=0x%08x\n",
 			MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz));
 			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)
 		if (data->blocks > 1 && data->blksz & 3)
 			goto fail;
 			goto fail;
 		atmci_set_timeout(host, data);
 		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;
 	iflags = MCI_CMDRDY;

+ 4 - 1
drivers/net/e1000e/e1000.h

@@ -257,7 +257,6 @@ struct e1000_adapter {
 	struct net_device *netdev;
 	struct net_device *netdev;
 	struct pci_dev *pdev;
 	struct pci_dev *pdev;
 	struct net_device_stats net_stats;
 	struct net_device_stats net_stats;
-	spinlock_t stats_lock;      /* prevent concurrent stats updates */
 
 
 	/* structs defined in e1000_hw.h */
 	/* structs defined in e1000_hw.h */
 	struct e1000_hw hw;
 	struct e1000_hw hw;
@@ -284,6 +283,8 @@ struct e1000_adapter {
 	unsigned long led_status;
 	unsigned long led_status;
 
 
 	unsigned int flags;
 	unsigned int flags;
+	struct work_struct downshift_task;
+	struct work_struct update_phy_task;
 };
 };
 
 
 struct e1000_info {
 struct e1000_info {
@@ -305,6 +306,7 @@ struct e1000_info {
 #define FLAG_HAS_CTRLEXT_ON_LOAD          (1 << 5)
 #define FLAG_HAS_CTRLEXT_ON_LOAD          (1 << 5)
 #define FLAG_HAS_SWSM_ON_LOAD             (1 << 6)
 #define FLAG_HAS_SWSM_ON_LOAD             (1 << 6)
 #define FLAG_HAS_JUMBO_FRAMES             (1 << 7)
 #define FLAG_HAS_JUMBO_FRAMES             (1 << 7)
+#define FLAG_READ_ONLY_NVM                (1 << 8)
 #define FLAG_IS_ICH                       (1 << 9)
 #define FLAG_IS_ICH                       (1 << 9)
 #define FLAG_HAS_SMART_POWER_DOWN         (1 << 11)
 #define FLAG_HAS_SMART_POWER_DOWN         (1 << 11)
 #define FLAG_IS_QUAD_PORT_A               (1 << 12)
 #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 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_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,
 extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
 						 bool state);
 						 bool state);
 extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
 extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);

+ 8 - 1
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[11] = er32(TIDV);
 
 
 	regs_buff[12] = adapter->hw.phy.type;  /* PHY type (IGP=1, M88=0) */
 	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) {
 	if (hw->phy.type == e1000_phy_m88) {
 		e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
 		e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
 		regs_buff[13] = (u32)phy_data; /* cable length */
 		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[22] = adapter->phy_stats.receive_errors;
 		regs_buff[23] = regs_buff[13]; /* mdix mode */
 		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);
 	e1e_rphy(hw, PHY_1000T_STATUS, &phy_data);
 	regs_buff[24] = (u32)phy_data;  /* phy local receiver status */
 	regs_buff[24] = (u32)phy_data;  /* phy local receiver status */
 	regs_buff[25] = regs_buff[24];  /* phy remote 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)))
 	if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16)))
 		return -EFAULT;
 		return -EFAULT;
 
 
+	if (adapter->flags & FLAG_READ_ONLY_NVM)
+		return -EINVAL;
+
 	max_len = hw->nvm.word_size * 2;
 	max_len = hw->nvm.word_size * 2;
 
 
 	first_word = eeprom->offset >> 1;
 	first_word = eeprom->offset >> 1;

+ 78 - 0
drivers/net/e1000e/ich8lan.c

@@ -58,6 +58,7 @@
 #define ICH_FLASH_HSFCTL		0x0006
 #define ICH_FLASH_HSFCTL		0x0006
 #define ICH_FLASH_FADDR			0x0008
 #define ICH_FLASH_FADDR			0x0008
 #define ICH_FLASH_FDATA0		0x0010
 #define ICH_FLASH_FDATA0		0x0010
+#define ICH_FLASH_PR0			0x0074
 
 
 #define ICH_FLASH_READ_COMMAND_TIMEOUT	500
 #define ICH_FLASH_READ_COMMAND_TIMEOUT	500
 #define ICH_FLASH_WRITE_COMMAND_TIMEOUT	500
 #define ICH_FLASH_WRITE_COMMAND_TIMEOUT	500
@@ -150,6 +151,19 @@ union ich8_hws_flash_regacc {
 	u16 regval;
 	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 s32 e1000_setup_link_ich8lan(struct e1000_hw *hw);
 static void e1000_clear_hw_cntrs_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);
 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;
 	return 0;
 }
 }
 
 
+static DEFINE_MUTEX(nvm_mutex);
+static pid_t nvm_owner = -1;
+
 /**
 /**
  *  e1000_acquire_swflag_ich8lan - Acquire software control flag
  *  e1000_acquire_swflag_ich8lan - Acquire software control flag
  *  @hw: pointer to the HW structure
  *  @hw: pointer to the HW structure
@@ -379,6 +396,15 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
 	u32 extcnf_ctrl;
 	u32 extcnf_ctrl;
 	u32 timeout = PHY_CFG_TIMEOUT;
 	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) {
 	while (timeout) {
 		extcnf_ctrl = er32(EXTCNF_CTRL);
 		extcnf_ctrl = er32(EXTCNF_CTRL);
 		extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
 		extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
@@ -393,6 +419,8 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
 
 
 	if (!timeout) {
 	if (!timeout) {
 		hw_dbg(hw, "FW or HW has locked the resource for too long.\n");
 		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;
 		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 = er32(EXTCNF_CTRL);
 	extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
 	extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
 	ew32(EXTCNF_CTRL, extcnf_ctrl);
 	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.
 	 * programming failed.
 	 */
 	 */
 	if (ret_val) {
 	if (ret_val) {
+		/* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
 		hw_dbg(hw, "Flash commit failed.\n");
 		hw_dbg(hw, "Flash commit failed.\n");
 		e1000_release_swflag_ich8lan(hw);
 		e1000_release_swflag_ich8lan(hw);
 		return ret_val;
 		return ret_val;
@@ -1373,6 +1405,49 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
 	return e1000e_validate_nvm_checksum_generic(hw);
 	return e1000e_validate_nvm_checksum_generic(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
  *  e1000_write_flash_data_ich8lan - Writes bytes to the NVM
  *  @hw: pointer to the HW structure
  *  @hw: pointer to the HW structure
@@ -1720,6 +1795,9 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
 	ew32(CTRL, (ctrl | E1000_CTRL_RST));
 	ew32(CTRL, (ctrl | E1000_CTRL_RST));
 	msleep(20);
 	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);
 	ret_val = e1000e_get_auto_rd_done(hw);
 	if (ret_val) {
 	if (ret_val) {
 		/*
 		/*

+ 35 - 37
drivers/net/e1000e/netdev.c

@@ -47,7 +47,7 @@
 
 
 #include "e1000.h"
 #include "e1000.h"
 
 
-#define DRV_VERSION "0.3.3.3-k2"
+#define DRV_VERSION "0.3.3.3-k6"
 char e1000e_driver_name[] = "e1000e";
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 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);
 	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
  * e1000_intr_msi - Interrupt Handler
  * @irq: interrupt number
  * @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) &&
 		if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
 		    (!(er32(STATUS) & E1000_STATUS_LU)))
 		    (!(er32(STATUS) & E1000_STATUS_LU)))
-			e1000e_gig_downshift_workaround_ich8lan(hw);
+			schedule_work(&adapter->downshift_task);
 
 
 		/*
 		/*
 		 * 80003ES2LAN workaround-- For packet buffer work-around on
 		 * 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) &&
 		if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
 		    (!(er32(STATUS) & E1000_STATUS_LU)))
 		    (!(er32(STATUS) & E1000_STATUS_LU)))
-			e1000e_gig_downshift_workaround_ich8lan(hw);
+			schedule_work(&adapter->downshift_task);
 
 
 		/*
 		/*
 		 * 80003ES2LAN workaround--
 		 * 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. */
 	/* Explicitly disable IRQ since the NIC can be in any state. */
 	e1000_irq_disable(adapter);
 	e1000_irq_disable(adapter);
 
 
-	spin_lock_init(&adapter->stats_lock);
-
 	set_bit(__E1000_DOWN, &adapter->state);
 	set_bit(__E1000_DOWN, &adapter->state);
 	return 0;
 	return 0;
 
 
@@ -2912,6 +2918,21 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
 	return 0;
 	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
  * Need to wait a few seconds after link up to get diagnostic information from
  * the phy
  * 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)
 static void e1000_update_phy_info(unsigned long data)
 {
 {
 	struct e1000_adapter *adapter = (struct e1000_adapter *) 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 e1000_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
 	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
 	 * 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))
 	if (pci_channel_offline(pdev))
 		return;
 		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.crcerrs += er32(CRCERRS);
 	adapter->stats.gprc += er32(GPRC);
 	adapter->stats.gprc += er32(GPRC);
 	adapter->stats.gorc += er32(GORCL);
 	adapter->stats.gorc += er32(GORCL);
@@ -3022,21 +3031,10 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
 
 
 	/* Tx Dropped needs to be maintained elsewhere */
 	/* 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 */
 	/* Management Stats */
 	adapter->stats.mgptc += er32(MGTPTC);
 	adapter->stats.mgptc += er32(MGTPTC);
 	adapter->stats.mgprc += er32(MGTPRC);
 	adapter->stats.mgprc += er32(MGTPRC);
 	adapter->stats.mgpdc += er32(MGTPDC);
 	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_hw *hw = &adapter->hw;
 	struct e1000_phy_regs *phy = &adapter->phy_regs;
 	struct e1000_phy_regs *phy = &adapter->phy_regs;
 	int ret_val;
 	int ret_val;
-	unsigned long irq_flags;
-
-
-	spin_lock_irqsave(&adapter->stats_lock, irq_flags);
 
 
 	if ((er32(STATUS) & E1000_STATUS_LU) &&
 	if ((er32(STATUS) & E1000_STATUS_LU) &&
 	    (adapter->hw.phy.media_type == e1000_media_type_copper)) {
 	    (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->stat1000 = 0;
 		phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF);
 		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)
 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++;
 	adapter->bd_number = cards_found++;
 
 
+	e1000e_check_options(adapter);
+
 	/* setup adapter struct */
 	/* setup adapter struct */
 	err = e1000_sw_init(adapter);
 	err = e1000_sw_init(adapter);
 	if (err)
 	if (err)
@@ -4482,6 +4476,10 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
 	if (err)
 	if (err)
 		goto err_hw_init;
 		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);
 	hw->mac.ops.get_bus_info(&adapter->hw);
 
 
 	adapter->hw.phy.autoneg_wait_to_complete = 0;
 	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->reset_task, e1000_reset_task);
 	INIT_WORK(&adapter->watchdog_task, e1000_watchdog_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 */
 	/* Initialize link parameters. User can change them with ethtool */
 	adapter->hw.mac.autoneg = 1;
 	adapter->hw.mac.autoneg = 1;

+ 30 - 0
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");
 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 {
 struct e1000_option {
 	enum { enable_option, range_option, list_option } type;
 	enum { enable_option, range_option, list_option } type;
 	const char *name;
 	const char *name;
@@ -388,4 +397,25 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
 								       opt.def);
 								       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;
+			}
+		}
+	}
 }
 }

+ 19 - 0
drivers/pci/pci-sysfs.c

@@ -16,6 +16,7 @@
 
 
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
 #include <linux/stat.h>
 #include <linux/stat.h>
 #include <linux/topology.h>
 #include <linux/topology.h>
@@ -484,6 +485,21 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
 #endif /* HAVE_PCI_LEGACY */
 #endif /* HAVE_PCI_LEGACY */
 
 
 #ifdef HAVE_PCI_MMAP
 #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
  * pci_mmap_resource - map a PCI resource into user memory space
  * @kobj: kobject for mapping
  * @kobj: kobject for mapping
@@ -510,6 +526,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
 	if (i >= PCI_ROM_RESOURCE)
 	if (i >= PCI_ROM_RESOURCE)
 		return -ENODEV;
 		return -ENODEV;
 
 
+	if (!pci_mmap_fits(pdev, i, vma))
+		return -EINVAL;
+
 	/* pci_mmap_page_range() expects the same kind of entry as coming
 	/* 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
 	 * from /proc/bus/pci/ which is a "user visible" value. If this is
 	 * different from the resource itself, arch will do necessary fixup.
 	 * different from the resource itself, arch will do necessary fixup.

+ 9 - 6
drivers/rtc/rtc-dev.c

@@ -422,6 +422,12 @@ done:
 	return err;
 	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)
 static int rtc_dev_release(struct inode *inode, struct file *file)
 {
 {
 	struct rtc_device *rtc = file->private_data;
 	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)
 	if (rtc->ops->release)
 		rtc->ops->release(rtc->dev.parent);
 		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);
 	clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
 	return 0;
 	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 = {
 static const struct file_operations rtc_dev_fops = {
 	.owner		= THIS_MODULE,
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.llseek		= no_llseek,

+ 20 - 35
drivers/s390/cio/qdio_setup.c

@@ -447,51 +447,36 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
 {
 {
 	char s[80];
 	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) {
 	switch (irq_ptr->qib.qfmt) {
 	case QDIO_QETH_QFMT:
 	case QDIO_QETH_QFMT:
-		sprintf(s + strlen(s), "OSADE ");
+		sprintf(s + strlen(s), "OSA ");
 		break;
 		break;
 	case QDIO_ZFCP_QFMT:
 	case QDIO_ZFCP_QFMT:
 		sprintf(s + strlen(s), "ZFCP ");
 		sprintf(s + strlen(s), "ZFCP ");
 		break;
 		break;
 	case QDIO_IQDIO_QFMT:
 	case QDIO_IQDIO_QFMT:
-		sprintf(s + strlen(s), "HiperSockets ");
+		sprintf(s + strlen(s), "HS ");
 		break;
 		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");
 	sprintf(s + strlen(s), "\n");
-	printk(KERN_INFO "qdio: %s", s);
+	printk(KERN_INFO "%s", s);
 }
 }
 
 
 int __init qdio_setup_init(void)
 int __init qdio_setup_init(void)

+ 1 - 1
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;
 			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,
 			dev_err(&spi->dev,
 				"message rejected : "
 				"message rejected : "
 				"device min speed (%d Hz) exceeds "
 				"device min speed (%d Hz) exceeds "

+ 2 - 2
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 DMA_INT_MASK		(DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
 #define RESET_DMA_CHANNEL	(DCSR_NODESC | DMA_INT_MASK)
 #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
 #define MAX_DMA_LEN		8191
 
 
 /*
 /*
@@ -896,7 +896,7 @@ static void pump_transfers(unsigned long data)
 				|| transfer->rx_dma || transfer->tx_dma) {
 				|| transfer->rx_dma || transfer->tx_dma) {
 			dev_err(&drv_data->pdev->dev,
 			dev_err(&drv_data->pdev->dev,
 				"pump_transfers: mapped transfer length "
 				"pump_transfers: mapped transfer length "
-				"of %lu is greater than %d\n",
+				"of %u is greater than %d\n",
 				transfer->len, MAX_DMA_LEN);
 				transfer->len, MAX_DMA_LEN);
 			message->status = -EINVAL;
 			message->status = -EINVAL;
 			giveback(drv_data);
 			giveback(drv_data);

+ 5 - 1
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 (!fbcon_is_inactive(vc, info)) {
 		if (ops->blank_state != blank) {
 		if (ops->blank_state != blank) {
+			int ret = 1;
+
 			ops->blank_state = blank;
 			ops->blank_state = blank;
 			fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
 			fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
 			ops->cursor_flash = (!blank);
 			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);
 				fbcon_generic_blank(vc, info, blank);
 		}
 		}
 
 

Some files were not shown because too many files changed in this diff