Ver Fonte

Merge branch 'fix' of git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6

Russell King há 14 anos atrás
pai
commit
04228460a3
100 ficheiros alterados com 1074 adições e 840 exclusões
  1. 1 0
      Documentation/accounting/getdelays.c
  2. 0 5
      Documentation/kernel-parameters.txt
  3. 31 28
      Documentation/scsi/scsi_mid_low_api.txt
  4. 10 1
      Documentation/trace/postprocess/trace-vmscan-postprocess.pl
  5. 2 2
      MAINTAINERS
  6. 1 1
      Makefile
  7. 1 0
      arch/arm/common/it8152.c
  8. 1 0
      arch/arm/include/asm/hardware/it8152.h
  9. 2 0
      arch/arm/mach-at91/include/mach/at91_mci.h
  10. 1 1
      arch/arm/mach-ixp4xx/common-pci.c
  11. 2 2
      arch/arm/mach-pxa/sleep.S
  12. 7 0
      arch/arm/mach-s3c2412/Kconfig
  13. 2 1
      arch/arm/mach-s3c2412/Makefile
  14. 1 0
      arch/arm/mach-s3c2416/Kconfig
  15. 6 0
      arch/arm/mach-s5pv210/mach-aquila.c
  16. 6 0
      arch/arm/mach-s5pv210/mach-goni.c
  17. 26 4
      arch/arm/mach-shmobile/include/mach/entry-macro.S
  18. 1 1
      arch/arm/mach-shmobile/include/mach/vmalloc.h
  19. 1 1
      arch/arm/plat-s3c24xx/Kconfig
  20. 4 0
      arch/mips/mm/sc-mips.c
  21. 3 7
      arch/mn10300/kernel/time.c
  22. 1 0
      arch/powerpc/platforms/52xx/mpc52xx_gpt.c
  23. 1 1
      arch/sh/boards/mach-se/7206/irq.c
  24. 1 1
      arch/sh/kernel/cpu/sh2a/clock-sh7201.c
  25. 1 2
      arch/sh/kernel/cpu/sh4/clock-sh4-202.c
  26. 1 1
      arch/tile/include/asm/signal.h
  27. 3 3
      arch/tile/kernel/compat_signal.c
  28. 21 3
      arch/tile/kernel/intvec_32.S
  29. 8 0
      arch/tile/kernel/process.c
  30. 4 6
      arch/tile/kernel/signal.c
  31. 1 1
      arch/x86/boot/compressed/misc.c
  32. 3 0
      arch/x86/include/asm/e820.h
  33. 1 0
      arch/x86/kernel/Makefile
  34. 8 0
      arch/x86/kernel/apic/apic.c
  35. 2 2
      arch/x86/kernel/apic/io_apic.c
  36. 0 7
      arch/x86/kernel/apic/probe_64.c
  37. 7 5
      arch/x86/kernel/head_32.S
  38. 16 10
      arch/x86/kernel/hpet.c
  39. 5 11
      arch/x86/kernel/microcode_intel.c
  40. 48 0
      arch/x86/kernel/resource.c
  41. 14 4
      arch/x86/kernel/setup.c
  42. 2 1
      arch/x86/kernel/xsave.c
  43. 5 13
      arch/x86/pci/i386.c
  44. 2 2
      arch/x86/vdso/Makefile
  45. 3 2
      block/blk-map.c
  46. 3 3
      block/blk-merge.c
  47. 22 29
      block/blk-settings.c
  48. 1 1
      block/blk-sysfs.c
  49. 25 14
      block/blk-throttle.c
  50. 3 0
      drivers/acpi/acpica/evgpeinit.c
  51. 0 5
      drivers/acpi/battery.c
  52. 60 37
      drivers/acpi/scan.c
  53. 11 11
      drivers/ata/Kconfig
  54. 1 1
      drivers/ata/Makefile
  55. 15 9
      drivers/ata/libata-core.c
  56. 14 3
      drivers/ata/libata-eh.c
  57. 3 4
      drivers/ata/libata-sff.c
  58. 14 6
      drivers/ata/pata_cs5536.c
  59. 2 0
      drivers/block/cciss.c
  60. 8 6
      drivers/block/drbd/drbd_receiver.c
  61. 2 1
      drivers/block/drbd/drbd_req.h
  62. 9 1
      drivers/block/drbd/drbd_worker.c
  63. 4 2
      drivers/bluetooth/hci_ldisc.c
  64. 9 2
      drivers/char/agp/intel-gtt.c
  65. 7 5
      drivers/char/ramoops.c
  66. 11 6
      drivers/clocksource/sh_cmt.c
  67. 15 4
      drivers/gpio/cs5535-gpio.c
  68. 3 0
      drivers/gpio/gpiolib.c
  69. 1 1
      drivers/gpio/rdc321x-gpio.c
  70. 5 2
      drivers/gpu/drm/drm_crtc_helper.c
  71. 1 1
      drivers/gpu/drm/i915/intel_bios.c
  72. 30 7
      drivers/gpu/drm/i915/intel_dp.c
  73. 8 11
      drivers/gpu/drm/i915/intel_ringbuffer.c
  74. 3 2
      drivers/gpu/drm/i915/intel_ringbuffer.h
  75. 6 3
      drivers/gpu/drm/i915/intel_sdvo.c
  76. 4 3
      drivers/gpu/drm/radeon/atombios_crtc.c
  77. 12 15
      drivers/gpu/drm/radeon/evergreen.c
  78. 1 0
      drivers/gpu/drm/radeon/evergreend.h
  79. 8 2
      drivers/gpu/drm/radeon/r600.c
  80. 4 5
      drivers/gpu/drm/radeon/r600_cs.c
  81. 4 5
      drivers/gpu/drm/radeon/radeon_device.c
  82. 19 0
      drivers/gpu/drm/radeon/radeon_drv.c
  83. 1 1
      drivers/gpu/drm/radeon/radeon_fb.c
  84. 1 1
      drivers/leds/led-class.c
  85. 2 8
      drivers/md/dm-table.c
  86. 0 3
      drivers/md/md.c
  87. 11 10
      drivers/media/IR/keymaps/rc-rc6-mce.c
  88. 16 13
      drivers/media/IR/lirc_dev.c
  89. 109 65
      drivers/media/IR/mceusb.c
  90. 8 2
      drivers/media/IR/nuvoton-cir.c
  91. 12 9
      drivers/media/IR/streamzap.c
  92. 4 4
      drivers/media/common/saa7146_hlp.c
  93. 8 8
      drivers/media/common/saa7146_video.c
  94. 3 114
      drivers/media/video/bt8xx/bttv-driver.c
  95. 184 232
      drivers/media/video/gspca/sonixj.c
  96. 0 2
      drivers/media/video/mx2_camera.c
  97. 48 3
      drivers/media/video/s5p-fimc/fimc-capture.c
  98. 33 21
      drivers/media/video/s5p-fimc/fimc-core.c
  99. 16 8
      drivers/media/video/s5p-fimc/fimc-core.h
  100. 3 0
      drivers/media/video/s5p-fimc/regs-fimc.h

+ 1 - 0
Documentation/accounting/getdelays.c

@@ -516,6 +516,7 @@ int main(int argc, char *argv[])
 			default:
 			default:
 				fprintf(stderr, "Unknown nla_type %d\n",
 				fprintf(stderr, "Unknown nla_type %d\n",
 					na->nla_type);
 					na->nla_type);
+			case TASKSTATS_TYPE_NULL:
 				break;
 				break;
 			}
 			}
 			na = (struct nlattr *) (GENLMSG_DATA(&msg) + len);
 			na = (struct nlattr *) (GENLMSG_DATA(&msg) + len);

+ 0 - 5
Documentation/kernel-parameters.txt

@@ -2175,11 +2175,6 @@ and is between 256 and 4096 characters. It is defined in the file
 	reset_devices	[KNL] Force drivers to reset the underlying device
 	reset_devices	[KNL] Force drivers to reset the underlying device
 			during initialization.
 			during initialization.
 
 
-	resource_alloc_from_bottom
-			Allocate new resources from the beginning of available
-			space, not the end.  If you need to use this, please
-			report a bug.
-
 	resume=		[SWSUSP]
 	resume=		[SWSUSP]
 			Specify the partition device for software suspend
 			Specify the partition device for software suspend
 
 

+ 31 - 28
Documentation/scsi/scsi_mid_low_api.txt

@@ -1044,9 +1044,9 @@ Details:
 
 
 
 
 /**
 /**
- *      queuecommand - queue scsi command, invoke 'done' on completion
+ *      queuecommand - queue scsi command, invoke scp->scsi_done on completion
+ *      @shost: pointer to the scsi host object
  *      @scp: pointer to scsi command object
  *      @scp: pointer to scsi command object
- *      @done: function pointer to be invoked on completion
  *
  *
  *      Returns 0 on success.
  *      Returns 0 on success.
  *
  *
@@ -1074,42 +1074,45 @@ Details:
  *
  *
  *      Other types of errors that are detected immediately may be
  *      Other types of errors that are detected immediately may be
  *      flagged by setting scp->result to an appropriate value,
  *      flagged by setting scp->result to an appropriate value,
- *      invoking the 'done' callback, and then returning 0 from this
- *      function. If the command is not performed immediately (and the
- *      LLD is starting (or will start) the given command) then this
- *      function should place 0 in scp->result and return 0.
+ *      invoking the scp->scsi_done callback, and then returning 0
+ *      from this function. If the command is not performed
+ *      immediately (and the LLD is starting (or will start) the given
+ *      command) then this function should place 0 in scp->result and
+ *      return 0.
  *
  *
  *      Command ownership.  If the driver returns zero, it owns the
  *      Command ownership.  If the driver returns zero, it owns the
- *      command and must take responsibility for ensuring the 'done'
- *      callback is executed.  Note: the driver may call done before
- *      returning zero, but after it has called done, it may not
- *      return any value other than zero.  If the driver makes a
- *      non-zero return, it must not execute the command's done
- *      callback at any time.
- *
- *      Locks: struct Scsi_Host::host_lock held on entry (with "irqsave")
- *             and is expected to be held on return.
+ *      command and must take responsibility for ensuring the
+ *      scp->scsi_done callback is executed.  Note: the driver may
+ *      call scp->scsi_done before returning zero, but after it has
+ *      called scp->scsi_done, it may not return any value other than
+ *      zero.  If the driver makes a non-zero return, it must not
+ *      execute the command's scsi_done callback at any time.
+ *
+ *      Locks: up to and including 2.6.36, struct Scsi_Host::host_lock
+ *             held on entry (with "irqsave") and is expected to be
+ *             held on return. From 2.6.37 onwards, queuecommand is
+ *             called without any locks held.
  *
  *
  *      Calling context: in interrupt (soft irq) or process context
  *      Calling context: in interrupt (soft irq) or process context
  *
  *
- *      Notes: This function should be relatively fast. Normally it will
- *      not wait for IO to complete. Hence the 'done' callback is invoked 
- *      (often directly from an interrupt service routine) some time after
- *      this function has returned. In some cases (e.g. pseudo adapter 
- *      drivers that manufacture the response to a SCSI INQUIRY)
- *      the 'done' callback may be invoked before this function returns.
- *      If the 'done' callback is not invoked within a certain period
- *      the SCSI mid level will commence error processing.
- *      If a status of CHECK CONDITION is placed in "result" when the
- *      'done' callback is invoked, then the LLD driver should 
- *      perform autosense and fill in the struct scsi_cmnd::sense_buffer
+ *      Notes: This function should be relatively fast. Normally it
+ *      will not wait for IO to complete. Hence the scp->scsi_done
+ *      callback is invoked (often directly from an interrupt service
+ *      routine) some time after this function has returned. In some
+ *      cases (e.g. pseudo adapter drivers that manufacture the
+ *      response to a SCSI INQUIRY) the scp->scsi_done callback may be
+ *      invoked before this function returns.  If the scp->scsi_done
+ *      callback is not invoked within a certain period the SCSI mid
+ *      level will commence error processing.  If a status of CHECK
+ *      CONDITION is placed in "result" when the scp->scsi_done
+ *      callback is invoked, then the LLD driver should perform
+ *      autosense and fill in the struct scsi_cmnd::sense_buffer
  *      array. The scsi_cmnd::sense_buffer array is zeroed prior to
  *      array. The scsi_cmnd::sense_buffer array is zeroed prior to
  *      the mid level queuing a command to an LLD.
  *      the mid level queuing a command to an LLD.
  *
  *
  *      Defined in: LLD
  *      Defined in: LLD
  **/
  **/
-    int queuecommand(struct scsi_cmnd * scp, 
-                     void (*done)(struct scsi_cmnd *))
+    int queuecommand(struct Scsi_Host *shost, struct scsi_cmnd * scp)
 
 
 
 
 /**
 /**

+ 10 - 1
Documentation/trace/postprocess/trace-vmscan-postprocess.pl

@@ -373,9 +373,18 @@ EVENT_PROCESS:
 				print "         $regex_lru_isolate/o\n";
 				print "         $regex_lru_isolate/o\n";
 				next;
 				next;
 			}
 			}
+			my $isolate_mode = $1;
 			my $nr_scanned = $4;
 			my $nr_scanned = $4;
 			my $nr_contig_dirty = $7;
 			my $nr_contig_dirty = $7;
-			$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
+
+			# To closer match vmstat scanning statistics, only count isolate_both
+			# and isolate_inactive as scanning. isolate_active is rotation
+			# isolate_inactive == 0
+			# isolate_active   == 1
+			# isolate_both     == 2
+			if ($isolate_mode != 1) {
+				$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
+			}
 			$perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty;
 			$perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty;
 		} elsif ($tracepoint eq "mm_vmscan_lru_shrink_inactive") {
 		} elsif ($tracepoint eq "mm_vmscan_lru_shrink_inactive") {
 			$details = $5;
 			$details = $5;

+ 2 - 2
MAINTAINERS

@@ -405,7 +405,7 @@ S:	Supported
 F:	drivers/usb/gadget/amd5536udc.*
 F:	drivers/usb/gadget/amd5536udc.*
 
 
 AMD GEODE PROCESSOR/CHIPSET SUPPORT
 AMD GEODE PROCESSOR/CHIPSET SUPPORT
-P:	Jordan Crouse
+P:	Andres Salomon <dilinger@queued.net>
 L:	linux-geode@lists.infradead.org (moderated for non-subscribers)
 L:	linux-geode@lists.infradead.org (moderated for non-subscribers)
 W:	http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
 W:	http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
 S:	Supported
 S:	Supported
@@ -4605,7 +4605,7 @@ F:	drivers/pcmcia/
 F:	include/pcmcia/
 F:	include/pcmcia/
 
 
 PCNET32 NETWORK DRIVER
 PCNET32 NETWORK DRIVER
-M:	Don Fry <pcnet32@verizon.net>
+M:	Don Fry <pcnet32@frontier.com>
 L:	netdev@vger.kernel.org
 L:	netdev@vger.kernel.org
 S:	Maintained
 S:	Maintained
 F:	drivers/net/pcnet32.c
 F:	drivers/net/pcnet32.c

+ 1 - 1
Makefile

@@ -1,7 +1,7 @@
 VERSION = 2
 VERSION = 2
 PATCHLEVEL = 6
 PATCHLEVEL = 6
 SUBLEVEL = 37
 SUBLEVEL = 37
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc8
 NAME = Flesh-Eating Bats with Fangs
 NAME = Flesh-Eating Bats with Fangs
 
 
 # *DOCUMENTATION*
 # *DOCUMENTATION*

+ 1 - 0
arch/arm/common/it8152.c

@@ -352,3 +352,4 @@ struct pci_bus * __init it8152_pci_scan_bus(int nr, struct pci_sys_data *sys)
 	return pci_scan_bus(nr, &it8152_ops, sys);
 	return pci_scan_bus(nr, &it8152_ops, sys);
 }
 }
 
 
+EXPORT_SYMBOL(dma_set_coherent_mask);

+ 1 - 0
arch/arm/include/asm/hardware/it8152.h

@@ -76,6 +76,7 @@ extern unsigned long it8152_base_address;
   IT8152_PD_IRQ(0)  Audio controller (ACR)
   IT8152_PD_IRQ(0)  Audio controller (ACR)
  */
  */
 #define IT8152_IRQ(x)   (IRQ_BOARD_START + (x))
 #define IT8152_IRQ(x)   (IRQ_BOARD_START + (x))
+#define IT8152_LAST_IRQ	(IRQ_BOARD_START + 40)
 
 
 /* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
 /* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
 #define IT8152_LD_IRQ_COUNT     9
 #define IT8152_LD_IRQ_COUNT     9

+ 2 - 0
arch/arm/mach-at91/include/mach/at91_mci.h

@@ -74,6 +74,8 @@
 #define			AT91_MCI_TRTYP_BLOCK	(0 << 19)
 #define			AT91_MCI_TRTYP_BLOCK	(0 << 19)
 #define			AT91_MCI_TRTYP_MULTIPLE	(1 << 19)
 #define			AT91_MCI_TRTYP_MULTIPLE	(1 << 19)
 #define			AT91_MCI_TRTYP_STREAM	(2 << 19)
 #define			AT91_MCI_TRTYP_STREAM	(2 << 19)
+#define			AT91_MCI_TRTYP_SDIO_BYTE	(4 << 19)
+#define			AT91_MCI_TRTYP_SDIO_BLOCK	(5 << 19)
 
 
 #define AT91_MCI_BLKR		0x18		/* Block Register */
 #define AT91_MCI_BLKR		0x18		/* Block Register */
 #define		AT91_MCI_BLKR_BCNT(n)	((0xffff & (n)) << 0)	/* Block count */
 #define		AT91_MCI_BLKR_BCNT(n)	((0xffff & (n)) << 0)	/* Block count */

+ 1 - 1
arch/arm/mach-ixp4xx/common-pci.c

@@ -513,4 +513,4 @@ int dma_set_coherent_mask(struct device *dev, u64 mask)
 
 
 EXPORT_SYMBOL(ixp4xx_pci_read);
 EXPORT_SYMBOL(ixp4xx_pci_read);
 EXPORT_SYMBOL(ixp4xx_pci_write);
 EXPORT_SYMBOL(ixp4xx_pci_write);
-
+EXPORT_SYMBOL(dma_set_coherent_mask);

+ 2 - 2
arch/arm/mach-pxa/sleep.S

@@ -353,8 +353,8 @@ resume_turn_on_mmu:
 
 
 	@ Let us ensure we jump to resume_after_mmu only when the mcr above
 	@ Let us ensure we jump to resume_after_mmu only when the mcr above
 	@ actually took effect.  They call it the "cpwait" operation.
 	@ actually took effect.  They call it the "cpwait" operation.
-	mrc	p15, 0, r1, c2, c0, 0		@ queue a dependency on CP15
-	sub	pc, r2, r1, lsr #32		@ jump to virtual addr
+	mrc	p15, 0, r0, c2, c0, 0		@ queue a dependency on CP15
+	sub	pc, r2, r0, lsr #32		@ jump to virtual addr
 	nop
 	nop
 	nop
 	nop
 	nop
 	nop

+ 7 - 0
arch/arm/mach-s3c2412/Kconfig

@@ -28,9 +28,16 @@ config S3C2412_DMA
 
 
 config S3C2412_PM
 config S3C2412_PM
 	bool
 	bool
+	select S3C2412_PM_SLEEP
 	help
 	help
 	  Internal config node to apply S3C2412 power management
 	  Internal config node to apply S3C2412 power management
 
 
+config S3C2412_PM_SLEEP
+	bool
+	help
+	  Internal config node to apply sleep for S3C2412 power management.
+	  Can be selected by another SoCs with similar sleep procedure.
+
 # Note, the S3C2412 IOtiming support is in plat-s3c24xx
 # Note, the S3C2412 IOtiming support is in plat-s3c24xx
 
 
 config S3C2412_CPUFREQ
 config S3C2412_CPUFREQ

+ 2 - 1
arch/arm/mach-s3c2412/Makefile

@@ -14,7 +14,8 @@ obj-$(CONFIG_CPU_S3C2412)	+= irq.o
 obj-$(CONFIG_CPU_S3C2412)	+= clock.o
 obj-$(CONFIG_CPU_S3C2412)	+= clock.o
 obj-$(CONFIG_CPU_S3C2412)	+= gpio.o
 obj-$(CONFIG_CPU_S3C2412)	+= gpio.o
 obj-$(CONFIG_S3C2412_DMA)	+= dma.o
 obj-$(CONFIG_S3C2412_DMA)	+= dma.o
-obj-$(CONFIG_S3C2412_PM)	+= pm.o sleep.o
+obj-$(CONFIG_S3C2412_PM)	+= pm.o
+obj-$(CONFIG_S3C2412_PM_SLEEP)	+= sleep.o
 obj-$(CONFIG_S3C2412_CPUFREQ)	+= cpu-freq.o
 obj-$(CONFIG_S3C2412_CPUFREQ)	+= cpu-freq.o
 
 
 # Machine support
 # Machine support

+ 1 - 0
arch/arm/mach-s3c2416/Kconfig

@@ -27,6 +27,7 @@ config S3C2416_DMA
 
 
 config S3C2416_PM
 config S3C2416_PM
 	bool
 	bool
+	select S3C2412_PM_SLEEP
 	help
 	help
 	  Internal config node to apply S3C2416 power management
 	  Internal config node to apply S3C2416 power management
 
 

+ 6 - 0
arch/arm/mach-s5pv210/mach-aquila.c

@@ -378,6 +378,12 @@ static struct max8998_regulator_data aquila_regulators[] = {
 static struct max8998_platform_data aquila_max8998_pdata = {
 static struct max8998_platform_data aquila_max8998_pdata = {
 	.num_regulators	= ARRAY_SIZE(aquila_regulators),
 	.num_regulators	= ARRAY_SIZE(aquila_regulators),
 	.regulators	= aquila_regulators,
 	.regulators	= aquila_regulators,
+	.buck1_set1	= S5PV210_GPH0(3),
+	.buck1_set2	= S5PV210_GPH0(4),
+	.buck2_set3	= S5PV210_GPH0(5),
+	.buck1_max_voltage1 = 1200000,
+	.buck1_max_voltage2 = 1200000,
+	.buck2_max_voltage = 1200000,
 };
 };
 #endif
 #endif
 
 

+ 6 - 0
arch/arm/mach-s5pv210/mach-goni.c

@@ -518,6 +518,12 @@ static struct max8998_regulator_data goni_regulators[] = {
 static struct max8998_platform_data goni_max8998_pdata = {
 static struct max8998_platform_data goni_max8998_pdata = {
 	.num_regulators	= ARRAY_SIZE(goni_regulators),
 	.num_regulators	= ARRAY_SIZE(goni_regulators),
 	.regulators	= goni_regulators,
 	.regulators	= goni_regulators,
+	.buck1_set1	= S5PV210_GPH0(3),
+	.buck1_set2	= S5PV210_GPH0(4),
+	.buck2_set3	= S5PV210_GPH0(5),
+	.buck1_max_voltage1 = 1200000,
+	.buck1_max_voltage2 = 1200000,
+	.buck2_max_voltage = 1200000,
 };
 };
 #endif
 #endif
 
 

+ 26 - 4
arch/arm/mach-shmobile/include/mach/entry-macro.S

@@ -1,4 +1,5 @@
 /*
 /*
+ * Copyright (C) 2010 Magnus Damm
  * Copyright (C) 2008 Renesas Solutions Corp.
  * Copyright (C) 2008 Renesas Solutions Corp.
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
@@ -14,24 +15,45 @@
  * along with this program; if not, write to the Free Software
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
  */
-#include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/irqs.h>
 
 
+#define INTCA_BASE	0xe6980000
+#define INTFLGA_OFFS	0x00000018 /* accept pending interrupt */
+#define INTEVTA_OFFS	0x00000020 /* vector number of accepted interrupt */
+#define INTLVLA_OFFS	0x00000030 /* priority level of accepted interrupt */
+#define INTLVLB_OFFS	0x00000034 /* previous priority level */
+
 	.macro  disable_fiq
 	.macro  disable_fiq
 	.endm
 	.endm
 
 
 	.macro  get_irqnr_preamble, base, tmp
 	.macro  get_irqnr_preamble, base, tmp
-	ldr     \base, =INTFLGA
+	ldr     \base, =INTCA_BASE
 	.endm
 	.endm
 
 
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
 	.endm
 
 
 	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-	ldr     \irqnr, [\base]
+	/* The single INTFLGA read access below results in the following:
+	 *
+	 * 1. INTLVLB is updated with old priority value from INTLVLA
+	 * 2. Highest priority interrupt is accepted
+	 * 3. INTLVLA is updated to contain priority of accepted interrupt
+	 * 4. Accepted interrupt vector is stored in INTFLGA and INTEVTA
+	 */
+	ldr     \irqnr, [\base, #INTFLGA_OFFS]
+
+	/* Restore INTLVLA with the value saved in INTLVLB.
+	 * This is required to support interrupt priorities properly.
+	 */
+	ldrb	\tmp, [\base, #INTLVLB_OFFS]
+	strb    \tmp, [\base, #INTLVLA_OFFS]
+
+	/* Handle invalid vector number case */
 	cmp	\irqnr, #0
 	cmp	\irqnr, #0
 	beq	1000f
 	beq	1000f
-	/* intevt to irq number */
+
+	/* Convert vector to irq number, same as the evt2irq() macro */
 	lsr	\irqnr, \irqnr, #0x5
 	lsr	\irqnr, \irqnr, #0x5
 	subs	\irqnr, \irqnr, #16
 	subs	\irqnr, \irqnr, #16
 
 

+ 1 - 1
arch/arm/mach-shmobile/include/mach/vmalloc.h

@@ -2,6 +2,6 @@
 #define __ASM_MACH_VMALLOC_H
 #define __ASM_MACH_VMALLOC_H
 
 
 /* Vmalloc at ... - 0xe5ffffff */
 /* Vmalloc at ... - 0xe5ffffff */
-#define VMALLOC_END 0xe6000000
+#define VMALLOC_END 0xe6000000UL
 
 
 #endif /* __ASM_MACH_VMALLOC_H */
 #endif /* __ASM_MACH_VMALLOC_H */

+ 1 - 1
arch/arm/plat-s3c24xx/Kconfig

@@ -8,7 +8,7 @@ config PLAT_S3C24XX
 	default y
 	default y
 	select NO_IOPORT
 	select NO_IOPORT
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_REQUIRE_GPIOLIB
-	select S3C_DEVICE_NAND
+	select S3C_DEV_NAND
 	select S3C_GPIO_CFG_S3C24XX
 	select S3C_GPIO_CFG_S3C24XX
 	help
 	help
 	  Base platform code for any Samsung S3C24XX device
 	  Base platform code for any Samsung S3C24XX device

+ 4 - 0
arch/mips/mm/sc-mips.c

@@ -68,6 +68,9 @@ static struct bcache_ops mips_sc_ops = {
  */
  */
 static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 {
 {
+	unsigned int config2 = read_c0_config2();
+	unsigned int tmp;
+
 	/* Check the bypass bit (L2B) */
 	/* Check the bypass bit (L2B) */
 	switch (c->cputype) {
 	switch (c->cputype) {
 	case CPU_34K:
 	case CPU_34K:
@@ -83,6 +86,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 		c->scache.linesz = 2 << tmp;
 		c->scache.linesz = 2 << tmp;
 	else
 	else
 		return 0;
 		return 0;
+	return 1;
 }
 }
 
 
 static inline int __init mips_sc_probe(void)
 static inline int __init mips_sc_probe(void)

+ 3 - 7
arch/mn10300/kernel/time.c

@@ -40,21 +40,17 @@ unsigned long long sched_clock(void)
 		unsigned long long ll;
 		unsigned long long ll;
 		unsigned l[2];
 		unsigned l[2];
 	} tsc64, result;
 	} tsc64, result;
-	unsigned long tsc, tmp;
+	unsigned long tmp;
 	unsigned product[3]; /* 96-bit intermediate value */
 	unsigned product[3]; /* 96-bit intermediate value */
 
 
 	/* cnt32_to_63() is not safe with preemption */
 	/* cnt32_to_63() is not safe with preemption */
 	preempt_disable();
 	preempt_disable();
 
 
-	/* read the TSC value
-	 */
-	tsc = get_cycles();
-
-	/* expand to 64-bits.
+	/* expand the tsc to 64-bits.
 	 * - sched_clock() must be called once a minute or better or the
 	 * - sched_clock() must be called once a minute or better or the
 	 *   following will go horribly wrong - see cnt32_to_63()
 	 *   following will go horribly wrong - see cnt32_to_63()
 	 */
 	 */
-	tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL;
+	tsc64.ll = cnt32_to_63(get_cycles()) & 0x7fffffffffffffffULL;
 
 
 	preempt_enable();
 	preempt_enable();
 
 

+ 1 - 0
arch/powerpc/platforms/52xx/mpc52xx_gpt.c

@@ -63,6 +63,7 @@
 #include <linux/of_gpio.h>
 #include <linux/of_gpio.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
+#include <linux/fs.h>
 #include <linux/watchdog.h>
 #include <linux/watchdog.h>
 #include <linux/miscdevice.h>
 #include <linux/miscdevice.h>
 #include <linux/uaccess.h>
 #include <linux/uaccess.h>

+ 1 - 1
arch/sh/boards/mach-se/7206/irq.c

@@ -140,7 +140,7 @@ void __init init_se7206_IRQ(void)
 	make_se7206_irq(IRQ1_IRQ); /* ATA */
 	make_se7206_irq(IRQ1_IRQ); /* ATA */
 	make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */
 	make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */
 
 
-	__raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR); /* ICR1 */
+	__raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR1); /* ICR1 */
 
 
 	/* FPGA System register setup*/
 	/* FPGA System register setup*/
 	__raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */
 	__raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */

+ 1 - 1
arch/sh/kernel/cpu/sh2a/clock-sh7201.c

@@ -34,7 +34,7 @@ static const int pfc_divisors[]={1,2,3,4,6,8,12};
 
 
 static void master_clk_init(struct clk *clk)
 static void master_clk_init(struct clk *clk)
 {
 {
-	return 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
+	clk->rate = 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
 }
 }
 
 
 static struct clk_ops sh7201_master_clk_ops = {
 static struct clk_ops sh7201_master_clk_ops = {

+ 1 - 2
arch/sh/kernel/cpu/sh4/clock-sh4-202.c

@@ -81,8 +81,7 @@ static void shoc_clk_init(struct clk *clk)
 	for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) {
 	for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) {
 		int divisor = frqcr3_divisors[i];
 		int divisor = frqcr3_divisors[i];
 
 
-		if (clk->ops->set_rate(clk, clk->parent->rate /
-						divisor, 0) == 0)
+		if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0)
 			break;
 			break;
 	}
 	}
 
 

+ 1 - 1
arch/tile/include/asm/signal.h

@@ -25,7 +25,7 @@
 
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 struct pt_regs;
 struct pt_regs;
-int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *);
+int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
 int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);
 int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);
 void do_signal(struct pt_regs *regs);
 void do_signal(struct pt_regs *regs);
 #endif
 #endif

+ 3 - 3
arch/tile/kernel/compat_signal.c

@@ -290,12 +290,12 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
 	return ret;
 	return ret;
 }
 }
 
 
+/* The assembly shim for this function arranges to ignore the return value. */
 long compat_sys_rt_sigreturn(struct pt_regs *regs)
 long compat_sys_rt_sigreturn(struct pt_regs *regs)
 {
 {
 	struct compat_rt_sigframe __user *frame =
 	struct compat_rt_sigframe __user *frame =
 		(struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
 		(struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
 	sigset_t set;
 	sigset_t set;
-	long r0;
 
 
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 		goto badframe;
@@ -308,13 +308,13 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)
 	recalc_sigpending();
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 	spin_unlock_irq(&current->sighand->siglock);
 
 
-	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
+	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 		goto badframe;
 		goto badframe;
 
 
 	if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
 	if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
 		goto badframe;
 		goto badframe;
 
 
-	return r0;
+	return 0;
 
 
 badframe:
 badframe:
 	force_sig(SIGSEGV, current);
 	force_sig(SIGSEGV, current);

+ 21 - 3
arch/tile/kernel/intvec_32.S

@@ -1342,8 +1342,8 @@ handle_syscall:
 	lw      r20, r20
 	lw      r20, r20
 
 
 	/* Jump to syscall handler. */
 	/* Jump to syscall handler. */
-	jalr    r20; .Lhandle_syscall_link:
-	FEEDBACK_REENTER(handle_syscall)
+	jalr    r20
+.Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */
 
 
 	/*
 	/*
 	 * Write our r0 onto the stack so it gets restored instead
 	 * Write our r0 onto the stack so it gets restored instead
@@ -1352,6 +1352,9 @@ handle_syscall:
 	PTREGS_PTR(r29, PTREGS_OFFSET_REG(0))
 	PTREGS_PTR(r29, PTREGS_OFFSET_REG(0))
 	sw      r29, r0
 	sw      r29, r0
 
 
+.Lsyscall_sigreturn_skip:
+	FEEDBACK_REENTER(handle_syscall)
+
 	/* Do syscall trace again, if requested. */
 	/* Do syscall trace again, if requested. */
 	lw	r30, r31
 	lw	r30, r31
 	andi    r30, r30, _TIF_SYSCALL_TRACE
 	andi    r30, r30, _TIF_SYSCALL_TRACE
@@ -1536,9 +1539,24 @@ STD_ENTRY_LOCAL(bad_intr)
 	};                                              \
 	};                                              \
 	STD_ENDPROC(_##x)
 	STD_ENDPROC(_##x)
 
 
+/*
+ * Special-case sigreturn to not write r0 to the stack on return.
+ * This is technically more efficient, but it also avoids difficulties
+ * in the 64-bit OS when handling 32-bit compat code, since we must not
+ * sign-extend r0 for the sigreturn return-value case.
+ */
+#define PTREGS_SYSCALL_SIGRETURN(x, reg)                \
+	STD_ENTRY(_##x);                                \
+	addli   lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \
+	{                                               \
+	 PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \
+	 j      x                                       \
+	};                                              \
+	STD_ENDPROC(_##x)
+
 PTREGS_SYSCALL(sys_execve, r3)
 PTREGS_SYSCALL(sys_execve, r3)
 PTREGS_SYSCALL(sys_sigaltstack, r2)
 PTREGS_SYSCALL(sys_sigaltstack, r2)
-PTREGS_SYSCALL(sys_rt_sigreturn, r0)
+PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
 PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)
 PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)
 
 
 /* Save additional callee-saves to pt_regs, put address in r4 and jump. */
 /* Save additional callee-saves to pt_regs, put address in r4 and jump. */

+ 8 - 0
arch/tile/kernel/process.c

@@ -211,6 +211,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	childregs->regs[0] = 0;         /* return value is zero */
 	childregs->regs[0] = 0;         /* return value is zero */
 	childregs->sp = sp;  /* override with new user stack pointer */
 	childregs->sp = sp;  /* override with new user stack pointer */
 
 
+	/*
+	 * If CLONE_SETTLS is set, set "tp" in the new task to "r4",
+	 * which is passed in as arg #5 to sys_clone().
+	 */
+	if (clone_flags & CLONE_SETTLS)
+		childregs->tp = regs->regs[4];
+
 	/*
 	/*
 	 * Copy the callee-saved registers from the passed pt_regs struct
 	 * Copy the callee-saved registers from the passed pt_regs struct
 	 * into the context-switch callee-saved registers area.
 	 * into the context-switch callee-saved registers area.
@@ -539,6 +546,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
 	return __switch_to(prev, next, next_current_ksp0(next));
 	return __switch_to(prev, next, next_current_ksp0(next));
 }
 }
 
 
+/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */
 SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
 SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
 		void __user *, parent_tidptr, void __user *, child_tidptr,
 		void __user *, parent_tidptr, void __user *, child_tidptr,
 		struct pt_regs *, regs)
 		struct pt_regs *, regs)

+ 4 - 6
arch/tile/kernel/signal.c

@@ -52,7 +52,7 @@ SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
  */
  */
 
 
 int restore_sigcontext(struct pt_regs *regs,
 int restore_sigcontext(struct pt_regs *regs,
-		       struct sigcontext __user *sc, long *pr0)
+		       struct sigcontext __user *sc)
 {
 {
 	int err = 0;
 	int err = 0;
 	int i;
 	int i;
@@ -75,17 +75,15 @@ int restore_sigcontext(struct pt_regs *regs,
 
 
 	regs->faultnum = INT_SWINT_1_SIGRETURN;
 	regs->faultnum = INT_SWINT_1_SIGRETURN;
 
 
-	err |= __get_user(*pr0, &sc->gregs[0]);
 	return err;
 	return err;
 }
 }
 
 
-/* sigreturn() returns long since it restores r0 in the interrupted code. */
+/* The assembly shim for this function arranges to ignore the return value. */
 SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
 SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
 {
 {
 	struct rt_sigframe __user *frame =
 	struct rt_sigframe __user *frame =
 		(struct rt_sigframe __user *)(regs->sp);
 		(struct rt_sigframe __user *)(regs->sp);
 	sigset_t set;
 	sigset_t set;
-	long r0;
 
 
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 		goto badframe;
@@ -98,13 +96,13 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
 	recalc_sigpending();
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 	spin_unlock_irq(&current->sighand->siglock);
 
 
-	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
+	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 		goto badframe;
 		goto badframe;
 
 
 	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
 	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
 		goto badframe;
 		goto badframe;
 
 
-	return r0;
+	return 0;
 
 
 badframe:
 badframe:
 	force_sig(SIGSEGV, current);
 	force_sig(SIGSEGV, current);

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

@@ -355,7 +355,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
 	if (heap > 0x3fffffffffffUL)
 	if (heap > 0x3fffffffffffUL)
 		error("Destination address too large");
 		error("Destination address too large");
 #else
 #else
-	if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff))
+	if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff))
 		error("Destination address too large");
 		error("Destination address too large");
 #endif
 #endif
 #ifndef CONFIG_RELOCATABLE
 #ifndef CONFIG_RELOCATABLE

+ 3 - 0
arch/x86/include/asm/e820.h

@@ -72,6 +72,9 @@ struct e820map {
 #define BIOS_BEGIN		0x000a0000
 #define BIOS_BEGIN		0x000a0000
 #define BIOS_END		0x00100000
 #define BIOS_END		0x00100000
 
 
+#define BIOS_ROM_BASE		0xffe00000
+#define BIOS_ROM_END		0xffffffff
+
 #ifdef __KERNEL__
 #ifdef __KERNEL__
 /* see comment in arch/x86/kernel/e820.c */
 /* see comment in arch/x86/kernel/e820.c */
 extern struct e820map e820;
 extern struct e820map e820;

+ 1 - 0
arch/x86/kernel/Makefile

@@ -45,6 +45,7 @@ obj-y			+= pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
 obj-y			+= alternative.o i8253.o pci-nommu.o hw_breakpoint.o
 obj-y			+= alternative.o i8253.o pci-nommu.o hw_breakpoint.o
 obj-y			+= tsc.o io_delay.o rtc.o
 obj-y			+= tsc.o io_delay.o rtc.o
 obj-y			+= pci-iommu_table.o
 obj-y			+= pci-iommu_table.o
+obj-y			+= resource.o
 
 
 obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o
 obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o
 obj-y				+= process.o
 obj-y				+= process.o

+ 8 - 0
arch/x86/kernel/apic/apic.c

@@ -1389,6 +1389,14 @@ void __cpuinit end_local_APIC_setup(void)
 
 
 	setup_apic_nmi_watchdog(NULL);
 	setup_apic_nmi_watchdog(NULL);
 	apic_pm_activate();
 	apic_pm_activate();
+
+	/*
+	 * Now that local APIC setup is completed for BP, configure the fault
+	 * handling for interrupt remapping.
+	 */
+	if (!smp_processor_id() && intr_remapping_enabled)
+		enable_drhd_fault_handling();
+
 }
 }
 
 
 #ifdef CONFIG_X86_X2APIC
 #ifdef CONFIG_X86_X2APIC

+ 2 - 2
arch/x86/kernel/apic/io_apic.c

@@ -2430,13 +2430,12 @@ static void ack_apic_level(struct irq_data *data)
 {
 {
 	struct irq_cfg *cfg = data->chip_data;
 	struct irq_cfg *cfg = data->chip_data;
 	int i, do_unmask_irq = 0, irq = data->irq;
 	int i, do_unmask_irq = 0, irq = data->irq;
-	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long v;
 	unsigned long v;
 
 
 	irq_complete_move(cfg);
 	irq_complete_move(cfg);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 	/* If we are moving the irq we need to mask it */
 	/* If we are moving the irq we need to mask it */
-	if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
+	if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) {
 		do_unmask_irq = 1;
 		do_unmask_irq = 1;
 		mask_ioapic(cfg);
 		mask_ioapic(cfg);
 	}
 	}
@@ -3413,6 +3412,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
 	msg.data |= MSI_DATA_VECTOR(cfg->vector);
 	msg.data |= MSI_DATA_VECTOR(cfg->vector);
 	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
 	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+	msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest);
 
 
 	dmar_msi_write(irq, &msg);
 	dmar_msi_write(irq, &msg);
 
 

+ 0 - 7
arch/x86/kernel/apic/probe_64.c

@@ -79,13 +79,6 @@ void __init default_setup_apic_routing(void)
 		/* need to update phys_pkg_id */
 		/* need to update phys_pkg_id */
 		apic->phys_pkg_id = apicid_phys_pkg_id;
 		apic->phys_pkg_id = apicid_phys_pkg_id;
 	}
 	}
-
-	/*
-	 * Now that apic routing model is selected, configure the
-	 * fault handling for intr remapping.
-	 */
-	if (intr_remapping_enabled)
-		enable_drhd_fault_handling();
 }
 }
 
 
 /* Same for both flat and physical. */
 /* Same for both flat and physical. */

+ 7 - 5
arch/x86/kernel/head_32.S

@@ -60,16 +60,18 @@
 #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
 #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
 #endif
 #endif
 
 
+/* Number of possible pages in the lowmem region */
+LOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT)
+	
 /* Enough space to fit pagetables for the low memory linear map */
 /* Enough space to fit pagetables for the low memory linear map */
-MAPPING_BEYOND_END = \
-	PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
+MAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT
 
 
 /*
 /*
  * Worst-case size of the kernel mapping we need to make:
  * Worst-case size of the kernel mapping we need to make:
- * the worst-case size of the kernel itself, plus the extra we need
- * to map for the linear map.
+ * a relocatable kernel can live anywhere in lowmem, so we need to be able
+ * to map all of lowmem.
  */
  */
-KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT
+KERNEL_PAGES = LOWMEM_PAGES
 
 
 INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm
 INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm
 RESERVE_BRK(pagetables, INIT_MAP_SIZE)
 RESERVE_BRK(pagetables, INIT_MAP_SIZE)

+ 16 - 10
arch/x86/kernel/hpet.c

@@ -27,6 +27,9 @@
 #define HPET_DEV_FSB_CAP		0x1000
 #define HPET_DEV_FSB_CAP		0x1000
 #define HPET_DEV_PERI_CAP		0x2000
 #define HPET_DEV_PERI_CAP		0x2000
 
 
+#define HPET_MIN_CYCLES			128
+#define HPET_MIN_PROG_DELTA		(HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
+
 #define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt)
 #define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt)
 
 
 /*
 /*
@@ -299,8 +302,9 @@ static void hpet_legacy_clockevent_register(void)
 	/* Calculate the min / max delta */
 	/* Calculate the min / max delta */
 	hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
 	hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
 							   &hpet_clockevent);
 							   &hpet_clockevent);
-	/* 5 usec minimum reprogramming delta. */
-	hpet_clockevent.min_delta_ns = 5000;
+	/* Setup minimum reprogramming delta. */
+	hpet_clockevent.min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA,
+							   &hpet_clockevent);
 
 
 	/*
 	/*
 	 * Start hpet with the boot cpu mask and make it
 	 * Start hpet with the boot cpu mask and make it
@@ -393,22 +397,24 @@ static int hpet_next_event(unsigned long delta,
 	 * the wraparound into account) nor a simple count down event
 	 * the wraparound into account) nor a simple count down event
 	 * mode. Further the write to the comparator register is
 	 * mode. Further the write to the comparator register is
 	 * delayed internally up to two HPET clock cycles in certain
 	 * delayed internally up to two HPET clock cycles in certain
-	 * chipsets (ATI, ICH9,10). We worked around that by reading
-	 * back the compare register, but that required another
-	 * workaround for ICH9,10 chips where the first readout after
-	 * write can return the old stale value. We already have a
-	 * minimum delta of 5us enforced, but a NMI or SMI hitting
+	 * chipsets (ATI, ICH9,10). Some newer AMD chipsets have even
+	 * longer delays. We worked around that by reading back the
+	 * compare register, but that required another workaround for
+	 * ICH9,10 chips where the first readout after write can
+	 * return the old stale value. We already had a minimum
+	 * programming delta of 5us enforced, but a NMI or SMI hitting
 	 * between the counter readout and the comparator write can
 	 * between the counter readout and the comparator write can
 	 * move us behind that point easily. Now instead of reading
 	 * move us behind that point easily. Now instead of reading
 	 * the compare register back several times, we make the ETIME
 	 * the compare register back several times, we make the ETIME
 	 * decision based on the following: Return ETIME if the
 	 * decision based on the following: Return ETIME if the
-	 * counter value after the write is less than 8 HPET cycles
+	 * counter value after the write is less than HPET_MIN_CYCLES
 	 * away from the event or if the counter is already ahead of
 	 * away from the event or if the counter is already ahead of
-	 * the event.
+	 * the event. The minimum programming delta for the generic
+	 * clockevents code is set to 1.5 * HPET_MIN_CYCLES.
 	 */
 	 */
 	res = (s32)(cnt - hpet_readl(HPET_COUNTER));
 	res = (s32)(cnt - hpet_readl(HPET_COUNTER));
 
 
-	return res < 8 ? -ETIME : 0;
+	return res < HPET_MIN_CYCLES ? -ETIME : 0;
 }
 }
 
 
 static void hpet_legacy_set_mode(enum clock_event_mode mode,
 static void hpet_legacy_set_mode(enum clock_event_mode mode,

+ 5 - 11
arch/x86/kernel/microcode_intel.c

@@ -364,8 +364,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 
 
 		/* For performance reasons, reuse mc area when possible */
 		/* For performance reasons, reuse mc area when possible */
 		if (!mc || mc_size > curr_mc_size) {
 		if (!mc || mc_size > curr_mc_size) {
-			if (mc)
-				vfree(mc);
+			vfree(mc);
 			mc = vmalloc(mc_size);
 			mc = vmalloc(mc_size);
 			if (!mc)
 			if (!mc)
 				break;
 				break;
@@ -374,13 +373,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 
 
 		if (get_ucode_data(mc, ucode_ptr, mc_size) ||
 		if (get_ucode_data(mc, ucode_ptr, mc_size) ||
 		    microcode_sanity_check(mc) < 0) {
 		    microcode_sanity_check(mc) < 0) {
-			vfree(mc);
 			break;
 			break;
 		}
 		}
 
 
 		if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) {
 		if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) {
-			if (new_mc)
-				vfree(new_mc);
+			vfree(new_mc);
 			new_rev = mc_header.rev;
 			new_rev = mc_header.rev;
 			new_mc  = mc;
 			new_mc  = mc;
 			mc = NULL;	/* trigger new vmalloc */
 			mc = NULL;	/* trigger new vmalloc */
@@ -390,12 +387,10 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 		leftover  -= mc_size;
 		leftover  -= mc_size;
 	}
 	}
 
 
-	if (mc)
-		vfree(mc);
+	vfree(mc);
 
 
 	if (leftover) {
 	if (leftover) {
-		if (new_mc)
-			vfree(new_mc);
+		vfree(new_mc);
 		state = UCODE_ERROR;
 		state = UCODE_ERROR;
 		goto out;
 		goto out;
 	}
 	}
@@ -405,8 +400,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 		goto out;
 		goto out;
 	}
 	}
 
 
-	if (uci->mc)
-		vfree(uci->mc);
+	vfree(uci->mc);
 	uci->mc = (struct microcode_intel *)new_mc;
 	uci->mc = (struct microcode_intel *)new_mc;
 
 
 	pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
 	pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",

+ 48 - 0
arch/x86/kernel/resource.c

@@ -0,0 +1,48 @@
+#include <linux/ioport.h>
+#include <asm/e820.h>
+
+static void resource_clip(struct resource *res, resource_size_t start,
+			  resource_size_t end)
+{
+	resource_size_t low = 0, high = 0;
+
+	if (res->end < start || res->start > end)
+		return;		/* no conflict */
+
+	if (res->start < start)
+		low = start - res->start;
+
+	if (res->end > end)
+		high = res->end - end;
+
+	/* Keep the area above or below the conflict, whichever is larger */
+	if (low > high)
+		res->end = start - 1;
+	else
+		res->start = end + 1;
+}
+
+static void remove_e820_regions(struct resource *avail)
+{
+	int i;
+	struct e820entry *entry;
+
+	for (i = 0; i < e820.nr_map; i++) {
+		entry = &e820.map[i];
+
+		resource_clip(avail, entry->addr,
+			      entry->addr + entry->size - 1);
+	}
+}
+
+void arch_remove_reservations(struct resource *avail)
+{
+	/* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */
+	if (avail->flags & IORESOURCE_MEM) {
+		if (avail->start < BIOS_END)
+			avail->start = BIOS_END;
+		resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END);
+
+		remove_e820_regions(avail);
+	}
+}

+ 14 - 4
arch/x86/kernel/setup.c

@@ -501,7 +501,18 @@ static inline unsigned long long get_total_mem(void)
 	return total << PAGE_SHIFT;
 	return total << PAGE_SHIFT;
 }
 }
 
 
-#define DEFAULT_BZIMAGE_ADDR_MAX 0x37FFFFFF
+/*
+ * Keep the crash kernel below this limit.  On 32 bits earlier kernels
+ * would limit the kernel to the low 512 MiB due to mapping restrictions.
+ * On 64 bits, kexec-tools currently limits us to 896 MiB; increase this
+ * limit once kexec-tools are fixed.
+ */
+#ifdef CONFIG_X86_32
+# define CRASH_KERNEL_ADDR_MAX	(512 << 20)
+#else
+# define CRASH_KERNEL_ADDR_MAX	(896 << 20)
+#endif
+
 static void __init reserve_crashkernel(void)
 static void __init reserve_crashkernel(void)
 {
 {
 	unsigned long long total_mem;
 	unsigned long long total_mem;
@@ -520,10 +531,10 @@ static void __init reserve_crashkernel(void)
 		const unsigned long long alignment = 16<<20;	/* 16M */
 		const unsigned long long alignment = 16<<20;	/* 16M */
 
 
 		/*
 		/*
-		 *  kexec want bzImage is below DEFAULT_BZIMAGE_ADDR_MAX
+		 *  kexec want bzImage is below CRASH_KERNEL_ADDR_MAX
 		 */
 		 */
 		crash_base = memblock_find_in_range(alignment,
 		crash_base = memblock_find_in_range(alignment,
-			       DEFAULT_BZIMAGE_ADDR_MAX, crash_size, alignment);
+			       CRASH_KERNEL_ADDR_MAX, crash_size, alignment);
 
 
 		if (crash_base == MEMBLOCK_ERROR) {
 		if (crash_base == MEMBLOCK_ERROR) {
 			pr_info("crashkernel reservation failed - No suitable area found.\n");
 			pr_info("crashkernel reservation failed - No suitable area found.\n");
@@ -769,7 +780,6 @@ void __init setup_arch(char **cmdline_p)
 
 
 	x86_init.oem.arch_setup();
 	x86_init.oem.arch_setup();
 
 
-	resource_alloc_from_bottom = 0;
 	iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1;
 	iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1;
 	setup_memory_map();
 	setup_memory_map();
 	parse_setup_data();
 	parse_setup_data();

+ 2 - 1
arch/x86/kernel/xsave.c

@@ -394,7 +394,8 @@ static void __init setup_xstate_init(void)
 	 * Setup init_xstate_buf to represent the init state of
 	 * Setup init_xstate_buf to represent the init state of
 	 * all the features managed by the xsave
 	 * all the features managed by the xsave
 	 */
 	 */
-	init_xstate_buf = alloc_bootmem(xstate_size);
+	init_xstate_buf = alloc_bootmem_align(xstate_size,
+					      __alignof__(struct xsave_struct));
 	init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT;
 	init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT;
 
 
 	clts();
 	clts();

+ 5 - 13
arch/x86/pci/i386.c

@@ -65,21 +65,13 @@ pcibios_align_resource(void *data, const struct resource *res,
 			resource_size_t size, resource_size_t align)
 			resource_size_t size, resource_size_t align)
 {
 {
 	struct pci_dev *dev = data;
 	struct pci_dev *dev = data;
-	resource_size_t start = round_down(res->end - size + 1, align);
+	resource_size_t start = res->start;
 
 
 	if (res->flags & IORESOURCE_IO) {
 	if (res->flags & IORESOURCE_IO) {
-
-		/*
-		 * If we're avoiding ISA aliases, the largest contiguous I/O
-		 * port space is 256 bytes.  Clearing bits 9 and 10 preserves
-		 * all 256-byte and smaller alignments, so the result will
-		 * still be correctly aligned.
-		 */
-		if (!skip_isa_ioresource_align(dev))
-			start &= ~0x300;
-	} else if (res->flags & IORESOURCE_MEM) {
-		if (start < BIOS_END)
-			start = res->end;	/* fail; no space */
+		if (skip_isa_ioresource_align(dev))
+			return start;
+		if (start & 0x300)
+			start = (start + 0x3ff) & ~0x3ff;
 	}
 	}
 	return start;
 	return start;
 }
 }

+ 2 - 2
arch/x86/vdso/Makefile

@@ -25,7 +25,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
 
 
 export CPPFLAGS_vdso.lds += -P -C
 export CPPFLAGS_vdso.lds += -P -C
 
 
-VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \
+VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 		      	-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
 		      	-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
 
 
 $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
 $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
@@ -69,7 +69,7 @@ vdso32.so-$(VDSO32-y)		+= sysenter
 vdso32-images			= $(vdso32.so-y:%=vdso32-%.so)
 vdso32-images			= $(vdso32.so-y:%=vdso32-%.so)
 
 
 CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
 CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
-VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1
+VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1
 
 
 # This makes sure the $(obj) subdirectory exists even though vdso32/
 # This makes sure the $(obj) subdirectory exists even though vdso32/
 # is not a kbuild sub-make subdirectory.
 # is not a kbuild sub-make subdirectory.

+ 3 - 2
block/blk-map.c

@@ -201,12 +201,13 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
 	for (i = 0; i < iov_count; i++) {
 	for (i = 0; i < iov_count; i++) {
 		unsigned long uaddr = (unsigned long)iov[i].iov_base;
 		unsigned long uaddr = (unsigned long)iov[i].iov_base;
 
 
+		if (!iov[i].iov_len)
+			return -EINVAL;
+
 		if (uaddr & queue_dma_alignment(q)) {
 		if (uaddr & queue_dma_alignment(q)) {
 			unaligned = 1;
 			unaligned = 1;
 			break;
 			break;
 		}
 		}
-		if (!iov[i].iov_len)
-			return -EINVAL;
 	}
 	}
 
 
 	if (unaligned || (q->dma_pad_mask & len) || map_data)
 	if (unaligned || (q->dma_pad_mask & len) || map_data)

+ 3 - 3
block/blk-merge.c

@@ -21,7 +21,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
 		return 0;
 		return 0;
 
 
 	fbio = bio;
 	fbio = bio;
-	cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+	cluster = blk_queue_cluster(q);
 	seg_size = 0;
 	seg_size = 0;
 	nr_phys_segs = 0;
 	nr_phys_segs = 0;
 	for_each_bio(bio) {
 	for_each_bio(bio) {
@@ -87,7 +87,7 @@ EXPORT_SYMBOL(blk_recount_segments);
 static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
 static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
 				   struct bio *nxt)
 				   struct bio *nxt)
 {
 {
-	if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
+	if (!blk_queue_cluster(q))
 		return 0;
 		return 0;
 
 
 	if (bio->bi_seg_back_size + nxt->bi_seg_front_size >
 	if (bio->bi_seg_back_size + nxt->bi_seg_front_size >
@@ -123,7 +123,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
 	int nsegs, cluster;
 	int nsegs, cluster;
 
 
 	nsegs = 0;
 	nsegs = 0;
-	cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+	cluster = blk_queue_cluster(q);
 
 
 	/*
 	/*
 	 * for each bio in rq
 	 * for each bio in rq

+ 22 - 29
block/blk-settings.c

@@ -126,7 +126,7 @@ void blk_set_default_limits(struct queue_limits *lim)
 	lim->alignment_offset = 0;
 	lim->alignment_offset = 0;
 	lim->io_opt = 0;
 	lim->io_opt = 0;
 	lim->misaligned = 0;
 	lim->misaligned = 0;
-	lim->no_cluster = 0;
+	lim->cluster = 1;
 }
 }
 EXPORT_SYMBOL(blk_set_default_limits);
 EXPORT_SYMBOL(blk_set_default_limits);
 
 
@@ -229,8 +229,8 @@ void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask)
 EXPORT_SYMBOL(blk_queue_bounce_limit);
 EXPORT_SYMBOL(blk_queue_bounce_limit);
 
 
 /**
 /**
- * blk_queue_max_hw_sectors - set max sectors for a request for this queue
- * @q:  the request queue for the device
+ * blk_limits_max_hw_sectors - set hard and soft limit of max sectors for request
+ * @limits: the queue limits
  * @max_hw_sectors:  max hardware sectors in the usual 512b unit
  * @max_hw_sectors:  max hardware sectors in the usual 512b unit
  *
  *
  * Description:
  * Description:
@@ -244,7 +244,7 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);
  *    per-device basis in /sys/block/<device>/queue/max_sectors_kb.
  *    per-device basis in /sys/block/<device>/queue/max_sectors_kb.
  *    The soft limit can not exceed max_hw_sectors.
  *    The soft limit can not exceed max_hw_sectors.
  **/
  **/
-void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors)
+void blk_limits_max_hw_sectors(struct queue_limits *limits, unsigned int max_hw_sectors)
 {
 {
 	if ((max_hw_sectors << 9) < PAGE_CACHE_SIZE) {
 	if ((max_hw_sectors << 9) < PAGE_CACHE_SIZE) {
 		max_hw_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
 		max_hw_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
@@ -252,9 +252,23 @@ void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_secto
 		       __func__, max_hw_sectors);
 		       __func__, max_hw_sectors);
 	}
 	}
 
 
-	q->limits.max_hw_sectors = max_hw_sectors;
-	q->limits.max_sectors = min_t(unsigned int, max_hw_sectors,
-				      BLK_DEF_MAX_SECTORS);
+	limits->max_hw_sectors = max_hw_sectors;
+	limits->max_sectors = min_t(unsigned int, max_hw_sectors,
+				    BLK_DEF_MAX_SECTORS);
+}
+EXPORT_SYMBOL(blk_limits_max_hw_sectors);
+
+/**
+ * blk_queue_max_hw_sectors - set max sectors for a request for this queue
+ * @q:  the request queue for the device
+ * @max_hw_sectors:  max hardware sectors in the usual 512b unit
+ *
+ * Description:
+ *    See description for blk_limits_max_hw_sectors().
+ **/
+void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors)
+{
+	blk_limits_max_hw_sectors(&q->limits, max_hw_sectors);
 }
 }
 EXPORT_SYMBOL(blk_queue_max_hw_sectors);
 EXPORT_SYMBOL(blk_queue_max_hw_sectors);
 
 
@@ -464,15 +478,6 @@ EXPORT_SYMBOL(blk_queue_io_opt);
 void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
 void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
 {
 {
 	blk_stack_limits(&t->limits, &b->limits, 0);
 	blk_stack_limits(&t->limits, &b->limits, 0);
-
-	if (!t->queue_lock)
-		WARN_ON_ONCE(1);
-	else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
-		unsigned long flags;
-		spin_lock_irqsave(t->queue_lock, flags);
-		queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
-		spin_unlock_irqrestore(t->queue_lock, flags);
-	}
 }
 }
 EXPORT_SYMBOL(blk_queue_stack_limits);
 EXPORT_SYMBOL(blk_queue_stack_limits);
 
 
@@ -545,7 +550,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
 	t->io_min = max(t->io_min, b->io_min);
 	t->io_min = max(t->io_min, b->io_min);
 	t->io_opt = lcm(t->io_opt, b->io_opt);
 	t->io_opt = lcm(t->io_opt, b->io_opt);
 
 
-	t->no_cluster |= b->no_cluster;
+	t->cluster &= b->cluster;
 	t->discard_zeroes_data &= b->discard_zeroes_data;
 	t->discard_zeroes_data &= b->discard_zeroes_data;
 
 
 	/* Physical block size a multiple of the logical block size? */
 	/* Physical block size a multiple of the logical block size? */
@@ -641,7 +646,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
 		       sector_t offset)
 		       sector_t offset)
 {
 {
 	struct request_queue *t = disk->queue;
 	struct request_queue *t = disk->queue;
-	struct request_queue *b = bdev_get_queue(bdev);
 
 
 	if (bdev_stack_limits(&t->limits, bdev, offset >> 9) < 0) {
 	if (bdev_stack_limits(&t->limits, bdev, offset >> 9) < 0) {
 		char top[BDEVNAME_SIZE], bottom[BDEVNAME_SIZE];
 		char top[BDEVNAME_SIZE], bottom[BDEVNAME_SIZE];
@@ -652,17 +656,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
 		printk(KERN_NOTICE "%s: Warning: Device %s is misaligned\n",
 		printk(KERN_NOTICE "%s: Warning: Device %s is misaligned\n",
 		       top, bottom);
 		       top, bottom);
 	}
 	}
-
-	if (!t->queue_lock)
-		WARN_ON_ONCE(1);
-	else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
-		unsigned long flags;
-
-		spin_lock_irqsave(t->queue_lock, flags);
-		if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags))
-			queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
-		spin_unlock_irqrestore(t->queue_lock, flags);
-	}
 }
 }
 EXPORT_SYMBOL(disk_stack_limits);
 EXPORT_SYMBOL(disk_stack_limits);
 
 

+ 1 - 1
block/blk-sysfs.c

@@ -119,7 +119,7 @@ static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *
 
 
 static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)
 static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)
 {
 {
-	if (test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
+	if (blk_queue_cluster(q))
 		return queue_var_show(queue_max_segment_size(q), (page));
 		return queue_var_show(queue_max_segment_size(q), (page));
 
 
 	return queue_var_show(PAGE_CACHE_SIZE, (page));
 	return queue_var_show(PAGE_CACHE_SIZE, (page));

+ 25 - 14
block/blk-throttle.c

@@ -355,6 +355,12 @@ throtl_start_new_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
 			tg->slice_end[rw], jiffies);
 			tg->slice_end[rw], jiffies);
 }
 }
 
 
+static inline void throtl_set_slice_end(struct throtl_data *td,
+		struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
+{
+	tg->slice_end[rw] = roundup(jiffy_end, throtl_slice);
+}
+
 static inline void throtl_extend_slice(struct throtl_data *td,
 static inline void throtl_extend_slice(struct throtl_data *td,
 		struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
 		struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
 {
 {
@@ -391,6 +397,16 @@ throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
 	if (throtl_slice_used(td, tg, rw))
 	if (throtl_slice_used(td, tg, rw))
 		return;
 		return;
 
 
+	/*
+	 * A bio has been dispatched. Also adjust slice_end. It might happen
+	 * that initially cgroup limit was very low resulting in high
+	 * slice_end, but later limit was bumped up and bio was dispached
+	 * sooner, then we need to reduce slice_end. A high bogus slice_end
+	 * is bad because it does not allow new slice to start.
+	 */
+
+	throtl_set_slice_end(td, tg, rw, jiffies + throtl_slice);
+
 	time_elapsed = jiffies - tg->slice_start[rw];
 	time_elapsed = jiffies - tg->slice_start[rw];
 
 
 	nr_slices = time_elapsed / throtl_slice;
 	nr_slices = time_elapsed / throtl_slice;
@@ -709,26 +725,21 @@ static void throtl_process_limit_change(struct throtl_data *td)
 	struct throtl_grp *tg;
 	struct throtl_grp *tg;
 	struct hlist_node *pos, *n;
 	struct hlist_node *pos, *n;
 
 
-	/*
-	 * Make sure atomic_inc() effects from
-	 * throtl_update_blkio_group_read_bps(), group of functions are
-	 * visible.
-	 * Is this required or smp_mb__after_atomic_inc() was suffcient
-	 * after the atomic_inc().
-	 */
-	smp_rmb();
 	if (!atomic_read(&td->limits_changed))
 	if (!atomic_read(&td->limits_changed))
 		return;
 		return;
 
 
 	throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed));
 	throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed));
 
 
-	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
-		/*
-		 * Do I need an smp_rmb() here to make sure tg->limits_changed
-		 * update is visible. I am relying on smp_rmb() at the
-		 * beginning of function and not putting a new one here.
-		 */
+	/*
+	 * Make sure updates from throtl_update_blkio_group_read_bps() group
+	 * of functions to tg->limits_changed are visible. We do not
+	 * want update td->limits_changed to be visible but update to
+	 * tg->limits_changed not being visible yet on this cpu. Hence
+	 * the read barrier.
+	 */
+	smp_rmb();
 
 
+	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
 		if (throtl_tg_on_rr(tg) && tg->limits_changed) {
 		if (throtl_tg_on_rr(tg) && tg->limits_changed) {
 			throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
 			throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
 				" riops=%u wiops=%u", tg->bps[READ],
 				" riops=%u wiops=%u", tg->bps[READ],

+ 3 - 0
drivers/acpi/acpica/evgpeinit.c

@@ -408,6 +408,9 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
 		return_ACPI_STATUS(AE_OK);
 		return_ACPI_STATUS(AE_OK);
 	}
 	}
 
 
+	/* Disable the GPE in case it's been enabled already. */
+	(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
+
 	/*
 	/*
 	 * Add the GPE information from above to the gpe_event_info block for
 	 * Add the GPE information from above to the gpe_event_info block for
 	 * use during dispatch of this GPE.
 	 * use during dispatch of this GPE.

+ 0 - 5
drivers/acpi/battery.c

@@ -130,8 +130,6 @@ struct acpi_battery {
 	unsigned long flags;
 	unsigned long flags;
 };
 };
 
 
-static int acpi_battery_update(struct acpi_battery *battery);
-
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
 
 
 inline int acpi_battery_present(struct acpi_battery *battery)
 inline int acpi_battery_present(struct acpi_battery *battery)
@@ -186,9 +184,6 @@ static int acpi_battery_get_property(struct power_supply *psy,
 	int ret = 0;
 	int ret = 0;
 	struct acpi_battery *battery = to_acpi_battery(psy);
 	struct acpi_battery *battery = to_acpi_battery(psy);
 
 
-	if (acpi_battery_update(battery))
-		return -ENODEV;
-
 	if (acpi_battery_present(battery)) {
 	if (acpi_battery_present(battery)) {
 		/* run battery update only if it is present */
 		/* run battery update only if it is present */
 		acpi_battery_get_state(battery);
 		acpi_battery_get_state(battery);

+ 60 - 37
drivers/acpi/scan.c

@@ -705,54 +705,85 @@ static int acpi_bus_get_perf_flags(struct acpi_device *device)
 }
 }
 
 
 static acpi_status
 static acpi_status
-acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
-					     union acpi_object *package)
+acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
+					     struct acpi_device_wakeup *wakeup)
 {
 {
-	int i = 0;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *package = NULL;
 	union acpi_object *element = NULL;
 	union acpi_object *element = NULL;
+	acpi_status status;
+	int i = 0;
 
 
-	if (!device || !package || (package->package.count < 2))
+	if (!wakeup)
 		return AE_BAD_PARAMETER;
 		return AE_BAD_PARAMETER;
 
 
+	/* _PRW */
+	status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer);
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));
+		return status;
+	}
+
+	package = (union acpi_object *)buffer.pointer;
+
+	if (!package || (package->package.count < 2)) {
+		status = AE_BAD_DATA;
+		goto out;
+	}
+
 	element = &(package->package.elements[0]);
 	element = &(package->package.elements[0]);
-	if (!element)
-		return AE_BAD_PARAMETER;
+	if (!element) {
+		status = AE_BAD_DATA;
+		goto out;
+	}
 	if (element->type == ACPI_TYPE_PACKAGE) {
 	if (element->type == ACPI_TYPE_PACKAGE) {
 		if ((element->package.count < 2) ||
 		if ((element->package.count < 2) ||
 		    (element->package.elements[0].type !=
 		    (element->package.elements[0].type !=
 		     ACPI_TYPE_LOCAL_REFERENCE)
 		     ACPI_TYPE_LOCAL_REFERENCE)
-		    || (element->package.elements[1].type != ACPI_TYPE_INTEGER))
-			return AE_BAD_DATA;
-		device->wakeup.gpe_device =
+		    || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) {
+			status = AE_BAD_DATA;
+			goto out;
+		}
+		wakeup->gpe_device =
 		    element->package.elements[0].reference.handle;
 		    element->package.elements[0].reference.handle;
-		device->wakeup.gpe_number =
+		wakeup->gpe_number =
 		    (u32) element->package.elements[1].integer.value;
 		    (u32) element->package.elements[1].integer.value;
 	} else if (element->type == ACPI_TYPE_INTEGER) {
 	} else if (element->type == ACPI_TYPE_INTEGER) {
-		device->wakeup.gpe_number = element->integer.value;
-	} else
-		return AE_BAD_DATA;
+		wakeup->gpe_device = NULL;
+		wakeup->gpe_number = element->integer.value;
+	} else {
+		status = AE_BAD_DATA;
+		goto out;
+	}
 
 
 	element = &(package->package.elements[1]);
 	element = &(package->package.elements[1]);
 	if (element->type != ACPI_TYPE_INTEGER) {
 	if (element->type != ACPI_TYPE_INTEGER) {
-		return AE_BAD_DATA;
+		status = AE_BAD_DATA;
+		goto out;
 	}
 	}
-	device->wakeup.sleep_state = element->integer.value;
+	wakeup->sleep_state = element->integer.value;
 
 
 	if ((package->package.count - 2) > ACPI_MAX_HANDLES) {
 	if ((package->package.count - 2) > ACPI_MAX_HANDLES) {
-		return AE_NO_MEMORY;
+		status = AE_NO_MEMORY;
+		goto out;
 	}
 	}
-	device->wakeup.resources.count = package->package.count - 2;
-	for (i = 0; i < device->wakeup.resources.count; i++) {
+	wakeup->resources.count = package->package.count - 2;
+	for (i = 0; i < wakeup->resources.count; i++) {
 		element = &(package->package.elements[i + 2]);
 		element = &(package->package.elements[i + 2]);
-		if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
-			return AE_BAD_DATA;
+		if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
+			status = AE_BAD_DATA;
+			goto out;
+		}
 
 
-		device->wakeup.resources.handles[i] = element->reference.handle;
+		wakeup->resources.handles[i] = element->reference.handle;
 	}
 	}
 
 
-	acpi_gpe_can_wake(device->wakeup.gpe_device, device->wakeup.gpe_number);
+	acpi_gpe_can_wake(wakeup->gpe_device, wakeup->gpe_number);
 
 
-	return AE_OK;
+ out:
+	kfree(buffer.pointer);
+
+	return status;
 }
 }
 
 
 static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
 static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
@@ -787,26 +818,15 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
 static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
 static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
 {
 {
 	acpi_status status = 0;
 	acpi_status status = 0;
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-	union acpi_object *package = NULL;
 	int psw_error;
 	int psw_error;
 
 
-	/* _PRW */
-	status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));
-		goto end;
-	}
-
-	package = (union acpi_object *)buffer.pointer;
-	status = acpi_bus_extract_wakeup_device_power_package(device, package);
+	status = acpi_bus_extract_wakeup_device_power_package(device->handle,
+							      &device->wakeup);
 	if (ACPI_FAILURE(status)) {
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
 		ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
 		goto end;
 		goto end;
 	}
 	}
 
 
-	kfree(buffer.pointer);
-
 	device->wakeup.flags.valid = 1;
 	device->wakeup.flags.valid = 1;
 	device->wakeup.prepare_count = 0;
 	device->wakeup.prepare_count = 0;
 	acpi_bus_set_run_wake_flags(device);
 	acpi_bus_set_run_wake_flags(device);
@@ -1351,6 +1371,7 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
 	struct acpi_bus_ops *ops = context;
 	struct acpi_bus_ops *ops = context;
 	int type;
 	int type;
 	unsigned long long sta;
 	unsigned long long sta;
+	struct acpi_device_wakeup wakeup;
 	struct acpi_device *device;
 	struct acpi_device *device;
 	acpi_status status;
 	acpi_status status;
 	int result;
 	int result;
@@ -1360,8 +1381,10 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
 		return AE_OK;
 		return AE_OK;
 
 
 	if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
 	if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
-	    !(sta & ACPI_STA_DEVICE_FUNCTIONING))
+	    !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
+		acpi_bus_extract_wakeup_device_power_package(handle, &wakeup);
 		return AE_CTRL_DEPTH;
 		return AE_CTRL_DEPTH;
+	}
 
 
 	/*
 	/*
 	 * We may already have an acpi_device from a previous enumeration.  If
 	 * We may already have an acpi_device from a previous enumeration.  If

+ 11 - 11
drivers/ata/Kconfig

@@ -128,16 +128,6 @@ config PDC_ADMA
 
 
 	  If unsure, say N.
 	  If unsure, say N.
 
 
-config PATA_MPC52xx
-	tristate "Freescale MPC52xx SoC internal IDE"
-	depends on PPC_MPC52xx && PPC_BESTCOMM
-	select PPC_BESTCOMM_ATA
-	help
-	  This option enables support for integrated IDE controller
-	  of the Freescale MPC52xx SoC.
-
-	  If unsure, say N.
-
 config PATA_OCTEON_CF
 config PATA_OCTEON_CF
 	tristate "OCTEON Boot Bus Compact Flash support"
 	tristate "OCTEON Boot Bus Compact Flash support"
 	depends on CPU_CAVIUM_OCTEON
 	depends on CPU_CAVIUM_OCTEON
@@ -366,7 +356,7 @@ config PATA_CS5535
 
 
 config PATA_CS5536
 config PATA_CS5536
 	tristate "CS5536 PATA support"
 	tristate "CS5536 PATA support"
-	depends on PCI && X86 && !X86_64
+	depends on PCI
 	help
 	help
 	  This option enables support for the AMD CS5536
 	  This option enables support for the AMD CS5536
 	  companion chip used with the Geode LX processor family.
 	  companion chip used with the Geode LX processor family.
@@ -491,6 +481,16 @@ config PATA_MARVELL
 
 
 	  If unsure, say N.
 	  If unsure, say N.
 
 
+config PATA_MPC52xx
+	tristate "Freescale MPC52xx SoC internal IDE"
+	depends on PPC_MPC52xx && PPC_BESTCOMM
+	select PPC_BESTCOMM_ATA
+	help
+	  This option enables support for integrated IDE controller
+	  of the Freescale MPC52xx SoC.
+
+	  If unsure, say N.
+
 config PATA_NETCELL
 config PATA_NETCELL
 	tristate "NETCELL Revolution RAID support"
 	tristate "NETCELL Revolution RAID support"
 	depends on PCI
 	depends on PCI

+ 1 - 1
drivers/ata/Makefile

@@ -11,7 +11,6 @@ obj-$(CONFIG_SATA_DWC)		+= sata_dwc_460ex.o
 
 
 # SFF w/ custom DMA
 # SFF w/ custom DMA
 obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o
 obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o
-obj-$(CONFIG_PATA_MPC52xx)	+= pata_mpc52xx.o
 obj-$(CONFIG_PATA_OCTEON_CF)	+= pata_octeon_cf.o
 obj-$(CONFIG_PATA_OCTEON_CF)	+= pata_octeon_cf.o
 obj-$(CONFIG_SATA_QSTOR)	+= sata_qstor.o
 obj-$(CONFIG_SATA_QSTOR)	+= sata_qstor.o
 obj-$(CONFIG_SATA_SX4)		+= sata_sx4.o
 obj-$(CONFIG_SATA_SX4)		+= sata_sx4.o
@@ -52,6 +51,7 @@ obj-$(CONFIG_PATA_IT821X)	+= pata_it821x.o
 obj-$(CONFIG_PATA_JMICRON)	+= pata_jmicron.o
 obj-$(CONFIG_PATA_JMICRON)	+= pata_jmicron.o
 obj-$(CONFIG_PATA_MACIO)	+= pata_macio.o
 obj-$(CONFIG_PATA_MACIO)	+= pata_macio.o
 obj-$(CONFIG_PATA_MARVELL)	+= pata_marvell.o
 obj-$(CONFIG_PATA_MARVELL)	+= pata_marvell.o
+obj-$(CONFIG_PATA_MPC52xx)	+= pata_mpc52xx.o
 obj-$(CONFIG_PATA_NETCELL)	+= pata_netcell.o
 obj-$(CONFIG_PATA_NETCELL)	+= pata_netcell.o
 obj-$(CONFIG_PATA_NINJA32)	+= pata_ninja32.o
 obj-$(CONFIG_PATA_NINJA32)	+= pata_ninja32.o
 obj-$(CONFIG_PATA_NS87415)	+= pata_ns87415.o
 obj-$(CONFIG_PATA_NS87415)	+= pata_ns87415.o

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

@@ -4807,9 +4807,6 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc)
 {
 {
 	struct ata_device *dev = qc->dev;
 	struct ata_device *dev = qc->dev;
 
 
-	if (ata_tag_internal(qc->tag))
-		return;
-
 	if (ata_is_nodata(qc->tf.protocol))
 	if (ata_is_nodata(qc->tf.protocol))
 		return;
 		return;
 
 
@@ -4858,14 +4855,23 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
 		if (unlikely(qc->err_mask))
 		if (unlikely(qc->err_mask))
 			qc->flags |= ATA_QCFLAG_FAILED;
 			qc->flags |= ATA_QCFLAG_FAILED;
 
 
-		if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
-			/* always fill result TF for failed qc */
+		/*
+		 * Finish internal commands without any further processing
+		 * and always with the result TF filled.
+		 */
+		if (unlikely(ata_tag_internal(qc->tag))) {
 			fill_result_tf(qc);
 			fill_result_tf(qc);
+			__ata_qc_complete(qc);
+			return;
+		}
 
 
-			if (!ata_tag_internal(qc->tag))
-				ata_qc_schedule_eh(qc);
-			else
-				__ata_qc_complete(qc);
+		/*
+		 * Non-internal qc has failed.  Fill the result TF and
+		 * summon EH.
+		 */
+		if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
+			fill_result_tf(qc);
+			ata_qc_schedule_eh(qc);
 			return;
 			return;
 		}
 		}
 
 

+ 14 - 3
drivers/ata/libata-eh.c

@@ -3275,6 +3275,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 	struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;
 	struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;
 	struct ata_eh_context *ehc = &link->eh_context;
 	struct ata_eh_context *ehc = &link->eh_context;
 	struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
 	struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
+	enum ata_lpm_policy old_policy = link->lpm_policy;
 	unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
 	unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
 	unsigned int err_mask;
 	unsigned int err_mask;
 	int rc;
 	int rc;
@@ -3338,6 +3339,14 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 		goto fail;
 		goto fail;
 	}
 	}
 
 
+	/*
+	 * Low level driver acked the transition.  Issue DIPM command
+	 * with the new policy set.
+	 */
+	link->lpm_policy = policy;
+	if (ap && ap->slave_link)
+		ap->slave_link->lpm_policy = policy;
+
 	/* host config updated, enable DIPM if transitioning to MIN_POWER */
 	/* host config updated, enable DIPM if transitioning to MIN_POWER */
 	ata_for_each_dev(dev, link, ENABLED) {
 	ata_for_each_dev(dev, link, ENABLED) {
 		if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) {
 		if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) {
@@ -3353,12 +3362,14 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 		}
 		}
 	}
 	}
 
 
-	link->lpm_policy = policy;
-	if (ap && ap->slave_link)
-		ap->slave_link->lpm_policy = policy;
 	return 0;
 	return 0;
 
 
 fail:
 fail:
+	/* restore the old policy */
+	link->lpm_policy = old_policy;
+	if (ap && ap->slave_link)
+		ap->slave_link->lpm_policy = old_policy;
+
 	/* if no device or only one more chance is left, disable LPM */
 	/* if no device or only one more chance is left, disable LPM */
 	if (!dev || ehc->tries[dev->devno] <= 2) {
 	if (!dev || ehc->tries[dev->devno] <= 2) {
 		ata_link_printk(link, KERN_WARNING,
 		ata_link_printk(link, KERN_WARNING,

+ 3 - 4
drivers/ata/libata-sff.c

@@ -1532,11 +1532,10 @@ static unsigned int __ata_sff_port_intr(struct ata_port *ap,
 		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
 		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
 			return ata_sff_idle_irq(ap);
 			return ata_sff_idle_irq(ap);
 		break;
 		break;
-	case HSM_ST:
-	case HSM_ST_LAST:
-		break;
-	default:
+	case HSM_ST_IDLE:
 		return ata_sff_idle_irq(ap);
 		return ata_sff_idle_irq(ap);
+	default:
+		break;
 	}
 	}
 
 
 	/* check main status, clearing INTRQ if needed */
 	/* check main status, clearing INTRQ if needed */

+ 14 - 6
drivers/ata/pata_cs5536.c

@@ -37,10 +37,22 @@
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/libata.h>
 #include <linux/libata.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_host.h>
+
+#ifdef CONFIG_X86_32
 #include <asm/msr.h>
 #include <asm/msr.h>
+static int use_msr;
+module_param_named(msr, use_msr, int, 0644);
+MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");
+#else
+#undef rdmsr	/* avoid accidental MSR usage on, e.g. x86-64 */
+#undef wrmsr
+#define rdmsr(x, y, z) do { } while (0)
+#define wrmsr(x, y, z) do { } while (0)
+#define use_msr 0
+#endif
 
 
 #define DRV_NAME	"pata_cs5536"
 #define DRV_NAME	"pata_cs5536"
-#define DRV_VERSION	"0.0.7"
+#define DRV_VERSION	"0.0.8"
 
 
 enum {
 enum {
 	CFG			= 0,
 	CFG			= 0,
@@ -75,8 +87,6 @@ enum {
 	IDE_ETC_NODMA		= 0x03,
 	IDE_ETC_NODMA		= 0x03,
 };
 };
 
 
-static int use_msr;
-
 static const u32 msr_reg[4] = {
 static const u32 msr_reg[4] = {
 	MSR_IDE_CFG, MSR_IDE_DTC, MSR_IDE_CAST, MSR_IDE_ETC,
 	MSR_IDE_CFG, MSR_IDE_DTC, MSR_IDE_CAST, MSR_IDE_ETC,
 };
 };
@@ -88,7 +98,7 @@ static const u8 pci_reg[4] = {
 static inline int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
 static inline int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
 {
 {
 	if (unlikely(use_msr)) {
 	if (unlikely(use_msr)) {
-		u32 dummy;
+		u32 dummy __maybe_unused;
 
 
 		rdmsr(msr_reg[reg], *val, dummy);
 		rdmsr(msr_reg[reg], *val, dummy);
 		return 0;
 		return 0;
@@ -294,8 +304,6 @@ MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, cs5536);
 MODULE_DEVICE_TABLE(pci, cs5536);
 MODULE_VERSION(DRV_VERSION);
 MODULE_VERSION(DRV_VERSION);
-module_param_named(msr, use_msr, int, 0644);
-MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");
 
 
 module_init(cs5536_init);
 module_init(cs5536_init);
 module_exit(cs5536_exit);
 module_exit(cs5536_exit);

+ 2 - 0
drivers/block/cciss.c

@@ -2834,6 +2834,8 @@ static int cciss_revalidate(struct gendisk *disk)
 	InquiryData_struct *inq_buff = NULL;
 	InquiryData_struct *inq_buff = NULL;
 
 
 	for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
 	for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
+		if (!h->drv[logvol])
+			continue;
 		if (memcmp(h->drv[logvol]->LunID, drv->LunID,
 		if (memcmp(h->drv[logvol]->LunID, drv->LunID,
 			sizeof(drv->LunID)) == 0) {
 			sizeof(drv->LunID)) == 0) {
 			FOUND = 1;
 			FOUND = 1;

+ 8 - 6
drivers/block/drbd/drbd_receiver.c

@@ -3627,17 +3627,19 @@ static void drbdd(struct drbd_conf *mdev)
 		}
 		}
 
 
 		shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header);
 		shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header);
-		rv = drbd_recv(mdev, &header->h80.payload, shs);
-		if (unlikely(rv != shs)) {
-			dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
-			goto err_out;
-		}
-
 		if (packet_size - shs > 0 && !drbd_cmd_handler[cmd].expect_payload) {
 		if (packet_size - shs > 0 && !drbd_cmd_handler[cmd].expect_payload) {
 			dev_err(DEV, "No payload expected %s l:%d\n", cmdname(cmd), packet_size);
 			dev_err(DEV, "No payload expected %s l:%d\n", cmdname(cmd), packet_size);
 			goto err_out;
 			goto err_out;
 		}
 		}
 
 
+		if (shs) {
+			rv = drbd_recv(mdev, &header->h80.payload, shs);
+			if (unlikely(rv != shs)) {
+				dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
+				goto err_out;
+			}
+		}
+
 		rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs);
 		rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs);
 
 
 		if (unlikely(!rv)) {
 		if (unlikely(!rv)) {

+ 2 - 1
drivers/block/drbd/drbd_req.h

@@ -339,7 +339,8 @@ static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)
 }
 }
 
 
 /* completion of master bio is outside of spinlock.
 /* completion of master bio is outside of spinlock.
- * If you need it irqsave, do it your self! */
+ * If you need it irqsave, do it your self!
+ * Which means: don't use from bio endio callback. */
 static inline int req_mod(struct drbd_request *req,
 static inline int req_mod(struct drbd_request *req,
 		enum drbd_req_event what)
 		enum drbd_req_event what)
 {
 {

+ 9 - 1
drivers/block/drbd/drbd_worker.c

@@ -193,8 +193,10 @@ void drbd_endio_sec(struct bio *bio, int error)
  */
  */
 void drbd_endio_pri(struct bio *bio, int error)
 void drbd_endio_pri(struct bio *bio, int error)
 {
 {
+	unsigned long flags;
 	struct drbd_request *req = bio->bi_private;
 	struct drbd_request *req = bio->bi_private;
 	struct drbd_conf *mdev = req->mdev;
 	struct drbd_conf *mdev = req->mdev;
+	struct bio_and_error m;
 	enum drbd_req_event what;
 	enum drbd_req_event what;
 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
 
 
@@ -220,7 +222,13 @@ void drbd_endio_pri(struct bio *bio, int error)
 	bio_put(req->private_bio);
 	bio_put(req->private_bio);
 	req->private_bio = ERR_PTR(error);
 	req->private_bio = ERR_PTR(error);
 
 
-	req_mod(req, what);
+	/* not req_mod(), we need irqsave here! */
+	spin_lock_irqsave(&mdev->req_lock, flags);
+	__req_mod(req, what, &m);
+	spin_unlock_irqrestore(&mdev->req_lock, flags);
+
+	if (m.bio)
+		complete_master_bio(mdev, &m);
 }
 }
 
 
 int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
 int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)

+ 4 - 2
drivers/bluetooth/hci_ldisc.c

@@ -311,8 +311,10 @@ static void hci_uart_tty_close(struct tty_struct *tty)
 
 
 		if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
 		if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
 			hu->proto->close(hu);
 			hu->proto->close(hu);
-			hci_unregister_dev(hdev);
-			hci_free_dev(hdev);
+			if (hdev) {
+				hci_unregister_dev(hdev);
+				hci_free_dev(hdev);
+			}
 		}
 		}
 	}
 	}
 }
 }

+ 9 - 2
drivers/char/agp/intel-gtt.c

@@ -1192,12 +1192,19 @@ static void i9xx_chipset_flush(void)
 		writel(1, intel_private.i9xx_flush_page);
 		writel(1, intel_private.i9xx_flush_page);
 }
 }
 
 
-static void i965_write_entry(dma_addr_t addr, unsigned int entry,
+static void i965_write_entry(dma_addr_t addr,
+			     unsigned int entry,
 			     unsigned int flags)
 			     unsigned int flags)
 {
 {
+	u32 pte_flags;
+
+	pte_flags = I810_PTE_VALID;
+	if (flags == AGP_USER_CACHED_MEMORY)
+		pte_flags |= I830_PTE_SYSTEM_CACHED;
+
 	/* Shift high bits down */
 	/* Shift high bits down */
 	addr |= (addr >> 28) & 0xf0;
 	addr |= (addr >> 28) & 0xf0;
-	writel(addr | I810_PTE_VALID, intel_private.gtt + entry);
+	writel(addr | pte_flags, intel_private.gtt + entry);
 }
 }
 
 
 static bool gen6_check_flags(unsigned int flags)
 static bool gen6_check_flags(unsigned int flags)

+ 7 - 5
drivers/char/ramoops.c

@@ -29,7 +29,6 @@
 #include <linux/ramoops.h>
 #include <linux/ramoops.h>
 
 
 #define RAMOOPS_KERNMSG_HDR "===="
 #define RAMOOPS_KERNMSG_HDR "===="
-#define RAMOOPS_HEADER_SIZE   (5 + sizeof(struct timeval))
 
 
 #define RECORD_SIZE 4096
 #define RECORD_SIZE 4096
 
 
@@ -65,8 +64,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
 			struct ramoops_context, dump);
 			struct ramoops_context, dump);
 	unsigned long s1_start, s2_start;
 	unsigned long s1_start, s2_start;
 	unsigned long l1_cpy, l2_cpy;
 	unsigned long l1_cpy, l2_cpy;
-	int res;
-	char *buf;
+	int res, hdr_size;
+	char *buf, *buf_orig;
 	struct timeval timestamp;
 	struct timeval timestamp;
 
 
 	/* Only dump oopses if dump_oops is set */
 	/* Only dump oopses if dump_oops is set */
@@ -74,6 +73,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
 		return;
 		return;
 
 
 	buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE));
 	buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE));
+	buf_orig = buf;
+
 	memset(buf, '\0', RECORD_SIZE);
 	memset(buf, '\0', RECORD_SIZE);
 	res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
 	res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
 	buf += res;
 	buf += res;
@@ -81,8 +82,9 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
 	res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec);
 	res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec);
 	buf += res;
 	buf += res;
 
 
-	l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE));
-	l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE) - l2_cpy);
+	hdr_size = buf - buf_orig;
+	l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - hdr_size));
+	l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - hdr_size) - l2_cpy);
 
 
 	s2_start = l2 - l2_cpy;
 	s2_start = l2 - l2_cpy;
 	s1_start = l1 - l1_cpy;
 	s1_start = l1 - l1_cpy;

+ 11 - 6
drivers/clocksource/sh_cmt.c

@@ -283,16 +283,21 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
 	} while (delay);
 	} while (delay);
 }
 }
 
 
-static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
+static void __sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
 {
 {
-	unsigned long flags;
-
 	if (delta > p->max_match_value)
 	if (delta > p->max_match_value)
 		dev_warn(&p->pdev->dev, "delta out of range\n");
 		dev_warn(&p->pdev->dev, "delta out of range\n");
 
 
-	spin_lock_irqsave(&p->lock, flags);
 	p->next_match_value = delta;
 	p->next_match_value = delta;
 	sh_cmt_clock_event_program_verify(p, 0);
 	sh_cmt_clock_event_program_verify(p, 0);
+}
+
+static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&p->lock, flags);
+	__sh_cmt_set_next(p, delta);
 	spin_unlock_irqrestore(&p->lock, flags);
 	spin_unlock_irqrestore(&p->lock, flags);
 }
 }
 
 
@@ -359,7 +364,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)
 
 
 	/* setup timeout if no clockevent */
 	/* setup timeout if no clockevent */
 	if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT)))
 	if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT)))
-		sh_cmt_set_next(p, p->max_match_value);
+		__sh_cmt_set_next(p, p->max_match_value);
  out:
  out:
 	spin_unlock_irqrestore(&p->lock, flags);
 	spin_unlock_irqrestore(&p->lock, flags);
 
 
@@ -381,7 +386,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)
 
 
 	/* adjust the timeout to maximum if only clocksource left */
 	/* adjust the timeout to maximum if only clocksource left */
 	if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE))
 	if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE))
-		sh_cmt_set_next(p, p->max_match_value);
+		__sh_cmt_set_next(p, p->max_match_value);
 
 
 	spin_unlock_irqrestore(&p->lock, flags);
 	spin_unlock_irqrestore(&p->lock, flags);
 }
 }

+ 15 - 4
drivers/gpio/cs5535-gpio.c

@@ -56,15 +56,26 @@ static struct cs5535_gpio_chip {
  * registers, see include/linux/cs5535.h.
  * registers, see include/linux/cs5535.h.
  */
  */
 
 
-static void errata_outl(u32 val, unsigned long addr)
+static void errata_outl(struct cs5535_gpio_chip *chip, u32 val,
+		unsigned int reg)
 {
 {
+	unsigned long addr = chip->base + 0x80 + reg;
+
 	/*
 	/*
 	 * According to the CS5536 errata (#36), after suspend
 	 * According to the CS5536 errata (#36), after suspend
 	 * a write to the high bank GPIO register will clear all
 	 * a write to the high bank GPIO register will clear all
 	 * non-selected bits; the recommended workaround is a
 	 * non-selected bits; the recommended workaround is a
 	 * read-modify-write operation.
 	 * read-modify-write operation.
+	 *
+	 * Don't apply this errata to the edge status GPIOs, as writing
+	 * to their lower bits will clear them.
 	 */
 	 */
-	val |= inl(addr);
+	if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) {
+		if (val & 0xffff)
+			val |= (inl(addr) & 0xffff); /* ignore the high bits */
+		else
+			val |= (inl(addr) ^ (val >> 16));
+	}
 	outl(val, addr);
 	outl(val, addr);
 }
 }
 
 
@@ -76,7 +87,7 @@ static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
 		outl(1 << offset, chip->base + reg);
 		outl(1 << offset, chip->base + reg);
 	else
 	else
 		/* high bank register */
 		/* high bank register */
-		errata_outl(1 << (offset - 16), chip->base + 0x80 + reg);
+		errata_outl(chip, 1 << (offset - 16), reg);
 }
 }
 
 
 void cs5535_gpio_set(unsigned offset, unsigned int reg)
 void cs5535_gpio_set(unsigned offset, unsigned int reg)
@@ -98,7 +109,7 @@ static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,
 		outl(1 << (offset + 16), chip->base + reg);
 		outl(1 << (offset + 16), chip->base + reg);
 	else
 	else
 		/* high bank register */
 		/* high bank register */
-		errata_outl(1 << offset, chip->base + 0x80 + reg);
+		errata_outl(chip, 1 << offset, reg);
 }
 }
 
 
 void cs5535_gpio_clear(unsigned offset, unsigned int reg)
 void cs5535_gpio_clear(unsigned offset, unsigned int reg)

+ 3 - 0
drivers/gpio/gpiolib.c

@@ -1281,6 +1281,9 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
 		err = gpio_direction_output(gpio,
 		err = gpio_direction_output(gpio,
 				(flags & GPIOF_INIT_HIGH) ? 1 : 0);
 				(flags & GPIOF_INIT_HIGH) ? 1 : 0);
 
 
+	if (err)
+		gpio_free(gpio);
+
 	return err;
 	return err;
 }
 }
 EXPORT_SYMBOL_GPL(gpio_request_one);
 EXPORT_SYMBOL_GPL(gpio_request_one);

+ 1 - 1
drivers/gpio/rdc321x-gpio.c

@@ -135,7 +135,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
 	struct rdc321x_gpio *rdc321x_gpio_dev;
 	struct rdc321x_gpio *rdc321x_gpio_dev;
 	struct rdc321x_gpio_pdata *pdata;
 	struct rdc321x_gpio_pdata *pdata;
 
 
-	pdata = pdev->dev.platform_data;
+	pdata = platform_get_drvdata(pdev);
 	if (!pdata) {
 	if (!pdata) {
 		dev_err(&pdev->dev, "no platform data supplied\n");
 		dev_err(&pdev->dev, "no platform data supplied\n");
 		return -ENODEV;
 		return -ENODEV;

+ 5 - 2
drivers/gpu/drm/drm_crtc_helper.c

@@ -241,7 +241,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
 	}
 	}
 
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		if (encoder->crtc && !drm_helper_encoder_in_use(encoder)) {
+		if (!drm_helper_encoder_in_use(encoder)) {
 			drm_encoder_disable(encoder);
 			drm_encoder_disable(encoder);
 			/* disconnector encoder from any connector */
 			/* disconnector encoder from any connector */
 			encoder->crtc = NULL;
 			encoder->crtc = NULL;
@@ -874,7 +874,10 @@ static void output_poll_execute(struct work_struct *work)
 			continue;
 			continue;
 
 
 		connector->status = connector->funcs->detect(connector, false);
 		connector->status = connector->funcs->detect(connector, false);
-		DRM_DEBUG_KMS("connector status updated to %d\n", connector->status);
+		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
+			      connector->base.id,
+			      drm_get_connector_name(connector),
+			      old_status, connector->status);
 		if (old_status != connector->status)
 		if (old_status != connector->status)
 			changed = true;
 			changed = true;
 	}
 	}

+ 1 - 1
drivers/gpu/drm/i915/intel_bios.c

@@ -270,7 +270,7 @@ parse_general_features(struct drm_i915_private *dev_priv,
 					general->ssc_freq ? 66 : 48;
 					general->ssc_freq ? 66 : 48;
 			else if (IS_GEN5(dev) || IS_GEN6(dev))
 			else if (IS_GEN5(dev) || IS_GEN6(dev))
 				dev_priv->lvds_ssc_freq =
 				dev_priv->lvds_ssc_freq =
-					general->ssc_freq ? 100 : 120;
+					general->ssc_freq ? 120 : 100;
 			else
 			else
 				dev_priv->lvds_ssc_freq =
 				dev_priv->lvds_ssc_freq =
 					general->ssc_freq ? 100 : 96;
 					general->ssc_freq ? 100 : 96;

+ 30 - 7
drivers/gpu/drm/i915/intel_dp.c

@@ -479,6 +479,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 	uint16_t address = algo_data->address;
 	uint16_t address = algo_data->address;
 	uint8_t msg[5];
 	uint8_t msg[5];
 	uint8_t reply[2];
 	uint8_t reply[2];
+	unsigned retry;
 	int msg_bytes;
 	int msg_bytes;
 	int reply_bytes;
 	int reply_bytes;
 	int ret;
 	int ret;
@@ -513,14 +514,33 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 		break;
 		break;
 	}
 	}
 
 
-	for (;;) {
-	  ret = intel_dp_aux_ch(intel_dp,
-				msg, msg_bytes,
-				reply, reply_bytes);
+	for (retry = 0; retry < 5; retry++) {
+		ret = intel_dp_aux_ch(intel_dp,
+				      msg, msg_bytes,
+				      reply, reply_bytes);
 		if (ret < 0) {
 		if (ret < 0) {
 			DRM_DEBUG_KMS("aux_ch failed %d\n", ret);
 			DRM_DEBUG_KMS("aux_ch failed %d\n", ret);
 			return ret;
 			return ret;
 		}
 		}
+
+		switch (reply[0] & AUX_NATIVE_REPLY_MASK) {
+		case AUX_NATIVE_REPLY_ACK:
+			/* I2C-over-AUX Reply field is only valid
+			 * when paired with AUX ACK.
+			 */
+			break;
+		case AUX_NATIVE_REPLY_NACK:
+			DRM_DEBUG_KMS("aux_ch native nack\n");
+			return -EREMOTEIO;
+		case AUX_NATIVE_REPLY_DEFER:
+			udelay(100);
+			continue;
+		default:
+			DRM_ERROR("aux_ch invalid native reply 0x%02x\n",
+				  reply[0]);
+			return -EREMOTEIO;
+		}
+
 		switch (reply[0] & AUX_I2C_REPLY_MASK) {
 		switch (reply[0] & AUX_I2C_REPLY_MASK) {
 		case AUX_I2C_REPLY_ACK:
 		case AUX_I2C_REPLY_ACK:
 			if (mode == MODE_I2C_READ) {
 			if (mode == MODE_I2C_READ) {
@@ -528,17 +548,20 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 			}
 			}
 			return reply_bytes - 1;
 			return reply_bytes - 1;
 		case AUX_I2C_REPLY_NACK:
 		case AUX_I2C_REPLY_NACK:
-			DRM_DEBUG_KMS("aux_ch nack\n");
+			DRM_DEBUG_KMS("aux_i2c nack\n");
 			return -EREMOTEIO;
 			return -EREMOTEIO;
 		case AUX_I2C_REPLY_DEFER:
 		case AUX_I2C_REPLY_DEFER:
-			DRM_DEBUG_KMS("aux_ch defer\n");
+			DRM_DEBUG_KMS("aux_i2c defer\n");
 			udelay(100);
 			udelay(100);
 			break;
 			break;
 		default:
 		default:
-			DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]);
+			DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]);
 			return -EREMOTEIO;
 			return -EREMOTEIO;
 		}
 		}
 	}
 	}
+
+	DRM_ERROR("too many retries, giving up\n");
+	return -EREMOTEIO;
 }
 }
 
 
 static int
 static int

+ 8 - 11
drivers/gpu/drm/i915/intel_ringbuffer.c

@@ -696,20 +696,17 @@ int intel_wait_ring_buffer(struct drm_device *dev,
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 head;
 	u32 head;
 
 
-	head = intel_read_status_page(ring, 4);
-	if (head) {
-		ring->head = head & HEAD_ADDR;
-		ring->space = ring->head - (ring->tail + 8);
-		if (ring->space < 0)
-			ring->space += ring->size;
-		if (ring->space >= n)
-			return 0;
-	}
-
 	trace_i915_ring_wait_begin (dev);
 	trace_i915_ring_wait_begin (dev);
 	end = jiffies + 3 * HZ;
 	end = jiffies + 3 * HZ;
 	do {
 	do {
-		ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
+		/* If the reported head position has wrapped or hasn't advanced,
+		 * fallback to the slow and accurate path.
+		 */
+		head = intel_read_status_page(ring, 4);
+		if (head < ring->actual_head)
+			head = I915_READ_HEAD(ring);
+		ring->actual_head = head;
+		ring->head = head & HEAD_ADDR;
 		ring->space = ring->head - (ring->tail + 8);
 		ring->space = ring->head - (ring->tail + 8);
 		if (ring->space < 0)
 		if (ring->space < 0)
 			ring->space += ring->size;
 			ring->space += ring->size;

+ 3 - 2
drivers/gpu/drm/i915/intel_ringbuffer.h

@@ -30,8 +30,9 @@ struct  intel_ring_buffer {
 	struct		drm_device *dev;
 	struct		drm_device *dev;
 	struct		drm_gem_object *gem_object;
 	struct		drm_gem_object *gem_object;
 
 
-	unsigned int	head;
-	unsigned int	tail;
+	u32		actual_head;
+	u32		head;
+	u32		tail;
 	int		space;
 	int		space;
 	struct intel_hw_status_page status_page;
 	struct intel_hw_status_page status_page;
 
 

+ 6 - 3
drivers/gpu/drm/i915/intel_sdvo.c

@@ -1908,9 +1908,12 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
 		speed = mapping->i2c_speed;
 		speed = mapping->i2c_speed;
 	}
 	}
 
 
-	sdvo->i2c = &dev_priv->gmbus[pin].adapter;
-	intel_gmbus_set_speed(sdvo->i2c, speed);
-	intel_gmbus_force_bit(sdvo->i2c, true);
+	if (pin < GMBUS_NUM_PORTS) {
+		sdvo->i2c = &dev_priv->gmbus[pin].adapter;
+		intel_gmbus_set_speed(sdvo->i2c, speed);
+		intel_gmbus_force_bit(sdvo->i2c, true);
+	} else
+		sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter;
 }
 }
 
 
 static bool
 static bool

+ 4 - 3
drivers/gpu/drm/radeon/atombios_crtc.c

@@ -253,7 +253,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
 	case DRM_MODE_DPMS_OFF:
 		drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
 		drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
-		atombios_blank_crtc(crtc, ATOM_ENABLE);
+		if (radeon_crtc->enabled)
+			atombios_blank_crtc(crtc, ATOM_ENABLE);
 		if (ASIC_IS_DCE3(rdev))
 		if (ASIC_IS_DCE3(rdev))
 			atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
 			atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
 		atombios_enable_crtc(crtc, ATOM_DISABLE);
 		atombios_enable_crtc(crtc, ATOM_DISABLE);
@@ -530,7 +531,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
 					dp_clock = dig_connector->dp_clock;
 					dp_clock = dig_connector->dp_clock;
 				}
 				}
 			}
 			}
-
+#if 0 /* doesn't work properly on some laptops */
 			/* use recommended ref_div for ss */
 			/* use recommended ref_div for ss */
 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 				if (ss_enabled) {
 				if (ss_enabled) {
@@ -540,7 +541,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
 					}
 					}
 				}
 				}
 			}
 			}
-
+#endif
 			if (ASIC_IS_AVIVO(rdev)) {
 			if (ASIC_IS_AVIVO(rdev)) {
 				/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
 				/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
 				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
 				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)

+ 12 - 15
drivers/gpu/drm/radeon/evergreen.c

@@ -748,6 +748,8 @@ void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev)
 	unsigned i;
 	unsigned i;
 	u32 tmp;
 	u32 tmp;
 
 
+	WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
+
 	WREG32(VM_CONTEXT0_REQUEST_RESPONSE, REQUEST_TYPE(1));
 	WREG32(VM_CONTEXT0_REQUEST_RESPONSE, REQUEST_TYPE(1));
 	for (i = 0; i < rdev->usec_timeout; i++) {
 	for (i = 0; i < rdev->usec_timeout; i++) {
 		/* read MC_STATUS */
 		/* read MC_STATUS */
@@ -1922,7 +1924,6 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev)
 static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
 static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
 {
 {
 	struct evergreen_mc_save save;
 	struct evergreen_mc_save save;
-	u32 srbm_reset = 0;
 	u32 grbm_reset = 0;
 	u32 grbm_reset = 0;
 
 
 	dev_info(rdev->dev, "GPU softreset \n");
 	dev_info(rdev->dev, "GPU softreset \n");
@@ -1961,16 +1962,6 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
 	udelay(50);
 	udelay(50);
 	WREG32(GRBM_SOFT_RESET, 0);
 	WREG32(GRBM_SOFT_RESET, 0);
 	(void)RREG32(GRBM_SOFT_RESET);
 	(void)RREG32(GRBM_SOFT_RESET);
-
-	/* reset all the system blocks */
-	srbm_reset = SRBM_SOFT_RESET_ALL_MASK;
-
-	dev_info(rdev->dev, "  SRBM_SOFT_RESET=0x%08X\n", srbm_reset);
-	WREG32(SRBM_SOFT_RESET, srbm_reset);
-	(void)RREG32(SRBM_SOFT_RESET);
-	udelay(50);
-	WREG32(SRBM_SOFT_RESET, 0);
-	(void)RREG32(SRBM_SOFT_RESET);
 	/* Wait a little for things to settle down */
 	/* Wait a little for things to settle down */
 	udelay(50);
 	udelay(50);
 	dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
 	dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
@@ -1981,10 +1972,6 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
 		RREG32(GRBM_STATUS_SE1));
 		RREG32(GRBM_STATUS_SE1));
 	dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
 	dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
 		RREG32(SRBM_STATUS));
 		RREG32(SRBM_STATUS));
-	/* After reset we need to reinit the asic as GPU often endup in an
-	 * incoherent state.
-	 */
-	atom_asic_init(rdev->mode_info.atom_context);
 	evergreen_mc_resume(rdev, &save);
 	evergreen_mc_resume(rdev, &save);
 	return 0;
 	return 0;
 }
 }
@@ -2596,6 +2583,11 @@ int evergreen_resume(struct radeon_device *rdev)
 {
 {
 	int r;
 	int r;
 
 
+	/* reset the asic, the gfx blocks are often in a bad state
+	 * after the driver is unloaded or after a resume
+	 */
+	if (radeon_asic_reset(rdev))
+		dev_warn(rdev->dev, "GPU reset failed !\n");
 	/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
 	/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
 	 * posting will perform necessary task to bring back GPU into good
 	 * posting will perform necessary task to bring back GPU into good
 	 * shape.
 	 * shape.
@@ -2712,6 +2704,11 @@ int evergreen_init(struct radeon_device *rdev)
 	r = radeon_atombios_init(rdev);
 	r = radeon_atombios_init(rdev);
 	if (r)
 	if (r)
 		return r;
 		return r;
+	/* reset the asic, the gfx blocks are often in a bad state
+	 * after the driver is unloaded or after a resume
+	 */
+	if (radeon_asic_reset(rdev))
+		dev_warn(rdev->dev, "GPU reset failed !\n");
 	/* Post card if necessary */
 	/* Post card if necessary */
 	if (!evergreen_card_posted(rdev)) {
 	if (!evergreen_card_posted(rdev)) {
 		if (!rdev->bios) {
 		if (!rdev->bios) {

+ 1 - 0
drivers/gpu/drm/radeon/evergreend.h

@@ -174,6 +174,7 @@
 #define	HDP_NONSURFACE_BASE				0x2C04
 #define	HDP_NONSURFACE_BASE				0x2C04
 #define	HDP_NONSURFACE_INFO				0x2C08
 #define	HDP_NONSURFACE_INFO				0x2C08
 #define	HDP_NONSURFACE_SIZE				0x2C0C
 #define	HDP_NONSURFACE_SIZE				0x2C0C
+#define HDP_MEM_COHERENCY_FLUSH_CNTL			0x5480
 #define HDP_REG_COHERENCY_FLUSH_CNTL			0x54A0
 #define HDP_REG_COHERENCY_FLUSH_CNTL			0x54A0
 #define	HDP_TILING_CONFIG				0x2F3C
 #define	HDP_TILING_CONFIG				0x2F3C
 
 

+ 8 - 2
drivers/gpu/drm/radeon/r600.c

@@ -1342,13 +1342,19 @@ bool r600_gpu_is_lockup(struct radeon_device *rdev)
 	u32 srbm_status;
 	u32 srbm_status;
 	u32 grbm_status;
 	u32 grbm_status;
 	u32 grbm_status2;
 	u32 grbm_status2;
+	struct r100_gpu_lockup *lockup;
 	int r;
 	int r;
 
 
+	if (rdev->family >= CHIP_RV770)
+		lockup = &rdev->config.rv770.lockup;
+	else
+		lockup = &rdev->config.r600.lockup;
+
 	srbm_status = RREG32(R_000E50_SRBM_STATUS);
 	srbm_status = RREG32(R_000E50_SRBM_STATUS);
 	grbm_status = RREG32(R_008010_GRBM_STATUS);
 	grbm_status = RREG32(R_008010_GRBM_STATUS);
 	grbm_status2 = RREG32(R_008014_GRBM_STATUS2);
 	grbm_status2 = RREG32(R_008014_GRBM_STATUS2);
 	if (!G_008010_GUI_ACTIVE(grbm_status)) {
 	if (!G_008010_GUI_ACTIVE(grbm_status)) {
-		r100_gpu_lockup_update(&rdev->config.r300.lockup, &rdev->cp);
+		r100_gpu_lockup_update(lockup, &rdev->cp);
 		return false;
 		return false;
 	}
 	}
 	/* force CP activities */
 	/* force CP activities */
@@ -1360,7 +1366,7 @@ bool r600_gpu_is_lockup(struct radeon_device *rdev)
 		radeon_ring_unlock_commit(rdev);
 		radeon_ring_unlock_commit(rdev);
 	}
 	}
 	rdev->cp.rptr = RREG32(R600_CP_RB_RPTR);
 	rdev->cp.rptr = RREG32(R600_CP_RB_RPTR);
-	return r100_gpu_cp_is_lockup(rdev, &rdev->config.r300.lockup, &rdev->cp);
+	return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp);
 }
 }
 
 
 int r600_asic_reset(struct radeon_device *rdev)
 int r600_asic_reset(struct radeon_device *rdev)

+ 4 - 5
drivers/gpu/drm/radeon/r600_cs.c

@@ -315,11 +315,10 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
 		if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
 		if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
 			/* the initial DDX does bad things with the CB size occasionally */
 			/* the initial DDX does bad things with the CB size occasionally */
 			/* it rounds up height too far for slice tile max but the BO is smaller */
 			/* it rounds up height too far for slice tile max but the BO is smaller */
-			tmp = (height - 7) * 8 * bpe;
-			if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
-				dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]));
-				return -EINVAL;
-			}
+			/* r600c,g also seem to flush at bad times in some apps resulting in
+			 * bogus values here. So for linear just allow anything to avoid breaking
+			 * broken userspace.
+			 */
 		} else {
 		} else {
 			dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]));
 			dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]));
 			return -EINVAL;
 			return -EINVAL;

+ 4 - 5
drivers/gpu/drm/radeon/radeon_device.c

@@ -910,11 +910,6 @@ int radeon_resume_kms(struct drm_device *dev)
 	radeon_pm_resume(rdev);
 	radeon_pm_resume(rdev);
 	radeon_restore_bios_scratch_regs(rdev);
 	radeon_restore_bios_scratch_regs(rdev);
 
 
-	/* turn on display hw */
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
-	}
-
 	radeon_fbdev_set_suspend(rdev, 0);
 	radeon_fbdev_set_suspend(rdev, 0);
 	release_console_sem();
 	release_console_sem();
 
 
@@ -922,6 +917,10 @@ int radeon_resume_kms(struct drm_device *dev)
 	radeon_hpd_init(rdev);
 	radeon_hpd_init(rdev);
 	/* blat the mode back in */
 	/* blat the mode back in */
 	drm_helper_resume_force_mode(dev);
 	drm_helper_resume_force_mode(dev);
+	/* turn on display hw */
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+	}
 	return 0;
 	return 0;
 }
 }
 
 

+ 19 - 0
drivers/gpu/drm/radeon/radeon_drv.c

@@ -232,9 +232,28 @@ static struct drm_driver driver_old = {
 
 
 static struct drm_driver kms_driver;
 static struct drm_driver kms_driver;
 
 
+static void radeon_kick_out_firmware_fb(struct pci_dev *pdev)
+{
+	struct apertures_struct *ap;
+	bool primary = false;
+
+	ap = alloc_apertures(1);
+	ap->ranges[0].base = pci_resource_start(pdev, 0);
+	ap->ranges[0].size = pci_resource_len(pdev, 0);
+
+#ifdef CONFIG_X86
+	primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
+#endif
+	remove_conflicting_framebuffers(ap, "radeondrmfb", primary);
+	kfree(ap);
+}
+
 static int __devinit
 static int __devinit
 radeon_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 radeon_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 {
+	/* Get rid of things like offb */
+	radeon_kick_out_firmware_fb(pdev);
+
 	return drm_get_pci_dev(pdev, ent, &kms_driver);
 	return drm_get_pci_dev(pdev, ent, &kms_driver);
 }
 }
 
 

+ 1 - 1
drivers/gpu/drm/radeon/radeon_fb.c

@@ -245,7 +245,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
 		goto out_unref;
 		goto out_unref;
 	}
 	}
 	info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base;
 	info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base;
-	info->apertures->ranges[0].size = rdev->mc.real_vram_size;
+	info->apertures->ranges[0].size = rdev->mc.aper_size;
 
 
 	info->fix.mmio_start = 0;
 	info->fix.mmio_start = 0;
 	info->fix.mmio_len = 0;
 	info->fix.mmio_len = 0;

+ 1 - 1
drivers/leds/led-class.c

@@ -267,7 +267,7 @@ void led_blink_set(struct led_classdev *led_cdev,
 		   unsigned long *delay_off)
 		   unsigned long *delay_off)
 {
 {
 	if (led_cdev->blink_set &&
 	if (led_cdev->blink_set &&
-	    led_cdev->blink_set(led_cdev, delay_on, delay_off))
+	    !led_cdev->blink_set(led_cdev, delay_on, delay_off))
 		return;
 		return;
 
 
 	/* blink with 1 Hz as default if nothing specified */
 	/* blink with 1 Hz as default if nothing specified */

+ 2 - 8
drivers/md/dm-table.c

@@ -517,9 +517,8 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
 	 */
 	 */
 
 
 	if (q->merge_bvec_fn && !ti->type->merge)
 	if (q->merge_bvec_fn && !ti->type->merge)
-		limits->max_sectors =
-			min_not_zero(limits->max_sectors,
-				     (unsigned int) (PAGE_SIZE >> 9));
+		blk_limits_max_hw_sectors(limits,
+					  (unsigned int) (PAGE_SIZE >> 9));
 	return 0;
 	return 0;
 }
 }
 EXPORT_SYMBOL_GPL(dm_set_device_limits);
 EXPORT_SYMBOL_GPL(dm_set_device_limits);
@@ -1131,11 +1130,6 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
 	 */
 	 */
 	q->limits = *limits;
 	q->limits = *limits;
 
 
-	if (limits->no_cluster)
-		queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
-	else
-		queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q);
-
 	if (!dm_table_supports_discards(t))
 	if (!dm_table_supports_discards(t))
 		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
 		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
 	else
 	else

+ 0 - 3
drivers/md/md.c

@@ -4295,9 +4295,6 @@ static int md_alloc(dev_t dev, char *name)
 		goto abort;
 		goto abort;
 	mddev->queue->queuedata = mddev;
 	mddev->queue->queuedata = mddev;
 
 
-	/* Can be unlocked because the queue is new: no concurrency */
-	queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, mddev->queue);
-
 	blk_queue_make_request(mddev->queue, md_make_request);
 	blk_queue_make_request(mddev->queue, md_make_request);
 
 
 	disk = alloc_disk(1 << shift);
 	disk = alloc_disk(1 << shift);

+ 11 - 10
drivers/media/IR/keymaps/rc-rc6-mce.c

@@ -26,8 +26,8 @@ static struct ir_scancode rc6_mce[] = {
 
 
 	{ 0x800f040a, KEY_DELETE },
 	{ 0x800f040a, KEY_DELETE },
 	{ 0x800f040b, KEY_ENTER },
 	{ 0x800f040b, KEY_ENTER },
-	{ 0x800f040c, KEY_POWER },
-	{ 0x800f040d, KEY_PROG1 }, 		/* Windows MCE button */
+	{ 0x800f040c, KEY_POWER },		/* PC Power */
+	{ 0x800f040d, KEY_PROG1 },		/* Windows MCE button */
 	{ 0x800f040e, KEY_MUTE },
 	{ 0x800f040e, KEY_MUTE },
 	{ 0x800f040f, KEY_INFO },
 	{ 0x800f040f, KEY_INFO },
 
 
@@ -56,31 +56,32 @@ static struct ir_scancode rc6_mce[] = {
 	{ 0x800f0422, KEY_OK },
 	{ 0x800f0422, KEY_OK },
 	{ 0x800f0423, KEY_EXIT },
 	{ 0x800f0423, KEY_EXIT },
 	{ 0x800f0424, KEY_DVD },
 	{ 0x800f0424, KEY_DVD },
-	{ 0x800f0425, KEY_TUNER }, 		/* LiveTV */
-	{ 0x800f0426, KEY_EPG }, 		/* Guide */
-	{ 0x800f0427, KEY_ZOOM }, 		/* Aspect */
+	{ 0x800f0425, KEY_TUNER },		/* LiveTV */
+	{ 0x800f0426, KEY_EPG },		/* Guide */
+	{ 0x800f0427, KEY_ZOOM },		/* Aspect */
 
 
 	{ 0x800f043a, KEY_BRIGHTNESSUP },
 	{ 0x800f043a, KEY_BRIGHTNESSUP },
 
 
 	{ 0x800f0446, KEY_TV },
 	{ 0x800f0446, KEY_TV },
-	{ 0x800f0447, KEY_AUDIO }, 		/* My Music */
-	{ 0x800f0448, KEY_PVR }, 		/* RecordedTV */
+	{ 0x800f0447, KEY_AUDIO },		/* My Music */
+	{ 0x800f0448, KEY_PVR },		/* RecordedTV */
 	{ 0x800f0449, KEY_CAMERA },
 	{ 0x800f0449, KEY_CAMERA },
 	{ 0x800f044a, KEY_VIDEO },
 	{ 0x800f044a, KEY_VIDEO },
 	{ 0x800f044c, KEY_LANGUAGE },
 	{ 0x800f044c, KEY_LANGUAGE },
 	{ 0x800f044d, KEY_TITLE },
 	{ 0x800f044d, KEY_TITLE },
-	{ 0x800f044e, KEY_PRINT }, 	/* Print - HP OEM version of remote */
+	{ 0x800f044e, KEY_PRINT },	/* Print - HP OEM version of remote */
 
 
 	{ 0x800f0450, KEY_RADIO },
 	{ 0x800f0450, KEY_RADIO },
 
 
-	{ 0x800f045a, KEY_SUBTITLE }, 		/* Caption/Teletext */
+	{ 0x800f045a, KEY_SUBTITLE },		/* Caption/Teletext */
 	{ 0x800f045b, KEY_RED },
 	{ 0x800f045b, KEY_RED },
 	{ 0x800f045c, KEY_GREEN },
 	{ 0x800f045c, KEY_GREEN },
 	{ 0x800f045d, KEY_YELLOW },
 	{ 0x800f045d, KEY_YELLOW },
 	{ 0x800f045e, KEY_BLUE },
 	{ 0x800f045e, KEY_BLUE },
 
 
+	{ 0x800f0465, KEY_POWER2 },	/* TV Power */
 	{ 0x800f046e, KEY_PLAYPAUSE },
 	{ 0x800f046e, KEY_PLAYPAUSE },
-	{ 0x800f046f, KEY_MEDIA }, 	/* Start media application (NEW) */
+	{ 0x800f046f, KEY_MEDIA },	/* Start media application (NEW) */
 
 
 	{ 0x800f0480, KEY_BRIGHTNESSDOWN },
 	{ 0x800f0480, KEY_BRIGHTNESSDOWN },
 	{ 0x800f0481, KEY_PLAYPAUSE },
 	{ 0x800f0481, KEY_PLAYPAUSE },

+ 16 - 13
drivers/media/IR/lirc_dev.c

@@ -522,10 +522,8 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
 
 
 	dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
 	dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
 
 
-	if (!ir->attached) {
-		mutex_unlock(&ir->irctl_lock);
+	if (!ir->attached)
 		return POLLERR;
 		return POLLERR;
-	}
 
 
 	poll_wait(file, &ir->buf->wait_poll, wait);
 	poll_wait(file, &ir->buf->wait_poll, wait);
 
 
@@ -649,18 +647,18 @@ ssize_t lirc_dev_fop_read(struct file *file,
 	if (!buf)
 	if (!buf)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	if (mutex_lock_interruptible(&ir->irctl_lock))
-		return -ERESTARTSYS;
+	if (mutex_lock_interruptible(&ir->irctl_lock)) {
+		ret = -ERESTARTSYS;
+		goto out_unlocked;
+	}
 	if (!ir->attached) {
 	if (!ir->attached) {
-		mutex_unlock(&ir->irctl_lock);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out_locked;
 	}
 	}
 
 
 	if (length % ir->chunk_size) {
 	if (length % ir->chunk_size) {
-		dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n",
-			ir->d.name, ir->d.minor);
-		mutex_unlock(&ir->irctl_lock);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_locked;
 	}
 	}
 
 
 	/*
 	/*
@@ -711,18 +709,23 @@ ssize_t lirc_dev_fop_read(struct file *file,
 			lirc_buffer_read(ir->buf, buf);
 			lirc_buffer_read(ir->buf, buf);
 			ret = copy_to_user((void *)buffer+written, buf,
 			ret = copy_to_user((void *)buffer+written, buf,
 					   ir->buf->chunk_size);
 					   ir->buf->chunk_size);
-			written += ir->buf->chunk_size;
+			if (!ret)
+				written += ir->buf->chunk_size;
+			else
+				ret = -EFAULT;
 		}
 		}
 	}
 	}
 
 
 	remove_wait_queue(&ir->buf->wait_poll, &wait);
 	remove_wait_queue(&ir->buf->wait_poll, &wait);
 	set_current_state(TASK_RUNNING);
 	set_current_state(TASK_RUNNING);
+
+out_locked:
 	mutex_unlock(&ir->irctl_lock);
 	mutex_unlock(&ir->irctl_lock);
 
 
 out_unlocked:
 out_unlocked:
 	kfree(buf);
 	kfree(buf);
 	dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
 	dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
-		ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
+		ir->d.name, ir->d.minor, ret ? "<fail>" : "<ok>", ret);
 
 
 	return ret ? ret : written;
 	return ret ? ret : written;
 }
 }

+ 109 - 65
drivers/media/IR/mceusb.c

@@ -35,10 +35,10 @@
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/input.h>
 #include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
 #include <media/ir-core.h>
 #include <media/ir-core.h>
-#include <media/ir-common.h>
 
 
 #define DRIVER_VERSION	"1.91"
 #define DRIVER_VERSION	"1.91"
 #define DRIVER_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>"
 #define DRIVER_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>"
@@ -49,6 +49,7 @@
 #define USB_BUFLEN		32 /* USB reception buffer length */
 #define USB_BUFLEN		32 /* USB reception buffer length */
 #define USB_CTRL_MSG_SZ		2  /* Size of usb ctrl msg on gen1 hw */
 #define USB_CTRL_MSG_SZ		2  /* Size of usb ctrl msg on gen1 hw */
 #define MCE_G1_INIT_MSGS	40 /* Init messages on gen1 hw to throw out */
 #define MCE_G1_INIT_MSGS	40 /* Init messages on gen1 hw to throw out */
+#define MS_TO_NS(msec)		((msec) * 1000)
 
 
 /* MCE constants */
 /* MCE constants */
 #define MCE_CMDBUF_SIZE		384  /* MCE Command buffer length */
 #define MCE_CMDBUF_SIZE		384  /* MCE Command buffer length */
@@ -74,6 +75,7 @@
 #define MCE_PACKET_LENGTH_MASK	0x1f /* Packet length mask */
 #define MCE_PACKET_LENGTH_MASK	0x1f /* Packet length mask */
 
 
 /* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */
 /* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */
+#define MCE_CMD_SIG_END		0x01	/* End of signal */
 #define MCE_CMD_PING		0x03	/* Ping device */
 #define MCE_CMD_PING		0x03	/* Ping device */
 #define MCE_CMD_UNKNOWN		0x04	/* Unknown */
 #define MCE_CMD_UNKNOWN		0x04	/* Unknown */
 #define MCE_CMD_UNKNOWN2	0x05	/* Unknown */
 #define MCE_CMD_UNKNOWN2	0x05	/* Unknown */
@@ -91,6 +93,7 @@
 #define MCE_CMD_G_TXMASK	0x13	/* Set TX port bitmask */
 #define MCE_CMD_G_TXMASK	0x13	/* Set TX port bitmask */
 #define MCE_CMD_S_RXSENSOR	0x14	/* Set RX sensor (std/learning) */
 #define MCE_CMD_S_RXSENSOR	0x14	/* Set RX sensor (std/learning) */
 #define MCE_CMD_G_RXSENSOR	0x15	/* Get RX sensor (std/learning) */
 #define MCE_CMD_G_RXSENSOR	0x15	/* Get RX sensor (std/learning) */
+#define MCE_RSP_PULSE_COUNT	0x15	/* RX pulse count (only if learning) */
 #define MCE_CMD_TX_PORTS	0x16	/* Get number of TX ports */
 #define MCE_CMD_TX_PORTS	0x16	/* Get number of TX ports */
 #define MCE_CMD_G_WAKESRC	0x17	/* Get wake source */
 #define MCE_CMD_G_WAKESRC	0x17	/* Get wake source */
 #define MCE_CMD_UNKNOWN7	0x18	/* Unknown */
 #define MCE_CMD_UNKNOWN7	0x18	/* Unknown */
@@ -146,14 +149,16 @@ enum mceusb_model_type {
 	MCE_GEN3,
 	MCE_GEN3,
 	MCE_GEN2_TX_INV,
 	MCE_GEN2_TX_INV,
 	POLARIS_EVK,
 	POLARIS_EVK,
+	CX_HYBRID_TV,
 };
 };
 
 
 struct mceusb_model {
 struct mceusb_model {
 	u32 mce_gen1:1;
 	u32 mce_gen1:1;
 	u32 mce_gen2:1;
 	u32 mce_gen2:1;
 	u32 mce_gen3:1;
 	u32 mce_gen3:1;
-	u32 tx_mask_inverted:1;
+	u32 tx_mask_normal:1;
 	u32 is_polaris:1;
 	u32 is_polaris:1;
+	u32 no_tx:1;
 
 
 	const char *rc_map;	/* Allow specify a per-board map */
 	const char *rc_map;	/* Allow specify a per-board map */
 	const char *name;	/* per-board name */
 	const char *name;	/* per-board name */
@@ -162,18 +167,18 @@ struct mceusb_model {
 static const struct mceusb_model mceusb_model[] = {
 static const struct mceusb_model mceusb_model[] = {
 	[MCE_GEN1] = {
 	[MCE_GEN1] = {
 		.mce_gen1 = 1,
 		.mce_gen1 = 1,
-		.tx_mask_inverted = 1,
+		.tx_mask_normal = 1,
 	},
 	},
 	[MCE_GEN2] = {
 	[MCE_GEN2] = {
 		.mce_gen2 = 1,
 		.mce_gen2 = 1,
 	},
 	},
 	[MCE_GEN2_TX_INV] = {
 	[MCE_GEN2_TX_INV] = {
 		.mce_gen2 = 1,
 		.mce_gen2 = 1,
-		.tx_mask_inverted = 1,
+		.tx_mask_normal = 1,
 	},
 	},
 	[MCE_GEN3] = {
 	[MCE_GEN3] = {
 		.mce_gen3 = 1,
 		.mce_gen3 = 1,
-		.tx_mask_inverted = 1,
+		.tx_mask_normal = 1,
 	},
 	},
 	[POLARIS_EVK] = {
 	[POLARIS_EVK] = {
 		.is_polaris = 1,
 		.is_polaris = 1,
@@ -183,7 +188,12 @@ static const struct mceusb_model mceusb_model[] = {
 		 * to allow testing it
 		 * to allow testing it
 		 */
 		 */
 		.rc_map = RC_MAP_RC5_HAUPPAUGE_NEW,
 		.rc_map = RC_MAP_RC5_HAUPPAUGE_NEW,
-		.name = "cx231xx MCE IR",
+		.name = "Conexant Hybrid TV (cx231xx) MCE IR",
+	},
+	[CX_HYBRID_TV] = {
+		.is_polaris = 1,
+		.no_tx = 1, /* tx isn't wired up at all */
+		.name = "Conexant Hybrid TV (cx231xx) MCE IR",
 	},
 	},
 };
 };
 
 
@@ -273,6 +283,8 @@ static struct usb_device_id mceusb_dev_table[] = {
 	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
 	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
 	/* Formosa Industrial Computing */
 	/* Formosa Industrial Computing */
 	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03e) },
 	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03e) },
+	/* Fintek eHome Infrared Transceiver (HP branded) */
+	{ USB_DEVICE(VENDOR_FINTEK, 0x5168) },
 	/* Fintek eHome Infrared Transceiver */
 	/* Fintek eHome Infrared Transceiver */
 	{ USB_DEVICE(VENDOR_FINTEK, 0x0602) },
 	{ USB_DEVICE(VENDOR_FINTEK, 0x0602) },
 	/* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
 	/* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
@@ -292,9 +304,12 @@ static struct usb_device_id mceusb_dev_table[] = {
 	{ USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },
 	{ USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },
 	/* TiVo PC IR Receiver */
 	/* TiVo PC IR Receiver */
 	{ USB_DEVICE(VENDOR_TIVO, 0x2000) },
 	{ USB_DEVICE(VENDOR_TIVO, 0x2000) },
-	/* Conexant SDK */
+	/* Conexant Hybrid TV "Shelby" Polaris SDK */
 	{ USB_DEVICE(VENDOR_CONEXANT, 0x58a1),
 	{ USB_DEVICE(VENDOR_CONEXANT, 0x58a1),
 	  .driver_info = POLARIS_EVK },
 	  .driver_info = POLARIS_EVK },
+	/* Conexant Hybrid TV RDU253S Polaris */
+	{ USB_DEVICE(VENDOR_CONEXANT, 0x58a5),
+	  .driver_info = CX_HYBRID_TV },
 	/* Terminating entry */
 	/* Terminating entry */
 	{ }
 	{ }
 };
 };
@@ -303,7 +318,10 @@ static struct usb_device_id mceusb_dev_table[] = {
 struct mceusb_dev {
 struct mceusb_dev {
 	/* ir-core bits */
 	/* ir-core bits */
 	struct ir_dev_props *props;
 	struct ir_dev_props *props;
-	struct ir_raw_event rawir;
+
+	/* optional features we can enable */
+	bool carrier_report_enabled;
+	bool learning_enabled;
 
 
 	/* core device bits */
 	/* core device bits */
 	struct device *dev;
 	struct device *dev;
@@ -318,6 +336,8 @@ struct mceusb_dev {
 	/* buffers and dma */
 	/* buffers and dma */
 	unsigned char *buf_in;
 	unsigned char *buf_in;
 	unsigned int len_in;
 	unsigned int len_in;
+	dma_addr_t dma_in;
+	dma_addr_t dma_out;
 
 
 	enum {
 	enum {
 		CMD_HEADER = 0,
 		CMD_HEADER = 0,
@@ -325,15 +345,14 @@ struct mceusb_dev {
 		CMD_DATA,
 		CMD_DATA,
 		PARSE_IRDATA,
 		PARSE_IRDATA,
 	} parser_state;
 	} parser_state;
-	u8 cmd, rem;		/* Remaining IR data bytes in packet */
 
 
-	dma_addr_t dma_in;
-	dma_addr_t dma_out;
+	u8 cmd, rem;		/* Remaining IR data bytes in packet */
 
 
 	struct {
 	struct {
 		u32 connected:1;
 		u32 connected:1;
-		u32 tx_mask_inverted:1;
+		u32 tx_mask_normal:1;
 		u32 microsoft_gen1:1;
 		u32 microsoft_gen1:1;
+		u32 no_tx:1;
 	} flags;
 	} flags;
 
 
 	/* transmit support */
 	/* transmit support */
@@ -408,9 +427,10 @@ static int mceusb_cmdsize(u8 cmd, u8 subcmd)
 		case MCE_CMD_UNKNOWN:
 		case MCE_CMD_UNKNOWN:
 		case MCE_CMD_S_CARRIER:
 		case MCE_CMD_S_CARRIER:
 		case MCE_CMD_S_TIMEOUT:
 		case MCE_CMD_S_TIMEOUT:
-		case MCE_CMD_G_RXSENSOR:
+		case MCE_RSP_PULSE_COUNT:
 			datasize = 2;
 			datasize = 2;
 			break;
 			break;
+		case MCE_CMD_SIG_END:
 		case MCE_CMD_S_TXMASK:
 		case MCE_CMD_S_TXMASK:
 		case MCE_CMD_S_RXSENSOR:
 		case MCE_CMD_S_RXSENSOR:
 			datasize = 1;
 			datasize = 1;
@@ -433,7 +453,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
 		return;
 		return;
 
 
 	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
 	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
-	if (ir->flags.microsoft_gen1 && !out)
+	if (ir->flags.microsoft_gen1 && !out && !offset)
 		skip = 2;
 		skip = 2;
 
 
 	if (len <= skip)
 	if (len <= skip)
@@ -491,6 +511,9 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
 		break;
 		break;
 	case MCE_COMMAND_HEADER:
 	case MCE_COMMAND_HEADER:
 		switch (subcmd) {
 		switch (subcmd) {
+		case MCE_CMD_SIG_END:
+			dev_info(dev, "End of signal\n");
+			break;
 		case MCE_CMD_PING:
 		case MCE_CMD_PING:
 			dev_info(dev, "Ping\n");
 			dev_info(dev, "Ping\n");
 			break;
 			break;
@@ -525,10 +548,11 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
 				 inout, data1 == 0x02 ? "short" : "long");
 				 inout, data1 == 0x02 ? "short" : "long");
 			break;
 			break;
 		case MCE_CMD_G_RXSENSOR:
 		case MCE_CMD_G_RXSENSOR:
-			if (len == 2)
+		/* aka MCE_RSP_PULSE_COUNT */
+			if (out)
 				dev_info(dev, "Get receive sensor\n");
 				dev_info(dev, "Get receive sensor\n");
-			else
-				dev_info(dev, "Received pulse count is %d\n",
+			else if (ir->learning_enabled)
+				dev_info(dev, "RX pulse count: %d\n",
 					 ((data1 << 8) | data2));
 					 ((data1 << 8) | data2));
 			break;
 			break;
 		case MCE_RSP_CMD_INVALID:
 		case MCE_RSP_CMD_INVALID:
@@ -724,16 +748,16 @@ out:
 	return ret ? ret : n;
 	return ret ? ret : n;
 }
 }
 
 
-/* Sets active IR outputs -- mce devices typically (all?) have two */
+/* Sets active IR outputs -- mce devices typically have two */
 static int mceusb_set_tx_mask(void *priv, u32 mask)
 static int mceusb_set_tx_mask(void *priv, u32 mask)
 {
 {
 	struct mceusb_dev *ir = priv;
 	struct mceusb_dev *ir = priv;
 
 
-	if (ir->flags.tx_mask_inverted)
+	if (ir->flags.tx_mask_normal)
+		ir->tx_mask = mask;
+	else
 		ir->tx_mask = (mask != MCE_DEFAULT_TX_MASK ?
 		ir->tx_mask = (mask != MCE_DEFAULT_TX_MASK ?
 				mask ^ MCE_DEFAULT_TX_MASK : mask) << 1;
 				mask ^ MCE_DEFAULT_TX_MASK : mask) << 1;
-	else
-		ir->tx_mask = mask;
 
 
 	return 0;
 	return 0;
 }
 }
@@ -752,7 +776,7 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
 
 
 		if (carrier == 0) {
 		if (carrier == 0) {
 			ir->carrier = carrier;
 			ir->carrier = carrier;
-			cmdbuf[2] = 0x01;
+			cmdbuf[2] = MCE_CMD_SIG_END;
 			cmdbuf[3] = MCE_IRDATA_TRAILER;
 			cmdbuf[3] = MCE_IRDATA_TRAILER;
 			dev_dbg(ir->dev, "%s: disabling carrier "
 			dev_dbg(ir->dev, "%s: disabling carrier "
 				"modulation\n", __func__);
 				"modulation\n", __func__);
@@ -782,6 +806,34 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
 	return carrier;
 	return carrier;
 }
 }
 
 
+/*
+ * We don't do anything but print debug spew for many of the command bits
+ * we receive from the hardware, but some of them are useful information
+ * we want to store so that we can use them.
+ */
+static void mceusb_handle_command(struct mceusb_dev *ir, int index)
+{
+	u8 hi = ir->buf_in[index + 1] & 0xff;
+	u8 lo = ir->buf_in[index + 2] & 0xff;
+
+	switch (ir->buf_in[index]) {
+	/* 2-byte return value commands */
+	case MCE_CMD_S_TIMEOUT:
+		ir->props->timeout = MS_TO_NS((hi << 8 | lo) / 2);
+		break;
+
+	/* 1-byte return value commands */
+	case MCE_CMD_S_TXMASK:
+		ir->tx_mask = hi;
+		break;
+	case MCE_CMD_S_RXSENSOR:
+		ir->learning_enabled = (hi == 0x02);
+		break;
+	default:
+		break;
+	}
+}
+
 static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 {
 {
 	DEFINE_IR_RAW_EVENT(rawir);
 	DEFINE_IR_RAW_EVENT(rawir);
@@ -791,39 +843,30 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 	if (ir->flags.microsoft_gen1)
 	if (ir->flags.microsoft_gen1)
 		i = 2;
 		i = 2;
 
 
+	/* if there's no data, just return now */
+	if (buf_len <= i)
+		return;
+
 	for (; i < buf_len; i++) {
 	for (; i < buf_len; i++) {
 		switch (ir->parser_state) {
 		switch (ir->parser_state) {
 		case SUBCMD:
 		case SUBCMD:
 			ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]);
 			ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]);
 			mceusb_dev_printdata(ir, ir->buf_in, i - 1,
 			mceusb_dev_printdata(ir, ir->buf_in, i - 1,
 					     ir->rem + 2, false);
 					     ir->rem + 2, false);
+			mceusb_handle_command(ir, i);
 			ir->parser_state = CMD_DATA;
 			ir->parser_state = CMD_DATA;
 			break;
 			break;
 		case PARSE_IRDATA:
 		case PARSE_IRDATA:
 			ir->rem--;
 			ir->rem--;
 			rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
 			rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
 			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
 			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
-					 * MCE_TIME_UNIT * 1000;
-
-			if ((ir->buf_in[i] & MCE_PULSE_MASK) == 0x7f) {
-				if (ir->rawir.pulse == rawir.pulse) {
-					ir->rawir.duration += rawir.duration;
-				} else {
-					ir->rawir.duration = rawir.duration;
-					ir->rawir.pulse = rawir.pulse;
-				}
-				if (ir->rem)
-					break;
-			}
-			rawir.duration += ir->rawir.duration;
-			ir->rawir.duration = 0;
-			ir->rawir.pulse = rawir.pulse;
+					 * MS_TO_NS(MCE_TIME_UNIT);
 
 
 			dev_dbg(ir->dev, "Storing %s with duration %d\n",
 			dev_dbg(ir->dev, "Storing %s with duration %d\n",
 				rawir.pulse ? "pulse" : "space",
 				rawir.pulse ? "pulse" : "space",
 				rawir.duration);
 				rawir.duration);
 
 
-			ir_raw_event_store(ir->idev, &rawir);
+			ir_raw_event_store_with_filter(ir->idev, &rawir);
 			break;
 			break;
 		case CMD_DATA:
 		case CMD_DATA:
 			ir->rem--;
 			ir->rem--;
@@ -839,17 +882,10 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 				continue;
 				continue;
 			}
 			}
 			ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
 			ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
-			mceusb_dev_printdata(ir, ir->buf_in, i, ir->rem + 1, false);
-			if (ir->rem) {
+			mceusb_dev_printdata(ir, ir->buf_in,
+					     i, ir->rem + 1, false);
+			if (ir->rem)
 				ir->parser_state = PARSE_IRDATA;
 				ir->parser_state = PARSE_IRDATA;
-				break;
-			}
-			/*
-			 * a package with len=0 (e. g. 0x80) means end of
-			 * data. We could use it to do the call to
-			 * ir_raw_event_handle(). For now, we don't need to
-			 * use it.
-			 */
 			break;
 			break;
 		}
 		}
 
 
@@ -984,9 +1020,11 @@ static void mceusb_get_parameters(struct mceusb_dev *ir)
 	mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
 	mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
 	mce_sync_in(ir, NULL, maxp);
 	mce_sync_in(ir, NULL, maxp);
 
 
-	/* get the transmitter bitmask */
-	mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
-	mce_sync_in(ir, NULL, maxp);
+	if (!ir->flags.no_tx) {
+		/* get the transmitter bitmask */
+		mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
+		mce_sync_in(ir, NULL, maxp);
+	}
 
 
 	/* get receiver timeout value */
 	/* get receiver timeout value */
 	mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
 	mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
@@ -1035,12 +1073,18 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
 	props->priv = ir;
 	props->priv = ir;
 	props->driver_type = RC_DRIVER_IR_RAW;
 	props->driver_type = RC_DRIVER_IR_RAW;
 	props->allowed_protos = IR_TYPE_ALL;
 	props->allowed_protos = IR_TYPE_ALL;
-	props->s_tx_mask = mceusb_set_tx_mask;
-	props->s_tx_carrier = mceusb_set_tx_carrier;
-	props->tx_ir = mceusb_tx_ir;
+	props->timeout = MS_TO_NS(1000);
+	if (!ir->flags.no_tx) {
+		props->s_tx_mask = mceusb_set_tx_mask;
+		props->s_tx_carrier = mceusb_set_tx_carrier;
+		props->tx_ir = mceusb_tx_ir;
+	}
 
 
 	ir->props = props;
 	ir->props = props;
 
 
+	usb_to_input_id(ir->usbdev, &idev->id);
+	idev->dev.parent = ir->dev;
+
 	if (mceusb_model[ir->model].rc_map)
 	if (mceusb_model[ir->model].rc_map)
 		rc_map = mceusb_model[ir->model].rc_map;
 		rc_map = mceusb_model[ir->model].rc_map;
 
 
@@ -1074,16 +1118,16 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
 	enum mceusb_model_type model = id->driver_info;
 	enum mceusb_model_type model = id->driver_info;
 	bool is_gen3;
 	bool is_gen3;
 	bool is_microsoft_gen1;
 	bool is_microsoft_gen1;
-	bool tx_mask_inverted;
+	bool tx_mask_normal;
 	bool is_polaris;
 	bool is_polaris;
 
 
-	dev_dbg(&intf->dev, ": %s called\n", __func__);
+	dev_dbg(&intf->dev, "%s called\n", __func__);
 
 
 	idesc  = intf->cur_altsetting;
 	idesc  = intf->cur_altsetting;
 
 
 	is_gen3 = mceusb_model[model].mce_gen3;
 	is_gen3 = mceusb_model[model].mce_gen3;
 	is_microsoft_gen1 = mceusb_model[model].mce_gen1;
 	is_microsoft_gen1 = mceusb_model[model].mce_gen1;
-	tx_mask_inverted = mceusb_model[model].tx_mask_inverted;
+	tx_mask_normal = mceusb_model[model].tx_mask_normal;
 	is_polaris = mceusb_model[model].is_polaris;
 	is_polaris = mceusb_model[model].is_polaris;
 
 
 	if (is_polaris) {
 	if (is_polaris) {
@@ -1107,7 +1151,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
 			ep_in = ep;
 			ep_in = ep;
 			ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
 			ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
 			ep_in->bInterval = 1;
 			ep_in->bInterval = 1;
-			dev_dbg(&intf->dev, ": acceptable inbound endpoint "
+			dev_dbg(&intf->dev, "acceptable inbound endpoint "
 				"found\n");
 				"found\n");
 		}
 		}
 
 
@@ -1122,12 +1166,12 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
 			ep_out = ep;
 			ep_out = ep;
 			ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
 			ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
 			ep_out->bInterval = 1;
 			ep_out->bInterval = 1;
-			dev_dbg(&intf->dev, ": acceptable outbound endpoint "
+			dev_dbg(&intf->dev, "acceptable outbound endpoint "
 				"found\n");
 				"found\n");
 		}
 		}
 	}
 	}
 	if (ep_in == NULL) {
 	if (ep_in == NULL) {
-		dev_dbg(&intf->dev, ": inbound and/or endpoint not found\n");
+		dev_dbg(&intf->dev, "inbound and/or endpoint not found\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -1150,11 +1194,10 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
 	ir->dev = &intf->dev;
 	ir->dev = &intf->dev;
 	ir->len_in = maxp;
 	ir->len_in = maxp;
 	ir->flags.microsoft_gen1 = is_microsoft_gen1;
 	ir->flags.microsoft_gen1 = is_microsoft_gen1;
-	ir->flags.tx_mask_inverted = tx_mask_inverted;
+	ir->flags.tx_mask_normal = tx_mask_normal;
+	ir->flags.no_tx = mceusb_model[model].no_tx;
 	ir->model = model;
 	ir->model = model;
 
 
-	init_ir_raw_event(&ir->rawir);
-
 	/* Saving usb interface data for use by the transmitter routine */
 	/* Saving usb interface data for use by the transmitter routine */
 	ir->usb_ep_in = ep_in;
 	ir->usb_ep_in = ep_in;
 	ir->usb_ep_out = ep_out;
 	ir->usb_ep_out = ep_out;
@@ -1191,7 +1234,8 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
 
 
 	mceusb_get_parameters(ir);
 	mceusb_get_parameters(ir);
 
 
-	mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK);
+	if (!ir->flags.no_tx)
+		mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK);
 
 
 	usb_set_intfdata(intf, ir);
 	usb_set_intfdata(intf, ir);
 
 

+ 8 - 2
drivers/media/IR/nuvoton-cir.c

@@ -603,6 +603,8 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
 	count = nvt->pkts;
 	count = nvt->pkts;
 	nvt_dbg_verbose("Processing buffer of len %d", count);
 	nvt_dbg_verbose("Processing buffer of len %d", count);
 
 
+	init_ir_raw_event(&rawir);
+
 	for (i = 0; i < count; i++) {
 	for (i = 0; i < count; i++) {
 		nvt->pkts--;
 		nvt->pkts--;
 		sample = nvt->buf[i];
 		sample = nvt->buf[i];
@@ -643,11 +645,15 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
 		 * indicates end of IR signal, but new data incoming. In both
 		 * indicates end of IR signal, but new data incoming. In both
 		 * cases, it means we're ready to call ir_raw_event_handle
 		 * cases, it means we're ready to call ir_raw_event_handle
 		 */
 		 */
-		if (sample == BUF_PULSE_BIT || ((sample != BUF_LEN_MASK) &&
-		    (sample & BUF_REPEAT_MASK) == BUF_REPEAT_BYTE))
+		if ((sample == BUF_PULSE_BIT) && nvt->pkts) {
+			nvt_dbg("Calling ir_raw_event_handle (signal end)\n");
 			ir_raw_event_handle(nvt->rdev);
 			ir_raw_event_handle(nvt->rdev);
+		}
 	}
 	}
 
 
+	nvt_dbg("Calling ir_raw_event_handle (buffer empty)\n");
+	ir_raw_event_handle(nvt->rdev);
+
 	if (nvt->pkts) {
 	if (nvt->pkts) {
 		nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts);
 		nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts);
 		nvt->pkts = 0;
 		nvt->pkts = 0;

+ 12 - 9
drivers/media/IR/streamzap.c

@@ -34,8 +34,9 @@
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/input.h>
 #include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
 #include <media/ir-core.h>
 #include <media/ir-core.h>
 
 
 #define DRIVER_VERSION	"1.61"
 #define DRIVER_VERSION	"1.61"
@@ -140,7 +141,9 @@ static struct usb_driver streamzap_driver = {
 
 
 static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
 static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
 {
 {
-	ir_raw_event_store(sz->idev, &rawir);
+	dev_dbg(sz->dev, "Storing %s with duration %u us\n",
+		(rawir.pulse ? "pulse" : "space"), rawir.duration);
+	ir_raw_event_store_with_filter(sz->idev, &rawir);
 }
 }
 
 
 static void sz_push_full_pulse(struct streamzap_ir *sz,
 static void sz_push_full_pulse(struct streamzap_ir *sz,
@@ -167,7 +170,6 @@ static void sz_push_full_pulse(struct streamzap_ir *sz,
 			rawir.duration *= 1000;
 			rawir.duration *= 1000;
 			rawir.duration &= IR_MAX_DURATION;
 			rawir.duration &= IR_MAX_DURATION;
 		}
 		}
-		dev_dbg(sz->dev, "ls %u\n", rawir.duration);
 		sz_push(sz, rawir);
 		sz_push(sz, rawir);
 
 
 		sz->idle = false;
 		sz->idle = false;
@@ -180,7 +182,6 @@ static void sz_push_full_pulse(struct streamzap_ir *sz,
 	sz->sum += rawir.duration;
 	sz->sum += rawir.duration;
 	rawir.duration *= 1000;
 	rawir.duration *= 1000;
 	rawir.duration &= IR_MAX_DURATION;
 	rawir.duration &= IR_MAX_DURATION;
-	dev_dbg(sz->dev, "p %u\n", rawir.duration);
 	sz_push(sz, rawir);
 	sz_push(sz, rawir);
 }
 }
 
 
@@ -200,7 +201,6 @@ static void sz_push_full_space(struct streamzap_ir *sz,
 	rawir.duration += SZ_RESOLUTION / 2;
 	rawir.duration += SZ_RESOLUTION / 2;
 	sz->sum += rawir.duration;
 	sz->sum += rawir.duration;
 	rawir.duration *= 1000;
 	rawir.duration *= 1000;
-	dev_dbg(sz->dev, "s %u\n", rawir.duration);
 	sz_push(sz, rawir);
 	sz_push(sz, rawir);
 }
 }
 
 
@@ -221,8 +221,6 @@ static void streamzap_callback(struct urb *urb)
 	struct streamzap_ir *sz;
 	struct streamzap_ir *sz;
 	unsigned int i;
 	unsigned int i;
 	int len;
 	int len;
-	static int timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) &
-				IR_MAX_DURATION) | 0x03000000);
 
 
 	if (!urb)
 	if (!urb)
 		return;
 		return;
@@ -246,7 +244,7 @@ static void streamzap_callback(struct urb *urb)
 
 
 	dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
 	dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
 	for (i = 0; i < len; i++) {
 	for (i = 0; i < len; i++) {
-		dev_dbg(sz->dev, "sz idx %d: %x\n",
+		dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",
 			i, (unsigned char)sz->buf_in[i]);
 			i, (unsigned char)sz->buf_in[i]);
 		switch (sz->decoder_state) {
 		switch (sz->decoder_state) {
 		case PulseSpace:
 		case PulseSpace:
@@ -273,7 +271,7 @@ static void streamzap_callback(struct urb *urb)
 				DEFINE_IR_RAW_EVENT(rawir);
 				DEFINE_IR_RAW_EVENT(rawir);
 
 
 				rawir.pulse = false;
 				rawir.pulse = false;
-				rawir.duration = timeout;
+				rawir.duration = sz->props->timeout;
 				sz->idle = true;
 				sz->idle = true;
 				if (sz->timeout_enabled)
 				if (sz->timeout_enabled)
 					sz_push(sz, rawir);
 					sz_push(sz, rawir);
@@ -335,6 +333,9 @@ static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz)
 
 
 	sz->props = props;
 	sz->props = props;
 
 
+	usb_to_input_id(sz->usbdev, &idev->id);
+	idev->dev.parent = sz->dev;
+
 	ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME);
 	ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME);
 	if (ret < 0) {
 	if (ret < 0) {
 		dev_err(dev, "remote input device register failed\n");
 		dev_err(dev, "remote input device register failed\n");
@@ -444,6 +445,8 @@ static int __devinit streamzap_probe(struct usb_interface *intf,
 	sz->decoder_state = PulseSpace;
 	sz->decoder_state = PulseSpace;
 	/* FIXME: don't yet have a way to set this */
 	/* FIXME: don't yet have a way to set this */
 	sz->timeout_enabled = true;
 	sz->timeout_enabled = true;
+	sz->props->timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) &
+				IR_MAX_DURATION) | 0x03000000);
 	#if 0
 	#if 0
 	/* not yet supported, depends on patches from maxim */
 	/* not yet supported, depends on patches from maxim */
 	/* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
 	/* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */

+ 4 - 4
drivers/media/common/saa7146_hlp.c

@@ -558,7 +558,7 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e
 static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
 static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
 {
 {
 	struct saa7146_vv *vv = dev->vv_data;
 	struct saa7146_vv *vv = dev->vv_data;
-	struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat);
+	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat);
 
 
 	int b_depth = vv->ov_fmt->depth;
 	int b_depth = vv->ov_fmt->depth;
 	int b_bpl = vv->ov_fb.fmt.bytesperline;
 	int b_bpl = vv->ov_fb.fmt.bytesperline;
@@ -702,7 +702,7 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
 	struct saa7146_vv *vv = dev->vv_data;
 	struct saa7146_vv *vv = dev->vv_data;
 	struct saa7146_video_dma vdma1;
 	struct saa7146_video_dma vdma1;
 
 
-	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
 
 	int width = buf->fmt->width;
 	int width = buf->fmt->width;
 	int height = buf->fmt->height;
 	int height = buf->fmt->height;
@@ -827,7 +827,7 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71
 	struct saa7146_video_dma vdma2;
 	struct saa7146_video_dma vdma2;
 	struct saa7146_video_dma vdma3;
 	struct saa7146_video_dma vdma3;
 
 
-	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
 
 	int width = buf->fmt->width;
 	int width = buf->fmt->width;
 	int height = buf->fmt->height;
 	int height = buf->fmt->height;
@@ -994,7 +994,7 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar)
 
 
 void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
 void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
 {
 {
-	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 	struct saa7146_vv *vv = dev->vv_data;
 	struct saa7146_vv *vv = dev->vv_data;
 	u32 vdma1_prot_addr;
 	u32 vdma1_prot_addr;
 
 

+ 8 - 8
drivers/media/common/saa7146_video.c

@@ -84,7 +84,7 @@ static struct saa7146_format formats[] = {
 
 
 static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format);
 static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format);
 
 
-struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc)
+struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc)
 {
 {
 	int i, j = NUM_FORMATS;
 	int i, j = NUM_FORMATS;
 
 
@@ -266,7 +266,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
 	struct scatterlist *list = dma->sglist;
 	struct scatterlist *list = dma->sglist;
 	int length = dma->sglen;
 	int length = dma->sglen;
-	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
 
 	DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
 	DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
 
 
@@ -408,7 +408,7 @@ static int video_begin(struct saa7146_fh *fh)
 		}
 		}
 	}
 	}
 
 
-	fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+	fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
 	/* we need to have a valid format set here */
 	/* we need to have a valid format set here */
 	BUG_ON(NULL == fmt);
 	BUG_ON(NULL == fmt);
 
 
@@ -460,7 +460,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
 		return -EBUSY;
 		return -EBUSY;
 	}
 	}
 
 
-	fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+	fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
 	/* we need to have a valid format set here */
 	/* we need to have a valid format set here */
 	BUG_ON(NULL == fmt);
 	BUG_ON(NULL == fmt);
 
 
@@ -536,7 +536,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
 		return -EPERM;
 		return -EPERM;
 
 
 	/* check args */
 	/* check args */
-	fmt = format_by_fourcc(dev, fb->fmt.pixelformat);
+	fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat);
 	if (NULL == fmt)
 	if (NULL == fmt)
 		return -EINVAL;
 		return -EINVAL;
 
 
@@ -760,7 +760,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
 
 
 	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
 	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
 
 
-	fmt = format_by_fourcc(dev, f->fmt.pix.pixelformat);
+	fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
 	if (NULL == fmt)
 	if (NULL == fmt)
 		return -EINVAL;
 		return -EINVAL;
 
 
@@ -1264,7 +1264,7 @@ static int buffer_prepare(struct videobuf_queue *q,
 		buf->fmt       = &fh->video_fmt;
 		buf->fmt       = &fh->video_fmt;
 		buf->vb.field  = fh->video_fmt.field;
 		buf->vb.field  = fh->video_fmt.field;
 
 
-		sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+		sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
 
 		release_all_pagetables(dev, buf);
 		release_all_pagetables(dev, buf);
 		if( 0 != IS_PLANAR(sfmt->trans)) {
 		if( 0 != IS_PLANAR(sfmt->trans)) {
@@ -1378,7 +1378,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
 	fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;
 	fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;
 	fh->video_fmt.bytesperline = 0;
 	fh->video_fmt.bytesperline = 0;
 	fh->video_fmt.field = V4L2_FIELD_ANY;
 	fh->video_fmt.field = V4L2_FIELD_ANY;
-	sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+	sfmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
 	fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
 	fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
 
 
 	videobuf_queue_sg_init(&fh->video_q, &video_qops,
 	videobuf_queue_sg_init(&fh->video_q, &video_qops,

+ 3 - 114
drivers/media/video/bt8xx/bttv-driver.c

@@ -854,7 +854,6 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
 		xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
 		xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
 
 
 	/* is it free? */
 	/* is it free? */
-	mutex_lock(&btv->lock);
 	if (btv->resources & xbits) {
 	if (btv->resources & xbits) {
 		/* no, someone else uses it */
 		/* no, someone else uses it */
 		goto fail;
 		goto fail;
@@ -884,11 +883,9 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
 	/* it's free, grab it */
 	/* it's free, grab it */
 	fh->resources  |= bit;
 	fh->resources  |= bit;
 	btv->resources |= bit;
 	btv->resources |= bit;
-	mutex_unlock(&btv->lock);
 	return 1;
 	return 1;
 
 
  fail:
  fail:
-	mutex_unlock(&btv->lock);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -940,7 +937,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
 		/* trying to free ressources not allocated by us ... */
 		/* trying to free ressources not allocated by us ... */
 		printk("bttv: BUG! (btres)\n");
 		printk("bttv: BUG! (btres)\n");
 	}
 	}
-	mutex_lock(&btv->lock);
 	fh->resources  &= ~bits;
 	fh->resources  &= ~bits;
 	btv->resources &= ~bits;
 	btv->resources &= ~bits;
 
 
@@ -951,8 +947,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
 
 
 	if (0 == (bits & VBI_RESOURCES))
 	if (0 == (bits & VBI_RESOURCES))
 		disclaim_vbi_lines(btv);
 		disclaim_vbi_lines(btv);
-
-	mutex_unlock(&btv->lock);
 }
 }
 
 
 /* ----------------------------------------------------------------------- */
 /* ----------------------------------------------------------------------- */
@@ -1713,28 +1707,20 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
 
 
 		/* Make sure tvnorm and vbi_end remain consistent
 		/* Make sure tvnorm and vbi_end remain consistent
 		   until we're done. */
 		   until we're done. */
-		mutex_lock(&btv->lock);
 
 
 		norm = btv->tvnorm;
 		norm = btv->tvnorm;
 
 
 		/* In this mode capturing always starts at defrect.top
 		/* In this mode capturing always starts at defrect.top
 		   (default VDELAY), ignoring cropping parameters. */
 		   (default VDELAY), ignoring cropping parameters. */
 		if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
 		if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
-			mutex_unlock(&btv->lock);
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
 
 
-		mutex_unlock(&btv->lock);
-
 		c.rect = bttv_tvnorms[norm].cropcap.defrect;
 		c.rect = bttv_tvnorms[norm].cropcap.defrect;
 	} else {
 	} else {
-		mutex_lock(&btv->lock);
-
 		norm = btv->tvnorm;
 		norm = btv->tvnorm;
 		c = btv->crop[!!fh->do_crop];
 		c = btv->crop[!!fh->do_crop];
 
 
-		mutex_unlock(&btv->lock);
-
 		if (width < c.min_scaled_width ||
 		if (width < c.min_scaled_width ||
 		    width > c.max_scaled_width ||
 		    width > c.max_scaled_width ||
 		    height < c.min_scaled_height)
 		    height < c.min_scaled_height)
@@ -1858,7 +1844,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
 	unsigned int i;
 	unsigned int i;
 	int err;
 	int err;
 
 
-	mutex_lock(&btv->lock);
 	err = v4l2_prio_check(&btv->prio, fh->prio);
 	err = v4l2_prio_check(&btv->prio, fh->prio);
 	if (err)
 	if (err)
 		goto err;
 		goto err;
@@ -1874,7 +1859,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
 	set_tvnorm(btv, i);
 	set_tvnorm(btv, i);
 
 
 err:
 err:
-	mutex_unlock(&btv->lock);
 
 
 	return err;
 	return err;
 }
 }
@@ -1898,7 +1882,6 @@ static int bttv_enum_input(struct file *file, void *priv,
 	struct bttv *btv = fh->btv;
 	struct bttv *btv = fh->btv;
 	int rc = 0;
 	int rc = 0;
 
 
-	mutex_lock(&btv->lock);
 	if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
 	if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
 		rc = -EINVAL;
 		rc = -EINVAL;
 		goto err;
 		goto err;
@@ -1928,7 +1911,6 @@ static int bttv_enum_input(struct file *file, void *priv,
 	i->std = BTTV_NORMS;
 	i->std = BTTV_NORMS;
 
 
 err:
 err:
-	mutex_unlock(&btv->lock);
 
 
 	return rc;
 	return rc;
 }
 }
@@ -1938,9 +1920,7 @@ static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
 	struct bttv_fh *fh = priv;
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
 	struct bttv *btv = fh->btv;
 
 
-	mutex_lock(&btv->lock);
 	*i = btv->input;
 	*i = btv->input;
-	mutex_unlock(&btv->lock);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1952,7 +1932,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)
 
 
 	int err;
 	int err;
 
 
-	mutex_lock(&btv->lock);
 	err = v4l2_prio_check(&btv->prio, fh->prio);
 	err = v4l2_prio_check(&btv->prio, fh->prio);
 	if (unlikely(err))
 	if (unlikely(err))
 		goto err;
 		goto err;
@@ -1965,7 +1944,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)
 	set_input(btv, i, btv->tvnorm);
 	set_input(btv, i, btv->tvnorm);
 
 
 err:
 err:
-	mutex_unlock(&btv->lock);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1979,7 +1957,6 @@ static int bttv_s_tuner(struct file *file, void *priv,
 	if (unlikely(0 != t->index))
 	if (unlikely(0 != t->index))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	mutex_lock(&btv->lock);
 	if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
 	if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
 		err = -EINVAL;
 		err = -EINVAL;
 		goto err;
 		goto err;
@@ -1995,7 +1972,6 @@ static int bttv_s_tuner(struct file *file, void *priv,
 		btv->audio_mode_gpio(btv, t, 1);
 		btv->audio_mode_gpio(btv, t, 1);
 
 
 err:
 err:
-	mutex_unlock(&btv->lock);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -2006,10 +1982,8 @@ static int bttv_g_frequency(struct file *file, void *priv,
 	struct bttv_fh *fh  = priv;
 	struct bttv_fh *fh  = priv;
 	struct bttv *btv = fh->btv;
 	struct bttv *btv = fh->btv;
 
 
-	mutex_lock(&btv->lock);
 	f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 	f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 	f->frequency = btv->freq;
 	f->frequency = btv->freq;
-	mutex_unlock(&btv->lock);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -2024,7 +1998,6 @@ static int bttv_s_frequency(struct file *file, void *priv,
 	if (unlikely(f->tuner != 0))
 	if (unlikely(f->tuner != 0))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	mutex_lock(&btv->lock);
 	err = v4l2_prio_check(&btv->prio, fh->prio);
 	err = v4l2_prio_check(&btv->prio, fh->prio);
 	if (unlikely(err))
 	if (unlikely(err))
 		goto err;
 		goto err;
@@ -2039,7 +2012,6 @@ static int bttv_s_frequency(struct file *file, void *priv,
 	if (btv->has_matchbox && btv->radio_user)
 	if (btv->has_matchbox && btv->radio_user)
 		tea5757_set_freq(btv, btv->freq);
 		tea5757_set_freq(btv, btv->freq);
 err:
 err:
-	mutex_unlock(&btv->lock);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -2172,7 +2144,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,
 
 
 	/* Make sure tvnorm, vbi_end and the current cropping parameters
 	/* Make sure tvnorm, vbi_end and the current cropping parameters
 	   remain consistent until we're done. */
 	   remain consistent until we're done. */
-	mutex_lock(&btv->lock);
 
 
 	b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
 	b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
 
 
@@ -2250,7 +2221,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,
 	rc = 0; /* success */
 	rc = 0; /* success */
 
 
  fail:
  fail:
-	mutex_unlock(&btv->lock);
 
 
 	return rc;
 	return rc;
 }
 }
@@ -2282,9 +2252,7 @@ verify_window_lock		(struct bttv_fh *               fh,
 	if (V4L2_FIELD_ANY == field) {
 	if (V4L2_FIELD_ANY == field) {
 		__s32 height2;
 		__s32 height2;
 
 
-		mutex_lock(&fh->btv->lock);
 		height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
 		height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
-		mutex_unlock(&fh->btv->lock);
 		field = (win->w.height > height2)
 		field = (win->w.height > height2)
 			? V4L2_FIELD_INTERLACED
 			? V4L2_FIELD_INTERLACED
 			: V4L2_FIELD_TOP;
 			: V4L2_FIELD_TOP;
@@ -2360,7 +2328,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
 		}
 		}
 	}
 	}
 
 
-	mutex_lock(&fh->cap.vb_lock);
 	/* clip against screen */
 	/* clip against screen */
 	if (NULL != btv->fbuf.base)
 	if (NULL != btv->fbuf.base)
 		n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
 		n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
@@ -2391,13 +2358,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
 	fh->ov.field    = win->field;
 	fh->ov.field    = win->field;
 	fh->ov.setup_ok = 1;
 	fh->ov.setup_ok = 1;
 
 
-	/*
-	 * FIXME: btv is protected by btv->lock mutex, while btv->init
-	 *	  is protected by fh->cap.vb_lock. This seems to open the
-	 *	  possibility for some race situations. Maybe the better would
-	 *	  be to unify those locks or to use another way to store the
-	 *	  init values that will be consumed by videobuf callbacks
-	 */
 	btv->init.ov.w.width   = win->w.width;
 	btv->init.ov.w.width   = win->w.width;
 	btv->init.ov.w.height  = win->w.height;
 	btv->init.ov.w.height  = win->w.height;
 	btv->init.ov.field     = win->field;
 	btv->init.ov.field     = win->field;
@@ -2412,7 +2372,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
 		bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
 		bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
 		retval = bttv_switch_overlay(btv,fh,new);
 		retval = bttv_switch_overlay(btv,fh,new);
 	}
 	}
-	mutex_unlock(&fh->cap.vb_lock);
 	return retval;
 	return retval;
 }
 }
 
 
@@ -2526,9 +2485,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
 	if (V4L2_FIELD_ANY == field) {
 	if (V4L2_FIELD_ANY == field) {
 		__s32 height2;
 		__s32 height2;
 
 
-		mutex_lock(&btv->lock);
 		height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
 		height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
-		mutex_unlock(&btv->lock);
 		field = (f->fmt.pix.height > height2)
 		field = (f->fmt.pix.height > height2)
 			? V4L2_FIELD_INTERLACED
 			? V4L2_FIELD_INTERLACED
 			: V4L2_FIELD_BOTTOM;
 			: V4L2_FIELD_BOTTOM;
@@ -2614,7 +2571,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
 	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 
 
 	/* update our state informations */
 	/* update our state informations */
-	mutex_lock(&fh->cap.vb_lock);
 	fh->fmt              = fmt;
 	fh->fmt              = fmt;
 	fh->cap.field        = f->fmt.pix.field;
 	fh->cap.field        = f->fmt.pix.field;
 	fh->cap.last         = V4L2_FIELD_NONE;
 	fh->cap.last         = V4L2_FIELD_NONE;
@@ -2623,7 +2579,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
 	btv->init.fmt        = fmt;
 	btv->init.fmt        = fmt;
 	btv->init.width      = f->fmt.pix.width;
 	btv->init.width      = f->fmt.pix.width;
 	btv->init.height     = f->fmt.pix.height;
 	btv->init.height     = f->fmt.pix.height;
-	mutex_unlock(&fh->cap.vb_lock);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -2649,11 +2604,9 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
 	unsigned int i;
 	unsigned int i;
 	struct bttv_fh *fh = priv;
 	struct bttv_fh *fh = priv;
 
 
-	mutex_lock(&fh->cap.vb_lock);
 	retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
 	retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
 				     V4L2_MEMORY_MMAP);
 				     V4L2_MEMORY_MMAP);
 	if (retval < 0) {
 	if (retval < 0) {
-		mutex_unlock(&fh->cap.vb_lock);
 		return retval;
 		return retval;
 	}
 	}
 
 
@@ -2665,7 +2618,6 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
 	for (i = 0; i < gbuffers; i++)
 	for (i = 0; i < gbuffers; i++)
 		mbuf->offsets[i] = i * gbufsize;
 		mbuf->offsets[i] = i * gbufsize;
 
 
-	mutex_unlock(&fh->cap.vb_lock);
 	return 0;
 	return 0;
 }
 }
 #endif
 #endif
@@ -2775,10 +2727,8 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
 	int retval = 0;
 	int retval = 0;
 
 
 	if (on) {
 	if (on) {
-		mutex_lock(&fh->cap.vb_lock);
 		/* verify args */
 		/* verify args */
 		if (unlikely(!btv->fbuf.base)) {
 		if (unlikely(!btv->fbuf.base)) {
-			mutex_unlock(&fh->cap.vb_lock);
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
 		if (unlikely(!fh->ov.setup_ok)) {
 		if (unlikely(!fh->ov.setup_ok)) {
@@ -2787,13 +2737,11 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
 		}
 		}
 		if (retval)
 		if (retval)
 			return retval;
 			return retval;
-		mutex_unlock(&fh->cap.vb_lock);
 	}
 	}
 
 
 	if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
 	if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
 		return -EBUSY;
 		return -EBUSY;
 
 
-	mutex_lock(&fh->cap.vb_lock);
 	if (on) {
 	if (on) {
 		fh->ov.tvnorm = btv->tvnorm;
 		fh->ov.tvnorm = btv->tvnorm;
 		new = videobuf_sg_alloc(sizeof(*new));
 		new = videobuf_sg_alloc(sizeof(*new));
@@ -2805,7 +2753,6 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
 
 
 	/* switch over */
 	/* switch over */
 	retval = bttv_switch_overlay(btv, fh, new);
 	retval = bttv_switch_overlay(btv, fh, new);
-	mutex_unlock(&fh->cap.vb_lock);
 	return retval;
 	return retval;
 }
 }
 
 
@@ -2844,7 +2791,6 @@ static int bttv_s_fbuf(struct file *file, void *f,
 	}
 	}
 
 
 	/* ok, accept it */
 	/* ok, accept it */
-	mutex_lock(&fh->cap.vb_lock);
 	btv->fbuf.base       = fb->base;
 	btv->fbuf.base       = fb->base;
 	btv->fbuf.fmt.width  = fb->fmt.width;
 	btv->fbuf.fmt.width  = fb->fmt.width;
 	btv->fbuf.fmt.height = fb->fmt.height;
 	btv->fbuf.fmt.height = fb->fmt.height;
@@ -2876,7 +2822,6 @@ static int bttv_s_fbuf(struct file *file, void *f,
 			retval = bttv_switch_overlay(btv, fh, new);
 			retval = bttv_switch_overlay(btv, fh, new);
 		}
 		}
 	}
 	}
-	mutex_unlock(&fh->cap.vb_lock);
 	return retval;
 	return retval;
 }
 }
 
 
@@ -2955,7 +2900,6 @@ static int bttv_queryctrl(struct file *file, void *priv,
 	     c->id >= V4L2_CID_PRIVATE_LASTP1))
 	     c->id >= V4L2_CID_PRIVATE_LASTP1))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	mutex_lock(&btv->lock);
 	if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
 	if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
 		*c = no_ctl;
 		*c = no_ctl;
 	else {
 	else {
@@ -2963,7 +2907,6 @@ static int bttv_queryctrl(struct file *file, void *priv,
 
 
 		*c = (NULL != ctrl) ? *ctrl : no_ctl;
 		*c = (NULL != ctrl) ? *ctrl : no_ctl;
 	}
 	}
-	mutex_unlock(&btv->lock);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -2974,10 +2917,8 @@ static int bttv_g_parm(struct file *file, void *f,
 	struct bttv_fh *fh = f;
 	struct bttv_fh *fh = f;
 	struct bttv *btv = fh->btv;
 	struct bttv *btv = fh->btv;
 
 
-	mutex_lock(&btv->lock);
 	v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
 	v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
 				    &parm->parm.capture.timeperframe);
 				    &parm->parm.capture.timeperframe);
-	mutex_unlock(&btv->lock);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -2993,7 +2934,6 @@ static int bttv_g_tuner(struct file *file, void *priv,
 	if (0 != t->index)
 	if (0 != t->index)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	mutex_lock(&btv->lock);
 	t->rxsubchans = V4L2_TUNER_SUB_MONO;
 	t->rxsubchans = V4L2_TUNER_SUB_MONO;
 	bttv_call_all(btv, tuner, g_tuner, t);
 	bttv_call_all(btv, tuner, g_tuner, t);
 	strcpy(t->name, "Television");
 	strcpy(t->name, "Television");
@@ -3005,7 +2945,6 @@ static int bttv_g_tuner(struct file *file, void *priv,
 	if (btv->audio_mode_gpio)
 	if (btv->audio_mode_gpio)
 		btv->audio_mode_gpio(btv, t, 0);
 		btv->audio_mode_gpio(btv, t, 0);
 
 
-	mutex_unlock(&btv->lock);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3014,9 +2953,7 @@ static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
 	struct bttv_fh *fh = f;
 	struct bttv_fh *fh = f;
 	struct bttv *btv = fh->btv;
 	struct bttv *btv = fh->btv;
 
 
-	mutex_lock(&btv->lock);
 	*p = v4l2_prio_max(&btv->prio);
 	*p = v4l2_prio_max(&btv->prio);
-	mutex_unlock(&btv->lock);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -3028,9 +2965,7 @@ static int bttv_s_priority(struct file *file, void *f,
 	struct bttv *btv = fh->btv;
 	struct bttv *btv = fh->btv;
 	int	rc;
 	int	rc;
 
 
-	mutex_lock(&btv->lock);
 	rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
 	rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
-	mutex_unlock(&btv->lock);
 
 
 	return rc;
 	return rc;
 }
 }
@@ -3045,9 +2980,7 @@ static int bttv_cropcap(struct file *file, void *priv,
 	    cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
 	    cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	mutex_lock(&btv->lock);
 	*cap = bttv_tvnorms[btv->tvnorm].cropcap;
 	*cap = bttv_tvnorms[btv->tvnorm].cropcap;
-	mutex_unlock(&btv->lock);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -3065,9 +2998,7 @@ static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
 	   inconsistent with fh->width or fh->height and apps
 	   inconsistent with fh->width or fh->height and apps
 	   do not expect a change here. */
 	   do not expect a change here. */
 
 
-	mutex_lock(&btv->lock);
 	crop->c = btv->crop[!!fh->do_crop].rect;
 	crop->c = btv->crop[!!fh->do_crop].rect;
-	mutex_unlock(&btv->lock);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -3091,17 +3022,14 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
 	/* Make sure tvnorm, vbi_end and the current cropping
 	/* Make sure tvnorm, vbi_end and the current cropping
 	   parameters remain consistent until we're done. Note
 	   parameters remain consistent until we're done. Note
 	   read() may change vbi_end in check_alloc_btres_lock(). */
 	   read() may change vbi_end in check_alloc_btres_lock(). */
-	mutex_lock(&btv->lock);
 	retval = v4l2_prio_check(&btv->prio, fh->prio);
 	retval = v4l2_prio_check(&btv->prio, fh->prio);
 	if (0 != retval) {
 	if (0 != retval) {
-		mutex_unlock(&btv->lock);
 		return retval;
 		return retval;
 	}
 	}
 
 
 	retval = -EBUSY;
 	retval = -EBUSY;
 
 
 	if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
 	if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
-		mutex_unlock(&btv->lock);
 		return retval;
 		return retval;
 	}
 	}
 
 
@@ -3113,7 +3041,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
 
 
 	b_top = max(b->top, btv->vbi_end);
 	b_top = max(b->top, btv->vbi_end);
 	if (b_top + 32 >= b_bottom) {
 	if (b_top + 32 >= b_bottom) {
-		mutex_unlock(&btv->lock);
 		return retval;
 		return retval;
 	}
 	}
 
 
@@ -3136,12 +3063,8 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
 
 
 	btv->crop[1] = c;
 	btv->crop[1] = c;
 
 
-	mutex_unlock(&btv->lock);
-
 	fh->do_crop = 1;
 	fh->do_crop = 1;
 
 
-	mutex_lock(&fh->cap.vb_lock);
-
 	if (fh->width < c.min_scaled_width) {
 	if (fh->width < c.min_scaled_width) {
 		fh->width = c.min_scaled_width;
 		fh->width = c.min_scaled_width;
 		btv->init.width = c.min_scaled_width;
 		btv->init.width = c.min_scaled_width;
@@ -3158,8 +3081,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
 		btv->init.height = c.max_scaled_height;
 		btv->init.height = c.max_scaled_height;
 	}
 	}
 
 
-	mutex_unlock(&fh->cap.vb_lock);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3227,7 +3148,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
 		return videobuf_poll_stream(file, &fh->vbi, wait);
 		return videobuf_poll_stream(file, &fh->vbi, wait);
 	}
 	}
 
 
-	mutex_lock(&fh->cap.vb_lock);
 	if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
 	if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
 		/* streaming capture */
 		/* streaming capture */
 		if (list_empty(&fh->cap.stream))
 		if (list_empty(&fh->cap.stream))
@@ -3262,7 +3182,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
 	else
 	else
 		rc = 0;
 		rc = 0;
 err:
 err:
-	mutex_unlock(&fh->cap.vb_lock);
 	return rc;
 	return rc;
 }
 }
 
 
@@ -3293,23 +3212,11 @@ static int bttv_open(struct file *file)
 		return -ENOMEM;
 		return -ENOMEM;
 	file->private_data = fh;
 	file->private_data = fh;
 
 
-	/*
-	 * btv is protected by btv->lock mutex, while btv->init and other
-	 * streaming vars are protected by fh->cap.vb_lock. We need to take
-	 * care of both locks to avoid troubles. However, vb_lock is used also
-	 * inside videobuf, without calling buf->lock. So, it is a very bad
-	 * idea to hold both locks at the same time.
-	 * Let's first copy btv->init at fh, holding cap.vb_lock, and then work
-	 * with the rest of init, holding btv->lock.
-	 */
-	mutex_lock(&fh->cap.vb_lock);
 	*fh = btv->init;
 	*fh = btv->init;
-	mutex_unlock(&fh->cap.vb_lock);
 
 
 	fh->type = type;
 	fh->type = type;
 	fh->ov.setup_ok = 0;
 	fh->ov.setup_ok = 0;
 
 
-	mutex_lock(&btv->lock);
 	v4l2_prio_open(&btv->prio, &fh->prio);
 	v4l2_prio_open(&btv->prio, &fh->prio);
 
 
 	videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
 	videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
@@ -3317,13 +3224,13 @@ static int bttv_open(struct file *file)
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			    V4L2_FIELD_INTERLACED,
 			    V4L2_FIELD_INTERLACED,
 			    sizeof(struct bttv_buffer),
 			    sizeof(struct bttv_buffer),
-			    fh, NULL);
+			    fh, &btv->lock);
 	videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
 	videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
 			    &btv->c.pci->dev, &btv->s_lock,
 			    &btv->c.pci->dev, &btv->s_lock,
 			    V4L2_BUF_TYPE_VBI_CAPTURE,
 			    V4L2_BUF_TYPE_VBI_CAPTURE,
 			    V4L2_FIELD_SEQ_TB,
 			    V4L2_FIELD_SEQ_TB,
 			    sizeof(struct bttv_buffer),
 			    sizeof(struct bttv_buffer),
-			    fh, NULL);
+			    fh, &btv->lock);
 	set_tvnorm(btv,btv->tvnorm);
 	set_tvnorm(btv,btv->tvnorm);
 	set_input(btv, btv->input, btv->tvnorm);
 	set_input(btv, btv->input, btv->tvnorm);
 
 
@@ -3346,7 +3253,6 @@ static int bttv_open(struct file *file)
 	bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
 	bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
 
 
 	bttv_field_count(btv);
 	bttv_field_count(btv);
-	mutex_unlock(&btv->lock);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3355,7 +3261,6 @@ static int bttv_release(struct file *file)
 	struct bttv_fh *fh = file->private_data;
 	struct bttv_fh *fh = file->private_data;
 	struct bttv *btv = fh->btv;
 	struct bttv *btv = fh->btv;
 
 
-	mutex_lock(&btv->lock);
 	/* turn off overlay */
 	/* turn off overlay */
 	if (check_btres(fh, RESOURCE_OVERLAY))
 	if (check_btres(fh, RESOURCE_OVERLAY))
 		bttv_switch_overlay(btv,fh,NULL);
 		bttv_switch_overlay(btv,fh,NULL);
@@ -3381,14 +3286,8 @@ static int bttv_release(struct file *file)
 
 
 	/* free stuff */
 	/* free stuff */
 
 
-	/*
-	 * videobuf uses cap.vb_lock - we should avoid holding btv->lock,
-	 * otherwise we may have dead lock conditions
-	 */
-	mutex_unlock(&btv->lock);
 	videobuf_mmap_free(&fh->cap);
 	videobuf_mmap_free(&fh->cap);
 	videobuf_mmap_free(&fh->vbi);
 	videobuf_mmap_free(&fh->vbi);
-	mutex_lock(&btv->lock);
 	v4l2_prio_close(&btv->prio, fh->prio);
 	v4l2_prio_close(&btv->prio, fh->prio);
 	file->private_data = NULL;
 	file->private_data = NULL;
 	kfree(fh);
 	kfree(fh);
@@ -3398,7 +3297,6 @@ static int bttv_release(struct file *file)
 
 
 	if (!btv->users)
 	if (!btv->users)
 		audio_mute(btv, 1);
 		audio_mute(btv, 1);
-	mutex_unlock(&btv->lock);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -3502,11 +3400,8 @@ static int radio_open(struct file *file)
 	if (unlikely(!fh))
 	if (unlikely(!fh))
 		return -ENOMEM;
 		return -ENOMEM;
 	file->private_data = fh;
 	file->private_data = fh;
-	mutex_lock(&fh->cap.vb_lock);
 	*fh = btv->init;
 	*fh = btv->init;
-	mutex_unlock(&fh->cap.vb_lock);
 
 
-	mutex_lock(&btv->lock);
 	v4l2_prio_open(&btv->prio, &fh->prio);
 	v4l2_prio_open(&btv->prio, &fh->prio);
 
 
 	btv->radio_user++;
 	btv->radio_user++;
@@ -3514,7 +3409,6 @@ static int radio_open(struct file *file)
 	bttv_call_all(btv, tuner, s_radio);
 	bttv_call_all(btv, tuner, s_radio);
 	audio_input(btv,TVAUDIO_INPUT_RADIO);
 	audio_input(btv,TVAUDIO_INPUT_RADIO);
 
 
-	mutex_unlock(&btv->lock);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3524,7 +3418,6 @@ static int radio_release(struct file *file)
 	struct bttv *btv = fh->btv;
 	struct bttv *btv = fh->btv;
 	struct rds_command cmd;
 	struct rds_command cmd;
 
 
-	mutex_lock(&btv->lock);
 	v4l2_prio_close(&btv->prio, fh->prio);
 	v4l2_prio_close(&btv->prio, fh->prio);
 	file->private_data = NULL;
 	file->private_data = NULL;
 	kfree(fh);
 	kfree(fh);
@@ -3532,7 +3425,6 @@ static int radio_release(struct file *file)
 	btv->radio_user--;
 	btv->radio_user--;
 
 
 	bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd);
 	bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd);
-	mutex_unlock(&btv->lock);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -3561,7 +3453,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 		return -EINVAL;
 		return -EINVAL;
 	if (0 != t->index)
 	if (0 != t->index)
 		return -EINVAL;
 		return -EINVAL;
-	mutex_lock(&btv->lock);
 	strcpy(t->name, "Radio");
 	strcpy(t->name, "Radio");
 	t->type = V4L2_TUNER_RADIO;
 	t->type = V4L2_TUNER_RADIO;
 
 
@@ -3570,8 +3461,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 	if (btv->audio_mode_gpio)
 	if (btv->audio_mode_gpio)
 		btv->audio_mode_gpio(btv, t, 0);
 		btv->audio_mode_gpio(btv, t, 0);
 
 
-	mutex_unlock(&btv->lock);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3692,7 +3581,7 @@ static const struct v4l2_file_operations radio_fops =
 	.open	  = radio_open,
 	.open	  = radio_open,
 	.read     = radio_read,
 	.read     = radio_read,
 	.release  = radio_release,
 	.release  = radio_release,
-	.ioctl	  = video_ioctl2,
+	.unlocked_ioctl = video_ioctl2,
 	.poll     = radio_poll,
 	.poll     = radio_poll,
 };
 };
 
 

+ 184 - 232
drivers/media/video/gspca/sonixj.c

@@ -63,7 +63,10 @@ struct sd {
 #define QUALITY_DEF 80
 #define QUALITY_DEF 80
 	u8 jpegqual;			/* webcam quality */
 	u8 jpegqual;			/* webcam quality */
 
 
+	u8 reg01;
+	u8 reg17;
 	u8 reg18;
 	u8 reg18;
+	u8 flags;
 
 
 	s8 ag_cnt;
 	s8 ag_cnt;
 #define AG_CNT_START 13
 #define AG_CNT_START 13
@@ -96,6 +99,22 @@ enum sensors {
 	SENSOR_SP80708,
 	SENSOR_SP80708,
 };
 };
 
 
+/* device flags */
+#define PDN_INV	1		/* inverse pin S_PWR_DN / sn_xxx tables */
+
+/* sn9c1xx definitions */
+/* register 0x01 */
+#define S_PWR_DN	0x01	/* sensor power down */
+#define S_PDN_INV	0x02	/* inverse pin S_PWR_DN */
+#define V_TX_EN		0x04	/* video transfer enable */
+#define LED		0x08	/* output to pin LED */
+#define SCL_SEL_OD	0x20	/* open-drain mode */
+#define SYS_SEL_48M	0x40	/* system clock 0: 24MHz, 1: 48MHz */
+/* register 0x17 */
+#define MCK_SIZE_MASK	0x1f	/* sensor master clock */
+#define SEN_CLK_EN	0x20	/* enable sensor clock */
+#define DEF_EN		0x80	/* defect pixel by 0: soft, 1: hard */
+
 /* V4L2 controls supported by the driver */
 /* V4L2 controls supported by the driver */
 static void setbrightness(struct gspca_dev *gspca_dev);
 static void setbrightness(struct gspca_dev *gspca_dev);
 static void setcontrast(struct gspca_dev *gspca_dev);
 static void setcontrast(struct gspca_dev *gspca_dev);
@@ -1755,141 +1774,6 @@ static void po2030n_probe(struct gspca_dev *gspca_dev)
 	}
 	}
 }
 }
 
 
-static void bridge_init(struct gspca_dev *gspca_dev,
-			  const u8 *sn9c1xx)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	u8 reg0102[2];
-	const u8 *reg9a;
-	static const u8 reg9a_def[] =
-		{0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
-	static const u8 reg9a_spec[] =
-		{0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
-	static const u8 regd4[] = {0x60, 0x00, 0x00};
-
-	/* sensor clock already enabled in sd_init */
-	/* reg_w1(gspca_dev, 0xf1, 0x00); */
-	reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
-
-	/* configure gpio */
-	reg0102[0] = sn9c1xx[1];
-	reg0102[1] = sn9c1xx[2];
-	if (gspca_dev->audio)
-		reg0102[1] |= 0x04;	/* keep the audio connection */
-	reg_w(gspca_dev, 0x01, reg0102, 2);
-	reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
-	reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
-	switch (sd->sensor) {
-	case SENSOR_GC0307:
-	case SENSOR_OV7660:
-	case SENSOR_PO1030:
-	case SENSOR_PO2030N:
-	case SENSOR_SOI768:
-	case SENSOR_SP80708:
-		reg9a = reg9a_spec;
-		break;
-	default:
-		reg9a = reg9a_def;
-		break;
-	}
-	reg_w(gspca_dev, 0x9a, reg9a, 6);
-
-	reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
-
-	reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
-
-	switch (sd->sensor) {
-	case SENSOR_ADCM1700:
-		reg_w1(gspca_dev, 0x01, 0x43);
-		reg_w1(gspca_dev, 0x17, 0x62);
-		reg_w1(gspca_dev, 0x01, 0x42);
-		reg_w1(gspca_dev, 0x01, 0x42);
-		break;
-	case SENSOR_GC0307:
-		msleep(50);
-		reg_w1(gspca_dev, 0x01, 0x61);
-		reg_w1(gspca_dev, 0x17, 0x22);
-		reg_w1(gspca_dev, 0x01, 0x60);
-		reg_w1(gspca_dev, 0x01, 0x40);
-		msleep(50);
-		break;
-	case SENSOR_MI0360B:
-		reg_w1(gspca_dev, 0x01, 0x61);
-		reg_w1(gspca_dev, 0x17, 0x60);
-		reg_w1(gspca_dev, 0x01, 0x60);
-		reg_w1(gspca_dev, 0x01, 0x40);
-		break;
-	case SENSOR_MT9V111:
-		reg_w1(gspca_dev, 0x01, 0x61);
-		reg_w1(gspca_dev, 0x17, 0x61);
-		reg_w1(gspca_dev, 0x01, 0x60);
-		reg_w1(gspca_dev, 0x01, 0x40);
-		break;
-	case SENSOR_OM6802:
-		msleep(10);
-		reg_w1(gspca_dev, 0x02, 0x73);
-		reg_w1(gspca_dev, 0x17, 0x60);
-		reg_w1(gspca_dev, 0x01, 0x22);
-		msleep(100);
-		reg_w1(gspca_dev, 0x01, 0x62);
-		reg_w1(gspca_dev, 0x17, 0x64);
-		reg_w1(gspca_dev, 0x17, 0x64);
-		reg_w1(gspca_dev, 0x01, 0x42);
-		msleep(10);
-		reg_w1(gspca_dev, 0x01, 0x42);
-		i2c_w8(gspca_dev, om6802_init0[0]);
-		i2c_w8(gspca_dev, om6802_init0[1]);
-		msleep(15);
-		reg_w1(gspca_dev, 0x02, 0x71);
-		msleep(150);
-		break;
-	case SENSOR_OV7630:
-		reg_w1(gspca_dev, 0x01, 0x61);
-		reg_w1(gspca_dev, 0x17, 0xe2);
-		reg_w1(gspca_dev, 0x01, 0x60);
-		reg_w1(gspca_dev, 0x01, 0x40);
-		break;
-	case SENSOR_OV7648:
-		reg_w1(gspca_dev, 0x01, 0x63);
-		reg_w1(gspca_dev, 0x17, 0x20);
-		reg_w1(gspca_dev, 0x01, 0x62);
-		reg_w1(gspca_dev, 0x01, 0x42);
-		break;
-	case SENSOR_PO1030:
-	case SENSOR_SOI768:
-		reg_w1(gspca_dev, 0x01, 0x61);
-		reg_w1(gspca_dev, 0x17, 0x20);
-		reg_w1(gspca_dev, 0x01, 0x60);
-		reg_w1(gspca_dev, 0x01, 0x40);
-		break;
-	case SENSOR_PO2030N:
-	case SENSOR_OV7660:
-		reg_w1(gspca_dev, 0x01, 0x63);
-		reg_w1(gspca_dev, 0x17, 0x20);
-		reg_w1(gspca_dev, 0x01, 0x62);
-		reg_w1(gspca_dev, 0x01, 0x42);
-		break;
-	case SENSOR_SP80708:
-		reg_w1(gspca_dev, 0x01, 0x63);
-		reg_w1(gspca_dev, 0x17, 0x20);
-		reg_w1(gspca_dev, 0x01, 0x62);
-		reg_w1(gspca_dev, 0x01, 0x42);
-		msleep(100);
-		reg_w1(gspca_dev, 0x02, 0x62);
-		break;
-	default:
-/*	case SENSOR_HV7131R: */
-/*	case SENSOR_MI0360: */
-/*	case SENSOR_MO4000: */
-		reg_w1(gspca_dev, 0x01, 0x43);
-		reg_w1(gspca_dev, 0x17, 0x61);
-		reg_w1(gspca_dev, 0x01, 0x42);
-		if (sd->sensor == SENSOR_HV7131R)
-			hv7131r_probe(gspca_dev);
-		break;
-	}
-}
-
 /* this function is called at probe time */
 /* this function is called at probe time */
 static int sd_config(struct gspca_dev *gspca_dev,
 static int sd_config(struct gspca_dev *gspca_dev,
 			const struct usb_device_id *id)
 			const struct usb_device_id *id)
@@ -1898,7 +1782,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
 	struct cam *cam;
 	struct cam *cam;
 
 
 	sd->bridge = id->driver_info >> 16;
 	sd->bridge = id->driver_info >> 16;
-	sd->sensor = id->driver_info;
+	sd->sensor = id->driver_info >> 8;
+	sd->flags = id->driver_info;
 
 
 	cam = &gspca_dev->cam;
 	cam = &gspca_dev->cam;
 	if (sd->sensor == SENSOR_ADCM1700) {
 	if (sd->sensor == SENSOR_ADCM1700) {
@@ -1929,7 +1814,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
 	/* setup a selector by bridge */
 	/* setup a selector by bridge */
 	reg_w1(gspca_dev, 0xf1, 0x01);
 	reg_w1(gspca_dev, 0xf1, 0x01);
 	reg_r(gspca_dev, 0x00, 1);
 	reg_r(gspca_dev, 0x00, 1);
-	reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
+	reg_w1(gspca_dev, 0xf1, 0x00);
 	reg_r(gspca_dev, 0x00, 1);		/* get sonix chip id */
 	reg_r(gspca_dev, 0x00, 1);		/* get sonix chip id */
 	regF1 = gspca_dev->usb_buf[0];
 	regF1 = gspca_dev->usb_buf[0];
 	if (gspca_dev->usb_err < 0)
 	if (gspca_dev->usb_err < 0)
@@ -2423,10 +2308,17 @@ static int sd_start(struct gspca_dev *gspca_dev)
 {
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	struct sd *sd = (struct sd *) gspca_dev;
 	int i;
 	int i;
-	u8 reg1, reg17;
+	u8 reg01, reg17;
+	u8 reg0102[2];
 	const u8 *sn9c1xx;
 	const u8 *sn9c1xx;
 	const u8 (*init)[8];
 	const u8 (*init)[8];
+	const u8 *reg9a;
 	int mode;
 	int mode;
+	static const u8 reg9a_def[] =
+		{0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
+	static const u8 reg9a_spec[] =
+		{0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
+	static const u8 regd4[] = {0x60, 0x00, 0x00};
 	static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
 	static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
 	static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
 	static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
 	static const u8 CA_adcm1700[] =
 	static const u8 CA_adcm1700[] =
@@ -2448,7 +2340,85 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
 
 	/* initialize the bridge */
 	/* initialize the bridge */
 	sn9c1xx = sn_tb[sd->sensor];
 	sn9c1xx = sn_tb[sd->sensor];
-	bridge_init(gspca_dev, sn9c1xx);
+
+	/* sensor clock already enabled in sd_init */
+	/* reg_w1(gspca_dev, 0xf1, 0x00); */
+	reg01 = sn9c1xx[1];
+	if (sd->flags & PDN_INV)
+		reg01 ^= S_PDN_INV;		/* power down inverted */
+	reg_w1(gspca_dev, 0x01, reg01);
+
+	/* configure gpio */
+	reg0102[0] = reg01;
+	reg0102[1] = sn9c1xx[2];
+	if (gspca_dev->audio)
+		reg0102[1] |= 0x04;	/* keep the audio connection */
+	reg_w(gspca_dev, 0x01, reg0102, 2);
+	reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
+	reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
+	switch (sd->sensor) {
+	case SENSOR_GC0307:
+	case SENSOR_OV7660:
+	case SENSOR_PO1030:
+	case SENSOR_PO2030N:
+	case SENSOR_SOI768:
+	case SENSOR_SP80708:
+		reg9a = reg9a_spec;
+		break;
+	default:
+		reg9a = reg9a_def;
+		break;
+	}
+	reg_w(gspca_dev, 0x9a, reg9a, 6);
+
+	reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
+
+	reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
+
+	reg17 = sn9c1xx[0x17];
+	switch (sd->sensor) {
+	case SENSOR_GC0307:
+		msleep(50);		/*fixme: is it useful? */
+		break;
+	case SENSOR_OM6802:
+		msleep(10);
+		reg_w1(gspca_dev, 0x02, 0x73);
+		reg17 |= SEN_CLK_EN;
+		reg_w1(gspca_dev, 0x17, reg17);
+		reg_w1(gspca_dev, 0x01, 0x22);
+		msleep(100);
+		reg01 = SCL_SEL_OD | S_PDN_INV;
+		reg17 &= MCK_SIZE_MASK;
+		reg17 |= 0x04;		/* clock / 4 */
+		break;
+	}
+	reg01 |= SYS_SEL_48M;
+	reg_w1(gspca_dev, 0x01, reg01);
+	reg17 |= SEN_CLK_EN;
+	reg_w1(gspca_dev, 0x17, reg17);
+	reg01 &= ~S_PWR_DN;		/* sensor power on */
+	reg_w1(gspca_dev, 0x01, reg01);
+	reg01 &= ~SYS_SEL_48M;
+	reg_w1(gspca_dev, 0x01, reg01);
+
+	switch (sd->sensor) {
+	case SENSOR_HV7131R:
+		hv7131r_probe(gspca_dev);	/*fixme: is it useful? */
+		break;
+	case SENSOR_OM6802:
+		msleep(10);
+		reg_w1(gspca_dev, 0x01, reg01);
+		i2c_w8(gspca_dev, om6802_init0[0]);
+		i2c_w8(gspca_dev, om6802_init0[1]);
+		msleep(15);
+		reg_w1(gspca_dev, 0x02, 0x71);
+		msleep(150);
+		break;
+	case SENSOR_SP80708:
+		msleep(100);
+		reg_w1(gspca_dev, 0x02, 0x62);
+		break;
+	}
 
 
 	/* initialize the sensor */
 	/* initialize the sensor */
 	i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
 	i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
@@ -2476,30 +2446,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
 	}
 	}
 	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
 	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
 	switch (sd->sensor) {
 	switch (sd->sensor) {
-	case SENSOR_GC0307:
-		reg17 = 0xa2;
-		break;
-	case SENSOR_MT9V111:
-	case SENSOR_MI0360B:
-		reg17 = 0xe0;
-		break;
-	case SENSOR_ADCM1700:
-	case SENSOR_OV7630:
-		reg17 = 0xe2;
-		break;
-	case SENSOR_OV7648:
-		reg17 = 0x20;
-		break;
-	case SENSOR_OV7660:
-	case SENSOR_SOI768:
-		reg17 = 0xa0;
-		break;
-	case SENSOR_PO1030:
-	case SENSOR_PO2030N:
-		reg17 = 0xa0;
+	case SENSOR_OM6802:
+/*	case SENSOR_OV7648:		* fixme: sometimes */
 		break;
 		break;
 	default:
 	default:
-		reg17 = 0x60;
+		reg17 |= DEF_EN;
 		break;
 		break;
 	}
 	}
 	reg_w1(gspca_dev, 0x17, reg17);
 	reg_w1(gspca_dev, 0x17, reg17);
@@ -2546,95 +2497,67 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
 
 	init = NULL;
 	init = NULL;
 	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-	if (mode)
-		reg1 = 0x46;	/* 320x240: clk 48Mhz, video trf enable */
-	else
-		reg1 = 0x06;	/* 640x480: clk 24Mhz, video trf enable */
-	reg17 = 0x61;		/* 0x:20: enable sensor clock */
+	reg01 |= SYS_SEL_48M | V_TX_EN;
+	reg17 &= ~MCK_SIZE_MASK;
+	reg17 |= 0x02;			/* clock / 2 */
 	switch (sd->sensor) {
 	switch (sd->sensor) {
 	case SENSOR_ADCM1700:
 	case SENSOR_ADCM1700:
 		init = adcm1700_sensor_param1;
 		init = adcm1700_sensor_param1;
-		reg1 = 0x46;
-		reg17 = 0xe2;
 		break;
 		break;
 	case SENSOR_GC0307:
 	case SENSOR_GC0307:
 		init = gc0307_sensor_param1;
 		init = gc0307_sensor_param1;
-		reg17 = 0xa2;
-		reg1 = 0x44;
+		break;
+	case SENSOR_HV7131R:
+	case SENSOR_MI0360:
+		if (mode)
+			reg01 |= SYS_SEL_48M;	/* 320x240: clk 48Mhz */
+		else
+			reg01 &= ~SYS_SEL_48M;	/* 640x480: clk 24Mhz */
+		reg17 &= ~MCK_SIZE_MASK;
+		reg17 |= 0x01;			/* clock / 1 */
 		break;
 		break;
 	case SENSOR_MI0360B:
 	case SENSOR_MI0360B:
 		init = mi0360b_sensor_param1;
 		init = mi0360b_sensor_param1;
-		reg1 &= ~0x02;		/* don't inverse pin S_PWR_DN */
-		reg17 = 0xe2;
 		break;
 		break;
 	case SENSOR_MO4000:
 	case SENSOR_MO4000:
-		if (mode) {
-/*			reg1 = 0x46;	 * 320 clk 48Mhz 60fp/s */
-			reg1 = 0x06;	/* clk 24Mz */
-		} else {
-			reg17 = 0x22;	/* 640 MCKSIZE */
-/*			reg1 = 0x06;	 * 640 clk 24Mz (done) */
+		if (mode) {			/* if 320x240 */
+			reg01 &= ~SYS_SEL_48M;	/* clk 24Mz */
+			reg17 &= ~MCK_SIZE_MASK;
+			reg17 |= 0x01;		/* clock / 1 */
 		}
 		}
 		break;
 		break;
 	case SENSOR_MT9V111:
 	case SENSOR_MT9V111:
 		init = mt9v111_sensor_param1;
 		init = mt9v111_sensor_param1;
-		if (mode) {
-			reg1 = 0x04;	/* 320 clk 48Mhz */
-		} else {
-/*			reg1 = 0x06;	 * 640 clk 24Mz (done) */
-			reg17 = 0xc2;
-		}
 		break;
 		break;
 	case SENSOR_OM6802:
 	case SENSOR_OM6802:
 		init = om6802_sensor_param1;
 		init = om6802_sensor_param1;
-		reg17 = 0x64;		/* 640 MCKSIZE */
+		if (!mode) {			/* if 640x480 */
+			reg17 &= ~MCK_SIZE_MASK;
+			reg17 |= 0x01;		/* clock / 4 */
+		}
 		break;
 		break;
 	case SENSOR_OV7630:
 	case SENSOR_OV7630:
 		init = ov7630_sensor_param1;
 		init = ov7630_sensor_param1;
-		reg17 = 0xe2;
-		reg1 = 0x44;
 		break;
 		break;
 	case SENSOR_OV7648:
 	case SENSOR_OV7648:
 		init = ov7648_sensor_param1;
 		init = ov7648_sensor_param1;
-		reg17 = 0x21;
-/*		reg1 = 0x42;		 * 42 - 46? */
+		reg17 &= ~MCK_SIZE_MASK;
+		reg17 |= 0x01;			/* clock / 1 */
 		break;
 		break;
 	case SENSOR_OV7660:
 	case SENSOR_OV7660:
 		init = ov7660_sensor_param1;
 		init = ov7660_sensor_param1;
-		if (sd->bridge == BRIDGE_SN9C120) {
-			if (mode) {		/* 320x240 - 160x120 */
-				reg17 = 0xa2;
-				reg1 = 0x44;	/* 48 Mhz, video trf eneble */
-			}
-		} else {
-			reg17 = 0x22;
-			reg1 = 0x06;	/* 24 Mhz, video trf eneble
-					 * inverse power down */
-		}
 		break;
 		break;
 	case SENSOR_PO1030:
 	case SENSOR_PO1030:
 		init = po1030_sensor_param1;
 		init = po1030_sensor_param1;
-		reg17 = 0xa2;
-		reg1 = 0x44;
 		break;
 		break;
 	case SENSOR_PO2030N:
 	case SENSOR_PO2030N:
 		init = po2030n_sensor_param1;
 		init = po2030n_sensor_param1;
-		reg1 = 0x46;
-		reg17 = 0xa2;
 		break;
 		break;
 	case SENSOR_SOI768:
 	case SENSOR_SOI768:
 		init = soi768_sensor_param1;
 		init = soi768_sensor_param1;
-		reg1 = 0x44;
-		reg17 = 0xa2;
 		break;
 		break;
 	case SENSOR_SP80708:
 	case SENSOR_SP80708:
 		init = sp80708_sensor_param1;
 		init = sp80708_sensor_param1;
-		if (mode) {
-/*??			reg1 = 0x04;	 * 320 clk 48Mhz */
-		} else {
-			reg1 = 0x46;	 /* 640 clk 48Mz */
-			reg17 = 0xa2;
-		}
 		break;
 		break;
 	}
 	}
 
 
@@ -2684,7 +2607,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
 	setjpegqual(gspca_dev);
 	setjpegqual(gspca_dev);
 
 
 	reg_w1(gspca_dev, 0x17, reg17);
 	reg_w1(gspca_dev, 0x17, reg17);
-	reg_w1(gspca_dev, 0x01, reg1);
+	reg_w1(gspca_dev, 0x01, reg01);
+	sd->reg01 = reg01;
+	sd->reg17 = reg17;
 
 
 	sethvflip(gspca_dev);
 	sethvflip(gspca_dev);
 	setbrightness(gspca_dev);
 	setbrightness(gspca_dev);
@@ -2706,41 +2631,64 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
 		{ 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
 		{ 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
 	static const u8 stopsoi768[] =
 	static const u8 stopsoi768[] =
 		{ 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
 		{ 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
-	u8 data;
-	const u8 *sn9c1xx;
+	u8 reg01;
+	u8 reg17;
 
 
-	data = 0x0b;
+	reg01 = sd->reg01;
+	reg17 = sd->reg17 & ~SEN_CLK_EN;
 	switch (sd->sensor) {
 	switch (sd->sensor) {
+	case SENSOR_ADCM1700:
 	case SENSOR_GC0307:
 	case SENSOR_GC0307:
-		data = 0x29;
+	case SENSOR_PO2030N:
+	case SENSOR_SP80708:
+		reg01 |= LED;
+		reg_w1(gspca_dev, 0x01, reg01);
+		reg01 &= ~(LED | V_TX_EN);
+		reg_w1(gspca_dev, 0x01, reg01);
+/*		reg_w1(gspca_dev, 0x02, 0x??);	 * LED off ? */
 		break;
 		break;
 	case SENSOR_HV7131R:
 	case SENSOR_HV7131R:
+		reg01 &= ~V_TX_EN;
+		reg_w1(gspca_dev, 0x01, reg01);
 		i2c_w8(gspca_dev, stophv7131);
 		i2c_w8(gspca_dev, stophv7131);
-		data = 0x2b;
 		break;
 		break;
 	case SENSOR_MI0360:
 	case SENSOR_MI0360:
 	case SENSOR_MI0360B:
 	case SENSOR_MI0360B:
+		reg01 &= ~V_TX_EN;
+		reg_w1(gspca_dev, 0x01, reg01);
+/*		reg_w1(gspca_dev, 0x02, 0x40);	  * LED off ? */
 		i2c_w8(gspca_dev, stopmi0360);
 		i2c_w8(gspca_dev, stopmi0360);
-		data = 0x29;
 		break;
 		break;
-	case SENSOR_OV7648:
-		i2c_w8(gspca_dev, stopov7648);
-		/* fall thru */
 	case SENSOR_MT9V111:
 	case SENSOR_MT9V111:
-	case SENSOR_OV7630:
+	case SENSOR_OM6802:
 	case SENSOR_PO1030:
 	case SENSOR_PO1030:
-		data = 0x29;
+		reg01 &= ~V_TX_EN;
+		reg_w1(gspca_dev, 0x01, reg01);
+		break;
+	case SENSOR_OV7630:
+	case SENSOR_OV7648:
+		reg01 &= ~V_TX_EN;
+		reg_w1(gspca_dev, 0x01, reg01);
+		i2c_w8(gspca_dev, stopov7648);
+		break;
+	case SENSOR_OV7660:
+		reg01 &= ~V_TX_EN;
+		reg_w1(gspca_dev, 0x01, reg01);
 		break;
 		break;
 	case SENSOR_SOI768:
 	case SENSOR_SOI768:
 		i2c_w8(gspca_dev, stopsoi768);
 		i2c_w8(gspca_dev, stopsoi768);
-		data = 0x29;
 		break;
 		break;
 	}
 	}
-	sn9c1xx = sn_tb[sd->sensor];
-	reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
-	reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
-	reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
-	reg_w1(gspca_dev, 0x01, data);
+
+	reg01 |= SCL_SEL_OD;
+	reg_w1(gspca_dev, 0x01, reg01);
+	reg01 |= S_PWR_DN;		/* sensor power down */
+	reg_w1(gspca_dev, 0x01, reg01);
+	reg_w1(gspca_dev, 0x17, reg17);
+	reg01 &= ~SYS_SEL_48M;		/* clock 24MHz */
+	reg_w1(gspca_dev, 0x01, reg01);
+	reg01 |= LED;
+	reg_w1(gspca_dev, 0x01, reg01);
 	/* Don't disable sensor clock as that disables the button on the cam */
 	/* Don't disable sensor clock as that disables the button on the cam */
 	/* reg_w1(gspca_dev, 0xf1, 0x01); */
 	/* reg_w1(gspca_dev, 0xf1, 0x01); */
 }
 }
@@ -2954,14 +2902,18 @@ static const struct sd_desc sd_desc = {
 /* -- module initialisation -- */
 /* -- module initialisation -- */
 #define BS(bridge, sensor) \
 #define BS(bridge, sensor) \
 	.driver_info = (BRIDGE_ ## bridge << 16) \
 	.driver_info = (BRIDGE_ ## bridge << 16) \
-			| SENSOR_ ## sensor
+			| (SENSOR_ ## sensor << 8)
+#define BSF(bridge, sensor, flags) \
+	.driver_info = (BRIDGE_ ## bridge << 16) \
+			| (SENSOR_ ## sensor << 8) \
+			| (flags)
 static const __devinitdata struct usb_device_id device_table[] = {
 static const __devinitdata struct usb_device_id device_table[] = {
 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
 	{USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},
 	{USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},
 	{USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
 	{USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
 #endif
 #endif
-	{USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)},
-	{USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)},
+	{USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, PDN_INV)},
+	{USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)},
 	{USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
 	{USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
 	{USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
 	{USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
 	{USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
 	{USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},

+ 0 - 2
drivers/media/video/mx2_camera.c

@@ -807,8 +807,6 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd,
 
 
 	if (common_flags & SOCAM_PCLK_SAMPLE_RISING)
 	if (common_flags & SOCAM_PCLK_SAMPLE_RISING)
 		csicr1 |= CSICR1_REDGE;
 		csicr1 |= CSICR1_REDGE;
-	if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
-		csicr1 |= CSICR1_INV_PCLK;
 	if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
 	if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
 		csicr1 |= CSICR1_SOF_POL;
 		csicr1 |= CSICR1_SOF_POL;
 	if (common_flags & SOCAM_HSYNC_ACTIVE_HIGH)
 	if (common_flags & SOCAM_HSYNC_ACTIVE_HIGH)

+ 48 - 3
drivers/media/video/s5p-fimc/fimc-capture.c

@@ -522,6 +522,7 @@ static int fimc_cap_streamon(struct file *file, void *priv,
 	INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
 	INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
 	fimc->vid_cap.active_buf_cnt = 0;
 	fimc->vid_cap.active_buf_cnt = 0;
 	fimc->vid_cap.frame_count = 0;
 	fimc->vid_cap.frame_count = 0;
+	fimc->vid_cap.buf_index = fimc_hw_get_frame_index(fimc);
 
 
 	set_bit(ST_CAPT_PEND, &fimc->state);
 	set_bit(ST_CAPT_PEND, &fimc->state);
 	ret = videobuf_streamon(&fimc->vid_cap.vbq);
 	ret = videobuf_streamon(&fimc->vid_cap.vbq);
@@ -652,6 +653,50 @@ static int fimc_cap_s_ctrl(struct file *file, void *priv,
 	return ret;
 	return ret;
 }
 }
 
 
+static int fimc_cap_cropcap(struct file *file, void *fh,
+			    struct v4l2_cropcap *cr)
+{
+	struct fimc_frame *f;
+	struct fimc_ctx *ctx = fh;
+	struct fimc_dev *fimc = ctx->fimc_dev;
+
+	if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&fimc->lock))
+		return -ERESTARTSYS;
+
+	f = &ctx->s_frame;
+	cr->bounds.left		= 0;
+	cr->bounds.top		= 0;
+	cr->bounds.width	= f->o_width;
+	cr->bounds.height	= f->o_height;
+	cr->defrect		= cr->bounds;
+
+	mutex_unlock(&fimc->lock);
+	return 0;
+}
+
+static int fimc_cap_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
+{
+	struct fimc_frame *f;
+	struct fimc_ctx *ctx = file->private_data;
+	struct fimc_dev *fimc = ctx->fimc_dev;
+
+
+	if (mutex_lock_interruptible(&fimc->lock))
+		return -ERESTARTSYS;
+
+	f = &ctx->s_frame;
+	cr->c.left	= f->offs_h;
+	cr->c.top	= f->offs_v;
+	cr->c.width	= f->width;
+	cr->c.height	= f->height;
+
+	mutex_unlock(&fimc->lock);
+	return 0;
+}
+
 static int fimc_cap_s_crop(struct file *file, void *fh,
 static int fimc_cap_s_crop(struct file *file, void *fh,
 			       struct v4l2_crop *cr)
 			       struct v4l2_crop *cr)
 {
 {
@@ -716,9 +761,9 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
 	.vidioc_g_ctrl			= fimc_vidioc_g_ctrl,
 	.vidioc_g_ctrl			= fimc_vidioc_g_ctrl,
 	.vidioc_s_ctrl			= fimc_cap_s_ctrl,
 	.vidioc_s_ctrl			= fimc_cap_s_ctrl,
 
 
-	.vidioc_g_crop			= fimc_vidioc_g_crop,
+	.vidioc_g_crop			= fimc_cap_g_crop,
 	.vidioc_s_crop			= fimc_cap_s_crop,
 	.vidioc_s_crop			= fimc_cap_s_crop,
-	.vidioc_cropcap			= fimc_vidioc_cropcap,
+	.vidioc_cropcap			= fimc_cap_cropcap,
 
 
 	.vidioc_enum_input		= fimc_cap_enum_input,
 	.vidioc_enum_input		= fimc_cap_enum_input,
 	.vidioc_s_input			= fimc_cap_s_input,
 	.vidioc_s_input			= fimc_cap_s_input,
@@ -785,7 +830,7 @@ int fimc_register_capture_device(struct fimc_dev *fimc)
 	videobuf_queue_dma_contig_init(&vid_cap->vbq, &fimc_qops,
 	videobuf_queue_dma_contig_init(&vid_cap->vbq, &fimc_qops,
 		vid_cap->v4l2_dev.dev, &fimc->irqlock,
 		vid_cap->v4l2_dev.dev, &fimc->irqlock,
 		V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
 		V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
-		sizeof(struct fimc_vid_buffer), (void *)ctx);
+		sizeof(struct fimc_vid_buffer), (void *)ctx, NULL);
 
 
 	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
 	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
 	if (ret) {
 	if (ret) {

+ 33 - 21
drivers/media/video/s5p-fimc/fimc-core.c

@@ -50,8 +50,8 @@ static struct fimc_fmt fimc_formats[] = {
 		.planes_cnt = 1,
 		.planes_cnt = 1,
 		.flags = FMT_FLAGS_M2M,
 		.flags = FMT_FLAGS_M2M,
 	}, {
 	}, {
-		.name = "XRGB-8-8-8-8, 24 bpp",
-		.fourcc	= V4L2_PIX_FMT_RGB24,
+		.name = "XRGB-8-8-8-8, 32 bpp",
+		.fourcc	= V4L2_PIX_FMT_RGB32,
 		.depth = 32,
 		.depth = 32,
 		.color	= S5P_FIMC_RGB888,
 		.color	= S5P_FIMC_RGB888,
 		.buff_cnt = 1,
 		.buff_cnt = 1,
@@ -983,6 +983,7 @@ int fimc_vidioc_queryctrl(struct file *file, void *priv,
 {
 {
 	struct fimc_ctx *ctx = priv;
 	struct fimc_ctx *ctx = priv;
 	struct v4l2_queryctrl *c;
 	struct v4l2_queryctrl *c;
+	int ret = -EINVAL;
 
 
 	c = get_ctrl(qc->id);
 	c = get_ctrl(qc->id);
 	if (c) {
 	if (c) {
@@ -990,10 +991,14 @@ int fimc_vidioc_queryctrl(struct file *file, void *priv,
 		return 0;
 		return 0;
 	}
 	}
 
 
-	if (ctx->state & FIMC_CTX_CAP)
-		return v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
+	if (ctx->state & FIMC_CTX_CAP) {
+		if (mutex_lock_interruptible(&ctx->fimc_dev->lock))
+			return -ERESTARTSYS;
+		ret = v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
 					core, queryctrl, qc);
 					core, queryctrl, qc);
-	return -EINVAL;
+		mutex_unlock(&ctx->fimc_dev->lock);
+	}
+	return ret;
 }
 }
 
 
 int fimc_vidioc_g_ctrl(struct file *file, void *priv,
 int fimc_vidioc_g_ctrl(struct file *file, void *priv,
@@ -1115,7 +1120,7 @@ static int fimc_m2m_s_ctrl(struct file *file, void *priv,
 	return 0;
 	return 0;
 }
 }
 
 
-int fimc_vidioc_cropcap(struct file *file, void *fh,
+static int fimc_m2m_cropcap(struct file *file, void *fh,
 			struct v4l2_cropcap *cr)
 			struct v4l2_cropcap *cr)
 {
 {
 	struct fimc_frame *frame;
 	struct fimc_frame *frame;
@@ -1139,7 +1144,7 @@ int fimc_vidioc_cropcap(struct file *file, void *fh,
 	return 0;
 	return 0;
 }
 }
 
 
-int fimc_vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
+static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
 {
 {
 	struct fimc_frame *frame;
 	struct fimc_frame *frame;
 	struct fimc_ctx *ctx = file->private_data;
 	struct fimc_ctx *ctx = file->private_data;
@@ -1167,22 +1172,22 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
 	struct fimc_frame *f;
 	struct fimc_frame *f;
 	u32 min_size, halign;
 	u32 min_size, halign;
 
 
-	f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ?
-		&ctx->s_frame : &ctx->d_frame;
-
 	if (cr->c.top < 0 || cr->c.left < 0) {
 	if (cr->c.top < 0 || cr->c.left < 0) {
 		v4l2_err(&fimc->m2m.v4l2_dev,
 		v4l2_err(&fimc->m2m.v4l2_dev,
 			"doesn't support negative values for top & left\n");
 			"doesn't support negative values for top & left\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	f = ctx_get_frame(ctx, cr->type);
-	if (IS_ERR(f))
-		return PTR_ERR(f);
+	if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		f = (ctx->state & FIMC_CTX_CAP) ? &ctx->s_frame : &ctx->d_frame;
+	else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+		 ctx->state & FIMC_CTX_M2M)
+		f = &ctx->s_frame;
+	else
+		return -EINVAL;
 
 
-	min_size = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		? fimc->variant->min_inp_pixsize
-		: fimc->variant->min_out_pixsize;
+	min_size = (f == &ctx->s_frame) ?
+		fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize;
 
 
 	if (ctx->state & FIMC_CTX_M2M) {
 	if (ctx->state & FIMC_CTX_M2M) {
 		if (fimc->id == 1 && fimc->variant->pix_hoff)
 		if (fimc->id == 1 && fimc->variant->pix_hoff)
@@ -1233,6 +1238,9 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
 	f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ?
 	f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ?
 		&ctx->s_frame : &ctx->d_frame;
 		&ctx->s_frame : &ctx->d_frame;
 
 
+	if (mutex_lock_interruptible(&fimc->lock))
+		return -ERESTARTSYS;
+
 	spin_lock_irqsave(&ctx->slock, flags);
 	spin_lock_irqsave(&ctx->slock, flags);
 	if (~ctx->state & (FIMC_SRC_FMT | FIMC_DST_FMT)) {
 	if (~ctx->state & (FIMC_SRC_FMT | FIMC_DST_FMT)) {
 		/* Check to see if scaling ratio is within supported range */
 		/* Check to see if scaling ratio is within supported range */
@@ -1241,9 +1249,9 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
 		else
 		else
 			ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame);
 			ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame);
 		if (ret) {
 		if (ret) {
-			spin_unlock_irqrestore(&ctx->slock, flags);
 			v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range");
 			v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range");
-			return -EINVAL;
+			ret = -EINVAL;
+			goto scr_unlock;
 		}
 		}
 	}
 	}
 	ctx->state |= FIMC_PARAMS;
 	ctx->state |= FIMC_PARAMS;
@@ -1253,7 +1261,9 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
 	f->width  = cr->c.width;
 	f->width  = cr->c.width;
 	f->height = cr->c.height;
 	f->height = cr->c.height;
 
 
+scr_unlock:
 	spin_unlock_irqrestore(&ctx->slock, flags);
 	spin_unlock_irqrestore(&ctx->slock, flags);
+	mutex_unlock(&fimc->lock);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1285,9 +1295,9 @@ static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
 	.vidioc_g_ctrl			= fimc_vidioc_g_ctrl,
 	.vidioc_g_ctrl			= fimc_vidioc_g_ctrl,
 	.vidioc_s_ctrl			= fimc_m2m_s_ctrl,
 	.vidioc_s_ctrl			= fimc_m2m_s_ctrl,
 
 
-	.vidioc_g_crop			= fimc_vidioc_g_crop,
+	.vidioc_g_crop			= fimc_m2m_g_crop,
 	.vidioc_s_crop			= fimc_m2m_s_crop,
 	.vidioc_s_crop			= fimc_m2m_s_crop,
-	.vidioc_cropcap			= fimc_vidioc_cropcap
+	.vidioc_cropcap			= fimc_m2m_cropcap
 
 
 };
 };
 
 
@@ -1396,7 +1406,7 @@ static const struct v4l2_file_operations fimc_m2m_fops = {
 	.open		= fimc_m2m_open,
 	.open		= fimc_m2m_open,
 	.release	= fimc_m2m_release,
 	.release	= fimc_m2m_release,
 	.poll		= fimc_m2m_poll,
 	.poll		= fimc_m2m_poll,
-	.ioctl		= video_ioctl2,
+	.unlocked_ioctl	= video_ioctl2,
 	.mmap		= fimc_m2m_mmap,
 	.mmap		= fimc_m2m_mmap,
 };
 };
 
 
@@ -1736,6 +1746,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
 	.pix_hoff	 = 1,
 	.pix_hoff	 = 1,
 	.has_inp_rot	 = 1,
 	.has_inp_rot	 = 1,
 	.has_out_rot	 = 1,
 	.has_out_rot	 = 1,
+	.has_cistatus2	 = 1,
 	.min_inp_pixsize = 16,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 16,
 	.min_out_pixsize = 16,
 	.hor_offs_align	 = 1,
 	.hor_offs_align	 = 1,
@@ -1745,6 +1756,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
 
 
 static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
 static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
 	.pix_hoff	 = 1,
 	.pix_hoff	 = 1,
+	.has_cistatus2	 = 1,
 	.min_inp_pixsize = 16,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 16,
 	.min_out_pixsize = 16,
 	.hor_offs_align	 = 1,
 	.hor_offs_align	 = 1,

+ 16 - 8
drivers/media/video/s5p-fimc/fimc-core.h

@@ -13,13 +13,15 @@
 
 
 /*#define DEBUG*/
 /*#define DEBUG*/
 
 
+#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/types.h>
+#include <linux/videodev2.h>
 #include <media/videobuf-core.h>
 #include <media/videobuf-core.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/v4l2-mediabus.h>
 #include <media/v4l2-mediabus.h>
 #include <media/s3c_fimc.h>
 #include <media/s3c_fimc.h>
-#include <linux/videodev2.h>
+
 #include "regs-fimc.h"
 #include "regs-fimc.h"
 
 
 #define err(fmt, args...) \
 #define err(fmt, args...) \
@@ -369,6 +371,7 @@ struct fimc_pix_limit {
  * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes
  * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes
  * @has_inp_rot: set if has input rotator
  * @has_inp_rot: set if has input rotator
  * @has_out_rot: set if has output rotator
  * @has_out_rot: set if has output rotator
+ * @has_cistatus2: 1 if CISTATUS2 register is present in this IP revision
  * @pix_limit: pixel size constraints for the scaler
  * @pix_limit: pixel size constraints for the scaler
  * @min_inp_pixsize: minimum input pixel size
  * @min_inp_pixsize: minimum input pixel size
  * @min_out_pixsize: minimum output pixel size
  * @min_out_pixsize: minimum output pixel size
@@ -379,6 +382,7 @@ struct samsung_fimc_variant {
 	unsigned int	pix_hoff:1;
 	unsigned int	pix_hoff:1;
 	unsigned int	has_inp_rot:1;
 	unsigned int	has_inp_rot:1;
 	unsigned int	has_out_rot:1;
 	unsigned int	has_out_rot:1;
+	unsigned int	has_cistatus2:1;
 	struct fimc_pix_limit *pix_limit;
 	struct fimc_pix_limit *pix_limit;
 	u16		min_inp_pixsize;
 	u16		min_inp_pixsize;
 	u16		min_out_pixsize;
 	u16		min_out_pixsize;
@@ -554,11 +558,19 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,
 	return frame;
 	return frame;
 }
 }
 
 
+/* Return an index to the buffer actually being written. */
 static inline u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
 static inline u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
 {
 {
-	u32 reg = readl(dev->regs + S5P_CISTATUS);
-	return (reg & S5P_CISTATUS_FRAMECNT_MASK) >>
-		S5P_CISTATUS_FRAMECNT_SHIFT;
+	u32 reg;
+
+	if (dev->variant->has_cistatus2) {
+		reg = readl(dev->regs + S5P_CISTATUS2) & 0x3F;
+		return reg > 0 ? --reg : reg;
+	} else {
+		reg = readl(dev->regs + S5P_CISTATUS);
+		return (reg & S5P_CISTATUS_FRAMECNT_MASK) >>
+			S5P_CISTATUS_FRAMECNT_SHIFT;
+	}
 }
 }
 
 
 /* -----------------------------------------------------*/
 /* -----------------------------------------------------*/
@@ -594,10 +606,6 @@ int fimc_vidioc_g_fmt(struct file *file, void *priv,
 		      struct v4l2_format *f);
 		      struct v4l2_format *f);
 int fimc_vidioc_try_fmt(struct file *file, void *priv,
 int fimc_vidioc_try_fmt(struct file *file, void *priv,
 			struct v4l2_format *f);
 			struct v4l2_format *f);
-int fimc_vidioc_g_crop(struct file *file, void *fh,
-		       struct v4l2_crop *cr);
-int fimc_vidioc_cropcap(struct file *file, void *fh,
-			struct v4l2_cropcap *cr);
 int fimc_vidioc_queryctrl(struct file *file, void *priv,
 int fimc_vidioc_queryctrl(struct file *file, void *priv,
 			  struct v4l2_queryctrl *qc);
 			  struct v4l2_queryctrl *qc);
 int fimc_vidioc_g_ctrl(struct file *file, void *priv,
 int fimc_vidioc_g_ctrl(struct file *file, void *priv,

+ 3 - 0
drivers/media/video/s5p-fimc/regs-fimc.h

@@ -165,6 +165,9 @@
 #define S5P_CISTATUS_VVALID_A		(1 << 15)
 #define S5P_CISTATUS_VVALID_A		(1 << 15)
 #define S5P_CISTATUS_VVALID_B		(1 << 14)
 #define S5P_CISTATUS_VVALID_B		(1 << 14)
 
 
+/* Indexes to the last and the currently processed buffer. */
+#define S5P_CISTATUS2			0x68
+
 /* Image capture control */
 /* Image capture control */
 #define S5P_CIIMGCPT			0xc0
 #define S5P_CIIMGCPT			0xc0
 #define S5P_CIIMGCPT_IMGCPTEN		(1 << 31)
 #define S5P_CIIMGCPT_IMGCPTEN		(1 << 31)

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff