소스 검색

Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6

Steve French 17 년 전
부모
커밋
5b4d4771e2
100개의 변경된 파일3234개의 추가작업 그리고 947개의 파일을 삭제
  1. 5 2
      Documentation/lguest/lguest.c
  2. 2 2
      Documentation/pci.txt
  3. 1 1
      Documentation/scheduler/sched-stats.txt
  4. 3 5
      Documentation/usb/usb-help.txt
  5. 1 1
      MAINTAINERS
  6. 1 1
      Makefile
  7. 7 8
      arch/alpha/kernel/pci_iommu.c
  8. 0 3
      arch/x86/Kconfig
  9. 8 1
      arch/x86/kernel/ptrace.c
  10. 33 5
      arch/x86/kernel/signal_64.c
  11. 22 33
      arch/x86/lguest/boot.c
  12. 0 2
      arch/x86/mm/ioremap.c
  13. 9 9
      arch/x86/mm/pgtable_32.c
  14. 10 0
      arch/x86/pci/pcbios.c
  15. 1 3
      crypto/chainiv.c
  16. 0 2
      crypto/eseqiv.c
  17. 9 0
      drivers/ata/Kconfig
  18. 1 0
      drivers/ata/Makefile
  19. 13 1
      drivers/ata/ahci.c
  20. 4 4
      drivers/ata/libata-acpi.c
  21. 9 8
      drivers/ata/libata-core.c
  22. 10 0
      drivers/ata/libata-eh.c
  23. 22 14
      drivers/ata/libata-sff.c
  24. 1 1
      drivers/ata/pata_pdc2027x.c
  25. 314 0
      drivers/ata/pata_rb500_cf.c
  26. 1 1
      drivers/base/platform.c
  27. 4 0
      drivers/base/sys.c
  28. 43 18
      drivers/char/nozomi.c
  29. 0 6
      drivers/char/riscom8.c
  30. 1 0
      drivers/gpio/pca953x.c
  31. 2 1
      drivers/infiniband/core/cm.c
  32. 22 16
      drivers/infiniband/core/fmr_pool.c
  33. 3 2
      drivers/infiniband/core/iwcm.c
  34. 4 1
      drivers/infiniband/hw/cxgb3/iwch_provider.c
  35. 24 23
      drivers/infiniband/ulp/iser/iser_verbs.c
  36. 1 1
      drivers/input/serio/i8042.h
  37. 13 2
      drivers/lguest/core.c
  38. 8 7
      drivers/lguest/lguest_user.c
  39. 1 1
      drivers/lguest/page_tables.c
  40. 3 1
      drivers/md/bitmap.c
  41. 1 1
      drivers/md/md.c
  42. 1 1
      drivers/memstick/Kconfig
  43. 28 5
      drivers/memstick/core/memstick.c
  44. 92 14
      drivers/memstick/core/mspro_block.c
  45. 10 0
      drivers/memstick/host/Kconfig
  46. 3 3
      drivers/memstick/host/Makefile
  47. 945 0
      drivers/memstick/host/jmb38x_ms.c
  48. 279 290
      drivers/memstick/host/tifm_ms.c
  49. 2 0
      drivers/misc/tifm_7xx1.c
  50. 1 0
      drivers/pci/hotplug/ibmphp_ebda.c
  51. 1 1
      drivers/serial/of_serial.c
  52. 1 1
      drivers/usb/gadget/Kconfig
  53. 46 16
      drivers/usb/host/ehci-hcd.c
  54. 2 0
      drivers/usb/serial/cypress_m8.c
  55. 4 0
      drivers/usb/serial/cypress_m8.h
  56. 1 0
      drivers/usb/serial/ftdi_sio.c
  57. 3 0
      drivers/usb/serial/ftdi_sio.h
  58. 6 4
      drivers/usb/serial/generic.c
  59. 62 13
      drivers/usb/serial/option.c
  60. 2 2
      drivers/usb/storage/sddr55.c
  61. 13 0
      drivers/video/Kconfig
  62. 1 0
      drivers/video/Makefile
  63. 3 3
      drivers/video/bf54x-lq043fb.c
  64. 685 0
      drivers/video/bfin-t350mcqb-fb.c
  65. 1 1
      drivers/video/mbx/mbxfb.c
  66. 15 7
      drivers/video/stifb.c
  67. 1 13
      drivers/video/tridentfb.c
  68. 2 2
      drivers/watchdog/cpu5wdt.c
  69. 24 190
      drivers/watchdog/hpwdt.c
  70. 64 14
      drivers/watchdog/it8712f_wdt.c
  71. 1 1
      drivers/watchdog/machzwd.c
  72. 2 2
      drivers/watchdog/mtx-1_wdt.c
  73. 2 2
      drivers/watchdog/pcwd_usb.c
  74. 4 4
      drivers/watchdog/s3c2410_wdt.c
  75. 1 1
      drivers/watchdog/shwdt.c
  76. 4 5
      fs/ocfs2/cluster/tcp.c
  77. 12 9
      fs/ocfs2/dlm/dlmcommon.h
  78. 1 1
      fs/ocfs2/dlm/dlmconvert.c
  79. 66 37
      fs/ocfs2/dlm/dlmdomain.c
  80. 15 3
      fs/ocfs2/dlm/dlmmaster.c
  81. 47 10
      fs/ocfs2/dlm/dlmrecovery.c
  82. 4 2
      fs/ocfs2/dlm/dlmthread.c
  83. 1 1
      fs/ocfs2/dlmglue.c
  84. 1 1
      fs/ocfs2/resize.c
  85. 2 3
      include/asm-x86/pgtable_32.h
  86. 1 1
      include/crypto/internal/skcipher.h
  87. 23 0
      include/linux/firmware.h
  88. 88 44
      include/linux/memstick.h
  89. 2 2
      include/linux/pci.h
  90. 1 0
      include/linux/pci_ids.h
  91. 1 1
      include/linux/tifm.h
  92. 4 0
      include/linux/time.h
  93. 1 8
      include/linux/timex.h
  94. 1 1
      include/linux/usb/Kbuild
  95. 0 4
      include/linux/usb/gadget.h
  96. 3 31
      init/Kconfig
  97. 3 2
      ipc/shm.c
  98. 15 0
      kernel/Kconfig.preempt
  99. 1 1
      kernel/exit.c
  100. 12 3
      kernel/module.c

+ 5 - 2
Documentation/lguest/lguest.c

@@ -486,9 +486,12 @@ static void concat(char *dst, char *args[])
 	unsigned int i, len = 0;
 	unsigned int i, len = 0;
 
 
 	for (i = 0; args[i]; i++) {
 	for (i = 0; args[i]; i++) {
+		if (i) {
+			strcat(dst+len, " ");
+			len++;
+		}
 		strcpy(dst+len, args[i]);
 		strcpy(dst+len, args[i]);
-		strcat(dst+len, " ");
-		len += strlen(args[i]) + 1;
+		len += strlen(args[i]);
 	}
 	}
 	/* In case it's empty. */
 	/* In case it's empty. */
 	dst[len] = '\0';
 	dst[len] = '\0';

+ 2 - 2
Documentation/pci.txt

@@ -123,7 +123,7 @@ initialization with a pointer to a structure describing the driver
 
 
 
 
 The ID table is an array of struct pci_device_id entries ending with an
 The ID table is an array of struct pci_device_id entries ending with an
-all-zero entry; use of the macro DECLARE_PCI_DEVICE_TABLE is the preferred
+all-zero entry; use of the macro DEFINE_PCI_DEVICE_TABLE is the preferred
 method of declaring the table.  Each entry consists of:
 method of declaring the table.  Each entry consists of:
 
 
 	vendor,device	Vendor and device ID to match (or PCI_ANY_ID)
 	vendor,device	Vendor and device ID to match (or PCI_ANY_ID)
@@ -193,7 +193,7 @@ Tips on when/where to use the above attributes:
 	o Do not mark the struct pci_driver.
 	o Do not mark the struct pci_driver.
 
 
 	o The ID table array should be marked __devinitconst; this is done
 	o The ID table array should be marked __devinitconst; this is done
-	  automatically if the table is declared with DECLARE_PCI_DEVICE_TABLE().
+	  automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE().
 
 
 	o The probe() and remove() functions should be marked __devinit
 	o The probe() and remove() functions should be marked __devinit
 	  and __devexit respectively.  All initialization functions
 	  and __devexit respectively.  All initialization functions

+ 1 - 1
Documentation/scheduler/sched-stats.txt

@@ -142,7 +142,7 @@ of idleness (idle, busy, and newly idle):
 
 
 /proc/<pid>/schedstat
 /proc/<pid>/schedstat
 ----------------
 ----------------
-schedstats also adds a new /proc/<pid/schedstat file to include some of
+schedstats also adds a new /proc/<pid>/schedstat file to include some of
 the same information on a per-process level.  There are three fields in
 the same information on a per-process level.  There are three fields in
 this file correlating for that process to:
 this file correlating for that process to:
      1) time spent on the cpu
      1) time spent on the cpu

+ 3 - 5
Documentation/usb/usb-help.txt

@@ -1,5 +1,5 @@
 usb-help.txt
 usb-help.txt
-2000-July-12
+2008-Mar-7
 
 
 For USB help other than the readme files that are located in
 For USB help other than the readme files that are located in
 Documentation/usb/*, see the following:
 Documentation/usb/*, see the following:
@@ -10,9 +10,7 @@ Linux-USB project:  http://www.linux-usb.org
 Linux USB Guide:    http://linux-usb.sourceforge.net
 Linux USB Guide:    http://linux-usb.sourceforge.net
 Linux-USB device overview (working devices and drivers):
 Linux-USB device overview (working devices and drivers):
                     http://www.qbik.ch/usb/devices/
                     http://www.qbik.ch/usb/devices/
-    
-The Linux-USB mailing lists are:
-  linux-usb-users@lists.sourceforge.net   for general user help
-  linux-usb-devel@lists.sourceforge.net   for developer discussions
+
+The Linux-USB mailing list is at linux-usb@vger.kernel.org
 
 
 ###
 ###

+ 1 - 1
MAINTAINERS

@@ -2156,7 +2156,7 @@ L:	netdev@vger.kernel.org
 S:	Maintained
 S:	Maintained
 
 
 IPATH DRIVER:
 IPATH DRIVER:
-P:	Arthur Jones
+P:	Ralph Campbell
 M:	infinipath@qlogic.com
 M:	infinipath@qlogic.com
 L:	general@lists.openfabrics.org
 L:	general@lists.openfabrics.org
 T:	git git://git.qlogic.com/ipath-linux-2.6
 T:	git git://git.qlogic.com/ipath-linux-2.6

+ 1 - 1
Makefile

@@ -1,7 +1,7 @@
 VERSION = 2
 VERSION = 2
 PATCHLEVEL = 6
 PATCHLEVEL = 6
 SUBLEVEL = 25
 SUBLEVEL = 25
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc5
 NAME = Funky Weasel is Jiggy wit it
 NAME = Funky Weasel is Jiggy wit it
 
 
 # *DOCUMENTATION*
 # *DOCUMENTATION*

+ 7 - 8
arch/alpha/kernel/pci_iommu.c

@@ -144,15 +144,14 @@ iommu_arena_find_pages(struct device *dev, struct pci_iommu_arena *arena,
 	unsigned long base;
 	unsigned long base;
 	unsigned long boundary_size;
 	unsigned long boundary_size;
 
 
-	BUG_ON(arena->dma_base & ~PAGE_MASK);
 	base = arena->dma_base >> PAGE_SHIFT;
 	base = arena->dma_base >> PAGE_SHIFT;
-	if (dev)
-		boundary_size = ALIGN(dma_get_max_seg_size(dev) + 1, PAGE_SIZE)
-			>> PAGE_SHIFT;
-	else
-		boundary_size = ALIGN(1UL << 32, PAGE_SIZE) >> PAGE_SHIFT;
-
-	BUG_ON(!is_power_of_2(boundary_size));
+	if (dev) {
+		boundary_size = dma_get_seg_boundary(dev) + 1;
+		BUG_ON(!is_power_of_2(boundary_size));
+		boundary_size >>= PAGE_SHIFT;
+	} else {
+		boundary_size = 1UL << (32 - PAGE_SHIFT);
+	}
 
 
 	/* Search forward for the first mask-aligned sequence of N free ptes */
 	/* Search forward for the first mask-aligned sequence of N free ptes */
 	ptes = arena->ptes;
 	ptes = arena->ptes;

+ 0 - 3
arch/x86/Kconfig

@@ -66,9 +66,6 @@ config MMU
 config ZONE_DMA
 config ZONE_DMA
 	def_bool y
 	def_bool y
 
 
-config QUICKLIST
-	def_bool X86_32
-
 config SBUS
 config SBUS
 	bool
 	bool
 
 

+ 8 - 1
arch/x86/kernel/ptrace.c

@@ -1055,10 +1055,17 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 value)
 	R32(esi, si);
 	R32(esi, si);
 	R32(ebp, bp);
 	R32(ebp, bp);
 	R32(eax, ax);
 	R32(eax, ax);
-	R32(orig_eax, orig_ax);
 	R32(eip, ip);
 	R32(eip, ip);
 	R32(esp, sp);
 	R32(esp, sp);
 
 
+	case offsetof(struct user32, regs.orig_eax):
+		/*
+		 * Sign-extend the value so that orig_eax = -1
+		 * causes (long)orig_ax < 0 tests to fire correctly.
+		 */
+		regs->orig_ax = (long) (s32) value;
+		break;
+
 	case offsetof(struct user32, regs.eflags):
 	case offsetof(struct user32, regs.eflags):
 		return set_flags(child, value);
 		return set_flags(child, value);
 
 

+ 33 - 5
arch/x86/kernel/signal_64.c

@@ -310,6 +310,35 @@ give_sigsegv:
 	return -EFAULT;
 	return -EFAULT;
 }
 }
 
 
+/*
+ * Return -1L or the syscall number that @regs is executing.
+ */
+static long current_syscall(struct pt_regs *regs)
+{
+	/*
+	 * We always sign-extend a -1 value being set here,
+	 * so this is always either -1L or a syscall number.
+	 */
+	return regs->orig_ax;
+}
+
+/*
+ * Return a value that is -EFOO if the system call in @regs->orig_ax
+ * returned an error.  This only works for @regs from @current.
+ */
+static long current_syscall_ret(struct pt_regs *regs)
+{
+#ifdef CONFIG_IA32_EMULATION
+	if (test_thread_flag(TIF_IA32))
+		/*
+		 * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
+		 * and will match correctly in comparisons.
+		 */
+		return (int) regs->ax;
+#endif
+	return regs->ax;
+}
+
 /*
 /*
  * OK, we're invoking a handler
  * OK, we're invoking a handler
  */	
  */	
@@ -327,9 +356,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 #endif
 #endif
 
 
 	/* Are we from a system call? */
 	/* Are we from a system call? */
-	if ((long)regs->orig_ax >= 0) {
+	if (current_syscall(regs) >= 0) {
 		/* If so, check system call restarting.. */
 		/* If so, check system call restarting.. */
-		switch (regs->ax) {
+		switch (current_syscall_ret(regs)) {
 		        case -ERESTART_RESTARTBLOCK:
 		        case -ERESTART_RESTARTBLOCK:
 			case -ERESTARTNOHAND:
 			case -ERESTARTNOHAND:
 				regs->ax = -EINTR;
 				regs->ax = -EINTR;
@@ -426,10 +455,9 @@ static void do_signal(struct pt_regs *regs)
 	}
 	}
 
 
 	/* Did we come from a system call? */
 	/* Did we come from a system call? */
-	if ((long)regs->orig_ax >= 0) {
+	if (current_syscall(regs) >= 0) {
 		/* Restart the system call - no handlers present */
 		/* Restart the system call - no handlers present */
-		long res = regs->ax;
-		switch (res) {
+		switch (current_syscall_ret(regs)) {
 		case -ERESTARTNOHAND:
 		case -ERESTARTNOHAND:
 		case -ERESTARTSYS:
 		case -ERESTARTSYS:
 		case -ERESTARTNOINTR:
 		case -ERESTARTNOINTR:

+ 22 - 33
arch/x86/lguest/boot.c

@@ -84,7 +84,6 @@ struct lguest_data lguest_data = {
 	.blocked_interrupts = { 1 }, /* Block timer interrupts */
 	.blocked_interrupts = { 1 }, /* Block timer interrupts */
 	.syscall_vec = SYSCALL_VECTOR,
 	.syscall_vec = SYSCALL_VECTOR,
 };
 };
-static cycle_t clock_base;
 
 
 /*G:037 async_hcall() is pretty simple: I'm quite proud of it really.  We have a
 /*G:037 async_hcall() is pretty simple: I'm quite proud of it really.  We have a
  * ring buffer of stored hypercalls which the Host will run though next time we
  * ring buffer of stored hypercalls which the Host will run though next time we
@@ -327,8 +326,8 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx,
 	case 1:	/* Basic feature request. */
 	case 1:	/* Basic feature request. */
 		/* We only allow kernel to see SSE3, CMPXCHG16B and SSSE3 */
 		/* We only allow kernel to see SSE3, CMPXCHG16B and SSSE3 */
 		*cx &= 0x00002201;
 		*cx &= 0x00002201;
-		/* SSE, SSE2, FXSR, MMX, CMOV, CMPXCHG8B, FPU. */
-		*dx &= 0x07808101;
+		/* SSE, SSE2, FXSR, MMX, CMOV, CMPXCHG8B, TSC, FPU. */
+		*dx &= 0x07808111;
 		/* The Host can do a nice optimization if it knows that the
 		/* The Host can do a nice optimization if it knows that the
 		 * kernel mappings (addresses above 0xC0000000 or whatever
 		 * kernel mappings (addresses above 0xC0000000 or whatever
 		 * PAGE_OFFSET is set to) haven't changed.  But Linux calls
 		 * PAGE_OFFSET is set to) haven't changed.  But Linux calls
@@ -481,7 +480,7 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
 {
 {
 	*pmdp = pmdval;
 	*pmdp = pmdval;
 	lazy_hcall(LHCALL_SET_PMD, __pa(pmdp)&PAGE_MASK,
 	lazy_hcall(LHCALL_SET_PMD, __pa(pmdp)&PAGE_MASK,
-		   (__pa(pmdp)&(PAGE_SIZE-1)), 0);
+		   (__pa(pmdp)&(PAGE_SIZE-1))/4, 0);
 }
 }
 
 
 /* There are a couple of legacy places where the kernel sets a PTE, but we
 /* There are a couple of legacy places where the kernel sets a PTE, but we
@@ -595,19 +594,25 @@ static unsigned long lguest_get_wallclock(void)
 	return lguest_data.time.tv_sec;
 	return lguest_data.time.tv_sec;
 }
 }
 
 
+/* The TSC is a Time Stamp Counter.  The Host tells us what speed it runs at,
+ * or 0 if it's unusable as a reliable clock source.  This matches what we want
+ * here: if we return 0 from this function, the x86 TSC clock will not register
+ * itself. */
+static unsigned long lguest_cpu_khz(void)
+{
+	return lguest_data.tsc_khz;
+}
+
+/* If we can't use the TSC, the kernel falls back to our "lguest_clock", where
+ * we read the time value given to us by the Host. */
 static cycle_t lguest_clock_read(void)
 static cycle_t lguest_clock_read(void)
 {
 {
 	unsigned long sec, nsec;
 	unsigned long sec, nsec;
 
 
-	/* If the Host tells the TSC speed, we can trust that. */
-	if (lguest_data.tsc_khz)
-		return native_read_tsc();
-
-	/* If we can't use the TSC, we read the time value written by the Host.
-	 * Since it's in two parts (seconds and nanoseconds), we risk reading
-	 * it just as it's changing from 99 & 0.999999999 to 100 and 0, and
-	 * getting 99 and 0.  As Linux tends to come apart under the stress of
-	 * time travel, we must be careful: */
+	/* Since the time is in two parts (seconds and nanoseconds), we risk
+	 * reading it just as it's changing from 99 & 0.999999999 to 100 and 0,
+	 * and getting 99 and 0.  As Linux tends to come apart under the stress
+	 * of time travel, we must be careful: */
 	do {
 	do {
 		/* First we read the seconds part. */
 		/* First we read the seconds part. */
 		sec = lguest_data.time.tv_sec;
 		sec = lguest_data.time.tv_sec;
@@ -622,14 +627,14 @@ static cycle_t lguest_clock_read(void)
 		/* Now if the seconds part has changed, try again. */
 		/* Now if the seconds part has changed, try again. */
 	} while (unlikely(lguest_data.time.tv_sec != sec));
 	} while (unlikely(lguest_data.time.tv_sec != sec));
 
 
-	/* Our non-TSC clock is in real nanoseconds. */
+	/* Our lguest clock is in real nanoseconds. */
 	return sec*1000000000ULL + nsec;
 	return sec*1000000000ULL + nsec;
 }
 }
 
 
-/* This is what we tell the kernel is our clocksource.  */
+/* This is the fallback clocksource: lower priority than the TSC clocksource. */
 static struct clocksource lguest_clock = {
 static struct clocksource lguest_clock = {
 	.name		= "lguest",
 	.name		= "lguest",
-	.rating		= 400,
+	.rating		= 200,
 	.read		= lguest_clock_read,
 	.read		= lguest_clock_read,
 	.mask		= CLOCKSOURCE_MASK(64),
 	.mask		= CLOCKSOURCE_MASK(64),
 	.mult		= 1 << 22,
 	.mult		= 1 << 22,
@@ -637,12 +642,6 @@ static struct clocksource lguest_clock = {
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 };
 
 
-/* The "scheduler clock" is just our real clock, adjusted to start at zero */
-static unsigned long long lguest_sched_clock(void)
-{
-	return cyc2ns(&lguest_clock, lguest_clock_read() - clock_base);
-}
-
 /* We also need a "struct clock_event_device": Linux asks us to set it to go
 /* We also need a "struct clock_event_device": Linux asks us to set it to go
  * off some time in the future.  Actually, James Morris figured all this out, I
  * off some time in the future.  Actually, James Morris figured all this out, I
  * just applied the patch. */
  * just applied the patch. */
@@ -712,19 +711,8 @@ static void lguest_time_init(void)
 	/* Set up the timer interrupt (0) to go to our simple timer routine */
 	/* Set up the timer interrupt (0) to go to our simple timer routine */
 	set_irq_handler(0, lguest_time_irq);
 	set_irq_handler(0, lguest_time_irq);
 
 
-	/* Our clock structure looks like arch/x86/kernel/tsc_32.c if we can
-	 * use the TSC, otherwise it's a dumb nanosecond-resolution clock.
-	 * Either way, the "rating" is set so high that it's always chosen over
-	 * any other clocksource. */
-	if (lguest_data.tsc_khz)
-		lguest_clock.mult = clocksource_khz2mult(lguest_data.tsc_khz,
-							 lguest_clock.shift);
-	clock_base = lguest_clock_read();
 	clocksource_register(&lguest_clock);
 	clocksource_register(&lguest_clock);
 
 
-	/* Now we've set up our clock, we can use it as the scheduler clock */
-	pv_time_ops.sched_clock = lguest_sched_clock;
-
 	/* We can't set cpumask in the initializer: damn C limitations!  Set it
 	/* We can't set cpumask in the initializer: damn C limitations!  Set it
 	 * here and register our timer device. */
 	 * here and register our timer device. */
 	lguest_clockevent.cpumask = cpumask_of_cpu(0);
 	lguest_clockevent.cpumask = cpumask_of_cpu(0);
@@ -995,6 +983,7 @@ __init void lguest_init(void)
 	/* time operations */
 	/* time operations */
 	pv_time_ops.get_wallclock = lguest_get_wallclock;
 	pv_time_ops.get_wallclock = lguest_get_wallclock;
 	pv_time_ops.time_init = lguest_time_init;
 	pv_time_ops.time_init = lguest_time_init;
+	pv_time_ops.get_cpu_khz = lguest_cpu_khz;
 
 
 	/* Now is a good time to look at the implementations of these functions
 	/* Now is a good time to look at the implementations of these functions
 	 * before returning to the rest of lguest_init(). */
 	 * before returning to the rest of lguest_init(). */

+ 0 - 2
arch/x86/mm/ioremap.c

@@ -134,8 +134,6 @@ static void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
 			return NULL;
 			return NULL;
 	}
 	}
 
 
-	WARN_ON_ONCE(page_is_ram(pfn));
-
 	switch (mode) {
 	switch (mode) {
 	case IOR_MODE_UNCACHED:
 	case IOR_MODE_UNCACHED:
 	default:
 	default:

+ 9 - 9
arch/x86/mm/pgtable_32.c

@@ -342,12 +342,16 @@ static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
 
 
 pgd_t *pgd_alloc(struct mm_struct *mm)
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
 {
-	pgd_t *pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
+	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
 
 
-	mm->pgd = pgd;		/* so that alloc_pd can use it */
+	/* so that alloc_pd can use it */
+	mm->pgd = pgd;
+	if (pgd)
+		pgd_ctor(pgd);
 
 
 	if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
 	if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
-		quicklist_free(0, pgd_dtor, pgd);
+		pgd_dtor(pgd);
+		free_page((unsigned long)pgd);
 		pgd = NULL;
 		pgd = NULL;
 	}
 	}
 
 
@@ -357,12 +361,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 {
 {
 	pgd_mop_up_pmds(mm, pgd);
 	pgd_mop_up_pmds(mm, pgd);
-	quicklist_free(0, pgd_dtor, pgd);
-}
-
-void check_pgt_cache(void)
-{
-	quicklist_trim(0, pgd_dtor, 25, 16);
+	pgd_dtor(pgd);
+	free_page((unsigned long)pgd);
 }
 }
 
 
 void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
 void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)

+ 10 - 0
arch/x86/pci/pcbios.c

@@ -198,6 +198,11 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
 			  "b" (bx),
 			  "b" (bx),
 			  "D" ((long)reg),
 			  "D" ((long)reg),
 			  "S" (&pci_indirect));
 			  "S" (&pci_indirect));
+		/*
+		 * Zero-extend the result beyond 8 bits, do not trust the
+		 * BIOS having done it:
+		 */
+		*value &= 0xff;
 		break;
 		break;
 	case 2:
 	case 2:
 		__asm__("lcall *(%%esi); cld\n\t"
 		__asm__("lcall *(%%esi); cld\n\t"
@@ -210,6 +215,11 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
 			  "b" (bx),
 			  "b" (bx),
 			  "D" ((long)reg),
 			  "D" ((long)reg),
 			  "S" (&pci_indirect));
 			  "S" (&pci_indirect));
+		/*
+		 * Zero-extend the result beyond 16 bits, do not trust the
+		 * BIOS having done it:
+		 */
+		*value &= 0xffff;
 		break;
 		break;
 	case 4:
 	case 4:
 		__asm__("lcall *(%%esi); cld\n\t"
 		__asm__("lcall *(%%esi); cld\n\t"

+ 1 - 3
crypto/chainiv.c

@@ -318,10 +318,8 @@ int __init chainiv_module_init(void)
 {
 {
 	return crypto_register_template(&chainiv_tmpl);
 	return crypto_register_template(&chainiv_tmpl);
 }
 }
-EXPORT_SYMBOL_GPL(chainiv_module_init);
 
 
-void __exit chainiv_module_exit(void)
+void chainiv_module_exit(void)
 {
 {
 	crypto_unregister_template(&chainiv_tmpl);
 	crypto_unregister_template(&chainiv_tmpl);
 }
 }
-EXPORT_SYMBOL_GPL(chainiv_module_exit);

+ 0 - 2
crypto/eseqiv.c

@@ -251,10 +251,8 @@ int __init eseqiv_module_init(void)
 {
 {
 	return crypto_register_template(&eseqiv_tmpl);
 	return crypto_register_template(&eseqiv_tmpl);
 }
 }
-EXPORT_SYMBOL_GPL(eseqiv_module_init);
 
 
 void __exit eseqiv_module_exit(void)
 void __exit eseqiv_module_exit(void)
 {
 {
 	crypto_unregister_template(&eseqiv_tmpl);
 	crypto_unregister_template(&eseqiv_tmpl);
 }
 }
-EXPORT_SYMBOL_GPL(eseqiv_module_exit);

+ 9 - 0
drivers/ata/Kconfig

@@ -538,6 +538,15 @@ config PATA_RADISYS
 
 
 	  If unsure, say N.
 	  If unsure, say N.
 
 
+config PATA_RB500
+	tristate "RouterBoard 500 PATA CompactFlash support"
+	depends on MIKROTIK_RB500
+	help
+	  This option enables support for the RouterBoard 500
+	  PATA CompactFlash controller.
+
+	  If unsure, say N.
+
 config PATA_RZ1000
 config PATA_RZ1000
 	tristate "PC Tech RZ1000 PATA support"
 	tristate "PC Tech RZ1000 PATA support"
 	depends on PCI
 	depends on PCI

+ 1 - 0
drivers/ata/Makefile

@@ -55,6 +55,7 @@ obj-$(CONFIG_PATA_PDC2027X)	+= pata_pdc2027x.o
 obj-$(CONFIG_PATA_PDC_OLD)	+= pata_pdc202xx_old.o
 obj-$(CONFIG_PATA_PDC_OLD)	+= pata_pdc202xx_old.o
 obj-$(CONFIG_PATA_QDI)		+= pata_qdi.o
 obj-$(CONFIG_PATA_QDI)		+= pata_qdi.o
 obj-$(CONFIG_PATA_RADISYS)	+= pata_radisys.o
 obj-$(CONFIG_PATA_RADISYS)	+= pata_radisys.o
+obj-$(CONFIG_PATA_RB500)	+= pata_rb500_cf.o
 obj-$(CONFIG_PATA_RZ1000)	+= pata_rz1000.o
 obj-$(CONFIG_PATA_RZ1000)	+= pata_rz1000.o
 obj-$(CONFIG_PATA_SC1200)	+= pata_sc1200.o
 obj-$(CONFIG_PATA_SC1200)	+= pata_sc1200.o
 obj-$(CONFIG_PATA_SERVERWORKS)	+= pata_serverworks.o
 obj-$(CONFIG_PATA_SERVERWORKS)	+= pata_serverworks.o

+ 13 - 1
drivers/ata/ahci.c

@@ -567,6 +567,18 @@ static const struct pci_device_id ahci_pci_tbl[] = {
 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci },		/* MCP79 */
 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci },		/* MCP79 */
 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci },		/* MCP79 */
 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci },		/* MCP79 */
 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci },		/* MCP79 */
 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci },		/* MCP79 */
+	{ PCI_VDEVICE(NVIDIA, 0x0bc8), board_ahci },		/* MCP7B */
+	{ PCI_VDEVICE(NVIDIA, 0x0bc9), board_ahci },		/* MCP7B */
+	{ PCI_VDEVICE(NVIDIA, 0x0bca), board_ahci },		/* MCP7B */
+	{ PCI_VDEVICE(NVIDIA, 0x0bcb), board_ahci },		/* MCP7B */
+	{ PCI_VDEVICE(NVIDIA, 0x0bcc), board_ahci },		/* MCP7B */
+	{ PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci },		/* MCP7B */
+	{ PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci },		/* MCP7B */
+	{ PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci },		/* MCP7B */
+	{ PCI_VDEVICE(NVIDIA, 0x0bd0), board_ahci },		/* MCP7B */
+	{ PCI_VDEVICE(NVIDIA, 0x0bd1), board_ahci },		/* MCP7B */
+	{ PCI_VDEVICE(NVIDIA, 0x0bd2), board_ahci },		/* MCP7B */
+	{ PCI_VDEVICE(NVIDIA, 0x0bd3), board_ahci },		/* MCP7B */
 
 
 	/* SiS */
 	/* SiS */
 	{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
 	{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
@@ -672,7 +684,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
 		cap &= ~HOST_CAP_NCQ;
 		cap &= ~HOST_CAP_NCQ;
 	}
 	}
 
 
-	if ((cap && HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
+	if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
 		dev_printk(KERN_INFO, &pdev->dev,
 		dev_printk(KERN_INFO, &pdev->dev,
 			   "controller can't do PMP, turning off CAP_PMP\n");
 			   "controller can't do PMP, turning off CAP_PMP\n");
 		cap &= ~HOST_CAP_PMP;
 		cap &= ~HOST_CAP_PMP;

+ 4 - 4
drivers/ata/libata-acpi.c

@@ -382,7 +382,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
 
 
 	if (ata_msg_probe(ap))
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
 		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
-			       __FUNCTION__, ap->port_no);
+			       __func__, ap->port_no);
 
 
 	/* _GTF has no input parameters */
 	/* _GTF has no input parameters */
 	status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output);
 	status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output);
@@ -402,7 +402,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
 		if (ata_msg_probe(ap))
 		if (ata_msg_probe(ap))
 			ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: "
 			ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: "
 				"length or ptr is NULL (0x%llx, 0x%p)\n",
 				"length or ptr is NULL (0x%llx, 0x%p)\n",
-				__FUNCTION__,
+				__func__,
 				(unsigned long long)output.length,
 				(unsigned long long)output.length,
 				output.pointer);
 				output.pointer);
 		rc = -EINVAL;
 		rc = -EINVAL;
@@ -432,7 +432,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
 		if (ata_msg_probe(ap))
 		if (ata_msg_probe(ap))
 			ata_dev_printk(dev, KERN_DEBUG,
 			ata_dev_printk(dev, KERN_DEBUG,
 				       "%s: returning gtf=%p, gtf_count=%d\n",
 				       "%s: returning gtf=%p, gtf_count=%d\n",
-				       __FUNCTION__, *gtf, rc);
+				       __func__, *gtf, rc);
 	}
 	}
 	return rc;
 	return rc;
 
 
@@ -725,7 +725,7 @@ static int ata_acpi_push_id(struct ata_device *dev)
 
 
 	if (ata_msg_probe(ap))
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n",
 		ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n",
-			       __FUNCTION__, dev->devno, ap->port_no);
+			       __func__, dev->devno, ap->port_no);
 
 
 	/* Give the drive Identify data to the drive via the _SDD method */
 	/* Give the drive Identify data to the drive via the _SDD method */
 	/* _SDD: set up input parameters */
 	/* _SDD: set up input parameters */

+ 9 - 8
drivers/ata/libata-core.c

@@ -106,7 +106,8 @@ static struct ata_force_ent *ata_force_tbl;
 static int ata_force_tbl_size;
 static int ata_force_tbl_size;
 
 
 static char ata_force_param_buf[PAGE_SIZE] __initdata;
 static char ata_force_param_buf[PAGE_SIZE] __initdata;
-module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0444);
+/* param_buf is thrown away after initialization, disallow read */
+module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0);
 MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/kernel-parameters.txt for details)");
 MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/kernel-parameters.txt for details)");
 
 
 int atapi_enabled = 1;
 int atapi_enabled = 1;
@@ -1719,7 +1720,7 @@ void ata_port_flush_task(struct ata_port *ap)
 	cancel_rearming_delayed_work(&ap->port_task);
 	cancel_rearming_delayed_work(&ap->port_task);
 
 
 	if (ata_msg_ctl(ap))
 	if (ata_msg_ctl(ap))
-		ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
+		ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __func__);
 }
 }
 
 
 static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
 static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
@@ -2056,7 +2057,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
 	int rc;
 	int rc;
 
 
 	if (ata_msg_ctl(ap))
 	if (ata_msg_ctl(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
+		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
 
 
 	ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
 	ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
  retry:
  retry:
@@ -2253,12 +2254,12 @@ int ata_dev_configure(struct ata_device *dev)
 
 
 	if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
 	if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
 		ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT -- nodev\n",
 		ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT -- nodev\n",
-			       __FUNCTION__);
+			       __func__);
 		return 0;
 		return 0;
 	}
 	}
 
 
 	if (ata_msg_probe(ap))
 	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
+		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
 
 
 	/* set horkage */
 	/* set horkage */
 	dev->horkage |= ata_dev_blacklisted(dev);
 	dev->horkage |= ata_dev_blacklisted(dev);
@@ -2279,7 +2280,7 @@ int ata_dev_configure(struct ata_device *dev)
 		ata_dev_printk(dev, KERN_DEBUG,
 		ata_dev_printk(dev, KERN_DEBUG,
 			       "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x "
 			       "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x "
 			       "85:%04x 86:%04x 87:%04x 88:%04x\n",
 			       "85:%04x 86:%04x 87:%04x 88:%04x\n",
-			       __FUNCTION__,
+			       __func__,
 			       id[49], id[82], id[83], id[84],
 			       id[49], id[82], id[83], id[84],
 			       id[85], id[86], id[87], id[88]);
 			       id[85], id[86], id[87], id[88]);
 
 
@@ -2511,13 +2512,13 @@ int ata_dev_configure(struct ata_device *dev)
 
 
 	if (ata_msg_probe(ap))
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
 		ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
-			__FUNCTION__, ata_chk_status(ap));
+			__func__, ata_chk_status(ap));
 	return 0;
 	return 0;
 
 
 err_out_nosup:
 err_out_nosup:
 	if (ata_msg_probe(ap))
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG,
 		ata_dev_printk(dev, KERN_DEBUG,
-			       "%s: EXIT, err\n", __FUNCTION__);
+			       "%s: EXIT, err\n", __func__);
 	return rc;
 	return rc;
 }
 }
 
 

+ 10 - 0
drivers/ata/libata-eh.c

@@ -2150,6 +2150,15 @@ int ata_eh_reset(struct ata_link *link, int classify,
 			ap->ops->set_piomode(ap, dev);
 			ap->ops->set_piomode(ap, dev);
 	}
 	}
 
 
+	if (!softreset && !hardreset) {
+		if (verbose)
+			ata_link_printk(link, KERN_INFO, "no reset method "
+					"available, skipping reset\n");
+		if (!(lflags & ATA_LFLAG_ASSUME_CLASS))
+			lflags |= ATA_LFLAG_ASSUME_ATA;
+		goto done;
+	}
+
 	/* Determine which reset to use and record in ehc->i.action.
 	/* Determine which reset to use and record in ehc->i.action.
 	 * prereset() may examine and modify it.
 	 * prereset() may examine and modify it.
 	 */
 	 */
@@ -2254,6 +2263,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
 		lflags |= ATA_LFLAG_ASSUME_ATA;
 		lflags |= ATA_LFLAG_ASSUME_ATA;
 	}
 	}
 
 
+ done:
 	ata_link_for_each_dev(dev, link) {
 	ata_link_for_each_dev(dev, link) {
 		/* After the reset, the device state is PIO 0 and the
 		/* After the reset, the device state is PIO 0 and the
 		 * controller state is undefined.  Reset also wakes up
 		 * controller state is undefined.  Reset also wakes up

+ 22 - 14
drivers/ata/libata-sff.c

@@ -56,7 +56,8 @@ u8 ata_irq_on(struct ata_port *ap)
 	ap->ctl &= ~ATA_NIEN;
 	ap->ctl &= ~ATA_NIEN;
 	ap->last_ctl = ap->ctl;
 	ap->last_ctl = ap->ctl;
 
 
-	iowrite8(ap->ctl, ioaddr->ctl_addr);
+	if (ioaddr->ctl_addr)
+		iowrite8(ap->ctl, ioaddr->ctl_addr);
 	tmp = ata_wait_idle(ap);
 	tmp = ata_wait_idle(ap);
 
 
 	ap->ops->irq_clear(ap);
 	ap->ops->irq_clear(ap);
@@ -81,12 +82,14 @@ void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
 
 
 	if (tf->ctl != ap->last_ctl) {
 	if (tf->ctl != ap->last_ctl) {
-		iowrite8(tf->ctl, ioaddr->ctl_addr);
+		if (ioaddr->ctl_addr)
+			iowrite8(tf->ctl, ioaddr->ctl_addr);
 		ap->last_ctl = tf->ctl;
 		ap->last_ctl = tf->ctl;
 		ata_wait_idle(ap);
 		ata_wait_idle(ap);
 	}
 	}
 
 
 	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
 	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+		WARN_ON(!ioaddr->ctl_addr);
 		iowrite8(tf->hob_feature, ioaddr->feature_addr);
 		iowrite8(tf->hob_feature, ioaddr->feature_addr);
 		iowrite8(tf->hob_nsect, ioaddr->nsect_addr);
 		iowrite8(tf->hob_nsect, ioaddr->nsect_addr);
 		iowrite8(tf->hob_lbal, ioaddr->lbal_addr);
 		iowrite8(tf->hob_lbal, ioaddr->lbal_addr);
@@ -167,14 +170,17 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 	tf->device = ioread8(ioaddr->device_addr);
 	tf->device = ioread8(ioaddr->device_addr);
 
 
 	if (tf->flags & ATA_TFLAG_LBA48) {
 	if (tf->flags & ATA_TFLAG_LBA48) {
-		iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
-		tf->hob_feature = ioread8(ioaddr->error_addr);
-		tf->hob_nsect = ioread8(ioaddr->nsect_addr);
-		tf->hob_lbal = ioread8(ioaddr->lbal_addr);
-		tf->hob_lbam = ioread8(ioaddr->lbam_addr);
-		tf->hob_lbah = ioread8(ioaddr->lbah_addr);
-		iowrite8(tf->ctl, ioaddr->ctl_addr);
-		ap->last_ctl = tf->ctl;
+		if (likely(ioaddr->ctl_addr)) {
+			iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
+			tf->hob_feature = ioread8(ioaddr->error_addr);
+			tf->hob_nsect = ioread8(ioaddr->nsect_addr);
+			tf->hob_lbal = ioread8(ioaddr->lbal_addr);
+			tf->hob_lbam = ioread8(ioaddr->lbam_addr);
+			tf->hob_lbah = ioread8(ioaddr->lbah_addr);
+			iowrite8(tf->ctl, ioaddr->ctl_addr);
+			ap->last_ctl = tf->ctl;
+		} else
+			WARN_ON(1);
 	}
 	}
 }
 }
 
 
@@ -352,7 +358,8 @@ void ata_bmdma_freeze(struct ata_port *ap)
 	ap->ctl |= ATA_NIEN;
 	ap->ctl |= ATA_NIEN;
 	ap->last_ctl = ap->ctl;
 	ap->last_ctl = ap->ctl;
 
 
-	iowrite8(ap->ctl, ioaddr->ctl_addr);
+	if (ioaddr->ctl_addr)
+		iowrite8(ap->ctl, ioaddr->ctl_addr);
 
 
 	/* Under certain circumstances, some controllers raise IRQ on
 	/* Under certain circumstances, some controllers raise IRQ on
 	 * ATA_NIEN manipulation.  Also, many controllers fail to mask
 	 * ATA_NIEN manipulation.  Also, many controllers fail to mask
@@ -459,13 +466,14 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
  */
  */
 void ata_bmdma_error_handler(struct ata_port *ap)
 void ata_bmdma_error_handler(struct ata_port *ap)
 {
 {
-	ata_reset_fn_t hardreset;
+	ata_reset_fn_t softreset = NULL, hardreset = NULL;
 
 
-	hardreset = NULL;
+	if (ap->ioaddr.ctl_addr)
+		softreset = ata_std_softreset;
 	if (sata_scr_valid(&ap->link))
 	if (sata_scr_valid(&ap->link))
 		hardreset = sata_std_hardreset;
 		hardreset = sata_std_hardreset;
 
 
-	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
+	ata_bmdma_drive_eh(ap, ata_std_prereset, softreset, hardreset,
 			   ata_std_postreset);
 			   ata_std_postreset);
 }
 }
 
 

+ 1 - 1
drivers/ata/pata_pdc2027x.c

@@ -39,7 +39,7 @@
 #undef PDC_DEBUG
 #undef PDC_DEBUG
 
 
 #ifdef PDC_DEBUG
 #ifdef PDC_DEBUG
-#define PDPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#define PDPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
 #else
 #else
 #define PDPRINTK(fmt, args...)
 #define PDPRINTK(fmt, args...)
 #endif
 #endif

+ 314 - 0
drivers/ata/pata_rb500_cf.c

@@ -0,0 +1,314 @@
+/*
+ *  A low-level PATA driver to handle a Compact Flash connected on the
+ *  Mikrotik's RouterBoard 532 board.
+ *
+ *  Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
+ *  Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
+ *
+ *  This file was based on: drivers/ata/pata_ixp4xx_cf.c
+ *	Copyright (C) 2006-07 Tower Technologies
+ *	Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ *  Also was based on the driver for Linux 2.4.xx published by Mikrotik for
+ *  their RouterBoard 1xx and 5xx series devices. The original Mikrotik code
+ *  seems not to have a license.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <linux/libata.h>
+#include <scsi/scsi_host.h>
+
+#include <asm/gpio.h>
+
+#define DRV_NAME	"pata-rb500-cf"
+#define DRV_VERSION	"0.1.0"
+#define DRV_DESC	"PATA driver for RouterBOARD 532 Compact Flash"
+
+#define RB500_CF_MAXPORTS	1
+#define RB500_CF_IO_DELAY	400
+
+#define RB500_CF_REG_CMD	0x0800
+#define RB500_CF_REG_CTRL	0x080E
+#define RB500_CF_REG_DATA	0x0C00
+
+struct rb500_cf_info {
+	void __iomem	*iobase;
+	unsigned int	gpio_line;
+	int		frozen;
+	unsigned int	irq;
+};
+
+/* ------------------------------------------------------------------------ */
+
+static inline void rb500_pata_finish_io(struct ata_port *ap)
+{
+	struct ata_host *ah = ap->host;
+	struct rb500_cf_info *info = ah->private_data;
+
+	ata_altstatus(ap);
+	ndelay(RB500_CF_IO_DELAY);
+
+	set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
+}
+
+static void rb500_pata_exec_command(struct ata_port *ap,
+				const struct ata_taskfile *tf)
+{
+	writeb(tf->command, ap->ioaddr.command_addr);
+	rb500_pata_finish_io(ap);
+}
+
+static void rb500_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
+				unsigned int buflen, int write_data)
+{
+	struct ata_port *ap = adev->link->ap;
+	void __iomem *ioaddr = ap->ioaddr.data_addr;
+
+	if (write_data) {
+		for (; buflen > 0; buflen--, buf++)
+			writeb(*buf, ioaddr);
+	} else {
+		for (; buflen > 0; buflen--, buf++)
+			*buf = readb(ioaddr);
+	}
+
+	rb500_pata_finish_io(adev->link->ap);
+}
+
+static void rb500_pata_freeze(struct ata_port *ap)
+{
+	struct rb500_cf_info *info = ap->host->private_data;
+
+	info->frozen = 1;
+}
+
+static void rb500_pata_thaw(struct ata_port *ap)
+{
+	struct rb500_cf_info *info = ap->host->private_data;
+
+	info->frozen = 0;
+}
+
+static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance)
+{
+	struct ata_host *ah = dev_instance;
+	struct rb500_cf_info *info = ah->private_data;
+
+	if (gpio_get_value(info->gpio_line)) {
+		set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
+		if (!info->frozen)
+			ata_interrupt(info->irq, dev_instance);
+	} else {
+		set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void rb500_pata_irq_clear(struct ata_port *ap)
+{
+}
+
+static int rb500_pata_port_start(struct ata_port *ap)
+{
+	return 0;
+}
+
+static struct ata_port_operations rb500_pata_port_ops = {
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+
+	.exec_command		= rb500_pata_exec_command,
+	.check_status 		= ata_check_status,
+	.dev_select 		= ata_std_dev_select,
+
+	.data_xfer		= rb500_pata_data_xfer,
+
+	.qc_prep 		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+
+	.freeze			= rb500_pata_freeze,
+	.thaw			= rb500_pata_thaw,
+	.error_handler		= ata_bmdma_error_handler,
+
+	.irq_handler		= rb500_pata_irq_handler,
+	.irq_clear		= rb500_pata_irq_clear,
+	.irq_on			= ata_irq_on,
+
+	.port_start		= rb500_pata_port_start,
+};
+
+/* ------------------------------------------------------------------------ */
+
+static struct scsi_host_template rb500_pata_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
+	.bios_param		= ata_std_bios_param,
+	.proc_name		= DRV_NAME,
+
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.dma_boundary		= ATA_DMA_BOUNDARY,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+};
+
+/* ------------------------------------------------------------------------ */
+
+static void rb500_pata_setup_ports(struct ata_host *ah)
+{
+	struct rb500_cf_info *info = ah->private_data;
+	struct ata_port *ap;
+
+	ap = ah->ports[0];
+
+	ap->ops		= &rb500_pata_port_ops;
+	ap->pio_mask	= 0x1f; /* PIO4 */
+	ap->flags	= ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
+
+	ap->ioaddr.cmd_addr	= info->iobase + RB500_CF_REG_CMD;
+	ap->ioaddr.ctl_addr	= info->iobase + RB500_CF_REG_CTRL;
+	ap->ioaddr.altstatus_addr = info->iobase + RB500_CF_REG_CTRL;
+
+	ata_std_ports(&ap->ioaddr);
+
+	ap->ioaddr.data_addr	= info->iobase + RB500_CF_REG_DATA;
+}
+
+static __devinit int rb500_pata_driver_probe(struct platform_device *pdev)
+{
+	unsigned int irq;
+	int gpio;
+	struct resource *res;
+	struct ata_host *ah;
+	struct rb500_cf_info *info;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "no IOMEM resource found\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_err(&pdev->dev, "no IRQ resource found\n");
+		return -ENOENT;
+	}
+
+	gpio = irq_to_gpio(irq);
+	if (gpio < 0) {
+		dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq);
+		return -ENOENT;
+	}
+
+	ret = gpio_request(gpio, DRV_NAME);
+	if (ret) {
+		dev_err(&pdev->dev, "GPIO request failed\n");
+		return ret;
+	}
+
+	/* allocate host */
+	ah = ata_host_alloc(&pdev->dev, RB500_CF_MAXPORTS);
+	if (!ah)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ah);
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	ah->private_data = info;
+	info->gpio_line = gpio;
+	info->irq = irq;
+
+	info->iobase = devm_ioremap_nocache(&pdev->dev, res->start,
+				res->end - res->start + 1);
+	if (!info->iobase)
+		return -ENOMEM;
+
+	ret = gpio_direction_input(gpio);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to set GPIO direction, err=%d\n",
+				ret);
+		goto err_free_gpio;
+	}
+
+	rb500_pata_setup_ports(ah);
+
+	ret = ata_host_activate(ah, irq, rb500_pata_irq_handler,
+				IRQF_TRIGGER_LOW, &rb500_pata_sht);
+	if (ret)
+		goto err_free_gpio;
+
+	return 0;
+
+err_free_gpio:
+	gpio_free(gpio);
+
+	return ret;
+}
+
+static __devexit int rb500_pata_driver_remove(struct platform_device *pdev)
+{
+	struct ata_host *ah = platform_get_drvdata(pdev);
+	struct rb500_cf_info *info = ah->private_data;
+
+	ata_host_detach(ah);
+	gpio_free(info->gpio_line);
+
+	return 0;
+}
+
+static struct platform_driver rb500_pata_platform_driver = {
+	.probe		= rb500_pata_driver_probe,
+	.remove		= __devexit_p(rb500_pata_driver_remove),
+	.driver	 = {
+		.name   = DRV_NAME,
+		.owner  = THIS_MODULE,
+	},
+};
+
+/* ------------------------------------------------------------------------ */
+
+#define DRV_INFO DRV_DESC " version " DRV_VERSION
+
+static int __init rb500_pata_module_init(void)
+{
+	printk(KERN_INFO DRV_INFO "\n");
+
+	return platform_driver_register(&rb500_pata_platform_driver);
+}
+
+static void __exit rb500_pata_module_exit(void)
+{
+	platform_driver_unregister(&rb500_pata_platform_driver);
+}
+
+MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
+MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+
+module_init(rb500_pata_module_init);
+module_exit(rb500_pata_module_exit);

+ 1 - 1
drivers/base/platform.c

@@ -648,7 +648,7 @@ u64 dma_get_required_mask(struct device *dev)
 		high_totalram += high_totalram - 1;
 		high_totalram += high_totalram - 1;
 		mask = (((u64)high_totalram) << 32) + 0xffffffff;
 		mask = (((u64)high_totalram) << 32) + 0xffffffff;
 	}
 	}
-	return mask & *dev->dma_mask;
+	return mask;
 }
 }
 EXPORT_SYMBOL_GPL(dma_get_required_mask);
 EXPORT_SYMBOL_GPL(dma_get_required_mask);
 #endif
 #endif

+ 4 - 0
drivers/base/sys.c

@@ -133,6 +133,7 @@ int sysdev_class_register(struct sysdev_class * cls)
 	pr_debug("Registering sysdev class '%s'\n",
 	pr_debug("Registering sysdev class '%s'\n",
 		 kobject_name(&cls->kset.kobj));
 		 kobject_name(&cls->kset.kobj));
 	INIT_LIST_HEAD(&cls->drivers);
 	INIT_LIST_HEAD(&cls->drivers);
+	memset(&cls->kset.kobj, 0x00, sizeof(struct kobject));
 	cls->kset.kobj.parent = &system_kset->kobj;
 	cls->kset.kobj.parent = &system_kset->kobj;
 	cls->kset.kobj.ktype = &ktype_sysdev_class;
 	cls->kset.kobj.ktype = &ktype_sysdev_class;
 	cls->kset.kobj.kset = system_kset;
 	cls->kset.kobj.kset = system_kset;
@@ -227,6 +228,9 @@ int sysdev_register(struct sys_device * sysdev)
 
 
 	pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj));
 	pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj));
 
 
+	/* initialize the kobject to 0, in case it had previously been used */
+	memset(&sysdev->kobj, 0x00, sizeof(struct kobject));
+
 	/* Make sure the kset is set */
 	/* Make sure the kset is set */
 	sysdev->kobj.kset = &cls->kset;
 	sysdev->kobj.kset = &cls->kset;
 
 

+ 43 - 18
drivers/char/nozomi.c

@@ -190,6 +190,14 @@ enum card_type {
 	F32_8 = 8192,	/* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */
 	F32_8 = 8192,	/* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */
 };
 };
 
 
+/* Initialization states a card can be in */
+enum card_state {
+	NOZOMI_STATE_UKNOWN	= 0,
+	NOZOMI_STATE_ENABLED	= 1,	/* pci device enabled */
+	NOZOMI_STATE_ALLOCATED	= 2,	/* config setup done */
+	NOZOMI_STATE_READY	= 3,	/* flowcontrols received */
+};
+
 /* Two different toggle channels exist */
 /* Two different toggle channels exist */
 enum channel_type {
 enum channel_type {
 	CH_A = 0,
 	CH_A = 0,
@@ -385,6 +393,7 @@ struct nozomi {
 	spinlock_t spin_mutex;	/* secures access to registers and tty */
 	spinlock_t spin_mutex;	/* secures access to registers and tty */
 
 
 	unsigned int index_start;
 	unsigned int index_start;
+	enum card_state state;
 	u32 open_ttys;
 	u32 open_ttys;
 };
 };
 
 
@@ -686,6 +695,7 @@ static int nozomi_read_config_table(struct nozomi *dc)
 		dc->last_ier = dc->last_ier | CTRL_DL;
 		dc->last_ier = dc->last_ier | CTRL_DL;
 		writew(dc->last_ier, dc->reg_ier);
 		writew(dc->last_ier, dc->reg_ier);
 
 
+		dc->state = NOZOMI_STATE_ALLOCATED;
 		dev_info(&dc->pdev->dev, "Initialization OK!\n");
 		dev_info(&dc->pdev->dev, "Initialization OK!\n");
 		return 1;
 		return 1;
 	}
 	}
@@ -944,6 +954,14 @@ static int receive_flow_control(struct nozomi *dc)
 	case CTRL_APP2:
 	case CTRL_APP2:
 		port = PORT_APP2;
 		port = PORT_APP2;
 		enable_ier = APP2_DL;
 		enable_ier = APP2_DL;
+		if (dc->state == NOZOMI_STATE_ALLOCATED) {
+			/*
+			 * After card initialization the flow control
+			 * received for APP2 is always the last
+			 */
+			dc->state = NOZOMI_STATE_READY;
+			dev_info(&dc->pdev->dev, "Device READY!\n");
+		}
 		break;
 		break;
 	default:
 	default:
 		dev_err(&dc->pdev->dev,
 		dev_err(&dc->pdev->dev,
@@ -1366,22 +1384,12 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
 
 
 	dc->pdev = pdev;
 	dc->pdev = pdev;
 
 
-	/* Find out what card type it is */
-	nozomi_get_card_type(dc);
-
 	ret = pci_enable_device(dc->pdev);
 	ret = pci_enable_device(dc->pdev);
 	if (ret) {
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to enable PCI Device\n");
 		dev_err(&pdev->dev, "Failed to enable PCI Device\n");
 		goto err_free;
 		goto err_free;
 	}
 	}
 
 
-	start = pci_resource_start(dc->pdev, 0);
-	if (start == 0) {
-		dev_err(&pdev->dev, "No I/O address for card detected\n");
-		ret = -ENODEV;
-		goto err_disable_device;
-	}
-
 	ret = pci_request_regions(dc->pdev, NOZOMI_NAME);
 	ret = pci_request_regions(dc->pdev, NOZOMI_NAME);
 	if (ret) {
 	if (ret) {
 		dev_err(&pdev->dev, "I/O address 0x%04x already in use\n",
 		dev_err(&pdev->dev, "I/O address 0x%04x already in use\n",
@@ -1389,6 +1397,16 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
 		goto err_disable_device;
 		goto err_disable_device;
 	}
 	}
 
 
+	start = pci_resource_start(dc->pdev, 0);
+	if (start == 0) {
+		dev_err(&pdev->dev, "No I/O address for card detected\n");
+		ret = -ENODEV;
+		goto err_rel_regs;
+	}
+
+	/* Find out what card type it is */
+	nozomi_get_card_type(dc);
+
 	dc->base_addr = ioremap(start, dc->card_type);
 	dc->base_addr = ioremap(start, dc->card_type);
 	if (!dc->base_addr) {
 	if (!dc->base_addr) {
 		dev_err(&pdev->dev, "Unable to map card MMIO\n");
 		dev_err(&pdev->dev, "Unable to map card MMIO\n");
@@ -1425,6 +1443,14 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
 	dc->index_start = ndev_idx * MAX_PORT;
 	dc->index_start = ndev_idx * MAX_PORT;
 	ndevs[ndev_idx] = dc;
 	ndevs[ndev_idx] = dc;
 
 
+	pci_set_drvdata(pdev, dc);
+
+	/* Enable RESET interrupt */
+	dc->last_ier = RESET;
+	iowrite16(dc->last_ier, dc->reg_ier);
+
+	dc->state = NOZOMI_STATE_ENABLED;
+
 	for (i = 0; i < MAX_PORT; i++) {
 	for (i = 0; i < MAX_PORT; i++) {
 		mutex_init(&dc->port[i].tty_sem);
 		mutex_init(&dc->port[i].tty_sem);
 		dc->port[i].tty_open_count = 0;
 		dc->port[i].tty_open_count = 0;
@@ -1433,12 +1459,6 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
 							&pdev->dev);
 							&pdev->dev);
 	}
 	}
 
 
-	/* Enable  RESET interrupt. */
-	dc->last_ier = RESET;
-	writew(dc->last_ier, dc->reg_ier);
-
-	pci_set_drvdata(pdev, dc);
-
 	return 0;
 	return 0;
 
 
 err_free_sbuf:
 err_free_sbuf:
@@ -1553,7 +1573,7 @@ static int ntty_open(struct tty_struct *tty, struct file *file)
 	struct nozomi *dc = get_dc_by_tty(tty);
 	struct nozomi *dc = get_dc_by_tty(tty);
 	unsigned long flags;
 	unsigned long flags;
 
 
-	if (!port || !dc)
+	if (!port || !dc || dc->state != NOZOMI_STATE_READY)
 		return -ENODEV;
 		return -ENODEV;
 
 
 	if (mutex_lock_interruptible(&port->tty_sem))
 	if (mutex_lock_interruptible(&port->tty_sem))
@@ -1716,6 +1736,10 @@ static int ntty_tiocmget(struct tty_struct *tty, struct file *file)
 static int ntty_tiocmset(struct tty_struct *tty, struct file *file,
 static int ntty_tiocmset(struct tty_struct *tty, struct file *file,
 	unsigned int set, unsigned int clear)
 	unsigned int set, unsigned int clear)
 {
 {
+	struct nozomi *dc = get_dc_by_tty(tty);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dc->spin_mutex, flags);
 	if (set & TIOCM_RTS)
 	if (set & TIOCM_RTS)
 		set_rts(tty, 1);
 		set_rts(tty, 1);
 	else if (clear & TIOCM_RTS)
 	else if (clear & TIOCM_RTS)
@@ -1725,6 +1749,7 @@ static int ntty_tiocmset(struct tty_struct *tty, struct file *file,
 		set_dtr(tty, 1);
 		set_dtr(tty, 1);
 	else if (clear & TIOCM_DTR)
 	else if (clear & TIOCM_DTR)
 		set_dtr(tty, 0);
 		set_dtr(tty, 0);
+	spin_unlock_irqrestore(&dc->spin_mutex, flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1762,7 +1787,7 @@ static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp)
 	icount.brk = cnow.brk;
 	icount.brk = cnow.brk;
 	icount.buf_overrun = cnow.buf_overrun;
 	icount.buf_overrun = cnow.buf_overrun;
 
 
-	return copy_to_user(argp, &icount, sizeof(icount));
+	return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
 }
 }
 
 
 static int ntty_ioctl(struct tty_struct *tty, struct file *file,
 static int ntty_ioctl(struct tty_struct *tty, struct file *file,

+ 0 - 6
drivers/char/riscom8.c

@@ -1620,14 +1620,8 @@ static int __init rc_init_drivers(void)
 
 
 static void rc_release_drivers(void)
 static void rc_release_drivers(void)
 {
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
 	tty_unregister_driver(riscom_driver);
 	tty_unregister_driver(riscom_driver);
 	put_tty_driver(riscom_driver);
 	put_tty_driver(riscom_driver);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
 }
 }
 
 
 #ifndef MODULE
 #ifndef MODULE

+ 1 - 0
drivers/gpio/pca953x.c

@@ -184,6 +184,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
 	gc->direction_output = pca953x_gpio_direction_output;
 	gc->direction_output = pca953x_gpio_direction_output;
 	gc->get = pca953x_gpio_get_value;
 	gc->get = pca953x_gpio_get_value;
 	gc->set = pca953x_gpio_set_value;
 	gc->set = pca953x_gpio_set_value;
+	gc->can_sleep = 1;
 
 
 	gc->base = chip->gpio_start;
 	gc->base = chip->gpio_start;
 	gc->ngpio = gpios;
 	gc->ngpio = gpios;

+ 2 - 1
drivers/infiniband/core/cm.c

@@ -3759,6 +3759,7 @@ static void cm_remove_one(struct ib_device *device)
 		port = cm_dev->port[i-1];
 		port = cm_dev->port[i-1];
 		ib_modify_port(device, port->port_num, 0, &port_modify);
 		ib_modify_port(device, port->port_num, 0, &port_modify);
 		ib_unregister_mad_agent(port->mad_agent);
 		ib_unregister_mad_agent(port->mad_agent);
+		flush_workqueue(cm.wq);
 		cm_remove_port_fs(port);
 		cm_remove_port_fs(port);
 	}
 	}
 	kobject_put(&cm_dev->dev_obj);
 	kobject_put(&cm_dev->dev_obj);
@@ -3813,6 +3814,7 @@ static void __exit ib_cm_cleanup(void)
 		cancel_delayed_work(&timewait_info->work.work);
 		cancel_delayed_work(&timewait_info->work.work);
 	spin_unlock_irq(&cm.lock);
 	spin_unlock_irq(&cm.lock);
 
 
+	ib_unregister_client(&cm_client);
 	destroy_workqueue(cm.wq);
 	destroy_workqueue(cm.wq);
 
 
 	list_for_each_entry_safe(timewait_info, tmp, &cm.timewait_list, list) {
 	list_for_each_entry_safe(timewait_info, tmp, &cm.timewait_list, list) {
@@ -3820,7 +3822,6 @@ static void __exit ib_cm_cleanup(void)
 		kfree(timewait_info);
 		kfree(timewait_info);
 	}
 	}
 
 
-	ib_unregister_client(&cm_client);
 	class_unregister(&cm_class);
 	class_unregister(&cm_class);
 	idr_destroy(&cm.local_id_table);
 	idr_destroy(&cm.local_id_table);
 }
 }

+ 22 - 16
drivers/infiniband/core/fmr_pool.c

@@ -139,7 +139,7 @@ static inline struct ib_pool_fmr *ib_fmr_cache_lookup(struct ib_fmr_pool *pool,
 static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
 static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
 {
 {
 	int                 ret;
 	int                 ret;
-	struct ib_pool_fmr *fmr, *next;
+	struct ib_pool_fmr *fmr;
 	LIST_HEAD(unmap_list);
 	LIST_HEAD(unmap_list);
 	LIST_HEAD(fmr_list);
 	LIST_HEAD(fmr_list);
 
 
@@ -158,20 +158,6 @@ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
 #endif
 #endif
 	}
 	}
 
 
-	/*
-	 * The free_list may hold FMRs that have been put there
-	 * because they haven't reached the max_remap count.
-	 * Invalidate their mapping as well.
-	 */
-	list_for_each_entry_safe(fmr, next, &pool->free_list, list) {
-		if (fmr->remap_count == 0)
-			continue;
-		hlist_del_init(&fmr->cache_node);
-		fmr->remap_count = 0;
-		list_add_tail(&fmr->fmr->list, &fmr_list);
-		list_move(&fmr->list, &unmap_list);
-	}
-
 	list_splice(&pool->dirty_list, &unmap_list);
 	list_splice(&pool->dirty_list, &unmap_list);
 	INIT_LIST_HEAD(&pool->dirty_list);
 	INIT_LIST_HEAD(&pool->dirty_list);
 	pool->dirty_len = 0;
 	pool->dirty_len = 0;
@@ -384,6 +370,11 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
 
 
 	i = 0;
 	i = 0;
 	list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
 	list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
+		if (fmr->remap_count) {
+			INIT_LIST_HEAD(&fmr_list);
+			list_add_tail(&fmr->fmr->list, &fmr_list);
+			ib_unmap_fmr(&fmr_list);
+		}
 		ib_dealloc_fmr(fmr->fmr);
 		ib_dealloc_fmr(fmr->fmr);
 		list_del(&fmr->list);
 		list_del(&fmr->list);
 		kfree(fmr);
 		kfree(fmr);
@@ -407,8 +398,23 @@ EXPORT_SYMBOL(ib_destroy_fmr_pool);
  */
  */
 int ib_flush_fmr_pool(struct ib_fmr_pool *pool)
 int ib_flush_fmr_pool(struct ib_fmr_pool *pool)
 {
 {
-	int serial = atomic_inc_return(&pool->req_ser);
+	int serial;
+	struct ib_pool_fmr *fmr, *next;
+
+	/*
+	 * The free_list holds FMRs that may have been used
+	 * but have not been remapped enough times to be dirty.
+	 * Put them on the dirty list now so that the cleanup
+	 * thread will reap them too.
+	 */
+	spin_lock_irq(&pool->pool_lock);
+	list_for_each_entry_safe(fmr, next, &pool->free_list, list) {
+		if (fmr->remap_count > 0)
+			list_move(&fmr->list, &pool->dirty_list);
+	}
+	spin_unlock_irq(&pool->pool_lock);
 
 
+	serial = atomic_inc_return(&pool->req_ser);
 	wake_up_process(pool->thread);
 	wake_up_process(pool->thread);
 
 
 	if (wait_event_interruptible(pool->force_wait,
 	if (wait_event_interruptible(pool->force_wait,

+ 3 - 2
drivers/infiniband/core/iwcm.c

@@ -839,6 +839,7 @@ static void cm_work_handler(struct work_struct *_work)
 	unsigned long flags;
 	unsigned long flags;
 	int empty;
 	int empty;
 	int ret = 0;
 	int ret = 0;
+	int destroy_id;
 
 
 	spin_lock_irqsave(&cm_id_priv->lock, flags);
 	spin_lock_irqsave(&cm_id_priv->lock, flags);
 	empty = list_empty(&cm_id_priv->work_list);
 	empty = list_empty(&cm_id_priv->work_list);
@@ -857,9 +858,9 @@ static void cm_work_handler(struct work_struct *_work)
 			destroy_cm_id(&cm_id_priv->id);
 			destroy_cm_id(&cm_id_priv->id);
 		}
 		}
 		BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
 		BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
+		destroy_id = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
 		if (iwcm_deref_id(cm_id_priv)) {
 		if (iwcm_deref_id(cm_id_priv)) {
-			if (test_bit(IWCM_F_CALLBACK_DESTROY,
-				     &cm_id_priv->flags)) {
+			if (destroy_id) {
 				BUG_ON(!list_empty(&cm_id_priv->work_list));
 				BUG_ON(!list_empty(&cm_id_priv->work_list));
 				free_cm_id(cm_id_priv);
 				free_cm_id(cm_id_priv);
 			}
 			}

+ 4 - 1
drivers/infiniband/hw/cxgb3/iwch_provider.c

@@ -189,7 +189,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
 		return ERR_PTR(-ENOMEM);
 		return ERR_PTR(-ENOMEM);
 	}
 	}
 	chp->rhp = rhp;
 	chp->rhp = rhp;
-	chp->ibcq.cqe = (1 << chp->cq.size_log2) - 1;
+	chp->ibcq.cqe = 1 << chp->cq.size_log2;
 	spin_lock_init(&chp->lock);
 	spin_lock_init(&chp->lock);
 	atomic_set(&chp->refcnt, 1);
 	atomic_set(&chp->refcnt, 1);
 	init_waitqueue_head(&chp->wait);
 	init_waitqueue_head(&chp->wait);
@@ -819,8 +819,11 @@ static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
 		kfree(qhp);
 		kfree(qhp);
 		return ERR_PTR(-ENOMEM);
 		return ERR_PTR(-ENOMEM);
 	}
 	}
+
 	attrs->cap.max_recv_wr = rqsize - 1;
 	attrs->cap.max_recv_wr = rqsize - 1;
 	attrs->cap.max_send_wr = sqsize;
 	attrs->cap.max_send_wr = sqsize;
+	attrs->cap.max_inline_data = T3_MAX_INLINE;
+
 	qhp->rhp = rhp;
 	qhp->rhp = rhp;
 	qhp->attr.pd = php->pdid;
 	qhp->attr.pd = php->pdid;
 	qhp->attr.scq = ((struct iwch_cq *) attrs->send_cq)->cq.cqid;
 	qhp->attr.scq = ((struct iwch_cq *) attrs->send_cq)->cq.cqid;

+ 24 - 23
drivers/infiniband/ulp/iser/iser_verbs.c

@@ -237,36 +237,32 @@ static int iser_free_ib_conn_res(struct iser_conn *ib_conn)
 static
 static
 struct iser_device *iser_device_find_by_ib_device(struct rdma_cm_id *cma_id)
 struct iser_device *iser_device_find_by_ib_device(struct rdma_cm_id *cma_id)
 {
 {
-	struct list_head    *p_list;
-	struct iser_device  *device = NULL;
+	struct iser_device *device;
 
 
 	mutex_lock(&ig.device_list_mutex);
 	mutex_lock(&ig.device_list_mutex);
 
 
-	p_list = ig.device_list.next;
-	while (p_list != &ig.device_list) {
-		device = list_entry(p_list, struct iser_device, ig_list);
+	list_for_each_entry(device, &ig.device_list, ig_list)
 		/* find if there's a match using the node GUID */
 		/* find if there's a match using the node GUID */
 		if (device->ib_device->node_guid == cma_id->device->node_guid)
 		if (device->ib_device->node_guid == cma_id->device->node_guid)
-			break;
-	}
+			goto inc_refcnt;
 
 
-	if (device == NULL) {
-		device = kzalloc(sizeof *device, GFP_KERNEL);
-		if (device == NULL)
-			goto out;
-		/* assign this device to the device */
-		device->ib_device = cma_id->device;
-		/* init the device and link it into ig device list */
-		if (iser_create_device_ib_res(device)) {
-			kfree(device);
-			device = NULL;
-			goto out;
-		}
-		list_add(&device->ig_list, &ig.device_list);
+	device = kzalloc(sizeof *device, GFP_KERNEL);
+	if (device == NULL)
+		goto out;
+
+	/* assign this device to the device */
+	device->ib_device = cma_id->device;
+	/* init the device and link it into ig device list */
+	if (iser_create_device_ib_res(device)) {
+		kfree(device);
+		device = NULL;
+		goto out;
 	}
 	}
-out:
-	BUG_ON(device == NULL);
+	list_add(&device->ig_list, &ig.device_list);
+
+inc_refcnt:
 	device->refcount++;
 	device->refcount++;
+out:
 	mutex_unlock(&ig.device_list_mutex);
 	mutex_unlock(&ig.device_list_mutex);
 	return device;
 	return device;
 }
 }
@@ -372,6 +368,12 @@ static void iser_addr_handler(struct rdma_cm_id *cma_id)
 	int    ret;
 	int    ret;
 
 
 	device = iser_device_find_by_ib_device(cma_id);
 	device = iser_device_find_by_ib_device(cma_id);
+	if (!device) {
+		iser_err("device lookup/creation failed\n");
+		iser_connect_error(cma_id);
+		return;
+	}
+
 	ib_conn = (struct iser_conn *)cma_id->context;
 	ib_conn = (struct iser_conn *)cma_id->context;
 	ib_conn->device = device;
 	ib_conn->device = device;
 
 
@@ -380,7 +382,6 @@ static void iser_addr_handler(struct rdma_cm_id *cma_id)
 		iser_err("resolve route failed: %d\n", ret);
 		iser_err("resolve route failed: %d\n", ret);
 		iser_connect_error(cma_id);
 		iser_connect_error(cma_id);
 	}
 	}
-	return;
 }
 }
 
 
 static void iser_route_handler(struct rdma_cm_id *cma_id)
 static void iser_route_handler(struct rdma_cm_id *cma_id)

+ 1 - 1
drivers/input/serio/i8042.h

@@ -16,7 +16,7 @@
 
 
 #if defined(CONFIG_MACH_JAZZ)
 #if defined(CONFIG_MACH_JAZZ)
 #include "i8042-jazzio.h"
 #include "i8042-jazzio.h"
-#elif defined(CONFIG_SGI_IP22)
+#elif defined(CONFIG_SGI_HAS_I8042)
 #include "i8042-ip22io.h"
 #include "i8042-ip22io.h"
 #elif defined(CONFIG_PPC)
 #elif defined(CONFIG_PPC)
 #include "i8042-ppcio.h"
 #include "i8042-ppcio.h"

+ 13 - 2
drivers/lguest/core.c

@@ -69,11 +69,22 @@ static __init int map_switcher(void)
 		switcher_page[i] = virt_to_page(addr);
 		switcher_page[i] = virt_to_page(addr);
 	}
 	}
 
 
+	/* First we check that the Switcher won't overlap the fixmap area at
+	 * the top of memory.  It's currently nowhere near, but it could have
+	 * very strange effects if it ever happened. */
+	if (SWITCHER_ADDR + (TOTAL_SWITCHER_PAGES+1)*PAGE_SIZE > FIXADDR_START){
+		err = -ENOMEM;
+		printk("lguest: mapping switcher would thwack fixmap\n");
+		goto free_pages;
+	}
+
 	/* Now we reserve the "virtual memory area" we want: 0xFFC00000
 	/* Now we reserve the "virtual memory area" we want: 0xFFC00000
 	 * (SWITCHER_ADDR).  We might not get it in theory, but in practice
 	 * (SWITCHER_ADDR).  We might not get it in theory, but in practice
-	 * it's worked so far. */
+	 * it's worked so far.  The end address needs +1 because __get_vm_area
+	 * allocates an extra guard page, so we need space for that. */
 	switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE,
 	switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE,
-				       VM_ALLOC, SWITCHER_ADDR, VMALLOC_END);
+				     VM_ALLOC, SWITCHER_ADDR, SWITCHER_ADDR
+				     + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE);
 	if (!switcher_vma) {
 	if (!switcher_vma) {
 		err = -ENOMEM;
 		err = -ENOMEM;
 		printk("lguest: could not map switcher pages high\n");
 		printk("lguest: could not map switcher pages high\n");

+ 8 - 7
drivers/lguest/lguest_user.c

@@ -241,15 +241,16 @@ static ssize_t write(struct file *file, const char __user *in,
 		cpu = &lg->cpus[cpu_id];
 		cpu = &lg->cpus[cpu_id];
 		if (!cpu)
 		if (!cpu)
 			return -EINVAL;
 			return -EINVAL;
-	}
 
 
-	/* Once the Guest is dead, all you can do is read() why it died. */
-	if (lg && lg->dead)
-		return -ENOENT;
+		/* Once the Guest is dead, you can only read() why it died. */
+		if (lg->dead)
+			return -ENOENT;
 
 
-	/* If you're not the task which owns the Guest, you can only break */
-	if (lg && current != cpu->tsk && req != LHREQ_BREAK)
-		return -EPERM;
+		/* If you're not the task which owns the Guest, all you can do
+		 * is break the Launcher out of running the Guest. */
+		if (current != cpu->tsk && req != LHREQ_BREAK)
+			return -EPERM;
+	}
 
 
 	switch (req) {
 	switch (req) {
 	case LHREQ_INITIALIZE:
 	case LHREQ_INITIALIZE:

+ 1 - 1
drivers/lguest/page_tables.c

@@ -391,7 +391,7 @@ static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable)
 {
 {
 	unsigned int i;
 	unsigned int i;
 	for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++)
 	for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++)
-		if (lg->pgdirs[i].gpgdir == pgtable)
+		if (lg->pgdirs[i].pgdir && lg->pgdirs[i].gpgdir == pgtable)
 			break;
 			break;
 	return i;
 	return i;
 }
 }

+ 3 - 1
drivers/md/bitmap.c

@@ -1045,7 +1045,8 @@ void bitmap_daemon_work(struct bitmap *bitmap)
 	if (bitmap == NULL)
 	if (bitmap == NULL)
 		return;
 		return;
 	if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
 	if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
-		return;
+		goto done;
+
 	bitmap->daemon_lastrun = jiffies;
 	bitmap->daemon_lastrun = jiffies;
 	if (bitmap->allclean) {
 	if (bitmap->allclean) {
 		bitmap->mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
 		bitmap->mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
@@ -1142,6 +1143,7 @@ void bitmap_daemon_work(struct bitmap *bitmap)
 		}
 		}
 	}
 	}
 
 
+ done:
 	if (bitmap->allclean == 0)
 	if (bitmap->allclean == 0)
 		bitmap->mddev->thread->timeout = bitmap->daemon_sleep * HZ;
 		bitmap->mddev->thread->timeout = bitmap->daemon_sleep * HZ;
 }
 }

+ 1 - 1
drivers/md/md.c

@@ -5149,7 +5149,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
 			if (mddev->ro==1)
 			if (mddev->ro==1)
 				seq_printf(seq, " (read-only)");
 				seq_printf(seq, " (read-only)");
 			if (mddev->ro==2)
 			if (mddev->ro==2)
-				seq_printf(seq, "(auto-read-only)");
+				seq_printf(seq, " (auto-read-only)");
 			seq_printf(seq, " %s", mddev->pers->name);
 			seq_printf(seq, " %s", mddev->pers->name);
 		}
 		}
 
 

+ 1 - 1
drivers/memstick/Kconfig

@@ -8,7 +8,7 @@ menuconfig MEMSTICK
 	  Sony MemoryStick is a proprietary storage/extension card protocol.
 	  Sony MemoryStick is a proprietary storage/extension card protocol.
 
 
 	  If you want MemoryStick support, you should say Y here and also
 	  If you want MemoryStick support, you should say Y here and also
-	  to the specific driver for your MMC interface.
+	  to the specific driver for your MemoryStick interface.
 
 
 if MEMSTICK
 if MEMSTICK
 
 

+ 28 - 5
drivers/memstick/core/memstick.c

@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/delay.h>
 
 
 #define DRIVER_NAME "memstick"
 #define DRIVER_NAME "memstick"
-#define DRIVER_VERSION "0.2"
 
 
 static unsigned int cmd_retries = 3;
 static unsigned int cmd_retries = 3;
 module_param(cmd_retries, uint, 0644);
 module_param(cmd_retries, uint, 0644);
@@ -236,7 +235,7 @@ int memstick_next_req(struct memstick_host *host, struct memstick_request **mrq)
 		rc = host->card->next_request(host->card, mrq);
 		rc = host->card->next_request(host->card, mrq);
 
 
 	if (!rc)
 	if (!rc)
-		host->retries = cmd_retries;
+		host->retries = cmd_retries > 1 ? cmd_retries - 1 : 1;
 	else
 	else
 		*mrq = NULL;
 		*mrq = NULL;
 
 
@@ -271,7 +270,7 @@ void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc,
 		mrq->data_dir = READ;
 		mrq->data_dir = READ;
 
 
 	mrq->sg = *sg;
 	mrq->sg = *sg;
-	mrq->io_type = MEMSTICK_IO_SG;
+	mrq->long_data = 1;
 
 
 	if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD)
 	if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD)
 		mrq->need_card_int = 1;
 		mrq->need_card_int = 1;
@@ -306,7 +305,7 @@ void memstick_init_req(struct memstick_request *mrq, unsigned char tpc,
 	if (mrq->data_dir == WRITE)
 	if (mrq->data_dir == WRITE)
 		memcpy(mrq->data, buf, mrq->data_len);
 		memcpy(mrq->data, buf, mrq->data_len);
 
 
-	mrq->io_type = MEMSTICK_IO_VAL;
+	mrq->long_data = 0;
 
 
 	if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD)
 	if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD)
 		mrq->need_card_int = 1;
 		mrq->need_card_int = 1;
@@ -561,6 +560,31 @@ void memstick_free_host(struct memstick_host *host)
 }
 }
 EXPORT_SYMBOL(memstick_free_host);
 EXPORT_SYMBOL(memstick_free_host);
 
 
+/**
+ * memstick_suspend_host - notify bus driver of host suspension
+ * @host - host to use
+ */
+void memstick_suspend_host(struct memstick_host *host)
+{
+	mutex_lock(&host->lock);
+	host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
+	mutex_unlock(&host->lock);
+}
+EXPORT_SYMBOL(memstick_suspend_host);
+
+/**
+ * memstick_resume_host - notify bus driver of host resumption
+ * @host - host to use
+ */
+void memstick_resume_host(struct memstick_host *host)
+{
+	mutex_lock(&host->lock);
+	host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);
+	mutex_unlock(&host->lock);
+	memstick_detect_change(host);
+}
+EXPORT_SYMBOL(memstick_resume_host);
+
 int memstick_register_driver(struct memstick_driver *drv)
 int memstick_register_driver(struct memstick_driver *drv)
 {
 {
 	drv->driver.bus = &memstick_bus_type;
 	drv->driver.bus = &memstick_bus_type;
@@ -611,4 +635,3 @@ module_exit(memstick_exit);
 MODULE_AUTHOR("Alex Dubov");
 MODULE_AUTHOR("Alex Dubov");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Sony MemoryStick core driver");
 MODULE_DESCRIPTION("Sony MemoryStick core driver");
-MODULE_VERSION(DRIVER_VERSION);

+ 92 - 14
drivers/memstick/core/mspro_block.c

@@ -16,10 +16,10 @@
 #include <linux/idr.h>
 #include <linux/idr.h>
 #include <linux/hdreg.h>
 #include <linux/hdreg.h>
 #include <linux/kthread.h>
 #include <linux/kthread.h>
+#include <linux/delay.h>
 #include <linux/memstick.h>
 #include <linux/memstick.h>
 
 
 #define DRIVER_NAME "mspro_block"
 #define DRIVER_NAME "mspro_block"
-#define DRIVER_VERSION "0.2"
 
 
 static int major;
 static int major;
 module_param(major, int, 0644);
 module_param(major, int, 0644);
@@ -110,6 +110,17 @@ struct mspro_mbr {
 	unsigned int  sectors_per_partition;
 	unsigned int  sectors_per_partition;
 } __attribute__((packed));
 } __attribute__((packed));
 
 
+struct mspro_specfile {
+	char           name[8];
+	char           ext[3];
+	unsigned char  attr;
+	unsigned char  reserved[10];
+	unsigned short time;
+	unsigned short date;
+	unsigned short cluster;
+	unsigned int   size;
+} __attribute__((packed));
+
 struct mspro_devinfo {
 struct mspro_devinfo {
 	unsigned short cylinders;
 	unsigned short cylinders;
 	unsigned short heads;
 	unsigned short heads;
@@ -293,6 +304,20 @@ static ssize_t mspro_block_attr_show_sysinfo(struct device *dev,
 						     dev_attr);
 						     dev_attr);
 	struct mspro_sys_info *x_sys = x_attr->data;
 	struct mspro_sys_info *x_sys = x_attr->data;
 	ssize_t rc = 0;
 	ssize_t rc = 0;
+	int date_tz = 0, date_tz_f = 0;
+
+	if (x_sys->assembly_date[0] > 0x80U) {
+		date_tz = (~x_sys->assembly_date[0]) + 1;
+		date_tz_f = date_tz & 3;
+		date_tz >>= 2;
+		date_tz = -date_tz;
+		date_tz_f *= 15;
+	} else if (x_sys->assembly_date[0] < 0x80U) {
+		date_tz = x_sys->assembly_date[0];
+		date_tz_f = date_tz & 3;
+		date_tz >>= 2;
+		date_tz_f *= 15;
+	}
 
 
 	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "class: %x\n",
 	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "class: %x\n",
 			x_sys->class);
 			x_sys->class);
@@ -305,8 +330,8 @@ static ssize_t mspro_block_attr_show_sysinfo(struct device *dev,
 	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "page size: %x\n",
 	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "page size: %x\n",
 			be16_to_cpu(x_sys->page_size));
 			be16_to_cpu(x_sys->page_size));
 	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly date: "
 	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly date: "
-			"%d %04u-%02u-%02u %02u:%02u:%02u\n",
-			x_sys->assembly_date[0],
+			"GMT%+d:%d %04u-%02u-%02u %02u:%02u:%02u\n",
+			date_tz, date_tz_f,
 			be16_to_cpu(*(unsigned short *)
 			be16_to_cpu(*(unsigned short *)
 				    &x_sys->assembly_date[1]),
 				    &x_sys->assembly_date[1]),
 			x_sys->assembly_date[3], x_sys->assembly_date[4],
 			x_sys->assembly_date[3], x_sys->assembly_date[4],
@@ -398,6 +423,41 @@ static ssize_t mspro_block_attr_show_mbr(struct device *dev,
 	return rc;
 	return rc;
 }
 }
 
 
+static ssize_t mspro_block_attr_show_specfile(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buffer)
+{
+	struct mspro_sys_attr *x_attr = container_of(attr,
+						     struct mspro_sys_attr,
+						     dev_attr);
+	struct mspro_specfile *x_spfile = x_attr->data;
+	char name[9], ext[4];
+	ssize_t rc = 0;
+
+	memcpy(name, x_spfile->name, 8);
+	name[8] = 0;
+	memcpy(ext, x_spfile->ext, 3);
+	ext[3] = 0;
+
+	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "name: %s\n", name);
+	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "ext: %s\n", ext);
+	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "attribute: %x\n",
+			x_spfile->attr);
+	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "time: %d:%d:%d\n",
+			x_spfile->time >> 11,
+			(x_spfile->time >> 5) & 0x3f,
+			(x_spfile->time & 0x1f) * 2);
+	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "date: %d-%d-%d\n",
+			(x_spfile->date >> 9) + 1980,
+			(x_spfile->date >> 5) & 0xf,
+			x_spfile->date & 0x1f);
+	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start cluster: %x\n",
+			x_spfile->cluster);
+	rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "size: %x\n",
+			x_spfile->size);
+	return rc;
+}
+
 static ssize_t mspro_block_attr_show_devinfo(struct device *dev,
 static ssize_t mspro_block_attr_show_devinfo(struct device *dev,
 					     struct device_attribute *attr,
 					     struct device_attribute *attr,
 					     char *buffer)
 					     char *buffer)
@@ -430,6 +490,9 @@ static sysfs_show_t mspro_block_attr_show(unsigned char tag)
 		return mspro_block_attr_show_modelname;
 		return mspro_block_attr_show_modelname;
 	case MSPRO_BLOCK_ID_MBR:
 	case MSPRO_BLOCK_ID_MBR:
 		return mspro_block_attr_show_mbr;
 		return mspro_block_attr_show_mbr;
+	case MSPRO_BLOCK_ID_SPECFILEVALUES1:
+	case MSPRO_BLOCK_ID_SPECFILEVALUES2:
+		return mspro_block_attr_show_specfile;
 	case MSPRO_BLOCK_ID_DEVINFO:
 	case MSPRO_BLOCK_ID_DEVINFO:
 		return mspro_block_attr_show_devinfo;
 		return mspro_block_attr_show_devinfo;
 	default:
 	default:
@@ -629,7 +692,7 @@ static void mspro_block_process_request(struct memstick_dev *card,
 			param.system = msb->system;
 			param.system = msb->system;
 			param.data_count = cpu_to_be16(page_count);
 			param.data_count = cpu_to_be16(page_count);
 			param.data_address = cpu_to_be32((uint32_t)t_sec);
 			param.data_address = cpu_to_be32((uint32_t)t_sec);
-			param.cmd_param = 0;
+			param.tpc_param = 0;
 
 
 			msb->data_dir = rq_data_dir(req);
 			msb->data_dir = rq_data_dir(req);
 			msb->transfer_cmd = msb->data_dir == READ
 			msb->transfer_cmd = msb->data_dir == READ
@@ -758,10 +821,10 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card)
 	struct memstick_host *host = card->host;
 	struct memstick_host *host = card->host;
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
 	struct mspro_param_register param = {
 	struct mspro_param_register param = {
-		.system = 0,
+		.system = MEMSTICK_SYS_PAR4,
 		.data_count = 0,
 		.data_count = 0,
 		.data_address = 0,
 		.data_address = 0,
-		.cmd_param = 0
+		.tpc_param = 0
 	};
 	};
 
 
 	card->next_request = h_mspro_block_req_init;
 	card->next_request = h_mspro_block_req_init;
@@ -773,8 +836,8 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card)
 	if (card->current_mrq.error)
 	if (card->current_mrq.error)
 		return card->current_mrq.error;
 		return card->current_mrq.error;
 
 
-	msb->system = 0;
-	host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PARALLEL);
+	msb->system = MEMSTICK_SYS_PAR4;
+	host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4);
 
 
 	card->next_request = h_mspro_block_req_init;
 	card->next_request = h_mspro_block_req_init;
 	msb->mrq_handler = h_mspro_block_default;
 	msb->mrq_handler = h_mspro_block_default;
@@ -783,8 +846,24 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card)
 	wait_for_completion(&card->mrq_complete);
 	wait_for_completion(&card->mrq_complete);
 
 
 	if (card->current_mrq.error) {
 	if (card->current_mrq.error) {
-		msb->system = 0x80;
+		msb->system = MEMSTICK_SYS_SERIAL;
+		host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
+		msleep(1000);
+		host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);
 		host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
 		host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
+
+		if (memstick_set_rw_addr(card))
+			return card->current_mrq.error;
+
+		param.system = msb->system;
+
+		card->next_request = h_mspro_block_req_init;
+		msb->mrq_handler = h_mspro_block_default;
+		memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, &param,
+				  sizeof(param));
+		memstick_new_req(host);
+		wait_for_completion(&card->mrq_complete);
+
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
 
 
@@ -802,7 +881,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
 		.system = msb->system,
 		.system = msb->system,
 		.data_count = cpu_to_be16(1),
 		.data_count = cpu_to_be16(1),
 		.data_address = 0,
 		.data_address = 0,
-		.cmd_param = 0
+		.tpc_param = 0
 	};
 	};
 	struct mspro_attribute *attr = NULL;
 	struct mspro_attribute *attr = NULL;
 	struct mspro_sys_attr *s_attr = NULL;
 	struct mspro_sys_attr *s_attr = NULL;
@@ -922,7 +1001,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
 		param.system = msb->system;
 		param.system = msb->system;
 		param.data_count = cpu_to_be16((rc / msb->page_size) + 1);
 		param.data_count = cpu_to_be16((rc / msb->page_size) + 1);
 		param.data_address = cpu_to_be32(addr / msb->page_size);
 		param.data_address = cpu_to_be32(addr / msb->page_size);
-		param.cmd_param = 0;
+		param.tpc_param = 0;
 
 
 		sg_init_one(&msb->req_sg[0], buffer,
 		sg_init_one(&msb->req_sg[0], buffer,
 			    be16_to_cpu(param.data_count) * msb->page_size);
 			    be16_to_cpu(param.data_count) * msb->page_size);
@@ -964,7 +1043,7 @@ static int mspro_block_init_card(struct memstick_dev *card)
 	struct memstick_host *host = card->host;
 	struct memstick_host *host = card->host;
 	int rc = 0;
 	int rc = 0;
 
 
-	msb->system = 0x80;
+	msb->system = MEMSTICK_SYS_SERIAL;
 	card->reg_addr.r_offset = offsetof(struct mspro_register, status);
 	card->reg_addr.r_offset = offsetof(struct mspro_register, status);
 	card->reg_addr.r_length = sizeof(struct ms_status_register);
 	card->reg_addr.r_length = sizeof(struct ms_status_register);
 	card->reg_addr.w_offset = offsetof(struct mspro_register, param);
 	card->reg_addr.w_offset = offsetof(struct mspro_register, param);
@@ -973,7 +1052,7 @@ static int mspro_block_init_card(struct memstick_dev *card)
 	if (memstick_set_rw_addr(card))
 	if (memstick_set_rw_addr(card))
 		return -EIO;
 		return -EIO;
 
 
-	if (host->caps & MEMSTICK_CAP_PARALLEL) {
+	if (host->caps & MEMSTICK_CAP_PAR4) {
 		if (mspro_block_switch_to_parallel(card))
 		if (mspro_block_switch_to_parallel(card))
 			printk(KERN_WARNING "%s: could not switch to "
 			printk(KERN_WARNING "%s: could not switch to "
 			       "parallel interface\n", card->dev.bus_id);
 			       "parallel interface\n", card->dev.bus_id);
@@ -1348,4 +1427,3 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Alex Dubov");
 MODULE_AUTHOR("Alex Dubov");
 MODULE_DESCRIPTION("Sony MemoryStickPro block device driver");
 MODULE_DESCRIPTION("Sony MemoryStickPro block device driver");
 MODULE_DEVICE_TABLE(memstick, mspro_block_id_tbl);
 MODULE_DEVICE_TABLE(memstick, mspro_block_id_tbl);
-MODULE_VERSION(DRIVER_VERSION);

+ 10 - 0
drivers/memstick/host/Kconfig

@@ -20,3 +20,13 @@ config MEMSTICK_TIFM_MS
           To compile this driver as a module, choose M here: the
           To compile this driver as a module, choose M here: the
 	  module will be called tifm_ms.
 	  module will be called tifm_ms.
 
 
+config MEMSTICK_JMICRON_38X
+	tristate "JMicron JMB38X MemoryStick interface support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && PCI
+
+	help
+	  Say Y here if you want to be able to access MemoryStick cards with
+	  the JMicron(R) JMB38X MemoryStick card reader.
+
+          To compile this driver as a module, choose M here: the
+	  module will be called jmb38x_ms.

+ 3 - 3
drivers/memstick/host/Makefile

@@ -3,8 +3,8 @@
 #
 #
 
 
 ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
 ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
+	EXTRA_CFLAGS			+= -DDEBUG
 endif
 endif
 
 
-obj-$(CONFIG_MEMSTICK_TIFM_MS)	+= tifm_ms.o
-
+obj-$(CONFIG_MEMSTICK_TIFM_MS)		+= tifm_ms.o
+obj-$(CONFIG_MEMSTICK_JMICRON_38X)	+= jmb38x_ms.o

+ 945 - 0
drivers/memstick/host/jmb38x_ms.c

@@ -0,0 +1,945 @@
+/*
+ *  jmb38x_ms.c - JMicron jmb38x MemoryStick card reader
+ *
+ *  Copyright (C) 2008 Alex Dubov <oakad@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/highmem.h>
+#include <linux/memstick.h>
+
+#define DRIVER_NAME "jmb38x_ms"
+
+static int no_dma;
+module_param(no_dma, bool, 0644);
+
+enum {
+	DMA_ADDRESS       = 0x00,
+	BLOCK             = 0x04,
+	DMA_CONTROL       = 0x08,
+	TPC_P0            = 0x0c,
+	TPC_P1            = 0x10,
+	TPC               = 0x14,
+	HOST_CONTROL      = 0x18,
+	DATA              = 0x1c,
+	STATUS            = 0x20,
+	INT_STATUS        = 0x24,
+	INT_STATUS_ENABLE = 0x28,
+	INT_SIGNAL_ENABLE = 0x2c,
+	TIMER             = 0x30,
+	TIMER_CONTROL     = 0x34,
+	PAD_OUTPUT_ENABLE = 0x38,
+	PAD_PU_PD         = 0x3c,
+	CLOCK_DELAY       = 0x40,
+	ADMA_ADDRESS      = 0x44,
+	CLOCK_CONTROL     = 0x48,
+	LED_CONTROL       = 0x4c,
+	VERSION           = 0x50
+};
+
+struct jmb38x_ms_host {
+	struct jmb38x_ms        *chip;
+	void __iomem            *addr;
+	spinlock_t              lock;
+	int                     id;
+	char                    host_id[DEVICE_ID_SIZE];
+	int                     irq;
+	unsigned int            block_pos;
+	unsigned long           timeout_jiffies;
+	struct timer_list       timer;
+	struct memstick_request *req;
+	unsigned char           eject:1,
+				use_dma:1;
+	unsigned char           cmd_flags;
+	unsigned char           io_pos;
+	unsigned int            io_word[2];
+};
+
+struct jmb38x_ms {
+	struct pci_dev        *pdev;
+	int                   host_cnt;
+	struct memstick_host  *hosts[];
+};
+
+#define BLOCK_COUNT_MASK       0xffff0000
+#define BLOCK_SIZE_MASK        0x00000fff
+
+#define DMA_CONTROL_ENABLE     0x00000001
+
+#define TPC_DATA_SEL           0x00008000
+#define TPC_DIR                0x00004000
+#define TPC_WAIT_INT           0x00002000
+#define TPC_GET_INT            0x00000800
+#define TPC_CODE_SZ_MASK       0x00000700
+#define TPC_DATA_SZ_MASK       0x00000007
+
+#define HOST_CONTROL_RESET_REQ 0x00008000
+#define HOST_CONTROL_REI       0x00004000
+#define HOST_CONTROL_LED       0x00000400
+#define HOST_CONTROL_FAST_CLK  0x00000200
+#define HOST_CONTROL_RESET     0x00000100
+#define HOST_CONTROL_POWER_EN  0x00000080
+#define HOST_CONTROL_CLOCK_EN  0x00000040
+#define HOST_CONTROL_IF_SHIFT  4
+
+#define HOST_CONTROL_IF_SERIAL 0x0
+#define HOST_CONTROL_IF_PAR4   0x1
+#define HOST_CONTROL_IF_PAR8   0x3
+
+#define STATUS_HAS_MEDIA        0x00000400
+#define STATUS_FIFO_EMPTY       0x00000200
+#define STATUS_FIFO_FULL        0x00000100
+
+#define INT_STATUS_TPC_ERR      0x00080000
+#define INT_STATUS_CRC_ERR      0x00040000
+#define INT_STATUS_TIMER_TO     0x00020000
+#define INT_STATUS_HSK_TO       0x00010000
+#define INT_STATUS_ANY_ERR      0x00008000
+#define INT_STATUS_FIFO_WRDY    0x00000080
+#define INT_STATUS_FIFO_RRDY    0x00000040
+#define INT_STATUS_MEDIA_OUT    0x00000010
+#define INT_STATUS_MEDIA_IN     0x00000008
+#define INT_STATUS_DMA_BOUNDARY 0x00000004
+#define INT_STATUS_EOTRAN       0x00000002
+#define INT_STATUS_EOTPC        0x00000001
+
+#define INT_STATUS_ALL          0x000f801f
+
+#define PAD_OUTPUT_ENABLE_MS  0x0F3F
+
+#define PAD_PU_PD_OFF         0x7FFF0000
+#define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000
+#define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000
+
+enum {
+	CMD_READY    = 0x01,
+	FIFO_READY   = 0x02,
+	REG_DATA     = 0x04,
+	AUTO_GET_INT = 0x08
+};
+
+static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host,
+					unsigned char *buf, unsigned int length)
+{
+	unsigned int off = 0;
+
+	while (host->io_pos && length) {
+		buf[off++] = host->io_word[0] & 0xff;
+		host->io_word[0] >>= 8;
+		length--;
+		host->io_pos--;
+	}
+
+	if (!length)
+		return off;
+
+	while (!(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
+		if (length < 4)
+			break;
+		*(unsigned int *)(buf + off) = __raw_readl(host->addr + DATA);
+		length -= 4;
+		off += 4;
+	}
+
+	if (length
+	    && !(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
+		host->io_word[0] = readl(host->addr + DATA);
+		for (host->io_pos = 4; host->io_pos; --host->io_pos) {
+			buf[off++] = host->io_word[0] & 0xff;
+			host->io_word[0] >>= 8;
+			length--;
+			if (!length)
+				break;
+		}
+	}
+
+	return off;
+}
+
+static unsigned int jmb38x_ms_read_reg_data(struct jmb38x_ms_host *host,
+					    unsigned char *buf,
+					    unsigned int length)
+{
+	unsigned int off = 0;
+
+	while (host->io_pos > 4 && length) {
+		buf[off++] = host->io_word[0] & 0xff;
+		host->io_word[0] >>= 8;
+		length--;
+		host->io_pos--;
+	}
+
+	if (!length)
+		return off;
+
+	while (host->io_pos && length) {
+		buf[off++] = host->io_word[1] & 0xff;
+		host->io_word[1] >>= 8;
+		length--;
+		host->io_pos--;
+	}
+
+	return off;
+}
+
+static unsigned int jmb38x_ms_write_data(struct jmb38x_ms_host *host,
+					 unsigned char *buf,
+					 unsigned int length)
+{
+	unsigned int off = 0;
+
+	if (host->io_pos) {
+		while (host->io_pos < 4 && length) {
+			host->io_word[0] |=  buf[off++] << (host->io_pos * 8);
+			host->io_pos++;
+			length--;
+		}
+	}
+
+	if (host->io_pos == 4
+	    && !(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
+		writel(host->io_word[0], host->addr + DATA);
+		host->io_pos = 0;
+		host->io_word[0] = 0;
+	} else if (host->io_pos) {
+		return off;
+	}
+
+	if (!length)
+		return off;
+
+	while (!(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
+		if (length < 4)
+			break;
+
+		__raw_writel(*(unsigned int *)(buf + off),
+			     host->addr + DATA);
+		length -= 4;
+		off += 4;
+	}
+
+	switch (length) {
+	case 3:
+		host->io_word[0] |= buf[off + 2] << 16;
+		host->io_pos++;
+	case 2:
+		host->io_word[0] |= buf[off + 1] << 8;
+		host->io_pos++;
+	case 1:
+		host->io_word[0] |= buf[off];
+		host->io_pos++;
+	}
+
+	off += host->io_pos;
+
+	return off;
+}
+
+static unsigned int jmb38x_ms_write_reg_data(struct jmb38x_ms_host *host,
+					     unsigned char *buf,
+					     unsigned int length)
+{
+	unsigned int off = 0;
+
+	while (host->io_pos < 4 && length) {
+		host->io_word[0] &= ~(0xff << (host->io_pos * 8));
+		host->io_word[0] |=  buf[off++] << (host->io_pos * 8);
+		host->io_pos++;
+		length--;
+	}
+
+	if (!length)
+		return off;
+
+	while (host->io_pos < 8 && length) {
+		host->io_word[1] &= ~(0xff << (host->io_pos * 8));
+		host->io_word[1] |=  buf[off++] << (host->io_pos * 8);
+		host->io_pos++;
+		length--;
+	}
+
+	return off;
+}
+
+static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host)
+{
+	unsigned int length;
+	unsigned int off;
+	unsigned int t_size, p_off, p_cnt;
+	unsigned char *buf;
+	struct page *pg;
+	unsigned long flags = 0;
+
+	if (host->req->long_data) {
+		length = host->req->sg.length - host->block_pos;
+		off = host->req->sg.offset + host->block_pos;
+	} else {
+		length = host->req->data_len - host->block_pos;
+		off = 0;
+	}
+
+	while (length) {
+		if (host->req->long_data) {
+			pg = nth_page(sg_page(&host->req->sg),
+				      off >> PAGE_SHIFT);
+			p_off = offset_in_page(off);
+			p_cnt = PAGE_SIZE - p_off;
+			p_cnt = min(p_cnt, length);
+
+			local_irq_save(flags);
+			buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
+		} else {
+			buf = host->req->data + host->block_pos;
+			p_cnt = host->req->data_len - host->block_pos;
+		}
+
+		if (host->req->data_dir == WRITE)
+			t_size = !(host->cmd_flags & REG_DATA)
+				 ? jmb38x_ms_write_data(host, buf, p_cnt)
+				 : jmb38x_ms_write_reg_data(host, buf, p_cnt);
+		else
+			t_size = !(host->cmd_flags & REG_DATA)
+				 ? jmb38x_ms_read_data(host, buf, p_cnt)
+				 : jmb38x_ms_read_reg_data(host, buf, p_cnt);
+
+		if (host->req->long_data) {
+			kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
+			local_irq_restore(flags);
+		}
+
+		if (!t_size)
+			break;
+		host->block_pos += t_size;
+		length -= t_size;
+		off += t_size;
+	}
+
+	if (!length && host->req->data_dir == WRITE) {
+		if (host->cmd_flags & REG_DATA) {
+			writel(host->io_word[0], host->addr + TPC_P0);
+			writel(host->io_word[1], host->addr + TPC_P1);
+		} else if (host->io_pos) {
+			writel(host->io_word[0], host->addr + DATA);
+		}
+	}
+
+	return length;
+}
+
+static int jmb38x_ms_issue_cmd(struct memstick_host *msh)
+{
+	struct jmb38x_ms_host *host = memstick_priv(msh);
+	unsigned char *data;
+	unsigned int data_len, cmd, t_val;
+
+	if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) {
+		dev_dbg(msh->cdev.dev, "no media status\n");
+		host->req->error = -ETIME;
+		return host->req->error;
+	}
+
+	dev_dbg(msh->cdev.dev, "control %08x\n",
+		readl(host->addr + HOST_CONTROL));
+	dev_dbg(msh->cdev.dev, "status %08x\n", readl(host->addr + INT_STATUS));
+	dev_dbg(msh->cdev.dev, "hstatus %08x\n", readl(host->addr + STATUS));
+
+	host->cmd_flags = 0;
+	host->block_pos = 0;
+	host->io_pos = 0;
+	host->io_word[0] = 0;
+	host->io_word[1] = 0;
+
+	cmd = host->req->tpc << 16;
+	cmd |= TPC_DATA_SEL;
+
+	if (host->req->data_dir == READ)
+		cmd |= TPC_DIR;
+	if (host->req->need_card_int)
+		cmd |= TPC_WAIT_INT;
+	if (host->req->get_int_reg)
+		cmd |= TPC_GET_INT;
+
+	data = host->req->data;
+
+	host->use_dma = !no_dma;
+
+	if (host->req->long_data) {
+		data_len = host->req->sg.length;
+	} else {
+		data_len = host->req->data_len;
+		host->use_dma = 0;
+	}
+
+	if (data_len <= 8) {
+		cmd &= ~(TPC_DATA_SEL | 0xf);
+		host->cmd_flags |= REG_DATA;
+		cmd |= data_len & 0xf;
+		host->use_dma = 0;
+	}
+
+	if (host->use_dma) {
+		if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1,
+				    host->req->data_dir == READ
+				    ? PCI_DMA_FROMDEVICE
+				    : PCI_DMA_TODEVICE)) {
+			host->req->error = -ENOMEM;
+			return host->req->error;
+		}
+		data_len = sg_dma_len(&host->req->sg);
+		writel(sg_dma_address(&host->req->sg),
+		       host->addr + DMA_ADDRESS);
+		writel(((1 << 16) & BLOCK_COUNT_MASK)
+		       | (data_len & BLOCK_SIZE_MASK),
+		       host->addr + BLOCK);
+		writel(DMA_CONTROL_ENABLE, host->addr + DMA_CONTROL);
+	} else if (!(host->cmd_flags & REG_DATA)) {
+		writel(((1 << 16) & BLOCK_COUNT_MASK)
+		       | (data_len & BLOCK_SIZE_MASK),
+		       host->addr + BLOCK);
+			t_val = readl(host->addr + INT_STATUS_ENABLE);
+			t_val |= host->req->data_dir == READ
+				 ? INT_STATUS_FIFO_RRDY
+				 : INT_STATUS_FIFO_WRDY;
+
+			writel(t_val, host->addr + INT_STATUS_ENABLE);
+			writel(t_val, host->addr + INT_SIGNAL_ENABLE);
+	} else {
+		cmd &= ~(TPC_DATA_SEL | 0xf);
+		host->cmd_flags |= REG_DATA;
+		cmd |= data_len & 0xf;
+
+		if (host->req->data_dir == WRITE) {
+			jmb38x_ms_transfer_data(host);
+			writel(host->io_word[0], host->addr + TPC_P0);
+			writel(host->io_word[1], host->addr + TPC_P1);
+		}
+	}
+
+	mod_timer(&host->timer, jiffies + host->timeout_jiffies);
+	writel(HOST_CONTROL_LED | readl(host->addr + HOST_CONTROL),
+	       host->addr + HOST_CONTROL);
+	host->req->error = 0;
+
+	writel(cmd, host->addr + TPC);
+	dev_dbg(msh->cdev.dev, "executing TPC %08x, len %x\n", cmd, data_len);
+
+	return 0;
+}
+
+static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last)
+{
+	struct jmb38x_ms_host *host = memstick_priv(msh);
+	unsigned int t_val = 0;
+	int rc;
+
+	del_timer(&host->timer);
+
+	dev_dbg(msh->cdev.dev, "c control %08x\n",
+		readl(host->addr + HOST_CONTROL));
+	dev_dbg(msh->cdev.dev, "c status %08x\n",
+		readl(host->addr + INT_STATUS));
+	dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS));
+
+	if (host->req->get_int_reg) {
+		t_val = readl(host->addr + TPC_P0);
+		host->req->int_reg = (t_val & 0xff);
+	}
+
+	if (host->use_dma) {
+		writel(0, host->addr + DMA_CONTROL);
+		pci_unmap_sg(host->chip->pdev, &host->req->sg, 1,
+			     host->req->data_dir == READ
+			     ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+	} else {
+		t_val = readl(host->addr + INT_STATUS_ENABLE);
+		if (host->req->data_dir == READ)
+			t_val &= ~INT_STATUS_FIFO_RRDY;
+		else
+			t_val &= ~INT_STATUS_FIFO_WRDY;
+
+		writel(t_val, host->addr + INT_STATUS_ENABLE);
+		writel(t_val, host->addr + INT_SIGNAL_ENABLE);
+	}
+
+	writel((~HOST_CONTROL_LED) & readl(host->addr + HOST_CONTROL),
+	       host->addr + HOST_CONTROL);
+
+	if (!last) {
+		do {
+			rc = memstick_next_req(msh, &host->req);
+		} while (!rc && jmb38x_ms_issue_cmd(msh));
+	} else {
+		do {
+			rc = memstick_next_req(msh, &host->req);
+			if (!rc)
+				host->req->error = -ETIME;
+		} while (!rc);
+	}
+}
+
+static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id)
+{
+	struct memstick_host *msh = dev_id;
+	struct jmb38x_ms_host *host = memstick_priv(msh);
+	unsigned int irq_status;
+
+	spin_lock(&host->lock);
+	irq_status = readl(host->addr + INT_STATUS);
+	dev_dbg(&host->chip->pdev->dev, "irq_status = %08x\n", irq_status);
+	if (irq_status == 0 || irq_status == (~0)) {
+		spin_unlock(&host->lock);
+		return IRQ_NONE;
+	}
+
+	if (host->req) {
+		if (irq_status & INT_STATUS_ANY_ERR) {
+			if (irq_status & INT_STATUS_CRC_ERR)
+				host->req->error = -EILSEQ;
+			else
+				host->req->error = -ETIME;
+		} else {
+			if (host->use_dma) {
+				if (irq_status & INT_STATUS_EOTRAN)
+					host->cmd_flags |= FIFO_READY;
+			} else {
+				if (irq_status & (INT_STATUS_FIFO_RRDY
+						  | INT_STATUS_FIFO_WRDY))
+					jmb38x_ms_transfer_data(host);
+
+				if (irq_status & INT_STATUS_EOTRAN) {
+					jmb38x_ms_transfer_data(host);
+					host->cmd_flags |= FIFO_READY;
+				}
+			}
+
+			if (irq_status & INT_STATUS_EOTPC) {
+				host->cmd_flags |= CMD_READY;
+				if (host->cmd_flags & REG_DATA) {
+					if (host->req->data_dir == READ) {
+						host->io_word[0]
+							= readl(host->addr
+								+ TPC_P0);
+						host->io_word[1]
+							= readl(host->addr
+								+ TPC_P1);
+						host->io_pos = 8;
+
+						jmb38x_ms_transfer_data(host);
+					}
+					host->cmd_flags |= FIFO_READY;
+				}
+			}
+		}
+	}
+
+	if (irq_status & (INT_STATUS_MEDIA_IN | INT_STATUS_MEDIA_OUT)) {
+		dev_dbg(&host->chip->pdev->dev, "media changed\n");
+		memstick_detect_change(msh);
+	}
+
+	writel(irq_status, host->addr + INT_STATUS);
+
+	if (host->req
+	    && (((host->cmd_flags & CMD_READY)
+		 && (host->cmd_flags & FIFO_READY))
+		|| host->req->error))
+		jmb38x_ms_complete_cmd(msh, 0);
+
+	spin_unlock(&host->lock);
+	return IRQ_HANDLED;
+}
+
+static void jmb38x_ms_abort(unsigned long data)
+{
+	struct memstick_host *msh = (struct memstick_host *)data;
+	struct jmb38x_ms_host *host = memstick_priv(msh);
+	unsigned long flags;
+
+	dev_dbg(&host->chip->pdev->dev, "abort\n");
+	spin_lock_irqsave(&host->lock, flags);
+	if (host->req) {
+		host->req->error = -ETIME;
+		jmb38x_ms_complete_cmd(msh, 0);
+	}
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void jmb38x_ms_request(struct memstick_host *msh)
+{
+	struct jmb38x_ms_host *host = memstick_priv(msh);
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&host->lock, flags);
+	if (host->req) {
+		spin_unlock_irqrestore(&host->lock, flags);
+		BUG();
+		return;
+	}
+
+	do {
+		rc = memstick_next_req(msh, &host->req);
+	} while (!rc && jmb38x_ms_issue_cmd(msh));
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void jmb38x_ms_reset(struct jmb38x_ms_host *host)
+{
+	unsigned int host_ctl = readl(host->addr + HOST_CONTROL);
+
+	writel(host_ctl | HOST_CONTROL_RESET_REQ | HOST_CONTROL_RESET,
+	       host->addr + HOST_CONTROL);
+
+	while (HOST_CONTROL_RESET_REQ
+	       & (host_ctl = readl(host->addr + HOST_CONTROL))) {
+		ndelay(100);
+		dev_dbg(&host->chip->pdev->dev, "reset\n");
+	}
+
+	writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE);
+	writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE);
+
+	dev_dbg(&host->chip->pdev->dev, "reset\n");
+}
+
+static void jmb38x_ms_set_param(struct memstick_host *msh,
+				enum memstick_param param,
+				int value)
+{
+	struct jmb38x_ms_host *host = memstick_priv(msh);
+	unsigned int host_ctl;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	switch (param) {
+	case MEMSTICK_POWER:
+		if (value == MEMSTICK_POWER_ON) {
+			jmb38x_ms_reset(host);
+
+			writel(host->id ? PAD_PU_PD_ON_MS_SOCK1
+					  : PAD_PU_PD_ON_MS_SOCK0,
+			       host->addr + PAD_PU_PD);
+
+			writel(PAD_OUTPUT_ENABLE_MS,
+			       host->addr + PAD_OUTPUT_ENABLE);
+
+			host_ctl = readl(host->addr + HOST_CONTROL);
+			host_ctl |= 7;
+			writel(host_ctl | (HOST_CONTROL_POWER_EN
+					   | HOST_CONTROL_CLOCK_EN),
+			       host->addr + HOST_CONTROL);
+
+			dev_dbg(&host->chip->pdev->dev, "power on\n");
+		} else if (value == MEMSTICK_POWER_OFF) {
+			writel(readl(host->addr + HOST_CONTROL)
+			       & ~(HOST_CONTROL_POWER_EN
+				   | HOST_CONTROL_CLOCK_EN),
+			       host->addr +  HOST_CONTROL);
+			writel(0, host->addr + PAD_OUTPUT_ENABLE);
+			writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD);
+			dev_dbg(&host->chip->pdev->dev, "power off\n");
+		}
+		break;
+	case MEMSTICK_INTERFACE:
+		/* jmb38x_ms_reset(host); */
+
+		host_ctl = readl(host->addr + HOST_CONTROL);
+		host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT);
+		/* host_ctl |= 7; */
+
+		if (value == MEMSTICK_SERIAL) {
+			host_ctl &= ~HOST_CONTROL_FAST_CLK;
+			host_ctl |= HOST_CONTROL_IF_SERIAL
+				    << HOST_CONTROL_IF_SHIFT;
+			host_ctl |= HOST_CONTROL_REI;
+			writel(0, host->addr + CLOCK_DELAY);
+		} else if (value == MEMSTICK_PAR4) {
+			host_ctl |= HOST_CONTROL_FAST_CLK;
+			host_ctl |= HOST_CONTROL_IF_PAR4
+				    << HOST_CONTROL_IF_SHIFT;
+			host_ctl &= ~HOST_CONTROL_REI;
+			writel(4, host->addr + CLOCK_DELAY);
+		} else if (value == MEMSTICK_PAR8) {
+			host_ctl |= HOST_CONTROL_FAST_CLK;
+			host_ctl |= HOST_CONTROL_IF_PAR8
+				    << HOST_CONTROL_IF_SHIFT;
+			host_ctl &= ~HOST_CONTROL_REI;
+			writel(4, host->addr + CLOCK_DELAY);
+		}
+		writel(host_ctl, host->addr + HOST_CONTROL);
+		break;
+	};
+
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+#ifdef CONFIG_PM
+
+static int jmb38x_ms_suspend(struct pci_dev *dev, pm_message_t state)
+{
+	struct jmb38x_ms *jm = pci_get_drvdata(dev);
+	int cnt;
+
+	for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
+		if (!jm->hosts[cnt])
+			break;
+		memstick_suspend_host(jm->hosts[cnt]);
+	}
+
+	pci_save_state(dev);
+	pci_enable_wake(dev, pci_choose_state(dev, state), 0);
+	pci_disable_device(dev);
+	pci_set_power_state(dev, pci_choose_state(dev, state));
+	return 0;
+}
+
+static int jmb38x_ms_resume(struct pci_dev *dev)
+{
+	struct jmb38x_ms *jm = pci_get_drvdata(dev);
+	int rc;
+
+	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
+	rc = pci_enable_device(dev);
+	if (rc)
+		return rc;
+	pci_set_master(dev);
+
+	pci_read_config_dword(dev, 0xac, &rc);
+	pci_write_config_dword(dev, 0xac, rc | 0x00470000);
+
+	for (rc = 0; rc < jm->host_cnt; ++rc) {
+		if (!jm->hosts[rc])
+			break;
+		memstick_resume_host(jm->hosts[rc]);
+		memstick_detect_change(jm->hosts[rc]);
+	}
+
+	return 0;
+}
+
+#else
+
+#define jmb38x_ms_suspend NULL
+#define jmb38x_ms_resume NULL
+
+#endif /* CONFIG_PM */
+
+static int jmb38x_ms_count_slots(struct pci_dev *pdev)
+{
+	int cnt, rc = 0;
+
+	for (cnt = 0; cnt < PCI_ROM_RESOURCE; ++cnt) {
+		if (!(IORESOURCE_MEM & pci_resource_flags(pdev, cnt)))
+			break;
+
+		if (256 != pci_resource_len(pdev, cnt))
+			break;
+
+		++rc;
+	}
+	return rc;
+}
+
+static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt)
+{
+	struct memstick_host *msh;
+	struct jmb38x_ms_host *host;
+
+	msh = memstick_alloc_host(sizeof(struct jmb38x_ms_host),
+				  &jm->pdev->dev);
+	if (!msh)
+		return NULL;
+
+	host = memstick_priv(msh);
+	host->chip = jm;
+	host->addr = ioremap(pci_resource_start(jm->pdev, cnt),
+			     pci_resource_len(jm->pdev, cnt));
+	if (!host->addr)
+		goto err_out_free;
+
+	spin_lock_init(&host->lock);
+	host->id = cnt;
+	snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d",
+		 host->id);
+	host->irq = jm->pdev->irq;
+	host->timeout_jiffies = msecs_to_jiffies(4000);
+	msh->request = jmb38x_ms_request;
+	msh->set_param = jmb38x_ms_set_param;
+	/*
+	msh->caps = MEMSTICK_CAP_AUTO_GET_INT | MEMSTICK_CAP_PAR4
+		    | MEMSTICK_CAP_PAR8;
+	*/
+	msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8;
+
+	setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh);
+
+	if (!request_irq(host->irq, jmb38x_ms_isr, IRQF_SHARED, host->host_id,
+			 msh))
+		return msh;
+
+	iounmap(host->addr);
+err_out_free:
+	kfree(msh);
+	return NULL;
+}
+
+static void jmb38x_ms_free_host(struct memstick_host *msh)
+{
+	struct jmb38x_ms_host *host = memstick_priv(msh);
+
+	free_irq(host->irq, msh);
+	iounmap(host->addr);
+	memstick_free_host(msh);
+}
+
+static int jmb38x_ms_probe(struct pci_dev *pdev,
+			   const struct pci_device_id *dev_id)
+{
+	struct jmb38x_ms *jm;
+	int pci_dev_busy = 0;
+	int rc, cnt;
+
+	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	if (rc)
+		return rc;
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	pci_set_master(pdev);
+
+	rc = pci_request_regions(pdev, DRIVER_NAME);
+	if (rc) {
+		pci_dev_busy = 1;
+		goto err_out;
+	}
+
+	pci_read_config_dword(pdev, 0xac, &rc);
+	pci_write_config_dword(pdev, 0xac, rc | 0x00470000);
+
+	cnt = jmb38x_ms_count_slots(pdev);
+	if (!cnt) {
+		rc = -ENODEV;
+		pci_dev_busy = 1;
+		goto err_out;
+	}
+
+	jm = kzalloc(sizeof(struct jmb38x_ms)
+		     + cnt * sizeof(struct memstick_host *), GFP_KERNEL);
+	if (!jm) {
+		rc = -ENOMEM;
+		goto err_out_int;
+	}
+
+	jm->pdev = pdev;
+	jm->host_cnt = cnt;
+	pci_set_drvdata(pdev, jm);
+
+	for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
+		jm->hosts[cnt] = jmb38x_ms_alloc_host(jm, cnt);
+		if (!jm->hosts[cnt])
+			break;
+
+		rc = memstick_add_host(jm->hosts[cnt]);
+
+		if (rc) {
+			jmb38x_ms_free_host(jm->hosts[cnt]);
+			jm->hosts[cnt] = NULL;
+			break;
+		}
+	}
+
+	if (cnt)
+		return 0;
+
+	rc = -ENODEV;
+
+	pci_set_drvdata(pdev, NULL);
+	kfree(jm);
+err_out_int:
+	pci_release_regions(pdev);
+err_out:
+	if (!pci_dev_busy)
+		pci_disable_device(pdev);
+	return rc;
+}
+
+static void jmb38x_ms_remove(struct pci_dev *dev)
+{
+	struct jmb38x_ms *jm = pci_get_drvdata(dev);
+	struct jmb38x_ms_host *host;
+	int cnt;
+	unsigned long flags;
+
+	for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
+		if (!jm->hosts[cnt])
+			break;
+
+		host = memstick_priv(jm->hosts[cnt]);
+
+		writel(0, host->addr + INT_SIGNAL_ENABLE);
+		writel(0, host->addr + INT_STATUS_ENABLE);
+		mmiowb();
+		dev_dbg(&jm->pdev->dev, "interrupts off\n");
+		spin_lock_irqsave(&host->lock, flags);
+		if (host->req) {
+			host->req->error = -ETIME;
+			jmb38x_ms_complete_cmd(jm->hosts[cnt], 1);
+		}
+		spin_unlock_irqrestore(&host->lock, flags);
+
+		memstick_remove_host(jm->hosts[cnt]);
+		dev_dbg(&jm->pdev->dev, "host removed\n");
+
+		jmb38x_ms_free_host(jm->hosts[cnt]);
+	}
+
+	pci_set_drvdata(dev, NULL);
+	pci_release_regions(dev);
+	pci_disable_device(dev);
+	kfree(jm);
+}
+
+static struct pci_device_id jmb38x_ms_id_tbl [] = {
+	{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS, PCI_ANY_ID,
+	  PCI_ANY_ID, 0, 0, 0 },
+	{ }
+};
+
+static struct pci_driver jmb38x_ms_driver = {
+	.name = DRIVER_NAME,
+	.id_table = jmb38x_ms_id_tbl,
+	.probe = jmb38x_ms_probe,
+	.remove = jmb38x_ms_remove,
+	.suspend = jmb38x_ms_suspend,
+	.resume = jmb38x_ms_resume
+};
+
+static int __init jmb38x_ms_init(void)
+{
+	return pci_register_driver(&jmb38x_ms_driver);
+}
+
+static void __exit jmb38x_ms_exit(void)
+{
+	pci_unregister_driver(&jmb38x_ms_driver);
+}
+
+MODULE_AUTHOR("Alex Dubov");
+MODULE_DESCRIPTION("JMicron jmb38x MemoryStick driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, jmb38x_ms_id_tbl);
+
+module_init(jmb38x_ms_init);
+module_exit(jmb38x_ms_exit);

+ 279 - 290
drivers/memstick/host/tifm_ms.c

@@ -20,293 +20,315 @@
 #include <asm/io.h>
 #include <asm/io.h>
 
 
 #define DRIVER_NAME "tifm_ms"
 #define DRIVER_NAME "tifm_ms"
-#define DRIVER_VERSION "0.1"
 
 
 static int no_dma;
 static int no_dma;
 module_param(no_dma, bool, 0644);
 module_param(no_dma, bool, 0644);
 
 
-#define TIFM_MS_TIMEOUT      0x00100
-#define TIFM_MS_BADCRC       0x00200
-#define TIFM_MS_EOTPC        0x01000
-#define TIFM_MS_INT          0x02000
-
-/* The meaning of the bit majority in this constant is unknown. */
-#define TIFM_MS_SERIAL       0x04010
+/*
+ * Some control bits of TIFM appear to conform to Sony's reference design,
+ * so I'm just assuming they all are.
+ */
 
 
-#define TIFM_MS_SYS_LATCH    0x00100
-#define TIFM_MS_SYS_NOT_RDY  0x00800
-#define TIFM_MS_SYS_DATA     0x10000
+#define TIFM_MS_STAT_DRQ     0x04000
+#define TIFM_MS_STAT_MSINT   0x02000
+#define TIFM_MS_STAT_RDY     0x01000
+#define TIFM_MS_STAT_CRC     0x00200
+#define TIFM_MS_STAT_TOE     0x00100
+#define TIFM_MS_STAT_EMP     0x00020
+#define TIFM_MS_STAT_FUL     0x00010
+#define TIFM_MS_STAT_CED     0x00008
+#define TIFM_MS_STAT_ERR     0x00004
+#define TIFM_MS_STAT_BRQ     0x00002
+#define TIFM_MS_STAT_CNK     0x00001
+
+#define TIFM_MS_SYS_DMA      0x10000
+#define TIFM_MS_SYS_RESET    0x08000
+#define TIFM_MS_SYS_SRAC     0x04000
+#define TIFM_MS_SYS_INTEN    0x02000
+#define TIFM_MS_SYS_NOCRC    0x01000
+#define TIFM_MS_SYS_INTCLR   0x00800
+#define TIFM_MS_SYS_MSIEN    0x00400
+#define TIFM_MS_SYS_FCLR     0x00200
+#define TIFM_MS_SYS_FDIR     0x00100
+#define TIFM_MS_SYS_DAM      0x00080
+#define TIFM_MS_SYS_DRM      0x00040
+#define TIFM_MS_SYS_DRQSL    0x00020
+#define TIFM_MS_SYS_REI      0x00010
+#define TIFM_MS_SYS_REO      0x00008
+#define TIFM_MS_SYS_BSY_MASK 0x00007
+
+#define TIFM_MS_SYS_FIFO     (TIFM_MS_SYS_INTEN | TIFM_MS_SYS_MSIEN \
+			      | TIFM_MS_SYS_FCLR | TIFM_MS_SYS_BSY_MASK)
 
 
 /* Hardware flags */
 /* Hardware flags */
 enum {
 enum {
-	CMD_READY  = 0x0001,
-	FIFO_READY = 0x0002,
-	CARD_READY = 0x0004,
-	DATA_CARRY = 0x0008
+	CMD_READY  = 0x01,
+	FIFO_READY = 0x02,
+	CARD_INT   = 0x04
 };
 };
 
 
 struct tifm_ms {
 struct tifm_ms {
 	struct tifm_dev         *dev;
 	struct tifm_dev         *dev;
-	unsigned short          eject:1,
-				no_dma:1;
-	unsigned short          cmd_flags;
+	struct timer_list       timer;
+	struct memstick_request *req;
 	unsigned int            mode_mask;
 	unsigned int            mode_mask;
 	unsigned int            block_pos;
 	unsigned int            block_pos;
 	unsigned long           timeout_jiffies;
 	unsigned long           timeout_jiffies;
-
-	struct timer_list       timer;
-	struct memstick_request *req;
+	unsigned char           eject:1,
+				use_dma:1;
+	unsigned char           cmd_flags;
+	unsigned char           io_pos;
 	unsigned int            io_word;
 	unsigned int            io_word;
 };
 };
 
 
-static void tifm_ms_read_fifo(struct tifm_ms *host, unsigned int fifo_offset,
-			      struct page *pg, unsigned int page_off,
-			      unsigned int length)
+static unsigned int tifm_ms_read_data(struct tifm_ms *host,
+				      unsigned char *buf, unsigned int length)
 {
 {
 	struct tifm_dev *sock = host->dev;
 	struct tifm_dev *sock = host->dev;
-	unsigned int cnt = 0, off = 0;
-	unsigned char *buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + page_off;
+	unsigned int off = 0;
+
+	while (host->io_pos && length) {
+		buf[off++] = host->io_word & 0xff;
+		host->io_word >>= 8;
+		length--;
+		host->io_pos--;
+	}
 
 
-	if (host->cmd_flags & DATA_CARRY) {
-		while ((fifo_offset & 3) && length) {
+	if (!length)
+		return off;
+
+	while (!(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) {
+		if (length < 4)
+			break;
+		*(unsigned int *)(buf + off) = __raw_readl(sock->addr
+							   + SOCK_MS_DATA);
+		length -= 4;
+		off += 4;
+	}
+
+	if (length
+	    && !(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) {
+		host->io_word = readl(sock->addr + SOCK_MS_DATA);
+		for (host->io_pos = 4; host->io_pos; --host->io_pos) {
 			buf[off++] = host->io_word & 0xff;
 			buf[off++] = host->io_word & 0xff;
 			host->io_word >>= 8;
 			host->io_word >>= 8;
 			length--;
 			length--;
-			fifo_offset++;
+			if (!length)
+				break;
 		}
 		}
-		if (!(fifo_offset & 3))
-			host->cmd_flags &= ~DATA_CARRY;
-		if (!length)
-			return;
 	}
 	}
 
 
-	do {
-		host->io_word = readl(sock->addr + SOCK_FIFO_ACCESS
-				      + fifo_offset);
-		cnt = 4;
-		while (length && cnt) {
-			buf[off++] = (host->io_word >> 8) & 0xff;
-			cnt--;
-			length--;
-		}
-		fifo_offset += 4 - cnt;
-	} while (length);
-
-	if (cnt)
-		host->cmd_flags |= DATA_CARRY;
-
-	kunmap_atomic(buf - page_off, KM_BIO_DST_IRQ);
+	return off;
 }
 }
 
 
-static void tifm_ms_write_fifo(struct tifm_ms *host, unsigned int fifo_offset,
-			       struct page *pg, unsigned int page_off,
-			       unsigned int length)
+static unsigned int tifm_ms_write_data(struct tifm_ms *host,
+				       unsigned char *buf, unsigned int length)
 {
 {
 	struct tifm_dev *sock = host->dev;
 	struct tifm_dev *sock = host->dev;
-	unsigned int cnt = 0, off = 0;
-	unsigned char *buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + page_off;
+	unsigned int off = 0;
 
 
-	if (host->cmd_flags & DATA_CARRY) {
-		while (fifo_offset & 3) {
-			host->io_word |= buf[off++] << (8 * (fifo_offset & 3));
+	if (host->io_pos) {
+		while (host->io_pos < 4 && length) {
+			host->io_word |=  buf[off++] << (host->io_pos * 8);
+			host->io_pos++;
 			length--;
 			length--;
-			fifo_offset++;
 		}
 		}
-		if (!(fifo_offset & 3)) {
-			writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS
-			       + fifo_offset - 4);
-
-			host->cmd_flags &= ~DATA_CARRY;
-		}
-		if (!length)
-			return;
 	}
 	}
 
 
-	do {
-		cnt = 4;
+	if (host->io_pos == 4
+	    && !(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) {
+		writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM),
+		       sock->addr + SOCK_MS_SYSTEM);
+		writel(host->io_word, sock->addr + SOCK_MS_DATA);
+		host->io_pos = 0;
 		host->io_word = 0;
 		host->io_word = 0;
-		while (length && cnt) {
-			host->io_word |= buf[off++] << (4 - cnt);
-			cnt--;
-			length--;
-		}
-		fifo_offset += 4 - cnt;
-		if (!cnt)
-			writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS
-					      + fifo_offset - 4);
-
-	} while (length);
-
-	if (cnt)
-		host->cmd_flags |= DATA_CARRY;
+	} else if (host->io_pos) {
+		return off;
+	}
 
 
-	kunmap_atomic(buf - page_off, KM_BIO_SRC_IRQ);
-}
+	if (!length)
+		return off;
 
 
-static void tifm_ms_move_block(struct tifm_ms *host, unsigned int length)
-{
-	unsigned int t_size;
-	unsigned int off = host->req->sg.offset + host->block_pos;
-	unsigned int p_off, p_cnt;
-	struct page *pg;
-	unsigned long flags;
+	while (!(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) {
+		if (length < 4)
+			break;
+		writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM),
+		       sock->addr + SOCK_MS_SYSTEM);
+		__raw_writel(*(unsigned int *)(buf + off),
+			     sock->addr + SOCK_MS_DATA);
+		length -= 4;
+		off += 4;
+	}
 
 
-	dev_dbg(&host->dev->dev, "moving block\n");
-	local_irq_save(flags);
-	t_size = length;
-	while (t_size) {
-		pg = nth_page(sg_page(&host->req->sg), off >> PAGE_SHIFT);
-		p_off = offset_in_page(off);
-		p_cnt = PAGE_SIZE - p_off;
-		p_cnt = min(p_cnt, t_size);
+	switch (length) {
+	case 3:
+		host->io_word |= buf[off + 2] << 16;
+		host->io_pos++;
+	case 2:
+		host->io_word |= buf[off + 1] << 8;
+		host->io_pos++;
+	case 1:
+		host->io_word |= buf[off];
+		host->io_pos++;
+	}
 
 
-		if (host->req->data_dir == WRITE)
-			tifm_ms_write_fifo(host, length - t_size,
-					   pg, p_off, p_cnt);
-		else
-			tifm_ms_read_fifo(host, length - t_size,
-					  pg, p_off, p_cnt);
+	off += host->io_pos;
 
 
-		t_size -= p_cnt;
-	}
-	local_irq_restore(flags);
+	return off;
 }
 }
 
 
-static int tifm_ms_transfer_data(struct tifm_ms *host, int skip)
+static unsigned int tifm_ms_transfer_data(struct tifm_ms *host)
 {
 {
 	struct tifm_dev *sock = host->dev;
 	struct tifm_dev *sock = host->dev;
-	unsigned int length = host->req->sg.length - host->block_pos;
+	unsigned int length;
+	unsigned int off;
+	unsigned int t_size, p_off, p_cnt;
+	unsigned char *buf;
+	struct page *pg;
+	unsigned long flags = 0;
+
+	if (host->req->long_data) {
+		length = host->req->sg.length - host->block_pos;
+		off = host->req->sg.offset + host->block_pos;
+	} else {
+		length = host->req->data_len - host->block_pos;
+		off = 0;
+	}
+	dev_dbg(&sock->dev, "fifo data transfer, %d, %d\n", length,
+		host->block_pos);
+
+	while (length) {
+		if (host->req->long_data) {
+			pg = nth_page(sg_page(&host->req->sg),
+				      off >> PAGE_SHIFT);
+			p_off = offset_in_page(off);
+			p_cnt = PAGE_SIZE - p_off;
+			p_cnt = min(p_cnt, length);
+
+			local_irq_save(flags);
+			buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
+		} else {
+			buf = host->req->data + host->block_pos;
+			p_cnt = host->req->data_len - host->block_pos;
+		}
 
 
-	if (!length)
-		return 1;
+		t_size = host->req->data_dir == WRITE
+			 ? tifm_ms_write_data(host, buf, p_cnt)
+			 : tifm_ms_read_data(host, buf, p_cnt);
 
 
-	if (length > TIFM_FIFO_SIZE)
-		length = TIFM_FIFO_SIZE;
+		if (host->req->long_data) {
+			kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
+			local_irq_restore(flags);
+		}
 
 
-	if (!skip) {
-		tifm_ms_move_block(host, length);
-		host->block_pos += length;
+		if (!t_size)
+			break;
+		host->block_pos += t_size;
+		length -= t_size;
+		off += t_size;
 	}
 	}
 
 
-	if ((host->req->data_dir == READ)
-	    && (host->block_pos == host->req->sg.length))
-		return 1;
-
-	writel(ilog2(length) - 2, sock->addr + SOCK_FIFO_PAGE_SIZE);
-	if (host->req->data_dir == WRITE)
-		writel((1 << 8) | TIFM_DMA_TX, sock->addr + SOCK_DMA_CONTROL);
-	else
-		writel((1 << 8), sock->addr + SOCK_DMA_CONTROL);
+	dev_dbg(&sock->dev, "fifo data transfer, %d remaining\n", length);
+	if (!length && (host->req->data_dir == WRITE)) {
+		if (host->io_pos) {
+			writel(TIFM_MS_SYS_FDIR
+			       | readl(sock->addr + SOCK_MS_SYSTEM),
+			       sock->addr + SOCK_MS_SYSTEM);
+			writel(host->io_word, sock->addr + SOCK_MS_DATA);
+		}
+		writel(TIFM_MS_SYS_FDIR
+		       | readl(sock->addr + SOCK_MS_SYSTEM),
+		       sock->addr + SOCK_MS_SYSTEM);
+		writel(0, sock->addr + SOCK_MS_DATA);
+	} else {
+		readl(sock->addr + SOCK_MS_DATA);
+	}
 
 
-	return 0;
+	return length;
 }
 }
 
 
 static int tifm_ms_issue_cmd(struct tifm_ms *host)
 static int tifm_ms_issue_cmd(struct tifm_ms *host)
 {
 {
 	struct tifm_dev *sock = host->dev;
 	struct tifm_dev *sock = host->dev;
 	unsigned char *data;
 	unsigned char *data;
-	unsigned int data_len = 0, cmd = 0, cmd_mask = 0, cnt, tval = 0;
+	unsigned int data_len, cmd, sys_param;
 
 
+	host->cmd_flags = 0;
+	host->block_pos = 0;
+	host->io_pos = 0;
+	host->io_word = 0;
 	host->cmd_flags = 0;
 	host->cmd_flags = 0;
 
 
-	if (host->req->io_type == MEMSTICK_IO_SG) {
-		if (!host->no_dma) {
-			if (1 != tifm_map_sg(sock, &host->req->sg, 1,
-					     host->req->data_dir == READ
-					     ? PCI_DMA_FROMDEVICE
-					     : PCI_DMA_TODEVICE)) {
-				host->req->error = -ENOMEM;
-				return host->req->error;
-			}
-			data_len = sg_dma_len(&host->req->sg);
-		} else
-			data_len = host->req->sg.length;
-
-		writel(TIFM_FIFO_INT_SETALL,
-		       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-		writel(TIFM_FIFO_ENABLE,
-		       sock->addr + SOCK_FIFO_CONTROL);
-		writel(TIFM_FIFO_INTMASK,
-		       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+	data = host->req->data;
 
 
-		if (!host->no_dma) {
-			writel(ilog2(data_len) - 2,
-			       sock->addr + SOCK_FIFO_PAGE_SIZE);
-			writel(sg_dma_address(&host->req->sg),
-			       sock->addr + SOCK_DMA_ADDRESS);
-			if (host->req->data_dir == WRITE)
-				writel((1 << 8) | TIFM_DMA_TX | TIFM_DMA_EN,
-				       sock->addr + SOCK_DMA_CONTROL);
-			else
-				writel((1 << 8) | TIFM_DMA_EN,
-				       sock->addr + SOCK_DMA_CONTROL);
-		} else {
-			tifm_ms_transfer_data(host,
-					      host->req->data_dir == READ);
-		}
+	host->use_dma = !no_dma;
 
 
-		cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM);
-		cmd_mask |= TIFM_MS_SYS_DATA | TIFM_MS_SYS_NOT_RDY;
-		writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
-	} else if (host->req->io_type == MEMSTICK_IO_VAL) {
-		data = host->req->data;
+	if (host->req->long_data) {
+		data_len = host->req->sg.length;
+		if (!is_power_of_2(data_len))
+			host->use_dma = 0;
+	} else {
 		data_len = host->req->data_len;
 		data_len = host->req->data_len;
+		host->use_dma = 0;
+	}
 
 
-		cmd_mask = host->mode_mask | 0x2607; /* unknown constant */
-
-		if (host->req->data_dir == WRITE) {
-			cmd_mask |= TIFM_MS_SYS_LATCH;
-			writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
-			for (cnt = 0; (data_len - cnt) >= 4; cnt += 4) {
-				writel(TIFM_MS_SYS_LATCH
-				       | readl(sock->addr + SOCK_MS_SYSTEM),
-				       sock->addr + SOCK_MS_SYSTEM);
-				__raw_writel(*(unsigned int *)(data + cnt),
-					     sock->addr + SOCK_MS_DATA);
-				dev_dbg(&sock->dev, "writing %x\n",
-					*(int *)(data + cnt));
-			}
-			switch (data_len - cnt) {
-			case 3:
-				tval |= data[cnt + 2] << 16;
-			case 2:
-				tval |= data[cnt + 1] << 8;
-			case 1:
-				tval |= data[cnt];
-				writel(TIFM_MS_SYS_LATCH
-				       | readl(sock->addr + SOCK_MS_SYSTEM),
-				       sock->addr + SOCK_MS_SYSTEM);
-				writel(tval, sock->addr + SOCK_MS_DATA);
-				dev_dbg(&sock->dev, "writing %x\n", tval);
-			}
+	writel(TIFM_FIFO_INT_SETALL,
+	       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+	writel(TIFM_FIFO_ENABLE,
+	       sock->addr + SOCK_FIFO_CONTROL);
+
+	if (host->use_dma) {
+		if (1 != tifm_map_sg(sock, &host->req->sg, 1,
+				     host->req->data_dir == READ
+				     ? PCI_DMA_FROMDEVICE
+				     : PCI_DMA_TODEVICE)) {
+			host->req->error = -ENOMEM;
+			return host->req->error;
+		}
+		data_len = sg_dma_len(&host->req->sg);
 
 
-			writel(TIFM_MS_SYS_LATCH
-			       | readl(sock->addr + SOCK_MS_SYSTEM),
-			       sock->addr + SOCK_MS_SYSTEM);
-			writel(0, sock->addr + SOCK_MS_DATA);
-			dev_dbg(&sock->dev, "writing %x\n", 0);
+		writel(ilog2(data_len) - 2,
+		       sock->addr + SOCK_FIFO_PAGE_SIZE);
+		writel(TIFM_FIFO_INTMASK,
+		       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+		sys_param = TIFM_DMA_EN | (1 << 8);
+		if (host->req->data_dir == WRITE)
+			sys_param |= TIFM_DMA_TX;
+
+		writel(TIFM_FIFO_INTMASK,
+		       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
 
 
-		} else
-			writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
+		writel(sg_dma_address(&host->req->sg),
+		       sock->addr + SOCK_DMA_ADDRESS);
+		writel(sys_param, sock->addr + SOCK_DMA_CONTROL);
+	} else {
+		writel(host->mode_mask | TIFM_MS_SYS_FIFO,
+		       sock->addr + SOCK_MS_SYSTEM);
 
 
-		cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM);
-		cmd_mask &= ~TIFM_MS_SYS_DATA;
-		cmd_mask |= TIFM_MS_SYS_NOT_RDY;
-		dev_dbg(&sock->dev, "mask %x\n", cmd_mask);
-		writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
-	} else
-		BUG();
+		writel(TIFM_FIFO_MORE,
+		       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+	}
 
 
 	mod_timer(&host->timer, jiffies + host->timeout_jiffies);
 	mod_timer(&host->timer, jiffies + host->timeout_jiffies);
 	writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
 	writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
 	       sock->addr + SOCK_CONTROL);
 	       sock->addr + SOCK_CONTROL);
 	host->req->error = 0;
 	host->req->error = 0;
 
 
+	sys_param = readl(sock->addr + SOCK_MS_SYSTEM);
+	sys_param |= TIFM_MS_SYS_INTCLR;
+
+	if (host->use_dma)
+		sys_param |= TIFM_MS_SYS_DMA;
+	else
+		sys_param &= ~TIFM_MS_SYS_DMA;
+
+	writel(sys_param, sock->addr + SOCK_MS_SYSTEM);
+
 	cmd = (host->req->tpc & 0xf) << 12;
 	cmd = (host->req->tpc & 0xf) << 12;
 	cmd |= data_len;
 	cmd |= data_len;
 	writel(cmd, sock->addr + SOCK_MS_COMMAND);
 	writel(cmd, sock->addr + SOCK_MS_COMMAND);
 
 
-	dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, cmd_mask);
+	dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, sys_param);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -314,47 +336,20 @@ static void tifm_ms_complete_cmd(struct tifm_ms *host)
 {
 {
 	struct tifm_dev *sock = host->dev;
 	struct tifm_dev *sock = host->dev;
 	struct memstick_host *msh = tifm_get_drvdata(sock);
 	struct memstick_host *msh = tifm_get_drvdata(sock);
-	unsigned int tval = 0, data_len;
-	unsigned char *data;
 	int rc;
 	int rc;
 
 
 	del_timer(&host->timer);
 	del_timer(&host->timer);
-	if (host->req->io_type == MEMSTICK_IO_SG) {
-		if (!host->no_dma)
-			tifm_unmap_sg(sock, &host->req->sg, 1,
-				      host->req->data_dir == READ
-				      ? PCI_DMA_FROMDEVICE
-				      : PCI_DMA_TODEVICE);
-	} else if (host->req->io_type == MEMSTICK_IO_VAL) {
-		writel(~TIFM_MS_SYS_DATA & readl(sock->addr + SOCK_MS_SYSTEM),
-		       sock->addr + SOCK_MS_SYSTEM);
-
-		data = host->req->data;
-		data_len = host->req->data_len;
 
 
-		if (host->req->data_dir == READ) {
-			for (rc = 0; (data_len - rc) >= 4; rc += 4)
-				*(int *)(data + rc)
-					= __raw_readl(sock->addr
-						      + SOCK_MS_DATA);
-
-			if (data_len - rc)
-				tval = readl(sock->addr + SOCK_MS_DATA);
-			switch (data_len - rc) {
-			case 3:
-				data[rc + 2] = (tval >> 16) & 0xff;
-			case 2:
-				data[rc + 1] = (tval >> 8) & 0xff;
-			case 1:
-				data[rc] = tval & 0xff;
-			}
-			readl(sock->addr + SOCK_MS_DATA);
-		}
-	}
+	if (host->use_dma)
+		tifm_unmap_sg(sock, &host->req->sg, 1,
+			      host->req->data_dir == READ
+			      ? PCI_DMA_FROMDEVICE
+			      : PCI_DMA_TODEVICE);
 
 
 	writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
 	writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
 	       sock->addr + SOCK_CONTROL);
 	       sock->addr + SOCK_CONTROL);
 
 
+	dev_dbg(&sock->dev, "TPC complete\n");
 	do {
 	do {
 		rc = memstick_next_req(msh, &host->req);
 		rc = memstick_next_req(msh, &host->req);
 	} while (!rc && tifm_ms_issue_cmd(host));
 	} while (!rc && tifm_ms_issue_cmd(host));
@@ -365,11 +360,10 @@ static int tifm_ms_check_status(struct tifm_ms *host)
 	if (!host->req->error) {
 	if (!host->req->error) {
 		if (!(host->cmd_flags & CMD_READY))
 		if (!(host->cmd_flags & CMD_READY))
 			return 1;
 			return 1;
-		if ((host->req->io_type == MEMSTICK_IO_SG)
-		    && !(host->cmd_flags & FIFO_READY))
+		if (!(host->cmd_flags & FIFO_READY))
 			return 1;
 			return 1;
 		if (host->req->need_card_int
 		if (host->req->need_card_int
-		    && !(host->cmd_flags & CARD_READY))
+		    && !(host->cmd_flags & CARD_INT))
 			return 1;
 			return 1;
 	}
 	}
 	return 0;
 	return 0;
@@ -379,18 +373,24 @@ static int tifm_ms_check_status(struct tifm_ms *host)
 static void tifm_ms_data_event(struct tifm_dev *sock)
 static void tifm_ms_data_event(struct tifm_dev *sock)
 {
 {
 	struct tifm_ms *host;
 	struct tifm_ms *host;
-	unsigned int fifo_status = 0;
+	unsigned int fifo_status = 0, host_status = 0;
 	int rc = 1;
 	int rc = 1;
 
 
 	spin_lock(&sock->lock);
 	spin_lock(&sock->lock);
 	host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock));
 	host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock));
 	fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
 	fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
-	dev_dbg(&sock->dev, "data event: fifo_status %x, flags %x\n",
-		fifo_status, host->cmd_flags);
+	host_status = readl(sock->addr + SOCK_MS_STATUS);
+	dev_dbg(&sock->dev,
+		"data event: fifo_status %x, host_status %x, flags %x\n",
+		fifo_status, host_status, host->cmd_flags);
 
 
 	if (host->req) {
 	if (host->req) {
-		if (fifo_status & TIFM_FIFO_READY) {
-			if (!host->no_dma || tifm_ms_transfer_data(host, 0)) {
+		if (host->use_dma && (fifo_status & 1)) {
+			host->cmd_flags |= FIFO_READY;
+			rc = tifm_ms_check_status(host);
+		}
+		if (!host->use_dma && (fifo_status & TIFM_FIFO_MORE)) {
+			if (!tifm_ms_transfer_data(host)) {
 				host->cmd_flags |= FIFO_READY;
 				host->cmd_flags |= FIFO_READY;
 				rc = tifm_ms_check_status(host);
 				rc = tifm_ms_check_status(host);
 			}
 			}
@@ -419,9 +419,9 @@ static void tifm_ms_card_event(struct tifm_dev *sock)
 		host_status, host->cmd_flags);
 		host_status, host->cmd_flags);
 
 
 	if (host->req) {
 	if (host->req) {
-		if (host_status & TIFM_MS_TIMEOUT)
+		if (host_status & TIFM_MS_STAT_TOE)
 			host->req->error = -ETIME;
 			host->req->error = -ETIME;
-		else if (host_status & TIFM_MS_BADCRC)
+		else if (host_status & TIFM_MS_STAT_CRC)
 			host->req->error = -EILSEQ;
 			host->req->error = -EILSEQ;
 
 
 		if (host->req->error) {
 		if (host->req->error) {
@@ -430,18 +430,17 @@ static void tifm_ms_card_event(struct tifm_dev *sock)
 			writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
 			writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
 		}
 		}
 
 
-		if (host_status & TIFM_MS_EOTPC)
+		if (host_status & TIFM_MS_STAT_RDY)
 			host->cmd_flags |= CMD_READY;
 			host->cmd_flags |= CMD_READY;
-		if (host_status & TIFM_MS_INT)
-			host->cmd_flags |= CARD_READY;
+
+		if (host_status & TIFM_MS_STAT_MSINT)
+			host->cmd_flags |= CARD_INT;
 
 
 		rc = tifm_ms_check_status(host);
 		rc = tifm_ms_check_status(host);
 
 
 	}
 	}
 
 
-	writel(TIFM_MS_SYS_NOT_RDY | readl(sock->addr + SOCK_MS_SYSTEM),
-	       sock->addr + SOCK_MS_SYSTEM);
-	writel((~TIFM_MS_SYS_DATA) & readl(sock->addr + SOCK_MS_SYSTEM),
+	writel(TIFM_MS_SYS_INTCLR | readl(sock->addr + SOCK_MS_SYSTEM),
 	       sock->addr + SOCK_MS_SYSTEM);
 	       sock->addr + SOCK_MS_SYSTEM);
 
 
 	if (!rc)
 	if (!rc)
@@ -497,15 +496,26 @@ static void tifm_ms_set_param(struct memstick_host *msh,
 
 
 	switch (param) {
 	switch (param) {
 	case MEMSTICK_POWER:
 	case MEMSTICK_POWER:
-		/* this is set by card detection mechanism */
+		/* also affected by media detection mechanism */
+		if (value == MEMSTICK_POWER_ON) {
+			host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI;
+			writel(TIFM_MS_SYS_RESET, sock->addr + SOCK_MS_SYSTEM);
+			writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR,
+			       sock->addr + SOCK_MS_SYSTEM);
+			writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
+		} else if (value == MEMSTICK_POWER_OFF) {
+			writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR,
+			       sock->addr + SOCK_MS_SYSTEM);
+			writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
+		}
 		break;
 		break;
 	case MEMSTICK_INTERFACE:
 	case MEMSTICK_INTERFACE:
 		if (value == MEMSTICK_SERIAL) {
 		if (value == MEMSTICK_SERIAL) {
-			host->mode_mask = TIFM_MS_SERIAL;
+			host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI;
 			writel((~TIFM_CTRL_FAST_CLK)
 			writel((~TIFM_CTRL_FAST_CLK)
 			       & readl(sock->addr + SOCK_CONTROL),
 			       & readl(sock->addr + SOCK_CONTROL),
 			       sock->addr + SOCK_CONTROL);
 			       sock->addr + SOCK_CONTROL);
-		} else if (value == MEMSTICK_PARALLEL) {
+		} else if (value == MEMSTICK_PAR4) {
 			host->mode_mask = 0;
 			host->mode_mask = 0;
 			writel(TIFM_CTRL_FAST_CLK
 			writel(TIFM_CTRL_FAST_CLK
 			       | readl(sock->addr + SOCK_CONTROL),
 			       | readl(sock->addr + SOCK_CONTROL),
@@ -532,21 +542,6 @@ static void tifm_ms_abort(unsigned long data)
 	tifm_eject(host->dev);
 	tifm_eject(host->dev);
 }
 }
 
 
-static int tifm_ms_initialize_host(struct tifm_ms *host)
-{
-	struct tifm_dev *sock = host->dev;
-	struct memstick_host *msh = tifm_get_drvdata(sock);
-
-	host->mode_mask = TIFM_MS_SERIAL;
-	writel(0x8000, sock->addr + SOCK_MS_SYSTEM);
-	writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM);
-	writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
-	if (tifm_has_ms_pif(sock))
-		msh->caps |= MEMSTICK_CAP_PARALLEL;
-
-	return 0;
-}
-
 static int tifm_ms_probe(struct tifm_dev *sock)
 static int tifm_ms_probe(struct tifm_dev *sock)
 {
 {
 	struct memstick_host *msh;
 	struct memstick_host *msh;
@@ -568,7 +563,6 @@ static int tifm_ms_probe(struct tifm_dev *sock)
 	tifm_set_drvdata(sock, msh);
 	tifm_set_drvdata(sock, msh);
 	host->dev = sock;
 	host->dev = sock;
 	host->timeout_jiffies = msecs_to_jiffies(1000);
 	host->timeout_jiffies = msecs_to_jiffies(1000);
-	host->no_dma = no_dma;
 
 
 	setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host);
 	setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host);
 
 
@@ -576,10 +570,10 @@ static int tifm_ms_probe(struct tifm_dev *sock)
 	msh->set_param = tifm_ms_set_param;
 	msh->set_param = tifm_ms_set_param;
 	sock->card_event = tifm_ms_card_event;
 	sock->card_event = tifm_ms_card_event;
 	sock->data_event = tifm_ms_data_event;
 	sock->data_event = tifm_ms_data_event;
-	rc = tifm_ms_initialize_host(host);
+	if (tifm_has_ms_pif(sock))
+		msh->caps |= MEMSTICK_CAP_PAR4;
 
 
-	if (!rc)
-		rc = memstick_add_host(msh);
+	rc = memstick_add_host(msh);
 	if (!rc)
 	if (!rc)
 		return 0;
 		return 0;
 
 
@@ -601,7 +595,7 @@ static void tifm_ms_remove(struct tifm_dev *sock)
 		writel(TIFM_FIFO_INT_SETALL,
 		writel(TIFM_FIFO_INT_SETALL,
 		       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
 		       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
 		writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
 		writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
-		if ((host->req->io_type == MEMSTICK_IO_SG) && !host->no_dma)
+		if (host->use_dma)
 			tifm_unmap_sg(sock, &host->req->sg, 1,
 			tifm_unmap_sg(sock, &host->req->sg, 1,
 				      host->req->data_dir == READ
 				      host->req->data_dir == READ
 				      ? PCI_DMA_TODEVICE
 				      ? PCI_DMA_TODEVICE
@@ -617,10 +611,6 @@ static void tifm_ms_remove(struct tifm_dev *sock)
 	spin_unlock_irqrestore(&sock->lock, flags);
 	spin_unlock_irqrestore(&sock->lock, flags);
 
 
 	memstick_remove_host(msh);
 	memstick_remove_host(msh);
-
-	writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM);
-	writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
-
 	memstick_free_host(msh);
 	memstick_free_host(msh);
 }
 }
 
 
@@ -628,17 +618,17 @@ static void tifm_ms_remove(struct tifm_dev *sock)
 
 
 static int tifm_ms_suspend(struct tifm_dev *sock, pm_message_t state)
 static int tifm_ms_suspend(struct tifm_dev *sock, pm_message_t state)
 {
 {
+	struct memstick_host *msh = tifm_get_drvdata(sock);
+
+	memstick_suspend_host(msh);
 	return 0;
 	return 0;
 }
 }
 
 
 static int tifm_ms_resume(struct tifm_dev *sock)
 static int tifm_ms_resume(struct tifm_dev *sock)
 {
 {
 	struct memstick_host *msh = tifm_get_drvdata(sock);
 	struct memstick_host *msh = tifm_get_drvdata(sock);
-	struct tifm_ms *host = memstick_priv(msh);
-
-	tifm_ms_initialize_host(host);
-	memstick_detect_change(msh);
 
 
+	memstick_resume_host(msh);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -679,7 +669,6 @@ MODULE_AUTHOR("Alex Dubov");
 MODULE_DESCRIPTION("TI FlashMedia MemoryStick driver");
 MODULE_DESCRIPTION("TI FlashMedia MemoryStick driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(tifm, tifm_ms_id_tbl);
 MODULE_DEVICE_TABLE(tifm, tifm_ms_id_tbl);
-MODULE_VERSION(DRIVER_VERSION);
 
 
 module_init(tifm_ms_init);
 module_init(tifm_ms_init);
 module_exit(tifm_ms_exit);
 module_exit(tifm_ms_exit);

+ 2 - 0
drivers/misc/tifm_7xx1.c

@@ -367,6 +367,8 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
 	if (rc)
 	if (rc)
 		goto err_out_irq;
 		goto err_out_irq;
 
 
+	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
+	       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
 	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
 	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
 	       fm->addr + FM_SET_INTERRUPT_ENABLE);
 	       fm->addr + FM_SET_INTERRUPT_ENABLE);
 	return 0;
 	return 0;

+ 1 - 0
drivers/pci/hotplug/ibmphp_ebda.c

@@ -963,6 +963,7 @@ static int __init ebda_rsrc_controller (void)
 
 
 			bus_info_ptr1 = ibmphp_find_same_bus_num (hpc_ptr->slots[index].slot_bus_num);
 			bus_info_ptr1 = ibmphp_find_same_bus_num (hpc_ptr->slots[index].slot_bus_num);
 			if (!bus_info_ptr1) {
 			if (!bus_info_ptr1) {
+				kfree(tmp_slot);
 				rc = -ENODEV;
 				rc = -ENODEV;
 				goto error;
 				goto error;
 			}
 			}

+ 1 - 1
drivers/serial/of_serial.c

@@ -138,7 +138,7 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = {
 	{ /* end of list */ },
 	{ /* end of list */ },
 };
 };
 
 
-static struct of_platform_driver __devinitdata of_platform_serial_driver = {
+static struct of_platform_driver of_platform_serial_driver = {
 	.owner = THIS_MODULE,
 	.owner = THIS_MODULE,
 	.name = "of_serial",
 	.name = "of_serial",
 	.probe = of_platform_serial_probe,
 	.probe = of_platform_serial_probe,

+ 1 - 1
drivers/usb/gadget/Kconfig

@@ -131,7 +131,7 @@ config USB_ATMEL_USBA
 
 
 config USB_GADGET_FSL_USB2
 config USB_GADGET_FSL_USB2
 	boolean "Freescale Highspeed USB DR Peripheral Controller"
 	boolean "Freescale Highspeed USB DR Peripheral Controller"
-	depends on MPC834x || PPC_MPC831x
+	depends on FSL_SOC
 	select USB_GADGET_DUALSPEED
 	select USB_GADGET_DUALSPEED
 	help
 	help
 	   Some of Freescale PowerPC processors have a High Speed
 	   Some of Freescale PowerPC processors have a High Speed

+ 46 - 16
drivers/usb/host/ehci-hcd.c

@@ -281,23 +281,44 @@ static void ehci_iaa_watchdog(unsigned long param)
 {
 {
 	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
 	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
 	unsigned long		flags;
 	unsigned long		flags;
-	u32			status, cmd;
 
 
 	spin_lock_irqsave (&ehci->lock, flags);
 	spin_lock_irqsave (&ehci->lock, flags);
-	WARN_ON(!ehci->reclaim);
 
 
-	status = ehci_readl(ehci, &ehci->regs->status);
-	cmd = ehci_readl(ehci, &ehci->regs->command);
-	ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd);
-
-	/* lost IAA irqs wedge things badly; seen first with a vt8235 */
-	if (ehci->reclaim) {
-		if (status & STS_IAA) {
-			ehci_vdbg (ehci, "lost IAA\n");
+	/* Lost IAA irqs wedge things badly; seen first with a vt8235.
+	 * So we need this watchdog, but must protect it against both
+	 * (a) SMP races against real IAA firing and retriggering, and
+	 * (b) clean HC shutdown, when IAA watchdog was pending.
+	 */
+	if (ehci->reclaim
+			&& !timer_pending(&ehci->iaa_watchdog)
+			&& HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
+		u32 cmd, status;
+
+		/* If we get here, IAA is *REALLY* late.  It's barely
+		 * conceivable that the system is so busy that CMD_IAAD
+		 * is still legitimately set, so let's be sure it's
+		 * clear before we read STS_IAA.  (The HC should clear
+		 * CMD_IAAD when it sets STS_IAA.)
+		 */
+		cmd = ehci_readl(ehci, &ehci->regs->command);
+		if (cmd & CMD_IAAD)
+			ehci_writel(ehci, cmd & ~CMD_IAAD,
+					&ehci->regs->command);
+
+		/* If IAA is set here it either legitimately triggered
+		 * before we cleared IAAD above (but _way_ late, so we'll
+		 * still count it as lost) ... or a silicon erratum:
+		 * - VIA seems to set IAA without triggering the IRQ;
+		 * - IAAD potentially cleared without setting IAA.
+		 */
+		status = ehci_readl(ehci, &ehci->regs->status);
+		if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
 			COUNT (ehci->stats.lost_iaa);
 			COUNT (ehci->stats.lost_iaa);
 			ehci_writel(ehci, STS_IAA, &ehci->regs->status);
 			ehci_writel(ehci, STS_IAA, &ehci->regs->status);
 		}
 		}
-		ehci_writel(ehci, cmd & ~CMD_IAAD, &ehci->regs->command);
+
+		ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n",
+				status, cmd);
 		end_unlink_async(ehci);
 		end_unlink_async(ehci);
 	}
 	}
 
 
@@ -631,7 +652,7 @@ static int ehci_run (struct usb_hcd *hcd)
 static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 {
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	u32			status, pcd_status = 0;
+	u32			status, pcd_status = 0, cmd;
 	int			bh;
 	int			bh;
 
 
 	spin_lock (&ehci->lock);
 	spin_lock (&ehci->lock);
@@ -652,7 +673,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 
 
 	/* clear (just) interrupts */
 	/* clear (just) interrupts */
 	ehci_writel(ehci, status, &ehci->regs->status);
 	ehci_writel(ehci, status, &ehci->regs->status);
-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted write */
+	cmd = ehci_readl(ehci, &ehci->regs->command);
 	bh = 0;
 	bh = 0;
 
 
 #ifdef	EHCI_VERBOSE_DEBUG
 #ifdef	EHCI_VERBOSE_DEBUG
@@ -673,8 +694,17 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 
 
 	/* complete the unlinking of some qh [4.15.2.3] */
 	/* complete the unlinking of some qh [4.15.2.3] */
 	if (status & STS_IAA) {
 	if (status & STS_IAA) {
-		COUNT (ehci->stats.reclaim);
-		end_unlink_async(ehci);
+		/* guard against (alleged) silicon errata */
+		if (cmd & CMD_IAAD) {
+			ehci_writel(ehci, cmd & ~CMD_IAAD,
+					&ehci->regs->command);
+			ehci_dbg(ehci, "IAA with IAAD still set?\n");
+		}
+		if (ehci->reclaim) {
+			COUNT(ehci->stats.reclaim);
+			end_unlink_async(ehci);
+		} else
+			ehci_dbg(ehci, "IAA with nothing to reclaim?\n");
 	}
 	}
 
 
 	/* remote wakeup [4.3.1] */
 	/* remote wakeup [4.3.1] */
@@ -781,7 +811,7 @@ static int ehci_urb_enqueue (
 static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
 {
 	/* failfast */
 	/* failfast */
-	if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))
+	if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim)
 		end_unlink_async(ehci);
 		end_unlink_async(ehci);
 
 
 	/* if it's not linked then there's nothing to do */
 	/* if it's not linked then there's nothing to do */

+ 2 - 0
drivers/usb/serial/cypress_m8.c

@@ -94,6 +94,7 @@ static struct usb_device_id id_table_earthmate [] = {
 
 
 static struct usb_device_id id_table_cyphidcomrs232 [] = {
 static struct usb_device_id id_table_cyphidcomrs232 [] = {
 	{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
 	{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
+	{ USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
 	{ }						/* Terminating entry */
 	{ }						/* Terminating entry */
 };
 };
 
 
@@ -106,6 +107,7 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
 	{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
 	{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
 	{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
 	{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
 	{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
+	{ USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
 	{ USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
 	{ USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
 	{ }						/* Terminating entry */
 	{ }						/* Terminating entry */
 };
 };

+ 4 - 0
drivers/usb/serial/cypress_m8.h

@@ -19,6 +19,10 @@
 #define VENDOR_ID_CYPRESS		 0x04b4
 #define VENDOR_ID_CYPRESS		 0x04b4
 #define PRODUCT_ID_CYPHIDCOM		 0x5500
 #define PRODUCT_ID_CYPHIDCOM		 0x5500
 
 
+/* Powercom UPS, chip CY7C63723 */
+#define VENDOR_ID_POWERCOM		 0x0d9f
+#define PRODUCT_ID_UPS			 0x0002
+
 /* Nokia CA-42 USB to serial cable */
 /* Nokia CA-42 USB to serial cable */
 #define VENDOR_ID_DAZZLE		0x07d0
 #define VENDOR_ID_DAZZLE		0x07d0
 #define PRODUCT_ID_CA42			0x4101
 #define PRODUCT_ID_CA42			0x4101

+ 1 - 0
drivers/usb/serial/ftdi_sio.c

@@ -359,6 +359,7 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
 	{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
 	{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
 	{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
 	{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID),
 	{ USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID),

+ 3 - 0
drivers/usb/serial/ftdi_sio.h

@@ -557,6 +557,9 @@
 #define TML_VID			0x1B91	/* Vendor ID */
 #define TML_VID			0x1B91	/* Vendor ID */
 #define TML_USB_SERIAL_PID	0x0064	/* USB - Serial Converter */
 #define TML_USB_SERIAL_PID	0x0064	/* USB - Serial Converter */
 
 
+/* Propox devices */
+#define FTDI_PROPOX_JTAGCABLEII_PID	0xD738
+
 /* Commands */
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */

+ 6 - 4
drivers/usb/serial/generic.c

@@ -323,7 +323,7 @@ static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
 		room = tty_buffer_request_room(tty, urb->actual_length);
 		room = tty_buffer_request_room(tty, urb->actual_length);
 		if (room) {
 		if (room) {
 			tty_insert_flip_string(tty, urb->transfer_buffer, room);
 			tty_insert_flip_string(tty, urb->transfer_buffer, room);
-			tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
+			tty_flip_buffer_push(tty);
 		}
 		}
 	}
 	}
 
 
@@ -349,10 +349,12 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
 
 
 	/* Throttle the device if requested by tty */
 	/* Throttle the device if requested by tty */
 	spin_lock_irqsave(&port->lock, flags);
 	spin_lock_irqsave(&port->lock, flags);
-	if (!(port->throttled = port->throttle_req))
-		/* Handle data and continue reading from device */
+	if (!(port->throttled = port->throttle_req)) {
+		spin_unlock_irqrestore(&port->lock, flags);
 		flush_and_resubmit_read_urb(port);
 		flush_and_resubmit_read_urb(port);
-	spin_unlock_irqrestore(&port->lock, flags);
+	} else {
+		spin_unlock_irqrestore(&port->lock, flags);
+	}
 }
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
 EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
 
 

+ 62 - 13
drivers/usb/serial/option.c

@@ -111,6 +111,42 @@ static int  option_send_setup(struct usb_serial_port *port);
 #define HUAWEI_PRODUCT_E220BIS			0x1004
 #define HUAWEI_PRODUCT_E220BIS			0x1004
 
 
 #define NOVATELWIRELESS_VENDOR_ID		0x1410
 #define NOVATELWIRELESS_VENDOR_ID		0x1410
+
+/* MERLIN EVDO PRODUCTS */
+#define NOVATELWIRELESS_PRODUCT_V640		0x1100
+#define NOVATELWIRELESS_PRODUCT_V620		0x1110
+#define NOVATELWIRELESS_PRODUCT_V740		0x1120
+#define NOVATELWIRELESS_PRODUCT_V720		0x1130
+
+/* MERLIN HSDPA/HSPA PRODUCTS */
+#define NOVATELWIRELESS_PRODUCT_U730		0x1400
+#define NOVATELWIRELESS_PRODUCT_U740		0x1410
+#define NOVATELWIRELESS_PRODUCT_U870		0x1420
+#define NOVATELWIRELESS_PRODUCT_XU870		0x1430
+#define NOVATELWIRELESS_PRODUCT_X950D		0x1450
+
+/* EXPEDITE PRODUCTS */
+#define NOVATELWIRELESS_PRODUCT_EV620		0x2100
+#define NOVATELWIRELESS_PRODUCT_ES720		0x2110
+#define NOVATELWIRELESS_PRODUCT_E725		0x2120
+#define NOVATELWIRELESS_PRODUCT_EU730		0x2400
+#define NOVATELWIRELESS_PRODUCT_EU740		0x2410
+#define NOVATELWIRELESS_PRODUCT_EU870D		0x2420
+
+/* OVATION PRODUCTS */
+#define NOVATELWIRELESS_PRODUCT_MC727		0x4100
+#define NOVATELWIRELESS_PRODUCT_MC950D		0x4400
+
+/* FUTURE NOVATEL PRODUCTS */
+#define NOVATELWIRELESS_PRODUCT_EVDO_1		0x6000
+#define NOVATELWIRELESS_PRODUCT_HSPA_1		0x7000
+#define NOVATELWIRELESS_PRODUCT_EMBEDDED_1	0x8000
+#define NOVATELWIRELESS_PRODUCT_GLOBAL_1	0x9000
+#define NOVATELWIRELESS_PRODUCT_EVDO_2		0x6001
+#define NOVATELWIRELESS_PRODUCT_HSPA_2		0x7001
+#define NOVATELWIRELESS_PRODUCT_EMBEDDED_2	0x8001
+#define NOVATELWIRELESS_PRODUCT_GLOBAL_2	0x9001
+
 #define DELL_VENDOR_ID				0x413C
 #define DELL_VENDOR_ID				0x413C
 
 
 #define KYOCERA_VENDOR_ID			0x0c88
 #define KYOCERA_VENDOR_ID			0x0c88
@@ -168,21 +204,34 @@ static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1100) }, /* Novatel Merlin XS620/S640 */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1110) }, /* Novatel Merlin S620 */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1120) }, /* Novatel Merlin EX720 */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1130) }, /* Novatel Merlin S720 */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1400) }, /* Novatel U730 */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1410) }, /* Novatel U740 */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1420) }, /* Novatel EU870 */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2100) }, /* Novatel EV620 CDMA/EV-DO */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V720) }, /* Novatel Merlin V720/S720/PC720 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U730) }, /* Novatel U730/U740 (VF version) */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U740) }, /* Novatel U740 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U870) }, /* Novatel U870 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_XU870) }, /* Novatel Merlin XU870 HSDPA/3G */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_X950D) }, /* Novatel X950D */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EV620) }, /* Novatel EV620/ES620 CDMA/EV-DO */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES720) }, /* Novatel ES620/ES720/U720/USB720 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E725) }, /* Novatel E725/E726 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x4100) }, /* Novatel U727 */
-	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x4400) }, /* Novatel MC950 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU730) }, /* Novatel EU730 and Vodafone EU740 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU740) }, /* Novatel non-Vodafone EU740 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x5010) }, /* Novatel U727 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x5010) }, /* Novatel U727 */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_1) }, /* Novatel EVDO product */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_1) }, /* Novatel HSPA product */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EMBEDDED_1) }, /* Novatel Embedded product */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_GLOBAL_1) }, /* Novatel Global product */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_2) }, /* Novatel EVDO product */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_2) }, /* Novatel HSPA product */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EMBEDDED_2) }, /* Novatel Embedded product */
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_GLOBAL_2) }, /* Novatel Global product */
+
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8114) },	/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8114) },	/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8115) },	/* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8115) },	/* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8116) },	/* Dell Wireless 5505 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
 	{ USB_DEVICE(DELL_VENDOR_ID, 0x8116) },	/* Dell Wireless 5505 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */

+ 2 - 2
drivers/usb/storage/sddr55.c

@@ -522,8 +522,8 @@ int sddr55_reset(struct us_data *us) {
 
 
 static unsigned long sddr55_get_capacity(struct us_data *us) {
 static unsigned long sddr55_get_capacity(struct us_data *us) {
 
 
-	unsigned char manufacturerID;
-	unsigned char deviceID;
+	unsigned char uninitialized_var(manufacturerID);
+	unsigned char uninitialized_var(deviceID);
 	int result;
 	int result;
 	struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
 	struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
 
 

+ 13 - 0
drivers/video/Kconfig

@@ -553,6 +553,19 @@ config FB_BF54X_LQ043
 	help
 	help
 	 This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD
 	 This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD
 
 
+config FB_BFIN_T350MCQB
+	tristate "Varitronix COG-T350MCQB TFT LCD display (BF527 EZKIT)"
+	depends on FB && BLACKFIN
+	select BFIN_GPTIMERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	 This is the framebuffer device driver for a Varitronix VL-PS-COG-T350MCQB-01 display TFT LCD
+	 This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI
+	 It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK.
+
+
 config FB_STI
 config FB_STI
 	tristate "HP STI frame buffer device support"
 	tristate "HP STI frame buffer device support"
 	depends on FB && PARISC
 	depends on FB && PARISC

+ 1 - 0
drivers/video/Makefile

@@ -122,6 +122,7 @@ obj-$(CONFIG_FB_EFI)              += efifb.o
 obj-$(CONFIG_FB_VGA16)            += vga16fb.o
 obj-$(CONFIG_FB_VGA16)            += vga16fb.o
 obj-$(CONFIG_FB_OF)               += offb.o
 obj-$(CONFIG_FB_OF)               += offb.o
 obj-$(CONFIG_FB_BF54X_LQ043)	  += bf54x-lq043fb.o
 obj-$(CONFIG_FB_BF54X_LQ043)	  += bf54x-lq043fb.o
+obj-$(CONFIG_FB_BFIN_T350MCQB)	  += bfin-t350mcqb-fb.o
 
 
 # the test framebuffer is last
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o

+ 3 - 3
drivers/video/bf54x-lq043fb.c

@@ -8,7 +8,7 @@
  *
  *
  *
  *
  * Modified:
  * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
+ *               Copyright 2007-2008 Analog Devices Inc.
  *
  *
  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
  *
  *
@@ -241,7 +241,7 @@ static int request_ports(struct bfin_bf54xfb_info *fbi)
 	u16 eppi_req_18[] = EPPI0_18;
 	u16 eppi_req_18[] = EPPI0_18;
 	u16 disp = fbi->mach_info->disp;
 	u16 disp = fbi->mach_info->disp;
 
 
-	if (gpio_request(disp, NULL)) {
+	if (gpio_request(disp, DRIVER_NAME)) {
 		printk(KERN_ERR "Requesting GPIO %d faild\n", disp);
 		printk(KERN_ERR "Requesting GPIO %d faild\n", disp);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
@@ -672,7 +672,7 @@ static int __init bfin_bf54x_probe(struct platform_device *pdev)
 				      &bfin_lq043fb_bl_ops);
 				      &bfin_lq043fb_bl_ops);
 	bl_dev->props.max_brightness = 255;
 	bl_dev->props.max_brightness = 255;
 
 
-	lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops);
+	lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops);
 	lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
 	lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
 #endif
 #endif
 
 

+ 685 - 0
drivers/video/bfin-t350mcqb-fb.c

@@ -0,0 +1,685 @@
+/*
+ * File:         drivers/video/bfin-t350mcqb-fb.c
+ * Based on:
+ * Author:       Michael Hennerich <hennerich@blackfin.uclinux.org>
+ *
+ * Created:
+ * Description:  Blackfin LCD Framebufer driver
+ *
+ *
+ * Modified:
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/dma-mapping.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+#include <asm/gptimers.h>
+
+#define NO_BL_SUPPORT
+
+#define LCD_X_RES		320	/* Horizontal Resolution */
+#define LCD_Y_RES		240	/* Vertical Resolution */
+#define LCD_BPP			24	/* Bit Per Pixel */
+
+#define	DMA_BUS_SIZE		16
+#define	LCD_CLK         	(12*1000*1000)	/* 12MHz */
+
+#define CLOCKS_PER_PIX		3
+
+	/*
+	 * HS and VS timing parameters (all in number of PPI clk ticks)
+	 */
+
+#define U_LINE		1				/* Blanking Lines */
+
+#define H_ACTPIX	(LCD_X_RES * CLOCKS_PER_PIX)	/* active horizontal pixel */
+#define H_PERIOD	(408 * CLOCKS_PER_PIX)		/* HS period */
+#define H_PULSE		90				/* HS pulse width */
+#define H_START		204				/* first valid pixel */
+
+#define	V_LINES		(LCD_Y_RES + U_LINE)		/* total vertical lines */
+#define V_PULSE		(3 * H_PERIOD)			/* VS pulse width (1-5 H_PERIODs) */
+#define V_PERIOD	(H_PERIOD * V_LINES)		/* VS period */
+
+#define ACTIVE_VIDEO_MEM_OFFSET	(U_LINE * H_ACTPIX)
+
+#define BFIN_LCD_NBR_PALETTE_ENTRIES	256
+
+#define DRIVER_NAME "bfin-t350mcqb"
+static char driver_name[] = DRIVER_NAME;
+
+struct bfin_t350mcqbfb_info {
+	struct fb_info *fb;
+	struct device *dev;
+	unsigned char *fb_buffer;	/* RGB Buffer */
+	dma_addr_t dma_handle;
+	int lq043_mmap;
+	int lq043_open_cnt;
+	int irq;
+	spinlock_t lock;	/* lock */
+};
+
+static int nocursor;
+module_param(nocursor, int, 0644);
+MODULE_PARM_DESC(nocursor, "cursor enable/disable");
+
+#define PPI_TX_MODE		0x2
+#define PPI_XFER_TYPE_11	0xC
+#define PPI_PORT_CFG_01		0x10
+#define PPI_PACK_EN		0x80
+#define PPI_POLS_1		0x8000
+
+static void bfin_t350mcqb_config_ppi(struct bfin_t350mcqbfb_info *fbi)
+{
+	bfin_write_PPI_DELAY(H_START);
+	bfin_write_PPI_COUNT(H_ACTPIX-1);
+	bfin_write_PPI_FRAME(V_LINES);
+
+	bfin_write_PPI_CONTROL(PPI_TX_MODE |	   /* output mode , PORT_DIR */
+				PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */
+				PPI_PORT_CFG_01 |  /* two frame sync PORT_CFG */
+				PPI_PACK_EN |	   /* packing enabled PACK_EN */
+				PPI_POLS_1);	   /* faling edge syncs POLS */
+}
+
+static inline void bfin_t350mcqb_disable_ppi(void)
+{
+	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
+}
+
+static inline void bfin_t350mcqb_enable_ppi(void)
+{
+	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+}
+
+static void bfin_t350mcqb_start_timers(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+		enable_gptimers(TIMER1bit);
+		enable_gptimers(TIMER0bit);
+	local_irq_restore(flags);
+}
+
+static void bfin_t350mcqb_stop_timers(void)
+{
+	disable_gptimers(TIMER0bit | TIMER1bit);
+
+	set_gptimer_status(0, TIMER_STATUS_TRUN0 | TIMER_STATUS_TRUN1 |
+				TIMER_STATUS_TIMIL0 | TIMER_STATUS_TIMIL1 |
+				 TIMER_STATUS_TOVF0 | TIMER_STATUS_TOVF1);
+
+}
+
+static void bfin_t350mcqb_init_timers(void)
+{
+
+	bfin_t350mcqb_stop_timers();
+
+	set_gptimer_period(TIMER0_id, H_PERIOD);
+	set_gptimer_pwidth(TIMER0_id, H_PULSE);
+	set_gptimer_config(TIMER0_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
+				      TIMER_TIN_SEL | TIMER_CLK_SEL|
+				      TIMER_EMU_RUN);
+
+	set_gptimer_period(TIMER1_id, V_PERIOD);
+	set_gptimer_pwidth(TIMER1_id, V_PULSE);
+	set_gptimer_config(TIMER1_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
+				      TIMER_TIN_SEL | TIMER_CLK_SEL |
+				      TIMER_EMU_RUN);
+
+}
+
+static void bfin_t350mcqb_config_dma(struct bfin_t350mcqbfb_info *fbi)
+{
+
+	set_dma_config(CH_PPI,
+		       set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
+					   INTR_DISABLE, DIMENSION_2D,
+					   DATA_SIZE_16,
+					   DMA_NOSYNC_KEEP_DMA_BUF));
+	set_dma_x_count(CH_PPI, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE);
+	set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8);
+	set_dma_y_count(CH_PPI, V_LINES);
+
+	set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8);
+	set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer);
+
+}
+
+static int bfin_t350mcqb_request_ports(int action)
+{
+	u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+			    P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
+			    P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
+			    P_PPI0_D6, P_PPI0_D7, 0};
+
+	if (action) {
+		if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) {
+			printk(KERN_ERR "Requesting Peripherals faild\n");
+			return -EFAULT;
+		}
+	} else
+		peripheral_free_list(ppi0_req_8);
+
+	return 0;
+}
+
+static int bfin_t350mcqb_fb_open(struct fb_info *info, int user)
+{
+	struct bfin_t350mcqbfb_info *fbi = info->par;
+
+	spin_lock(&fbi->lock);
+	fbi->lq043_open_cnt++;
+
+	if (fbi->lq043_open_cnt <= 1) {
+
+		bfin_t350mcqb_disable_ppi();
+		SSYNC();
+
+		bfin_t350mcqb_config_dma(fbi);
+		bfin_t350mcqb_config_ppi(fbi);
+		bfin_t350mcqb_init_timers();
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		bfin_t350mcqb_enable_ppi();
+		bfin_t350mcqb_start_timers();
+	}
+
+	spin_unlock(&fbi->lock);
+
+	return 0;
+}
+
+static int bfin_t350mcqb_fb_release(struct fb_info *info, int user)
+{
+	struct bfin_t350mcqbfb_info *fbi = info->par;
+
+	spin_lock(&fbi->lock);
+
+	fbi->lq043_open_cnt--;
+	fbi->lq043_mmap = 0;
+
+	if (fbi->lq043_open_cnt <= 0) {
+		bfin_t350mcqb_disable_ppi();
+		SSYNC();
+		disable_dma(CH_PPI);
+		bfin_t350mcqb_stop_timers();
+		memset(fbi->fb_buffer, 0, info->fix.smem_len);
+	}
+
+	spin_unlock(&fbi->lock);
+
+	return 0;
+}
+
+static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var,
+				   struct fb_info *info)
+{
+
+	if (var->bits_per_pixel != LCD_BPP) {
+		pr_debug("%s: depth not supported: %u BPP\n", __FUNCTION__,
+			 var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (info->var.xres != var->xres || info->var.yres != var->yres ||
+	    info->var.xres_virtual != var->xres_virtual ||
+	    info->var.yres_virtual != var->yres_virtual) {
+		pr_debug("%s: Resolution not supported: X%u x Y%u \n",
+			 __FUNCTION__, var->xres, var->yres);
+		return -EINVAL;
+	}
+
+	/*
+	 *  Memory limit
+	 */
+
+	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+			 __FUNCTION__, var->yres_virtual);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int bfin_t350mcqb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct bfin_t350mcqbfb_info *fbi = info->par;
+
+	if (fbi->lq043_mmap)
+		return -1;
+
+	spin_lock(&fbi->lock);
+	fbi->lq043_mmap = 1;
+	spin_unlock(&fbi->lock);
+
+	vma->vm_start = (unsigned long)(fbi->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET);
+
+	vma->vm_end = vma->vm_start + info->fix.smem_len;
+	/* For those who don't understand how mmap works, go read
+	 *   Documentation/nommu-mmap.txt.
+	 * For those that do, you will know that the VM_MAYSHARE flag
+	 * must be set in the vma->vm_flags structure on noMMU
+	 *   Other flags can be set, and are documented in
+	 *   include/linux/mm.h
+	 */
+	vma->vm_flags |= VM_MAYSHARE;
+
+	return 0;
+}
+
+int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	if (nocursor)
+		return 0;
+	else
+		return -EINVAL;	/* just to force soft_cursor() call */
+}
+
+static int bfin_t350mcqb_fb_setcolreg(u_int regno, u_int red, u_int green,
+				   u_int blue, u_int transp,
+				   struct fb_info *info)
+{
+	if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
+		return -EINVAL;
+
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+
+		u32 value;
+		/* Place color in the pseudopalette */
+		if (regno > 16)
+			return -EINVAL;
+
+		red >>= (16 - info->var.red.length);
+		green >>= (16 - info->var.green.length);
+		blue >>= (16 - info->var.blue.length);
+
+		value = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset);
+		value &= 0xFFFFFF;
+
+		((u32 *) (info->pseudo_palette))[regno] = value;
+
+	}
+
+	return 0;
+}
+
+static struct fb_ops bfin_t350mcqb_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = bfin_t350mcqb_fb_open,
+	.fb_release = bfin_t350mcqb_fb_release,
+	.fb_check_var = bfin_t350mcqb_fb_check_var,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_mmap = bfin_t350mcqb_fb_mmap,
+	.fb_cursor = bfin_t350mcqb_fb_cursor,
+	.fb_setcolreg = bfin_t350mcqb_fb_setcolreg,
+};
+
+#ifndef NO_BL_SUPPORT
+static int bl_get_brightness(struct backlight_device *bd)
+{
+	return 0;
+}
+
+static struct backlight_ops bfin_lq043fb_bl_ops = {
+	.get_brightness = bl_get_brightness,
+};
+
+static struct backlight_device *bl_dev;
+
+static int bfin_lcd_get_power(struct lcd_device *dev)
+{
+	return 0;
+}
+
+static int bfin_lcd_set_power(struct lcd_device *dev, int power)
+{
+	return 0;
+}
+
+static int bfin_lcd_get_contrast(struct lcd_device *dev)
+{
+	return 0;
+}
+
+static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
+{
+
+	return 0;
+}
+
+static int bfin_lcd_check_fb(struct fb_info *fi)
+{
+	if (!fi || (fi == &bfin_t350mcqb_fb))
+		return 1;
+	return 0;
+}
+
+static struct lcd_ops bfin_lcd_ops = {
+	.get_power = bfin_lcd_get_power,
+	.set_power = bfin_lcd_set_power,
+	.get_contrast = bfin_lcd_get_contrast,
+	.set_contrast = bfin_lcd_set_contrast,
+	.check_fb = bfin_lcd_check_fb,
+};
+
+static struct lcd_device *lcd_dev;
+#endif
+
+static irqreturn_t bfin_t350mcqb_irq_error(int irq, void *dev_id)
+{
+	/*struct bfin_t350mcqbfb_info *info = (struct bfin_t350mcqbfb_info *)dev_id;*/
+
+	u16 status = bfin_read_PPI_STATUS();
+	bfin_write_PPI_STATUS(0xFFFF);
+
+	if (status) {
+		bfin_t350mcqb_disable_ppi();
+		disable_dma(CH_PPI);
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		bfin_t350mcqb_enable_ppi();
+		bfin_write_PPI_STATUS(0xFFFF);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
+{
+	struct bfin_t350mcqbfb_info *info;
+	struct fb_info *fbinfo;
+	int ret;
+
+	printk(KERN_INFO DRIVER_NAME ": %dx%d %d-bit RGB FrameBuffer initializing...\n",
+					 LCD_X_RES, LCD_Y_RES, LCD_BPP);
+
+	if (request_dma(CH_PPI, "CH_PPI") < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": couldn't request CH_PPI DMA\n");
+		ret = -EFAULT;
+		goto out1;
+	}
+
+	fbinfo =
+	    framebuffer_alloc(sizeof(struct bfin_t350mcqbfb_info), &pdev->dev);
+	if (!fbinfo) {
+		ret = -ENOMEM;
+		goto out2;
+	}
+
+	info = fbinfo->par;
+	info->fb = fbinfo;
+	info->dev = &pdev->dev;
+
+	platform_set_drvdata(pdev, fbinfo);
+
+	strcpy(fbinfo->fix.id, driver_name);
+
+	fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
+	fbinfo->fix.type_aux = 0;
+	fbinfo->fix.xpanstep = 0;
+	fbinfo->fix.ypanstep = 0;
+	fbinfo->fix.ywrapstep = 0;
+	fbinfo->fix.accel = FB_ACCEL_NONE;
+	fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	fbinfo->var.nonstd = 0;
+	fbinfo->var.activate = FB_ACTIVATE_NOW;
+	fbinfo->var.height = -1;
+	fbinfo->var.width = -1;
+	fbinfo->var.accel_flags = 0;
+	fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
+
+	fbinfo->var.xres = LCD_X_RES;
+	fbinfo->var.xres_virtual = LCD_X_RES;
+	fbinfo->var.yres = LCD_Y_RES;
+	fbinfo->var.yres_virtual = LCD_Y_RES;
+	fbinfo->var.bits_per_pixel = LCD_BPP;
+
+	fbinfo->var.red.offset = 0;
+	fbinfo->var.green.offset = 8;
+	fbinfo->var.blue.offset = 16;
+	fbinfo->var.transp.offset = 0;
+	fbinfo->var.red.length = 8;
+	fbinfo->var.green.length = 8;
+	fbinfo->var.blue.length = 8;
+	fbinfo->var.transp.length = 0;
+	fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * LCD_BPP / 8;
+
+	fbinfo->fix.line_length = fbinfo->var.xres_virtual *
+	    fbinfo->var.bits_per_pixel / 8;
+
+
+	fbinfo->fbops = &bfin_t350mcqb_fb_ops;
+	fbinfo->flags = FBINFO_FLAG_DEFAULT;
+
+	info->fb_buffer =
+	    dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
+			       GFP_KERNEL);
+
+	if (NULL == info->fb_buffer) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": couldn't allocate dma buffer.\n");
+		ret = -ENOMEM;
+		goto out3;
+	}
+
+	memset(info->fb_buffer, 0, fbinfo->fix.smem_len);
+
+	fbinfo->screen_base = (void *)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
+	fbinfo->fix.smem_start = (int)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
+
+	fbinfo->fbops = &bfin_t350mcqb_fb_ops;
+
+	fbinfo->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
+	if (!fbinfo->pseudo_palette) {
+		printk(KERN_ERR DRIVER_NAME
+		       "Fail to allocate pseudo_palette\n");
+
+		ret = -ENOMEM;
+		goto out4;
+	}
+
+	memset(fbinfo->pseudo_palette, 0, sizeof(u32) * 16);
+
+	if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0)
+	    < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       "Fail to allocate colormap (%d entries)\n",
+		       BFIN_LCD_NBR_PALETTE_ENTRIES);
+		ret = -EFAULT;
+		goto out5;
+	}
+
+	if (bfin_t350mcqb_request_ports(1)) {
+		printk(KERN_ERR DRIVER_NAME ": couldn't request gpio port.\n");
+		ret = -EFAULT;
+		goto out6;
+	}
+
+	info->irq = platform_get_irq(pdev, 0);
+	if (info->irq < 0) {
+		ret = -EINVAL;
+		goto out7;
+	}
+
+	if (request_irq(info->irq, (void *)bfin_t350mcqb_irq_error, IRQF_DISABLED,
+			"PPI ERROR", info) < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": unable to request PPI ERROR IRQ\n");
+		ret = -EFAULT;
+		goto out7;
+	}
+
+	if (register_framebuffer(fbinfo) < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": unable to register framebuffer.\n");
+		ret = -EINVAL;
+		goto out8;
+	}
+#ifndef NO_BL_SUPPORT
+	bl_dev =
+	    backlight_device_register("bf52x-bl", NULL, NULL,
+				      &bfin_lq043fb_bl_ops);
+	bl_dev->props.max_brightness = 255;
+
+	lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops);
+	lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
+#endif
+
+	return 0;
+
+out8:
+	free_irq(info->irq, info);
+out7:
+	bfin_t350mcqb_request_ports(0);
+out6:
+	fb_dealloc_cmap(&fbinfo->cmap);
+out5:
+	kfree(fbinfo->pseudo_palette);
+out4:
+	dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
+			  info->dma_handle);
+out3:
+	framebuffer_release(fbinfo);
+out2:
+	free_dma(CH_PPI);
+out1:
+	platform_set_drvdata(pdev, NULL);
+
+	return ret;
+}
+
+static int bfin_t350mcqb_remove(struct platform_device *pdev)
+{
+
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct bfin_t350mcqbfb_info *info = fbinfo->par;
+
+	free_dma(CH_PPI);
+	free_irq(info->irq, info);
+
+	if (info->fb_buffer != NULL)
+		dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
+				  info->dma_handle);
+
+	kfree(fbinfo->pseudo_palette);
+	fb_dealloc_cmap(&fbinfo->cmap);
+
+#ifndef NO_BL_SUPPORT
+	lcd_device_unregister(lcd_dev);
+	backlight_device_unregister(bl_dev);
+#endif
+
+	unregister_framebuffer(fbinfo);
+
+	bfin_t350mcqb_request_ports(0);
+
+	printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_t350mcqb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct bfin_t350mcqbfb_info *info = fbinfo->par;
+
+	bfin_t350mcqb_disable_ppi();
+	disable_dma(CH_PPI);
+	bfin_write_PPI_STATUS(0xFFFF);
+
+	return 0;
+}
+
+static int bfin_t350mcqb_resume(struct platform_device *pdev)
+{
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct bfin_t350mcqbfb_info *info = fbinfo->par;
+
+	enable_dma(CH_PPI);
+	bfin_t350mcqb_enable_ppi();
+
+	return 0;
+}
+#else
+#define bfin_t350mcqb_suspend	NULL
+#define bfin_t350mcqb_resume	NULL
+#endif
+
+static struct platform_driver bfin_t350mcqb_driver = {
+	.probe = bfin_t350mcqb_probe,
+	.remove = bfin_t350mcqb_remove,
+	.suspend = bfin_t350mcqb_suspend,
+	.resume = bfin_t350mcqb_resume,
+	.driver = {
+		   .name = DRIVER_NAME,
+		   .owner = THIS_MODULE,
+		   },
+};
+
+static int __devinit bfin_t350mcqb_driver_init(void)
+{
+	return platform_driver_register(&bfin_t350mcqb_driver);
+}
+
+static void __exit bfin_t350mcqb_driver_cleanup(void)
+{
+	platform_driver_unregister(&bfin_t350mcqb_driver);
+}
+
+MODULE_DESCRIPTION("Blackfin TFT LCD Driver");
+MODULE_LICENSE("GPL");
+
+module_init(bfin_t350mcqb_driver_init);
+module_exit(bfin_t350mcqb_driver_cleanup);

+ 1 - 1
drivers/video/mbx/mbxfb.c

@@ -889,7 +889,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
 	struct mbxfb_info *mfbi;
 	struct mbxfb_info *mfbi;
 	struct mbxfb_platform_data *pdata;
 	struct mbxfb_platform_data *pdata;
 
 
-	dev_dbg(dev, "mbxfb_probe\n");
+	dev_dbg(&dev->dev, "mbxfb_probe\n");
 
 
 	pdata = dev->dev.platform_data;
 	pdata = dev->dev.platform_data;
 	if (!pdata) {
 	if (!pdata) {

+ 15 - 7
drivers/video/stifb.c

@@ -505,16 +505,24 @@ ngleSetupAttrPlanes(struct stifb_info *fb, int BufferNumber)
 static void
 static void
 rattlerSetupPlanes(struct stifb_info *fb)
 rattlerSetupPlanes(struct stifb_info *fb)
 {
 {
+	int saved_id, y;
+
+ 	/* Write RAMDAC pixel read mask register so all overlay
+	 * planes are display-enabled.  (CRX24 uses Bt462 pixel
+	 * read mask register for overlay planes, not image planes).
+	 */
 	CRX24_SETUP_RAMDAC(fb);
 	CRX24_SETUP_RAMDAC(fb);
     
     
-	/* replacement for: SETUP_FB(fb, CRX24_OVERLAY_PLANES); */
-	WRITE_WORD(0x83000300, fb, REG_14);
-	SETUP_HW(fb);
-	WRITE_BYTE(1, fb, REG_16b1);
+	/* change fb->id temporarily to fool SETUP_FB() */
+	saved_id = fb->id;
+	fb->id = CRX24_OVERLAY_PLANES;
+	SETUP_FB(fb);
+	fb->id = saved_id;
+
+	for (y = 0; y < fb->info.var.yres; ++y)
+		memset(fb->info.screen_base + y * fb->info.fix.line_length,
+			0xff, fb->info.var.xres * fb->info.var.bits_per_pixel/8);
 
 
-	fb_memset((void*)fb->info.fix.smem_start, 0xff,
-		fb->info.var.yres*fb->info.fix.line_length);
-    
 	CRX24_SET_OVLY_MASK(fb);
 	CRX24_SET_OVLY_MASK(fb);
 	SETUP_FB(fb);
 	SETUP_FB(fb);
 }
 }

+ 1 - 13
drivers/video/tridentfb.c

@@ -566,44 +566,32 @@ static inline void write3CE(int reg, unsigned char val)
 
 
 static void enable_mmio(void)
 static void enable_mmio(void)
 {
 {
-	unsigned char tmp;
-
 	/* Goto New Mode */
 	/* Goto New Mode */
 	outb(0x0B, 0x3C4);
 	outb(0x0B, 0x3C4);
 	inb(0x3C5);
 	inb(0x3C5);
 
 
 	/* Unprotect registers */
 	/* Unprotect registers */
 	outb(NewMode1, 0x3C4);
 	outb(NewMode1, 0x3C4);
-	tmp = inb(0x3C5);
 	outb(0x80, 0x3C5);
 	outb(0x80, 0x3C5);
 
 
 	/* Enable MMIO */
 	/* Enable MMIO */
 	outb(PCIReg, 0x3D4);
 	outb(PCIReg, 0x3D4);
 	outb(inb(0x3D5) | 0x01, 0x3D5);
 	outb(inb(0x3D5) | 0x01, 0x3D5);
-
-	t_outb(NewMode1, 0x3C4);
-	t_outb(tmp, 0x3C5);
 }
 }
 
 
 static void disable_mmio(void)
 static void disable_mmio(void)
 {
 {
-	unsigned char tmp;
-
 	/* Goto New Mode */
 	/* Goto New Mode */
 	t_outb(0x0B, 0x3C4);
 	t_outb(0x0B, 0x3C4);
 	t_inb(0x3C5);
 	t_inb(0x3C5);
 
 
 	/* Unprotect registers */
 	/* Unprotect registers */
 	t_outb(NewMode1, 0x3C4);
 	t_outb(NewMode1, 0x3C4);
-	tmp = t_inb(0x3C5);
 	t_outb(0x80, 0x3C5);
 	t_outb(0x80, 0x3C5);
 
 
 	/* Disable MMIO */
 	/* Disable MMIO */
 	t_outb(PCIReg, 0x3D4);
 	t_outb(PCIReg, 0x3D4);
 	t_outb(t_inb(0x3D5) & ~0x01, 0x3D5);
 	t_outb(t_inb(0x3D5) & ~0x01, 0x3D5);
-
-	outb(NewMode1, 0x3C4);
-	outb(tmp, 0x3C5);
 }
 }
 
 
 #define crtc_unlock()	write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)
 #define crtc_unlock()	write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)
@@ -757,7 +745,7 @@ static unsigned int __devinit get_memsize(void)
 			switch (tmp) {
 			switch (tmp) {
 
 
 			case 0x01:
 			case 0x01:
-				k = 512;
+				k = 512 * Kb;
 				break;
 				break;
 			case 0x02:
 			case 0x02:
 				k = 6 * Mb;	/* XP */
 				k = 6 * Mb;	/* XP */

+ 2 - 2
drivers/watchdog/cpu5wdt.c

@@ -59,9 +59,9 @@ static int ticks = 10000;
 
 
 static struct {
 static struct {
 	struct completion stop;
 	struct completion stop;
-	volatile int running;
+	int running;
 	struct timer_list timer;
 	struct timer_list timer;
-	volatile int queue;
+	int queue;
 	int default_ticks;
 	int default_ticks;
 	unsigned long inuse;
 	unsigned long inuse;
 } cpu5wdt_device;
 } cpu5wdt_device;

+ 24 - 190
drivers/watchdog/hpwdt.c

@@ -58,41 +58,6 @@ struct bios32_service_dir {
 	u8 reserved[5];
 	u8 reserved[5];
 };
 };
 
 
-/*
- * smbios_entry_point     - defines SMBIOS entry point structure
- *
- * anchor[4]              - anchor string (_SM_)
- * checksum               - checksum of the entry point structure
- * length                 - length of the entry point structure
- * major_ver              - major version (02h for revision 2.1)
- * minor_ver              - minor version (01h for revision 2.1)
- * max_struct_size        - size of the largest SMBIOS structure
- * revision               - entry point structure revision implemented
- * formatted_area[5]      - reserved
- * intermediate_anchor[5] - intermediate anchor string (_DMI_)
- * intermediate_checksum  - intermediate checksum
- * table_length           - structure table length
- * table_address          - structure table address
- * table_num_structs      - number of SMBIOS structures present
- * bcd_revision           - BCD revision
- */
-struct smbios_entry_point {
-	u8 anchor[4];
-	u8 checksum;
-	u8 length;
-	u8 major_ver;
-	u8 minor_ver;
-	u16 max_struct_size;
-	u8 revision;
-	u8 formatted_area[5];
-	u8 intermediate_anchor[5];
-	u8 intermediate_checksum;
-	u16 table_length;
-	u64 table_address;
-	u16 table_num_structs;
-	u8 bcd_revision;
-};
-
 /* type 212 */
 /* type 212 */
 struct smbios_cru64_info {
 struct smbios_cru64_info {
 	u8 type;
 	u8 type;
@@ -175,31 +140,13 @@ static struct pci_device_id hpwdt_devices[] = {
 };
 };
 MODULE_DEVICE_TABLE(pci, hpwdt_devices);
 MODULE_DEVICE_TABLE(pci, hpwdt_devices);
 
 
-/*
- *	bios_checksum
- */
-static int __devinit bios_checksum(const char __iomem *ptr, int len)
-{
-	char sum = 0;
-	int i;
-
-	/*
-	 * calculate checksum of size bytes. This should add up
-	 * to zero if we have a valid header.
-	 */
-	for (i = 0; i < len; i++)
-		sum += ptr[i];
-
-	return ((sum == 0) && (len > 0));
-}
-
 #ifndef CONFIG_X86_64
 #ifndef CONFIG_X86_64
 /* --32 Bit Bios------------------------------------------------------------ */
 /* --32 Bit Bios------------------------------------------------------------ */
 
 
 #define HPWDT_ARCH	32
 #define HPWDT_ARCH	32
 
 
-asmlinkage void asminline_call(struct cmn_registers *pi86Regs,
-			       unsigned long *pRomEntry)
+static void asminline_call(struct cmn_registers *pi86Regs,
+			   unsigned long *pRomEntry)
 {
 {
 	asm("pushl       %ebp               \n\t"
 	asm("pushl       %ebp               \n\t"
 	    "movl        %esp, %ebp         \n\t"
 	    "movl        %esp, %ebp         \n\t"
@@ -302,6 +249,24 @@ static int __devinit cru_detect(unsigned long map_entry,
 	return retval;
 	return retval;
 }
 }
 
 
+/*
+ *	bios_checksum
+ */
+static int __devinit bios_checksum(const char __iomem *ptr, int len)
+{
+	char sum = 0;
+	int i;
+
+	/*
+	 * calculate checksum of size bytes. This should add up
+	 * to zero if we have a valid header.
+	 */
+	for (i = 0; i < len; i++)
+		sum += ptr[i];
+
+	return ((sum == 0) && (len > 0));
+}
+
 /*
 /*
  *	bios32_present
  *	bios32_present
  *
  *
@@ -368,8 +333,8 @@ static int __devinit detect_cru_service(void)
 
 
 #define HPWDT_ARCH	64
 #define HPWDT_ARCH	64
 
 
-asmlinkage void asminline_call(struct cmn_registers *pi86Regs,
-			       unsigned long *pRomEntry)
+static void asminline_call(struct cmn_registers *pi86Regs,
+			   unsigned long *pRomEntry)
 {
 {
 	asm("pushq      %rbp            \n\t"
 	asm("pushq      %rbp            \n\t"
 	    "movq       %rsp, %rbp      \n\t"
 	    "movq       %rsp, %rbp      \n\t"
@@ -410,12 +375,8 @@ asmlinkage void asminline_call(struct cmn_registers *pi86Regs,
  *	dmi_find_cru
  *	dmi_find_cru
  *
  *
  *	Routine Description:
  *	Routine Description:
- *	This function checks wether or not a SMBIOS/DMI record is
+ *	This function checks whether or not a SMBIOS/DMI record is
  *	the 64bit CRU info or not
  *	the 64bit CRU info or not
- *
- *	Return Value:
- *	0        :  SUCCESS - if record found
- *	<0       :  FAILURE - if record not found
  */
  */
 static void __devinit dmi_find_cru(const struct dmi_header *dm)
 static void __devinit dmi_find_cru(const struct dmi_header *dm)
 {
 {
@@ -434,138 +395,11 @@ static void __devinit dmi_find_cru(const struct dmi_header *dm)
 	}
 	}
 }
 }
 
 
-/*
- *	dmi_table
- *
- *	Routine Description:
- *	Decode the SMBIOS/DMI table and check if we have a 64bit CRU record
- *	or not.
- *
- *	We have to be cautious here. We have seen BIOSes with DMI pointers
- *	pointing to completely the wrong place for example
- */
-static void __devinit dmi_table(u8 *buf, int len, int num,
-		      void (*decode)(const struct dmi_header *))
-{
-	u8 *data = buf;
-	int i = 0;
-
-	/*
-	 *	Stop when we see all the items the table claimed to have
-	 *	OR we run off the end of the table (also happens)
-	 */
-	while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
-		const struct dmi_header *dm = (const struct dmi_header *)data;
-
-		/*
-		 *  We want to know the total length (formated area and strings)
-		 *  before decoding to make sure we won't run off the table in
-		 *  dmi_decode or dmi_string
-		 */
-		data += dm->length;
-		while ((data - buf < len - 1) && (data[0] || data[1]))
-			data++;
-		if (data - buf < len - 1)
-			decode(dm);
-		data += 2;
-		i++;
-	}
-}
-
-/*
- *	smbios_present
- *
- *	Routine Description:
- *	This function parses the SMBIOS entry point table to retrieve
- *	the 64 bit CRU Service.
- *
- *	Return Value:
- *	0        :  SUCCESS
- *	<0       :  FAILURE
- */
-static int __devinit smbios_present(const char __iomem *p)
-{
-	struct smbios_entry_point *eps =
-		(struct smbios_entry_point *) p;
-	int length;
-	u8 *buf;
-
-	/* check if we have indeed the SMBIOS table entry point */
-	if ((strncmp((char *)eps->anchor, "_SM_",
-			     sizeof(eps->anchor))) == 0) {
-		length = eps->length;
-
-		/* SMBIOS v2.1 implementation might use 0x1e */
-		if ((length == 0x1e) &&
-		    (eps->major_ver == 2) &&
-		    (eps->minor_ver == 1))
-			length = 0x1f;
-
-		/*
-		 * Now we will check:
-		 * - SMBIOS checksum must be 0
-		 * - intermediate anchor should be _DMI_
-		 * - intermediate checksum should be 0
-		 */
-		if ((bios_checksum(p, length)) &&
-		    (strncmp((char *)eps->intermediate_anchor, "_DMI_",
-		             sizeof(eps->intermediate_anchor)) == 0) &&
-		    (bios_checksum(p+0x10, 15))) {
-			buf = ioremap(eps->table_address, eps->table_length);
-			if (buf == NULL)
-				return -ENODEV;
-
-
-			/* Scan the DMI table for the 64 bit CRU service */
-			dmi_table(buf, eps->table_length,
-			          eps->table_num_structs, dmi_find_cru);
-
-			iounmap(buf);
-			return 0;
-		}
-	}
-
-	return -ENODEV;
-}
-
-static int __devinit smbios_scan_machine(void)
-{
-	char __iomem *p, *q;
-	int rc;
-
-	if (efi_enabled) {
-		if (efi.smbios == EFI_INVALID_TABLE_ADDR)
-			return -ENODEV;
-
-		p = ioremap(efi.smbios, 32);
-		if (p == NULL)
-			return -ENOMEM;
-
-		rc = smbios_present(p);
-		iounmap(p);
-	} else {
-		/*
-		 * Search from 0x0f0000 through 0x0fffff, inclusive.
-		 */
-		p = ioremap(PCI_ROM_BASE1, ROM_SIZE);
-		if (p == NULL)
-			return -ENOMEM;
-
-		for (q = p; q < p + ROM_SIZE; q += 16) {
-			rc = smbios_present(q);
-			if (!rc) {
-				break;
-			}
-		}
-		iounmap(p);
-	}
-}
-
 static int __devinit detect_cru_service(void)
 static int __devinit detect_cru_service(void)
 {
 {
 	cru_rom_addr = NULL;
 	cru_rom_addr = NULL;
 
 
-	smbios_scan_machine();	/* will become dmi_walk(dmi_find_cru); */
+	dmi_walk(dmi_find_cru);
 
 
 	/* if cru_rom_addr has been set then we found a CRU service */
 	/* if cru_rom_addr has been set then we found a CRU service */
 	return ((cru_rom_addr != NULL)? 0: -ENODEV);
 	return ((cru_rom_addr != NULL)? 0: -ENODEV);

+ 64 - 14
drivers/watchdog/it8712f_wdt.c

@@ -7,7 +7,8 @@
  *
  *
  *	drivers/char/watchdog/scx200_wdt.c
  *	drivers/char/watchdog/scx200_wdt.c
  *	drivers/hwmon/it87.c
  *	drivers/hwmon/it87.c
- *	IT8712F EC-LPC I/O Preliminary Specification 0.9.2.pdf
+ *	IT8712F EC-LPC I/O Preliminary Specification 0.8.2
+ *	IT8712F EC-LPC I/O Preliminary Specification 0.9.3
  *
  *
  *	This program is free software; you can redistribute it and/or
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License as
  *	modify it under the terms of the GNU General Public License as
@@ -40,6 +41,7 @@ MODULE_DESCRIPTION("IT8712F Watchdog Driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 
 
+static int max_units = 255;
 static int margin = 60;		/* in seconds */
 static int margin = 60;		/* in seconds */
 module_param(margin, int, 0);
 module_param(margin, int, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
@@ -51,6 +53,7 @@ MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
 static struct semaphore it8712f_wdt_sem;
 static struct semaphore it8712f_wdt_sem;
 static unsigned expect_close;
 static unsigned expect_close;
 static spinlock_t io_lock;
 static spinlock_t io_lock;
+static unsigned char revision;
 
 
 /* Dog Food address - We use the game port address */
 /* Dog Food address - We use the game port address */
 static unsigned short address;
 static unsigned short address;
@@ -108,6 +111,15 @@ superio_inw(int reg)
 	return val;
 	return val;
 }
 }
 
 
+static void
+superio_outw(int val, int reg)
+{
+	outb(reg++, REG);
+	outb((val >> 8) & 0xff, VAL);
+	outb(reg, REG);
+	outb(val & 0xff, VAL);
+}
+
 static inline void
 static inline void
 superio_select(int ldn)
 superio_select(int ldn)
 {
 {
@@ -143,15 +155,33 @@ static void
 it8712f_wdt_update_margin(void)
 it8712f_wdt_update_margin(void)
 {
 {
 	int config = WDT_OUT_KRST | WDT_OUT_PWROK;
 	int config = WDT_OUT_KRST | WDT_OUT_PWROK;
-
-	printk(KERN_INFO NAME ": timer margin %d seconds\n", margin);
-
-	/* The timeout register only has 8bits wide */
-	if (margin < 256)
-		config |= WDT_UNIT_SEC;	/* else UNIT are MINUTES */
+	int units = margin;
+
+	/* Switch to minutes precision if the configured margin
+	 * value does not fit within the register width.
+	 */
+	if (units <= max_units) {
+		config |= WDT_UNIT_SEC; /* else UNIT is MINUTES */
+		printk(KERN_INFO NAME ": timer margin %d seconds\n", units);
+	} else {
+		units /= 60;
+		printk(KERN_INFO NAME ": timer margin %d minutes\n", units);
+	}
 	superio_outb(config, WDT_CONFIG);
 	superio_outb(config, WDT_CONFIG);
 
 
-	superio_outb((margin > 255) ? (margin / 60) : margin, WDT_TIMEOUT);
+	if (revision >= 0x08)
+		superio_outw(units, WDT_TIMEOUT);
+	else
+		superio_outb(units, WDT_TIMEOUT);
+}
+
+static int
+it8712f_wdt_get_status(void)
+{
+	if (superio_inb(WDT_CONTROL) & 0x01)
+		return WDIOF_CARDRESET;
+	else
+		return 0;
 }
 }
 
 
 static void
 static void
@@ -234,7 +264,7 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
 		.firmware_version = 1,
 		.firmware_version = 1,
 		.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
 		.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
 	};
 	};
-	int new_margin;
+	int value;
 
 
 	switch (cmd) {
 	switch (cmd) {
 	default:
 	default:
@@ -244,17 +274,27 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
 			return -EFAULT;
 			return -EFAULT;
 		return 0;
 		return 0;
 	case WDIOC_GETSTATUS:
 	case WDIOC_GETSTATUS:
+		superio_enter();
+		superio_select(LDN_GPIO);
+
+		value = it8712f_wdt_get_status();
+
+		superio_exit();
+
+		return put_user(value, p);
 	case WDIOC_GETBOOTSTATUS:
 	case WDIOC_GETBOOTSTATUS:
 		return put_user(0, p);
 		return put_user(0, p);
 	case WDIOC_KEEPALIVE:
 	case WDIOC_KEEPALIVE:
 		it8712f_wdt_ping();
 		it8712f_wdt_ping();
 		return 0;
 		return 0;
 	case WDIOC_SETTIMEOUT:
 	case WDIOC_SETTIMEOUT:
-		if (get_user(new_margin, p))
+		if (get_user(value, p))
 			return -EFAULT;
 			return -EFAULT;
-		if (new_margin < 1)
+		if (value < 1)
+			return -EINVAL;
+		if (value > (max_units * 60))
 			return -EINVAL;
 			return -EINVAL;
-		margin = new_margin;
+		margin = value;
 		superio_enter();
 		superio_enter();
 		superio_select(LDN_GPIO);
 		superio_select(LDN_GPIO);
 
 
@@ -262,6 +302,7 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
 
 
 		superio_exit();
 		superio_exit();
 		it8712f_wdt_ping();
 		it8712f_wdt_ping();
+		/* Fall through */
 	case WDIOC_GETTIMEOUT:
 	case WDIOC_GETTIMEOUT:
 		if (put_user(margin, p))
 		if (put_user(margin, p))
 			return -EFAULT;
 			return -EFAULT;
@@ -336,9 +377,18 @@ it8712f_wdt_find(unsigned short *address)
 	}
 	}
 
 
 	err = 0;
 	err = 0;
-	printk(KERN_DEBUG NAME ": Found IT%04xF chip revision %d - "
+	revision = superio_inb(DEVREV) & 0x0f;
+
+	/* Later revisions have 16-bit values per datasheet 0.9.1 */
+	if (revision >= 0x08)
+		max_units = 65535;
+
+	if (margin > (max_units * 60))
+		margin = (max_units * 60);
+
+	printk(KERN_INFO NAME ": Found IT%04xF chip revision %d - "
 		"using DogFood address 0x%x\n",
 		"using DogFood address 0x%x\n",
-		chip_type, superio_inb(DEVREV) & 0x0f, *address);
+		chip_type, revision, *address);
 
 
 exit:
 exit:
 	superio_exit();
 	superio_exit();

+ 1 - 1
drivers/watchdog/machzwd.c

@@ -141,7 +141,7 @@ static unsigned long next_heartbeat = 0;
 #ifndef ZF_DEBUG
 #ifndef ZF_DEBUG
 #	define dprintk(format, args...)
 #	define dprintk(format, args...)
 #else
 #else
-#	define dprintk(format, args...) printk(KERN_DEBUG PFX ":%s:%d: " format, __FUNCTION__, __LINE__ , ## args)
+#	define dprintk(format, args...) printk(KERN_DEBUG PFX ":%s:%d: " format, __func__, __LINE__ , ## args)
 #endif
 #endif
 
 
 
 

+ 2 - 2
drivers/watchdog/mtx-1_wdt.c

@@ -59,9 +59,9 @@ static int ticks = 100 * HZ;
 
 
 static struct {
 static struct {
 	struct completion stop;
 	struct completion stop;
-	volatile int running;
+	int running;
 	struct timer_list timer;
 	struct timer_list timer;
-	volatile int queue;
+	int queue;
 	int default_ticks;
 	int default_ticks;
 	unsigned long inuse;
 	unsigned long inuse;
 	unsigned gpio;
 	unsigned gpio;

+ 2 - 2
drivers/watchdog/pcwd_usb.c

@@ -179,11 +179,11 @@ static void usb_pcwd_intr_done(struct urb *urb)
 	case -ENOENT:
 	case -ENOENT:
 	case -ESHUTDOWN:
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		dbg("%s - urb shutting down with status: %d", __func__, urb->status);
 		return;
 		return;
 	/* -EPIPE:  should clear the halt */
 	/* -EPIPE:  should clear the halt */
 	default:		/* error */
 	default:		/* error */
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+		dbg("%s - nonzero urb status received: %d", __func__, urb->status);
 		goto resubmit;
 		goto resubmit;
 	}
 	}
 
 

+ 4 - 4
drivers/watchdog/s3c2410_wdt.c

@@ -144,7 +144,7 @@ static int s3c2410wdt_start(void)
 	}
 	}
 
 
 	DBG("%s: wdt_count=0x%08x, wtcon=%08lx\n",
 	DBG("%s: wdt_count=0x%08x, wtcon=%08lx\n",
-	    __FUNCTION__, wdt_count, wtcon);
+	    __func__, wdt_count, wtcon);
 
 
 	writel(wdt_count, wdt_base + S3C2410_WTDAT);
 	writel(wdt_count, wdt_base + S3C2410_WTDAT);
 	writel(wdt_count, wdt_base + S3C2410_WTCNT);
 	writel(wdt_count, wdt_base + S3C2410_WTCNT);
@@ -167,7 +167,7 @@ static int s3c2410wdt_set_heartbeat(int timeout)
 	count = timeout * freq;
 	count = timeout * freq;
 
 
 	DBG("%s: count=%d, timeout=%d, freq=%d\n",
 	DBG("%s: count=%d, timeout=%d, freq=%d\n",
-	    __FUNCTION__, count, timeout, freq);
+	    __func__, count, timeout, freq);
 
 
 	/* if the count is bigger than the watchdog register,
 	/* if the count is bigger than the watchdog register,
 	   then work out what we need to do (and if) we can
 	   then work out what we need to do (and if) we can
@@ -189,7 +189,7 @@ static int s3c2410wdt_set_heartbeat(int timeout)
 	tmr_margin = timeout;
 	tmr_margin = timeout;
 
 
 	DBG("%s: timeout=%d, divisor=%d, count=%d (%08x)\n",
 	DBG("%s: timeout=%d, divisor=%d, count=%d (%08x)\n",
-	    __FUNCTION__, timeout, divisor, count, count/divisor);
+	    __func__, timeout, divisor, count, count/divisor);
 
 
 	count /= divisor;
 	count /= divisor;
 	wdt_count = count;
 	wdt_count = count;
@@ -355,7 +355,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
 	int ret;
 	int ret;
 	int size;
 	int size;
 
 
-	DBG("%s: probe=%p\n", __FUNCTION__, pdev);
+	DBG("%s: probe=%p\n", __func__, pdev);
 
 
 	dev = &pdev->dev;
 	dev = &pdev->dev;
 	wdt_dev = &pdev->dev;
 	wdt_dev = &pdev->dev;

+ 1 - 1
drivers/watchdog/shwdt.c

@@ -298,7 +298,7 @@ static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
 	if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
 	if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
 			       PAGE_SIZE, vma->vm_page_prot)) {
 			       PAGE_SIZE, vma->vm_page_prot)) {
 		printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
 		printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
-		       __FUNCTION__);
+		       __func__);
 		return -EAGAIN;
 		return -EAGAIN;
 	}
 	}
 
 

+ 4 - 5
fs/ocfs2/cluster/tcp.c

@@ -451,9 +451,9 @@ static void o2net_set_nn_state(struct o2net_node *nn,
 		/* delay if we're withing a RECONNECT_DELAY of the
 		/* delay if we're withing a RECONNECT_DELAY of the
 		 * last attempt */
 		 * last attempt */
 		delay = (nn->nn_last_connect_attempt +
 		delay = (nn->nn_last_connect_attempt +
-			 msecs_to_jiffies(o2net_reconnect_delay(sc->sc_node)))
+			 msecs_to_jiffies(o2net_reconnect_delay(NULL)))
 			- jiffies;
 			- jiffies;
-		if (delay > msecs_to_jiffies(o2net_reconnect_delay(sc->sc_node)))
+		if (delay > msecs_to_jiffies(o2net_reconnect_delay(NULL)))
 			delay = 0;
 			delay = 0;
 		mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay);
 		mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay);
 		queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay);
 		queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay);
@@ -1552,12 +1552,11 @@ static void o2net_connect_expired(struct work_struct *work)
 
 
 	spin_lock(&nn->nn_lock);
 	spin_lock(&nn->nn_lock);
 	if (!nn->nn_sc_valid) {
 	if (!nn->nn_sc_valid) {
-		struct o2nm_node *node = nn->nn_sc->sc_node;
 		mlog(ML_ERROR, "no connection established with node %u after "
 		mlog(ML_ERROR, "no connection established with node %u after "
 		     "%u.%u seconds, giving up and returning errors.\n",
 		     "%u.%u seconds, giving up and returning errors.\n",
 		     o2net_num_from_nn(nn),
 		     o2net_num_from_nn(nn),
-		     o2net_idle_timeout(node) / 1000,
-		     o2net_idle_timeout(node) % 1000);
+		     o2net_idle_timeout(NULL) / 1000,
+		     o2net_idle_timeout(NULL) % 1000);
 
 
 		o2net_set_nn_state(nn, NULL, 0, -ENOTCONN);
 		o2net_set_nn_state(nn, NULL, 0, -ENOTCONN);
 	}
 	}

+ 12 - 9
fs/ocfs2/dlm/dlmcommon.h

@@ -176,6 +176,7 @@ struct dlm_mig_lockres_priv
 {
 {
 	struct dlm_lock_resource *lockres;
 	struct dlm_lock_resource *lockres;
 	u8 real_master;
 	u8 real_master;
+	u8 extra_ref;
 };
 };
 
 
 struct dlm_assert_master_priv
 struct dlm_assert_master_priv
@@ -602,17 +603,19 @@ enum dlm_query_join_response_code {
 	JOIN_PROTOCOL_MISMATCH,
 	JOIN_PROTOCOL_MISMATCH,
 };
 };
 
 
+struct dlm_query_join_packet {
+	u8 code;	/* Response code.  dlm_minor and fs_minor
+			   are only valid if this is JOIN_OK */
+	u8 dlm_minor;	/* The minor version of the protocol the
+			   dlm is speaking. */
+	u8 fs_minor;	/* The minor version of the protocol the
+			   filesystem is speaking. */
+	u8 reserved;
+};
+
 union dlm_query_join_response {
 union dlm_query_join_response {
 	u32 intval;
 	u32 intval;
-	struct {
-		u8 code;	/* Response code.  dlm_minor and fs_minor
-				   are only valid if this is JOIN_OK */
-		u8 dlm_minor;	/* The minor version of the protocol the
-				   dlm is speaking. */
-		u8 fs_minor;	/* The minor version of the protocol the
-				   filesystem is speaking. */
-		u8 reserved;
-	} packet;
+	struct dlm_query_join_packet packet;
 };
 };
 
 
 struct dlm_lock_request
 struct dlm_lock_request

+ 1 - 1
fs/ocfs2/dlm/dlmconvert.c

@@ -487,7 +487,7 @@ int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data,
 			       "cookie=%u:%llu\n",
 			       "cookie=%u:%llu\n",
 		     dlm_get_lock_cookie_node(be64_to_cpu(cnv->cookie)),
 		     dlm_get_lock_cookie_node(be64_to_cpu(cnv->cookie)),
 		     dlm_get_lock_cookie_seq(be64_to_cpu(cnv->cookie)));
 		     dlm_get_lock_cookie_seq(be64_to_cpu(cnv->cookie)));
-		__dlm_print_one_lock_resource(res);
+		dlm_print_one_lock_resource(res);
 		goto leave;
 		goto leave;
 	}
 	}
 
 

+ 66 - 37
fs/ocfs2/dlm/dlmdomain.c

@@ -713,14 +713,46 @@ static int dlm_query_join_proto_check(char *proto_type, int node,
 	return rc;
 	return rc;
 }
 }
 
 
+/*
+ * struct dlm_query_join_packet is made up of four one-byte fields.  They
+ * are effectively in big-endian order already.  However, little-endian
+ * machines swap them before putting the packet on the wire (because
+ * query_join's response is a status, and that status is treated as a u32
+ * on the wire).  Thus, a big-endian and little-endian machines will treat
+ * this structure differently.
+ *
+ * The solution is to have little-endian machines swap the structure when
+ * converting from the structure to the u32 representation.  This will
+ * result in the structure having the correct format on the wire no matter
+ * the host endian format.
+ */
+static void dlm_query_join_packet_to_wire(struct dlm_query_join_packet *packet,
+					  u32 *wire)
+{
+	union dlm_query_join_response response;
+
+	response.packet = *packet;
+	*wire = cpu_to_be32(response.intval);
+}
+
+static void dlm_query_join_wire_to_packet(u32 wire,
+					  struct dlm_query_join_packet *packet)
+{
+	union dlm_query_join_response response;
+
+	response.intval = cpu_to_be32(wire);
+	*packet = response.packet;
+}
+
 static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
 static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
 				  void **ret_data)
 				  void **ret_data)
 {
 {
 	struct dlm_query_join_request *query;
 	struct dlm_query_join_request *query;
-	union dlm_query_join_response response = {
-		.packet.code = JOIN_DISALLOW,
+	struct dlm_query_join_packet packet = {
+		.code = JOIN_DISALLOW,
 	};
 	};
 	struct dlm_ctxt *dlm = NULL;
 	struct dlm_ctxt *dlm = NULL;
+	u32 response;
 	u8 nodenum;
 	u8 nodenum;
 
 
 	query = (struct dlm_query_join_request *) msg->buf;
 	query = (struct dlm_query_join_request *) msg->buf;
@@ -737,11 +769,11 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
 		mlog(0, "node %u is not in our live map yet\n",
 		mlog(0, "node %u is not in our live map yet\n",
 		     query->node_idx);
 		     query->node_idx);
 
 
-		response.packet.code = JOIN_DISALLOW;
+		packet.code = JOIN_DISALLOW;
 		goto respond;
 		goto respond;
 	}
 	}
 
 
-	response.packet.code = JOIN_OK_NO_MAP;
+	packet.code = JOIN_OK_NO_MAP;
 
 
 	spin_lock(&dlm_domain_lock);
 	spin_lock(&dlm_domain_lock);
 	dlm = __dlm_lookup_domain_full(query->domain, query->name_len);
 	dlm = __dlm_lookup_domain_full(query->domain, query->name_len);
@@ -760,7 +792,7 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
 				mlog(0, "disallow join as node %u does not "
 				mlog(0, "disallow join as node %u does not "
 				     "have node %u in its nodemap\n",
 				     "have node %u in its nodemap\n",
 				     query->node_idx, nodenum);
 				     query->node_idx, nodenum);
-				response.packet.code = JOIN_DISALLOW;
+				packet.code = JOIN_DISALLOW;
 				goto unlock_respond;
 				goto unlock_respond;
 			}
 			}
 		}
 		}
@@ -780,23 +812,23 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
 			/*If this is a brand new context and we
 			/*If this is a brand new context and we
 			 * haven't started our join process yet, then
 			 * haven't started our join process yet, then
 			 * the other node won the race. */
 			 * the other node won the race. */
-			response.packet.code = JOIN_OK_NO_MAP;
+			packet.code = JOIN_OK_NO_MAP;
 		} else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) {
 		} else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) {
 			/* Disallow parallel joins. */
 			/* Disallow parallel joins. */
-			response.packet.code = JOIN_DISALLOW;
+			packet.code = JOIN_DISALLOW;
 		} else if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) {
 		} else if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) {
 			mlog(0, "node %u trying to join, but recovery "
 			mlog(0, "node %u trying to join, but recovery "
 			     "is ongoing.\n", bit);
 			     "is ongoing.\n", bit);
-			response.packet.code = JOIN_DISALLOW;
+			packet.code = JOIN_DISALLOW;
 		} else if (test_bit(bit, dlm->recovery_map)) {
 		} else if (test_bit(bit, dlm->recovery_map)) {
 			mlog(0, "node %u trying to join, but it "
 			mlog(0, "node %u trying to join, but it "
 			     "still needs recovery.\n", bit);
 			     "still needs recovery.\n", bit);
-			response.packet.code = JOIN_DISALLOW;
+			packet.code = JOIN_DISALLOW;
 		} else if (test_bit(bit, dlm->domain_map)) {
 		} else if (test_bit(bit, dlm->domain_map)) {
 			mlog(0, "node %u trying to join, but it "
 			mlog(0, "node %u trying to join, but it "
 			     "is still in the domain! needs recovery?\n",
 			     "is still in the domain! needs recovery?\n",
 			     bit);
 			     bit);
-			response.packet.code = JOIN_DISALLOW;
+			packet.code = JOIN_DISALLOW;
 		} else {
 		} else {
 			/* Alright we're fully a part of this domain
 			/* Alright we're fully a part of this domain
 			 * so we keep some state as to who's joining
 			 * so we keep some state as to who's joining
@@ -807,19 +839,15 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
 			if (dlm_query_join_proto_check("DLM", bit,
 			if (dlm_query_join_proto_check("DLM", bit,
 						       &dlm->dlm_locking_proto,
 						       &dlm->dlm_locking_proto,
 						       &query->dlm_proto)) {
 						       &query->dlm_proto)) {
-				response.packet.code =
-					JOIN_PROTOCOL_MISMATCH;
+				packet.code = JOIN_PROTOCOL_MISMATCH;
 			} else if (dlm_query_join_proto_check("fs", bit,
 			} else if (dlm_query_join_proto_check("fs", bit,
 							      &dlm->fs_locking_proto,
 							      &dlm->fs_locking_proto,
 							      &query->fs_proto)) {
 							      &query->fs_proto)) {
-				response.packet.code =
-					JOIN_PROTOCOL_MISMATCH;
+				packet.code = JOIN_PROTOCOL_MISMATCH;
 			} else {
 			} else {
-				response.packet.dlm_minor =
-					query->dlm_proto.pv_minor;
-				response.packet.fs_minor =
-					query->fs_proto.pv_minor;
-				response.packet.code = JOIN_OK;
+				packet.dlm_minor = query->dlm_proto.pv_minor;
+				packet.fs_minor = query->fs_proto.pv_minor;
+				packet.code = JOIN_OK;
 				__dlm_set_joining_node(dlm, query->node_idx);
 				__dlm_set_joining_node(dlm, query->node_idx);
 			}
 			}
 		}
 		}
@@ -830,9 +858,10 @@ unlock_respond:
 	spin_unlock(&dlm_domain_lock);
 	spin_unlock(&dlm_domain_lock);
 
 
 respond:
 respond:
-	mlog(0, "We respond with %u\n", response.packet.code);
+	mlog(0, "We respond with %u\n", packet.code);
 
 
-	return response.intval;
+	dlm_query_join_packet_to_wire(&packet, &response);
+	return response;
 }
 }
 
 
 static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,
 static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,
@@ -937,7 +966,7 @@ static int dlm_send_join_cancels(struct dlm_ctxt *dlm,
 			 sizeof(unsigned long))) {
 			 sizeof(unsigned long))) {
 		mlog(ML_ERROR,
 		mlog(ML_ERROR,
 		     "map_size %u != BITS_TO_LONGS(O2NM_MAX_NODES) %u\n",
 		     "map_size %u != BITS_TO_LONGS(O2NM_MAX_NODES) %u\n",
-		     map_size, BITS_TO_LONGS(O2NM_MAX_NODES));
+		     map_size, (unsigned)BITS_TO_LONGS(O2NM_MAX_NODES));
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
@@ -968,7 +997,8 @@ static int dlm_request_join(struct dlm_ctxt *dlm,
 {
 {
 	int status;
 	int status;
 	struct dlm_query_join_request join_msg;
 	struct dlm_query_join_request join_msg;
-	union dlm_query_join_response join_resp;
+	struct dlm_query_join_packet packet;
+	u32 join_resp;
 
 
 	mlog(0, "querying node %d\n", node);
 	mlog(0, "querying node %d\n", node);
 
 
@@ -984,11 +1014,12 @@ static int dlm_request_join(struct dlm_ctxt *dlm,
 
 
 	status = o2net_send_message(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY, &join_msg,
 	status = o2net_send_message(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY, &join_msg,
 				    sizeof(join_msg), node,
 				    sizeof(join_msg), node,
-				    &join_resp.intval);
+				    &join_resp);
 	if (status < 0 && status != -ENOPROTOOPT) {
 	if (status < 0 && status != -ENOPROTOOPT) {
 		mlog_errno(status);
 		mlog_errno(status);
 		goto bail;
 		goto bail;
 	}
 	}
+	dlm_query_join_wire_to_packet(join_resp, &packet);
 
 
 	/* -ENOPROTOOPT from the net code means the other side isn't
 	/* -ENOPROTOOPT from the net code means the other side isn't
 	    listening for our message type -- that's fine, it means
 	    listening for our message type -- that's fine, it means
@@ -997,10 +1028,10 @@ static int dlm_request_join(struct dlm_ctxt *dlm,
 	if (status == -ENOPROTOOPT) {
 	if (status == -ENOPROTOOPT) {
 		status = 0;
 		status = 0;
 		*response = JOIN_OK_NO_MAP;
 		*response = JOIN_OK_NO_MAP;
-	} else if (join_resp.packet.code == JOIN_DISALLOW ||
-		   join_resp.packet.code == JOIN_OK_NO_MAP) {
-		*response = join_resp.packet.code;
-	} else if (join_resp.packet.code == JOIN_PROTOCOL_MISMATCH) {
+	} else if (packet.code == JOIN_DISALLOW ||
+		   packet.code == JOIN_OK_NO_MAP) {
+		*response = packet.code;
+	} else if (packet.code == JOIN_PROTOCOL_MISMATCH) {
 		mlog(ML_NOTICE,
 		mlog(ML_NOTICE,
 		     "This node requested DLM locking protocol %u.%u and "
 		     "This node requested DLM locking protocol %u.%u and "
 		     "filesystem locking protocol %u.%u.  At least one of "
 		     "filesystem locking protocol %u.%u.  At least one of "
@@ -1012,14 +1043,12 @@ static int dlm_request_join(struct dlm_ctxt *dlm,
 		     dlm->fs_locking_proto.pv_minor,
 		     dlm->fs_locking_proto.pv_minor,
 		     node);
 		     node);
 		status = -EPROTO;
 		status = -EPROTO;
-		*response = join_resp.packet.code;
-	} else if (join_resp.packet.code == JOIN_OK) {
-		*response = join_resp.packet.code;
+		*response = packet.code;
+	} else if (packet.code == JOIN_OK) {
+		*response = packet.code;
 		/* Use the same locking protocol as the remote node */
 		/* Use the same locking protocol as the remote node */
-		dlm->dlm_locking_proto.pv_minor =
-			join_resp.packet.dlm_minor;
-		dlm->fs_locking_proto.pv_minor =
-			join_resp.packet.fs_minor;
+		dlm->dlm_locking_proto.pv_minor = packet.dlm_minor;
+		dlm->fs_locking_proto.pv_minor = packet.fs_minor;
 		mlog(0,
 		mlog(0,
 		     "Node %d responds JOIN_OK with DLM locking protocol "
 		     "Node %d responds JOIN_OK with DLM locking protocol "
 		     "%u.%u and fs locking protocol %u.%u\n",
 		     "%u.%u and fs locking protocol %u.%u\n",
@@ -1031,11 +1060,11 @@ static int dlm_request_join(struct dlm_ctxt *dlm,
 	} else {
 	} else {
 		status = -EINVAL;
 		status = -EINVAL;
 		mlog(ML_ERROR, "invalid response %d from node %u\n",
 		mlog(ML_ERROR, "invalid response %d from node %u\n",
-		     join_resp.packet.code, node);
+		     packet.code, node);
 	}
 	}
 
 
 	mlog(0, "status %d, node %d response is %d\n", status, node,
 	mlog(0, "status %d, node %d response is %d\n", status, node,
-		  *response);
+	     *response);
 
 
 bail:
 bail:
 	return status;
 	return status;

+ 15 - 3
fs/ocfs2/dlm/dlmmaster.c

@@ -1663,7 +1663,12 @@ way_up_top:
 		dlm_put_mle(tmpmle);
 		dlm_put_mle(tmpmle);
 	}
 	}
 send_response:
 send_response:
-
+	/*
+	 * __dlm_lookup_lockres() grabbed a reference to this lockres.
+	 * The reference is released by dlm_assert_master_worker() under
+	 * the call to dlm_dispatch_assert_master().  If
+	 * dlm_assert_master_worker() isn't called, we drop it here.
+	 */
 	if (dispatch_assert) {
 	if (dispatch_assert) {
 		if (response != DLM_MASTER_RESP_YES)
 		if (response != DLM_MASTER_RESP_YES)
 			mlog(ML_ERROR, "invalid response %d\n", response);
 			mlog(ML_ERROR, "invalid response %d\n", response);
@@ -1678,7 +1683,11 @@ send_response:
 		if (ret < 0) {
 		if (ret < 0) {
 			mlog(ML_ERROR, "failed to dispatch assert master work\n");
 			mlog(ML_ERROR, "failed to dispatch assert master work\n");
 			response = DLM_MASTER_RESP_ERROR;
 			response = DLM_MASTER_RESP_ERROR;
+			dlm_lockres_put(res);
 		}
 		}
+	} else {
+		if (res)
+			dlm_lockres_put(res);
 	}
 	}
 
 
 	dlm_put(dlm);
 	dlm_put(dlm);
@@ -2348,7 +2357,7 @@ int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
 			mlog(ML_ERROR, "%s:%.*s: node %u trying to drop ref "
 			mlog(ML_ERROR, "%s:%.*s: node %u trying to drop ref "
 		     	"but it is already dropped!\n", dlm->name,
 		     	"but it is already dropped!\n", dlm->name,
 		     	res->lockname.len, res->lockname.name, node);
 		     	res->lockname.len, res->lockname.name, node);
-			__dlm_print_one_lock_resource(res);
+			dlm_print_one_lock_resource(res);
 		}
 		}
 		ret = 0;
 		ret = 0;
 		goto done;
 		goto done;
@@ -2408,7 +2417,7 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data)
 		mlog(ML_ERROR, "%s:%.*s: node %u trying to drop ref "
 		mlog(ML_ERROR, "%s:%.*s: node %u trying to drop ref "
 		     "but it is already dropped!\n", dlm->name,
 		     "but it is already dropped!\n", dlm->name,
 		     res->lockname.len, res->lockname.name, node);
 		     res->lockname.len, res->lockname.name, node);
-		__dlm_print_one_lock_resource(res);
+		dlm_print_one_lock_resource(res);
 	}
 	}
 
 
 	dlm_lockres_put(res);
 	dlm_lockres_put(res);
@@ -2933,6 +2942,9 @@ static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
 				dlm_lockres_clear_refmap_bit(lock->ml.node, res);
 				dlm_lockres_clear_refmap_bit(lock->ml.node, res);
 				list_del_init(&lock->list);
 				list_del_init(&lock->list);
 				dlm_lock_put(lock);
 				dlm_lock_put(lock);
+				/* In a normal unlock, we would have added a
+				 * DLM_UNLOCK_FREE_LOCK action. Force it. */
+				dlm_lock_put(lock);
 			}
 			}
 		}
 		}
 		queue++;
 		queue++;

+ 47 - 10
fs/ocfs2/dlm/dlmrecovery.c

@@ -519,9 +519,9 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm)
 	return 0;
 	return 0;
 
 
 master_here:
 master_here:
-	mlog(0, "(%d) mastering recovery of %s:%u here(this=%u)!\n",
-	     task_pid_nr(dlm->dlm_reco_thread_task),
-	     dlm->name, dlm->reco.dead_node, dlm->node_num);
+	mlog(ML_NOTICE, "(%d) Node %u is the Recovery Master for the Dead Node "
+	     "%u for Domain %s\n", task_pid_nr(dlm->dlm_reco_thread_task),
+	     dlm->node_num, dlm->reco.dead_node, dlm->name);
 
 
 	status = dlm_remaster_locks(dlm, dlm->reco.dead_node);
 	status = dlm_remaster_locks(dlm, dlm->reco.dead_node);
 	if (status < 0) {
 	if (status < 0) {
@@ -1191,7 +1191,7 @@ static int dlm_add_lock_to_array(struct dlm_lock *lock,
 			    (ml->type == LKM_EXMODE ||
 			    (ml->type == LKM_EXMODE ||
 			     memcmp(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN))) {
 			     memcmp(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN))) {
 				mlog(ML_ERROR, "mismatched lvbs!\n");
 				mlog(ML_ERROR, "mismatched lvbs!\n");
-				__dlm_print_one_lock_resource(lock->lockres);
+				dlm_print_one_lock_resource(lock->lockres);
 				BUG();
 				BUG();
 			}
 			}
 			memcpy(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN);
 			memcpy(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN);
@@ -1327,6 +1327,7 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
 		(struct dlm_migratable_lockres *)msg->buf;
 		(struct dlm_migratable_lockres *)msg->buf;
 	int ret = 0;
 	int ret = 0;
 	u8 real_master;
 	u8 real_master;
+	u8 extra_refs = 0;
 	char *buf = NULL;
 	char *buf = NULL;
 	struct dlm_work_item *item = NULL;
 	struct dlm_work_item *item = NULL;
 	struct dlm_lock_resource *res = NULL;
 	struct dlm_lock_resource *res = NULL;
@@ -1404,16 +1405,28 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
 		__dlm_insert_lockres(dlm, res);
 		__dlm_insert_lockres(dlm, res);
 		spin_unlock(&dlm->spinlock);
 		spin_unlock(&dlm->spinlock);
 
 
+		/* Add an extra ref for this lock-less lockres lest the
+		 * dlm_thread purges it before we get the chance to add
+		 * locks to it */
+		dlm_lockres_get(res);
+
+		/* There are three refs that need to be put.
+		 * 1. Taken above.
+		 * 2. kref_init in dlm_new_lockres()->dlm_init_lockres().
+		 * 3. dlm_lookup_lockres()
+		 * The first one is handled at the end of this function. The
+		 * other two are handled in the worker thread after locks have
+		 * been attached. Yes, we don't wait for purge time to match
+		 * kref_init. The lockres will still have atleast one ref
+		 * added because it is in the hash __dlm_insert_lockres() */
+		extra_refs++;
+
 		/* now that the new lockres is inserted,
 		/* now that the new lockres is inserted,
 		 * make it usable by other processes */
 		 * make it usable by other processes */
 		spin_lock(&res->spinlock);
 		spin_lock(&res->spinlock);
 		res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
 		res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
 		spin_unlock(&res->spinlock);
 		spin_unlock(&res->spinlock);
 		wake_up(&res->wq);
 		wake_up(&res->wq);
-
-		/* add an extra ref for just-allocated lockres 
-		 * otherwise the lockres will be purged immediately */
-		dlm_lockres_get(res);
 	}
 	}
 
 
 	/* at this point we have allocated everything we need,
 	/* at this point we have allocated everything we need,
@@ -1443,12 +1456,17 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
 	dlm_init_work_item(dlm, item, dlm_mig_lockres_worker, buf);
 	dlm_init_work_item(dlm, item, dlm_mig_lockres_worker, buf);
 	item->u.ml.lockres = res; /* already have a ref */
 	item->u.ml.lockres = res; /* already have a ref */
 	item->u.ml.real_master = real_master;
 	item->u.ml.real_master = real_master;
+	item->u.ml.extra_ref = extra_refs;
 	spin_lock(&dlm->work_lock);
 	spin_lock(&dlm->work_lock);
 	list_add_tail(&item->list, &dlm->work_list);
 	list_add_tail(&item->list, &dlm->work_list);
 	spin_unlock(&dlm->work_lock);
 	spin_unlock(&dlm->work_lock);
 	queue_work(dlm->dlm_worker, &dlm->dispatched_work);
 	queue_work(dlm->dlm_worker, &dlm->dispatched_work);
 
 
 leave:
 leave:
+	/* One extra ref taken needs to be put here */
+	if (extra_refs)
+		dlm_lockres_put(res);
+
 	dlm_put(dlm);
 	dlm_put(dlm);
 	if (ret < 0) {
 	if (ret < 0) {
 		if (buf)
 		if (buf)
@@ -1464,17 +1482,19 @@ leave:
 
 
 static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data)
 static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data)
 {
 {
-	struct dlm_ctxt *dlm = data;
+	struct dlm_ctxt *dlm;
 	struct dlm_migratable_lockres *mres;
 	struct dlm_migratable_lockres *mres;
 	int ret = 0;
 	int ret = 0;
 	struct dlm_lock_resource *res;
 	struct dlm_lock_resource *res;
 	u8 real_master;
 	u8 real_master;
+	u8 extra_ref;
 
 
 	dlm = item->dlm;
 	dlm = item->dlm;
 	mres = (struct dlm_migratable_lockres *)data;
 	mres = (struct dlm_migratable_lockres *)data;
 
 
 	res = item->u.ml.lockres;
 	res = item->u.ml.lockres;
 	real_master = item->u.ml.real_master;
 	real_master = item->u.ml.real_master;
+	extra_ref = item->u.ml.extra_ref;
 
 
 	if (real_master == DLM_LOCK_RES_OWNER_UNKNOWN) {
 	if (real_master == DLM_LOCK_RES_OWNER_UNKNOWN) {
 		/* this case is super-rare. only occurs if
 		/* this case is super-rare. only occurs if
@@ -1517,6 +1537,12 @@ again:
 	}
 	}
 
 
 leave:
 leave:
+	/* See comment in dlm_mig_lockres_handler() */
+	if (res) {
+		if (extra_ref)
+			dlm_lockres_put(res);
+		dlm_lockres_put(res);
+	}
 	kfree(data);
 	kfree(data);
 	mlog_exit(ret);
 	mlog_exit(ret);
 }
 }
@@ -1644,7 +1670,8 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
 				/* retry!? */
 				/* retry!? */
 				BUG();
 				BUG();
 			}
 			}
-		}
+		} else /* put.. incase we are not the master */
+			dlm_lockres_put(res);
 		spin_unlock(&res->spinlock);
 		spin_unlock(&res->spinlock);
 	}
 	}
 	spin_unlock(&dlm->spinlock);
 	spin_unlock(&dlm->spinlock);
@@ -1921,6 +1948,7 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm,
 		     "Recovering res %s:%.*s, is already on recovery list!\n",
 		     "Recovering res %s:%.*s, is already on recovery list!\n",
 		     dlm->name, res->lockname.len, res->lockname.name);
 		     dlm->name, res->lockname.len, res->lockname.name);
 		list_del_init(&res->recovering);
 		list_del_init(&res->recovering);
+		dlm_lockres_put(res);
 	}
 	}
 	/* We need to hold a reference while on the recovery list */
 	/* We need to hold a reference while on the recovery list */
 	dlm_lockres_get(res);
 	dlm_lockres_get(res);
@@ -2130,11 +2158,16 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
 	assert_spin_locked(&dlm->spinlock);
 	assert_spin_locked(&dlm->spinlock);
 	assert_spin_locked(&res->spinlock);
 	assert_spin_locked(&res->spinlock);
 
 
+	/* We do two dlm_lock_put(). One for removing from list and the other is
+	 * to force the DLM_UNLOCK_FREE_LOCK action so as to free the locks */
+
 	/* TODO: check pending_asts, pending_basts here */
 	/* TODO: check pending_asts, pending_basts here */
 	list_for_each_entry_safe(lock, next, &res->granted, list) {
 	list_for_each_entry_safe(lock, next, &res->granted, list) {
 		if (lock->ml.node == dead_node) {
 		if (lock->ml.node == dead_node) {
 			list_del_init(&lock->list);
 			list_del_init(&lock->list);
 			dlm_lock_put(lock);
 			dlm_lock_put(lock);
+			/* Can't schedule DLM_UNLOCK_FREE_LOCK - do manually */
+			dlm_lock_put(lock);
 			freed++;
 			freed++;
 		}
 		}
 	}
 	}
@@ -2142,6 +2175,8 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
 		if (lock->ml.node == dead_node) {
 		if (lock->ml.node == dead_node) {
 			list_del_init(&lock->list);
 			list_del_init(&lock->list);
 			dlm_lock_put(lock);
 			dlm_lock_put(lock);
+			/* Can't schedule DLM_UNLOCK_FREE_LOCK - do manually */
+			dlm_lock_put(lock);
 			freed++;
 			freed++;
 		}
 		}
 	}
 	}
@@ -2149,6 +2184,8 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
 		if (lock->ml.node == dead_node) {
 		if (lock->ml.node == dead_node) {
 			list_del_init(&lock->list);
 			list_del_init(&lock->list);
 			dlm_lock_put(lock);
 			dlm_lock_put(lock);
+			/* Can't schedule DLM_UNLOCK_FREE_LOCK - do manually */
+			dlm_lock_put(lock);
 			freed++;
 			freed++;
 		}
 		}
 	}
 	}

+ 4 - 2
fs/ocfs2/dlm/dlmthread.c

@@ -176,12 +176,14 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm,
 	     res->lockname.name, master);
 	     res->lockname.name, master);
 
 
 	if (!master) {
 	if (!master) {
+		/* drop spinlock...  retake below */
+		spin_unlock(&dlm->spinlock);
+
 		spin_lock(&res->spinlock);
 		spin_lock(&res->spinlock);
 		/* This ensures that clear refmap is sent after the set */
 		/* This ensures that clear refmap is sent after the set */
 		__dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG);
 		__dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG);
 		spin_unlock(&res->spinlock);
 		spin_unlock(&res->spinlock);
-		/* drop spinlock to do messaging, retake below */
-		spin_unlock(&dlm->spinlock);
+
 		/* clear our bit from the master's refmap, ignore errors */
 		/* clear our bit from the master's refmap, ignore errors */
 		ret = dlm_drop_lockres_ref(dlm, res);
 		ret = dlm_drop_lockres_ref(dlm, res);
 		if (ret < 0) {
 		if (ret < 0) {

+ 1 - 1
fs/ocfs2/dlmglue.c

@@ -2409,7 +2409,7 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct seq_operations ocfs2_dlm_seq_ops = {
+static const struct seq_operations ocfs2_dlm_seq_ops = {
 	.start =	ocfs2_dlm_seq_start,
 	.start =	ocfs2_dlm_seq_start,
 	.stop =		ocfs2_dlm_seq_stop,
 	.stop =		ocfs2_dlm_seq_stop,
 	.next =		ocfs2_dlm_seq_next,
 	.next =		ocfs2_dlm_seq_next,

+ 1 - 1
fs/ocfs2/resize.c

@@ -597,7 +597,7 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
 		memset(cr, 0, sizeof(struct ocfs2_chain_rec));
 		memset(cr, 0, sizeof(struct ocfs2_chain_rec));
 	}
 	}
 
 
-	cr->c_blkno = le64_to_cpu(input->group);
+	cr->c_blkno = cpu_to_le64(input->group);
 	le32_add_cpu(&cr->c_total, input->clusters * cl_bpc);
 	le32_add_cpu(&cr->c_total, input->clusters * cl_bpc);
 	le32_add_cpu(&cr->c_free, input->frees * cl_bpc);
 	le32_add_cpu(&cr->c_free, input->frees * cl_bpc);
 
 

+ 2 - 3
include/asm-x86/pgtable_32.h

@@ -26,10 +26,9 @@ struct mm_struct;
 struct vm_area_struct;
 struct vm_area_struct;
 
 
 extern pgd_t swapper_pg_dir[1024];
 extern pgd_t swapper_pg_dir[1024];
-extern struct kmem_cache *pmd_cache;
-void check_pgt_cache(void);
 
 
-static inline void pgtable_cache_init(void) {}
+static inline void pgtable_cache_init(void) { }
+static inline void check_pgt_cache(void) { }
 void paging_init(void);
 void paging_init(void);
 
 
 
 

+ 1 - 1
include/crypto/internal/skcipher.h

@@ -68,7 +68,7 @@ void skcipher_geniv_exit(struct crypto_tfm *tfm);
 int __init eseqiv_module_init(void);
 int __init eseqiv_module_init(void);
 void __exit eseqiv_module_exit(void);
 void __exit eseqiv_module_exit(void);
 int __init chainiv_module_init(void);
 int __init chainiv_module_init(void);
-void __exit chainiv_module_exit(void);
+void chainiv_module_exit(void);
 
 
 static inline struct crypto_ablkcipher *skcipher_geniv_cipher(
 static inline struct crypto_ablkcipher *skcipher_geniv_cipher(
 	struct crypto_ablkcipher *geniv)
 	struct crypto_ablkcipher *geniv)

+ 23 - 0
include/linux/firmware.h

@@ -10,7 +10,10 @@ struct firmware {
 	size_t size;
 	size_t size;
 	u8 *data;
 	u8 *data;
 };
 };
+
 struct device;
 struct device;
+
+#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
 int request_firmware(const struct firmware **fw, const char *name,
 int request_firmware(const struct firmware **fw, const char *name,
 		     struct device *device);
 		     struct device *device);
 int request_firmware_nowait(
 int request_firmware_nowait(
@@ -19,4 +22,24 @@ int request_firmware_nowait(
 	void (*cont)(const struct firmware *fw, void *context));
 	void (*cont)(const struct firmware *fw, void *context));
 
 
 void release_firmware(const struct firmware *fw);
 void release_firmware(const struct firmware *fw);
+#else
+static inline int request_firmware(const struct firmware **fw,
+				   const char *name,
+				   struct device *device)
+{
+	return -EINVAL;
+}
+static inline int request_firmware_nowait(
+	struct module *module, int uevent,
+	const char *name, struct device *device, void *context,
+	void (*cont)(const struct firmware *fw, void *context))
+{
+	return -EINVAL;
+}
+
+static inline void release_firmware(const struct firmware *fw)
+{
+}
+#endif
+
 #endif
 #endif

+ 88 - 44
include/linux/memstick.h

@@ -22,6 +22,8 @@ struct ms_status_register {
 	unsigned char reserved;
 	unsigned char reserved;
 	unsigned char interrupt;
 	unsigned char interrupt;
 #define MEMSTICK_INT_CMDNAK             0x0001
 #define MEMSTICK_INT_CMDNAK             0x0001
+#define MEMSTICK_INT_IOREQ              0x0008
+#define MEMSTICK_INT_IOBREQ             0x0010
 #define MEMSTICK_INT_BREQ               0x0020
 #define MEMSTICK_INT_BREQ               0x0020
 #define MEMSTICK_INT_ERR                0x0040
 #define MEMSTICK_INT_ERR                0x0040
 #define MEMSTICK_INT_CED                0x0080
 #define MEMSTICK_INT_CED                0x0080
@@ -47,13 +49,17 @@ struct ms_status_register {
 
 
 struct ms_id_register {
 struct ms_id_register {
 	unsigned char type;
 	unsigned char type;
-	unsigned char reserved;
+	unsigned char if_mode;
 	unsigned char category;
 	unsigned char category;
 	unsigned char class;
 	unsigned char class;
 } __attribute__((packed));
 } __attribute__((packed));
 
 
 struct ms_param_register {
 struct ms_param_register {
 	unsigned char system;
 	unsigned char system;
+#define MEMSTICK_SYS_ATEN 0xc0
+#define MEMSTICK_SYS_BAMD 0x80
+#define MEMSTICK_SYS_PAM  0x08
+
 	unsigned char block_address_msb;
 	unsigned char block_address_msb;
 	unsigned short block_address;
 	unsigned short block_address;
 	unsigned char cp;
 	unsigned char cp;
@@ -90,16 +96,48 @@ struct ms_register {
 
 
 struct mspro_param_register {
 struct mspro_param_register {
 	unsigned char  system;
 	unsigned char  system;
+#define MEMSTICK_SYS_SERIAL 0x80
+#define MEMSTICK_SYS_PAR4   0x00
+#define MEMSTICK_SYS_PAR8   0x40
+
+	unsigned short data_count;
+	unsigned int   data_address;
+	unsigned char  tpc_param;
+} __attribute__((packed));
+
+struct mspro_io_info_register {
+	unsigned char version;
+	unsigned char io_category;
+	unsigned char current_req;
+	unsigned char card_opt_info;
+	unsigned char rdy_wait_time;
+} __attribute__((packed));
+
+struct mspro_io_func_register {
+	unsigned char func_enable;
+	unsigned char func_select;
+	unsigned char func_intmask;
+	unsigned char transfer_mode;
+} __attribute__((packed));
+
+struct mspro_io_cmd_register {
+	unsigned short tpc_param;
 	unsigned short data_count;
 	unsigned short data_count;
 	unsigned int   data_address;
 	unsigned int   data_address;
-	unsigned char  cmd_param;
 } __attribute__((packed));
 } __attribute__((packed));
 
 
 struct mspro_register {
 struct mspro_register {
-	struct ms_status_register    status;
-	struct ms_id_register        id;
-	unsigned char                reserved[8];
-	struct mspro_param_register  param;
+	struct ms_status_register     status;
+	struct ms_id_register         id;
+	unsigned char                 reserved0[8];
+	struct mspro_param_register   param;
+	unsigned char                 reserved1[8];
+	struct mspro_io_info_register io_info;
+	struct mspro_io_func_register io_func;
+	unsigned char                 reserved2[7];
+	struct mspro_io_cmd_register  io_cmd;
+	unsigned char                 io_int;
+	unsigned char                 io_int_func;
 } __attribute__((packed));
 } __attribute__((packed));
 
 
 struct ms_register_addr {
 struct ms_register_addr {
@@ -110,49 +148,55 @@ struct ms_register_addr {
 } __attribute__((packed));
 } __attribute__((packed));
 
 
 enum {
 enum {
+	MS_TPC_READ_MG_STATUS   = 0x01,
 	MS_TPC_READ_LONG_DATA   = 0x02,
 	MS_TPC_READ_LONG_DATA   = 0x02,
 	MS_TPC_READ_SHORT_DATA  = 0x03,
 	MS_TPC_READ_SHORT_DATA  = 0x03,
+	MS_TPC_READ_MG_DATA     = 0x03,
 	MS_TPC_READ_REG         = 0x04,
 	MS_TPC_READ_REG         = 0x04,
-	MS_TPC_READ_IO_DATA     = 0x05, /* unverified */
+	MS_TPC_READ_QUAD_DATA   = 0x05,
+	MS_TPC_READ_IO_DATA     = 0x05,
 	MS_TPC_GET_INT          = 0x07,
 	MS_TPC_GET_INT          = 0x07,
 	MS_TPC_SET_RW_REG_ADRS  = 0x08,
 	MS_TPC_SET_RW_REG_ADRS  = 0x08,
 	MS_TPC_EX_SET_CMD       = 0x09,
 	MS_TPC_EX_SET_CMD       = 0x09,
-	MS_TPC_WRITE_IO_DATA    = 0x0a, /* unverified */
+	MS_TPC_WRITE_QUAD_DATA  = 0x0a,
+	MS_TPC_WRITE_IO_DATA    = 0x0a,
 	MS_TPC_WRITE_REG        = 0x0b,
 	MS_TPC_WRITE_REG        = 0x0b,
 	MS_TPC_WRITE_SHORT_DATA = 0x0c,
 	MS_TPC_WRITE_SHORT_DATA = 0x0c,
+	MS_TPC_WRITE_MG_DATA    = 0x0c,
 	MS_TPC_WRITE_LONG_DATA  = 0x0d,
 	MS_TPC_WRITE_LONG_DATA  = 0x0d,
 	MS_TPC_SET_CMD          = 0x0e
 	MS_TPC_SET_CMD          = 0x0e
 };
 };
 
 
 enum {
 enum {
-	MS_CMD_BLOCK_END     = 0x33,
-	MS_CMD_RESET         = 0x3c,
-	MS_CMD_BLOCK_WRITE   = 0x55,
-	MS_CMD_SLEEP         = 0x5a,
-	MS_CMD_BLOCK_ERASE   = 0x99,
-	MS_CMD_BLOCK_READ    = 0xaa,
-	MS_CMD_CLEAR_BUF     = 0xc3,
-	MS_CMD_FLASH_STOP    = 0xcc,
-	MSPRO_CMD_FORMAT     = 0x10,
-	MSPRO_CMD_SLEEP      = 0x11,
-	MSPRO_CMD_READ_DATA  = 0x20,
-	MSPRO_CMD_WRITE_DATA = 0x21,
-	MSPRO_CMD_READ_ATRB  = 0x24,
-	MSPRO_CMD_STOP       = 0x25,
-	MSPRO_CMD_ERASE      = 0x26,
-	MSPRO_CMD_SET_IBA    = 0x46,
-	MSPRO_CMD_SET_IBD    = 0x47
-/*
-	MSPRO_CMD_RESET
-	MSPRO_CMD_WAKEUP
-	MSPRO_CMD_IN_IO_DATA
-	MSPRO_CMD_OUT_IO_DATA
-	MSPRO_CMD_READ_IO_ATRB
-	MSPRO_CMD_IN_IO_FIFO
-	MSPRO_CMD_OUT_IO_FIFO
-	MSPRO_CMD_IN_IOM
-	MSPRO_CMD_OUT_IOM
-*/
+	MS_CMD_BLOCK_END       = 0x33,
+	MS_CMD_RESET           = 0x3c,
+	MS_CMD_BLOCK_WRITE     = 0x55,
+	MS_CMD_SLEEP           = 0x5a,
+	MS_CMD_BLOCK_ERASE     = 0x99,
+	MS_CMD_BLOCK_READ      = 0xaa,
+	MS_CMD_CLEAR_BUF       = 0xc3,
+	MS_CMD_FLASH_STOP      = 0xcc,
+	MS_CMD_LOAD_ID         = 0x60,
+	MS_CMD_CMP_ICV         = 0x7f,
+	MSPRO_CMD_FORMAT       = 0x10,
+	MSPRO_CMD_SLEEP        = 0x11,
+	MSPRO_CMD_WAKEUP       = 0x12,
+	MSPRO_CMD_READ_DATA    = 0x20,
+	MSPRO_CMD_WRITE_DATA   = 0x21,
+	MSPRO_CMD_READ_ATRB    = 0x24,
+	MSPRO_CMD_STOP         = 0x25,
+	MSPRO_CMD_ERASE        = 0x26,
+	MSPRO_CMD_READ_QUAD    = 0x27,
+	MSPRO_CMD_WRITE_QUAD   = 0x28,
+	MSPRO_CMD_SET_IBD      = 0x46,
+	MSPRO_CMD_GET_IBD      = 0x47,
+	MSPRO_CMD_IN_IO_DATA   = 0xb0,
+	MSPRO_CMD_OUT_IO_DATA  = 0xb1,
+	MSPRO_CMD_READ_IO_ATRB = 0xb2,
+	MSPRO_CMD_IN_IO_FIFO   = 0xb3,
+	MSPRO_CMD_OUT_IO_FIFO  = 0xb4,
+	MSPRO_CMD_IN_IOM       = 0xb5,
+	MSPRO_CMD_OUT_IOM      = 0xb6,
 };
 };
 
 
 /*** Driver structures and functions ***/
 /*** Driver structures and functions ***/
@@ -165,7 +209,8 @@ enum memstick_param { MEMSTICK_POWER = 1, MEMSTICK_INTERFACE };
 #define MEMSTICK_POWER_ON  1
 #define MEMSTICK_POWER_ON  1
 
 
 #define MEMSTICK_SERIAL   0
 #define MEMSTICK_SERIAL   0
-#define MEMSTICK_PARALLEL 1
+#define MEMSTICK_PAR4     1
+#define MEMSTICK_PAR8     2
 
 
 struct memstick_host;
 struct memstick_host;
 struct memstick_driver;
 struct memstick_driver;
@@ -195,11 +240,7 @@ struct memstick_request {
 	unsigned char data_dir:1,
 	unsigned char data_dir:1,
 		      need_card_int:1,
 		      need_card_int:1,
 		      get_int_reg:1,
 		      get_int_reg:1,
-		      io_type:2;
-#define               MEMSTICK_IO_NONE 0
-#define               MEMSTICK_IO_VAL  1
-#define               MEMSTICK_IO_SG   2
-
+		      long_data:1;
 	unsigned char int_reg;
 	unsigned char int_reg;
 	int           error;
 	int           error;
 	union {
 	union {
@@ -231,8 +272,9 @@ struct memstick_host {
 	struct mutex        lock;
 	struct mutex        lock;
 	unsigned int        id;
 	unsigned int        id;
 	unsigned int        caps;
 	unsigned int        caps;
-#define MEMSTICK_CAP_PARALLEL      1
-#define MEMSTICK_CAP_AUTO_GET_INT  2
+#define MEMSTICK_CAP_AUTO_GET_INT  1
+#define MEMSTICK_CAP_PAR4          2
+#define MEMSTICK_CAP_PAR8          4
 
 
 	struct work_struct  media_checker;
 	struct work_struct  media_checker;
 	struct class_device cdev;
 	struct class_device cdev;
@@ -270,6 +312,8 @@ int memstick_add_host(struct memstick_host *host);
 void memstick_remove_host(struct memstick_host *host);
 void memstick_remove_host(struct memstick_host *host);
 void memstick_free_host(struct memstick_host *host);
 void memstick_free_host(struct memstick_host *host);
 void memstick_detect_change(struct memstick_host *host);
 void memstick_detect_change(struct memstick_host *host);
+void memstick_suspend_host(struct memstick_host *host);
+void memstick_resume_host(struct memstick_host *host);
 
 
 void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc,
 void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc,
 			  struct scatterlist *sg);
 			  struct scatterlist *sg);

+ 2 - 2
include/linux/pci.h

@@ -389,13 +389,13 @@ struct pci_driver {
 #define	to_pci_driver(drv) container_of(drv, struct pci_driver, driver)
 #define	to_pci_driver(drv) container_of(drv, struct pci_driver, driver)
 
 
 /**
 /**
- * DECLARE_PCI_DEVICE_TABLE - macro used to describe a pci device table
+ * DEFINE_PCI_DEVICE_TABLE - macro used to describe a pci device table
  * @_table: device table name
  * @_table: device table name
  *
  *
  * This macro is used to create a struct pci_device_id array (a device table)
  * This macro is used to create a struct pci_device_id array (a device table)
  * in a generic manner.
  * in a generic manner.
  */
  */
-#define DECLARE_PCI_DEVICE_TABLE(_table) \
+#define DEFINE_PCI_DEVICE_TABLE(_table) \
 	const struct pci_device_id _table[] __devinitconst
 	const struct pci_device_id _table[] __devinitconst
 
 
 /**
 /**

+ 1 - 0
include/linux/pci_ids.h

@@ -2184,6 +2184,7 @@
 #define PCI_DEVICE_ID_JMICRON_JMB366	0x2366
 #define PCI_DEVICE_ID_JMICRON_JMB366	0x2366
 #define PCI_DEVICE_ID_JMICRON_JMB368	0x2368
 #define PCI_DEVICE_ID_JMICRON_JMB368	0x2368
 #define PCI_DEVICE_ID_JMICRON_JMB38X_SD	0x2381
 #define PCI_DEVICE_ID_JMICRON_JMB38X_SD	0x2381
+#define PCI_DEVICE_ID_JMICRON_JMB38X_MS	0x2383
 
 
 #define PCI_VENDOR_ID_KORENIX		0x1982
 #define PCI_VENDOR_ID_KORENIX		0x1982
 #define PCI_DEVICE_ID_KORENIX_JETCARDF0	0x1600
 #define PCI_DEVICE_ID_KORENIX_JETCARDF0	0x1600

+ 1 - 1
include/linux/tifm.h

@@ -70,9 +70,9 @@ enum {
 
 
 #define TIFM_FIFO_ENABLE          0x00000001
 #define TIFM_FIFO_ENABLE          0x00000001
 #define TIFM_FIFO_READY           0x00000001
 #define TIFM_FIFO_READY           0x00000001
+#define TIFM_FIFO_MORE            0x00000008
 #define TIFM_FIFO_INT_SETALL      0x0000ffff
 #define TIFM_FIFO_INT_SETALL      0x0000ffff
 #define TIFM_FIFO_INTMASK         0x00000005
 #define TIFM_FIFO_INTMASK         0x00000005
-#define TIFM_FIFO_SIZE            0x00000200
 
 
 #define TIFM_DMA_RESET            0x00000002
 #define TIFM_DMA_RESET            0x00000002
 #define TIFM_DMA_TX               0x00008000
 #define TIFM_DMA_TX               0x00008000

+ 4 - 0
include/linux/time.h

@@ -174,6 +174,10 @@ static inline void timespec_add_ns(struct timespec *a, u64 ns)
 {
 {
 	ns += a->tv_nsec;
 	ns += a->tv_nsec;
 	while(unlikely(ns >= NSEC_PER_SEC)) {
 	while(unlikely(ns >= NSEC_PER_SEC)) {
+		/* The following asm() prevents the compiler from
+		 * optimising this loop into a modulo operation.  */
+		asm("" : "+r"(ns));
+
 		ns -= NSEC_PER_SEC;
 		ns -= NSEC_PER_SEC;
 		a->tv_sec++;
 		a->tv_sec++;
 	}
 	}

+ 1 - 8
include/linux/timex.h

@@ -232,14 +232,7 @@ static inline int ntp_synced(void)
 #else
 #else
 #define NTP_INTERVAL_FREQ  (HZ)
 #define NTP_INTERVAL_FREQ  (HZ)
 #endif
 #endif
-
-#define CLOCK_TICK_OVERFLOW	(LATCH * HZ - CLOCK_TICK_RATE)
-#define CLOCK_TICK_ADJUST	(((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \
-					(s64)CLOCK_TICK_RATE)
-
-/* Because using NSEC_PER_SEC would be too easy */
-#define NTP_INTERVAL_LENGTH ((((s64)TICK_USEC * NSEC_PER_USEC * USER_HZ) + \
-			      CLOCK_TICK_ADJUST) / NTP_INTERVAL_FREQ)
+#define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ)
 
 
 /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
 /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
 extern u64 current_tick_length(void);
 extern u64 current_tick_length(void);

+ 1 - 1
include/linux/usb/Kbuild

@@ -3,5 +3,5 @@ header-y += cdc.h
 header-y += ch9.h
 header-y += ch9.h
 header-y += gadgetfs.h
 header-y += gadgetfs.h
 header-y += midi.h
 header-y += midi.h
-unifdef-y += g_printer.h
+header-y += g_printer.h
 
 

+ 0 - 4
include/linux/usb/gadget.h

@@ -15,8 +15,6 @@
 #ifndef __LINUX_USB_GADGET_H
 #ifndef __LINUX_USB_GADGET_H
 #define __LINUX_USB_GADGET_H
 #define __LINUX_USB_GADGET_H
 
 
-#ifdef __KERNEL__
-
 struct usb_ep;
 struct usb_ep;
 
 
 /**
 /**
@@ -848,6 +846,4 @@ extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,
 
 
 extern void usb_ep_autoconfig_reset(struct usb_gadget *) __devinit;
 extern void usb_ep_autoconfig_reset(struct usb_gadget *) __devinit;
 
 
-#endif  /* __KERNEL__ */
-
 #endif	/* __LINUX_USB_GADGET_H */
 #endif	/* __LINUX_USB_GADGET_H */

+ 3 - 31
init/Kconfig

@@ -865,38 +865,10 @@ source "block/Kconfig"
 config PREEMPT_NOTIFIERS
 config PREEMPT_NOTIFIERS
 	bool
 	bool
 
 
-choice
-	prompt "RCU implementation type:"
-	default CLASSIC_RCU
-	help
-	  This allows you to choose either the classic RCU implementation
-	  that is designed for best read-side performance on non-realtime
-	  systems, or the preemptible RCU implementation for best latency
-	  on realtime systems.  Note that some kernel preemption modes
-	  will restrict your choice.
-
-	  Select the default if you are unsure.
-
 config CLASSIC_RCU
 config CLASSIC_RCU
-	bool "Classic RCU"
+	def_bool !PREEMPT_RCU
 	help
 	help
 	  This option selects the classic RCU implementation that is
 	  This option selects the classic RCU implementation that is
 	  designed for best read-side performance on non-realtime
 	  designed for best read-side performance on non-realtime
-	  systems.
-
-	  Say Y if you are unsure.
-
-config PREEMPT_RCU
-	bool "Preemptible RCU"
-	depends on PREEMPT
-	help
-	  This option reduces the latency of the kernel by making certain
-	  RCU sections preemptible. Normally RCU code is non-preemptible, if
-	  this option is selected then read-only RCU sections become
-	  preemptible. This helps latency, but may expose bugs due to
-	  now-naive assumptions about each RCU read-side critical section
-	  remaining on a given CPU through its execution.
-
-	  Say N if you are unsure.
-
-endchoice
+	  systems.  Classic RCU is the default.  Note that the
+	  PREEMPT_RCU symbol is used to select/deselect this option.

+ 3 - 2
ipc/shm.c

@@ -271,9 +271,10 @@ static struct mempolicy *shm_get_policy(struct vm_area_struct *vma,
 
 
 	if (sfd->vm_ops->get_policy)
 	if (sfd->vm_ops->get_policy)
 		pol = sfd->vm_ops->get_policy(vma, addr);
 		pol = sfd->vm_ops->get_policy(vma, addr);
-	else if (vma->vm_policy)
+	else if (vma->vm_policy) {
 		pol = vma->vm_policy;
 		pol = vma->vm_policy;
-	else
+		mpol_get(pol);	/* get_vma_policy() expects this */
+	} else
 		pol = current->mempolicy;
 		pol = current->mempolicy;
 	return pol;
 	return pol;
 }
 }

+ 15 - 0
kernel/Kconfig.preempt

@@ -52,8 +52,23 @@ config PREEMPT
 
 
 endchoice
 endchoice
 
 
+config PREEMPT_RCU
+	bool "Preemptible RCU"
+	depends on PREEMPT
+	default n
+	help
+	  This option reduces the latency of the kernel by making certain
+	  RCU sections preemptible. Normally RCU code is non-preemptible, if
+	  this option is selected then read-only RCU sections become
+	  preemptible. This helps latency, but may expose bugs due to
+	  now-naive assumptions about each RCU read-side critical section
+	  remaining on a given CPU through its execution.
+
+	  Say N if you are unsure.
+
 config RCU_TRACE
 config RCU_TRACE
 	bool "Enable tracing for RCU - currently stats in debugfs"
 	bool "Enable tracing for RCU - currently stats in debugfs"
+	depends on PREEMPT_RCU
 	select DEBUG_FS
 	select DEBUG_FS
 	default y
 	default y
 	help
 	help

+ 1 - 1
kernel/exit.c

@@ -1378,7 +1378,7 @@ unlock_sig:
 	if (!retval && infop)
 	if (!retval && infop)
 		retval = put_user(0, &infop->si_errno);
 		retval = put_user(0, &infop->si_errno);
 	if (!retval && infop)
 	if (!retval && infop)
-		retval = put_user(why, &infop->si_code);
+		retval = put_user((short)why, &infop->si_code);
 	if (!retval && infop)
 	if (!retval && infop)
 		retval = put_user(exit_code, &infop->si_status);
 		retval = put_user(exit_code, &infop->si_status);
 	if (!retval && infop)
 	if (!retval && infop)

+ 12 - 3
kernel/module.c

@@ -2178,10 +2178,20 @@ sys_init_module(void __user *umod,
 		wake_up(&module_wq);
 		wake_up(&module_wq);
 		return ret;
 		return ret;
 	}
 	}
+	if (ret > 0) {
+		printk(KERN_WARNING "%s: '%s'->init suspiciously returned %d, "
+				    "it should follow 0/-E convention\n"
+		       KERN_WARNING "%s: loading module anyway...\n",
+		       __func__, mod->name, ret,
+		       __func__);
+		dump_stack();
+	}
 
 
-	/* Now it's a first class citizen! */
-	mutex_lock(&module_mutex);
+	/* Now it's a first class citizen!  Wake up anyone waiting for it. */
 	mod->state = MODULE_STATE_LIVE;
 	mod->state = MODULE_STATE_LIVE;
+	wake_up(&module_wq);
+
+	mutex_lock(&module_mutex);
 	/* Drop initial reference. */
 	/* Drop initial reference. */
 	module_put(mod);
 	module_put(mod);
 	unwind_remove_table(mod->unwind_info, 1);
 	unwind_remove_table(mod->unwind_info, 1);
@@ -2190,7 +2200,6 @@ sys_init_module(void __user *umod,
 	mod->init_size = 0;
 	mod->init_size = 0;
 	mod->init_text_size = 0;
 	mod->init_text_size = 0;
 	mutex_unlock(&module_mutex);
 	mutex_unlock(&module_mutex);
-	wake_up(&module_wq);
 
 
 	return 0;
 	return 0;
 }
 }

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.