Selaa lähdekoodia

Merge commit 'v2.6.29-rc4' into tracing/core

Ingo Molnar 16 vuotta sitten
vanhempi
commit
4ad476e11f
100 muutettua tiedostoa jossa 2183 lisäystä ja 1527 poistoa
  1. 3 1
      .mailmap
  2. 0 16
      Documentation/cpu-freq/user-guide.txt
  3. 12 1
      Documentation/filesystems/sysfs-pci.txt
  4. 10 1
      MAINTAINERS
  5. 1 1
      Makefile
  6. 2 2
      arch/alpha/include/asm/bug.h
  7. 1 1
      arch/ia64/sn/kernel/io_acpi_init.c
  8. 1 1
      arch/ia64/sn/kernel/io_init.c
  9. 59 4
      arch/sh/boards/board-ap325rxa.c
  10. 20 7
      arch/sh/configs/ap325rxa_defconfig
  11. 33 9
      arch/sh/configs/migor_defconfig
  12. 9 12
      arch/sh/include/asm/mutex-llsc.h
  13. 3 19
      arch/sh/include/asm/syscall_32.h
  14. 3 19
      arch/sh/include/asm/syscall_64.h
  15. 1 1
      arch/sh/kernel/cpu/sh4/fpu.c
  16. 4 4
      arch/sh/kernel/setup.c
  17. 1 3
      arch/sh/kernel/signal_32.c
  18. 1 3
      arch/sh/kernel/signal_64.c
  19. 50 19
      arch/sh/lib/checksum.S
  20. 5 3
      arch/x86/ia32/ia32entry.S
  21. 2 2
      arch/x86/kernel/acpi/sleep.c
  22. 1 1
      arch/x86/kernel/apic.c
  23. 0 11
      arch/x86/kernel/cpu/cpufreq/Kconfig
  24. 15 0
      arch/x86/kernel/cpu/intel_cacheinfo.c
  25. 1 0
      arch/x86/kernel/entry_64.S
  26. 3 2
      arch/x86/kernel/io_apic.c
  27. 0 12
      arch/x86/kernel/irqinit_32.c
  28. 12 0
      arch/x86/mach-default/setup.c
  29. 11 1
      arch/x86/mach-voyager/setup.c
  30. 12 13
      arch/x86/mach-voyager/voyager_smp.c
  31. 6 2
      arch/x86/mm/fault.c
  32. 3 1
      arch/x86/xen/multicalls.h
  33. 2 1
      drivers/acpi/Kconfig
  34. 3 4
      drivers/acpi/acpica/tbutils.c
  35. 9 12
      drivers/acpi/acpica/uteval.c
  36. 3 2
      drivers/acpi/container.c
  37. 9 5
      drivers/acpi/dock.c
  38. 1 1
      drivers/acpi/ec.c
  39. 4 4
      drivers/acpi/glue.c
  40. 52 2
      drivers/acpi/osl.c
  41. 1 1
      drivers/acpi/pci_link.c
  42. 10 657
      drivers/acpi/processor_idle.c
  43. 0 105
      drivers/acpi/processor_perflib.c
  44. 27 26
      drivers/acpi/sleep.c
  45. 6 1
      drivers/acpi/tables.c
  46. 11 5
      drivers/acpi/video.c
  47. 5 3
      drivers/char/sx.c
  48. 8 1
      drivers/firewire/fw-card.c
  49. 7 2
      drivers/hwmon/hp_accel.c
  50. 4 4
      drivers/ieee1394/dv1394.c
  51. 3 3
      drivers/md/linear.c
  52. 14 10
      drivers/md/md.c
  53. 2 1
      drivers/md/raid1.c
  54. 1 0
      drivers/misc/Kconfig
  55. 1 1
      drivers/misc/atmel-ssc.c
  56. 3 3
      drivers/misc/hpilo.c
  57. 2 0
      drivers/misc/hpilo.h
  58. 3 2
      drivers/misc/sgi-xp/xpc.h
  59. 5 6
      drivers/misc/sgi-xp/xpc_uv.c
  60. 1 2
      drivers/net/cxgb3/sge.c
  61. 3 0
      drivers/net/gianfar.c
  62. 1 1
      drivers/net/gianfar.h
  63. 2 0
      drivers/net/wireless/iwlwifi/iwl-agn.c
  64. 3 0
      drivers/net/wireless/iwlwifi/iwl-sta.c
  65. 2 0
      drivers/net/wireless/iwlwifi/iwl3945-base.c
  66. 105 59
      drivers/pci/pci-driver.c
  67. 2 2
      drivers/pci/pci-sysfs.c
  68. 2 2
      drivers/pci/pci.c
  69. 2 2
      drivers/pci/pcie/aspm.c
  70. 1 15
      drivers/pci/pcie/portdrv_pci.c
  71. 5 3
      drivers/pci/rom.c
  72. 1 0
      drivers/platform/x86/Kconfig
  73. 165 11
      drivers/platform/x86/asus-laptop.c
  74. 15 1
      drivers/platform/x86/asus_acpi.c
  75. 144 20
      drivers/platform/x86/eeepc-laptop.c
  76. 4 2
      drivers/platform/x86/hp-wmi.c
  77. 1 1
      drivers/platform/x86/panasonic-laptop.c
  78. 6 0
      drivers/rtc/Kconfig
  79. 1 0
      drivers/rtc/Makefile
  80. 175 0
      drivers/rtc/rtc-dm355evm.c
  81. 0 1
      drivers/rtc/rtc-ds1390.c
  82. 19 14
      drivers/video/aty/aty128fb.c
  83. 26 16
      drivers/video/aty/atyfb_base.c
  84. 5 5
      drivers/video/aty/radeon_base.c
  85. 29 74
      drivers/video/aty/radeon_pm.c
  86. 0 2
      drivers/video/aty/radeonfb.h
  87. 1 1
      drivers/video/backlight/Makefile
  88. 0 0
      drivers/video/backlight/da903x_bl.c
  89. 14 6
      drivers/video/fbcmap.c
  90. 69 66
      drivers/video/fbmem.c
  91. 12 2
      fs/binfmt_elf.c
  92. 13 0
      fs/btrfs/Kconfig
  93. 53 8
      fs/btrfs/async-thread.c
  94. 0 1
      fs/btrfs/compression.c
  95. 244 32
      fs/btrfs/ctree.c
  96. 13 15
      fs/btrfs/ctree.h
  97. 87 33
      fs/btrfs/disk-io.c
  98. 2 0
      fs/btrfs/disk-io.h
  99. 365 73
      fs/btrfs/extent-tree.c
  100. 109 23
      fs/btrfs/extent_io.c

+ 3 - 1
.mailmap

@@ -92,6 +92,7 @@ Rudolf Marek <R.Marek@sh.cvut.cz>
 Rui Saraiva <rmps@joel.ist.utl.pt>
 Rui Saraiva <rmps@joel.ist.utl.pt>
 Sachin P Sant <ssant@in.ibm.com>
 Sachin P Sant <ssant@in.ibm.com>
 Sam Ravnborg <sam@mars.ravnborg.org>
 Sam Ravnborg <sam@mars.ravnborg.org>
+Sascha Hauer <s.hauer@pengutronix.de>
 S.Çağlar Onur <caglar@pardus.org.tr>
 S.Çağlar Onur <caglar@pardus.org.tr>
 Simon Kelley <simon@thekelleys.org.uk>
 Simon Kelley <simon@thekelleys.org.uk>
 Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
 Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
@@ -100,6 +101,7 @@ Tejun Heo <htejun@gmail.com>
 Thomas Graf <tgraf@suug.ch>
 Thomas Graf <tgraf@suug.ch>
 Tony Luck <tony.luck@intel.com>
 Tony Luck <tony.luck@intel.com>
 Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
 Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
-Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
 Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
 Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
+Uwe Kleine-König <ukl@pengutronix.de>
+Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
 Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
 Valdis Kletnieks <Valdis.Kletnieks@vt.edu>

+ 0 - 16
Documentation/cpu-freq/user-guide.txt

@@ -195,19 +195,3 @@ scaling_setspeed.		By "echoing" a new frequency into this
 				you can change the speed of the CPU,
 				you can change the speed of the CPU,
 				but only within the limits of
 				but only within the limits of
 				scaling_min_freq and scaling_max_freq.
 				scaling_min_freq and scaling_max_freq.
-				
-
-3.2 Deprecated Interfaces
--------------------------
-
-Depending on your kernel configuration, you might find the following 
-cpufreq-related files:
-/proc/cpufreq
-/proc/sys/cpu/*/speed
-/proc/sys/cpu/*/speed-min
-/proc/sys/cpu/*/speed-max
-
-These are files for deprecated interfaces to cpufreq, which offer far
-less functionality. Because of this, these interfaces aren't described
-here.
-

+ 12 - 1
Documentation/filesystems/sysfs-pci.txt

@@ -9,6 +9,7 @@ that support it.  For example, a given bus might look like this:
      |   |-- class
      |   |-- class
      |   |-- config
      |   |-- config
      |   |-- device
      |   |-- device
+     |   |-- enable
      |   |-- irq
      |   |-- irq
      |   |-- local_cpus
      |   |-- local_cpus
      |   |-- resource
      |   |-- resource
@@ -32,6 +33,7 @@ files, each with their own function.
        class		   PCI class (ascii, ro)
        class		   PCI class (ascii, ro)
        config		   PCI config space (binary, rw)
        config		   PCI config space (binary, rw)
        device		   PCI device (ascii, ro)
        device		   PCI device (ascii, ro)
+       enable	           Whether the device is enabled (ascii, rw)
        irq		   IRQ number (ascii, ro)
        irq		   IRQ number (ascii, ro)
        local_cpus	   nearby CPU mask (cpumask, ro)
        local_cpus	   nearby CPU mask (cpumask, ro)
        resource		   PCI resource host addresses (ascii, ro)
        resource		   PCI resource host addresses (ascii, ro)
@@ -57,10 +59,19 @@ used to do actual device programming from userspace.  Note that some platforms
 don't support mmapping of certain resources, so be sure to check the return
 don't support mmapping of certain resources, so be sure to check the return
 value from any attempted mmap.
 value from any attempted mmap.
 
 
+The 'enable' file provides a counter that indicates how many times the device 
+has been enabled.  If the 'enable' file currently returns '4', and a '1' is
+echoed into it, it will then return '5'.  Echoing a '0' into it will decrease
+the count.  Even when it returns to 0, though, some of the initialisation
+may not be reversed.  
+
 The 'rom' file is special in that it provides read-only access to the device's
 The 'rom' file is special in that it provides read-only access to the device's
 ROM file, if available.  It's disabled by default, however, so applications
 ROM file, if available.  It's disabled by default, however, so applications
 should write the string "1" to the file to enable it before attempting a read
 should write the string "1" to the file to enable it before attempting a read
-call, and disable it following the access by writing "0" to the file.
+call, and disable it following the access by writing "0" to the file.  Note
+that the device must be enabled for a rom read to return data succesfully.
+In the event a driver is not bound to the device, it can be enabled using the
+'enable' file, documented above.
 
 
 Accessing legacy resources through sysfs
 Accessing legacy resources through sysfs
 ----------------------------------------
 ----------------------------------------

+ 10 - 1
MAINTAINERS

@@ -1021,6 +1021,14 @@ M:	mb@bu3sch.de
 W:	http://bu3sch.de/btgpio.php
 W:	http://bu3sch.de/btgpio.php
 S:	Maintained
 S:	Maintained
 
 
+BTRFS FILE SYSTEM
+P:	Chris Mason
+M:	chris.mason@oracle.com
+L:	linux-btrfs@vger.kernel.org
+W:	http://btrfs.wiki.kernel.org/
+T:	git kernel.org:/pub/scm/linux/kernel/git/mason/btrfs-unstable.git
+S:	Maintained
+
 BTTV VIDEO4LINUX DRIVER
 BTTV VIDEO4LINUX DRIVER
 P:	Mauro Carvalho Chehab
 P:	Mauro Carvalho Chehab
 M:	mchehab@infradead.org
 M:	mchehab@infradead.org
@@ -2212,7 +2220,7 @@ P:	Sean Hefty
 M:	sean.hefty@intel.com
 M:	sean.hefty@intel.com
 P:	Hal Rosenstock
 P:	Hal Rosenstock
 M:	hal.rosenstock@gmail.com
 M:	hal.rosenstock@gmail.com
-L:	general@lists.openfabrics.org
+L:	general@lists.openfabrics.org (moderated for non-subscribers)
 W:	http://www.openib.org/
 W:	http://www.openib.org/
 T:	git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
 T:	git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
 S:	Supported
 S:	Supported
@@ -4847,6 +4855,7 @@ P:	Ingo Molnar
 M:	mingo@redhat.com
 M:	mingo@redhat.com
 P:	H. Peter Anvin
 P:	H. Peter Anvin
 M:	hpa@zytor.com
 M:	hpa@zytor.com
+M:	x86@kernel.org
 L:	linux-kernel@vger.kernel.org
 L:	linux-kernel@vger.kernel.org
 T:	git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
 T:	git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
 S:	Maintained
 S:	Maintained

+ 1 - 1
Makefile

@@ -1,7 +1,7 @@
 VERSION = 2
 VERSION = 2
 PATCHLEVEL = 6
 PATCHLEVEL = 6
 SUBLEVEL = 29
 SUBLEVEL = 29
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc4
 NAME = Erotic Pickled Herring
 NAME = Erotic Pickled Herring
 
 
 # *DOCUMENTATION*
 # *DOCUMENTATION*

+ 2 - 2
arch/alpha/include/asm/bug.h

@@ -8,12 +8,12 @@
 
 
 /* ??? Would be nice to use .gprel32 here, but we can't be sure that the
 /* ??? Would be nice to use .gprel32 here, but we can't be sure that the
    function loaded the GP, so this could fail in modules.  */
    function loaded the GP, so this could fail in modules.  */
-#define BUG()	{							\
+#define BUG()	do {							\
 	__asm__ __volatile__(						\
 	__asm__ __volatile__(						\
 		"call_pal %0  # bugchk\n\t"				\
 		"call_pal %0  # bugchk\n\t"				\
 		".long %1\n\t.8byte %2"					\
 		".long %1\n\t.8byte %2"					\
 		: : "i"(PAL_bugchk), "i"(__LINE__), "i"(__FILE__));	\
 		: : "i"(PAL_bugchk), "i"(__LINE__), "i"(__FILE__));	\
-	for ( ; ; ); }
+	for ( ; ; ); } while (0)
 
 
 #define HAVE_ARCH_BUG
 #define HAVE_ARCH_BUG
 #endif
 #endif

+ 1 - 1
arch/ia64/sn/kernel/io_acpi_init.c

@@ -443,7 +443,7 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
 		size = pci_resource_len(dev, PCI_ROM_RESOURCE);
 		size = pci_resource_len(dev, PCI_ROM_RESOURCE);
 		addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
 		addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
 			       size);
 			       size);
-		image_size = pci_get_rom_size(addr, size);
+		image_size = pci_get_rom_size(dev, addr, size);
 		dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
 		dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
 		dev->resource[PCI_ROM_RESOURCE].end =
 		dev->resource[PCI_ROM_RESOURCE].end =
 					(unsigned long) addr + image_size - 1;
 					(unsigned long) addr + image_size - 1;

+ 1 - 1
arch/ia64/sn/kernel/io_init.c

@@ -269,7 +269,7 @@ sn_io_slot_fixup(struct pci_dev *dev)
 
 
 			rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE),
 			rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE),
 				      size + 1);
 				      size + 1);
-			image_size = pci_get_rom_size(rom, size + 1);
+			image_size = pci_get_rom_size(dev, rom, size + 1);
 			dev->resource[PCI_ROM_RESOURCE].end =
 			dev->resource[PCI_ROM_RESOURCE].end =
 				dev->resource[PCI_ROM_RESOURCE].start +
 				dev->resource[PCI_ROM_RESOURCE].start +
 				image_size - 1;
 				image_size - 1;

+ 59 - 4
arch/sh/boards/board-ap325rxa.c

@@ -22,6 +22,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_gpio.h>
 #include <linux/spi/spi_gpio.h>
+#include <media/ov772x.h>
 #include <media/soc_camera_platform.h>
 #include <media/soc_camera_platform.h>
 #include <media/sh_mobile_ceu.h>
 #include <media/sh_mobile_ceu.h>
 #include <video/sh_mobile_lcdc.h>
 #include <video/sh_mobile_lcdc.h>
@@ -216,7 +217,14 @@ static struct platform_device lcdc_device = {
 	},
 	},
 };
 };
 
 
+static void camera_power(int val)
+{
+	gpio_set_value(GPIO_PTZ5, val); /* RST_CAM/RSTB */
+	mdelay(10);
+}
+
 #ifdef CONFIG_I2C
 #ifdef CONFIG_I2C
+/* support for the old ncm03j camera */
 static unsigned char camera_ncm03j_magic[] =
 static unsigned char camera_ncm03j_magic[] =
 {
 {
 	0x87, 0x00, 0x88, 0x08, 0x89, 0x01, 0x8A, 0xE8,
 	0x87, 0x00, 0x88, 0x08, 0x89, 0x01, 0x8A, 0xE8,
@@ -237,6 +245,23 @@ static unsigned char camera_ncm03j_magic[] =
 	0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
 	0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
 };
 };
 
 
+static int camera_probe(void)
+{
+	struct i2c_adapter *a = i2c_get_adapter(0);
+	struct i2c_msg msg;
+	int ret;
+
+	camera_power(1);
+	msg.addr = 0x6e;
+	msg.buf = camera_ncm03j_magic;
+	msg.len = 2;
+	msg.flags = 0;
+	ret = i2c_transfer(a, &msg, 1);
+	camera_power(0);
+
+	return ret;
+}
+
 static int camera_set_capture(struct soc_camera_platform_info *info,
 static int camera_set_capture(struct soc_camera_platform_info *info,
 			      int enable)
 			      int enable)
 {
 {
@@ -245,9 +270,11 @@ static int camera_set_capture(struct soc_camera_platform_info *info,
 	int ret = 0;
 	int ret = 0;
 	int i;
 	int i;
 
 
+	camera_power(0);
 	if (!enable)
 	if (!enable)
 		return 0; /* no disable for now */
 		return 0; /* no disable for now */
 
 
+	camera_power(1);
 	for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) {
 	for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) {
 		u_int8_t buf[8];
 		u_int8_t buf[8];
 
 
@@ -286,8 +313,35 @@ static struct platform_device camera_device = {
 		.platform_data	= &camera_info,
 		.platform_data	= &camera_info,
 	},
 	},
 };
 };
+
+static int __init camera_setup(void)
+{
+	if (camera_probe() > 0)
+		platform_device_register(&camera_device);
+
+	return 0;
+}
+late_initcall(camera_setup);
+
 #endif /* CONFIG_I2C */
 #endif /* CONFIG_I2C */
 
 
+static int ov7725_power(struct device *dev, int mode)
+{
+	camera_power(0);
+	if (mode)
+		camera_power(1);
+
+	return 0;
+}
+
+static struct ov772x_camera_info ov7725_info = {
+	.buswidth  = SOCAM_DATAWIDTH_8,
+	.flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
+	.link = {
+		.power  = ov7725_power,
+	},
+};
+
 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
 	.flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
 	.flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
 	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
 	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
@@ -338,9 +392,6 @@ static struct platform_device *ap325rxa_devices[] __initdata = {
 	&ap325rxa_nor_flash_device,
 	&ap325rxa_nor_flash_device,
 	&lcdc_device,
 	&lcdc_device,
 	&ceu_device,
 	&ceu_device,
-#ifdef CONFIG_I2C
-	&camera_device,
-#endif
 	&nand_flash_device,
 	&nand_flash_device,
 	&sdcard_cn3_device,
 	&sdcard_cn3_device,
 };
 };
@@ -349,6 +400,10 @@ static struct i2c_board_info __initdata ap325rxa_i2c_devices[] = {
 	{
 	{
 		I2C_BOARD_INFO("pcf8563", 0x51),
 		I2C_BOARD_INFO("pcf8563", 0x51),
 	},
 	},
+	{
+		I2C_BOARD_INFO("ov772x", 0x21),
+		.platform_data = &ov7725_info,
+	},
 };
 };
 
 
 static struct spi_board_info ap325rxa_spi_devices[] = {
 static struct spi_board_info ap325rxa_spi_devices[] = {
@@ -426,7 +481,7 @@ static int __init ap325rxa_devices_setup(void)
 	gpio_request(GPIO_PTZ6, NULL);
 	gpio_request(GPIO_PTZ6, NULL);
 	gpio_direction_output(GPIO_PTZ6, 0); /* STBY_CAM */
 	gpio_direction_output(GPIO_PTZ6, 0); /* STBY_CAM */
 	gpio_request(GPIO_PTZ5, NULL);
 	gpio_request(GPIO_PTZ5, NULL);
-	gpio_direction_output(GPIO_PTZ5, 1); /* RST_CAM */
+	gpio_direction_output(GPIO_PTZ5, 0); /* RST_CAM */
 	gpio_request(GPIO_PTZ4, NULL);
 	gpio_request(GPIO_PTZ4, NULL);
 	gpio_direction_output(GPIO_PTZ4, 0); /* SADDR */
 	gpio_direction_output(GPIO_PTZ4, 0); /* SADDR */
 
 

+ 20 - 7
arch/sh/configs/ap325rxa_defconfig

@@ -1,7 +1,7 @@
 #
 #
 # Automatically generated make config: don't edit
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28
-# Fri Jan  9 16:54:19 2009
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 27 11:45:08 2009
 #
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
 CONFIG_SUPERH32=y
@@ -45,12 +45,12 @@ CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_AUDIT is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
 CONFIG_GROUP_SCHED=y
 CONFIG_GROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 # CONFIG_RT_GROUP_SCHED is not set
 # CONFIG_RT_GROUP_SCHED is not set
 CONFIG_USER_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
 # CONFIG_RELAY is not set
@@ -378,6 +378,7 @@ CONFIG_WIRELESS=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
 # CONFIG_LIB80211 is not set
 # CONFIG_MAC80211 is not set
 # CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 # CONFIG_NET_9P is not set
 
 
@@ -400,6 +401,7 @@ CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_DEBUG is not set
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AR7_PARTS is not set
 # CONFIG_MTD_AR7_PARTS is not set
@@ -447,9 +449,7 @@ CONFIG_MTD_CFI_UTIL=y
 #
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xffffffff
-CONFIG_MTD_PHYSMAP_LEN=0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 # CONFIG_MTD_PLATRAM is not set
 # CONFIG_MTD_PLATRAM is not set
 
 
 #
 #
@@ -479,6 +479,12 @@ CONFIG_MTD_NAND_IDS=y
 CONFIG_MTD_NAND_SH_FLCTL=y
 CONFIG_MTD_NAND_SH_FLCTL=y
 # CONFIG_MTD_ONENAND is not set
 # CONFIG_MTD_ONENAND is not set
 
 
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
 #
 #
 # UBI - Unsorted block images
 # UBI - Unsorted block images
 #
 #
@@ -607,6 +613,10 @@ CONFIG_SMSC911X=y
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 # CONFIG_WLAN_80211 is not set
 # CONFIG_IWLWIFI_LEDS is not set
 # CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 # CONFIG_SLIP is not set
@@ -790,6 +800,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
 # CONFIG_REGULATOR is not set
 
 
 #
 #
@@ -837,7 +848,7 @@ CONFIG_SOC_CAMERA=y
 # CONFIG_SOC_CAMERA_MT9V022 is not set
 # CONFIG_SOC_CAMERA_MT9V022 is not set
 # CONFIG_SOC_CAMERA_TW9910 is not set
 # CONFIG_SOC_CAMERA_TW9910 is not set
 CONFIG_SOC_CAMERA_PLATFORM=y
 CONFIG_SOC_CAMERA_PLATFORM=y
-# CONFIG_SOC_CAMERA_OV772X is not set
+CONFIG_SOC_CAMERA_OV772X=y
 CONFIG_VIDEO_SH_MOBILE_CEU=y
 CONFIG_VIDEO_SH_MOBILE_CEU=y
 # CONFIG_RADIO_ADAPTERS is not set
 # CONFIG_RADIO_ADAPTERS is not set
 # CONFIG_DAB is not set
 # CONFIG_DAB is not set
@@ -1012,6 +1023,7 @@ CONFIG_FS_POSIX_ACL=y
 CONFIG_FILE_LOCKING=y
 CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
 CONFIG_DNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 CONFIG_INOTIFY_USER=y
@@ -1060,6 +1072,7 @@ CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_JFFS2_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_UBIFS_FS is not set
 # CONFIG_UBIFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
 # CONFIG_OMFS_FS is not set

+ 33 - 9
arch/sh/configs/migor_defconfig

@@ -1,7 +1,7 @@
 #
 #
 # Automatically generated make config: don't edit
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28
-# Fri Jan  9 17:09:35 2009
+# Linux kernel version: 2.6.29-rc1
+# Thu Jan 22 09:16:16 2009
 #
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
 CONFIG_SUPERH32=y
@@ -45,8 +45,12 @@ CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
 # CONFIG_GROUP_SCHED is not set
+
+#
+# Control Group support
+#
+# CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
 # CONFIG_RELAY is not set
@@ -389,6 +393,7 @@ CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
 # CONFIG_LIB80211 is not set
 # CONFIG_MAC80211 is not set
 # CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 # CONFIG_NET_9P is not set
 
 
@@ -411,6 +416,7 @@ CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_DEBUG is not set
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AR7_PARTS is not set
 # CONFIG_MTD_AR7_PARTS is not set
@@ -458,9 +464,7 @@ CONFIG_MTD_CFI_UTIL=y
 #
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xffffffff
-CONFIG_MTD_PHYSMAP_LEN=0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 # CONFIG_MTD_PLATRAM is not set
 # CONFIG_MTD_PLATRAM is not set
 
 
 #
 #
@@ -487,6 +491,12 @@ CONFIG_MTD_NAND_IDS=y
 CONFIG_MTD_NAND_PLATFORM=y
 CONFIG_MTD_NAND_PLATFORM=y
 # CONFIG_MTD_ONENAND is not set
 # CONFIG_MTD_ONENAND is not set
 
 
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
 #
 #
 # UBI - Unsorted block images
 # UBI - Unsorted block images
 #
 #
@@ -587,6 +597,10 @@ CONFIG_SMC91X=y
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 # CONFIG_WLAN_80211 is not set
 # CONFIG_IWLWIFI_LEDS is not set
 # CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 # CONFIG_SLIP is not set
@@ -761,6 +775,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
 # CONFIG_REGULATOR is not set
 
 
 #
 #
@@ -806,9 +821,9 @@ CONFIG_SOC_CAMERA=y
 # CONFIG_SOC_CAMERA_MT9M111 is not set
 # CONFIG_SOC_CAMERA_MT9M111 is not set
 # CONFIG_SOC_CAMERA_MT9T031 is not set
 # CONFIG_SOC_CAMERA_MT9T031 is not set
 # CONFIG_SOC_CAMERA_MT9V022 is not set
 # CONFIG_SOC_CAMERA_MT9V022 is not set
-# CONFIG_SOC_CAMERA_TW9910 is not set
-CONFIG_SOC_CAMERA_PLATFORM=y
-# CONFIG_SOC_CAMERA_OV772X is not set
+CONFIG_SOC_CAMERA_TW9910=y
+# CONFIG_SOC_CAMERA_PLATFORM is not set
+CONFIG_SOC_CAMERA_OV772X=y
 CONFIG_VIDEO_SH_MOBILE_CEU=y
 CONFIG_VIDEO_SH_MOBILE_CEU=y
 # CONFIG_RADIO_ADAPTERS is not set
 # CONFIG_RADIO_ADAPTERS is not set
 # CONFIG_DAB is not set
 # CONFIG_DAB is not set
@@ -866,11 +881,13 @@ CONFIG_USB_GADGET_SELECTED=y
 # CONFIG_USB_GADGET_PXA25X is not set
 # CONFIG_USB_GADGET_PXA25X is not set
 # CONFIG_USB_GADGET_PXA27X is not set
 # CONFIG_USB_GADGET_PXA27X is not set
 # CONFIG_USB_GADGET_S3C2410 is not set
 # CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
 CONFIG_USB_GADGET_M66592=y
 CONFIG_USB_GADGET_M66592=y
 CONFIG_USB_M66592=y
 CONFIG_USB_M66592=y
 CONFIG_SUPERH_BUILT_IN_M66592=y
 CONFIG_SUPERH_BUILT_IN_M66592=y
 # CONFIG_USB_GADGET_AMD5536UDC is not set
 # CONFIG_USB_GADGET_AMD5536UDC is not set
 # CONFIG_USB_GADGET_FSL_QE is not set
 # CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
 # CONFIG_USB_GADGET_NET2280 is not set
 # CONFIG_USB_GADGET_NET2280 is not set
 # CONFIG_USB_GADGET_GOKU is not set
 # CONFIG_USB_GADGET_GOKU is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
@@ -883,6 +900,11 @@ CONFIG_USB_G_SERIAL=y
 # CONFIG_USB_MIDI_GADGET is not set
 # CONFIG_USB_MIDI_GADGET is not set
 # CONFIG_USB_G_PRINTER is not set
 # CONFIG_USB_G_PRINTER is not set
 # CONFIG_USB_CDC_COMPOSITE is not set
 # CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
 # CONFIG_MMC is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_NEW_LEDS is not set
@@ -961,6 +983,7 @@ CONFIG_UIO_PDRV_GENIRQ=y
 CONFIG_FILE_LOCKING=y
 CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
 # CONFIG_INOTIFY is not set
 # CONFIG_QUOTA is not set
 # CONFIG_QUOTA is not set
@@ -1004,6 +1027,7 @@ CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_EFS_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
 # CONFIG_OMFS_FS is not set

+ 9 - 12
arch/sh/include/asm/mutex-llsc.h

@@ -21,38 +21,36 @@
 static inline void
 static inline void
 __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
 __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
 {
 {
-	int __ex_flag, __res;
+	int __done, __res;
 
 
 	__asm__ __volatile__ (
 	__asm__ __volatile__ (
 		"movli.l	@%2, %0	\n"
 		"movli.l	@%2, %0	\n"
 		"add		#-1, %0	\n"
 		"add		#-1, %0	\n"
 		"movco.l	%0, @%2	\n"
 		"movco.l	%0, @%2	\n"
 		"movt		%1	\n"
 		"movt		%1	\n"
-		: "=&z" (__res), "=&r" (__ex_flag)
+		: "=&z" (__res), "=&r" (__done)
 		: "r" (&(count)->counter)
 		: "r" (&(count)->counter)
 		: "t");
 		: "t");
 
 
-	__res |= !__ex_flag;
-	if (unlikely(__res != 0))
+	if (unlikely(!__done || __res != 0))
 		fail_fn(count);
 		fail_fn(count);
 }
 }
 
 
 static inline int
 static inline int
 __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
 __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
 {
 {
-	int __ex_flag, __res;
+	int __done, __res;
 
 
 	__asm__ __volatile__ (
 	__asm__ __volatile__ (
 		"movli.l	@%2, %0	\n"
 		"movli.l	@%2, %0	\n"
 		"add		#-1, %0	\n"
 		"add		#-1, %0	\n"
 		"movco.l	%0, @%2	\n"
 		"movco.l	%0, @%2	\n"
 		"movt		%1	\n"
 		"movt		%1	\n"
-		: "=&z" (__res), "=&r" (__ex_flag)
+		: "=&z" (__res), "=&r" (__done)
 		: "r" (&(count)->counter)
 		: "r" (&(count)->counter)
 		: "t");
 		: "t");
 
 
-	__res |= !__ex_flag;
-	if (unlikely(__res != 0))
+	if (unlikely(!__done || __res != 0))
 		__res = fail_fn(count);
 		__res = fail_fn(count);
 
 
 	return __res;
 	return __res;
@@ -61,19 +59,18 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
 static inline void
 static inline void
 __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
 __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
 {
 {
-	int __ex_flag, __res;
+	int __done, __res;
 
 
 	__asm__ __volatile__ (
 	__asm__ __volatile__ (
 		"movli.l	@%2, %0	\n\t"
 		"movli.l	@%2, %0	\n\t"
 		"add		#1, %0	\n\t"
 		"add		#1, %0	\n\t"
 		"movco.l	%0, @%2 \n\t"
 		"movco.l	%0, @%2 \n\t"
 		"movt		%1	\n\t"
 		"movt		%1	\n\t"
-		: "=&z" (__res), "=&r" (__ex_flag)
+		: "=&z" (__res), "=&r" (__done)
 		: "r" (&(count)->counter)
 		: "r" (&(count)->counter)
 		: "t");
 		: "t");
 
 
-	__res |= !__ex_flag;
-	if (unlikely(__res <= 0))
+	if (unlikely(!__done || __res <= 0))
 		fail_fn(count);
 		fail_fn(count);
 }
 }
 
 

+ 3 - 19
arch/sh/include/asm/syscall_32.h

@@ -21,23 +21,10 @@ static inline void syscall_rollback(struct task_struct *task,
 	 */
 	 */
 }
 }
 
 
-static inline bool syscall_has_error(struct pt_regs *regs)
-{
-	return (regs->sr & 0x1) ? true : false;
-}
-static inline void syscall_set_error(struct pt_regs *regs)
-{
-	regs->sr |= 0x1;
-}
-static inline void syscall_clear_error(struct pt_regs *regs)
-{
-	regs->sr &= ~0x1;
-}
-
 static inline long syscall_get_error(struct task_struct *task,
 static inline long syscall_get_error(struct task_struct *task,
 				     struct pt_regs *regs)
 				     struct pt_regs *regs)
 {
 {
-	return syscall_has_error(regs) ? regs->regs[0] : 0;
+	return IS_ERR_VALUE(regs->regs[0]) ? regs->regs[0] : 0;
 }
 }
 
 
 static inline long syscall_get_return_value(struct task_struct *task,
 static inline long syscall_get_return_value(struct task_struct *task,
@@ -50,13 +37,10 @@ static inline void syscall_set_return_value(struct task_struct *task,
 					    struct pt_regs *regs,
 					    struct pt_regs *regs,
 					    int error, long val)
 					    int error, long val)
 {
 {
-	if (error) {
-		syscall_set_error(regs);
+	if (error)
 		regs->regs[0] = -error;
 		regs->regs[0] = -error;
-	} else {
-		syscall_clear_error(regs);
+	else
 		regs->regs[0] = val;
 		regs->regs[0] = val;
-	}
 }
 }
 
 
 static inline void syscall_get_arguments(struct task_struct *task,
 static inline void syscall_get_arguments(struct task_struct *task,

+ 3 - 19
arch/sh/include/asm/syscall_64.h

@@ -21,23 +21,10 @@ static inline void syscall_rollback(struct task_struct *task,
 	 */
 	 */
 }
 }
 
 
-static inline bool syscall_has_error(struct pt_regs *regs)
-{
-	return (regs->sr & 0x1) ? true : false;
-}
-static inline void syscall_set_error(struct pt_regs *regs)
-{
-	regs->sr |= 0x1;
-}
-static inline void syscall_clear_error(struct pt_regs *regs)
-{
-	regs->sr &= ~0x1;
-}
-
 static inline long syscall_get_error(struct task_struct *task,
 static inline long syscall_get_error(struct task_struct *task,
 				     struct pt_regs *regs)
 				     struct pt_regs *regs)
 {
 {
-	return syscall_has_error(regs) ? regs->regs[9] : 0;
+	return IS_ERR_VALUE(regs->regs[9]) ? regs->regs[9] : 0;
 }
 }
 
 
 static inline long syscall_get_return_value(struct task_struct *task,
 static inline long syscall_get_return_value(struct task_struct *task,
@@ -50,13 +37,10 @@ static inline void syscall_set_return_value(struct task_struct *task,
 					    struct pt_regs *regs,
 					    struct pt_regs *regs,
 					    int error, long val)
 					    int error, long val)
 {
 {
-	if (error) {
-		syscall_set_error(regs);
+	if (error)
 		regs->regs[9] = -error;
 		regs->regs[9] = -error;
-	} else {
-		syscall_clear_error(regs);
+	else
 		regs->regs[9] = val;
 		regs->regs[9] = val;
-	}
 }
 }
 
 
 static inline void syscall_get_arguments(struct task_struct *task,
 static inline void syscall_get_arguments(struct task_struct *task,

+ 1 - 1
arch/sh/kernel/cpu/sh4/fpu.c

@@ -423,7 +423,7 @@ static int ieee_fpe_handler(struct pt_regs *regs)
 		int m;
 		int m;
 		unsigned int hx;
 		unsigned int hx;
 
 
-		m = (finsn >> 9) & 0x7;
+		m = (finsn >> 8) & 0x7;
 		hx = tsk->thread.fpu.hard.fp_regs[m];
 		hx = tsk->thread.fpu.hard.fp_regs[m];
 
 
 		if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR)
 		if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR)

+ 4 - 4
arch/sh/kernel/setup.c

@@ -262,11 +262,11 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
 			BOOTMEM_DEFAULT);
 			BOOTMEM_DEFAULT);
 
 
 	/*
 	/*
-	 * reserve physical page 0 - it's a special BIOS page on many boxes,
-	 * enabling clean reboots, SMP operation, laptop functions.
+	 * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
 	 */
 	 */
-	reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET,
-			BOOTMEM_DEFAULT);
+	if (CONFIG_ZERO_PAGE_OFFSET != 0)
+		reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET,
+				BOOTMEM_DEFAULT);
 
 
 	sparse_memory_present_with_active_regions(0);
 	sparse_memory_present_with_active_regions(0);
 
 

+ 1 - 3
arch/sh/kernel/signal_32.c

@@ -510,7 +510,6 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs,
 		case -ERESTARTNOHAND:
 		case -ERESTARTNOHAND:
 		no_system_call_restart:
 		no_system_call_restart:
 			regs->regs[0] = -EINTR;
 			regs->regs[0] = -EINTR;
-			regs->sr |= 1;
 			break;
 			break;
 
 
 		case -ERESTARTSYS:
 		case -ERESTARTSYS:
@@ -589,8 +588,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
 
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 	if (signr > 0) {
-		if (regs->sr & 1)
-			handle_syscall_restart(save_r0, regs, &ka.sa);
+		handle_syscall_restart(save_r0, regs, &ka.sa);
 
 
 		/* Whee!  Actually deliver the signal.  */
 		/* Whee!  Actually deliver the signal.  */
 		if (handle_signal(signr, &ka, &info, oldset,
 		if (handle_signal(signr, &ka, &info, oldset,

+ 1 - 3
arch/sh/kernel/signal_64.c

@@ -60,7 +60,6 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
 		case -ERESTARTNOHAND:
 		case -ERESTARTNOHAND:
 		no_system_call_restart:
 		no_system_call_restart:
 			regs->regs[REG_RET] = -EINTR;
 			regs->regs[REG_RET] = -EINTR;
-			regs->sr |= 1;
 			break;
 			break;
 
 
 		case -ERESTARTSYS:
 		case -ERESTARTSYS:
@@ -109,8 +108,7 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
 
 
 	signr = get_signal_to_deliver(&info, &ka, regs, 0);
 	signr = get_signal_to_deliver(&info, &ka, regs, 0);
 	if (signr > 0) {
 	if (signr > 0) {
-		if (regs->sr & 1)
-			handle_syscall_restart(regs, &ka.sa);
+		handle_syscall_restart(regs, &ka.sa);
 
 
 		/* Whee!  Actually deliver the signal.  */
 		/* Whee!  Actually deliver the signal.  */
 		if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
 		if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {

+ 50 - 19
arch/sh/lib/checksum.S

@@ -36,8 +36,7 @@
  */
  */
 
 
 /*	
 /*	
- * unsigned int csum_partial(const unsigned char *buf, int len,
- *                           unsigned int sum);
+ * asmlinkage __wsum csum_partial(const void *buf, int len, __wsum sum);
  */
  */
 
 
 .text
 .text
@@ -49,11 +48,31 @@ ENTRY(csum_partial)
 	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
 	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
 	   * alignment for the unrolled loop.
 	   * alignment for the unrolled loop.
 	   */
 	   */
-	mov	r5, r1
 	mov	r4, r0
 	mov	r4, r0
-	tst	#2, r0		! Check alignment.
-	bt	2f		! Jump if alignment is ok.
+	tst	#3, r0		! Check alignment.
+	bt/s	2f		! Jump if alignment is ok.
+	 mov	r4, r7		! Keep a copy to check for alignment
 	!
 	!
+	tst	#1, r0		! Check alignment.
+	bt	21f		! Jump if alignment is boundary of 2bytes.
+
+	! buf is odd
+	tst	r5, r5
+	add	#-1, r5
+	bt	9f
+	mov.b	@r4+, r0
+	extu.b	r0, r0
+	addc	r0, r6		! t=0 from previous tst
+	mov	r6, r0
+	shll8	r6
+	shlr16	r0
+	shlr8	r0
+	or	r0, r6
+	mov	r4, r0
+	tst	#2, r0
+	bt	2f
+21:
+	! buf is 2 byte aligned (len could be 0)
 	add	#-2, r5		! Alignment uses up two bytes.
 	add	#-2, r5		! Alignment uses up two bytes.
 	cmp/pz	r5		!
 	cmp/pz	r5		!
 	bt/s	1f		! Jump if we had at least two bytes.
 	bt/s	1f		! Jump if we had at least two bytes.
@@ -61,16 +80,17 @@ ENTRY(csum_partial)
 	bra	6f
 	bra	6f
 	 add	#2, r5		! r5 was < 2.  Deal with it.
 	 add	#2, r5		! r5 was < 2.  Deal with it.
 1:
 1:
-	mov	r5, r1		! Save new len for later use.
 	mov.w	@r4+, r0
 	mov.w	@r4+, r0
 	extu.w	r0, r0
 	extu.w	r0, r0
 	addc	r0, r6
 	addc	r0, r6
 	bf	2f
 	bf	2f
 	add	#1, r6
 	add	#1, r6
 2:
 2:
+	! buf is 4 byte aligned (len could be 0)
+	mov	r5, r1
 	mov	#-5, r0
 	mov	#-5, r0
-	shld	r0, r5
-	tst	r5, r5
+	shld	r0, r1
+	tst	r1, r1
 	bt/s	4f		! if it's =0, go to 4f
 	bt/s	4f		! if it's =0, go to 4f
 	 clrt
 	 clrt
 	.align	2
 	.align	2
@@ -92,30 +112,31 @@ ENTRY(csum_partial)
 	addc	r0, r6
 	addc	r0, r6
 	addc	r2, r6
 	addc	r2, r6
 	movt	r0
 	movt	r0
-	dt	r5
+	dt	r1
 	bf/s	3b
 	bf/s	3b
 	 cmp/eq	#1, r0
 	 cmp/eq	#1, r0
-	! here, we know r5==0
-	addc	r5, r6			! add carry to r6
+	! here, we know r1==0
+	addc	r1, r6			! add carry to r6
 4:
 4:
-	mov	r1, r0
+	mov	r5, r0
 	and	#0x1c, r0
 	and	#0x1c, r0
 	tst	r0, r0
 	tst	r0, r0
-	bt/s	6f
-	 mov	r0, r5
-	shlr2	r5
+	bt	6f
+	! 4 bytes or more remaining
+	mov	r0, r1
+	shlr2	r1
 	mov	#0, r2
 	mov	#0, r2
 5:
 5:
 	addc	r2, r6
 	addc	r2, r6
 	mov.l	@r4+, r2
 	mov.l	@r4+, r2
 	movt	r0
 	movt	r0
-	dt	r5
+	dt	r1
 	bf/s	5b
 	bf/s	5b
 	 cmp/eq	#1, r0
 	 cmp/eq	#1, r0
 	addc	r2, r6
 	addc	r2, r6
-	addc	r5, r6		! r5==0 here, so it means add carry-bit
+	addc	r1, r6		! r1==0 here, so it means add carry-bit
 6:
 6:
-	mov	r1, r5
+	! 3 bytes or less remaining
 	mov	#3, r0
 	mov	#3, r0
 	and	r0, r5
 	and	r0, r5
 	tst	r5, r5
 	tst	r5, r5
@@ -139,8 +160,18 @@ ENTRY(csum_partial)
 8:
 8:
 	addc	r0, r6
 	addc	r0, r6
 	mov	#0, r0
 	mov	#0, r0
-	addc	r0, r6 
+	addc	r0, r6
 9:
 9:
+	! Check if the buffer was misaligned, if so realign sum
+	mov	r7, r0
+	tst	#1, r0
+	bt	10f
+	mov	r6, r0
+	shll8	r6
+	shlr16	r0
+	shlr8	r0
+	or	r0, r6
+10:
 	rts
 	rts
 	 mov	r6, r0
 	 mov	r6, r0
 
 

+ 5 - 3
arch/x86/ia32/ia32entry.S

@@ -418,9 +418,9 @@ ENTRY(ia32_syscall)
 	orl   $TS_COMPAT,TI_status(%r10)
 	orl   $TS_COMPAT,TI_status(%r10)
 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
 	jnz ia32_tracesys
 	jnz ia32_tracesys
-ia32_do_syscall:	
 	cmpl $(IA32_NR_syscalls-1),%eax
 	cmpl $(IA32_NR_syscalls-1),%eax
-	ja  int_ret_from_sys_call	/* ia32_tracesys has set RAX(%rsp) */
+	ja ia32_badsys
+ia32_do_call:
 	IA32_ARG_FIXUP
 	IA32_ARG_FIXUP
 	call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
 	call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
 ia32_sysret:
 ia32_sysret:
@@ -435,7 +435,9 @@ ia32_tracesys:
 	call syscall_trace_enter
 	call syscall_trace_enter
 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
 	RESTORE_REST
 	RESTORE_REST
-	jmp ia32_do_syscall
+	cmpl $(IA32_NR_syscalls-1),%eax
+	ja  int_ret_from_sys_call	/* ia32_tracesys has set RAX(%rsp) */
+	jmp ia32_do_call
 END(ia32_syscall)
 END(ia32_syscall)
 
 
 ia32_badsys:
 ia32_badsys:

+ 2 - 2
arch/x86/kernel/acpi/sleep.c

@@ -156,11 +156,11 @@ static int __init acpi_sleep_setup(char *str)
 #ifdef CONFIG_HIBERNATION
 #ifdef CONFIG_HIBERNATION
 		if (strncmp(str, "s4_nohwsig", 10) == 0)
 		if (strncmp(str, "s4_nohwsig", 10) == 0)
 			acpi_no_s4_hw_signature();
 			acpi_no_s4_hw_signature();
+		if (strncmp(str, "s4_nonvs", 8) == 0)
+			acpi_s4_no_nvs();
 #endif
 #endif
 		if (strncmp(str, "old_ordering", 12) == 0)
 		if (strncmp(str, "old_ordering", 12) == 0)
 			acpi_old_suspend_ordering();
 			acpi_old_suspend_ordering();
-		if (strncmp(str, "s4_nonvs", 8) == 0)
-			acpi_s4_no_nvs();
 		str = strchr(str, ',');
 		str = strchr(str, ',');
 		if (str != NULL)
 		if (str != NULL)
 			str += strspn(str, ", \t");
 			str += strspn(str, ", \t");

+ 1 - 1
arch/x86/kernel/apic.c

@@ -1436,7 +1436,7 @@ static int __init detect_init_APIC(void)
 	switch (boot_cpu_data.x86_vendor) {
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_AMD:
 	case X86_VENDOR_AMD:
 		if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
 		if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
-		    (boot_cpu_data.x86 == 15))
+		    (boot_cpu_data.x86 >= 15))
 			break;
 			break;
 		goto no_apic;
 		goto no_apic;
 	case X86_VENDOR_INTEL:
 	case X86_VENDOR_INTEL:

+ 0 - 11
arch/x86/kernel/cpu/cpufreq/Kconfig

@@ -245,17 +245,6 @@ config X86_E_POWERSAVER
 
 
 comment "shared options"
 comment "shared options"
 
 
-config X86_ACPI_CPUFREQ_PROC_INTF
-	bool "/proc/acpi/processor/../performance interface (deprecated)"
-	depends on PROC_FS
-	depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
-	help
-	  This enables the deprecated /proc/acpi/processor/../performance
-	  interface. While it is helpful for debugging, the generic,
-	  cross-architecture cpufreq interfaces should be used.
-
-	  If in doubt, say N.
-
 config X86_SPEEDSTEP_LIB
 config X86_SPEEDSTEP_LIB
 	tristate
 	tristate
 	default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
 	default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)

+ 15 - 0
arch/x86/kernel/cpu/intel_cacheinfo.c

@@ -36,8 +36,11 @@ static struct _cache_table cache_table[] __cpuinitdata =
 {
 {
 	{ 0x06, LVL_1_INST, 8 },	/* 4-way set assoc, 32 byte line size */
 	{ 0x06, LVL_1_INST, 8 },	/* 4-way set assoc, 32 byte line size */
 	{ 0x08, LVL_1_INST, 16 },	/* 4-way set assoc, 32 byte line size */
 	{ 0x08, LVL_1_INST, 16 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x09, LVL_1_INST, 32 },	/* 4-way set assoc, 64 byte line size */
 	{ 0x0a, LVL_1_DATA, 8 },	/* 2 way set assoc, 32 byte line size */
 	{ 0x0a, LVL_1_DATA, 8 },	/* 2 way set assoc, 32 byte line size */
 	{ 0x0c, LVL_1_DATA, 16 },	/* 4-way set assoc, 32 byte line size */
 	{ 0x0c, LVL_1_DATA, 16 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x0d, LVL_1_DATA, 16 },	/* 4-way set assoc, 64 byte line size */
+	{ 0x21, LVL_2,      256 },	/* 8-way set assoc, 64 byte line size */
 	{ 0x22, LVL_3,      512 },	/* 4-way set assoc, sectored cache, 64 byte line size */
 	{ 0x22, LVL_3,      512 },	/* 4-way set assoc, sectored cache, 64 byte line size */
 	{ 0x23, LVL_3,      1024 },	/* 8-way set assoc, sectored cache, 64 byte line size */
 	{ 0x23, LVL_3,      1024 },	/* 8-way set assoc, sectored cache, 64 byte line size */
 	{ 0x25, LVL_3,      2048 },	/* 8-way set assoc, sectored cache, 64 byte line size */
 	{ 0x25, LVL_3,      2048 },	/* 8-way set assoc, sectored cache, 64 byte line size */
@@ -85,6 +88,18 @@ static struct _cache_table cache_table[] __cpuinitdata =
 	{ 0x85, LVL_2,    2048 },	/* 8-way set assoc, 32 byte line size */
 	{ 0x85, LVL_2,    2048 },	/* 8-way set assoc, 32 byte line size */
 	{ 0x86, LVL_2,     512 },	/* 4-way set assoc, 64 byte line size */
 	{ 0x86, LVL_2,     512 },	/* 4-way set assoc, 64 byte line size */
 	{ 0x87, LVL_2,    1024 },	/* 8-way set assoc, 64 byte line size */
 	{ 0x87, LVL_2,    1024 },	/* 8-way set assoc, 64 byte line size */
+	{ 0xd0, LVL_3,     512 },	/* 4-way set assoc, 64 byte line size */
+	{ 0xd1, LVL_3,    1024 },	/* 4-way set assoc, 64 byte line size */
+	{ 0xd2, LVL_3,    2048 },	/* 4-way set assoc, 64 byte line size */
+	{ 0xd6, LVL_3,    1024 },	/* 8-way set assoc, 64 byte line size */
+	{ 0xd7, LVL_3,    2038 },	/* 8-way set assoc, 64 byte line size */
+	{ 0xd8, LVL_3,    4096 },	/* 12-way set assoc, 64 byte line size */
+	{ 0xdc, LVL_3,    2048 },	/* 12-way set assoc, 64 byte line size */
+	{ 0xdd, LVL_3,    4096 },	/* 12-way set assoc, 64 byte line size */
+	{ 0xde, LVL_3,    8192 },	/* 12-way set assoc, 64 byte line size */
+	{ 0xe2, LVL_3,    2048 },	/* 16-way set assoc, 64 byte line size */
+	{ 0xe3, LVL_3,    4096 },	/* 16-way set assoc, 64 byte line size */
+	{ 0xe4, LVL_3,    8192 },	/* 16-way set assoc, 64 byte line size */
 	{ 0x00, 0, 0}
 	{ 0x00, 0, 0}
 };
 };
 
 

+ 1 - 0
arch/x86/kernel/entry_64.S

@@ -346,6 +346,7 @@ ENTRY(save_args)
 	popq_cfi %rax			/* move return address... */
 	popq_cfi %rax			/* move return address... */
 	mov %gs:pda_irqstackptr,%rsp
 	mov %gs:pda_irqstackptr,%rsp
 	EMPTY_FRAME 0
 	EMPTY_FRAME 0
+	pushq_cfi %rbp			/* backlink for unwinder */
 	pushq_cfi %rax			/* ... to the new stack */
 	pushq_cfi %rax			/* ... to the new stack */
 	/*
 	/*
 	 * We entered an interrupt context - irqs are off:
 	 * We entered an interrupt context - irqs are off:

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

@@ -2528,14 +2528,15 @@ static void irq_complete_move(struct irq_desc **descp)
 
 
 	vector = ~get_irq_regs()->orig_ax;
 	vector = ~get_irq_regs()->orig_ax;
 	me = smp_processor_id();
 	me = smp_processor_id();
+
+	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) {
 #ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
 #ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
 		*descp = desc = move_irq_desc(desc, me);
 		*descp = desc = move_irq_desc(desc, me);
 		/* get the new one */
 		/* get the new one */
 		cfg = desc->chip_data;
 		cfg = desc->chip_data;
 #endif
 #endif
-
-	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
 		send_cleanup_vector(cfg);
 		send_cleanup_vector(cfg);
+	}
 }
 }
 #else
 #else
 static inline void irq_complete_move(struct irq_desc **descp) {}
 static inline void irq_complete_move(struct irq_desc **descp) {}

+ 0 - 12
arch/x86/kernel/irqinit_32.c

@@ -78,15 +78,6 @@ void __init init_ISA_irqs(void)
 	}
 	}
 }
 }
 
 
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-static struct irqaction irq2 = {
-	.handler = no_action,
-	.mask = CPU_MASK_NONE,
-	.name = "cascade",
-};
-
 DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
 DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
 	[0 ... IRQ0_VECTOR - 1] = -1,
 	[0 ... IRQ0_VECTOR - 1] = -1,
 	[IRQ0_VECTOR] = 0,
 	[IRQ0_VECTOR] = 0,
@@ -178,9 +169,6 @@ void __init native_init_IRQ(void)
 	alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
 	alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
 #endif
 #endif
 
 
-	if (!acpi_ioapic)
-		setup_irq(2, &irq2);
-
 	/* setup after call gates are initialised (usually add in
 	/* setup after call gates are initialised (usually add in
 	 * the architecture specific gates)
 	 * the architecture specific gates)
 	 */
 	 */

+ 12 - 0
arch/x86/mach-default/setup.c

@@ -38,6 +38,15 @@ void __init pre_intr_init_hook(void)
 	init_ISA_irqs();
 	init_ISA_irqs();
 }
 }
 
 
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = {
+	.handler = no_action,
+	.mask = CPU_MASK_NONE,
+	.name = "cascade",
+};
+
 /**
 /**
  * intr_init_hook - post gate setup interrupt initialisation
  * intr_init_hook - post gate setup interrupt initialisation
  *
  *
@@ -53,6 +62,9 @@ void __init intr_init_hook(void)
 		if (x86_quirks->arch_intr_init())
 		if (x86_quirks->arch_intr_init())
 			return;
 			return;
 	}
 	}
+	if (!acpi_ioapic)
+		setup_irq(2, &irq2);
+
 }
 }
 
 
 /**
 /**

+ 11 - 1
arch/x86/mach-voyager/setup.c

@@ -33,13 +33,23 @@ void __init intr_init_hook(void)
 	setup_irq(2, &irq2);
 	setup_irq(2, &irq2);
 }
 }
 
 
-void __init pre_setup_arch_hook(void)
+static void voyager_disable_tsc(void)
 {
 {
 	/* Voyagers run their CPUs from independent clocks, so disable
 	/* Voyagers run their CPUs from independent clocks, so disable
 	 * the TSC code because we can't sync them */
 	 * the TSC code because we can't sync them */
 	setup_clear_cpu_cap(X86_FEATURE_TSC);
 	setup_clear_cpu_cap(X86_FEATURE_TSC);
 }
 }
 
 
+void __init pre_setup_arch_hook(void)
+{
+	voyager_disable_tsc();
+}
+
+void __init pre_time_init_hook(void)
+{
+	voyager_disable_tsc();
+}
+
 void __init trap_init_hook(void)
 void __init trap_init_hook(void)
 {
 {
 }
 }

+ 12 - 13
arch/x86/mach-voyager/voyager_smp.c

@@ -81,7 +81,7 @@ static void enable_local_vic_irq(unsigned int irq);
 static void disable_local_vic_irq(unsigned int irq);
 static void disable_local_vic_irq(unsigned int irq);
 static void before_handle_vic_irq(unsigned int irq);
 static void before_handle_vic_irq(unsigned int irq);
 static void after_handle_vic_irq(unsigned int irq);
 static void after_handle_vic_irq(unsigned int irq);
-static void set_vic_irq_affinity(unsigned int irq, cpumask_t mask);
+static void set_vic_irq_affinity(unsigned int irq, const struct cpumask *mask);
 static void ack_vic_irq(unsigned int irq);
 static void ack_vic_irq(unsigned int irq);
 static void vic_enable_cpi(void);
 static void vic_enable_cpi(void);
 static void do_boot_cpu(__u8 cpuid);
 static void do_boot_cpu(__u8 cpuid);
@@ -211,8 +211,6 @@ static __u32 cpu_booted_map;
 static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
 static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
 
 
 /* This is for the new dynamic CPU boot code */
 /* This is for the new dynamic CPU boot code */
-cpumask_t cpu_callin_map = CPU_MASK_NONE;
-cpumask_t cpu_callout_map = CPU_MASK_NONE;
 
 
 /* The per processor IRQ masks (these are usually kept in sync) */
 /* The per processor IRQ masks (these are usually kept in sync) */
 static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned;
 static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned;
@@ -378,7 +376,7 @@ void __init find_smp_config(void)
 	cpus_addr(phys_cpu_present_map)[0] |=
 	cpus_addr(phys_cpu_present_map)[0] |=
 	    voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK +
 	    voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK +
 				       3) << 24;
 				       3) << 24;
-	cpu_possible_map = phys_cpu_present_map;
+	init_cpu_possible(&phys_cpu_present_map);
 	printk("VOYAGER SMP: phys_cpu_present_map = 0x%lx\n",
 	printk("VOYAGER SMP: phys_cpu_present_map = 0x%lx\n",
 	       cpus_addr(phys_cpu_present_map)[0]);
 	       cpus_addr(phys_cpu_present_map)[0]);
 	/* Here we set up the VIC to enable SMP */
 	/* Here we set up the VIC to enable SMP */
@@ -1599,16 +1597,16 @@ static void after_handle_vic_irq(unsigned int irq)
  * change the mask and then do an interrupt enable CPI to re-enable on
  * change the mask and then do an interrupt enable CPI to re-enable on
  * the selected processors */
  * the selected processors */
 
 
-void set_vic_irq_affinity(unsigned int irq, cpumask_t mask)
+void set_vic_irq_affinity(unsigned int irq, const struct cpumask *mask)
 {
 {
 	/* Only extended processors handle interrupts */
 	/* Only extended processors handle interrupts */
 	unsigned long real_mask;
 	unsigned long real_mask;
 	unsigned long irq_mask = 1 << irq;
 	unsigned long irq_mask = 1 << irq;
 	int cpu;
 	int cpu;
 
 
-	real_mask = cpus_addr(mask)[0] & voyager_extended_vic_processors;
+	real_mask = cpus_addr(*mask)[0] & voyager_extended_vic_processors;
 
 
-	if (cpus_addr(mask)[0] == 0)
+	if (cpus_addr(*mask)[0] == 0)
 		/* can't have no CPUs to accept the interrupt -- extremely
 		/* can't have no CPUs to accept the interrupt -- extremely
 		 * bad things will happen */
 		 * bad things will happen */
 		return;
 		return;
@@ -1750,10 +1748,11 @@ static void __cpuinit voyager_smp_prepare_boot_cpu(void)
 	init_gdt(smp_processor_id());
 	init_gdt(smp_processor_id());
 	switch_to_new_gdt();
 	switch_to_new_gdt();
 
 
-	cpu_set(smp_processor_id(), cpu_online_map);
-	cpu_set(smp_processor_id(), cpu_callout_map);
-	cpu_set(smp_processor_id(), cpu_possible_map);
-	cpu_set(smp_processor_id(), cpu_present_map);
+	cpu_online_map = cpumask_of_cpu(smp_processor_id());
+	cpu_callout_map = cpumask_of_cpu(smp_processor_id());
+	cpu_callin_map = CPU_MASK_NONE;
+	cpu_present_map = cpumask_of_cpu(smp_processor_id());
+
 }
 }
 
 
 static int __cpuinit voyager_cpu_up(unsigned int cpu)
 static int __cpuinit voyager_cpu_up(unsigned int cpu)
@@ -1783,9 +1782,9 @@ void __init smp_setup_processor_id(void)
 	x86_write_percpu(cpu_number, hard_smp_processor_id());
 	x86_write_percpu(cpu_number, hard_smp_processor_id());
 }
 }
 
 
-static void voyager_send_call_func(cpumask_t callmask)
+static void voyager_send_call_func(const struct cpumask *callmask)
 {
 {
-	__u32 mask = cpus_addr(callmask)[0] & ~(1 << smp_processor_id());
+	__u32 mask = cpus_addr(*callmask)[0] & ~(1 << smp_processor_id());
 	send_CPI(mask, VIC_CALL_FUNCTION_CPI);
 	send_CPI(mask, VIC_CALL_FUNCTION_CPI);
 }
 }
 
 

+ 6 - 2
arch/x86/mm/fault.c

@@ -603,8 +603,6 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
 
 
 	si_code = SEGV_MAPERR;
 	si_code = SEGV_MAPERR;
 
 
-	if (notify_page_fault(regs))
-		return;
 	if (unlikely(kmmio_fault(regs, address)))
 	if (unlikely(kmmio_fault(regs, address)))
 		return;
 		return;
 
 
@@ -634,6 +632,9 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
 		if (spurious_fault(address, error_code))
 		if (spurious_fault(address, error_code))
 			return;
 			return;
 
 
+		/* kprobes don't want to hook the spurious faults. */
+		if (notify_page_fault(regs))
+			return;
 		/*
 		/*
 		 * Don't take the mm semaphore here. If we fixup a prefetch
 		 * Don't take the mm semaphore here. If we fixup a prefetch
 		 * fault we could otherwise deadlock.
 		 * fault we could otherwise deadlock.
@@ -641,6 +642,9 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
 		goto bad_area_nosemaphore;
 		goto bad_area_nosemaphore;
 	}
 	}
 
 
+	/* kprobes don't want to hook the spurious faults. */
+	if (notify_page_fault(regs))
+		return;
 
 
 	/*
 	/*
 	 * It's safe to allow irq's after cr2 has been saved and the
 	 * It's safe to allow irq's after cr2 has been saved and the

+ 3 - 1
arch/x86/xen/multicalls.h

@@ -19,8 +19,10 @@ DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags);
    paired with xen_mc_issue() */
    paired with xen_mc_issue() */
 static inline void xen_mc_batch(void)
 static inline void xen_mc_batch(void)
 {
 {
+	unsigned long flags;
 	/* need to disable interrupts until this entry is complete */
 	/* need to disable interrupts until this entry is complete */
-	local_irq_save(__get_cpu_var(xen_mc_irq_flags));
+	local_irq_save(flags);
+	__get_cpu_var(xen_mc_irq_flags) = flags;
 }
 }
 
 
 static inline struct multicall_space xen_mc_entry(size_t args)
 static inline struct multicall_space xen_mc_entry(size_t args)

+ 2 - 1
drivers/acpi/Kconfig

@@ -9,6 +9,7 @@ menuconfig ACPI
 	depends on PCI
 	depends on PCI
 	depends on PM
 	depends on PM
 	select PNP
 	select PNP
+	select CPU_IDLE
 	default y
 	default y
 	---help---
 	---help---
 	  Advanced Configuration and Power Interface (ACPI) support for 
 	  Advanced Configuration and Power Interface (ACPI) support for 
@@ -287,7 +288,7 @@ config ACPI_CONTAINER
 	  support physical cpu/memory hot-plug.
 	  support physical cpu/memory hot-plug.
 
 
 	  If one selects "m", this driver can be loaded with
 	  If one selects "m", this driver can be loaded with
-	  "modprobe acpi_container".
+	  "modprobe container".
 
 
 config ACPI_HOTPLUG_MEMORY
 config ACPI_HOTPLUG_MEMORY
 	tristate "Memory Hotplug"
 	tristate "Memory Hotplug"

+ 3 - 4
drivers/acpi/acpica/tbutils.c

@@ -538,10 +538,9 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
 			if (ACPI_FAILURE(status)) {
 			if (ACPI_FAILURE(status)) {
 				ACPI_WARNING((AE_INFO,
 				ACPI_WARNING((AE_INFO,
 					      "Truncating %u table entries!",
 					      "Truncating %u table entries!",
-					      (unsigned)
-					      (acpi_gbl_root_table_list.size -
-					       acpi_gbl_root_table_list.
-					       count)));
+					      (unsigned) (table_count -
+					       (acpi_gbl_root_table_list.
+					       count - 2))));
 				break;
 				break;
 			}
 			}
 		}
 		}

+ 9 - 12
drivers/acpi/acpica/uteval.c

@@ -116,9 +116,9 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
 		return_ACPI_STATUS(AE_NO_MEMORY);
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 	}
 
 
-	/* Default return value is SUPPORTED */
+	/* Default return value is 0, NOT-SUPPORTED */
 
 
-	return_desc->integer.value = ACPI_UINT32_MAX;
+	return_desc->integer.value = 0;
 	walk_state->return_desc = return_desc;
 	walk_state->return_desc = return_desc;
 
 
 	/* Compare input string to static table of supported interfaces */
 	/* Compare input string to static table of supported interfaces */
@@ -127,10 +127,8 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
 		if (!ACPI_STRCMP
 		if (!ACPI_STRCMP
 		    (string_desc->string.pointer,
 		    (string_desc->string.pointer,
 		     acpi_interfaces_supported[i])) {
 		     acpi_interfaces_supported[i])) {
-
-			/* The interface is supported */
-
-			return_ACPI_STATUS(AE_OK);
+			return_desc->integer.value = ACPI_UINT32_MAX;
+			goto done;
 		}
 		}
 	}
 	}
 
 
@@ -141,15 +139,14 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
 	 */
 	 */
 	status = acpi_os_validate_interface(string_desc->string.pointer);
 	status = acpi_os_validate_interface(string_desc->string.pointer);
 	if (ACPI_SUCCESS(status)) {
 	if (ACPI_SUCCESS(status)) {
-
-		/* The interface is supported */
-
-		return_ACPI_STATUS(AE_OK);
+		return_desc->integer.value = ACPI_UINT32_MAX;
 	}
 	}
 
 
-	/* The interface is not supported */
+done:
+	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, "ACPI: BIOS _OSI(%s) %ssupported\n",
+		string_desc->string.pointer,
+		return_desc->integer.value == 0 ? "not-" : ""));
 
 
-	return_desc->integer.value = 0;
 	return_ACPI_STATUS(AE_OK);
 	return_ACPI_STATUS(AE_OK);
 }
 }
 
 

+ 3 - 2
drivers/acpi/container.c

@@ -163,7 +163,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
 	case ACPI_NOTIFY_BUS_CHECK:
 	case ACPI_NOTIFY_BUS_CHECK:
 		/* Fall through */
 		/* Fall through */
 	case ACPI_NOTIFY_DEVICE_CHECK:
 	case ACPI_NOTIFY_DEVICE_CHECK:
-		printk("Container driver received %s event\n",
+		printk(KERN_WARNING "Container driver received %s event\n",
 		       (type == ACPI_NOTIFY_BUS_CHECK) ?
 		       (type == ACPI_NOTIFY_BUS_CHECK) ?
 		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
 		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
 		status = acpi_bus_get_device(handle, &device);
 		status = acpi_bus_get_device(handle, &device);
@@ -174,7 +174,8 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
 					kobject_uevent(&device->dev.kobj,
 					kobject_uevent(&device->dev.kobj,
 						       KOBJ_ONLINE);
 						       KOBJ_ONLINE);
 				else
 				else
-					printk("Failed to add container\n");
+					printk(KERN_WARNING
+					       "Failed to add container\n");
 			}
 			}
 		} else {
 		} else {
 			if (ACPI_SUCCESS(status)) {
 			if (ACPI_SUCCESS(status)) {

+ 9 - 5
drivers/acpi/dock.c

@@ -855,10 +855,14 @@ fdd_out:
 static ssize_t show_docked(struct device *dev,
 static ssize_t show_docked(struct device *dev,
 			   struct device_attribute *attr, char *buf)
 			   struct device_attribute *attr, char *buf)
 {
 {
+	struct acpi_device *tmp;
+
 	struct dock_station *dock_station = *((struct dock_station **)
 	struct dock_station *dock_station = *((struct dock_station **)
 		dev->platform_data);
 		dev->platform_data);
-	return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
 
 
+	if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp)))
+		return snprintf(buf, PAGE_SIZE, "1\n");
+	return snprintf(buf, PAGE_SIZE, "0\n");
 }
 }
 static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
 static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
 
 
@@ -984,7 +988,7 @@ static int dock_add(acpi_handle handle)
 
 
 	ret = device_create_file(&dock_device->dev, &dev_attr_docked);
 	ret = device_create_file(&dock_device->dev, &dev_attr_docked);
 	if (ret) {
 	if (ret) {
-		printk("Error %d adding sysfs file\n", ret);
+		printk(KERN_ERR "Error %d adding sysfs file\n", ret);
 		platform_device_unregister(dock_device);
 		platform_device_unregister(dock_device);
 		kfree(dock_station);
 		kfree(dock_station);
 		dock_station = NULL;
 		dock_station = NULL;
@@ -992,7 +996,7 @@ static int dock_add(acpi_handle handle)
 	}
 	}
 	ret = device_create_file(&dock_device->dev, &dev_attr_undock);
 	ret = device_create_file(&dock_device->dev, &dev_attr_undock);
 	if (ret) {
 	if (ret) {
-		printk("Error %d adding sysfs file\n", ret);
+		printk(KERN_ERR "Error %d adding sysfs file\n", ret);
 		device_remove_file(&dock_device->dev, &dev_attr_docked);
 		device_remove_file(&dock_device->dev, &dev_attr_docked);
 		platform_device_unregister(dock_device);
 		platform_device_unregister(dock_device);
 		kfree(dock_station);
 		kfree(dock_station);
@@ -1001,7 +1005,7 @@ static int dock_add(acpi_handle handle)
 	}
 	}
 	ret = device_create_file(&dock_device->dev, &dev_attr_uid);
 	ret = device_create_file(&dock_device->dev, &dev_attr_uid);
 	if (ret) {
 	if (ret) {
-		printk("Error %d adding sysfs file\n", ret);
+		printk(KERN_ERR "Error %d adding sysfs file\n", ret);
 		device_remove_file(&dock_device->dev, &dev_attr_docked);
 		device_remove_file(&dock_device->dev, &dev_attr_docked);
 		device_remove_file(&dock_device->dev, &dev_attr_undock);
 		device_remove_file(&dock_device->dev, &dev_attr_undock);
 		platform_device_unregister(dock_device);
 		platform_device_unregister(dock_device);
@@ -1011,7 +1015,7 @@ static int dock_add(acpi_handle handle)
 	}
 	}
 	ret = device_create_file(&dock_device->dev, &dev_attr_flags);
 	ret = device_create_file(&dock_device->dev, &dev_attr_flags);
 	if (ret) {
 	if (ret) {
-		printk("Error %d adding sysfs file\n", ret);
+		printk(KERN_ERR "Error %d adding sysfs file\n", ret);
 		device_remove_file(&dock_device->dev, &dev_attr_docked);
 		device_remove_file(&dock_device->dev, &dev_attr_docked);
 		device_remove_file(&dock_device->dev, &dev_attr_undock);
 		device_remove_file(&dock_device->dev, &dev_attr_undock);
 		device_remove_file(&dock_device->dev, &dev_attr_uid);
 		device_remove_file(&dock_device->dev, &dev_attr_uid);

+ 1 - 1
drivers/acpi/ec.c

@@ -982,7 +982,7 @@ int __init acpi_ec_ecdt_probe(void)
 		saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
 		saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
 		if (!saved_ec)
 		if (!saved_ec)
 			return -ENOMEM;
 			return -ENOMEM;
-		memcpy(&saved_ec, boot_ec, sizeof(saved_ec));
+		memcpy(saved_ec, boot_ec, sizeof(*saved_ec));
 	/* fall through */
 	/* fall through */
 	}
 	}
 	/* This workaround is needed only on some broken machines,
 	/* This workaround is needed only on some broken machines,

+ 4 - 4
drivers/acpi/glue.c

@@ -255,12 +255,12 @@ static int acpi_platform_notify(struct device *dev)
 	}
 	}
 	type = acpi_get_bus_type(dev->bus);
 	type = acpi_get_bus_type(dev->bus);
 	if (!type) {
 	if (!type) {
-		DBG("No ACPI bus support for %s\n", dev->bus_id);
+		DBG("No ACPI bus support for %s\n", dev_name(dev));
 		ret = -EINVAL;
 		ret = -EINVAL;
 		goto end;
 		goto end;
 	}
 	}
 	if ((ret = type->find_device(dev, &handle)) != 0)
 	if ((ret = type->find_device(dev, &handle)) != 0)
-		DBG("Can't get handler for %s\n", dev->bus_id);
+		DBG("Can't get handler for %s\n", dev_name(dev));
       end:
       end:
 	if (!ret)
 	if (!ret)
 		acpi_bind_one(dev, handle);
 		acpi_bind_one(dev, handle);
@@ -271,10 +271,10 @@ static int acpi_platform_notify(struct device *dev)
 
 
 		acpi_get_name(dev->archdata.acpi_handle,
 		acpi_get_name(dev->archdata.acpi_handle,
 			      ACPI_FULL_PATHNAME, &buffer);
 			      ACPI_FULL_PATHNAME, &buffer);
-		DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer);
+		DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer);
 		kfree(buffer.pointer);
 		kfree(buffer.pointer);
 	} else
 	} else
-		DBG("Device %s -> No ACPI support\n", dev->bus_id);
+		DBG("Device %s -> No ACPI support\n", dev_name(dev));
 #endif
 #endif
 
 
 	return ret;
 	return ret;

+ 52 - 2
drivers/acpi/osl.c

@@ -228,10 +228,10 @@ void acpi_os_vprintf(const char *fmt, va_list args)
 	if (acpi_in_debugger) {
 	if (acpi_in_debugger) {
 		kdb_printf("%s", buffer);
 		kdb_printf("%s", buffer);
 	} else {
 	} else {
-		printk("%s", buffer);
+		printk(KERN_CONT "%s", buffer);
 	}
 	}
 #else
 #else
-	printk("%s", buffer);
+	printk(KERN_CONT "%s", buffer);
 #endif
 #endif
 }
 }
 
 
@@ -1317,6 +1317,54 @@ acpi_os_validate_interface (char *interface)
 	return AE_SUPPORT;
 	return AE_SUPPORT;
 }
 }
 
 
+#ifdef	CONFIG_X86
+
+struct aml_port_desc {
+	uint	start;
+	uint	end;
+	char*   name;
+	char	warned;
+};
+
+static struct aml_port_desc aml_invalid_port_list[] = {
+	{0x20, 0x21, "PIC0", 0},
+	{0xA0, 0xA1, "PIC1", 0},
+	{0x4D0, 0x4D1, "ELCR", 0}
+};
+
+/*
+ * valid_aml_io_address()
+ *
+ * if valid, return true
+ * else invalid, warn once, return false
+ */
+static bool valid_aml_io_address(uint address, uint length)
+{
+	int i;
+	int entries = sizeof(aml_invalid_port_list) / sizeof(struct aml_port_desc);
+
+	for (i = 0; i < entries; ++i) {
+		if ((address >= aml_invalid_port_list[i].start &&
+			address <= aml_invalid_port_list[i].end) ||
+			(address + length >= aml_invalid_port_list[i].start &&
+			address  + length <= aml_invalid_port_list[i].end))
+		{
+			if (!aml_invalid_port_list[i].warned)
+			{
+				printk(KERN_ERR "ACPI: Denied BIOS AML access"
+					" to invalid port 0x%x+0x%x (%s)\n",
+					address, length,
+					aml_invalid_port_list[i].name);
+				aml_invalid_port_list[i].warned = 1;
+			}
+			return false;	/* invalid */
+		}
+	}
+	return true;	/* valid */
+}
+#else
+static inline bool valid_aml_io_address(uint address, uint length) { return true; }
+#endif
 /******************************************************************************
 /******************************************************************************
  *
  *
  * FUNCTION:    acpi_os_validate_address
  * FUNCTION:    acpi_os_validate_address
@@ -1346,6 +1394,8 @@ acpi_os_validate_address (
 
 
 	switch (space_id) {
 	switch (space_id) {
 	case ACPI_ADR_SPACE_SYSTEM_IO:
 	case ACPI_ADR_SPACE_SYSTEM_IO:
+		if (!valid_aml_io_address(address, length))
+			return AE_AML_ILLEGAL_ADDRESS;
 	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
 	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
 		/* Only interference checks against SystemIO and SytemMemory
 		/* Only interference checks against SystemIO and SytemMemory
 		   are needed */
 		   are needed */

+ 1 - 1
drivers/acpi/pci_link.c

@@ -593,7 +593,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
 		return -ENODEV;
 		return -ENODEV;
 	} else {
 	} else {
 		acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
 		acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
-		printk(PREFIX "%s [%s] enabled at IRQ %d\n",
+		printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
 		       acpi_device_name(link->device),
 		       acpi_device_name(link->device),
 		       acpi_device_bid(link->device), link->irq.active);
 		       acpi_device_bid(link->device), link->irq.active);
 	}
 	}

+ 10 - 657
drivers/acpi/processor_idle.c

@@ -66,43 +66,17 @@ ACPI_MODULE_NAME("processor_idle");
 #define ACPI_PROCESSOR_FILE_POWER	"power"
 #define ACPI_PROCESSOR_FILE_POWER	"power"
 #define US_TO_PM_TIMER_TICKS(t)		((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
 #define US_TO_PM_TIMER_TICKS(t)		((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
 #define PM_TIMER_TICK_NS		(1000000000ULL/PM_TIMER_FREQUENCY)
 #define PM_TIMER_TICK_NS		(1000000000ULL/PM_TIMER_FREQUENCY)
-#ifndef CONFIG_CPU_IDLE
-#define C2_OVERHEAD			4	/* 1us (3.579 ticks per us) */
-#define C3_OVERHEAD			4	/* 1us (3.579 ticks per us) */
-static void (*pm_idle_save) (void) __read_mostly;
-#else
 #define C2_OVERHEAD			1	/* 1us */
 #define C2_OVERHEAD			1	/* 1us */
 #define C3_OVERHEAD			1	/* 1us */
 #define C3_OVERHEAD			1	/* 1us */
-#endif
 #define PM_TIMER_TICKS_TO_US(p)		(((p) * 1000)/(PM_TIMER_FREQUENCY/1000))
 #define PM_TIMER_TICKS_TO_US(p)		(((p) * 1000)/(PM_TIMER_FREQUENCY/1000))
 
 
 static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;
 static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;
-#ifdef CONFIG_CPU_IDLE
 module_param(max_cstate, uint, 0000);
 module_param(max_cstate, uint, 0000);
-#else
-module_param(max_cstate, uint, 0644);
-#endif
 static unsigned int nocst __read_mostly;
 static unsigned int nocst __read_mostly;
 module_param(nocst, uint, 0000);
 module_param(nocst, uint, 0000);
 
 
-#ifndef CONFIG_CPU_IDLE
-/*
- * bm_history -- bit-mask with a bit per jiffy of bus-master activity
- * 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms
- * 800 HZ: 0xFFFFFFFF: 32 jiffies = 40ms
- * 100 HZ: 0x0000000F: 4 jiffies = 40ms
- * reduce history for more aggressive entry into C3
- */
-static unsigned int bm_history __read_mostly =
-    (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
-module_param(bm_history, uint, 0644);
-
-static int acpi_processor_set_power_policy(struct acpi_processor *pr);
-
-#else	/* CONFIG_CPU_IDLE */
 static unsigned int latency_factor __read_mostly = 2;
 static unsigned int latency_factor __read_mostly = 2;
 module_param(latency_factor, uint, 0644);
 module_param(latency_factor, uint, 0644);
-#endif
 
 
 /*
 /*
  * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
  * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
@@ -224,71 +198,6 @@ static void acpi_safe_halt(void)
 	current_thread_info()->status |= TS_POLLING;
 	current_thread_info()->status |= TS_POLLING;
 }
 }
 
 
-#ifndef CONFIG_CPU_IDLE
-
-static void
-acpi_processor_power_activate(struct acpi_processor *pr,
-			      struct acpi_processor_cx *new)
-{
-	struct acpi_processor_cx *old;
-
-	if (!pr || !new)
-		return;
-
-	old = pr->power.state;
-
-	if (old)
-		old->promotion.count = 0;
-	new->demotion.count = 0;
-
-	/* Cleanup from old state. */
-	if (old) {
-		switch (old->type) {
-		case ACPI_STATE_C3:
-			/* Disable bus master reload */
-			if (new->type != ACPI_STATE_C3 && pr->flags.bm_check)
-				acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
-			break;
-		}
-	}
-
-	/* Prepare to use new state. */
-	switch (new->type) {
-	case ACPI_STATE_C3:
-		/* Enable bus master reload */
-		if (old->type != ACPI_STATE_C3 && pr->flags.bm_check)
-			acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
-		break;
-	}
-
-	pr->power.state = new;
-
-	return;
-}
-
-static atomic_t c3_cpu_count;
-
-/* Common C-state entry for C2, C3, .. */
-static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
-{
-	/* Don't trace irqs off for idle */
-	stop_critical_timings();
-	if (cstate->entry_method == ACPI_CSTATE_FFH) {
-		/* Call into architectural FFH based C-state */
-		acpi_processor_ffh_cstate_enter(cstate);
-	} else {
-		int unused;
-		/* IO port based C-state */
-		inb(cstate->address);
-		/* Dummy wait op - must do something useless after P_LVL2 read
-		   because chipsets cannot guarantee that STPCLK# signal
-		   gets asserted in time to freeze execution properly. */
-		unused = inl(acpi_gbl_FADT.xpm_timer_block.address);
-	}
-	start_critical_timings();
-}
-#endif /* !CONFIG_CPU_IDLE */
-
 #ifdef ARCH_APICTIMER_STOPS_ON_C3
 #ifdef ARCH_APICTIMER_STOPS_ON_C3
 
 
 /*
 /*
@@ -390,421 +299,6 @@ static int tsc_halts_in_c(int state)
 }
 }
 #endif
 #endif
 
 
-#ifndef CONFIG_CPU_IDLE
-static void acpi_processor_idle(void)
-{
-	struct acpi_processor *pr = NULL;
-	struct acpi_processor_cx *cx = NULL;
-	struct acpi_processor_cx *next_state = NULL;
-	int sleep_ticks = 0;
-	u32 t1, t2 = 0;
-
-	/*
-	 * Interrupts must be disabled during bus mastering calculations and
-	 * for C2/C3 transitions.
-	 */
-	local_irq_disable();
-
-	pr = __get_cpu_var(processors);
-	if (!pr) {
-		local_irq_enable();
-		return;
-	}
-
-	/*
-	 * Check whether we truly need to go idle, or should
-	 * reschedule:
-	 */
-	if (unlikely(need_resched())) {
-		local_irq_enable();
-		return;
-	}
-
-	cx = pr->power.state;
-	if (!cx || acpi_idle_suspend) {
-		if (pm_idle_save) {
-			pm_idle_save(); /* enables IRQs */
-		} else {
-			acpi_safe_halt();
-			local_irq_enable();
-		}
-
-		return;
-	}
-
-	/*
-	 * Check BM Activity
-	 * -----------------
-	 * Check for bus mastering activity (if required), record, and check
-	 * for demotion.
-	 */
-	if (pr->flags.bm_check) {
-		u32 bm_status = 0;
-		unsigned long diff = jiffies - pr->power.bm_check_timestamp;
-
-		if (diff > 31)
-			diff = 31;
-
-		pr->power.bm_activity <<= diff;
-
-		acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
-		if (bm_status) {
-			pr->power.bm_activity |= 0x1;
-			acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
-		}
-		/*
-		 * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
-		 * the true state of bus mastering activity; forcing us to
-		 * manually check the BMIDEA bit of each IDE channel.
-		 */
-		else if (errata.piix4.bmisx) {
-			if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01)
-			    || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
-				pr->power.bm_activity |= 0x1;
-		}
-
-		pr->power.bm_check_timestamp = jiffies;
-
-		/*
-		 * If bus mastering is or was active this jiffy, demote
-		 * to avoid a faulty transition.  Note that the processor
-		 * won't enter a low-power state during this call (to this
-		 * function) but should upon the next.
-		 *
-		 * TBD: A better policy might be to fallback to the demotion
-		 *      state (use it for this quantum only) istead of
-		 *      demoting -- and rely on duration as our sole demotion
-		 *      qualification.  This may, however, introduce DMA
-		 *      issues (e.g. floppy DMA transfer overrun/underrun).
-		 */
-		if ((pr->power.bm_activity & 0x1) &&
-		    cx->demotion.threshold.bm) {
-			local_irq_enable();
-			next_state = cx->demotion.state;
-			goto end;
-		}
-	}
-
-#ifdef CONFIG_HOTPLUG_CPU
-	/*
-	 * Check for P_LVL2_UP flag before entering C2 and above on
-	 * an SMP system. We do it here instead of doing it at _CST/P_LVL
-	 * detection phase, to work cleanly with logical CPU hotplug.
-	 */
-	if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
-	    !pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
-		cx = &pr->power.states[ACPI_STATE_C1];
-#endif
-
-	/*
-	 * Sleep:
-	 * ------
-	 * Invoke the current Cx state to put the processor to sleep.
-	 */
-	if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) {
-		current_thread_info()->status &= ~TS_POLLING;
-		/*
-		 * TS_POLLING-cleared state must be visible before we
-		 * test NEED_RESCHED:
-		 */
-		smp_mb();
-		if (need_resched()) {
-			current_thread_info()->status |= TS_POLLING;
-			local_irq_enable();
-			return;
-		}
-	}
-
-	switch (cx->type) {
-
-	case ACPI_STATE_C1:
-		/*
-		 * Invoke C1.
-		 * Use the appropriate idle routine, the one that would
-		 * be used without acpi C-states.
-		 */
-		if (pm_idle_save) {
-			pm_idle_save(); /* enables IRQs */
-		} else {
-			acpi_safe_halt();
-			local_irq_enable();
-		}
-
-		/*
-		 * TBD: Can't get time duration while in C1, as resumes
-		 *      go to an ISR rather than here.  Need to instrument
-		 *      base interrupt handler.
-		 *
-		 * Note: the TSC better not stop in C1, sched_clock() will
-		 *       skew otherwise.
-		 */
-		sleep_ticks = 0xFFFFFFFF;
-
-		break;
-
-	case ACPI_STATE_C2:
-		/* Get start time (ticks) */
-		t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
-		/* Tell the scheduler that we are going deep-idle: */
-		sched_clock_idle_sleep_event();
-		/* Invoke C2 */
-		acpi_state_timer_broadcast(pr, cx, 1);
-		acpi_cstate_enter(cx);
-		/* Get end time (ticks) */
-		t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
-
-#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
-		/* TSC halts in C2, so notify users */
-		if (tsc_halts_in_c(ACPI_STATE_C2))
-			mark_tsc_unstable("possible TSC halt in C2");
-#endif
-		/* Compute time (ticks) that we were actually asleep */
-		sleep_ticks = ticks_elapsed(t1, t2);
-
-		/* Tell the scheduler how much we idled: */
-		sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
-
-		/* Re-enable interrupts */
-		local_irq_enable();
-		/* Do not account our idle-switching overhead: */
-		sleep_ticks -= cx->latency_ticks + C2_OVERHEAD;
-
-		current_thread_info()->status |= TS_POLLING;
-		acpi_state_timer_broadcast(pr, cx, 0);
-		break;
-
-	case ACPI_STATE_C3:
-		acpi_unlazy_tlb(smp_processor_id());
-		/*
-		 * Must be done before busmaster disable as we might
-		 * need to access HPET !
-		 */
-		acpi_state_timer_broadcast(pr, cx, 1);
-		/*
-		 * disable bus master
-		 * bm_check implies we need ARB_DIS
-		 * !bm_check implies we need cache flush
-		 * bm_control implies whether we can do ARB_DIS
-		 *
-		 * That leaves a case where bm_check is set and bm_control is
-		 * not set. In that case we cannot do much, we enter C3
-		 * without doing anything.
-		 */
-		if (pr->flags.bm_check && pr->flags.bm_control) {
-			if (atomic_inc_return(&c3_cpu_count) ==
-			    num_online_cpus()) {
-				/*
-				 * All CPUs are trying to go to C3
-				 * Disable bus master arbitration
-				 */
-				acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
-			}
-		} else if (!pr->flags.bm_check) {
-			/* SMP with no shared cache... Invalidate cache  */
-			ACPI_FLUSH_CPU_CACHE();
-		}
-
-		/* Get start time (ticks) */
-		t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
-		/* Invoke C3 */
-		/* Tell the scheduler that we are going deep-idle: */
-		sched_clock_idle_sleep_event();
-		acpi_cstate_enter(cx);
-		/* Get end time (ticks) */
-		t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
-		if (pr->flags.bm_check && pr->flags.bm_control) {
-			/* Enable bus master arbitration */
-			atomic_dec(&c3_cpu_count);
-			acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
-		}
-
-#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
-		/* TSC halts in C3, so notify users */
-		if (tsc_halts_in_c(ACPI_STATE_C3))
-			mark_tsc_unstable("TSC halts in C3");
-#endif
-		/* Compute time (ticks) that we were actually asleep */
-		sleep_ticks = ticks_elapsed(t1, t2);
-		/* Tell the scheduler how much we idled: */
-		sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
-
-		/* Re-enable interrupts */
-		local_irq_enable();
-		/* Do not account our idle-switching overhead: */
-		sleep_ticks -= cx->latency_ticks + C3_OVERHEAD;
-
-		current_thread_info()->status |= TS_POLLING;
-		acpi_state_timer_broadcast(pr, cx, 0);
-		break;
-
-	default:
-		local_irq_enable();
-		return;
-	}
-	cx->usage++;
-	if ((cx->type != ACPI_STATE_C1) && (sleep_ticks > 0))
-		cx->time += sleep_ticks;
-
-	next_state = pr->power.state;
-
-#ifdef CONFIG_HOTPLUG_CPU
-	/* Don't do promotion/demotion */
-	if ((cx->type == ACPI_STATE_C1) && (num_online_cpus() > 1) &&
-	    !pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) {
-		next_state = cx;
-		goto end;
-	}
-#endif
-
-	/*
-	 * Promotion?
-	 * ----------
-	 * Track the number of longs (time asleep is greater than threshold)
-	 * and promote when the count threshold is reached.  Note that bus
-	 * mastering activity may prevent promotions.
-	 * Do not promote above max_cstate.
-	 */
-	if (cx->promotion.state &&
-	    ((cx->promotion.state - pr->power.states) <= max_cstate)) {
-		if (sleep_ticks > cx->promotion.threshold.ticks &&
-		  cx->promotion.state->latency <=
-				pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) {
-			cx->promotion.count++;
-			cx->demotion.count = 0;
-			if (cx->promotion.count >=
-			    cx->promotion.threshold.count) {
-				if (pr->flags.bm_check) {
-					if (!
-					    (pr->power.bm_activity & cx->
-					     promotion.threshold.bm)) {
-						next_state =
-						    cx->promotion.state;
-						goto end;
-					}
-				} else {
-					next_state = cx->promotion.state;
-					goto end;
-				}
-			}
-		}
-	}
-
-	/*
-	 * Demotion?
-	 * ---------
-	 * Track the number of shorts (time asleep is less than time threshold)
-	 * and demote when the usage threshold is reached.
-	 */
-	if (cx->demotion.state) {
-		if (sleep_ticks < cx->demotion.threshold.ticks) {
-			cx->demotion.count++;
-			cx->promotion.count = 0;
-			if (cx->demotion.count >= cx->demotion.threshold.count) {
-				next_state = cx->demotion.state;
-				goto end;
-			}
-		}
-	}
-
-      end:
-	/*
-	 * Demote if current state exceeds max_cstate
-	 * or if the latency of the current state is unacceptable
-	 */
-	if ((pr->power.state - pr->power.states) > max_cstate ||
-		pr->power.state->latency >
-				pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) {
-		if (cx->demotion.state)
-			next_state = cx->demotion.state;
-	}
-
-	/*
-	 * New Cx State?
-	 * -------------
-	 * If we're going to start using a new Cx state we must clean up
-	 * from the previous and prepare to use the new.
-	 */
-	if (next_state != pr->power.state)
-		acpi_processor_power_activate(pr, next_state);
-}
-
-static int acpi_processor_set_power_policy(struct acpi_processor *pr)
-{
-	unsigned int i;
-	unsigned int state_is_set = 0;
-	struct acpi_processor_cx *lower = NULL;
-	struct acpi_processor_cx *higher = NULL;
-	struct acpi_processor_cx *cx;
-
-
-	if (!pr)
-		return -EINVAL;
-
-	/*
-	 * This function sets the default Cx state policy (OS idle handler).
-	 * Our scheme is to promote quickly to C2 but more conservatively
-	 * to C3.  We're favoring C2  for its characteristics of low latency
-	 * (quick response), good power savings, and ability to allow bus
-	 * mastering activity.  Note that the Cx state policy is completely
-	 * customizable and can be altered dynamically.
-	 */
-
-	/* startup state */
-	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
-		cx = &pr->power.states[i];
-		if (!cx->valid)
-			continue;
-
-		if (!state_is_set)
-			pr->power.state = cx;
-		state_is_set++;
-		break;
-	}
-
-	if (!state_is_set)
-		return -ENODEV;
-
-	/* demotion */
-	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
-		cx = &pr->power.states[i];
-		if (!cx->valid)
-			continue;
-
-		if (lower) {
-			cx->demotion.state = lower;
-			cx->demotion.threshold.ticks = cx->latency_ticks;
-			cx->demotion.threshold.count = 1;
-			if (cx->type == ACPI_STATE_C3)
-				cx->demotion.threshold.bm = bm_history;
-		}
-
-		lower = cx;
-	}
-
-	/* promotion */
-	for (i = (ACPI_PROCESSOR_MAX_POWER - 1); i > 0; i--) {
-		cx = &pr->power.states[i];
-		if (!cx->valid)
-			continue;
-
-		if (higher) {
-			cx->promotion.state = higher;
-			cx->promotion.threshold.ticks = cx->latency_ticks;
-			if (cx->type >= ACPI_STATE_C2)
-				cx->promotion.threshold.count = 4;
-			else
-				cx->promotion.threshold.count = 10;
-			if (higher->type == ACPI_STATE_C3)
-				cx->promotion.threshold.bm = bm_history;
-		}
-
-		higher = cx;
-	}
-
-	return 0;
-}
-#endif /* !CONFIG_CPU_IDLE */
-
 static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
 static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
 {
 {
 
 
@@ -1047,11 +541,7 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
 	 */
 	 */
 	cx->valid = 1;
 	cx->valid = 1;
 
 
-#ifndef CONFIG_CPU_IDLE
-	cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
-#else
 	cx->latency_ticks = cx->latency;
 	cx->latency_ticks = cx->latency;
-#endif
 
 
 	return;
 	return;
 }
 }
@@ -1121,7 +611,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
 					  " for C3 to be enabled on SMP systems\n"));
 					  " for C3 to be enabled on SMP systems\n"));
 			return;
 			return;
 		}
 		}
-		acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
 	}
 	}
 
 
 	/*
 	/*
@@ -1132,11 +621,16 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
 	 */
 	 */
 	cx->valid = 1;
 	cx->valid = 1;
 
 
-#ifndef CONFIG_CPU_IDLE
-	cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
-#else
 	cx->latency_ticks = cx->latency;
 	cx->latency_ticks = cx->latency;
-#endif
+	/*
+	 * On older chipsets, BM_RLD needs to be set
+	 * in order for Bus Master activity to wake the
+	 * system from C3.  Newer chipsets handle DMA
+	 * during C3 automatically and BM_RLD is a NOP.
+	 * In either case, the proper way to
+	 * handle BM_RLD is to set it and leave it set.
+	 */
+	acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
 
 
 	return;
 	return;
 }
 }
@@ -1201,20 +695,6 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
 
 
 	pr->power.count = acpi_processor_power_verify(pr);
 	pr->power.count = acpi_processor_power_verify(pr);
 
 
-#ifndef CONFIG_CPU_IDLE
-	/*
-	 * Set Default Policy
-	 * ------------------
-	 * Now that we know which states are supported, set the default
-	 * policy.  Note that this policy can be changed dynamically
-	 * (e.g. encourage deeper sleeps to conserve battery life when
-	 * not on AC).
-	 */
-	result = acpi_processor_set_power_policy(pr);
-	if (result)
-		return result;
-#endif
-
 	/*
 	/*
 	 * if one state of type C2 or C3 is available, mark this
 	 * if one state of type C2 or C3 is available, mark this
 	 * CPU as being "idle manageable"
 	 * CPU as being "idle manageable"
@@ -1312,69 +792,6 @@ static const struct file_operations acpi_processor_power_fops = {
 	.release = single_release,
 	.release = single_release,
 };
 };
 
 
-#ifndef CONFIG_CPU_IDLE
-
-int acpi_processor_cst_has_changed(struct acpi_processor *pr)
-{
-	int result = 0;
-
-	if (boot_option_idle_override)
-		return 0;
-
-	if (!pr)
-		return -EINVAL;
-
-	if (nocst) {
-		return -ENODEV;
-	}
-
-	if (!pr->flags.power_setup_done)
-		return -ENODEV;
-
-	/*
-	 * Fall back to the default idle loop, when pm_idle_save had
-	 * been initialized.
-	 */
-	if (pm_idle_save) {
-		pm_idle = pm_idle_save;
-		/* Relies on interrupts forcing exit from idle. */
-		synchronize_sched();
-	}
-
-	pr->flags.power = 0;
-	result = acpi_processor_get_power_info(pr);
-	if ((pr->flags.power == 1) && (pr->flags.power_setup_done))
-		pm_idle = acpi_processor_idle;
-
-	return result;
-}
-
-#ifdef CONFIG_SMP
-static void smp_callback(void *v)
-{
-	/* we already woke the CPU up, nothing more to do */
-}
-
-/*
- * This function gets called when a part of the kernel has a new latency
- * requirement.  This means we need to get all processors out of their C-state,
- * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that
- * wakes them all right up.
- */
-static int acpi_processor_latency_notify(struct notifier_block *b,
-		unsigned long l, void *v)
-{
-	smp_call_function(smp_callback, NULL, 1);
-	return NOTIFY_OK;
-}
-
-static struct notifier_block acpi_processor_latency_notifier = {
-	.notifier_call = acpi_processor_latency_notify,
-};
-
-#endif
-
-#else /* CONFIG_CPU_IDLE */
 
 
 /**
 /**
  * acpi_idle_bm_check - checks if bus master activity was detected
  * acpi_idle_bm_check - checks if bus master activity was detected
@@ -1383,7 +800,7 @@ static int acpi_idle_bm_check(void)
 {
 {
 	u32 bm_status = 0;
 	u32 bm_status = 0;
 
 
-	acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
+	acpi_get_register_unlocked(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
 	if (bm_status)
 	if (bm_status)
 		acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
 		acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
 	/*
 	/*
@@ -1399,25 +816,6 @@ static int acpi_idle_bm_check(void)
 	return bm_status;
 	return bm_status;
 }
 }
 
 
-/**
- * acpi_idle_update_bm_rld - updates the BM_RLD bit depending on target state
- * @pr: the processor
- * @target: the new target state
- */
-static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr,
-					   struct acpi_processor_cx *target)
-{
-	if (pr->flags.bm_rld_set && target->type != ACPI_STATE_C3) {
-		acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
-		pr->flags.bm_rld_set = 0;
-	}
-
-	if (!pr->flags.bm_rld_set && target->type == ACPI_STATE_C3) {
-		acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
-		pr->flags.bm_rld_set = 1;
-	}
-}
-
 /**
 /**
  * acpi_idle_do_entry - a helper function that does C2 and C3 type entry
  * acpi_idle_do_entry - a helper function that does C2 and C3 type entry
  * @cx: cstate data
  * @cx: cstate data
@@ -1473,9 +871,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
 		return 0;
 		return 0;
 	}
 	}
 
 
-	if (pr->flags.bm_check)
-		acpi_idle_update_bm_rld(pr, cx);
-
 	t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
 	t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
 	acpi_idle_do_entry(cx);
 	acpi_idle_do_entry(cx);
 	t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
 	t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
@@ -1527,9 +922,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 	 */
 	 */
 	acpi_state_timer_broadcast(pr, cx, 1);
 	acpi_state_timer_broadcast(pr, cx, 1);
 
 
-	if (pr->flags.bm_check)
-		acpi_idle_update_bm_rld(pr, cx);
-
 	if (cx->type == ACPI_STATE_C3)
 	if (cx->type == ACPI_STATE_C3)
 		ACPI_FLUSH_CPU_CACHE();
 		ACPI_FLUSH_CPU_CACHE();
 
 
@@ -1621,8 +1013,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 	 */
 	 */
 	acpi_state_timer_broadcast(pr, cx, 1);
 	acpi_state_timer_broadcast(pr, cx, 1);
 
 
-	acpi_idle_update_bm_rld(pr, cx);
-
 	/*
 	/*
 	 * disable bus master
 	 * disable bus master
 	 * bm_check implies we need ARB_DIS
 	 * bm_check implies we need ARB_DIS
@@ -1795,8 +1185,6 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
 	return ret;
 	return ret;
 }
 }
 
 
-#endif /* CONFIG_CPU_IDLE */
-
 int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
 int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
 			      struct acpi_device *device)
 			      struct acpi_device *device)
 {
 {
@@ -1825,10 +1213,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
 			       "ACPI: processor limited to max C-state %d\n",
 			       "ACPI: processor limited to max C-state %d\n",
 			       max_cstate);
 			       max_cstate);
 		first_run++;
 		first_run++;
-#if !defined(CONFIG_CPU_IDLE) && defined(CONFIG_SMP)
-		pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY,
-				&acpi_processor_latency_notifier);
-#endif
 	}
 	}
 
 
 	if (!pr)
 	if (!pr)
@@ -1852,11 +1236,9 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
 	 * platforms that only support C1.
 	 * platforms that only support C1.
 	 */
 	 */
 	if (pr->flags.power) {
 	if (pr->flags.power) {
-#ifdef CONFIG_CPU_IDLE
 		acpi_processor_setup_cpuidle(pr);
 		acpi_processor_setup_cpuidle(pr);
 		if (cpuidle_register_device(&pr->power.dev))
 		if (cpuidle_register_device(&pr->power.dev))
 			return -EIO;
 			return -EIO;
-#endif
 
 
 		printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id);
 		printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id);
 		for (i = 1; i <= pr->power.count; i++)
 		for (i = 1; i <= pr->power.count; i++)
@@ -1864,13 +1246,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
 				printk(" C%d[C%d]", i,
 				printk(" C%d[C%d]", i,
 				       pr->power.states[i].type);
 				       pr->power.states[i].type);
 		printk(")\n");
 		printk(")\n");
-
-#ifndef CONFIG_CPU_IDLE
-		if (pr->id == 0) {
-			pm_idle_save = pm_idle;
-			pm_idle = acpi_processor_idle;
-		}
-#endif
 	}
 	}
 
 
 	/* 'power' [R] */
 	/* 'power' [R] */
@@ -1889,34 +1264,12 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
 	if (boot_option_idle_override)
 	if (boot_option_idle_override)
 		return 0;
 		return 0;
 
 
-#ifdef CONFIG_CPU_IDLE
 	cpuidle_unregister_device(&pr->power.dev);
 	cpuidle_unregister_device(&pr->power.dev);
-#endif
 	pr->flags.power_setup_done = 0;
 	pr->flags.power_setup_done = 0;
 
 
 	if (acpi_device_dir(device))
 	if (acpi_device_dir(device))
 		remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,
 		remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,
 				  acpi_device_dir(device));
 				  acpi_device_dir(device));
 
 
-#ifndef CONFIG_CPU_IDLE
-
-	/* Unregister the idle handler when processor #0 is removed. */
-	if (pr->id == 0) {
-		if (pm_idle_save)
-			pm_idle = pm_idle_save;
-
-		/*
-		 * We are about to unload the current idle thread pm callback
-		 * (pm_idle), Wait for all processors to update cached/local
-		 * copies of pm_idle before proceeding.
-		 */
-		cpu_idle_wait();
-#ifdef CONFIG_SMP
-		pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY,
-				&acpi_processor_latency_notifier);
-#endif
-	}
-#endif
-
 	return 0;
 	return 0;
 }
 }

+ 0 - 105
drivers/acpi/processor_perflib.c

@@ -31,14 +31,6 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 #include <linux/cpufreq.h>
 
 
-#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/mutex.h>
-
-#include <asm/uaccess.h>
-#endif
-
 #ifdef CONFIG_X86
 #ifdef CONFIG_X86
 #include <asm/cpufeature.h>
 #include <asm/cpufeature.h>
 #endif
 #endif
@@ -434,96 +426,6 @@ int acpi_processor_notify_smm(struct module *calling_module)
 
 
 EXPORT_SYMBOL(acpi_processor_notify_smm);
 EXPORT_SYMBOL(acpi_processor_notify_smm);
 
 
-#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
-/* /proc/acpi/processor/../performance interface (DEPRECATED) */
-
-static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
-static struct file_operations acpi_processor_perf_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_processor_perf_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_processor *pr = seq->private;
-	int i;
-
-
-	if (!pr)
-		goto end;
-
-	if (!pr->performance) {
-		seq_puts(seq, "<not supported>\n");
-		goto end;
-	}
-
-	seq_printf(seq, "state count:             %d\n"
-		   "active state:            P%d\n",
-		   pr->performance->state_count, pr->performance->state);
-
-	seq_puts(seq, "states:\n");
-	for (i = 0; i < pr->performance->state_count; i++)
-		seq_printf(seq,
-			   "   %cP%d:                  %d MHz, %d mW, %d uS\n",
-			   (i == pr->performance->state ? '*' : ' '), i,
-			   (u32) pr->performance->states[i].core_frequency,
-			   (u32) pr->performance->states[i].power,
-			   (u32) pr->performance->states[i].transition_latency);
-
-      end:
-	return 0;
-}
-
-static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_processor_perf_seq_show,
-			   PDE(inode)->data);
-}
-
-static void acpi_cpufreq_add_file(struct acpi_processor *pr)
-{
-	struct acpi_device *device = NULL;
-
-
-	if (acpi_bus_get_device(pr->handle, &device))
-		return;
-
-	/* add file 'performance' [R/W] */
-	proc_create_data(ACPI_PROCESSOR_FILE_PERFORMANCE, S_IFREG | S_IRUGO,
-			 acpi_device_dir(device),
-			 &acpi_processor_perf_fops, acpi_driver_data(device));
-	return;
-}
-
-static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
-{
-	struct acpi_device *device = NULL;
-
-
-	if (acpi_bus_get_device(pr->handle, &device))
-		return;
-
-	/* remove file 'performance' */
-	remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
-			  acpi_device_dir(device));
-
-	return;
-}
-
-#else
-static void acpi_cpufreq_add_file(struct acpi_processor *pr)
-{
-	return;
-}
-static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
-{
-	return;
-}
-#endif				/* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
-
 static int acpi_processor_get_psd(struct acpi_processor	*pr)
 static int acpi_processor_get_psd(struct acpi_processor	*pr)
 {
 {
 	int result = 0;
 	int result = 0;
@@ -747,14 +649,12 @@ err_ret:
 }
 }
 EXPORT_SYMBOL(acpi_processor_preregister_performance);
 EXPORT_SYMBOL(acpi_processor_preregister_performance);
 
 
-
 int
 int
 acpi_processor_register_performance(struct acpi_processor_performance
 acpi_processor_register_performance(struct acpi_processor_performance
 				    *performance, unsigned int cpu)
 				    *performance, unsigned int cpu)
 {
 {
 	struct acpi_processor *pr;
 	struct acpi_processor *pr;
 
 
-
 	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
 	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
 		return -EINVAL;
 		return -EINVAL;
 
 
@@ -781,8 +681,6 @@ acpi_processor_register_performance(struct acpi_processor_performance
 		return -EIO;
 		return -EIO;
 	}
 	}
 
 
-	acpi_cpufreq_add_file(pr);
-
 	mutex_unlock(&performance_mutex);
 	mutex_unlock(&performance_mutex);
 	return 0;
 	return 0;
 }
 }
@@ -795,7 +693,6 @@ acpi_processor_unregister_performance(struct acpi_processor_performance
 {
 {
 	struct acpi_processor *pr;
 	struct acpi_processor *pr;
 
 
-
 	mutex_lock(&performance_mutex);
 	mutex_lock(&performance_mutex);
 
 
 	pr = per_cpu(processors, cpu);
 	pr = per_cpu(processors, cpu);
@@ -808,8 +705,6 @@ acpi_processor_unregister_performance(struct acpi_processor_performance
 		kfree(pr->performance->states);
 		kfree(pr->performance->states);
 	pr->performance = NULL;
 	pr->performance = NULL;
 
 
-	acpi_cpufreq_remove_file(pr);
-
 	mutex_unlock(&performance_mutex);
 	mutex_unlock(&performance_mutex);
 
 
 	return;
 	return;

+ 27 - 26
drivers/acpi/sleep.c

@@ -90,31 +90,6 @@ void __init acpi_old_suspend_ordering(void)
 	old_suspend_ordering = true;
 	old_suspend_ordering = true;
 }
 }
 
 
-/*
- * According to the ACPI specification the BIOS should make sure that ACPI is
- * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states.  Still,
- * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI
- * on such systems during resume.  Unfortunately that doesn't help in
- * particularly pathological cases in which SCI_EN has to be set directly on
- * resume, although the specification states very clearly that this flag is
- * owned by the hardware.  The set_sci_en_on_resume variable will be set in such
- * cases.
- */
-static bool set_sci_en_on_resume;
-/*
- * The ACPI specification wants us to save NVS memory regions during hibernation
- * and to restore them during the subsequent resume.  However, it is not certain
- * if this mechanism is going to work on all machines, so we allow the user to
- * disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line
- * option.
- */
-static bool s4_no_nvs;
-
-void __init acpi_s4_no_nvs(void)
-{
-	s4_no_nvs = true;
-}
-
 /**
 /**
  *	acpi_pm_disable_gpes - Disable the GPEs.
  *	acpi_pm_disable_gpes - Disable the GPEs.
  */
  */
@@ -193,6 +168,18 @@ static void acpi_pm_end(void)
 #endif /* CONFIG_ACPI_SLEEP */
 #endif /* CONFIG_ACPI_SLEEP */
 
 
 #ifdef CONFIG_SUSPEND
 #ifdef CONFIG_SUSPEND
+/*
+ * According to the ACPI specification the BIOS should make sure that ACPI is
+ * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states.  Still,
+ * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI
+ * on such systems during resume.  Unfortunately that doesn't help in
+ * particularly pathological cases in which SCI_EN has to be set directly on
+ * resume, although the specification states very clearly that this flag is
+ * owned by the hardware.  The set_sci_en_on_resume variable will be set in such
+ * cases.
+ */
+static bool set_sci_en_on_resume;
+
 extern void do_suspend_lowlevel(void);
 extern void do_suspend_lowlevel(void);
 
 
 static u32 acpi_suspend_states[] = {
 static u32 acpi_suspend_states[] = {
@@ -396,6 +383,20 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
 #endif /* CONFIG_SUSPEND */
 #endif /* CONFIG_SUSPEND */
 
 
 #ifdef CONFIG_HIBERNATION
 #ifdef CONFIG_HIBERNATION
+/*
+ * The ACPI specification wants us to save NVS memory regions during hibernation
+ * and to restore them during the subsequent resume.  However, it is not certain
+ * if this mechanism is going to work on all machines, so we allow the user to
+ * disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line
+ * option.
+ */
+static bool s4_no_nvs;
+
+void __init acpi_s4_no_nvs(void)
+{
+	s4_no_nvs = true;
+}
+
 static unsigned long s4_hardware_signature;
 static unsigned long s4_hardware_signature;
 static struct acpi_table_facs *facs;
 static struct acpi_table_facs *facs;
 static bool nosigcheck;
 static bool nosigcheck;
@@ -679,7 +680,7 @@ static void acpi_power_off_prepare(void)
 static void acpi_power_off(void)
 static void acpi_power_off(void)
 {
 {
 	/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
 	/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
-	printk("%s called\n", __func__);
+	printk(KERN_DEBUG "%s called\n", __func__);
 	local_irq_disable();
 	local_irq_disable();
 	acpi_enable_wakeup_device(ACPI_STATE_S5);
 	acpi_enable_wakeup_device(ACPI_STATE_S5);
 	acpi_enter_sleep_state(ACPI_STATE_S5);
 	acpi_enter_sleep_state(ACPI_STATE_S5);

+ 6 - 1
drivers/acpi/tables.c

@@ -293,7 +293,12 @@ static void __init check_multiple_madt(void)
 
 
 int __init acpi_table_init(void)
 int __init acpi_table_init(void)
 {
 {
-	acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
+	acpi_status status;
+
+	status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
+	if (ACPI_FAILURE(status))
+		return 1;
+
 	check_multiple_madt();
 	check_multiple_madt();
 	return 0;
 	return 0;
 }
 }

+ 11 - 5
drivers/acpi/video.c

@@ -1020,7 +1020,7 @@ acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
 	}
 	}
 
 
 	seq_printf(seq, "levels: ");
 	seq_printf(seq, "levels: ");
-	for (i = 0; i < dev->brightness->count; i++)
+	for (i = 2; i < dev->brightness->count; i++)
 		seq_printf(seq, " %d", dev->brightness->levels[i]);
 		seq_printf(seq, " %d", dev->brightness->levels[i]);
 	seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
 	seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
 
 
@@ -1059,7 +1059,7 @@ acpi_video_device_write_brightness(struct file *file,
 		return -EFAULT;
 		return -EFAULT;
 
 
 	/* validate through the list of available levels */
 	/* validate through the list of available levels */
-	for (i = 0; i < dev->brightness->count; i++)
+	for (i = 2; i < dev->brightness->count; i++)
 		if (level == dev->brightness->levels[i]) {
 		if (level == dev->brightness->levels[i]) {
 			if (ACPI_SUCCESS
 			if (ACPI_SUCCESS
 			    (acpi_video_device_lcd_set_level(dev, level)))
 			    (acpi_video_device_lcd_set_level(dev, level)))
@@ -1260,7 +1260,7 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
 			printk(KERN_WARNING PREFIX
 			printk(KERN_WARNING PREFIX
 			       "This indicates a BIOS bug. Please contact the manufacturer.\n");
 			       "This indicates a BIOS bug. Please contact the manufacturer.\n");
 		}
 		}
-		printk("%llx\n", options);
+		printk(KERN_WARNING "%llx\n", options);
 		seq_printf(seq, "can POST: <integrated video>");
 		seq_printf(seq, "can POST: <integrated video>");
 		if (options & 2)
 		if (options & 2)
 			seq_printf(seq, " <PCI video>");
 			seq_printf(seq, " <PCI video>");
@@ -1712,7 +1712,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
 	max = max_below = 0;
 	max = max_below = 0;
 	min = min_above = 255;
 	min = min_above = 255;
 	/* Find closest level to level_current */
 	/* Find closest level to level_current */
-	for (i = 0; i < device->brightness->count; i++) {
+	for (i = 2; i < device->brightness->count; i++) {
 		l = device->brightness->levels[i];
 		l = device->brightness->levels[i];
 		if (abs(l - level_current) < abs(delta)) {
 		if (abs(l - level_current) < abs(delta)) {
 			delta = l - level_current;
 			delta = l - level_current;
@@ -1722,7 +1722,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
 	}
 	}
 	/* Ajust level_current to closest available level */
 	/* Ajust level_current to closest available level */
 	level_current += delta;
 	level_current += delta;
-	for (i = 0; i < device->brightness->count; i++) {
+	for (i = 2; i < device->brightness->count; i++) {
 		l = device->brightness->levels[i];
 		l = device->brightness->levels[i];
 		if (l < min)
 		if (l < min)
 			min = l;
 			min = l;
@@ -2006,6 +2006,12 @@ static int acpi_video_bus_add(struct acpi_device *device)
 			device->pnp.bus_id[3] = '0' + instance;
 			device->pnp.bus_id[3] = '0' + instance;
 		instance ++;
 		instance ++;
 	}
 	}
+	/* a hack to fix the duplicate name "VGA" problem on Pa 3553 */
+	if (!strcmp(device->pnp.bus_id, "VGA")) {
+		if (instance)
+			device->pnp.bus_id[3] = '0' + instance;
+		instance++;
+	}
 
 
 	video->device = device;
 	video->device = device;
 	strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
 	strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);

+ 5 - 3
drivers/char/sx.c

@@ -1713,8 +1713,8 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
 		for (i = 0; i < SX_NBOARDS; i++)
 		for (i = 0; i < SX_NBOARDS; i++)
 			sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
 			sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
 		sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
 		sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
-		unlock_kernel();
-		return -EIO;
+		rc = -EIO;
+		goto out;
 	}
 	}
 
 
 	switch (cmd) {
 	switch (cmd) {
@@ -1747,7 +1747,8 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
 		break;
 		break;
 	case SXIO_DO_RAMTEST:
 	case SXIO_DO_RAMTEST:
 		if (sx_initialized)	/* Already initialized: better not ramtest the board.  */
 		if (sx_initialized)	/* Already initialized: better not ramtest the board.  */
-			return -EPERM;
+			rc = -EPERM;
+			break;
 		if (IS_SX_BOARD(board)) {
 		if (IS_SX_BOARD(board)) {
 			rc = do_memtest(board, 0, 0x7000);
 			rc = do_memtest(board, 0, 0x7000);
 			if (!rc)
 			if (!rc)
@@ -1844,6 +1845,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
 		rc = -ENOTTY;
 		rc = -ENOTTY;
 		break;
 		break;
 	}
 	}
+out:
 	unlock_kernel();
 	unlock_kernel();
 	func_exit();
 	func_exit();
 	return rc;
 	return rc;

+ 8 - 1
drivers/firewire/fw-card.c

@@ -412,6 +412,7 @@ fw_card_add(struct fw_card *card,
 {
 {
 	u32 *config_rom;
 	u32 *config_rom;
 	size_t length;
 	size_t length;
+	int err;
 
 
 	card->max_receive = max_receive;
 	card->max_receive = max_receive;
 	card->link_speed = link_speed;
 	card->link_speed = link_speed;
@@ -422,7 +423,13 @@ fw_card_add(struct fw_card *card,
 	list_add_tail(&card->link, &card_list);
 	list_add_tail(&card->link, &card_list);
 	mutex_unlock(&card_mutex);
 	mutex_unlock(&card_mutex);
 
 
-	return card->driver->enable(card, config_rom, length);
+	err = card->driver->enable(card, config_rom, length);
+	if (err < 0) {
+		mutex_lock(&card_mutex);
+		list_del(&card->link);
+		mutex_unlock(&card_mutex);
+	}
+	return err;
 }
 }
 EXPORT_SYMBOL(fw_card_add);
 EXPORT_SYMBOL(fw_card_add);
 
 

+ 7 - 2
drivers/hwmon/hp_accel.c

@@ -153,7 +153,10 @@ static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3};
 static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
 static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
 static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
 static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
 static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
 static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
+static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3};
 static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
 static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
+static struct axis_conversion lis3lv02d_axis_xy_rotated_right = {2, -1, 3};
+static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3};
 
 
 #define AXIS_DMI_MATCH(_ident, _name, _axis) {		\
 #define AXIS_DMI_MATCH(_ident, _name, _axis) {		\
 	.ident = _ident,				\
 	.ident = _ident,				\
@@ -172,10 +175,12 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
 	AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
 	AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
 	AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
 	AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
 	AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
 	AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
+	AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
+	AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd),
+	AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
+	AXIS_DMI_MATCH("NC671xx", "HP Compaq 671", xy_swap_yz_inverted),
 	{ NULL, }
 	{ NULL, }
 /* Laptop models without axis info (yet):
 /* Laptop models without axis info (yet):
- * "NC651xx" "HP Compaq 651"
- * "NC671xx" "HP Compaq 671"
  * "NC6910" "HP Compaq 6910"
  * "NC6910" "HP Compaq 6910"
  * HP Compaq 8710x Notebook PC / Mobile Workstation
  * HP Compaq 8710x Notebook PC / Mobile Workstation
  * "NC2400" "HP Compaq nc2400"
  * "NC2400" "HP Compaq nc2400"

+ 4 - 4
drivers/ieee1394/dv1394.c

@@ -1823,6 +1823,10 @@ static int dv1394_open(struct inode *inode, struct file *file)
 
 
 #endif
 #endif
 
 
+	printk(KERN_INFO "%s: NOTE, the dv1394 interface is unsupported "
+	       "and will not be available in the new firewire driver stack. "
+	       "Try libraw1394 based programs instead.\n", current->comm);
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -2567,10 +2571,6 @@ static int __init dv1394_init_module(void)
 {
 {
 	int ret;
 	int ret;
 
 
-	printk(KERN_WARNING
-	       "NOTE: The dv1394 driver is unsupported and may be removed in a "
-	       "future Linux release. Use raw1394 instead.\n");
-
 	cdev_init(&dv1394_cdev, &dv1394_fops);
 	cdev_init(&dv1394_cdev, &dv1394_fops);
 	dv1394_cdev.owner = THIS_MODULE;
 	dv1394_cdev.owner = THIS_MODULE;
 	ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16);
 	ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16);

+ 3 - 3
drivers/md/linear.c

@@ -25,13 +25,13 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
 {
 {
 	dev_info_t *hash;
 	dev_info_t *hash;
 	linear_conf_t *conf = mddev_to_conf(mddev);
 	linear_conf_t *conf = mddev_to_conf(mddev);
+	sector_t idx = sector >> conf->sector_shift;
 
 
 	/*
 	/*
 	 * sector_div(a,b) returns the remainer and sets a to a/b
 	 * sector_div(a,b) returns the remainer and sets a to a/b
 	 */
 	 */
-	sector >>= conf->sector_shift;
-	(void)sector_div(sector, conf->spacing);
-	hash = conf->hash_table[sector];
+	(void)sector_div(idx, conf->spacing);
+	hash = conf->hash_table[idx];
 
 
 	while (sector >= hash->num_sectors + hash->start_sector)
 	while (sector >= hash->num_sectors + hash->start_sector)
 		hash++;
 		hash++;

+ 14 - 10
drivers/md/md.c

@@ -1481,6 +1481,11 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
 		if (find_rdev_nr(mddev, rdev->desc_nr))
 		if (find_rdev_nr(mddev, rdev->desc_nr))
 			return -EBUSY;
 			return -EBUSY;
 	}
 	}
+	if (mddev->max_disks && rdev->desc_nr >= mddev->max_disks) {
+		printk(KERN_WARNING "md: %s: array is limited to %d devices\n",
+		       mdname(mddev), mddev->max_disks);
+		return -EBUSY;
+	}
 	bdevname(rdev->bdev,b);
 	bdevname(rdev->bdev,b);
 	while ( (s=strchr(b, '/')) != NULL)
 	while ( (s=strchr(b, '/')) != NULL)
 		*s = '!';
 		*s = '!';
@@ -2441,6 +2446,15 @@ static void analyze_sbs(mddev_t * mddev)
 
 
 	i = 0;
 	i = 0;
 	rdev_for_each(rdev, tmp, mddev) {
 	rdev_for_each(rdev, tmp, mddev) {
+		if (rdev->desc_nr >= mddev->max_disks ||
+		    i > mddev->max_disks) {
+			printk(KERN_WARNING
+			       "md: %s: %s: only %d devices permitted\n",
+			       mdname(mddev), bdevname(rdev->bdev, b),
+			       mddev->max_disks);
+			kick_rdev_from_array(rdev);
+			continue;
+		}
 		if (rdev != freshest)
 		if (rdev != freshest)
 			if (super_types[mddev->major_version].
 			if (super_types[mddev->major_version].
 			    validate_super(mddev, rdev)) {
 			    validate_super(mddev, rdev)) {
@@ -4614,13 +4628,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
 	 * noticed in interrupt contexts ...
 	 * noticed in interrupt contexts ...
 	 */
 	 */
 
 
-	if (rdev->desc_nr == mddev->max_disks) {
-		printk(KERN_WARNING "%s: can not hot-add to full array!\n",
-			mdname(mddev));
-		err = -EBUSY;
-		goto abort_unbind_export;
-	}
-
 	rdev->raid_disk = -1;
 	rdev->raid_disk = -1;
 
 
 	md_update_sb(mddev, 1);
 	md_update_sb(mddev, 1);
@@ -4634,9 +4641,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
 	md_new_event(mddev);
 	md_new_event(mddev);
 	return 0;
 	return 0;
 
 
-abort_unbind_export:
-	unbind_rdev_from_array(rdev);
-
 abort_export:
 abort_export:
 	export_rdev(rdev);
 	export_rdev(rdev);
 	return err;
 	return err;

+ 2 - 1
drivers/md/raid1.c

@@ -1640,7 +1640,8 @@ static void raid1d(mddev_t *mddev)
 			}
 			}
 
 
 			bio = r1_bio->bios[r1_bio->read_disk];
 			bio = r1_bio->bios[r1_bio->read_disk];
-			if ((disk=read_balance(conf, r1_bio)) == -1) {
+			if ((disk=read_balance(conf, r1_bio)) == -1 ||
+			    disk == r1_bio->read_disk) {
 				printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
 				printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
 				       " read error for block %llu\n",
 				       " read error for block %llu\n",
 				       bdevname(bio->bi_bdev,b),
 				       bdevname(bio->bi_bdev,b),

+ 1 - 0
drivers/misc/Kconfig

@@ -217,6 +217,7 @@ config DELL_LAPTOP
 	depends on EXPERIMENTAL
 	depends on EXPERIMENTAL
 	depends on BACKLIGHT_CLASS_DEVICE
 	depends on BACKLIGHT_CLASS_DEVICE
 	depends on RFKILL
 	depends on RFKILL
+	depends on POWER_SUPPLY
 	default n
 	default n
 	---help---
 	---help---
 	This driver adds support for rfkill and backlight control to Dell
 	This driver adds support for rfkill and backlight control to Dell

+ 1 - 1
drivers/misc/atmel-ssc.c

@@ -35,7 +35,7 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
 
 
 	if (!ssc_valid) {
 	if (!ssc_valid) {
 		spin_unlock(&user_lock);
 		spin_unlock(&user_lock);
-		dev_dbg(&ssc->pdev->dev, "could not find requested device\n");
+		pr_err("ssc: ssc%d platform device is missing\n", ssc_num);
 		return ERR_PTR(-ENODEV);
 		return ERR_PTR(-ENODEV);
 	}
 	}
 
 

+ 3 - 3
drivers/misc/hpilo.c

@@ -207,7 +207,7 @@ static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data)
 		  &device_ccb->recv_ctrl);
 		  &device_ccb->recv_ctrl);
 
 
 	/* give iLO some time to process stop request */
 	/* give iLO some time to process stop request */
-	for (retries = 1000; retries > 0; retries--) {
+	for (retries = MAX_WAIT; retries > 0; retries--) {
 		doorbell_set(driver_ccb);
 		doorbell_set(driver_ccb);
 		udelay(1);
 		udelay(1);
 		if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A))
 		if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A))
@@ -309,7 +309,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
 	doorbell_clr(driver_ccb);
 	doorbell_clr(driver_ccb);
 
 
 	/* make sure iLO is really handling requests */
 	/* make sure iLO is really handling requests */
-	for (i = 1000; i > 0; i--) {
+	for (i = MAX_WAIT; i > 0; i--) {
 		if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL))
 		if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL))
 			break;
 			break;
 		udelay(1);
 		udelay(1);
@@ -326,7 +326,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
 
 
 	return 0;
 	return 0;
 free:
 free:
-	pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa);
+	ilo_ccb_close(pdev, data);
 out:
 out:
 	return error;
 	return error;
 }
 }

+ 2 - 0
drivers/misc/hpilo.h

@@ -19,6 +19,8 @@
 #define MAX_ILO_DEV	1
 #define MAX_ILO_DEV	1
 /* max number of files */
 /* max number of files */
 #define MAX_OPEN	(MAX_CCB * MAX_ILO_DEV)
 #define MAX_OPEN	(MAX_CCB * MAX_ILO_DEV)
+/* spin counter for open/close delay */
+#define MAX_WAIT	10000
 
 
 /*
 /*
  * Per device, used to track global memory allocations.
  * Per device, used to track global memory allocations.

+ 3 - 2
drivers/misc/sgi-xp/xpc.h

@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  * for more details.
  *
  *
- * Copyright (c) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2004-2009 Silicon Graphics, Inc.  All Rights Reserved.
  */
  */
 
 
 /*
 /*
@@ -514,7 +514,8 @@ struct xpc_channel_uv {
 						/* partition's notify mq */
 						/* partition's notify mq */
 
 
 	struct xpc_send_msg_slot_uv *send_msg_slots;
 	struct xpc_send_msg_slot_uv *send_msg_slots;
-	struct xpc_notify_mq_msg_uv *recv_msg_slots;
+	void *recv_msg_slots;	/* each slot will hold a xpc_notify_mq_msg_uv */
+				/* structure plus the user's payload */
 
 
 	struct xpc_fifo_head_uv msg_slot_free_list;
 	struct xpc_fifo_head_uv msg_slot_free_list;
 	struct xpc_fifo_head_uv recv_msg_list;	/* deliverable payloads */
 	struct xpc_fifo_head_uv recv_msg_list;	/* deliverable payloads */

+ 5 - 6
drivers/misc/sgi-xp/xpc_uv.c

@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  * for more details.
  *
  *
- * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2008-2009 Silicon Graphics, Inc.  All Rights Reserved.
  */
  */
 
 
 /*
 /*
@@ -1010,8 +1010,8 @@ xpc_allocate_recv_msg_slot_uv(struct xpc_channel *ch)
 			continue;
 			continue;
 
 
 		for (entry = 0; entry < nentries; entry++) {
 		for (entry = 0; entry < nentries; entry++) {
-			msg_slot = ch_uv->recv_msg_slots + entry *
-			    ch->entry_size;
+			msg_slot = ch_uv->recv_msg_slots +
+			    entry * ch->entry_size;
 
 
 			msg_slot->hdr.msg_slot_number = entry;
 			msg_slot->hdr.msg_slot_number = entry;
 		}
 		}
@@ -1308,9 +1308,8 @@ xpc_handle_notify_mq_msg_uv(struct xpc_partition *part,
 	/* we're dealing with a normal message sent via the notify_mq */
 	/* we're dealing with a normal message sent via the notify_mq */
 	ch_uv = &ch->sn.uv;
 	ch_uv = &ch->sn.uv;
 
 
-	msg_slot = (struct xpc_notify_mq_msg_uv *)((u64)ch_uv->recv_msg_slots +
-		    (msg->hdr.msg_slot_number % ch->remote_nentries) *
-		    ch->entry_size);
+	msg_slot = ch_uv->recv_msg_slots +
+	    (msg->hdr.msg_slot_number % ch->remote_nentries) * ch->entry_size;
 
 
 	BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number);
 	BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number);
 	BUG_ON(msg_slot->hdr.size != 0);
 	BUG_ON(msg_slot->hdr.size != 0);

+ 1 - 2
drivers/net/cxgb3/sge.c

@@ -2276,8 +2276,7 @@ no_mem:
 		} else if ((len = ntohl(r->len_cq)) != 0) {
 		} else if ((len = ntohl(r->len_cq)) != 0) {
 			struct sge_fl *fl;
 			struct sge_fl *fl;
 
 
-			if (eth)
-				lro = qs->lro_enabled && is_eth_tcp(rss_hi);
+			lro &= eth && is_eth_tcp(rss_hi);
 
 
 			fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
 			fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
 			if (fl->use_pages) {
 			if (fl->use_pages) {

+ 3 - 0
drivers/net/gianfar.c

@@ -351,6 +351,9 @@ static int gfar_probe(struct of_device *ofdev,
 	/* Reset MAC layer */
 	/* Reset MAC layer */
 	gfar_write(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
 	gfar_write(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
 
 
+	/* We need to delay at least 3 TX clocks */
+	udelay(2);
+
 	tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
 	tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
 	gfar_write(&priv->regs->maccfg1, tempval);
 	gfar_write(&priv->regs->maccfg1, tempval);
 
 

+ 1 - 1
drivers/net/gianfar.h

@@ -312,7 +312,7 @@ extern const char gfar_driver_version[];
 #define ATTRELI_EI(x) (x)
 #define ATTRELI_EI(x) (x)
 
 
 #define BD_LFLAG(flags) ((flags) << 16)
 #define BD_LFLAG(flags) ((flags) << 16)
-#define BD_LENGTH_MASK		0x00ff
+#define BD_LENGTH_MASK		0x0000ffff
 
 
 /* TxBD status field bits */
 /* TxBD status field bits */
 #define TXBD_READY		0x8000
 #define TXBD_READY		0x8000

+ 2 - 0
drivers/net/wireless/iwlwifi/iwl-agn.c

@@ -4042,6 +4042,7 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 		priv->is_open = 1;
 		priv->is_open = 1;
 	}
 	}
 
 
+	pci_save_state(pdev);
 	pci_set_power_state(pdev, PCI_D3hot);
 	pci_set_power_state(pdev, PCI_D3hot);
 
 
 	return 0;
 	return 0;
@@ -4052,6 +4053,7 @@ static int iwl_pci_resume(struct pci_dev *pdev)
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
 
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
 
 
 	if (priv->is_open)
 	if (priv->is_open)
 		iwl_mac_start(priv->hw);
 		iwl_mac_start(priv->hw);

+ 3 - 0
drivers/net/wireless/iwlwifi/iwl-sta.c

@@ -480,6 +480,9 @@ void iwl_clear_stations_table(struct iwl_priv *priv)
 	priv->num_stations = 0;
 	priv->num_stations = 0;
 	memset(priv->stations, 0, sizeof(priv->stations));
 	memset(priv->stations, 0, sizeof(priv->stations));
 
 
+	/* clean ucode key table bit map */
+	priv->ucode_key_table = 0;
+
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
 }
 EXPORT_SYMBOL(iwl_clear_stations_table);
 EXPORT_SYMBOL(iwl_clear_stations_table);

+ 2 - 0
drivers/net/wireless/iwlwifi/iwl3945-base.c

@@ -8143,6 +8143,7 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 		priv->is_open = 1;
 		priv->is_open = 1;
 	}
 	}
 
 
+	pci_save_state(pdev);
 	pci_set_power_state(pdev, PCI_D3hot);
 	pci_set_power_state(pdev, PCI_D3hot);
 
 
 	return 0;
 	return 0;
@@ -8153,6 +8154,7 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)
 	struct iwl3945_priv *priv = pci_get_drvdata(pdev);
 	struct iwl3945_priv *priv = pci_get_drvdata(pdev);
 
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
 
 
 	if (priv->is_open)
 	if (priv->is_open)
 		iwl3945_mac_start(priv->hw);
 		iwl3945_mac_start(priv->hw);

+ 105 - 59
drivers/pci/pci-driver.c

@@ -355,6 +355,8 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
 	int i = 0;
 	int i = 0;
 
 
 	if (drv && drv->suspend) {
 	if (drv && drv->suspend) {
+		pci_power_t prev = pci_dev->current_state;
+
 		pci_dev->state_saved = false;
 		pci_dev->state_saved = false;
 
 
 		i = drv->suspend(pci_dev, state);
 		i = drv->suspend(pci_dev, state);
@@ -365,12 +367,16 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
 		if (pci_dev->state_saved)
 		if (pci_dev->state_saved)
 			goto Fixup;
 			goto Fixup;
 
 
-		if (WARN_ON_ONCE(pci_dev->current_state != PCI_D0))
+		if (pci_dev->current_state != PCI_D0
+		    && pci_dev->current_state != PCI_UNKNOWN) {
+			WARN_ONCE(pci_dev->current_state != prev,
+				"PCI PM: Device state not saved by %pF\n",
+				drv->suspend);
 			goto Fixup;
 			goto Fixup;
+		}
 	}
 	}
 
 
 	pci_save_state(pci_dev);
 	pci_save_state(pci_dev);
-	pci_dev->state_saved = true;
 	/*
 	/*
 	 * This is for compatibility with existing code with legacy PM support.
 	 * This is for compatibility with existing code with legacy PM support.
 	 */
 	 */
@@ -424,35 +430,20 @@ static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
 	pci_fixup_device(pci_fixup_resume_early, pci_dev);
 	pci_fixup_device(pci_fixup_resume_early, pci_dev);
 }
 }
 
 
-static int pci_pm_default_resume(struct pci_dev *pci_dev)
+static void pci_pm_default_resume(struct pci_dev *pci_dev)
 {
 {
 	pci_fixup_device(pci_fixup_resume, pci_dev);
 	pci_fixup_device(pci_fixup_resume, pci_dev);
 
 
 	if (!pci_is_bridge(pci_dev))
 	if (!pci_is_bridge(pci_dev))
 		pci_enable_wake(pci_dev, PCI_D0, false);
 		pci_enable_wake(pci_dev, PCI_D0, false);
-
-	return pci_pm_reenable_device(pci_dev);
-}
-
-static void pci_pm_default_suspend_generic(struct pci_dev *pci_dev)
-{
-	/* If device is enabled at this point, disable it */
-	pci_disable_enabled_device(pci_dev);
-	/*
-	 * Save state with interrupts enabled, because in principle the bus the
-	 * device is on may be put into a low power state after this code runs.
-	 */
-	pci_save_state(pci_dev);
 }
 }
 
 
 static void pci_pm_default_suspend(struct pci_dev *pci_dev)
 static void pci_pm_default_suspend(struct pci_dev *pci_dev)
 {
 {
-	pci_pm_default_suspend_generic(pci_dev);
-
+	/* Disable non-bridge devices without PM support */
 	if (!pci_is_bridge(pci_dev))
 	if (!pci_is_bridge(pci_dev))
-		pci_prepare_to_sleep(pci_dev);
-
-	pci_fixup_device(pci_fixup_suspend, pci_dev);
+		pci_disable_enabled_device(pci_dev);
+	pci_save_state(pci_dev);
 }
 }
 
 
 static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
 static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
@@ -497,21 +488,49 @@ static void pci_pm_complete(struct device *dev)
 static int pci_pm_suspend(struct device *dev)
 static int pci_pm_suspend(struct device *dev)
 {
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	struct pci_dev *pci_dev = to_pci_dev(dev);
-	struct device_driver *drv = dev->driver;
-	int error = 0;
+	struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
 
 	if (pci_has_legacy_pm_support(pci_dev))
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_suspend(dev, PMSG_SUSPEND);
 		return pci_legacy_suspend(dev, PMSG_SUSPEND);
 
 
-	if (drv && drv->pm && drv->pm->suspend) {
-		error = drv->pm->suspend(dev);
-		suspend_report_result(drv->pm->suspend, error);
+	if (!pm) {
+		pci_pm_default_suspend(pci_dev);
+		goto Fixup;
 	}
 	}
 
 
-	if (!error)
-		pci_pm_default_suspend(pci_dev);
+	pci_dev->state_saved = false;
 
 
-	return error;
+	if (pm->suspend) {
+		pci_power_t prev = pci_dev->current_state;
+		int error;
+
+		error = pm->suspend(dev);
+		suspend_report_result(pm->suspend, error);
+		if (error)
+			return error;
+
+		if (pci_dev->state_saved)
+			goto Fixup;
+
+		if (pci_dev->current_state != PCI_D0
+		    && pci_dev->current_state != PCI_UNKNOWN) {
+			WARN_ONCE(pci_dev->current_state != prev,
+				"PCI PM: State of device not saved by %pF\n",
+				pm->suspend);
+			goto Fixup;
+		}
+	}
+
+	if (!pci_dev->state_saved) {
+		pci_save_state(pci_dev);
+		if (!pci_is_bridge(pci_dev))
+			pci_prepare_to_sleep(pci_dev);
+	}
+
+ Fixup:
+	pci_fixup_device(pci_fixup_suspend, pci_dev);
+
+	return 0;
 }
 }
 
 
 static int pci_pm_suspend_noirq(struct device *dev)
 static int pci_pm_suspend_noirq(struct device *dev)
@@ -554,7 +573,7 @@ static int pci_pm_resume_noirq(struct device *dev)
 static int pci_pm_resume(struct device *dev)
 static int pci_pm_resume(struct device *dev)
 {
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	struct pci_dev *pci_dev = to_pci_dev(dev);
-	struct device_driver *drv = dev->driver;
+	struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 	int error = 0;
 	int error = 0;
 
 
 	/*
 	/*
@@ -567,12 +586,16 @@ static int pci_pm_resume(struct device *dev)
 	if (pci_has_legacy_pm_support(pci_dev))
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_resume(dev);
 		return pci_legacy_resume(dev);
 
 
-	error = pci_pm_default_resume(pci_dev);
+	pci_pm_default_resume(pci_dev);
 
 
-	if (!error && drv && drv->pm && drv->pm->resume)
-		error = drv->pm->resume(dev);
+	if (pm) {
+		if (pm->resume)
+			error = pm->resume(dev);
+	} else {
+		pci_pm_reenable_device(pci_dev);
+	}
 
 
-	return error;
+	return 0;
 }
 }
 
 
 #else /* !CONFIG_SUSPEND */
 #else /* !CONFIG_SUSPEND */
@@ -589,21 +612,31 @@ static int pci_pm_resume(struct device *dev)
 static int pci_pm_freeze(struct device *dev)
 static int pci_pm_freeze(struct device *dev)
 {
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	struct pci_dev *pci_dev = to_pci_dev(dev);
-	struct device_driver *drv = dev->driver;
-	int error = 0;
+	struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
 
 	if (pci_has_legacy_pm_support(pci_dev))
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_suspend(dev, PMSG_FREEZE);
 		return pci_legacy_suspend(dev, PMSG_FREEZE);
 
 
-	if (drv && drv->pm && drv->pm->freeze) {
-		error = drv->pm->freeze(dev);
-		suspend_report_result(drv->pm->freeze, error);
+	if (!pm) {
+		pci_pm_default_suspend(pci_dev);
+		return 0;
 	}
 	}
 
 
-	if (!error)
-		pci_pm_default_suspend_generic(pci_dev);
+	pci_dev->state_saved = false;
 
 
-	return error;
+	if (pm->freeze) {
+		int error;
+
+		error = pm->freeze(dev);
+		suspend_report_result(pm->freeze, error);
+		if (error)
+			return error;
+	}
+
+	if (!pci_dev->state_saved)
+		pci_save_state(pci_dev);
+
+	return 0;
 }
 }
 
 
 static int pci_pm_freeze_noirq(struct device *dev)
 static int pci_pm_freeze_noirq(struct device *dev)
@@ -646,16 +679,18 @@ static int pci_pm_thaw_noirq(struct device *dev)
 static int pci_pm_thaw(struct device *dev)
 static int pci_pm_thaw(struct device *dev)
 {
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	struct pci_dev *pci_dev = to_pci_dev(dev);
-	struct device_driver *drv = dev->driver;
+	struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 	int error = 0;
 	int error = 0;
 
 
 	if (pci_has_legacy_pm_support(pci_dev))
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_resume(dev);
 		return pci_legacy_resume(dev);
 
 
-	pci_pm_reenable_device(pci_dev);
-
-	if (drv && drv->pm && drv->pm->thaw)
-		error =  drv->pm->thaw(dev);
+	if (pm) {
+		if (pm->thaw)
+			error = pm->thaw(dev);
+	} else {
+		pci_pm_reenable_device(pci_dev);
+	}
 
 
 	return error;
 	return error;
 }
 }
@@ -663,22 +698,29 @@ static int pci_pm_thaw(struct device *dev)
 static int pci_pm_poweroff(struct device *dev)
 static int pci_pm_poweroff(struct device *dev)
 {
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	struct pci_dev *pci_dev = to_pci_dev(dev);
-	struct device_driver *drv = dev->driver;
+	struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 	int error = 0;
 	int error = 0;
 
 
 	if (pci_has_legacy_pm_support(pci_dev))
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_suspend(dev, PMSG_HIBERNATE);
 		return pci_legacy_suspend(dev, PMSG_HIBERNATE);
 
 
-	if (!drv || !drv->pm)
-		return 0;
+	if (!pm) {
+		pci_pm_default_suspend(pci_dev);
+		goto Fixup;
+	}
+
+	pci_dev->state_saved = false;
 
 
-	if (drv->pm->poweroff) {
-		error = drv->pm->poweroff(dev);
-		suspend_report_result(drv->pm->poweroff, error);
+	if (pm->poweroff) {
+		error = pm->poweroff(dev);
+		suspend_report_result(pm->poweroff, error);
 	}
 	}
 
 
-	if (!error)
-		pci_pm_default_suspend(pci_dev);
+	if (!pci_dev->state_saved && !pci_is_bridge(pci_dev))
+		pci_prepare_to_sleep(pci_dev);
+
+ Fixup:
+	pci_fixup_device(pci_fixup_suspend, pci_dev);
 
 
 	return error;
 	return error;
 }
 }
@@ -719,7 +761,7 @@ static int pci_pm_restore_noirq(struct device *dev)
 static int pci_pm_restore(struct device *dev)
 static int pci_pm_restore(struct device *dev)
 {
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	struct pci_dev *pci_dev = to_pci_dev(dev);
-	struct device_driver *drv = dev->driver;
+	struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 	int error = 0;
 	int error = 0;
 
 
 	/*
 	/*
@@ -732,10 +774,14 @@ static int pci_pm_restore(struct device *dev)
 	if (pci_has_legacy_pm_support(pci_dev))
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_resume(dev);
 		return pci_legacy_resume(dev);
 
 
-	error = pci_pm_default_resume(pci_dev);
+	pci_pm_default_resume(pci_dev);
 
 
-	if (!error && drv && drv->pm && drv->pm->restore)
-		error = drv->pm->restore(dev);
+	if (pm) {
+		if (pm->restore)
+			error = pm->restore(dev);
+	} else {
+		pci_pm_reenable_device(pci_dev);
+	}
 
 
 	return error;
 	return error;
 }
 }

+ 2 - 2
drivers/pci/pci-sysfs.c

@@ -768,8 +768,8 @@ pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
 		return -EINVAL;
 		return -EINVAL;
 	
 	
 	rom = pci_map_rom(pdev, &size);	/* size starts out as PCI window size */
 	rom = pci_map_rom(pdev, &size);	/* size starts out as PCI window size */
-	if (!rom)
-		return 0;
+	if (!rom || !size)
+		return -EIO;
 		
 		
 	if (off >= size)
 	if (off >= size)
 		count = 0;
 		count = 0;

+ 2 - 2
drivers/pci/pci.c

@@ -1418,10 +1418,10 @@ int pci_restore_standard_config(struct pci_dev *dev)
 		break;
 		break;
 	}
 	}
 
 
-	dev->current_state = PCI_D0;
+	pci_update_current_state(dev, PCI_D0);
 
 
  Restore:
  Restore:
-	return pci_restore_state(dev);
+	return dev->state_saved ? pci_restore_state(dev) : 0;
 }
 }
 
 
 /**
 /**

+ 2 - 2
drivers/pci/pcie/aspm.c

@@ -718,9 +718,9 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
 
 
 	/*
 	/*
 	 * All PCIe functions are in one slot, remove one function will remove
 	 * All PCIe functions are in one slot, remove one function will remove
-	 * the the whole slot, so just wait
+	 * the whole slot, so just wait until we are the last function left.
 	 */
 	 */
-	if (!list_empty(&parent->subordinate->devices))
+	if (!list_is_last(&pdev->bus_list, &parent->subordinate->devices))
 		goto out;
 		goto out;
 
 
 	/* All functions are removed, so just disable ASPM for the link */
 	/* All functions are removed, so just disable ASPM for the link */

+ 1 - 15
drivers/pci/pcie/portdrv_pci.c

@@ -55,25 +55,13 @@ static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
 
 
 }
 }
 
 
-static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state)
-{
-	return pci_save_state(dev);
-}
-
-static int pcie_portdrv_resume_early(struct pci_dev *dev)
-{
-	return pci_restore_state(dev);
-}
-
 static int pcie_portdrv_resume(struct pci_dev *dev)
 static int pcie_portdrv_resume(struct pci_dev *dev)
 {
 {
-	pcie_portdrv_restore_config(dev);
+	pci_set_master(dev);
 	return pcie_port_device_resume(dev);
 	return pcie_port_device_resume(dev);
 }
 }
 #else
 #else
 #define pcie_portdrv_suspend NULL
 #define pcie_portdrv_suspend NULL
-#define pcie_portdrv_suspend_late NULL
-#define pcie_portdrv_resume_early NULL
 #define pcie_portdrv_resume NULL
 #define pcie_portdrv_resume NULL
 #endif
 #endif
 
 
@@ -292,8 +280,6 @@ static struct pci_driver pcie_portdriver = {
 	.remove		= pcie_portdrv_remove,
 	.remove		= pcie_portdrv_remove,
 
 
 	.suspend	= pcie_portdrv_suspend,
 	.suspend	= pcie_portdrv_suspend,
-	.suspend_late	= pcie_portdrv_suspend_late,
-	.resume_early	= pcie_portdrv_resume_early,
 	.resume		= pcie_portdrv_resume,
 	.resume		= pcie_portdrv_resume,
 
 
 	.err_handler 	= &pcie_portdrv_err_handler,
 	.err_handler 	= &pcie_portdrv_err_handler,

+ 5 - 3
drivers/pci/rom.c

@@ -63,7 +63,7 @@ void pci_disable_rom(struct pci_dev *pdev)
  * The PCI window size could be much larger than the
  * The PCI window size could be much larger than the
  * actual image size.
  * actual image size.
  */
  */
-size_t pci_get_rom_size(void __iomem *rom, size_t size)
+size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
 {
 {
 	void __iomem *image;
 	void __iomem *image;
 	int last_image;
 	int last_image;
@@ -72,8 +72,10 @@ size_t pci_get_rom_size(void __iomem *rom, size_t size)
 	do {
 	do {
 		void __iomem *pds;
 		void __iomem *pds;
 		/* Standard PCI ROMs start out with these bytes 55 AA */
 		/* Standard PCI ROMs start out with these bytes 55 AA */
-		if (readb(image) != 0x55)
+		if (readb(image) != 0x55) {
+			dev_err(&pdev->dev, "Invalid ROM contents\n");
 			break;
 			break;
+		}
 		if (readb(image + 1) != 0xAA)
 		if (readb(image + 1) != 0xAA)
 			break;
 			break;
 		/* get the PCI data structure and check its signature */
 		/* get the PCI data structure and check its signature */
@@ -159,7 +161,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
 	 * size is much larger than the actual size of the ROM.
 	 * size is much larger than the actual size of the ROM.
 	 * True size is important if the ROM is going to be copied.
 	 * True size is important if the ROM is going to be copied.
 	 */
 	 */
-	*size = pci_get_rom_size(rom, *size);
+	*size = pci_get_rom_size(pdev, rom, *size);
 	return rom;
 	return rom;
 }
 }
 
 

+ 1 - 0
drivers/platform/x86/Kconfig

@@ -42,6 +42,7 @@ config ASUS_LAPTOP
 	depends on LEDS_CLASS
 	depends on LEDS_CLASS
 	depends on NEW_LEDS
 	depends on NEW_LEDS
 	depends on BACKLIGHT_CLASS_DEVICE
 	depends on BACKLIGHT_CLASS_DEVICE
+	depends on INPUT
 	---help---
 	---help---
 	  This is the new Linux driver for Asus laptops. It may also support some
 	  This is the new Linux driver for Asus laptops. It may also support some
 	  MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
 	  MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate

+ 165 - 11
drivers/platform/x86/asus-laptop.c

@@ -46,6 +46,7 @@
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
+#include <linux/input.h>
 
 
 #define ASUS_LAPTOP_VERSION "0.42"
 #define ASUS_LAPTOP_VERSION "0.42"
 
 
@@ -181,6 +182,8 @@ struct asus_hotk {
 	u8 light_level;		//light sensor level
 	u8 light_level;		//light sensor level
 	u8 light_switch;	//light sensor switch value
 	u8 light_switch;	//light sensor switch value
 	u16 event_count[128];	//count for each event TODO make this better
 	u16 event_count[128];	//count for each event TODO make this better
+	struct input_dev *inputdev;
+	u16 *keycode_map;
 };
 };
 
 
 /*
 /*
@@ -250,6 +253,37 @@ ASUS_LED(rled, "record");
 ASUS_LED(pled, "phone");
 ASUS_LED(pled, "phone");
 ASUS_LED(gled, "gaming");
 ASUS_LED(gled, "gaming");
 
 
+struct key_entry {
+	char type;
+	u8 code;
+	u16 keycode;
+};
+
+enum { KE_KEY, KE_END };
+
+static struct key_entry asus_keymap[] = {
+	{KE_KEY, 0x30, KEY_VOLUMEUP},
+	{KE_KEY, 0x31, KEY_VOLUMEDOWN},
+	{KE_KEY, 0x32, KEY_MUTE},
+	{KE_KEY, 0x33, KEY_SWITCHVIDEOMODE},
+	{KE_KEY, 0x34, KEY_SWITCHVIDEOMODE},
+	{KE_KEY, 0x40, KEY_PREVIOUSSONG},
+	{KE_KEY, 0x41, KEY_NEXTSONG},
+	{KE_KEY, 0x43, KEY_STOP},
+	{KE_KEY, 0x45, KEY_PLAYPAUSE},
+	{KE_KEY, 0x50, KEY_EMAIL},
+	{KE_KEY, 0x51, KEY_WWW},
+	{KE_KEY, 0x5C, BTN_EXTRA},  /* Performance */
+	{KE_KEY, 0x5D, KEY_WLAN},
+	{KE_KEY, 0x61, KEY_SWITCHVIDEOMODE},
+	{KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */
+	{KE_KEY, 0x82, KEY_CAMERA},
+	{KE_KEY, 0x8A, KEY_TV},
+	{KE_KEY, 0x95, KEY_MEDIA},
+	{KE_KEY, 0x99, KEY_PHONE},
+	{KE_END, 0},
+};
+
 /*
 /*
  * This function evaluates an ACPI method, given an int as parameter, the
  * This function evaluates an ACPI method, given an int as parameter, the
  * method is searched within the scope of the handle, can be NULL. The output
  * method is searched within the scope of the handle, can be NULL. The output
@@ -720,8 +754,68 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
 	return store_status(buf, count, NULL, GPS_ON);
 	return store_status(buf, count, NULL, GPS_ON);
 }
 }
 
 
+/*
+ * Hotkey functions
+ */
+static struct key_entry *asus_get_entry_by_scancode(int code)
+{
+	struct key_entry *key;
+
+	for (key = asus_keymap; key->type != KE_END; key++)
+		if (code == key->code)
+			return key;
+
+	return NULL;
+}
+
+static struct key_entry *asus_get_entry_by_keycode(int code)
+{
+	struct key_entry *key;
+
+	for (key = asus_keymap; key->type != KE_END; key++)
+		if (code == key->keycode && key->type == KE_KEY)
+			return key;
+
+	return NULL;
+}
+
+static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+	struct key_entry *key = asus_get_entry_by_scancode(scancode);
+
+	if (key && key->type == KE_KEY) {
+		*keycode = key->keycode;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
+{
+	struct key_entry *key;
+	int old_keycode;
+
+	if (keycode < 0 || keycode > KEY_MAX)
+		return -EINVAL;
+
+	key = asus_get_entry_by_scancode(scancode);
+	if (key && key->type == KE_KEY) {
+		old_keycode = key->keycode;
+		key->keycode = keycode;
+		set_bit(keycode, dev->keybit);
+		if (!asus_get_entry_by_keycode(old_keycode))
+			clear_bit(old_keycode, dev->keybit);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
 static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
 {
 {
+	static struct key_entry *key;
+
 	/* TODO Find a better way to handle events count. */
 	/* TODO Find a better way to handle events count. */
 	if (!hotk)
 	if (!hotk)
 		return;
 		return;
@@ -738,10 +832,24 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
 		lcd_blank(FB_BLANK_POWERDOWN);
 		lcd_blank(FB_BLANK_POWERDOWN);
 	}
 	}
 
 
-	acpi_bus_generate_proc_event(hotk->device, event,
-				hotk->event_count[event % 128]++);
-
-	return;
+	acpi_bus_generate_netlink_event(hotk->device->pnp.device_class,
+					dev_name(&hotk->device->dev), event,
+					hotk->event_count[event % 128]++);
+
+	if (hotk->inputdev) {
+		key = asus_get_entry_by_scancode(event);
+		if (!key)
+			return ;
+
+		switch (key->type) {
+		case KE_KEY:
+			input_report_key(hotk->inputdev, key->keycode, 1);
+			input_sync(hotk->inputdev);
+			input_report_key(hotk->inputdev, key->keycode, 0);
+			input_sync(hotk->inputdev);
+			break;
+		}
+	}
 }
 }
 
 
 #define ASUS_CREATE_DEVICE_ATTR(_name)					\
 #define ASUS_CREATE_DEVICE_ATTR(_name)					\
@@ -959,6 +1067,38 @@ static int asus_hotk_get_info(void)
 	return AE_OK;
 	return AE_OK;
 }
 }
 
 
+static int asus_input_init(void)
+{
+	const struct key_entry *key;
+	int result;
+
+	hotk->inputdev = input_allocate_device();
+	if (!hotk->inputdev) {
+		printk(ASUS_INFO "Unable to allocate input device\n");
+		return 0;
+	}
+	hotk->inputdev->name = "Asus Laptop extra buttons";
+	hotk->inputdev->phys = ASUS_HOTK_FILE "/input0";
+	hotk->inputdev->id.bustype = BUS_HOST;
+	hotk->inputdev->getkeycode = asus_getkeycode;
+	hotk->inputdev->setkeycode = asus_setkeycode;
+
+	for (key = asus_keymap; key->type != KE_END; key++) {
+		switch (key->type) {
+		case KE_KEY:
+			set_bit(EV_KEY, hotk->inputdev->evbit);
+			set_bit(key->keycode, hotk->inputdev->keybit);
+			break;
+		}
+	}
+	result = input_register_device(hotk->inputdev);
+	if (result) {
+		printk(ASUS_INFO "Unable to register input device\n");
+		input_free_device(hotk->inputdev);
+	}
+	return result;
+}
+
 static int asus_hotk_check(void)
 static int asus_hotk_check(void)
 {
 {
 	int result = 0;
 	int result = 0;
@@ -1044,7 +1184,7 @@ static int asus_hotk_add(struct acpi_device *device)
 	/* GPS is on by default */
 	/* GPS is on by default */
 	write_status(NULL, 1, GPS_ON);
 	write_status(NULL, 1, GPS_ON);
 
 
-      end:
+end:
 	if (result) {
 	if (result) {
 		kfree(hotk->name);
 		kfree(hotk->name);
 		kfree(hotk);
 		kfree(hotk);
@@ -1091,10 +1231,17 @@ static void asus_led_exit(void)
 	ASUS_LED_UNREGISTER(gled);
 	ASUS_LED_UNREGISTER(gled);
 }
 }
 
 
+static void asus_input_exit(void)
+{
+	if (hotk->inputdev)
+		input_unregister_device(hotk->inputdev);
+}
+
 static void __exit asus_laptop_exit(void)
 static void __exit asus_laptop_exit(void)
 {
 {
 	asus_backlight_exit();
 	asus_backlight_exit();
 	asus_led_exit();
 	asus_led_exit();
+	asus_input_exit();
 
 
 	acpi_bus_unregister_driver(&asus_hotk_driver);
 	acpi_bus_unregister_driver(&asus_hotk_driver);
 	sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);
 	sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);
@@ -1216,6 +1363,10 @@ static int __init asus_laptop_init(void)
 		printk(ASUS_INFO "Brightness ignored, must be controlled by "
 		printk(ASUS_INFO "Brightness ignored, must be controlled by "
 		       "ACPI video driver\n");
 		       "ACPI video driver\n");
 
 
+	result = asus_input_init();
+	if (result)
+		goto fail_input;
+
 	result = asus_led_init(dev);
 	result = asus_led_init(dev);
 	if (result)
 	if (result)
 		goto fail_led;
 		goto fail_led;
@@ -1242,22 +1393,25 @@ static int __init asus_laptop_init(void)
 
 
 	return 0;
 	return 0;
 
 
-      fail_sysfs:
+fail_sysfs:
 	platform_device_del(asuspf_device);
 	platform_device_del(asuspf_device);
 
 
-      fail_platform_device2:
+fail_platform_device2:
 	platform_device_put(asuspf_device);
 	platform_device_put(asuspf_device);
 
 
-      fail_platform_device1:
+fail_platform_device1:
 	platform_driver_unregister(&asuspf_driver);
 	platform_driver_unregister(&asuspf_driver);
 
 
-      fail_platform_driver:
+fail_platform_driver:
 	asus_led_exit();
 	asus_led_exit();
 
 
-      fail_led:
+fail_led:
+	asus_input_exit();
+
+fail_input:
 	asus_backlight_exit();
 	asus_backlight_exit();
 
 
-      fail_backlight:
+fail_backlight:
 
 
 	return result;
 	return result;
 }
 }

+ 15 - 1
drivers/platform/x86/asus_acpi.c

@@ -143,6 +143,7 @@ struct asus_hotk {
 							 S1300N, S5200N*/
 							 S1300N, S5200N*/
 		A4S,            /* Z81sp */
 		A4S,            /* Z81sp */
 		F3Sa,		/* (Centrino) */
 		F3Sa,		/* (Centrino) */
+		R1F,
 		END_MODEL
 		END_MODEL
 	} model;		/* Models currently supported */
 	} model;		/* Models currently supported */
 	u16 event_count[128];	/* Count for each event TODO make this better */
 	u16 event_count[128];	/* Count for each event TODO make this better */
@@ -420,7 +421,18 @@ static struct model_data model_conf[END_MODEL] = {
 		.display_get	= "\\ADVG",
 		.display_get	= "\\ADVG",
 		.display_set	= "SDSP",
 		.display_set	= "SDSP",
 	},
 	},
-
+	{
+		.name = "R1F",
+		.mt_bt_switch = "BLED",
+		.mt_mled = "MLED",
+		.mt_wled = "WLED",
+		.mt_lcd_switch = "\\Q10",
+		.lcd_status = "\\GP06",
+		.brightness_set = "SPLV",
+		.brightness_get = "GPLV",
+		.display_set = "SDSP",
+		.display_get = "\\INFB"
+	}
 };
 };
 
 
 /* procdir we use */
 /* procdir we use */
@@ -1165,6 +1177,8 @@ static int asus_model_match(char *model)
 		return W3V;
 		return W3V;
 	else if (strncmp(model, "W5A", 3) == 0)
 	else if (strncmp(model, "W5A", 3) == 0)
 		return W5A;
 		return W5A;
+	else if (strncmp(model, "R1F", 3) == 0)
+		return R1F;
 	else if (strncmp(model, "A4S", 3) == 0)
 	else if (strncmp(model, "A4S", 3) == 0)
 		return A4S;
 		return A4S;
 	else if (strncmp(model, "F3Sa", 4) == 0)
 	else if (strncmp(model, "F3Sa", 4) == 0)

+ 144 - 20
drivers/platform/x86/eeepc-laptop.c

@@ -30,6 +30,7 @@
 #include <linux/uaccess.h>
 #include <linux/uaccess.h>
 #include <linux/input.h>
 #include <linux/input.h>
 #include <linux/rfkill.h>
 #include <linux/rfkill.h>
+#include <linux/pci.h>
 
 
 #define EEEPC_LAPTOP_VERSION	"0.1"
 #define EEEPC_LAPTOP_VERSION	"0.1"
 
 
@@ -161,6 +162,10 @@ static struct key_entry eeepc_keymap[] = {
 	{KE_KEY, 0x13, KEY_MUTE },
 	{KE_KEY, 0x13, KEY_MUTE },
 	{KE_KEY, 0x14, KEY_VOLUMEDOWN },
 	{KE_KEY, 0x14, KEY_VOLUMEDOWN },
 	{KE_KEY, 0x15, KEY_VOLUMEUP },
 	{KE_KEY, 0x15, KEY_VOLUMEUP },
+	{KE_KEY, 0x1a, KEY_COFFEE },
+	{KE_KEY, 0x1b, KEY_ZOOM },
+	{KE_KEY, 0x1c, KEY_PROG2 },
+	{KE_KEY, 0x1d, KEY_PROG3 },
 	{KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
 	{KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
 	{KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
 	{KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
 	{KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
 	{KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
@@ -510,7 +515,43 @@ static int eeepc_hotk_check(void)
 static void notify_brn(void)
 static void notify_brn(void)
 {
 {
 	struct backlight_device *bd = eeepc_backlight_device;
 	struct backlight_device *bd = eeepc_backlight_device;
-	bd->props.brightness = read_brightness(bd);
+	if (bd)
+		bd->props.brightness = read_brightness(bd);
+}
+
+static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
+{
+	struct pci_dev *dev;
+	struct pci_bus *bus = pci_find_bus(0, 1);
+
+	if (event != ACPI_NOTIFY_BUS_CHECK)
+		return;
+
+	if (!bus) {
+		printk(EEEPC_WARNING "Unable to find PCI bus 1?\n");
+		return;
+	}
+
+	if (get_acpi(CM_ASL_WLAN) == 1) {
+		dev = pci_get_slot(bus, 0);
+		if (dev) {
+			/* Device already present */
+			pci_dev_put(dev);
+			return;
+		}
+		dev = pci_scan_single_device(bus, 0);
+		if (dev) {
+			pci_bus_assign_resources(bus);
+			if (pci_bus_add_device(dev))
+				printk(EEEPC_ERR "Unable to hotplug wifi\n");
+		}
+	} else {
+		dev = pci_get_slot(bus, 0);
+		if (dev) {
+			pci_remove_bus_device(dev);
+			pci_dev_put(dev);
+		}
+	}
 }
 }
 
 
 static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
 static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
@@ -520,8 +561,9 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
 		return;
 		return;
 	if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
 	if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
 		notify_brn();
 		notify_brn();
-	acpi_bus_generate_proc_event(ehotk->device, event,
-				     ehotk->event_count[event % 128]++);
+	acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
+					dev_name(&ehotk->device->dev), event,
+					ehotk->event_count[event % 128]++);
 	if (ehotk->inputdev) {
 	if (ehotk->inputdev) {
 		key = eepc_get_entry_by_scancode(event);
 		key = eepc_get_entry_by_scancode(event);
 		if (key) {
 		if (key) {
@@ -539,6 +581,45 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
 	}
 	}
 }
 }
 
 
+static int eeepc_register_rfkill_notifier(char *node)
+{
+	acpi_status status = AE_OK;
+	acpi_handle handle;
+
+	status = acpi_get_handle(NULL, node, &handle);
+
+	if (ACPI_SUCCESS(status)) {
+		status = acpi_install_notify_handler(handle,
+						     ACPI_SYSTEM_NOTIFY,
+						     eeepc_rfkill_notify,
+						     NULL);
+		if (ACPI_FAILURE(status))
+			printk(EEEPC_WARNING
+			       "Failed to register notify on %s\n", node);
+	} else
+		return -ENODEV;
+
+	return 0;
+}
+
+static void eeepc_unregister_rfkill_notifier(char *node)
+{
+	acpi_status status = AE_OK;
+	acpi_handle handle;
+
+	status = acpi_get_handle(NULL, node, &handle);
+
+	if (ACPI_SUCCESS(status)) {
+		status = acpi_remove_notify_handler(handle,
+						     ACPI_SYSTEM_NOTIFY,
+						     eeepc_rfkill_notify);
+		if (ACPI_FAILURE(status))
+			printk(EEEPC_ERR
+			       "Error removing rfkill notify handler %s\n",
+				node);
+	}
+}
+
 static int eeepc_hotk_add(struct acpi_device *device)
 static int eeepc_hotk_add(struct acpi_device *device)
 {
 {
 	acpi_status status = AE_OK;
 	acpi_status status = AE_OK;
@@ -558,7 +639,7 @@ static int eeepc_hotk_add(struct acpi_device *device)
 	ehotk->device = device;
 	ehotk->device = device;
 	result = eeepc_hotk_check();
 	result = eeepc_hotk_check();
 	if (result)
 	if (result)
-		goto end;
+		goto ehotk_fail;
 	status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
 	status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
 					     eeepc_hotk_notify, ehotk);
 					     eeepc_hotk_notify, ehotk);
 	if (ACPI_FAILURE(status))
 	if (ACPI_FAILURE(status))
@@ -569,18 +650,25 @@ static int eeepc_hotk_add(struct acpi_device *device)
 							   RFKILL_TYPE_WLAN);
 							   RFKILL_TYPE_WLAN);
 
 
 		if (!ehotk->eeepc_wlan_rfkill)
 		if (!ehotk->eeepc_wlan_rfkill)
-			goto end;
+			goto wlan_fail;
 
 
 		ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan";
 		ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan";
 		ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set;
 		ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set;
 		ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
 		ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
-		if (get_acpi(CM_ASL_WLAN) == 1)
+		if (get_acpi(CM_ASL_WLAN) == 1) {
 			ehotk->eeepc_wlan_rfkill->state =
 			ehotk->eeepc_wlan_rfkill->state =
 				RFKILL_STATE_UNBLOCKED;
 				RFKILL_STATE_UNBLOCKED;
-		else
+			rfkill_set_default(RFKILL_TYPE_WLAN,
+					   RFKILL_STATE_UNBLOCKED);
+		} else {
 			ehotk->eeepc_wlan_rfkill->state =
 			ehotk->eeepc_wlan_rfkill->state =
 				RFKILL_STATE_SOFT_BLOCKED;
 				RFKILL_STATE_SOFT_BLOCKED;
-		rfkill_register(ehotk->eeepc_wlan_rfkill);
+			rfkill_set_default(RFKILL_TYPE_WLAN,
+					   RFKILL_STATE_SOFT_BLOCKED);
+		}
+		result = rfkill_register(ehotk->eeepc_wlan_rfkill);
+		if (result)
+			goto wlan_fail;
 	}
 	}
 
 
 	if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
 	if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
@@ -588,27 +676,47 @@ static int eeepc_hotk_add(struct acpi_device *device)
 			rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH);
 			rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH);
 
 
 		if (!ehotk->eeepc_bluetooth_rfkill)
 		if (!ehotk->eeepc_bluetooth_rfkill)
-			goto end;
+			goto bluetooth_fail;
 
 
 		ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth";
 		ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth";
 		ehotk->eeepc_bluetooth_rfkill->toggle_radio =
 		ehotk->eeepc_bluetooth_rfkill->toggle_radio =
 			eeepc_bluetooth_rfkill_set;
 			eeepc_bluetooth_rfkill_set;
 		ehotk->eeepc_bluetooth_rfkill->get_state =
 		ehotk->eeepc_bluetooth_rfkill->get_state =
 			eeepc_bluetooth_rfkill_state;
 			eeepc_bluetooth_rfkill_state;
-		if (get_acpi(CM_ASL_BLUETOOTH) == 1)
+		if (get_acpi(CM_ASL_BLUETOOTH) == 1) {
 			ehotk->eeepc_bluetooth_rfkill->state =
 			ehotk->eeepc_bluetooth_rfkill->state =
 				RFKILL_STATE_UNBLOCKED;
 				RFKILL_STATE_UNBLOCKED;
-		else
+			rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
+					   RFKILL_STATE_UNBLOCKED);
+		} else {
 			ehotk->eeepc_bluetooth_rfkill->state =
 			ehotk->eeepc_bluetooth_rfkill->state =
 				RFKILL_STATE_SOFT_BLOCKED;
 				RFKILL_STATE_SOFT_BLOCKED;
-		rfkill_register(ehotk->eeepc_bluetooth_rfkill);
-	}
+			rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
+					   RFKILL_STATE_SOFT_BLOCKED);
+		}
 
 
- end:
-	if (result) {
-		kfree(ehotk);
-		ehotk = NULL;
+		result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
+		if (result)
+			goto bluetooth_fail;
 	}
 	}
+
+	eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
+	eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
+
+	return 0;
+
+ bluetooth_fail:
+	if (ehotk->eeepc_bluetooth_rfkill)
+		rfkill_free(ehotk->eeepc_bluetooth_rfkill);
+	rfkill_unregister(ehotk->eeepc_wlan_rfkill);
+	ehotk->eeepc_wlan_rfkill = NULL;
+ wlan_fail:
+	if (ehotk->eeepc_wlan_rfkill)
+		rfkill_free(ehotk->eeepc_wlan_rfkill);
+ ehotk_fail:
+	kfree(ehotk);
+	ehotk = NULL;
+
 	return result;
 	return result;
 }
 }
 
 
@@ -622,6 +730,10 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type)
 					    eeepc_hotk_notify);
 					    eeepc_hotk_notify);
 	if (ACPI_FAILURE(status))
 	if (ACPI_FAILURE(status))
 		printk(EEEPC_ERR "Error removing notify handler\n");
 		printk(EEEPC_ERR "Error removing notify handler\n");
+
+	eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
+	eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
+
 	kfree(ehotk);
 	kfree(ehotk);
 	return 0;
 	return 0;
 }
 }
@@ -737,13 +849,21 @@ static void eeepc_backlight_exit(void)
 {
 {
 	if (eeepc_backlight_device)
 	if (eeepc_backlight_device)
 		backlight_device_unregister(eeepc_backlight_device);
 		backlight_device_unregister(eeepc_backlight_device);
-	if (ehotk->inputdev)
-		input_unregister_device(ehotk->inputdev);
+	eeepc_backlight_device = NULL;
+}
+
+static void eeepc_rfkill_exit(void)
+{
 	if (ehotk->eeepc_wlan_rfkill)
 	if (ehotk->eeepc_wlan_rfkill)
 		rfkill_unregister(ehotk->eeepc_wlan_rfkill);
 		rfkill_unregister(ehotk->eeepc_wlan_rfkill);
 	if (ehotk->eeepc_bluetooth_rfkill)
 	if (ehotk->eeepc_bluetooth_rfkill)
 		rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
 		rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
-	eeepc_backlight_device = NULL;
+}
+
+static void eeepc_input_exit(void)
+{
+	if (ehotk->inputdev)
+		input_unregister_device(ehotk->inputdev);
 }
 }
 
 
 static void eeepc_hwmon_exit(void)
 static void eeepc_hwmon_exit(void)
@@ -762,6 +882,8 @@ static void eeepc_hwmon_exit(void)
 static void __exit eeepc_laptop_exit(void)
 static void __exit eeepc_laptop_exit(void)
 {
 {
 	eeepc_backlight_exit();
 	eeepc_backlight_exit();
+	eeepc_rfkill_exit();
+	eeepc_input_exit();
 	eeepc_hwmon_exit();
 	eeepc_hwmon_exit();
 	acpi_bus_unregister_driver(&eeepc_hotk_driver);
 	acpi_bus_unregister_driver(&eeepc_hotk_driver);
 	sysfs_remove_group(&platform_device->dev.kobj,
 	sysfs_remove_group(&platform_device->dev.kobj,
@@ -865,6 +987,8 @@ fail_platform_driver:
 fail_hwmon:
 fail_hwmon:
 	eeepc_backlight_exit();
 	eeepc_backlight_exit();
 fail_backlight:
 fail_backlight:
+	eeepc_input_exit();
+	eeepc_rfkill_exit();
 	return result;
 	return result;
 }
 }
 
 

+ 4 - 2
drivers/platform/x86/hp-wmi.c

@@ -463,9 +463,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
 
 
 	return 0;
 	return 0;
 register_wwan_err:
 register_wwan_err:
-	rfkill_unregister(bluetooth_rfkill);
+	if (bluetooth_rfkill)
+		rfkill_unregister(bluetooth_rfkill);
 register_bluetooth_error:
 register_bluetooth_error:
-	rfkill_unregister(wifi_rfkill);
+	if (wifi_rfkill)
+		rfkill_unregister(wifi_rfkill);
 add_sysfs_error:
 add_sysfs_error:
 	cleanup_sysfs(device);
 	cleanup_sysfs(device);
 	return err;
 	return err;

+ 1 - 1
drivers/platform/x86/panasonic-laptop.c

@@ -507,7 +507,7 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
 
 
 	hkey_num = result & 0xf;
 	hkey_num = result & 0xf;
 
 
-	if (hkey_num < 0 || hkey_num > ARRAY_SIZE(pcc->keymap)) {
+	if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 				  "hotkey number out of range: %d\n",
 				  "hotkey number out of range: %d\n",
 				  hkey_num));
 				  hkey_num));

+ 6 - 0
drivers/rtc/Kconfig

@@ -241,6 +241,12 @@ config RTC_DRV_M41T80_WDT
 	  If you say Y here you will get support for the
 	  If you say Y here you will get support for the
 	  watchdog timer in the ST M41T60 and M41T80 RTC chips series.
 	  watchdog timer in the ST M41T60 and M41T80 RTC chips series.
 
 
+config RTC_DRV_DM355EVM
+	tristate "TI DaVinci DM355 EVM RTC"
+	depends on MFD_DM355EVM_MSP
+	help
+	  Supports the RTC firmware in the MSP430 on the DM355 EVM.
+
 config RTC_DRV_TWL92330
 config RTC_DRV_TWL92330
 	boolean "TI TWL92330/Menelaus"
 	boolean "TI TWL92330/Menelaus"
 	depends on MENELAUS
 	depends on MENELAUS

+ 1 - 0
drivers/rtc/Makefile

@@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91SAM9)	+= rtc-at91sam9.o
 obj-$(CONFIG_RTC_DRV_AU1XXX)	+= rtc-au1xxx.o
 obj-$(CONFIG_RTC_DRV_AU1XXX)	+= rtc-au1xxx.o
 obj-$(CONFIG_RTC_DRV_BFIN)	+= rtc-bfin.o
 obj-$(CONFIG_RTC_DRV_BFIN)	+= rtc-bfin.o
 obj-$(CONFIG_RTC_DRV_CMOS)	+= rtc-cmos.o
 obj-$(CONFIG_RTC_DRV_CMOS)	+= rtc-cmos.o
+obj-$(CONFIG_RTC_DRV_DM355EVM)	+= rtc-dm355evm.o
 obj-$(CONFIG_RTC_DRV_DS1216)	+= rtc-ds1216.o
 obj-$(CONFIG_RTC_DRV_DS1216)	+= rtc-ds1216.o
 obj-$(CONFIG_RTC_DRV_DS1286)	+= rtc-ds1286.o
 obj-$(CONFIG_RTC_DRV_DS1286)	+= rtc-ds1286.o
 obj-$(CONFIG_RTC_DRV_DS1302)	+= rtc-ds1302.o
 obj-$(CONFIG_RTC_DRV_DS1302)	+= rtc-ds1302.o

+ 175 - 0
drivers/rtc/rtc-dm355evm.c

@@ -0,0 +1,175 @@
+/*
+ * rtc-dm355evm.c - access battery-backed counter in MSP430 firmware
+ *
+ * Copyright (c) 2008 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+
+#include <linux/i2c/dm355evm_msp.h>
+
+
+/*
+ * The MSP430 firmware on the DM355 EVM uses a watch crystal to feed
+ * a 1 Hz counter.  When a backup battery is supplied, that makes a
+ * reasonable RTC for applications where alarms and non-NTP drift
+ * compensation aren't important.
+ *
+ * The only real glitch is the inability to read or write all four
+ * counter bytes atomically:  the count may increment in the middle
+ * of an operation, causing trouble when the LSB rolls over.
+ *
+ * This driver was tested with firmware revision A4.
+ */
+union evm_time {
+	u8	bytes[4];
+	u32	value;
+};
+
+static int dm355evm_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	union evm_time	time;
+	int		status;
+	int		tries = 0;
+
+	do {
+		/*
+		 * Read LSB(0) to MSB(3) bytes.  Defend against the counter
+		 * rolling over by re-reading until the value is stable,
+		 * and assuming the four reads take at most a few seconds.
+		 */
+		status = dm355evm_msp_read(DM355EVM_MSP_RTC_0);
+		if (status < 0)
+			return status;
+		if (tries && time.bytes[0] == status)
+			break;
+		time.bytes[0] = status;
+
+		status = dm355evm_msp_read(DM355EVM_MSP_RTC_1);
+		if (status < 0)
+			return status;
+		if (tries && time.bytes[1] == status)
+			break;
+		time.bytes[1] = status;
+
+		status = dm355evm_msp_read(DM355EVM_MSP_RTC_2);
+		if (status < 0)
+			return status;
+		if (tries && time.bytes[2] == status)
+			break;
+		time.bytes[2] = status;
+
+		status = dm355evm_msp_read(DM355EVM_MSP_RTC_3);
+		if (status < 0)
+			return status;
+		if (tries && time.bytes[3] == status)
+			break;
+		time.bytes[3] = status;
+
+	} while (++tries < 5);
+
+	dev_dbg(dev, "read timestamp %08x\n", time.value);
+
+	rtc_time_to_tm(le32_to_cpu(time.value), tm);
+	return 0;
+}
+
+static int dm355evm_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	union evm_time	time;
+	unsigned long	value;
+	int		status;
+
+	rtc_tm_to_time(tm, &value);
+	time.value = cpu_to_le32(value);
+
+	dev_dbg(dev, "write timestamp %08x\n", time.value);
+
+	/*
+	 * REVISIT handle non-atomic writes ... maybe just retry until
+	 * byte[1] sticks (no rollover)?
+	 */
+	status = dm355evm_msp_write(time.bytes[0], DM355EVM_MSP_RTC_0);
+	if (status < 0)
+		return status;
+
+	status = dm355evm_msp_write(time.bytes[1], DM355EVM_MSP_RTC_1);
+	if (status < 0)
+		return status;
+
+	status = dm355evm_msp_write(time.bytes[2], DM355EVM_MSP_RTC_2);
+	if (status < 0)
+		return status;
+
+	status = dm355evm_msp_write(time.bytes[3], DM355EVM_MSP_RTC_3);
+	if (status < 0)
+		return status;
+
+	return 0;
+}
+
+static struct rtc_class_ops dm355evm_rtc_ops = {
+	.read_time	= dm355evm_rtc_read_time,
+	.set_time	= dm355evm_rtc_set_time,
+};
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit dm355evm_rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+
+	rtc = rtc_device_register(pdev->name,
+				  &pdev->dev, &dm355evm_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
+			PTR_ERR(rtc));
+		return PTR_ERR(rtc);
+	}
+	platform_set_drvdata(pdev, rtc);
+
+	return 0;
+}
+
+static int __devexit dm355evm_rtc_remove(struct platform_device *pdev)
+{
+	struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+	rtc_device_unregister(rtc);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+/*
+ * I2C is used to talk to the MSP430, but this platform device is
+ * exposed by an MFD driver that manages I2C communications.
+ */
+static struct platform_driver rtc_dm355evm_driver = {
+	.probe		= dm355evm_rtc_probe,
+	.remove		= __devexit_p(dm355evm_rtc_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "rtc-dm355evm",
+	},
+};
+
+static int __init dm355evm_rtc_init(void)
+{
+	return platform_driver_register(&rtc_dm355evm_driver);
+}
+module_init(dm355evm_rtc_init);
+
+static void __exit dm355evm_rtc_exit(void)
+{
+	platform_driver_unregister(&rtc_dm355evm_driver);
+}
+module_exit(dm355evm_rtc_exit);
+
+MODULE_LICENSE("GPL");

+ 0 - 1
drivers/rtc/rtc-ds1390.c

@@ -122,7 +122,6 @@ static const struct rtc_class_ops ds1390_rtc_ops = {
 
 
 static int __devinit ds1390_probe(struct spi_device *spi)
 static int __devinit ds1390_probe(struct spi_device *spi)
 {
 {
-	struct rtc_device *rtc;
 	unsigned char tmp;
 	unsigned char tmp;
 	struct ds1390 *chip;
 	struct ds1390 *chip;
 	int res;
 	int res;

+ 19 - 14
drivers/video/aty/aty128fb.c

@@ -1475,7 +1475,7 @@ static int aty128fb_set_par(struct fb_info *info)
 	aty128_set_pll(&par->pll, par);
 	aty128_set_pll(&par->pll, par);
 	aty128_set_fifo(&par->fifo_reg, par);
 	aty128_set_fifo(&par->fifo_reg, par);
 
 
-	config = aty_ld_le32(CONFIG_CNTL) & ~3;
+	config = aty_ld_le32(CNFG_CNTL) & ~3;
 
 
 #if defined(__BIG_ENDIAN)
 #if defined(__BIG_ENDIAN)
 	if (par->crtc.bpp == 32)
 	if (par->crtc.bpp == 32)
@@ -1484,7 +1484,7 @@ static int aty128fb_set_par(struct fb_info *info)
 		config |= 1;	/* make aperture do 16 bit swapping */
 		config |= 1;	/* make aperture do 16 bit swapping */
 #endif
 #endif
 
 
-	aty_st_le32(CONFIG_CNTL, config);
+	aty_st_le32(CNFG_CNTL, config);
 	aty_st_8(CRTC_EXT_CNTL + 1, 0);	/* turn the video back on */
 	aty_st_8(CRTC_EXT_CNTL + 1, 0);	/* turn the video back on */
 
 
 	info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
 	info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
@@ -1875,7 +1875,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i
 	u32 dac;
 	u32 dac;
 
 
 	/* Get the chip revision */
 	/* Get the chip revision */
-	chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
+	chip_rev = (aty_ld_le32(CNFG_CNTL) >> 16) & 0x1F;
 
 
 	strcpy(video_card, "Rage128 XX ");
 	strcpy(video_card, "Rage128 XX ");
 	video_card[8] = ent->device >> 8;
 	video_card[8] = ent->device >> 8;
@@ -2057,7 +2057,7 @@ static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_
 
 
 	/* Grab memory size from the card */
 	/* Grab memory size from the card */
 	// How does this relate to the resource length from the PCI hardware?
 	// How does this relate to the resource length from the PCI hardware?
-	par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
+	par->vram_size = aty_ld_le32(CNFG_MEMSIZE) & 0x03FFFFFF;
 
 
 	/* Virtualize the framebuffer */
 	/* Virtualize the framebuffer */
 	info->screen_base = ioremap(fb_addr, par->vram_size);
 	info->screen_base = ioremap(fb_addr, par->vram_size);
@@ -2374,6 +2374,8 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
 	/* Set the chip into the appropriate suspend mode (we use D2,
 	/* Set the chip into the appropriate suspend mode (we use D2,
 	 * D3 would require a complete re-initialisation of the chip,
 	 * D3 would require a complete re-initialisation of the chip,
 	 * including PCI config registers, clocks, AGP configuration, ...)
 	 * including PCI config registers, clocks, AGP configuration, ...)
+	 *
+	 * For resume, the core will have already brought us back to D0
 	 */
 	 */
 	if (suspend) {
 	if (suspend) {
 		/* Make sure CRTC2 is reset. Remove that the day we decide to
 		/* Make sure CRTC2 is reset. Remove that the day we decide to
@@ -2391,17 +2393,9 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
 		aty_st_le32(BUS_CNTL1, 0x00000010);
 		aty_st_le32(BUS_CNTL1, 0x00000010);
 		aty_st_le32(MEM_POWER_MISC, 0x0c830000);
 		aty_st_le32(MEM_POWER_MISC, 0x0c830000);
 		mdelay(100);
 		mdelay(100);
-		pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
+
 		/* Switch PCI power management to D2 */
 		/* Switch PCI power management to D2 */
-		pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL,
-			(pwr_command & ~PCI_PM_CTRL_STATE_MASK) | 2);
-		pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
-	} else {
-		/* Switch back PCI power management to D0 */
-		mdelay(100);
-		pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL, 0);
-		pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
-		mdelay(100);
+		pci_set_power_state(pdev, PCI_D2);
 	}
 	}
 }
 }
 
 
@@ -2410,6 +2404,12 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 	struct fb_info *info = pci_get_drvdata(pdev);
 	struct fb_info *info = pci_get_drvdata(pdev);
 	struct aty128fb_par *par = info->par;
 	struct aty128fb_par *par = info->par;
 
 
+	/* Because we may change PCI D state ourselves, we need to
+	 * first save the config space content so the core can
+	 * restore it properly on resume.
+	 */
+	pci_save_state(pdev);
+
 	/* We don't do anything but D2, for now we return 0, but
 	/* We don't do anything but D2, for now we return 0, but
 	 * we may want to change that. How do we know if the BIOS
 	 * we may want to change that. How do we know if the BIOS
 	 * can properly take care of D3 ? Also, with swsusp, we
 	 * can properly take care of D3 ? Also, with swsusp, we
@@ -2476,6 +2476,11 @@ static int aty128_do_resume(struct pci_dev *pdev)
 	if (pdev->dev.power.power_state.event == PM_EVENT_ON)
 	if (pdev->dev.power.power_state.event == PM_EVENT_ON)
 		return 0;
 		return 0;
 
 
+	/* PCI state will have been restored by the core, so
+	 * we should be in D0 now with our config space fully
+	 * restored
+	 */
+
 	/* Wakeup chip */
 	/* Wakeup chip */
 	aty128_set_suspend(par, 0);
 	aty128_set_suspend(par, 0);
 	par->asleep = 0;
 	par->asleep = 0;

+ 26 - 16
drivers/video/aty/atyfb_base.c

@@ -135,7 +135,7 @@
 #if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
 #if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
 defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT)
 defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT)
 static const u32 lt_lcd_regs[] = {
 static const u32 lt_lcd_regs[] = {
-	CONFIG_PANEL_LG,
+	CNFG_PANEL_LG,
 	LCD_GEN_CNTL_LG,
 	LCD_GEN_CNTL_LG,
 	DSTN_CONTROL_LG,
 	DSTN_CONTROL_LG,
 	HFB_PITCH_ADDR_LG,
 	HFB_PITCH_ADDR_LG,
@@ -446,7 +446,7 @@ static int __devinit correct_chipset(struct atyfb_par *par)
 	par->pll_limits.ecp_max = aty_chips[i].ecp_max;
 	par->pll_limits.ecp_max = aty_chips[i].ecp_max;
 	par->features = aty_chips[i].features;
 	par->features = aty_chips[i].features;
 
 
-	chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
+	chip_id = aty_ld_le32(CNFG_CHIP_ID, par);
 	type = chip_id & CFG_CHIP_TYPE;
 	type = chip_id & CFG_CHIP_TYPE;
 	rev = (chip_id & CFG_CHIP_REV) >> 24;
 	rev = (chip_id & CFG_CHIP_REV) >> 24;
 
 
@@ -629,7 +629,7 @@ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
 		    crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
 		    crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
 		    aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
 		    aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
 		}
 		}
-		crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par);
+		crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par);
 		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
 		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
 
 
 
 
@@ -676,7 +676,7 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
 		aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
 		aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
 
 
 		/* update non-shadow registers first */
 		/* update non-shadow registers first */
-		aty_st_lcd(CONFIG_PANEL, crtc->lcd_config_panel, par);
+		aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par);
 		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
 		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
 			~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
 			~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
 
 
@@ -858,7 +858,7 @@ static int aty_var_to_crtc(const struct fb_info *info,
 		if (!M64_HAS(MOBIL_BUS))
 		if (!M64_HAS(MOBIL_BUS))
 			crtc->lcd_index |= CRTC2_DISPLAY_DIS;
 			crtc->lcd_index |= CRTC2_DISPLAY_DIS;
 
 
-		crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par) | 0x4000;
+		crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par) | 0x4000;
 		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
 		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
 
 
 		crtc->lcd_gen_cntl &=
 		crtc->lcd_gen_cntl &=
@@ -1978,7 +1978,7 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par)
 
 
 	return timeout ? 0 : -EIO;
 	return timeout ? 0 : -EIO;
 }
 }
-#endif
+#endif /* CONFIG_PPC_PMAC */
 
 
 static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 {
@@ -2002,9 +2002,15 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 	par->asleep = 1;
 	par->asleep = 1;
 	par->lock_blank = 1;
 	par->lock_blank = 1;
 
 
+	/* Because we may change PCI D state ourselves, we need to
+	 * first save the config space content so the core can
+	 * restore it properly on resume.
+	 */
+	pci_save_state(pdev);
+
 #ifdef CONFIG_PPC_PMAC
 #ifdef CONFIG_PPC_PMAC
 	/* Set chip to "suspend" mode */
 	/* Set chip to "suspend" mode */
-	if (aty_power_mgmt(1, par)) {
+	if (machine_is(powermac) && aty_power_mgmt(1, par)) {
 		par->asleep = 0;
 		par->asleep = 0;
 		par->lock_blank = 0;
 		par->lock_blank = 0;
 		atyfb_blank(FB_BLANK_UNBLANK, info);
 		atyfb_blank(FB_BLANK_UNBLANK, info);
@@ -2047,11 +2053,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
 
 
 	acquire_console_sem();
 	acquire_console_sem();
 
 
+	/* PCI state will have been restored by the core, so
+	 * we should be in D0 now with our config space fully
+	 * restored
+	 */
+
 #ifdef CONFIG_PPC_PMAC
 #ifdef CONFIG_PPC_PMAC
-	if (pdev->dev.power.power_state.event == 2)
+	if (machine_is(powermac) &&
+	    pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)
 		aty_power_mgmt(0, par);
 		aty_power_mgmt(0, par);
-#else
-	pci_set_power_state(pdev, PCI_D0);
 #endif
 #endif
 
 
 	aty_resume_chip(info);
 	aty_resume_chip(info);
@@ -2254,7 +2264,7 @@ static int __devinit aty_init(struct fb_info *info)
 	if (!M64_HAS(INTEGRATED)) {
 	if (!M64_HAS(INTEGRATED)) {
 		u32 stat0;
 		u32 stat0;
 		u8 dac_type, dac_subtype, clk_type;
 		u8 dac_type, dac_subtype, clk_type;
-		stat0 = aty_ld_le32(CONFIG_STAT0, par);
+		stat0 = aty_ld_le32(CNFG_STAT0, par);
 		par->bus_type = (stat0 >> 0) & 0x07;
 		par->bus_type = (stat0 >> 0) & 0x07;
 		par->ram_type = (stat0 >> 3) & 0x07;
 		par->ram_type = (stat0 >> 3) & 0x07;
 		ramname = aty_gx_ram[par->ram_type];
 		ramname = aty_gx_ram[par->ram_type];
@@ -2324,7 +2334,7 @@ static int __devinit aty_init(struct fb_info *info)
 		par->dac_ops = &aty_dac_ct;
 		par->dac_ops = &aty_dac_ct;
 		par->pll_ops = &aty_pll_ct;
 		par->pll_ops = &aty_pll_ct;
 		par->bus_type = PCI;
 		par->bus_type = PCI;
-		par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07);
+		par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07);
 		ramname = aty_ct_ram[par->ram_type];
 		ramname = aty_ct_ram[par->ram_type];
 		/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
 		/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
 		if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
 		if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
@@ -2433,7 +2443,7 @@ static int __devinit aty_init(struct fb_info *info)
 		}
 		}
 
 
 	if (M64_HAS(MAGIC_VRAM_SIZE)) {
 	if (M64_HAS(MAGIC_VRAM_SIZE)) {
-		if (aty_ld_le32(CONFIG_STAT1, par) & 0x40000000)
+		if (aty_ld_le32(CNFG_STAT1, par) & 0x40000000)
 			info->fix.smem_len += 0x400000;
 			info->fix.smem_len += 0x400000;
 	}
 	}
 
 
@@ -2946,7 +2956,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
 		 * Fix PROMs idea of MEM_CNTL settings...
 		 * Fix PROMs idea of MEM_CNTL settings...
 		 */
 		 */
 		mem = aty_ld_le32(MEM_CNTL, par);
 		mem = aty_ld_le32(MEM_CNTL, par);
-		chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
+		chip_id = aty_ld_le32(CNFG_CHIP_ID, par);
 		if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
 		if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
 			switch (mem & 0x0f) {
 			switch (mem & 0x0f) {
 			case 3:
 			case 3:
@@ -2964,7 +2974,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
 			default:
 			default:
 				break;
 				break;
 			}
 			}
-			if ((aty_ld_le32(CONFIG_STAT0, par) & 7) >= SDRAM)
+			if ((aty_ld_le32(CNFG_STAT0, par) & 7) >= SDRAM)
 				mem &= ~(0x00700000);
 				mem &= ~(0x00700000);
 		}
 		}
 		mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
 		mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
@@ -3572,7 +3582,7 @@ static int __init atyfb_atari_probe(void)
 		}
 		}
 
 
 		/* Fake pci_id for correct_chipset() */
 		/* Fake pci_id for correct_chipset() */
-		switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) {
+		switch (aty_ld_le32(CNFG_CHIP_ID, par) & CFG_CHIP_TYPE) {
 		case 0x00d7:
 		case 0x00d7:
 			par->pci_id = PCI_CHIP_MACH64GX;
 			par->pci_id = PCI_CHIP_MACH64GX;
 			break;
 			break;

+ 5 - 5
drivers/video/aty/radeon_base.c

@@ -1936,8 +1936,8 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo)
 	OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B);
 	OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B);
 	mdelay(100);
 	mdelay(100);
 
 
-	aper_base = INREG(CONFIG_APER_0_BASE);
-	aper_size = INREG(CONFIG_APER_SIZE);
+	aper_base = INREG(CNFG_APER_0_BASE);
+	aper_size = INREG(CNFG_APER_SIZE);
 
 
 #ifdef SET_MC_FB_FROM_APERTURE
 #ifdef SET_MC_FB_FROM_APERTURE
 	/* Set framebuffer to be at the same address as set in PCI BAR */
 	/* Set framebuffer to be at the same address as set in PCI BAR */
@@ -2024,11 +2024,11 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
                      ~CRTC_H_CUTOFF_ACTIVE_EN);
                      ~CRTC_H_CUTOFF_ACTIVE_EN);
           }
           }
         } else {
         } else {
-          tmp = INREG(CONFIG_MEMSIZE);
+          tmp = INREG(CNFG_MEMSIZE);
         }
         }
 
 
 	/* mem size is bits [28:0], mask off the rest */
 	/* mem size is bits [28:0], mask off the rest */
-	rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
+	rinfo->video_ram = tmp & CNFG_MEMSIZE_MASK;
 
 
 	/*
 	/*
 	 * Hack to get around some busted production M6's
 	 * Hack to get around some busted production M6's
@@ -2228,7 +2228,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
 	 */
 	 */
 	rinfo->errata = 0;
 	rinfo->errata = 0;
 	if (rinfo->family == CHIP_FAMILY_R300 &&
 	if (rinfo->family == CHIP_FAMILY_R300 &&
-	    (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
+	    (INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK)
 	    == CFG_ATI_REV_A11)
 	    == CFG_ATI_REV_A11)
 		rinfo->errata |= CHIP_ERRATA_R300_CG;
 		rinfo->errata |= CHIP_ERRATA_R300_CG;
 
 

+ 29 - 74
drivers/video/aty/radeon_pm.c

@@ -333,7 +333,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
 	if (!rinfo->has_CRTC2) {
 	if (!rinfo->has_CRTC2) {
                 tmp = INPLL(pllSCLK_CNTL);
                 tmp = INPLL(pllSCLK_CNTL);
 
 
-		if ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13)
+		if ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13)
                     tmp &= ~(SCLK_CNTL__FORCE_CP	| SCLK_CNTL__FORCE_RB);
                     tmp &= ~(SCLK_CNTL__FORCE_CP	| SCLK_CNTL__FORCE_RB);
                 tmp &= ~(SCLK_CNTL__FORCE_HDP		| SCLK_CNTL__FORCE_DISP1 |
                 tmp &= ~(SCLK_CNTL__FORCE_HDP		| SCLK_CNTL__FORCE_DISP1 |
 			 SCLK_CNTL__FORCE_TOP		| SCLK_CNTL__FORCE_SE   |
 			 SCLK_CNTL__FORCE_TOP		| SCLK_CNTL__FORCE_SE   |
@@ -468,9 +468,9 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
 
 
 	/*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
 	/*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
 	if ((rinfo->family == CHIP_FAMILY_RV250 &&
 	if ((rinfo->family == CHIP_FAMILY_RV250 &&
-	     ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) ||
+	     ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) ||
 	    ((rinfo->family == CHIP_FAMILY_RV100) &&
 	    ((rinfo->family == CHIP_FAMILY_RV100) &&
-	     ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) {
+	     ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) {
 		tmp |= SCLK_CNTL__FORCE_CP;
 		tmp |= SCLK_CNTL__FORCE_CP;
 		tmp |= SCLK_CNTL__FORCE_VIP;
 		tmp |= SCLK_CNTL__FORCE_VIP;
 	}
 	}
@@ -486,7 +486,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
 		/* RV200::A11 A12 RV250::A11 A12 */
 		/* RV200::A11 A12 RV250::A11 A12 */
 		if (((rinfo->family == CHIP_FAMILY_RV200) ||
 		if (((rinfo->family == CHIP_FAMILY_RV200) ||
 		     (rinfo->family == CHIP_FAMILY_RV250)) &&
 		     (rinfo->family == CHIP_FAMILY_RV250)) &&
-		    ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13))
+		    ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13))
 			tmp |= SCLK_MORE_CNTL__FORCEON;
 			tmp |= SCLK_MORE_CNTL__FORCEON;
 
 
 		OUTPLL(pllSCLK_MORE_CNTL, tmp);
 		OUTPLL(pllSCLK_MORE_CNTL, tmp);
@@ -497,7 +497,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
 	/* RV200::A11 A12, RV250::A11 A12 */
 	/* RV200::A11 A12, RV250::A11 A12 */
 	if (((rinfo->family == CHIP_FAMILY_RV200) ||
 	if (((rinfo->family == CHIP_FAMILY_RV200) ||
 	     (rinfo->family == CHIP_FAMILY_RV250)) &&
 	     (rinfo->family == CHIP_FAMILY_RV250)) &&
-	    ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) {
+	    ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) {
 		tmp = INPLL(pllPLL_PWRMGT_CNTL);
 		tmp = INPLL(pllPLL_PWRMGT_CNTL);
 		tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE;
 		tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE;
 		OUTPLL(pllPLL_PWRMGT_CNTL, tmp);
 		OUTPLL(pllPLL_PWRMGT_CNTL, tmp);
@@ -702,7 +702,7 @@ static void radeon_pm_restore_regs(struct radeonfb_info *rinfo)
 	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
 	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
 	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
 	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
 	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
 	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
-	OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
+	OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
 
 
 	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
 	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
 	OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]);
 	OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]);
@@ -1723,7 +1723,7 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo)
 	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
 	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
 	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
 	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
 	OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]);
 	OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]);
-	OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
+	OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
 	OUTREG(BUS_CNTL, rinfo->save_regs[36]);
 	OUTREG(BUS_CNTL, rinfo->save_regs[36]);
 	OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
 	OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
 	OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]);
 	OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]);
@@ -1961,7 +1961,7 @@ static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo)
 	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/);
 	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/);
 	OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/);
 	OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/);
 	OUTREG(MC_IND_INDEX, 0);
 	OUTREG(MC_IND_INDEX, 0);
-	OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
+	OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
 
 
 	mdelay(20);
 	mdelay(20);
 }
 }
@@ -2361,7 +2361,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
 	OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249);
 	OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249);
 	OUTREG(MC_IND_INDEX, 0);
 	OUTREG(MC_IND_INDEX, 0);
 
 
-	OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
+	OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
 
 
 	radeon_pm_full_reset_sdram(rinfo);
 	radeon_pm_full_reset_sdram(rinfo);
 
 
@@ -2509,9 +2509,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
 
 
 static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
 static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
 {
 {
-	u16 pwr_cmd;
 	u32 tmp;
 	u32 tmp;
-	int i;
 
 
 	if (!rinfo->pm_reg)
 	if (!rinfo->pm_reg)
 		return;
 		return;
@@ -2557,32 +2555,14 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
 			}
 			}
 		}
 		}
 
 
-		for (i = 0; i < 64; ++i)
-			pci_read_config_dword(rinfo->pdev, i * 4,
-					      &rinfo->cfg_save[i]);
-
 		/* Switch PCI power management to D2. */
 		/* Switch PCI power management to D2. */
 		pci_disable_device(rinfo->pdev);
 		pci_disable_device(rinfo->pdev);
-		for (;;) {
-			pci_read_config_word(
-				rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
-				&pwr_cmd);
-			if (pwr_cmd & 2)
-				break;			
-			pci_write_config_word(
-				rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
-				(pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2);
-			mdelay(500);
-		}
+		pci_save_state(rinfo->pdev);
+		pci_set_power_state(rinfo->pdev, PCI_D2);
 	} else {
 	} else {
 		printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
 		printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
 		       pci_name(rinfo->pdev));
 		       pci_name(rinfo->pdev));
 
 
-		/* Switch back PCI powermanagment to D0 */
-		mdelay(200);
-		pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0);
-		mdelay(500);
-
 		if (rinfo->family <= CHIP_FAMILY_RV250) {
 		if (rinfo->family <= CHIP_FAMILY_RV250) {
 			/* Reset the SDRAM controller  */
 			/* Reset the SDRAM controller  */
 			radeon_pm_full_reset_sdram(rinfo);
 			radeon_pm_full_reset_sdram(rinfo);
@@ -2598,37 +2578,10 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
 	}
 	}
 }
 }
 
 
-static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo)
-{
-	int i;
-	static u32 radeon_cfg_after_resume[64];
-
-	for (i = 0; i < 64; ++i)
-		pci_read_config_dword(rinfo->pdev, i * 4,
-				      &radeon_cfg_after_resume[i]);
-
-	if (radeon_cfg_after_resume[PCI_BASE_ADDRESS_0/4]
-	    == rinfo->cfg_save[PCI_BASE_ADDRESS_0/4])
-		return 0;	/* assume everything is ok */
-
-	for (i = PCI_BASE_ADDRESS_0/4; i < 64; ++i) {
-		if (radeon_cfg_after_resume[i] != rinfo->cfg_save[i])
-			pci_write_config_dword(rinfo->pdev, i * 4,
-					       rinfo->cfg_save[i]);
-	}
-	pci_write_config_word(rinfo->pdev, PCI_CACHE_LINE_SIZE,
-			      rinfo->cfg_save[PCI_CACHE_LINE_SIZE/4]);
-	pci_write_config_word(rinfo->pdev, PCI_COMMAND,
-			      rinfo->cfg_save[PCI_COMMAND/4]);
-	return 1;
-}
-
-
 int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
 int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
 {
 {
         struct fb_info *info = pci_get_drvdata(pdev);
         struct fb_info *info = pci_get_drvdata(pdev);
         struct radeonfb_info *rinfo = info->par;
         struct radeonfb_info *rinfo = info->par;
-	int i;
 
 
 	if (mesg.event == pdev->dev.power.power_state.event)
 	if (mesg.event == pdev->dev.power.power_state.event)
 		return 0;
 		return 0;
@@ -2674,6 +2627,11 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
 	pmac_suspend_agp_for_card(pdev);
 	pmac_suspend_agp_for_card(pdev);
 #endif /* CONFIG_PPC_PMAC */
 #endif /* CONFIG_PPC_PMAC */
 
 
+	/* It's unclear whether or when the generic code will do that, so let's
+	 * do it ourselves. We save state before we do any power management
+	 */
+	pci_save_state(pdev);
+
 	/* If we support wakeup from poweroff, we save all regs we can including cfg
 	/* If we support wakeup from poweroff, we save all regs we can including cfg
 	 * space
 	 * space
 	 */
 	 */
@@ -2698,9 +2656,6 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
 			mdelay(20);
 			mdelay(20);
 			OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON));
 			OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON));
 		}
 		}
-		// FIXME: Use PCI layer
-		for (i = 0; i < 64; ++i)
-			pci_read_config_dword(pdev, i * 4, &rinfo->cfg_save[i]);
 		pci_disable_device(pdev);
 		pci_disable_device(pdev);
 	}
 	}
 	/* If we support D2, we go to it (should be fixed later with a flag forcing
 	/* If we support D2, we go to it (should be fixed later with a flag forcing
@@ -2717,6 +2672,13 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
 	return 0;
 	return 0;
 }
 }
 
 
+static int radeon_check_power_loss(struct radeonfb_info *rinfo)
+{
+	return rinfo->save_regs[4] != INPLL(CLK_PIN_CNTL) ||
+	       rinfo->save_regs[2] != INPLL(MCLK_CNTL) ||
+	       rinfo->save_regs[3] != INPLL(SCLK_CNTL);
+}
+
 int radeonfb_pci_resume(struct pci_dev *pdev)
 int radeonfb_pci_resume(struct pci_dev *pdev)
 {
 {
         struct fb_info *info = pci_get_drvdata(pdev);
         struct fb_info *info = pci_get_drvdata(pdev);
@@ -2735,20 +2697,13 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
 	printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n",
 	printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n",
 	       pci_name(pdev), pdev->dev.power.power_state.event);
 	       pci_name(pdev), pdev->dev.power.power_state.event);
 
 
-
-	if (pci_enable_device(pdev)) {
-		rc = -ENODEV;
-		printk(KERN_ERR "radeonfb (%s): can't enable PCI device !\n",
-		       pci_name(pdev));
-		goto bail;
-	}
-	pci_set_master(pdev);
-
+	/* PCI state will have been restored by the core, so
+	 * we should be in D0 now with our config space fully
+	 * restored
+	 */
 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-		/* Wakeup chip. Check from config space if we were powered off
-		 * (todo: additionally, check CLK_PIN_CNTL too)
-		 */
-		if ((rinfo->pm_mode & radeon_pm_off) && radeon_restore_pci_cfg(rinfo)) {
+		/* Wakeup chip */
+		if ((rinfo->pm_mode & radeon_pm_off) && radeon_check_power_loss(rinfo)) {
 			if (rinfo->reinit_func != NULL)
 			if (rinfo->reinit_func != NULL)
 				rinfo->reinit_func(rinfo);
 				rinfo->reinit_func(rinfo);
 			else {
 			else {

+ 0 - 2
drivers/video/aty/radeonfb.h

@@ -361,8 +361,6 @@ struct radeonfb_info {
 #ifdef CONFIG_FB_RADEON_I2C
 #ifdef CONFIG_FB_RADEON_I2C
 	struct radeon_i2c_chan 	i2c[4];
 	struct radeon_i2c_chan 	i2c[4];
 #endif
 #endif
-
-	u32			cfg_save[64];
 };
 };
 
 
 
 

+ 1 - 1
drivers/video/backlight/Makefile

@@ -18,7 +18,7 @@ obj-$(CONFIG_BACKLIGHT_OMAP1)	+= omap1_bl.o
 obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
 obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
 obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
 obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
 obj-$(CONFIG_BACKLIGHT_PWM)	+= pwm_bl.o
 obj-$(CONFIG_BACKLIGHT_PWM)	+= pwm_bl.o
-obj-$(CONFIG_BACKLIGHT_DA903X)	+= da903x.o
+obj-$(CONFIG_BACKLIGHT_DA903X)	+= da903x_bl.o
 obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
 obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
 obj-$(CONFIG_BACKLIGHT_TOSA)	+= tosa_bl.o
 obj-$(CONFIG_BACKLIGHT_TOSA)	+= tosa_bl.o
 obj-$(CONFIG_BACKLIGHT_SAHARA)	+= kb3886_bl.o
 obj-$(CONFIG_BACKLIGHT_SAHARA)	+= kb3886_bl.o

+ 0 - 0
drivers/video/backlight/da903x.c → drivers/video/backlight/da903x_bl.c


+ 14 - 6
drivers/video/fbcmap.c

@@ -250,10 +250,6 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
 	int rc, size = cmap->len * sizeof(u16);
 	int rc, size = cmap->len * sizeof(u16);
 	struct fb_cmap umap;
 	struct fb_cmap umap;
 
 
-	if (cmap->start < 0 || (!info->fbops->fb_setcolreg &&
-			        !info->fbops->fb_setcmap))
-		return -EINVAL;
-
 	memset(&umap, 0, sizeof(struct fb_cmap));
 	memset(&umap, 0, sizeof(struct fb_cmap));
 	rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL);
 	rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL);
 	if (rc)
 	if (rc)
@@ -262,11 +258,23 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
 	    copy_from_user(umap.green, cmap->green, size) ||
 	    copy_from_user(umap.green, cmap->green, size) ||
 	    copy_from_user(umap.blue, cmap->blue, size) ||
 	    copy_from_user(umap.blue, cmap->blue, size) ||
 	    (cmap->transp && copy_from_user(umap.transp, cmap->transp, size))) {
 	    (cmap->transp && copy_from_user(umap.transp, cmap->transp, size))) {
-		fb_dealloc_cmap(&umap);
-		return -EFAULT;
+		rc = -EFAULT;
+		goto out;
 	}
 	}
 	umap.start = cmap->start;
 	umap.start = cmap->start;
+	if (!lock_fb_info(info)) {
+		rc = -ENODEV;
+		goto out;
+	}
+	if (cmap->start < 0 || (!info->fbops->fb_setcolreg &&
+				!info->fbops->fb_setcmap)) {
+		rc = -EINVAL;
+		goto out1;
+	}
 	rc = fb_set_cmap(&umap, info);
 	rc = fb_set_cmap(&umap, info);
+out1:
+	unlock_fb_info(info);
+out:
 	fb_dealloc_cmap(&umap);
 	fb_dealloc_cmap(&umap);
 	return rc;
 	return rc;
 }
 }

+ 69 - 66
drivers/video/fbmem.c

@@ -1013,132 +1013,139 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
 	struct fb_var_screeninfo var;
 	struct fb_var_screeninfo var;
 	struct fb_fix_screeninfo fix;
 	struct fb_fix_screeninfo fix;
 	struct fb_con2fbmap con2fb;
 	struct fb_con2fbmap con2fb;
+	struct fb_cmap cmap_from;
 	struct fb_cmap_user cmap;
 	struct fb_cmap_user cmap;
 	struct fb_event event;
 	struct fb_event event;
 	void __user *argp = (void __user *)arg;
 	void __user *argp = (void __user *)arg;
 	long ret = 0;
 	long ret = 0;
 
 
-	fb = info->fbops;
-	if (!fb)
-		return -ENODEV;
-
 	switch (cmd) {
 	switch (cmd) {
 	case FBIOGET_VSCREENINFO:
 	case FBIOGET_VSCREENINFO:
-		ret = copy_to_user(argp, &info->var,
-				    sizeof(var)) ? -EFAULT : 0;
+		if (!lock_fb_info(info))
+			return -ENODEV;
+		var = info->var;
+		unlock_fb_info(info);
+
+		ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0;
 		break;
 		break;
 	case FBIOPUT_VSCREENINFO:
 	case FBIOPUT_VSCREENINFO:
-		if (copy_from_user(&var, argp, sizeof(var))) {
-			ret =  -EFAULT;
-			break;
-		}
+		if (copy_from_user(&var, argp, sizeof(var)))
+			return -EFAULT;
+		if (!lock_fb_info(info))
+			return -ENODEV;
 		acquire_console_sem();
 		acquire_console_sem();
 		info->flags |= FBINFO_MISC_USEREVENT;
 		info->flags |= FBINFO_MISC_USEREVENT;
 		ret = fb_set_var(info, &var);
 		ret = fb_set_var(info, &var);
 		info->flags &= ~FBINFO_MISC_USEREVENT;
 		info->flags &= ~FBINFO_MISC_USEREVENT;
 		release_console_sem();
 		release_console_sem();
-		if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
+		unlock_fb_info(info);
+		if (!ret && copy_to_user(argp, &var, sizeof(var)))
 			ret = -EFAULT;
 			ret = -EFAULT;
 		break;
 		break;
 	case FBIOGET_FSCREENINFO:
 	case FBIOGET_FSCREENINFO:
-		ret = copy_to_user(argp, &info->fix,
-				    sizeof(fix)) ? -EFAULT : 0;
+		if (!lock_fb_info(info))
+			return -ENODEV;
+		fix = info->fix;
+		unlock_fb_info(info);
+
+		ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
 		break;
 		break;
 	case FBIOPUTCMAP:
 	case FBIOPUTCMAP:
 		if (copy_from_user(&cmap, argp, sizeof(cmap)))
 		if (copy_from_user(&cmap, argp, sizeof(cmap)))
-			ret = -EFAULT;
-		else
-			ret = fb_set_user_cmap(&cmap, info);
+			return -EFAULT;
+		ret = fb_set_user_cmap(&cmap, info);
 		break;
 		break;
 	case FBIOGETCMAP:
 	case FBIOGETCMAP:
 		if (copy_from_user(&cmap, argp, sizeof(cmap)))
 		if (copy_from_user(&cmap, argp, sizeof(cmap)))
-			ret = -EFAULT;
-		else
-			ret = fb_cmap_to_user(&info->cmap, &cmap);
+			return -EFAULT;
+		if (!lock_fb_info(info))
+			return -ENODEV;
+		cmap_from = info->cmap;
+		unlock_fb_info(info);
+		ret = fb_cmap_to_user(&cmap_from, &cmap);
 		break;
 		break;
 	case FBIOPAN_DISPLAY:
 	case FBIOPAN_DISPLAY:
-		if (copy_from_user(&var, argp, sizeof(var))) {
-			ret = -EFAULT;
-			break;
-		}
+		if (copy_from_user(&var, argp, sizeof(var)))
+			return -EFAULT;
+		if (!lock_fb_info(info))
+			return -ENODEV;
 		acquire_console_sem();
 		acquire_console_sem();
 		ret = fb_pan_display(info, &var);
 		ret = fb_pan_display(info, &var);
 		release_console_sem();
 		release_console_sem();
+		unlock_fb_info(info);
 		if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
 		if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
-			ret = -EFAULT;
+			return -EFAULT;
 		break;
 		break;
 	case FBIO_CURSOR:
 	case FBIO_CURSOR:
 		ret = -EINVAL;
 		ret = -EINVAL;
 		break;
 		break;
 	case FBIOGET_CON2FBMAP:
 	case FBIOGET_CON2FBMAP:
 		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
 		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
-			ret = -EFAULT;
-		else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
-			ret = -EINVAL;
-		else {
-			con2fb.framebuffer = -1;
-			event.info = info;
-			event.data = &con2fb;
-			fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP,
-								&event);
-			ret = copy_to_user(argp, &con2fb,
-				    sizeof(con2fb)) ? -EFAULT : 0;
-		}
+			return -EFAULT;
+		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+			return -EINVAL;
+		con2fb.framebuffer = -1;
+		event.data = &con2fb;
+
+		if (!lock_fb_info(info))
+			return -ENODEV;
+		event.info = info;
+		fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
+		unlock_fb_info(info);
+
+		ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
 		break;
 		break;
 	case FBIOPUT_CON2FBMAP:
 	case FBIOPUT_CON2FBMAP:
-		if (copy_from_user(&con2fb, argp, sizeof(con2fb))) {
-			ret = -EFAULT;
-			break;
-		}
-		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) {
-			ret = -EINVAL;
-			break;
-		}
-		if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) {
-			ret = -EINVAL;
-			break;
-		}
+		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
+			return -EFAULT;
+		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+			return -EINVAL;
+		if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
+			return -EINVAL;
 		if (!registered_fb[con2fb.framebuffer])
 		if (!registered_fb[con2fb.framebuffer])
 			request_module("fb%d", con2fb.framebuffer);
 			request_module("fb%d", con2fb.framebuffer);
 		if (!registered_fb[con2fb.framebuffer]) {
 		if (!registered_fb[con2fb.framebuffer]) {
 			ret = -EINVAL;
 			ret = -EINVAL;
 			break;
 			break;
 		}
 		}
-		event.info = info;
 		event.data = &con2fb;
 		event.data = &con2fb;
+		if (!lock_fb_info(info))
+			return -ENODEV;
+		event.info = info;
 		ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,
 		ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,
 					      &event);
 					      &event);
+		unlock_fb_info(info);
 		break;
 		break;
 	case FBIOBLANK:
 	case FBIOBLANK:
+		if (!lock_fb_info(info))
+			return -ENODEV;
 		acquire_console_sem();
 		acquire_console_sem();
 		info->flags |= FBINFO_MISC_USEREVENT;
 		info->flags |= FBINFO_MISC_USEREVENT;
 		ret = fb_blank(info, arg);
 		ret = fb_blank(info, arg);
 		info->flags &= ~FBINFO_MISC_USEREVENT;
 		info->flags &= ~FBINFO_MISC_USEREVENT;
 		release_console_sem();
 		release_console_sem();
-		break;;
+		unlock_fb_info(info);
+		break;
 	default:
 	default:
-		if (fb->fb_ioctl == NULL)
-			ret = -ENOTTY;
-		else
+		if (!lock_fb_info(info))
+			return -ENODEV;
+		fb = info->fbops;
+		if (fb->fb_ioctl)
 			ret = fb->fb_ioctl(info, cmd, arg);
 			ret = fb->fb_ioctl(info, cmd, arg);
+		else
+			ret = -ENOTTY;
+		unlock_fb_info(info);
 	}
 	}
 	return ret;
 	return ret;
 }
 }
 
 
 static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-__acquires(&info->lock)
-__releases(&info->lock)
 {
 {
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct inode *inode = file->f_path.dentry->d_inode;
 	int fbidx = iminor(inode);
 	int fbidx = iminor(inode);
-	struct fb_info *info;
-	long ret;
+	struct fb_info *info = registered_fb[fbidx];
 
 
-	info = registered_fb[fbidx];
-	mutex_lock(&info->lock);
-	ret = do_fb_ioctl(info, cmd, arg);
-	mutex_unlock(&info->lock);
-	return ret;
+	return do_fb_ioctl(info, cmd, arg);
 }
 }
 
 
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_COMPAT
@@ -1257,8 +1264,6 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
 
 
 static long fb_compat_ioctl(struct file *file, unsigned int cmd,
 static long fb_compat_ioctl(struct file *file, unsigned int cmd,
 			    unsigned long arg)
 			    unsigned long arg)
-__acquires(&info->lock)
-__releases(&info->lock)
 {
 {
 	struct inode *inode = file->f_path.dentry->d_inode;
 	struct inode *inode = file->f_path.dentry->d_inode;
 	int fbidx = iminor(inode);
 	int fbidx = iminor(inode);
@@ -1266,7 +1271,6 @@ __releases(&info->lock)
 	struct fb_ops *fb = info->fbops;
 	struct fb_ops *fb = info->fbops;
 	long ret = -ENOIOCTLCMD;
 	long ret = -ENOIOCTLCMD;
 
 
-	mutex_lock(&info->lock);
 	switch(cmd) {
 	switch(cmd) {
 	case FBIOGET_VSCREENINFO:
 	case FBIOGET_VSCREENINFO:
 	case FBIOPUT_VSCREENINFO:
 	case FBIOPUT_VSCREENINFO:
@@ -1292,7 +1296,6 @@ __releases(&info->lock)
 			ret = fb->fb_compat_ioctl(info, cmd, arg);
 			ret = fb->fb_compat_ioctl(info, cmd, arg);
 		break;
 		break;
 	}
 	}
-	mutex_unlock(&info->lock);
 	return ret;
 	return ret;
 }
 }
 #endif
 #endif

+ 12 - 2
fs/binfmt_elf.c

@@ -1208,9 +1208,11 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
 	 * check for an ELF header.  If we find one, dump the first page to
 	 * check for an ELF header.  If we find one, dump the first page to
 	 * aid in determining what was mapped here.
 	 * aid in determining what was mapped here.
 	 */
 	 */
-	if (FILTER(ELF_HEADERS) && vma->vm_file != NULL && vma->vm_pgoff == 0) {
+	if (FILTER(ELF_HEADERS) &&
+	    vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) {
 		u32 __user *header = (u32 __user *) vma->vm_start;
 		u32 __user *header = (u32 __user *) vma->vm_start;
 		u32 word;
 		u32 word;
+		mm_segment_t fs = get_fs();
 		/*
 		/*
 		 * Doing it this way gets the constant folded by GCC.
 		 * Doing it this way gets the constant folded by GCC.
 		 */
 		 */
@@ -1223,7 +1225,15 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
 		magic.elfmag[EI_MAG1] = ELFMAG1;
 		magic.elfmag[EI_MAG1] = ELFMAG1;
 		magic.elfmag[EI_MAG2] = ELFMAG2;
 		magic.elfmag[EI_MAG2] = ELFMAG2;
 		magic.elfmag[EI_MAG3] = ELFMAG3;
 		magic.elfmag[EI_MAG3] = ELFMAG3;
-		if (get_user(word, header) == 0 && word == magic.cmp)
+		/*
+		 * Switch to the user "segment" for get_user(),
+		 * then put back what elf_core_dump() had in place.
+		 */
+		set_fs(USER_DS);
+		if (unlikely(get_user(word, header)))
+			word = 0;
+		set_fs(fs);
+		if (word == magic.cmp)
 			return PAGE_SIZE;
 			return PAGE_SIZE;
 	}
 	}
 
 

+ 13 - 0
fs/btrfs/Kconfig

@@ -16,3 +16,16 @@ config BTRFS_FS
 	  module will be called btrfs.
 	  module will be called btrfs.
 
 
 	  If unsure, say N.
 	  If unsure, say N.
+
+config BTRFS_FS_POSIX_ACL
+	bool "Btrfs POSIX Access Control Lists"
+	depends on BTRFS_FS
+	select FS_POSIX_ACL
+	help
+	  POSIX Access Control Lists (ACLs) support permissions for users and
+	  groups beyond the owner/group/world scheme.
+
+	  To learn more about Access Control Lists, visit the POSIX ACLs for
+	  Linux website <http://acl.bestbits.at/>.
+
+	  If you don't know what Access Control Lists are, say N

+ 53 - 8
fs/btrfs/async-thread.c

@@ -16,11 +16,11 @@
  * Boston, MA 021110-1307, USA.
  * Boston, MA 021110-1307, USA.
  */
  */
 
 
-#include <linux/version.h>
 #include <linux/kthread.h>
 #include <linux/kthread.h>
 #include <linux/list.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
-# include <linux/freezer.h>
+#include <linux/freezer.h>
+#include <linux/ftrace.h>
 #include "async-thread.h"
 #include "async-thread.h"
 
 
 #define WORK_QUEUED_BIT 0
 #define WORK_QUEUED_BIT 0
@@ -143,6 +143,7 @@ static int worker_loop(void *arg)
 	struct btrfs_work *work;
 	struct btrfs_work *work;
 	do {
 	do {
 		spin_lock_irq(&worker->lock);
 		spin_lock_irq(&worker->lock);
+again_locked:
 		while (!list_empty(&worker->pending)) {
 		while (!list_empty(&worker->pending)) {
 			cur = worker->pending.next;
 			cur = worker->pending.next;
 			work = list_entry(cur, struct btrfs_work, list);
 			work = list_entry(cur, struct btrfs_work, list);
@@ -165,14 +166,50 @@ static int worker_loop(void *arg)
 			check_idle_worker(worker);
 			check_idle_worker(worker);
 
 
 		}
 		}
-		worker->working = 0;
 		if (freezing(current)) {
 		if (freezing(current)) {
+			worker->working = 0;
+			spin_unlock_irq(&worker->lock);
 			refrigerator();
 			refrigerator();
 		} else {
 		} else {
-			set_current_state(TASK_INTERRUPTIBLE);
 			spin_unlock_irq(&worker->lock);
 			spin_unlock_irq(&worker->lock);
-			if (!kthread_should_stop())
+			if (!kthread_should_stop()) {
+				cpu_relax();
+				/*
+				 * we've dropped the lock, did someone else
+				 * jump_in?
+				 */
+				smp_mb();
+				if (!list_empty(&worker->pending))
+					continue;
+
+				/*
+				 * this short schedule allows more work to
+				 * come in without the queue functions
+				 * needing to go through wake_up_process()
+				 *
+				 * worker->working is still 1, so nobody
+				 * is going to try and wake us up
+				 */
+				schedule_timeout(1);
+				smp_mb();
+				if (!list_empty(&worker->pending))
+					continue;
+
+				/* still no more work?, sleep for real */
+				spin_lock_irq(&worker->lock);
+				set_current_state(TASK_INTERRUPTIBLE);
+				if (!list_empty(&worker->pending))
+					goto again_locked;
+
+				/*
+				 * this makes sure we get a wakeup when someone
+				 * adds something new to the queue
+				 */
+				worker->working = 0;
+				spin_unlock_irq(&worker->lock);
+
 				schedule();
 				schedule();
+			}
 			__set_current_state(TASK_RUNNING);
 			__set_current_state(TASK_RUNNING);
 		}
 		}
 	} while (!kthread_should_stop());
 	} while (!kthread_should_stop());
@@ -350,13 +387,14 @@ int btrfs_requeue_work(struct btrfs_work *work)
 {
 {
 	struct btrfs_worker_thread *worker = work->worker;
 	struct btrfs_worker_thread *worker = work->worker;
 	unsigned long flags;
 	unsigned long flags;
+	int wake = 0;
 
 
 	if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags))
 	if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags))
 		goto out;
 		goto out;
 
 
 	spin_lock_irqsave(&worker->lock, flags);
 	spin_lock_irqsave(&worker->lock, flags);
-	atomic_inc(&worker->num_pending);
 	list_add_tail(&work->list, &worker->pending);
 	list_add_tail(&work->list, &worker->pending);
+	atomic_inc(&worker->num_pending);
 
 
 	/* by definition we're busy, take ourselves off the idle
 	/* by definition we're busy, take ourselves off the idle
 	 * list
 	 * list
@@ -368,10 +406,16 @@ int btrfs_requeue_work(struct btrfs_work *work)
 			       &worker->workers->worker_list);
 			       &worker->workers->worker_list);
 		spin_unlock_irqrestore(&worker->workers->lock, flags);
 		spin_unlock_irqrestore(&worker->workers->lock, flags);
 	}
 	}
+	if (!worker->working) {
+		wake = 1;
+		worker->working = 1;
+	}
 
 
 	spin_unlock_irqrestore(&worker->lock, flags);
 	spin_unlock_irqrestore(&worker->lock, flags);
-
+	if (wake)
+		wake_up_process(worker->task);
 out:
 out:
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -398,9 +442,10 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
 	}
 	}
 
 
 	spin_lock_irqsave(&worker->lock, flags);
 	spin_lock_irqsave(&worker->lock, flags);
+
+	list_add_tail(&work->list, &worker->pending);
 	atomic_inc(&worker->num_pending);
 	atomic_inc(&worker->num_pending);
 	check_busy_worker(worker);
 	check_busy_worker(worker);
-	list_add_tail(&work->list, &worker->pending);
 
 
 	/*
 	/*
 	 * avoid calling into wake_up_process if this thread has already
 	 * avoid calling into wake_up_process if this thread has already

+ 0 - 1
fs/btrfs/compression.c

@@ -32,7 +32,6 @@
 #include <linux/swap.h>
 #include <linux/swap.h>
 #include <linux/writeback.h>
 #include <linux/writeback.h>
 #include <linux/bit_spinlock.h>
 #include <linux/bit_spinlock.h>
-#include <linux/version.h>
 #include <linux/pagevec.h>
 #include <linux/pagevec.h>
 #include "compat.h"
 #include "compat.h"
 #include "ctree.h"
 #include "ctree.h"

+ 244 - 32
fs/btrfs/ctree.c

@@ -54,6 +54,31 @@ struct btrfs_path *btrfs_alloc_path(void)
 	return path;
 	return path;
 }
 }
 
 
+/*
+ * set all locked nodes in the path to blocking locks.  This should
+ * be done before scheduling
+ */
+noinline void btrfs_set_path_blocking(struct btrfs_path *p)
+{
+	int i;
+	for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
+		if (p->nodes[i] && p->locks[i])
+			btrfs_set_lock_blocking(p->nodes[i]);
+	}
+}
+
+/*
+ * reset all the locked nodes in the patch to spinning locks.
+ */
+noinline void btrfs_clear_path_blocking(struct btrfs_path *p)
+{
+	int i;
+	for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
+		if (p->nodes[i] && p->locks[i])
+			btrfs_clear_lock_blocking(p->nodes[i]);
+	}
+}
+
 /* this also releases the path */
 /* this also releases the path */
 void btrfs_free_path(struct btrfs_path *p)
 void btrfs_free_path(struct btrfs_path *p)
 {
 {
@@ -272,6 +297,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
 	if (IS_ERR(cow))
 	if (IS_ERR(cow))
 		return PTR_ERR(cow);
 		return PTR_ERR(cow);
 
 
+	/* cow is set to blocking by btrfs_init_new_buffer */
+
 	copy_extent_buffer(cow, buf, 0, 0, cow->len);
 	copy_extent_buffer(cow, buf, 0, 0, cow->len);
 	btrfs_set_header_bytenr(cow, cow->start);
 	btrfs_set_header_bytenr(cow, cow->start);
 	btrfs_set_header_generation(cow, trans->transid);
 	btrfs_set_header_generation(cow, trans->transid);
@@ -388,17 +415,20 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
 		WARN_ON(1);
 		WARN_ON(1);
 	}
 	}
 
 
-	spin_lock(&root->fs_info->hash_lock);
 	if (btrfs_header_generation(buf) == trans->transid &&
 	if (btrfs_header_generation(buf) == trans->transid &&
 	    btrfs_header_owner(buf) == root->root_key.objectid &&
 	    btrfs_header_owner(buf) == root->root_key.objectid &&
 	    !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) {
 	    !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) {
 		*cow_ret = buf;
 		*cow_ret = buf;
-		spin_unlock(&root->fs_info->hash_lock);
 		WARN_ON(prealloc_dest);
 		WARN_ON(prealloc_dest);
 		return 0;
 		return 0;
 	}
 	}
-	spin_unlock(&root->fs_info->hash_lock);
+
 	search_start = buf->start & ~((u64)(1024 * 1024 * 1024) - 1);
 	search_start = buf->start & ~((u64)(1024 * 1024 * 1024) - 1);
+
+	if (parent)
+		btrfs_set_lock_blocking(parent);
+	btrfs_set_lock_blocking(buf);
+
 	ret = __btrfs_cow_block(trans, root, buf, parent,
 	ret = __btrfs_cow_block(trans, root, buf, parent,
 				 parent_slot, cow_ret, search_start, 0,
 				 parent_slot, cow_ret, search_start, 0,
 				 prealloc_dest);
 				 prealloc_dest);
@@ -504,6 +534,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 	if (parent_nritems == 1)
 	if (parent_nritems == 1)
 		return 0;
 		return 0;
 
 
+	btrfs_set_lock_blocking(parent);
+
 	for (i = start_slot; i < end_slot; i++) {
 	for (i = start_slot; i < end_slot; i++) {
 		int close = 1;
 		int close = 1;
 
 
@@ -564,6 +596,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 			search_start = last_block;
 			search_start = last_block;
 
 
 		btrfs_tree_lock(cur);
 		btrfs_tree_lock(cur);
+		btrfs_set_lock_blocking(cur);
 		err = __btrfs_cow_block(trans, root, cur, parent, i,
 		err = __btrfs_cow_block(trans, root, cur, parent, i,
 					&cur, search_start,
 					&cur, search_start,
 					min(16 * blocksize,
 					min(16 * blocksize,
@@ -862,6 +895,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
 		return 0;
 		return 0;
 
 
 	mid = path->nodes[level];
 	mid = path->nodes[level];
+
 	WARN_ON(!path->locks[level]);
 	WARN_ON(!path->locks[level]);
 	WARN_ON(btrfs_header_generation(mid) != trans->transid);
 	WARN_ON(btrfs_header_generation(mid) != trans->transid);
 
 
@@ -884,6 +918,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
 		/* promote the child to a root */
 		/* promote the child to a root */
 		child = read_node_slot(root, mid, 0);
 		child = read_node_slot(root, mid, 0);
 		btrfs_tree_lock(child);
 		btrfs_tree_lock(child);
+		btrfs_set_lock_blocking(child);
 		BUG_ON(!child);
 		BUG_ON(!child);
 		ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0);
 		ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0);
 		BUG_ON(ret);
 		BUG_ON(ret);
@@ -900,6 +935,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
 
 
 		add_root_to_dirty_list(root);
 		add_root_to_dirty_list(root);
 		btrfs_tree_unlock(child);
 		btrfs_tree_unlock(child);
+
 		path->locks[level] = 0;
 		path->locks[level] = 0;
 		path->nodes[level] = NULL;
 		path->nodes[level] = NULL;
 		clean_tree_block(trans, root, mid);
 		clean_tree_block(trans, root, mid);
@@ -924,6 +960,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
 	left = read_node_slot(root, parent, pslot - 1);
 	left = read_node_slot(root, parent, pslot - 1);
 	if (left) {
 	if (left) {
 		btrfs_tree_lock(left);
 		btrfs_tree_lock(left);
+		btrfs_set_lock_blocking(left);
 		wret = btrfs_cow_block(trans, root, left,
 		wret = btrfs_cow_block(trans, root, left,
 				       parent, pslot - 1, &left, 0);
 				       parent, pslot - 1, &left, 0);
 		if (wret) {
 		if (wret) {
@@ -934,6 +971,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
 	right = read_node_slot(root, parent, pslot + 1);
 	right = read_node_slot(root, parent, pslot + 1);
 	if (right) {
 	if (right) {
 		btrfs_tree_lock(right);
 		btrfs_tree_lock(right);
+		btrfs_set_lock_blocking(right);
 		wret = btrfs_cow_block(trans, root, right,
 		wret = btrfs_cow_block(trans, root, right,
 				       parent, pslot + 1, &right, 0);
 				       parent, pslot + 1, &right, 0);
 		if (wret) {
 		if (wret) {
@@ -1109,6 +1147,8 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
 		u32 left_nr;
 		u32 left_nr;
 
 
 		btrfs_tree_lock(left);
 		btrfs_tree_lock(left);
+		btrfs_set_lock_blocking(left);
+
 		left_nr = btrfs_header_nritems(left);
 		left_nr = btrfs_header_nritems(left);
 		if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
 		if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
 			wret = 1;
 			wret = 1;
@@ -1155,7 +1195,10 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
 	 */
 	 */
 	if (right) {
 	if (right) {
 		u32 right_nr;
 		u32 right_nr;
+
 		btrfs_tree_lock(right);
 		btrfs_tree_lock(right);
+		btrfs_set_lock_blocking(right);
+
 		right_nr = btrfs_header_nritems(right);
 		right_nr = btrfs_header_nritems(right);
 		if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
 		if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
 			wret = 1;
 			wret = 1;
@@ -1210,8 +1253,7 @@ static noinline void reada_for_search(struct btrfs_root *root,
 	struct btrfs_disk_key disk_key;
 	struct btrfs_disk_key disk_key;
 	u32 nritems;
 	u32 nritems;
 	u64 search;
 	u64 search;
-	u64 lowest_read;
-	u64 highest_read;
+	u64 target;
 	u64 nread = 0;
 	u64 nread = 0;
 	int direction = path->reada;
 	int direction = path->reada;
 	struct extent_buffer *eb;
 	struct extent_buffer *eb;
@@ -1235,8 +1277,7 @@ static noinline void reada_for_search(struct btrfs_root *root,
 		return;
 		return;
 	}
 	}
 
 
-	highest_read = search;
-	lowest_read = search;
+	target = search;
 
 
 	nritems = btrfs_header_nritems(node);
 	nritems = btrfs_header_nritems(node);
 	nr = slot;
 	nr = slot;
@@ -1256,27 +1297,80 @@ static noinline void reada_for_search(struct btrfs_root *root,
 				break;
 				break;
 		}
 		}
 		search = btrfs_node_blockptr(node, nr);
 		search = btrfs_node_blockptr(node, nr);
-		if ((search >= lowest_read && search <= highest_read) ||
-		    (search < lowest_read && lowest_read - search <= 16384) ||
-		    (search > highest_read && search - highest_read <= 16384)) {
+		if ((search <= target && target - search <= 65536) ||
+		    (search > target && search - target <= 65536)) {
 			readahead_tree_block(root, search, blocksize,
 			readahead_tree_block(root, search, blocksize,
 				     btrfs_node_ptr_generation(node, nr));
 				     btrfs_node_ptr_generation(node, nr));
 			nread += blocksize;
 			nread += blocksize;
 		}
 		}
 		nscan++;
 		nscan++;
-		if (path->reada < 2 && (nread > (64 * 1024) || nscan > 32))
+		if ((nread > 65536 || nscan > 32))
 			break;
 			break;
+	}
+}
 
 
-		if (nread > (256 * 1024) || nscan > 128)
-			break;
+/*
+ * returns -EAGAIN if it had to drop the path, or zero if everything was in
+ * cache
+ */
+static noinline int reada_for_balance(struct btrfs_root *root,
+				      struct btrfs_path *path, int level)
+{
+	int slot;
+	int nritems;
+	struct extent_buffer *parent;
+	struct extent_buffer *eb;
+	u64 gen;
+	u64 block1 = 0;
+	u64 block2 = 0;
+	int ret = 0;
+	int blocksize;
 
 
-		if (search < lowest_read)
-			lowest_read = search;
-		if (search > highest_read)
-			highest_read = search;
+	parent = path->nodes[level - 1];
+	if (!parent)
+		return 0;
+
+	nritems = btrfs_header_nritems(parent);
+	slot = path->slots[level];
+	blocksize = btrfs_level_size(root, level);
+
+	if (slot > 0) {
+		block1 = btrfs_node_blockptr(parent, slot - 1);
+		gen = btrfs_node_ptr_generation(parent, slot - 1);
+		eb = btrfs_find_tree_block(root, block1, blocksize);
+		if (eb && btrfs_buffer_uptodate(eb, gen))
+			block1 = 0;
+		free_extent_buffer(eb);
+	}
+	if (slot < nritems) {
+		block2 = btrfs_node_blockptr(parent, slot + 1);
+		gen = btrfs_node_ptr_generation(parent, slot + 1);
+		eb = btrfs_find_tree_block(root, block2, blocksize);
+		if (eb && btrfs_buffer_uptodate(eb, gen))
+			block2 = 0;
+		free_extent_buffer(eb);
+	}
+	if (block1 || block2) {
+		ret = -EAGAIN;
+		btrfs_release_path(root, path);
+		if (block1)
+			readahead_tree_block(root, block1, blocksize, 0);
+		if (block2)
+			readahead_tree_block(root, block2, blocksize, 0);
+
+		if (block1) {
+			eb = read_tree_block(root, block1, blocksize, 0);
+			free_extent_buffer(eb);
+		}
+		if (block1) {
+			eb = read_tree_block(root, block2, blocksize, 0);
+			free_extent_buffer(eb);
+		}
 	}
 	}
+	return ret;
 }
 }
 
 
+
 /*
 /*
  * when we walk down the tree, it is usually safe to unlock the higher layers
  * when we walk down the tree, it is usually safe to unlock the higher layers
  * in the tree.  The exceptions are when our path goes through slot 0, because
  * in the tree.  The exceptions are when our path goes through slot 0, because
@@ -1327,6 +1421,32 @@ static noinline void unlock_up(struct btrfs_path *path, int level,
 	}
 	}
 }
 }
 
 
+/*
+ * This releases any locks held in the path starting at level and
+ * going all the way up to the root.
+ *
+ * btrfs_search_slot will keep the lock held on higher nodes in a few
+ * corner cases, such as COW of the block at slot zero in the node.  This
+ * ignores those rules, and it should only be called when there are no
+ * more updates to be done higher up in the tree.
+ */
+noinline void btrfs_unlock_up_safe(struct btrfs_path *path, int level)
+{
+	int i;
+
+	if (path->keep_locks || path->lowest_level)
+		return;
+
+	for (i = level; i < BTRFS_MAX_LEVEL; i++) {
+		if (!path->nodes[i])
+			continue;
+		if (!path->locks[i])
+			continue;
+		btrfs_tree_unlock(path->nodes[i]);
+		path->locks[i] = 0;
+	}
+}
+
 /*
 /*
  * look for key in the tree.  path is filled in with nodes along the way
  * look for key in the tree.  path is filled in with nodes along the way
  * if key is found, we return zero and you can find the item in the leaf
  * if key is found, we return zero and you can find the item in the leaf
@@ -1387,31 +1507,30 @@ again:
 			int wret;
 			int wret;
 
 
 			/* is a cow on this block not required */
 			/* is a cow on this block not required */
-			spin_lock(&root->fs_info->hash_lock);
 			if (btrfs_header_generation(b) == trans->transid &&
 			if (btrfs_header_generation(b) == trans->transid &&
 			    btrfs_header_owner(b) == root->root_key.objectid &&
 			    btrfs_header_owner(b) == root->root_key.objectid &&
 			    !btrfs_header_flag(b, BTRFS_HEADER_FLAG_WRITTEN)) {
 			    !btrfs_header_flag(b, BTRFS_HEADER_FLAG_WRITTEN)) {
-				spin_unlock(&root->fs_info->hash_lock);
 				goto cow_done;
 				goto cow_done;
 			}
 			}
-			spin_unlock(&root->fs_info->hash_lock);
 
 
 			/* ok, we have to cow, is our old prealloc the right
 			/* ok, we have to cow, is our old prealloc the right
 			 * size?
 			 * size?
 			 */
 			 */
 			if (prealloc_block.objectid &&
 			if (prealloc_block.objectid &&
 			    prealloc_block.offset != b->len) {
 			    prealloc_block.offset != b->len) {
+				btrfs_release_path(root, p);
 				btrfs_free_reserved_extent(root,
 				btrfs_free_reserved_extent(root,
 					   prealloc_block.objectid,
 					   prealloc_block.objectid,
 					   prealloc_block.offset);
 					   prealloc_block.offset);
 				prealloc_block.objectid = 0;
 				prealloc_block.objectid = 0;
+				goto again;
 			}
 			}
 
 
 			/*
 			/*
 			 * for higher level blocks, try not to allocate blocks
 			 * for higher level blocks, try not to allocate blocks
 			 * with the block and the parent locks held.
 			 * with the block and the parent locks held.
 			 */
 			 */
-			if (level > 1 && !prealloc_block.objectid &&
+			if (level > 0 && !prealloc_block.objectid &&
 			    btrfs_path_lock_waiting(p, level)) {
 			    btrfs_path_lock_waiting(p, level)) {
 				u32 size = b->len;
 				u32 size = b->len;
 				u64 hint = b->start;
 				u64 hint = b->start;
@@ -1425,6 +1544,8 @@ again:
 				goto again;
 				goto again;
 			}
 			}
 
 
+			btrfs_set_path_blocking(p);
+
 			wret = btrfs_cow_block(trans, root, b,
 			wret = btrfs_cow_block(trans, root, b,
 					       p->nodes[level + 1],
 					       p->nodes[level + 1],
 					       p->slots[level + 1],
 					       p->slots[level + 1],
@@ -1446,6 +1567,22 @@ cow_done:
 		if (!p->skip_locking)
 		if (!p->skip_locking)
 			p->locks[level] = 1;
 			p->locks[level] = 1;
 
 
+		btrfs_clear_path_blocking(p);
+
+		/*
+		 * we have a lock on b and as long as we aren't changing
+		 * the tree, there is no way to for the items in b to change.
+		 * It is safe to drop the lock on our parent before we
+		 * go through the expensive btree search on b.
+		 *
+		 * If cow is true, then we might be changing slot zero,
+		 * which may require changing the parent.  So, we can't
+		 * drop the lock until after we know which slot we're
+		 * operating on.
+		 */
+		if (!cow)
+			btrfs_unlock_up_safe(p, level + 1);
+
 		ret = check_block(root, p, level);
 		ret = check_block(root, p, level);
 		if (ret) {
 		if (ret) {
 			ret = -1;
 			ret = -1;
@@ -1453,6 +1590,7 @@ cow_done:
 		}
 		}
 
 
 		ret = bin_search(b, key, level, &slot);
 		ret = bin_search(b, key, level, &slot);
+
 		if (level != 0) {
 		if (level != 0) {
 			if (ret && slot > 0)
 			if (ret && slot > 0)
 				slot -= 1;
 				slot -= 1;
@@ -1460,7 +1598,16 @@ cow_done:
 			if ((p->search_for_split || ins_len > 0) &&
 			if ((p->search_for_split || ins_len > 0) &&
 			    btrfs_header_nritems(b) >=
 			    btrfs_header_nritems(b) >=
 			    BTRFS_NODEPTRS_PER_BLOCK(root) - 3) {
 			    BTRFS_NODEPTRS_PER_BLOCK(root) - 3) {
-				int sret = split_node(trans, root, p, level);
+				int sret;
+
+				sret = reada_for_balance(root, p, level);
+				if (sret)
+					goto again;
+
+				btrfs_set_path_blocking(p);
+				sret = split_node(trans, root, p, level);
+				btrfs_clear_path_blocking(p);
+
 				BUG_ON(sret > 0);
 				BUG_ON(sret > 0);
 				if (sret) {
 				if (sret) {
 					ret = sret;
 					ret = sret;
@@ -1468,9 +1615,19 @@ cow_done:
 				}
 				}
 				b = p->nodes[level];
 				b = p->nodes[level];
 				slot = p->slots[level];
 				slot = p->slots[level];
-			} else if (ins_len < 0) {
-				int sret = balance_level(trans, root, p,
-							 level);
+			} else if (ins_len < 0 &&
+				   btrfs_header_nritems(b) <
+				   BTRFS_NODEPTRS_PER_BLOCK(root) / 4) {
+				int sret;
+
+				sret = reada_for_balance(root, p, level);
+				if (sret)
+					goto again;
+
+				btrfs_set_path_blocking(p);
+				sret = balance_level(trans, root, p, level);
+				btrfs_clear_path_blocking(p);
+
 				if (sret) {
 				if (sret) {
 					ret = sret;
 					ret = sret;
 					goto done;
 					goto done;
@@ -1504,7 +1661,7 @@ cow_done:
 				 * of the btree by dropping locks before
 				 * of the btree by dropping locks before
 				 * we read.
 				 * we read.
 				 */
 				 */
-				if (level > 1) {
+				if (level > 0) {
 					btrfs_release_path(NULL, p);
 					btrfs_release_path(NULL, p);
 					if (tmp)
 					if (tmp)
 						free_extent_buffer(tmp);
 						free_extent_buffer(tmp);
@@ -1519,6 +1676,7 @@ cow_done:
 						free_extent_buffer(tmp);
 						free_extent_buffer(tmp);
 					goto again;
 					goto again;
 				} else {
 				} else {
+					btrfs_set_path_blocking(p);
 					if (tmp)
 					if (tmp)
 						free_extent_buffer(tmp);
 						free_extent_buffer(tmp);
 					if (should_reada)
 					if (should_reada)
@@ -1528,14 +1686,29 @@ cow_done:
 					b = read_node_slot(root, b, slot);
 					b = read_node_slot(root, b, slot);
 				}
 				}
 			}
 			}
-			if (!p->skip_locking)
-				btrfs_tree_lock(b);
+			if (!p->skip_locking) {
+				int lret;
+
+				btrfs_clear_path_blocking(p);
+				lret = btrfs_try_spin_lock(b);
+
+				if (!lret) {
+					btrfs_set_path_blocking(p);
+					btrfs_tree_lock(b);
+					btrfs_clear_path_blocking(p);
+				}
+			}
 		} else {
 		} else {
 			p->slots[level] = slot;
 			p->slots[level] = slot;
 			if (ins_len > 0 &&
 			if (ins_len > 0 &&
 			    btrfs_leaf_free_space(root, b) < ins_len) {
 			    btrfs_leaf_free_space(root, b) < ins_len) {
-				int sret = split_leaf(trans, root, key,
+				int sret;
+
+				btrfs_set_path_blocking(p);
+				sret = split_leaf(trans, root, key,
 						      p, ins_len, ret == 0);
 						      p, ins_len, ret == 0);
+				btrfs_clear_path_blocking(p);
+
 				BUG_ON(sret > 0);
 				BUG_ON(sret > 0);
 				if (sret) {
 				if (sret) {
 					ret = sret;
 					ret = sret;
@@ -1549,12 +1722,16 @@ cow_done:
 	}
 	}
 	ret = 1;
 	ret = 1;
 done:
 done:
+	/*
+	 * we don't really know what they plan on doing with the path
+	 * from here on, so for now just mark it as blocking
+	 */
+	btrfs_set_path_blocking(p);
 	if (prealloc_block.objectid) {
 	if (prealloc_block.objectid) {
 		btrfs_free_reserved_extent(root,
 		btrfs_free_reserved_extent(root,
 			   prealloc_block.objectid,
 			   prealloc_block.objectid,
 			   prealloc_block.offset);
 			   prealloc_block.offset);
 	}
 	}
-
 	return ret;
 	return ret;
 }
 }
 
 
@@ -1578,6 +1755,8 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans,
 	ret = btrfs_cow_block(trans, root, eb, NULL, 0, &eb, 0);
 	ret = btrfs_cow_block(trans, root, eb, NULL, 0, &eb, 0);
 	BUG_ON(ret);
 	BUG_ON(ret);
 
 
+	btrfs_set_lock_blocking(eb);
+
 	parent = eb;
 	parent = eb;
 	while (1) {
 	while (1) {
 		level = btrfs_header_level(parent);
 		level = btrfs_header_level(parent);
@@ -1602,6 +1781,7 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans,
 			eb = read_tree_block(root, bytenr, blocksize,
 			eb = read_tree_block(root, bytenr, blocksize,
 					     generation);
 					     generation);
 			btrfs_tree_lock(eb);
 			btrfs_tree_lock(eb);
+			btrfs_set_lock_blocking(eb);
 		}
 		}
 
 
 		/*
 		/*
@@ -1626,6 +1806,7 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans,
 				eb = read_tree_block(root, bytenr, blocksize,
 				eb = read_tree_block(root, bytenr, blocksize,
 						generation);
 						generation);
 				btrfs_tree_lock(eb);
 				btrfs_tree_lock(eb);
+				btrfs_set_lock_blocking(eb);
 			}
 			}
 
 
 			ret = btrfs_cow_block(trans, root, eb, parent, slot,
 			ret = btrfs_cow_block(trans, root, eb, parent, slot,
@@ -2172,6 +2353,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
 
 
 	right = read_node_slot(root, upper, slot + 1);
 	right = read_node_slot(root, upper, slot + 1);
 	btrfs_tree_lock(right);
 	btrfs_tree_lock(right);
+	btrfs_set_lock_blocking(right);
+
 	free_space = btrfs_leaf_free_space(root, right);
 	free_space = btrfs_leaf_free_space(root, right);
 	if (free_space < data_size)
 	if (free_space < data_size)
 		goto out_unlock;
 		goto out_unlock;
@@ -2367,6 +2550,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
 
 
 	left = read_node_slot(root, path->nodes[1], slot - 1);
 	left = read_node_slot(root, path->nodes[1], slot - 1);
 	btrfs_tree_lock(left);
 	btrfs_tree_lock(left);
+	btrfs_set_lock_blocking(left);
+
 	free_space = btrfs_leaf_free_space(root, left);
 	free_space = btrfs_leaf_free_space(root, left);
 	if (free_space < data_size) {
 	if (free_space < data_size) {
 		ret = 1;
 		ret = 1;
@@ -2825,6 +3010,12 @@ int btrfs_split_item(struct btrfs_trans_handle *trans,
 	path->keep_locks = 0;
 	path->keep_locks = 0;
 	BUG_ON(ret);
 	BUG_ON(ret);
 
 
+	/*
+	 * make sure any changes to the path from split_leaf leave it
+	 * in a blocking state
+	 */
+	btrfs_set_path_blocking(path);
+
 	leaf = path->nodes[0];
 	leaf = path->nodes[0];
 	BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item));
 	BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item));
 
 
@@ -3354,6 +3545,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
 		BUG();
 		BUG();
 	}
 	}
 out:
 out:
+	btrfs_unlock_up_safe(path, 1);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -3441,15 +3633,22 @@ noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
 {
 {
 	int ret;
 	int ret;
 	u64 root_gen = btrfs_header_generation(path->nodes[1]);
 	u64 root_gen = btrfs_header_generation(path->nodes[1]);
+	u64 parent_start = path->nodes[1]->start;
+	u64 parent_owner = btrfs_header_owner(path->nodes[1]);
 
 
 	ret = del_ptr(trans, root, path, 1, path->slots[1]);
 	ret = del_ptr(trans, root, path, 1, path->slots[1]);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
+	/*
+	 * btrfs_free_extent is expensive, we want to make sure we
+	 * aren't holding any locks when we call it
+	 */
+	btrfs_unlock_up_safe(path, 0);
+
 	ret = btrfs_free_extent(trans, root, bytenr,
 	ret = btrfs_free_extent(trans, root, bytenr,
 				btrfs_level_size(root, 0),
 				btrfs_level_size(root, 0),
-				path->nodes[1]->start,
-				btrfs_header_owner(path->nodes[1]),
+				parent_start, parent_owner,
 				root_gen, 0, 1);
 				root_gen, 0, 1);
 	return ret;
 	return ret;
 }
 }
@@ -3721,12 +3920,14 @@ find_next_key:
 		 */
 		 */
 		if (slot >= nritems) {
 		if (slot >= nritems) {
 			path->slots[level] = slot;
 			path->slots[level] = slot;
+			btrfs_set_path_blocking(path);
 			sret = btrfs_find_next_key(root, path, min_key, level,
 			sret = btrfs_find_next_key(root, path, min_key, level,
 						  cache_only, min_trans);
 						  cache_only, min_trans);
 			if (sret == 0) {
 			if (sret == 0) {
 				btrfs_release_path(root, path);
 				btrfs_release_path(root, path);
 				goto again;
 				goto again;
 			} else {
 			} else {
+				btrfs_clear_path_blocking(path);
 				goto out;
 				goto out;
 			}
 			}
 		}
 		}
@@ -3738,16 +3939,20 @@ find_next_key:
 			unlock_up(path, level, 1);
 			unlock_up(path, level, 1);
 			goto out;
 			goto out;
 		}
 		}
+		btrfs_set_path_blocking(path);
 		cur = read_node_slot(root, cur, slot);
 		cur = read_node_slot(root, cur, slot);
 
 
 		btrfs_tree_lock(cur);
 		btrfs_tree_lock(cur);
+
 		path->locks[level - 1] = 1;
 		path->locks[level - 1] = 1;
 		path->nodes[level - 1] = cur;
 		path->nodes[level - 1] = cur;
 		unlock_up(path, level, 1);
 		unlock_up(path, level, 1);
+		btrfs_clear_path_blocking(path);
 	}
 	}
 out:
 out:
 	if (ret == 0)
 	if (ret == 0)
 		memcpy(min_key, &found_key, sizeof(found_key));
 		memcpy(min_key, &found_key, sizeof(found_key));
+	btrfs_set_path_blocking(path);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -3843,6 +4048,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
+	btrfs_set_path_blocking(path);
 	nritems = btrfs_header_nritems(path->nodes[0]);
 	nritems = btrfs_header_nritems(path->nodes[0]);
 	/*
 	/*
 	 * by releasing the path above we dropped all our locks.  A balance
 	 * by releasing the path above we dropped all our locks.  A balance
@@ -3873,6 +4079,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
 			free_extent_buffer(next);
 			free_extent_buffer(next);
 		}
 		}
 
 
+		/* the path was set to blocking above */
 		if (level == 1 && (path->locks[1] || path->skip_locking) &&
 		if (level == 1 && (path->locks[1] || path->skip_locking) &&
 		    path->reada)
 		    path->reada)
 			reada_for_search(root, path, level, slot, 0);
 			reada_for_search(root, path, level, slot, 0);
@@ -3881,6 +4088,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
 		if (!path->skip_locking) {
 		if (!path->skip_locking) {
 			WARN_ON(!btrfs_tree_locked(c));
 			WARN_ON(!btrfs_tree_locked(c));
 			btrfs_tree_lock(next);
 			btrfs_tree_lock(next);
+			btrfs_set_lock_blocking(next);
 		}
 		}
 		break;
 		break;
 	}
 	}
@@ -3897,12 +4105,15 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
 			path->locks[level] = 1;
 			path->locks[level] = 1;
 		if (!level)
 		if (!level)
 			break;
 			break;
+
+		btrfs_set_path_blocking(path);
 		if (level == 1 && path->locks[1] && path->reada)
 		if (level == 1 && path->locks[1] && path->reada)
 			reada_for_search(root, path, level, slot, 0);
 			reada_for_search(root, path, level, slot, 0);
 		next = read_node_slot(root, next, 0);
 		next = read_node_slot(root, next, 0);
 		if (!path->skip_locking) {
 		if (!path->skip_locking) {
 			WARN_ON(!btrfs_tree_locked(path->nodes[level]));
 			WARN_ON(!btrfs_tree_locked(path->nodes[level]));
 			btrfs_tree_lock(next);
 			btrfs_tree_lock(next);
+			btrfs_set_lock_blocking(next);
 		}
 		}
 	}
 	}
 done:
 done:
@@ -3927,6 +4138,7 @@ int btrfs_previous_item(struct btrfs_root *root,
 
 
 	while (1) {
 	while (1) {
 		if (path->slots[0] == 0) {
 		if (path->slots[0] == 0) {
+			btrfs_set_path_blocking(path);
 			ret = btrfs_prev_leaf(root, path);
 			ret = btrfs_prev_leaf(root, path);
 			if (ret != 0)
 			if (ret != 0)
 				return ret;
 				return ret;

+ 13 - 15
fs/btrfs/ctree.h

@@ -454,17 +454,11 @@ struct btrfs_timespec {
 	__le32 nsec;
 	__le32 nsec;
 } __attribute__ ((__packed__));
 } __attribute__ ((__packed__));
 
 
-typedef enum {
+enum btrfs_compression_type {
 	BTRFS_COMPRESS_NONE = 0,
 	BTRFS_COMPRESS_NONE = 0,
 	BTRFS_COMPRESS_ZLIB = 1,
 	BTRFS_COMPRESS_ZLIB = 1,
 	BTRFS_COMPRESS_LAST = 2,
 	BTRFS_COMPRESS_LAST = 2,
-} btrfs_compression_type;
-
-/* we don't understand any encryption methods right now */
-typedef enum {
-	BTRFS_ENCRYPTION_NONE = 0,
-	BTRFS_ENCRYPTION_LAST = 1,
-} btrfs_encryption_type;
+};
 
 
 struct btrfs_inode_item {
 struct btrfs_inode_item {
 	/* nfs style generation number */
 	/* nfs style generation number */
@@ -701,9 +695,7 @@ struct btrfs_fs_info {
 	struct btrfs_transaction *running_transaction;
 	struct btrfs_transaction *running_transaction;
 	wait_queue_head_t transaction_throttle;
 	wait_queue_head_t transaction_throttle;
 	wait_queue_head_t transaction_wait;
 	wait_queue_head_t transaction_wait;
-
 	wait_queue_head_t async_submit_wait;
 	wait_queue_head_t async_submit_wait;
-	wait_queue_head_t tree_log_wait;
 
 
 	struct btrfs_super_block super_copy;
 	struct btrfs_super_block super_copy;
 	struct btrfs_super_block super_for_commit;
 	struct btrfs_super_block super_for_commit;
@@ -711,7 +703,6 @@ struct btrfs_fs_info {
 	struct super_block *sb;
 	struct super_block *sb;
 	struct inode *btree_inode;
 	struct inode *btree_inode;
 	struct backing_dev_info bdi;
 	struct backing_dev_info bdi;
-	spinlock_t hash_lock;
 	struct mutex trans_mutex;
 	struct mutex trans_mutex;
 	struct mutex tree_log_mutex;
 	struct mutex tree_log_mutex;
 	struct mutex transaction_kthread_mutex;
 	struct mutex transaction_kthread_mutex;
@@ -730,10 +721,6 @@ struct btrfs_fs_info {
 	atomic_t async_submit_draining;
 	atomic_t async_submit_draining;
 	atomic_t nr_async_bios;
 	atomic_t nr_async_bios;
 	atomic_t async_delalloc_pages;
 	atomic_t async_delalloc_pages;
-	atomic_t tree_log_writers;
-	atomic_t tree_log_commit;
-	unsigned long tree_log_batch;
-	u64 tree_log_transid;
 
 
 	/*
 	/*
 	 * this is used by the balancing code to wait for all the pending
 	 * this is used by the balancing code to wait for all the pending
@@ -833,7 +820,14 @@ struct btrfs_root {
 	struct kobject root_kobj;
 	struct kobject root_kobj;
 	struct completion kobj_unregister;
 	struct completion kobj_unregister;
 	struct mutex objectid_mutex;
 	struct mutex objectid_mutex;
+
 	struct mutex log_mutex;
 	struct mutex log_mutex;
+	wait_queue_head_t log_writer_wait;
+	wait_queue_head_t log_commit_wait[2];
+	atomic_t log_writers;
+	atomic_t log_commit[2];
+	unsigned long log_transid;
+	unsigned long log_batch;
 
 
 	u64 objectid;
 	u64 objectid;
 	u64 last_trans;
 	u64 last_trans;
@@ -1841,6 +1835,10 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
 struct btrfs_path *btrfs_alloc_path(void);
 struct btrfs_path *btrfs_alloc_path(void);
 void btrfs_free_path(struct btrfs_path *p);
 void btrfs_free_path(struct btrfs_path *p);
 void btrfs_init_path(struct btrfs_path *p);
 void btrfs_init_path(struct btrfs_path *p);
+void btrfs_set_path_blocking(struct btrfs_path *p);
+void btrfs_clear_path_blocking(struct btrfs_path *p);
+void btrfs_unlock_up_safe(struct btrfs_path *p, int level);
+
 int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		   struct btrfs_path *path, int slot, int nr);
 		   struct btrfs_path *path, int slot, int nr);
 int btrfs_del_leaf(struct btrfs_trans_handle *trans,
 int btrfs_del_leaf(struct btrfs_trans_handle *trans,

+ 87 - 33
fs/btrfs/disk-io.c

@@ -16,7 +16,6 @@
  * Boston, MA 021110-1307, USA.
  * Boston, MA 021110-1307, USA.
  */
  */
 
 
-#include <linux/version.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/blkdev.h>
 #include <linux/blkdev.h>
 #include <linux/scatterlist.h>
 #include <linux/scatterlist.h>
@@ -800,7 +799,7 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
 	ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
 	ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
 
 
 	if (ret == 0)
 	if (ret == 0)
-		buf->flags |= EXTENT_UPTODATE;
+		set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags);
 	else
 	else
 		WARN_ON(1);
 		WARN_ON(1);
 	return buf;
 	return buf;
@@ -814,6 +813,10 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 	if (btrfs_header_generation(buf) ==
 	if (btrfs_header_generation(buf) ==
 	    root->fs_info->running_transaction->transid) {
 	    root->fs_info->running_transaction->transid) {
 		WARN_ON(!btrfs_tree_locked(buf));
 		WARN_ON(!btrfs_tree_locked(buf));
+
+		/* ugh, clear_extent_buffer_dirty can be expensive */
+		btrfs_set_lock_blocking(buf);
+
 		clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree,
 		clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree,
 					  buf);
 					  buf);
 	}
 	}
@@ -850,6 +853,14 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
 	spin_lock_init(&root->list_lock);
 	spin_lock_init(&root->list_lock);
 	mutex_init(&root->objectid_mutex);
 	mutex_init(&root->objectid_mutex);
 	mutex_init(&root->log_mutex);
 	mutex_init(&root->log_mutex);
+	init_waitqueue_head(&root->log_writer_wait);
+	init_waitqueue_head(&root->log_commit_wait[0]);
+	init_waitqueue_head(&root->log_commit_wait[1]);
+	atomic_set(&root->log_commit[0], 0);
+	atomic_set(&root->log_commit[1], 0);
+	atomic_set(&root->log_writers, 0);
+	root->log_batch = 0;
+	root->log_transid = 0;
 	extent_io_tree_init(&root->dirty_log_pages,
 	extent_io_tree_init(&root->dirty_log_pages,
 			     fs_info->btree_inode->i_mapping, GFP_NOFS);
 			     fs_info->btree_inode->i_mapping, GFP_NOFS);
 
 
@@ -934,15 +945,16 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
 	return 0;
 	return 0;
 }
 }
 
 
-int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
-			     struct btrfs_fs_info *fs_info)
+static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans,
+					 struct btrfs_fs_info *fs_info)
 {
 {
 	struct btrfs_root *root;
 	struct btrfs_root *root;
 	struct btrfs_root *tree_root = fs_info->tree_root;
 	struct btrfs_root *tree_root = fs_info->tree_root;
+	struct extent_buffer *leaf;
 
 
 	root = kzalloc(sizeof(*root), GFP_NOFS);
 	root = kzalloc(sizeof(*root), GFP_NOFS);
 	if (!root)
 	if (!root)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 
 	__setup_root(tree_root->nodesize, tree_root->leafsize,
 	__setup_root(tree_root->nodesize, tree_root->leafsize,
 		     tree_root->sectorsize, tree_root->stripesize,
 		     tree_root->sectorsize, tree_root->stripesize,
@@ -951,12 +963,23 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
 	root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID;
 	root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID;
 	root->root_key.type = BTRFS_ROOT_ITEM_KEY;
 	root->root_key.type = BTRFS_ROOT_ITEM_KEY;
 	root->root_key.offset = BTRFS_TREE_LOG_OBJECTID;
 	root->root_key.offset = BTRFS_TREE_LOG_OBJECTID;
+	/*
+	 * log trees do not get reference counted because they go away
+	 * before a real commit is actually done.  They do store pointers
+	 * to file data extents, and those reference counts still get
+	 * updated (along with back refs to the log tree).
+	 */
 	root->ref_cows = 0;
 	root->ref_cows = 0;
 
 
-	root->node = btrfs_alloc_free_block(trans, root, root->leafsize,
-					    0, BTRFS_TREE_LOG_OBJECTID,
-					    trans->transid, 0, 0, 0);
+	leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
+				      0, BTRFS_TREE_LOG_OBJECTID,
+				      trans->transid, 0, 0, 0);
+	if (IS_ERR(leaf)) {
+		kfree(root);
+		return ERR_CAST(leaf);
+	}
 
 
+	root->node = leaf;
 	btrfs_set_header_nritems(root->node, 0);
 	btrfs_set_header_nritems(root->node, 0);
 	btrfs_set_header_level(root->node, 0);
 	btrfs_set_header_level(root->node, 0);
 	btrfs_set_header_bytenr(root->node, root->node->start);
 	btrfs_set_header_bytenr(root->node, root->node->start);
@@ -968,7 +991,48 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
 			    BTRFS_FSID_SIZE);
 			    BTRFS_FSID_SIZE);
 	btrfs_mark_buffer_dirty(root->node);
 	btrfs_mark_buffer_dirty(root->node);
 	btrfs_tree_unlock(root->node);
 	btrfs_tree_unlock(root->node);
-	fs_info->log_root_tree = root;
+	return root;
+}
+
+int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
+			     struct btrfs_fs_info *fs_info)
+{
+	struct btrfs_root *log_root;
+
+	log_root = alloc_log_tree(trans, fs_info);
+	if (IS_ERR(log_root))
+		return PTR_ERR(log_root);
+	WARN_ON(fs_info->log_root_tree);
+	fs_info->log_root_tree = log_root;
+	return 0;
+}
+
+int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
+		       struct btrfs_root *root)
+{
+	struct btrfs_root *log_root;
+	struct btrfs_inode_item *inode_item;
+
+	log_root = alloc_log_tree(trans, root->fs_info);
+	if (IS_ERR(log_root))
+		return PTR_ERR(log_root);
+
+	log_root->last_trans = trans->transid;
+	log_root->root_key.offset = root->root_key.objectid;
+
+	inode_item = &log_root->root_item.inode;
+	inode_item->generation = cpu_to_le64(1);
+	inode_item->size = cpu_to_le64(3);
+	inode_item->nlink = cpu_to_le32(1);
+	inode_item->nbytes = cpu_to_le64(root->leafsize);
+	inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
+
+	btrfs_set_root_bytenr(&log_root->root_item, log_root->node->start);
+	btrfs_set_root_generation(&log_root->root_item, trans->transid);
+
+	WARN_ON(root->log_root);
+	root->log_root = log_root;
+	root->log_transid = 0;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1136,7 +1200,6 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
 {
 {
 	struct btrfs_fs_info *info = (struct btrfs_fs_info *)congested_data;
 	struct btrfs_fs_info *info = (struct btrfs_fs_info *)congested_data;
 	int ret = 0;
 	int ret = 0;
-	struct list_head *cur;
 	struct btrfs_device *device;
 	struct btrfs_device *device;
 	struct backing_dev_info *bdi;
 	struct backing_dev_info *bdi;
 #if 0
 #if 0
@@ -1144,8 +1207,7 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
 	    btrfs_congested_async(info, 0))
 	    btrfs_congested_async(info, 0))
 		return 1;
 		return 1;
 #endif
 #endif
-	list_for_each(cur, &info->fs_devices->devices) {
-		device = list_entry(cur, struct btrfs_device, dev_list);
+	list_for_each_entry(device, &info->fs_devices->devices, dev_list) {
 		if (!device->bdev)
 		if (!device->bdev)
 			continue;
 			continue;
 		bdi = blk_get_backing_dev_info(device->bdev);
 		bdi = blk_get_backing_dev_info(device->bdev);
@@ -1163,13 +1225,11 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
  */
  */
 static void __unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
 static void __unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
 {
 {
-	struct list_head *cur;
 	struct btrfs_device *device;
 	struct btrfs_device *device;
 	struct btrfs_fs_info *info;
 	struct btrfs_fs_info *info;
 
 
 	info = (struct btrfs_fs_info *)bdi->unplug_io_data;
 	info = (struct btrfs_fs_info *)bdi->unplug_io_data;
-	list_for_each(cur, &info->fs_devices->devices) {
-		device = list_entry(cur, struct btrfs_device, dev_list);
+	list_for_each_entry(device, &info->fs_devices->devices, dev_list) {
 		if (!device->bdev)
 		if (!device->bdev)
 			continue;
 			continue;
 
 
@@ -1447,7 +1507,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 	INIT_LIST_HEAD(&fs_info->dead_roots);
 	INIT_LIST_HEAD(&fs_info->dead_roots);
 	INIT_LIST_HEAD(&fs_info->hashers);
 	INIT_LIST_HEAD(&fs_info->hashers);
 	INIT_LIST_HEAD(&fs_info->delalloc_inodes);
 	INIT_LIST_HEAD(&fs_info->delalloc_inodes);
-	spin_lock_init(&fs_info->hash_lock);
 	spin_lock_init(&fs_info->delalloc_lock);
 	spin_lock_init(&fs_info->delalloc_lock);
 	spin_lock_init(&fs_info->new_trans_lock);
 	spin_lock_init(&fs_info->new_trans_lock);
 	spin_lock_init(&fs_info->ref_cache_lock);
 	spin_lock_init(&fs_info->ref_cache_lock);
@@ -1535,10 +1594,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 	init_waitqueue_head(&fs_info->transaction_throttle);
 	init_waitqueue_head(&fs_info->transaction_throttle);
 	init_waitqueue_head(&fs_info->transaction_wait);
 	init_waitqueue_head(&fs_info->transaction_wait);
 	init_waitqueue_head(&fs_info->async_submit_wait);
 	init_waitqueue_head(&fs_info->async_submit_wait);
-	init_waitqueue_head(&fs_info->tree_log_wait);
-	atomic_set(&fs_info->tree_log_commit, 0);
-	atomic_set(&fs_info->tree_log_writers, 0);
-	fs_info->tree_log_transid = 0;
 
 
 	__setup_root(4096, 4096, 4096, 4096, tree_root,
 	__setup_root(4096, 4096, 4096, 4096, tree_root,
 		     fs_info, BTRFS_ROOT_TREE_OBJECTID);
 		     fs_info, BTRFS_ROOT_TREE_OBJECTID);
@@ -1627,6 +1682,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 	 * low idle thresh
 	 * low idle thresh
 	 */
 	 */
 	fs_info->endio_workers.idle_thresh = 4;
 	fs_info->endio_workers.idle_thresh = 4;
+	fs_info->endio_meta_workers.idle_thresh = 4;
+
 	fs_info->endio_write_workers.idle_thresh = 64;
 	fs_info->endio_write_workers.idle_thresh = 64;
 	fs_info->endio_meta_write_workers.idle_thresh = 64;
 	fs_info->endio_meta_write_workers.idle_thresh = 64;
 
 
@@ -1740,13 +1797,13 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 	fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
 	fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
 	fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
 	fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
 					       "btrfs-cleaner");
 					       "btrfs-cleaner");
-	if (!fs_info->cleaner_kthread)
+	if (IS_ERR(fs_info->cleaner_kthread))
 		goto fail_csum_root;
 		goto fail_csum_root;
 
 
 	fs_info->transaction_kthread = kthread_run(transaction_kthread,
 	fs_info->transaction_kthread = kthread_run(transaction_kthread,
 						   tree_root,
 						   tree_root,
 						   "btrfs-transaction");
 						   "btrfs-transaction");
-	if (!fs_info->transaction_kthread)
+	if (IS_ERR(fs_info->transaction_kthread))
 		goto fail_cleaner;
 		goto fail_cleaner;
 
 
 	if (btrfs_super_log_root(disk_super) != 0) {
 	if (btrfs_super_log_root(disk_super) != 0) {
@@ -1828,13 +1885,14 @@ fail_sb_buffer:
 fail_iput:
 fail_iput:
 	invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
 	invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
 	iput(fs_info->btree_inode);
 	iput(fs_info->btree_inode);
-fail:
+
 	btrfs_close_devices(fs_info->fs_devices);
 	btrfs_close_devices(fs_info->fs_devices);
 	btrfs_mapping_tree_free(&fs_info->mapping_tree);
 	btrfs_mapping_tree_free(&fs_info->mapping_tree);
+	bdi_destroy(&fs_info->bdi);
 
 
+fail:
 	kfree(extent_root);
 	kfree(extent_root);
 	kfree(tree_root);
 	kfree(tree_root);
-	bdi_destroy(&fs_info->bdi);
 	kfree(fs_info);
 	kfree(fs_info);
 	kfree(chunk_root);
 	kfree(chunk_root);
 	kfree(dev_root);
 	kfree(dev_root);
@@ -1995,7 +2053,6 @@ static int write_dev_supers(struct btrfs_device *device,
 
 
 int write_all_supers(struct btrfs_root *root, int max_mirrors)
 int write_all_supers(struct btrfs_root *root, int max_mirrors)
 {
 {
-	struct list_head *cur;
 	struct list_head *head = &root->fs_info->fs_devices->devices;
 	struct list_head *head = &root->fs_info->fs_devices->devices;
 	struct btrfs_device *dev;
 	struct btrfs_device *dev;
 	struct btrfs_super_block *sb;
 	struct btrfs_super_block *sb;
@@ -2011,8 +2068,7 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors)
 
 
 	sb = &root->fs_info->super_for_commit;
 	sb = &root->fs_info->super_for_commit;
 	dev_item = &sb->dev_item;
 	dev_item = &sb->dev_item;
-	list_for_each(cur, head) {
-		dev = list_entry(cur, struct btrfs_device, dev_list);
+	list_for_each_entry(dev, head, dev_list) {
 		if (!dev->bdev) {
 		if (!dev->bdev) {
 			total_errors++;
 			total_errors++;
 			continue;
 			continue;
@@ -2045,8 +2101,7 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors)
 	}
 	}
 
 
 	total_errors = 0;
 	total_errors = 0;
-	list_for_each(cur, head) {
-		dev = list_entry(cur, struct btrfs_device, dev_list);
+	list_for_each_entry(dev, head, dev_list) {
 		if (!dev->bdev)
 		if (!dev->bdev)
 			continue;
 			continue;
 		if (!dev->in_fs_metadata || !dev->writeable)
 		if (!dev->in_fs_metadata || !dev->writeable)
@@ -2260,6 +2315,8 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
 	u64 transid = btrfs_header_generation(buf);
 	u64 transid = btrfs_header_generation(buf);
 	struct inode *btree_inode = root->fs_info->btree_inode;
 	struct inode *btree_inode = root->fs_info->btree_inode;
 
 
+	btrfs_set_lock_blocking(buf);
+
 	WARN_ON(!btrfs_tree_locked(buf));
 	WARN_ON(!btrfs_tree_locked(buf));
 	if (transid != root->fs_info->generation) {
 	if (transid != root->fs_info->generation) {
 		printk(KERN_CRIT "btrfs transid mismatch buffer %llu, "
 		printk(KERN_CRIT "btrfs transid mismatch buffer %llu, "
@@ -2302,14 +2359,13 @@ int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid)
 	int ret;
 	int ret;
 	ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
 	ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
 	if (ret == 0)
 	if (ret == 0)
-		buf->flags |= EXTENT_UPTODATE;
+		set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags);
 	return ret;
 	return ret;
 }
 }
 
 
 int btree_lock_page_hook(struct page *page)
 int btree_lock_page_hook(struct page *page)
 {
 {
 	struct inode *inode = page->mapping->host;
 	struct inode *inode = page->mapping->host;
-	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
 	struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
 	struct extent_buffer *eb;
 	struct extent_buffer *eb;
 	unsigned long len;
 	unsigned long len;
@@ -2324,9 +2380,7 @@ int btree_lock_page_hook(struct page *page)
 		goto out;
 		goto out;
 
 
 	btrfs_tree_lock(eb);
 	btrfs_tree_lock(eb);
-	spin_lock(&root->fs_info->hash_lock);
 	btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
 	btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
-	spin_unlock(&root->fs_info->hash_lock);
 	btrfs_tree_unlock(eb);
 	btrfs_tree_unlock(eb);
 	free_extent_buffer(eb);
 	free_extent_buffer(eb);
 out:
 out:

+ 2 - 0
fs/btrfs/disk-io.h

@@ -98,5 +98,7 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
 			     struct btrfs_fs_info *fs_info);
 			     struct btrfs_fs_info *fs_info);
 int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
 int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
 			     struct btrfs_fs_info *fs_info);
 			     struct btrfs_fs_info *fs_info);
+int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
+		       struct btrfs_root *root);
 int btree_lock_page_hook(struct page *page);
 int btree_lock_page_hook(struct page *page);
 #endif
 #endif

+ 365 - 73
fs/btrfs/extent-tree.c

@@ -19,7 +19,7 @@
 #include <linux/pagemap.h>
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
 #include <linux/writeback.h>
 #include <linux/blkdev.h>
 #include <linux/blkdev.h>
-#include <linux/version.h>
+#include <linux/sort.h>
 #include "compat.h"
 #include "compat.h"
 #include "hash.h"
 #include "hash.h"
 #include "crc32c.h"
 #include "crc32c.h"
@@ -30,7 +30,6 @@
 #include "volumes.h"
 #include "volumes.h"
 #include "locking.h"
 #include "locking.h"
 #include "ref-cache.h"
 #include "ref-cache.h"
-#include "compat.h"
 
 
 #define PENDING_EXTENT_INSERT 0
 #define PENDING_EXTENT_INSERT 0
 #define PENDING_EXTENT_DELETE 1
 #define PENDING_EXTENT_DELETE 1
@@ -326,10 +325,8 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
 						  u64 flags)
 						  u64 flags)
 {
 {
 	struct list_head *head = &info->space_info;
 	struct list_head *head = &info->space_info;
-	struct list_head *cur;
 	struct btrfs_space_info *found;
 	struct btrfs_space_info *found;
-	list_for_each(cur, head) {
-		found = list_entry(cur, struct btrfs_space_info, list);
+	list_for_each_entry(found, head, list) {
 		if (found->flags == flags)
 		if (found->flags == flags)
 			return found;
 			return found;
 	}
 	}
@@ -1525,15 +1522,55 @@ out:
 	return ret;
 	return ret;
 }
 }
 
 
-int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-		  struct extent_buffer *orig_buf, struct extent_buffer *buf,
-		  u32 *nr_extents)
+/* when a block goes through cow, we update the reference counts of
+ * everything that block points to.  The internal pointers of the block
+ * can be in just about any order, and it is likely to have clusters of
+ * things that are close together and clusters of things that are not.
+ *
+ * To help reduce the seeks that come with updating all of these reference
+ * counts, sort them by byte number before actual updates are done.
+ *
+ * struct refsort is used to match byte number to slot in the btree block.
+ * we sort based on the byte number and then use the slot to actually
+ * find the item.
+ *
+ * struct refsort is smaller than strcut btrfs_item and smaller than
+ * struct btrfs_key_ptr.  Since we're currently limited to the page size
+ * for a btree block, there's no way for a kmalloc of refsorts for a
+ * single node to be bigger than a page.
+ */
+struct refsort {
+	u64 bytenr;
+	u32 slot;
+};
+
+/*
+ * for passing into sort()
+ */
+static int refsort_cmp(const void *a_void, const void *b_void)
+{
+	const struct refsort *a = a_void;
+	const struct refsort *b = b_void;
+
+	if (a->bytenr < b->bytenr)
+		return -1;
+	if (a->bytenr > b->bytenr)
+		return 1;
+	return 0;
+}
+
+
+noinline int btrfs_inc_ref(struct btrfs_trans_handle *trans,
+			   struct btrfs_root *root,
+			   struct extent_buffer *orig_buf,
+			   struct extent_buffer *buf, u32 *nr_extents)
 {
 {
 	u64 bytenr;
 	u64 bytenr;
 	u64 ref_root;
 	u64 ref_root;
 	u64 orig_root;
 	u64 orig_root;
 	u64 ref_generation;
 	u64 ref_generation;
 	u64 orig_generation;
 	u64 orig_generation;
+	struct refsort *sorted;
 	u32 nritems;
 	u32 nritems;
 	u32 nr_file_extents = 0;
 	u32 nr_file_extents = 0;
 	struct btrfs_key key;
 	struct btrfs_key key;
@@ -1542,6 +1579,8 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 	int level;
 	int level;
 	int ret = 0;
 	int ret = 0;
 	int faili = 0;
 	int faili = 0;
+	int refi = 0;
+	int slot;
 	int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *,
 	int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *,
 			    u64, u64, u64, u64, u64, u64, u64, u64);
 			    u64, u64, u64, u64, u64, u64, u64, u64);
 
 
@@ -1553,6 +1592,9 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 	nritems = btrfs_header_nritems(buf);
 	nritems = btrfs_header_nritems(buf);
 	level = btrfs_header_level(buf);
 	level = btrfs_header_level(buf);
 
 
+	sorted = kmalloc(sizeof(struct refsort) * nritems, GFP_NOFS);
+	BUG_ON(!sorted);
+
 	if (root->ref_cows) {
 	if (root->ref_cows) {
 		process_func = __btrfs_inc_extent_ref;
 		process_func = __btrfs_inc_extent_ref;
 	} else {
 	} else {
@@ -1565,6 +1607,11 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		process_func = __btrfs_update_extent_ref;
 		process_func = __btrfs_update_extent_ref;
 	}
 	}
 
 
+	/*
+	 * we make two passes through the items.  In the first pass we
+	 * only record the byte number and slot.  Then we sort based on
+	 * byte number and do the actual work based on the sorted results
+	 */
 	for (i = 0; i < nritems; i++) {
 	for (i = 0; i < nritems; i++) {
 		cond_resched();
 		cond_resched();
 		if (level == 0) {
 		if (level == 0) {
@@ -1581,6 +1628,32 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 				continue;
 				continue;
 
 
 			nr_file_extents++;
 			nr_file_extents++;
+			sorted[refi].bytenr = bytenr;
+			sorted[refi].slot = i;
+			refi++;
+		} else {
+			bytenr = btrfs_node_blockptr(buf, i);
+			sorted[refi].bytenr = bytenr;
+			sorted[refi].slot = i;
+			refi++;
+		}
+	}
+	/*
+	 * if refi == 0, we didn't actually put anything into the sorted
+	 * array and we're done
+	 */
+	if (refi == 0)
+		goto out;
+
+	sort(sorted, refi, sizeof(struct refsort), refsort_cmp, NULL);
+
+	for (i = 0; i < refi; i++) {
+		cond_resched();
+		slot = sorted[i].slot;
+		bytenr = sorted[i].bytenr;
+
+		if (level == 0) {
+			btrfs_item_key_to_cpu(buf, &key, slot);
 
 
 			ret = process_func(trans, root, bytenr,
 			ret = process_func(trans, root, bytenr,
 					   orig_buf->start, buf->start,
 					   orig_buf->start, buf->start,
@@ -1589,25 +1662,25 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 					   key.objectid);
 					   key.objectid);
 
 
 			if (ret) {
 			if (ret) {
-				faili = i;
+				faili = slot;
 				WARN_ON(1);
 				WARN_ON(1);
 				goto fail;
 				goto fail;
 			}
 			}
 		} else {
 		} else {
-			bytenr = btrfs_node_blockptr(buf, i);
 			ret = process_func(trans, root, bytenr,
 			ret = process_func(trans, root, bytenr,
 					   orig_buf->start, buf->start,
 					   orig_buf->start, buf->start,
 					   orig_root, ref_root,
 					   orig_root, ref_root,
 					   orig_generation, ref_generation,
 					   orig_generation, ref_generation,
 					   level - 1);
 					   level - 1);
 			if (ret) {
 			if (ret) {
-				faili = i;
+				faili = slot;
 				WARN_ON(1);
 				WARN_ON(1);
 				goto fail;
 				goto fail;
 			}
 			}
 		}
 		}
 	}
 	}
 out:
 out:
+	kfree(sorted);
 	if (nr_extents) {
 	if (nr_extents) {
 		if (level == 0)
 		if (level == 0)
 			*nr_extents = nr_file_extents;
 			*nr_extents = nr_file_extents;
@@ -1616,6 +1689,7 @@ out:
 	}
 	}
 	return 0;
 	return 0;
 fail:
 fail:
+	kfree(sorted);
 	WARN_ON(1);
 	WARN_ON(1);
 	return ret;
 	return ret;
 }
 }
@@ -2159,7 +2233,8 @@ again:
 		ret = find_first_extent_bit(&info->extent_ins, search, &start,
 		ret = find_first_extent_bit(&info->extent_ins, search, &start,
 					    &end, EXTENT_WRITEBACK);
 					    &end, EXTENT_WRITEBACK);
 		if (ret) {
 		if (ret) {
-			if (skipped && all && !num_inserts) {
+			if (skipped && all && !num_inserts &&
+			    list_empty(&update_list)) {
 				skipped = 0;
 				skipped = 0;
 				search = 0;
 				search = 0;
 				continue;
 				continue;
@@ -2547,6 +2622,7 @@ again:
 		if (ret) {
 		if (ret) {
 			if (all && skipped && !nr) {
 			if (all && skipped && !nr) {
 				search = 0;
 				search = 0;
+				skipped = 0;
 				continue;
 				continue;
 			}
 			}
 			mutex_unlock(&info->extent_ins_mutex);
 			mutex_unlock(&info->extent_ins_mutex);
@@ -2700,13 +2776,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
 	/* if metadata always pin */
 	/* if metadata always pin */
 	if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID) {
 	if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID) {
 		if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
 		if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
-			struct btrfs_block_group_cache *cache;
-
-			/* btrfs_free_reserved_extent */
-			cache = btrfs_lookup_block_group(root->fs_info, bytenr);
-			BUG_ON(!cache);
-			btrfs_add_free_space(cache, bytenr, num_bytes);
-			put_block_group(cache);
+			mutex_lock(&root->fs_info->pinned_mutex);
+			btrfs_update_pinned_extents(root, bytenr, num_bytes, 1);
+			mutex_unlock(&root->fs_info->pinned_mutex);
 			update_reserved_extents(root, bytenr, num_bytes, 0);
 			update_reserved_extents(root, bytenr, num_bytes, 0);
 			return 0;
 			return 0;
 		}
 		}
@@ -3014,7 +3086,6 @@ loop_check:
 static void dump_space_info(struct btrfs_space_info *info, u64 bytes)
 static void dump_space_info(struct btrfs_space_info *info, u64 bytes)
 {
 {
 	struct btrfs_block_group_cache *cache;
 	struct btrfs_block_group_cache *cache;
-	struct list_head *l;
 
 
 	printk(KERN_INFO "space_info has %llu free, is %sfull\n",
 	printk(KERN_INFO "space_info has %llu free, is %sfull\n",
 	       (unsigned long long)(info->total_bytes - info->bytes_used -
 	       (unsigned long long)(info->total_bytes - info->bytes_used -
@@ -3022,8 +3093,7 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes)
 	       (info->full) ? "" : "not ");
 	       (info->full) ? "" : "not ");
 
 
 	down_read(&info->groups_sem);
 	down_read(&info->groups_sem);
-	list_for_each(l, &info->block_groups) {
-		cache = list_entry(l, struct btrfs_block_group_cache, list);
+	list_for_each_entry(cache, &info->block_groups, list) {
 		spin_lock(&cache->lock);
 		spin_lock(&cache->lock);
 		printk(KERN_INFO "block group %llu has %llu bytes, %llu used "
 		printk(KERN_INFO "block group %llu has %llu bytes, %llu used "
 		       "%llu pinned %llu reserved\n",
 		       "%llu pinned %llu reserved\n",
@@ -3342,7 +3412,10 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
 	btrfs_set_header_generation(buf, trans->transid);
 	btrfs_set_header_generation(buf, trans->transid);
 	btrfs_tree_lock(buf);
 	btrfs_tree_lock(buf);
 	clean_tree_block(trans, root, buf);
 	clean_tree_block(trans, root, buf);
+
+	btrfs_set_lock_blocking(buf);
 	btrfs_set_buffer_uptodate(buf);
 	btrfs_set_buffer_uptodate(buf);
+
 	if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
 	if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
 		set_extent_dirty(&root->dirty_log_pages, buf->start,
 		set_extent_dirty(&root->dirty_log_pages, buf->start,
 			 buf->start + buf->len - 1, GFP_NOFS);
 			 buf->start + buf->len - 1, GFP_NOFS);
@@ -3351,6 +3424,7 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
 			 buf->start + buf->len - 1, GFP_NOFS);
 			 buf->start + buf->len - 1, GFP_NOFS);
 	}
 	}
 	trans->blocks_used++;
 	trans->blocks_used++;
+	/* this returns a buffer locked for blocking */
 	return buf;
 	return buf;
 }
 }
 
 
@@ -3388,36 +3462,73 @@ int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
 {
 {
 	u64 leaf_owner;
 	u64 leaf_owner;
 	u64 leaf_generation;
 	u64 leaf_generation;
+	struct refsort *sorted;
 	struct btrfs_key key;
 	struct btrfs_key key;
 	struct btrfs_file_extent_item *fi;
 	struct btrfs_file_extent_item *fi;
 	int i;
 	int i;
 	int nritems;
 	int nritems;
 	int ret;
 	int ret;
+	int refi = 0;
+	int slot;
 
 
 	BUG_ON(!btrfs_is_leaf(leaf));
 	BUG_ON(!btrfs_is_leaf(leaf));
 	nritems = btrfs_header_nritems(leaf);
 	nritems = btrfs_header_nritems(leaf);
 	leaf_owner = btrfs_header_owner(leaf);
 	leaf_owner = btrfs_header_owner(leaf);
 	leaf_generation = btrfs_header_generation(leaf);
 	leaf_generation = btrfs_header_generation(leaf);
 
 
+	sorted = kmalloc(sizeof(*sorted) * nritems, GFP_NOFS);
+	/* we do this loop twice.  The first time we build a list
+	 * of the extents we have a reference on, then we sort the list
+	 * by bytenr.  The second time around we actually do the
+	 * extent freeing.
+	 */
 	for (i = 0; i < nritems; i++) {
 	for (i = 0; i < nritems; i++) {
 		u64 disk_bytenr;
 		u64 disk_bytenr;
 		cond_resched();
 		cond_resched();
 
 
 		btrfs_item_key_to_cpu(leaf, &key, i);
 		btrfs_item_key_to_cpu(leaf, &key, i);
+
+		/* only extents have references, skip everything else */
 		if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
 		if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
 			continue;
 			continue;
+
 		fi = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item);
 		fi = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item);
+
+		/* inline extents live in the btree, they don't have refs */
 		if (btrfs_file_extent_type(leaf, fi) ==
 		if (btrfs_file_extent_type(leaf, fi) ==
 		    BTRFS_FILE_EXTENT_INLINE)
 		    BTRFS_FILE_EXTENT_INLINE)
 			continue;
 			continue;
-		/*
-		 * FIXME make sure to insert a trans record that
-		 * repeats the snapshot del on crash
-		 */
+
 		disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
 		disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
+
+		/* holes don't have refs */
 		if (disk_bytenr == 0)
 		if (disk_bytenr == 0)
 			continue;
 			continue;
 
 
+		sorted[refi].bytenr = disk_bytenr;
+		sorted[refi].slot = i;
+		refi++;
+	}
+
+	if (refi == 0)
+		goto out;
+
+	sort(sorted, refi, sizeof(struct refsort), refsort_cmp, NULL);
+
+	for (i = 0; i < refi; i++) {
+		u64 disk_bytenr;
+
+		disk_bytenr = sorted[i].bytenr;
+		slot = sorted[i].slot;
+
+		cond_resched();
+
+		btrfs_item_key_to_cpu(leaf, &key, slot);
+		if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
+			continue;
+
+		fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
+
 		ret = __btrfs_free_extent(trans, root, disk_bytenr,
 		ret = __btrfs_free_extent(trans, root, disk_bytenr,
 				btrfs_file_extent_disk_num_bytes(leaf, fi),
 				btrfs_file_extent_disk_num_bytes(leaf, fi),
 				leaf->start, leaf_owner, leaf_generation,
 				leaf->start, leaf_owner, leaf_generation,
@@ -3428,6 +3539,8 @@ int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
 		wake_up(&root->fs_info->transaction_throttle);
 		wake_up(&root->fs_info->transaction_throttle);
 		cond_resched();
 		cond_resched();
 	}
 	}
+out:
+	kfree(sorted);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3437,9 +3550,25 @@ static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans,
 {
 {
 	int i;
 	int i;
 	int ret;
 	int ret;
-	struct btrfs_extent_info *info = ref->extents;
+	struct btrfs_extent_info *info;
+	struct refsort *sorted;
+
+	if (ref->nritems == 0)
+		return 0;
 
 
+	sorted = kmalloc(sizeof(*sorted) * ref->nritems, GFP_NOFS);
 	for (i = 0; i < ref->nritems; i++) {
 	for (i = 0; i < ref->nritems; i++) {
+		sorted[i].bytenr = ref->extents[i].bytenr;
+		sorted[i].slot = i;
+	}
+	sort(sorted, ref->nritems, sizeof(struct refsort), refsort_cmp, NULL);
+
+	/*
+	 * the items in the ref were sorted when the ref was inserted
+	 * into the ref cache, so this is already in order
+	 */
+	for (i = 0; i < ref->nritems; i++) {
+		info = ref->extents + sorted[i].slot;
 		ret = __btrfs_free_extent(trans, root, info->bytenr,
 		ret = __btrfs_free_extent(trans, root, info->bytenr,
 					  info->num_bytes, ref->bytenr,
 					  info->num_bytes, ref->bytenr,
 					  ref->owner, ref->generation,
 					  ref->owner, ref->generation,
@@ -3453,6 +3582,7 @@ static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans,
 		info++;
 		info++;
 	}
 	}
 
 
+	kfree(sorted);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3496,6 +3626,152 @@ static int drop_snap_lookup_refcount(struct btrfs_root *root, u64 start,
 	return ret;
 	return ret;
 }
 }
 
 
+/*
+ * this is used while deleting old snapshots, and it drops the refs
+ * on a whole subtree starting from a level 1 node.
+ *
+ * The idea is to sort all the leaf pointers, and then drop the
+ * ref on all the leaves in order.  Most of the time the leaves
+ * will have ref cache entries, so no leaf IOs will be required to
+ * find the extents they have references on.
+ *
+ * For each leaf, any references it has are also dropped in order
+ *
+ * This ends up dropping the references in something close to optimal
+ * order for reading and modifying the extent allocation tree.
+ */
+static noinline int drop_level_one_refs(struct btrfs_trans_handle *trans,
+					struct btrfs_root *root,
+					struct btrfs_path *path)
+{
+	u64 bytenr;
+	u64 root_owner;
+	u64 root_gen;
+	struct extent_buffer *eb = path->nodes[1];
+	struct extent_buffer *leaf;
+	struct btrfs_leaf_ref *ref;
+	struct refsort *sorted = NULL;
+	int nritems = btrfs_header_nritems(eb);
+	int ret;
+	int i;
+	int refi = 0;
+	int slot = path->slots[1];
+	u32 blocksize = btrfs_level_size(root, 0);
+	u32 refs;
+
+	if (nritems == 0)
+		goto out;
+
+	root_owner = btrfs_header_owner(eb);
+	root_gen = btrfs_header_generation(eb);
+	sorted = kmalloc(sizeof(*sorted) * nritems, GFP_NOFS);
+
+	/*
+	 * step one, sort all the leaf pointers so we don't scribble
+	 * randomly into the extent allocation tree
+	 */
+	for (i = slot; i < nritems; i++) {
+		sorted[refi].bytenr = btrfs_node_blockptr(eb, i);
+		sorted[refi].slot = i;
+		refi++;
+	}
+
+	/*
+	 * nritems won't be zero, but if we're picking up drop_snapshot
+	 * after a crash, slot might be > 0, so double check things
+	 * just in case.
+	 */
+	if (refi == 0)
+		goto out;
+
+	sort(sorted, refi, sizeof(struct refsort), refsort_cmp, NULL);
+
+	/*
+	 * the first loop frees everything the leaves point to
+	 */
+	for (i = 0; i < refi; i++) {
+		u64 ptr_gen;
+
+		bytenr = sorted[i].bytenr;
+
+		/*
+		 * check the reference count on this leaf.  If it is > 1
+		 * we just decrement it below and don't update any
+		 * of the refs the leaf points to.
+		 */
+		ret = drop_snap_lookup_refcount(root, bytenr, blocksize, &refs);
+		BUG_ON(ret);
+		if (refs != 1)
+			continue;
+
+		ptr_gen = btrfs_node_ptr_generation(eb, sorted[i].slot);
+
+		/*
+		 * the leaf only had one reference, which means the
+		 * only thing pointing to this leaf is the snapshot
+		 * we're deleting.  It isn't possible for the reference
+		 * count to increase again later
+		 *
+		 * The reference cache is checked for the leaf,
+		 * and if found we'll be able to drop any refs held by
+		 * the leaf without needing to read it in.
+		 */
+		ref = btrfs_lookup_leaf_ref(root, bytenr);
+		if (ref && ref->generation != ptr_gen) {
+			btrfs_free_leaf_ref(root, ref);
+			ref = NULL;
+		}
+		if (ref) {
+			ret = cache_drop_leaf_ref(trans, root, ref);
+			BUG_ON(ret);
+			btrfs_remove_leaf_ref(root, ref);
+			btrfs_free_leaf_ref(root, ref);
+		} else {
+			/*
+			 * the leaf wasn't in the reference cache, so
+			 * we have to read it.
+			 */
+			leaf = read_tree_block(root, bytenr, blocksize,
+					       ptr_gen);
+			ret = btrfs_drop_leaf_ref(trans, root, leaf);
+			BUG_ON(ret);
+			free_extent_buffer(leaf);
+		}
+		atomic_inc(&root->fs_info->throttle_gen);
+		wake_up(&root->fs_info->transaction_throttle);
+		cond_resched();
+	}
+
+	/*
+	 * run through the loop again to free the refs on the leaves.
+	 * This is faster than doing it in the loop above because
+	 * the leaves are likely to be clustered together.  We end up
+	 * working in nice chunks on the extent allocation tree.
+	 */
+	for (i = 0; i < refi; i++) {
+		bytenr = sorted[i].bytenr;
+		ret = __btrfs_free_extent(trans, root, bytenr,
+					blocksize, eb->start,
+					root_owner, root_gen, 0, 1);
+		BUG_ON(ret);
+
+		atomic_inc(&root->fs_info->throttle_gen);
+		wake_up(&root->fs_info->transaction_throttle);
+		cond_resched();
+	}
+out:
+	kfree(sorted);
+
+	/*
+	 * update the path to show we've processed the entire level 1
+	 * node.  This will get saved into the root's drop_snapshot_progress
+	 * field so these drops are not repeated again if this transaction
+	 * commits.
+	 */
+	path->slots[1] = nritems;
+	return 0;
+}
+
 /*
 /*
  * helper function for drop_snapshot, this walks down the tree dropping ref
  * helper function for drop_snapshot, this walks down the tree dropping ref
  * counts as it goes.
  * counts as it goes.
@@ -3511,7 +3787,6 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
 	struct extent_buffer *next;
 	struct extent_buffer *next;
 	struct extent_buffer *cur;
 	struct extent_buffer *cur;
 	struct extent_buffer *parent;
 	struct extent_buffer *parent;
-	struct btrfs_leaf_ref *ref;
 	u32 blocksize;
 	u32 blocksize;
 	int ret;
 	int ret;
 	u32 refs;
 	u32 refs;
@@ -3538,17 +3813,46 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
 		if (path->slots[*level] >=
 		if (path->slots[*level] >=
 		    btrfs_header_nritems(cur))
 		    btrfs_header_nritems(cur))
 			break;
 			break;
+
+		/* the new code goes down to level 1 and does all the
+		 * leaves pointed to that node in bulk.  So, this check
+		 * for level 0 will always be false.
+		 *
+		 * But, the disk format allows the drop_snapshot_progress
+		 * field in the root to leave things in a state where
+		 * a leaf will need cleaning up here.  If someone crashes
+		 * with the old code and then boots with the new code,
+		 * we might find a leaf here.
+		 */
 		if (*level == 0) {
 		if (*level == 0) {
 			ret = btrfs_drop_leaf_ref(trans, root, cur);
 			ret = btrfs_drop_leaf_ref(trans, root, cur);
 			BUG_ON(ret);
 			BUG_ON(ret);
 			break;
 			break;
 		}
 		}
+
+		/*
+		 * once we get to level one, process the whole node
+		 * at once, including everything below it.
+		 */
+		if (*level == 1) {
+			ret = drop_level_one_refs(trans, root, path);
+			BUG_ON(ret);
+			break;
+		}
+
 		bytenr = btrfs_node_blockptr(cur, path->slots[*level]);
 		bytenr = btrfs_node_blockptr(cur, path->slots[*level]);
 		ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]);
 		ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]);
 		blocksize = btrfs_level_size(root, *level - 1);
 		blocksize = btrfs_level_size(root, *level - 1);
 
 
 		ret = drop_snap_lookup_refcount(root, bytenr, blocksize, &refs);
 		ret = drop_snap_lookup_refcount(root, bytenr, blocksize, &refs);
 		BUG_ON(ret);
 		BUG_ON(ret);
+
+		/*
+		 * if there is more than one reference, we don't need
+		 * to read that node to drop any references it has.  We
+		 * just drop the ref we hold on that node and move on to the
+		 * next slot in this level.
+		 */
 		if (refs != 1) {
 		if (refs != 1) {
 			parent = path->nodes[*level];
 			parent = path->nodes[*level];
 			root_owner = btrfs_header_owner(parent);
 			root_owner = btrfs_header_owner(parent);
@@ -3567,46 +3871,12 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
 
 
 			continue;
 			continue;
 		}
 		}
+
 		/*
 		/*
-		 * at this point, we have a single ref, and since the
-		 * only place referencing this extent is a dead root
-		 * the reference count should never go higher.
-		 * So, we don't need to check it again
+		 * we need to keep freeing things in the next level down.
+		 * read the block and loop around to process it
 		 */
 		 */
-		if (*level == 1) {
-			ref = btrfs_lookup_leaf_ref(root, bytenr);
-			if (ref && ref->generation != ptr_gen) {
-				btrfs_free_leaf_ref(root, ref);
-				ref = NULL;
-			}
-			if (ref) {
-				ret = cache_drop_leaf_ref(trans, root, ref);
-				BUG_ON(ret);
-				btrfs_remove_leaf_ref(root, ref);
-				btrfs_free_leaf_ref(root, ref);
-				*level = 0;
-				break;
-			}
-		}
-		next = btrfs_find_tree_block(root, bytenr, blocksize);
-		if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) {
-			free_extent_buffer(next);
-
-			next = read_tree_block(root, bytenr, blocksize,
-					       ptr_gen);
-			cond_resched();
-#if 0
-			/*
-			 * this is a debugging check and can go away
-			 * the ref should never go all the way down to 1
-			 * at this point
-			 */
-			ret = lookup_extent_ref(NULL, root, bytenr, blocksize,
-						&refs);
-			BUG_ON(ret);
-			WARN_ON(refs != 1);
-#endif
-		}
+		next = read_tree_block(root, bytenr, blocksize, ptr_gen);
 		WARN_ON(*level <= 0);
 		WARN_ON(*level <= 0);
 		if (path->nodes[*level-1])
 		if (path->nodes[*level-1])
 			free_extent_buffer(path->nodes[*level-1]);
 			free_extent_buffer(path->nodes[*level-1]);
@@ -3631,11 +3901,16 @@ out:
 	root_owner = btrfs_header_owner(parent);
 	root_owner = btrfs_header_owner(parent);
 	root_gen = btrfs_header_generation(parent);
 	root_gen = btrfs_header_generation(parent);
 
 
+	/*
+	 * cleanup and free the reference on the last node
+	 * we processed
+	 */
 	ret = __btrfs_free_extent(trans, root, bytenr, blocksize,
 	ret = __btrfs_free_extent(trans, root, bytenr, blocksize,
 				  parent->start, root_owner, root_gen,
 				  parent->start, root_owner, root_gen,
 				  *level, 1);
 				  *level, 1);
 	free_extent_buffer(path->nodes[*level]);
 	free_extent_buffer(path->nodes[*level]);
 	path->nodes[*level] = NULL;
 	path->nodes[*level] = NULL;
+
 	*level += 1;
 	*level += 1;
 	BUG_ON(ret);
 	BUG_ON(ret);
 
 
@@ -3687,6 +3962,7 @@ static noinline int walk_down_subtree(struct btrfs_trans_handle *trans,
 
 
 		next = read_tree_block(root, bytenr, blocksize, ptr_gen);
 		next = read_tree_block(root, bytenr, blocksize, ptr_gen);
 		btrfs_tree_lock(next);
 		btrfs_tree_lock(next);
+		btrfs_set_lock_blocking(next);
 
 
 		ret = btrfs_lookup_extent_ref(trans, root, bytenr, blocksize,
 		ret = btrfs_lookup_extent_ref(trans, root, bytenr, blocksize,
 					      &refs);
 					      &refs);
@@ -3754,6 +4030,13 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
 		if (slot < btrfs_header_nritems(path->nodes[i]) - 1) {
 		if (slot < btrfs_header_nritems(path->nodes[i]) - 1) {
 			struct extent_buffer *node;
 			struct extent_buffer *node;
 			struct btrfs_disk_key disk_key;
 			struct btrfs_disk_key disk_key;
+
+			/*
+			 * there is more work to do in this level.
+			 * Update the drop_progress marker to reflect
+			 * the work we've done so far, and then bump
+			 * the slot number
+			 */
 			node = path->nodes[i];
 			node = path->nodes[i];
 			path->slots[i]++;
 			path->slots[i]++;
 			*level = i;
 			*level = i;
@@ -3765,6 +4048,11 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
 			return 0;
 			return 0;
 		} else {
 		} else {
 			struct extent_buffer *parent;
 			struct extent_buffer *parent;
+
+			/*
+			 * this whole node is done, free our reference
+			 * on it and go up one level
+			 */
 			if (path->nodes[*level] == root->node)
 			if (path->nodes[*level] == root->node)
 				parent = path->nodes[*level];
 				parent = path->nodes[*level];
 			else
 			else
@@ -4444,7 +4732,7 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans,
 	u64 lock_end = 0;
 	u64 lock_end = 0;
 	u64 num_bytes;
 	u64 num_bytes;
 	u64 ext_offset;
 	u64 ext_offset;
-	u64 first_pos;
+	u64 search_end = (u64)-1;
 	u32 nritems;
 	u32 nritems;
 	int nr_scaned = 0;
 	int nr_scaned = 0;
 	int extent_locked = 0;
 	int extent_locked = 0;
@@ -4452,7 +4740,6 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans,
 	int ret;
 	int ret;
 
 
 	memcpy(&key, leaf_key, sizeof(key));
 	memcpy(&key, leaf_key, sizeof(key));
-	first_pos = INT_LIMIT(loff_t) - extent_key->offset;
 	if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS) {
 	if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS) {
 		if (key.objectid < ref_path->owner_objectid ||
 		if (key.objectid < ref_path->owner_objectid ||
 		    (key.objectid == ref_path->owner_objectid &&
 		    (key.objectid == ref_path->owner_objectid &&
@@ -4501,7 +4788,7 @@ next:
 			if ((key.objectid > ref_path->owner_objectid) ||
 			if ((key.objectid > ref_path->owner_objectid) ||
 			    (key.objectid == ref_path->owner_objectid &&
 			    (key.objectid == ref_path->owner_objectid &&
 			     key.type > BTRFS_EXTENT_DATA_KEY) ||
 			     key.type > BTRFS_EXTENT_DATA_KEY) ||
-			    (key.offset >= first_pos + extent_key->offset))
+			    key.offset >= search_end)
 				break;
 				break;
 		}
 		}
 
 
@@ -4534,8 +4821,10 @@ next:
 		num_bytes = btrfs_file_extent_num_bytes(leaf, fi);
 		num_bytes = btrfs_file_extent_num_bytes(leaf, fi);
 		ext_offset = btrfs_file_extent_offset(leaf, fi);
 		ext_offset = btrfs_file_extent_offset(leaf, fi);
 
 
-		if (first_pos > key.offset - ext_offset)
-			first_pos = key.offset - ext_offset;
+		if (search_end == (u64)-1) {
+			search_end = key.offset - ext_offset +
+				btrfs_file_extent_ram_bytes(leaf, fi);
+		}
 
 
 		if (!extent_locked) {
 		if (!extent_locked) {
 			lock_start = key.offset;
 			lock_start = key.offset;
@@ -4724,7 +5013,7 @@ next:
 		}
 		}
 skip:
 skip:
 		if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS &&
 		if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS &&
-		    key.offset >= first_pos + extent_key->offset)
+		    key.offset >= search_end)
 			break;
 			break;
 
 
 		cond_resched();
 		cond_resched();
@@ -4778,6 +5067,7 @@ int btrfs_reloc_tree_cache_ref(struct btrfs_trans_handle *trans,
 		ref->bytenr = buf->start;
 		ref->bytenr = buf->start;
 		ref->owner = btrfs_header_owner(buf);
 		ref->owner = btrfs_header_owner(buf);
 		ref->generation = btrfs_header_generation(buf);
 		ref->generation = btrfs_header_generation(buf);
+
 		ret = btrfs_add_leaf_ref(root, ref, 0);
 		ret = btrfs_add_leaf_ref(root, ref, 0);
 		WARN_ON(ret);
 		WARN_ON(ret);
 		btrfs_free_leaf_ref(root, ref);
 		btrfs_free_leaf_ref(root, ref);
@@ -5957,9 +6247,11 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
 	BUG_ON(!path);
 	BUG_ON(!path);
 
 
-	btrfs_remove_free_space_cache(block_group);
+	spin_lock(&root->fs_info->block_group_cache_lock);
 	rb_erase(&block_group->cache_node,
 	rb_erase(&block_group->cache_node,
 		 &root->fs_info->block_group_cache_tree);
 		 &root->fs_info->block_group_cache_tree);
+	spin_unlock(&root->fs_info->block_group_cache_lock);
+	btrfs_remove_free_space_cache(block_group);
 	down_write(&block_group->space_info->groups_sem);
 	down_write(&block_group->space_info->groups_sem);
 	list_del(&block_group->list);
 	list_del(&block_group->list);
 	up_write(&block_group->space_info->groups_sem);
 	up_write(&block_group->space_info->groups_sem);

+ 109 - 23
fs/btrfs/extent_io.c

@@ -9,7 +9,6 @@
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
 #include <linux/blkdev.h>
 #include <linux/swap.h>
 #include <linux/swap.h>
-#include <linux/version.h>
 #include <linux/writeback.h>
 #include <linux/writeback.h>
 #include <linux/pagevec.h>
 #include <linux/pagevec.h>
 #include "extent_io.h"
 #include "extent_io.h"
@@ -31,7 +30,7 @@ static LIST_HEAD(buffers);
 static LIST_HEAD(states);
 static LIST_HEAD(states);
 
 
 #define LEAK_DEBUG 0
 #define LEAK_DEBUG 0
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
 static DEFINE_SPINLOCK(leak_lock);
 static DEFINE_SPINLOCK(leak_lock);
 #endif
 #endif
 
 
@@ -120,7 +119,7 @@ void extent_io_tree_init(struct extent_io_tree *tree,
 static struct extent_state *alloc_extent_state(gfp_t mask)
 static struct extent_state *alloc_extent_state(gfp_t mask)
 {
 {
 	struct extent_state *state;
 	struct extent_state *state;
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
 	unsigned long flags;
 	unsigned long flags;
 #endif
 #endif
 
 
@@ -130,7 +129,7 @@ static struct extent_state *alloc_extent_state(gfp_t mask)
 	state->state = 0;
 	state->state = 0;
 	state->private = 0;
 	state->private = 0;
 	state->tree = NULL;
 	state->tree = NULL;
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
 	spin_lock_irqsave(&leak_lock, flags);
 	spin_lock_irqsave(&leak_lock, flags);
 	list_add(&state->leak_list, &states);
 	list_add(&state->leak_list, &states);
 	spin_unlock_irqrestore(&leak_lock, flags);
 	spin_unlock_irqrestore(&leak_lock, flags);
@@ -145,11 +144,11 @@ static void free_extent_state(struct extent_state *state)
 	if (!state)
 	if (!state)
 		return;
 		return;
 	if (atomic_dec_and_test(&state->refs)) {
 	if (atomic_dec_and_test(&state->refs)) {
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
 		unsigned long flags;
 		unsigned long flags;
 #endif
 #endif
 		WARN_ON(state->tree);
 		WARN_ON(state->tree);
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
 		spin_lock_irqsave(&leak_lock, flags);
 		spin_lock_irqsave(&leak_lock, flags);
 		list_del(&state->leak_list);
 		list_del(&state->leak_list);
 		spin_unlock_irqrestore(&leak_lock, flags);
 		spin_unlock_irqrestore(&leak_lock, flags);
@@ -2378,11 +2377,6 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,
 	int scanned = 0;
 	int scanned = 0;
 	int range_whole = 0;
 	int range_whole = 0;
 
 
-	if (wbc->nonblocking && bdi_write_congested(bdi)) {
-		wbc->encountered_congestion = 1;
-		return 0;
-	}
-
 	pagevec_init(&pvec, 0);
 	pagevec_init(&pvec, 0);
 	if (wbc->range_cyclic) {
 	if (wbc->range_cyclic) {
 		index = mapping->writeback_index; /* Start from prev offset */
 		index = mapping->writeback_index; /* Start from prev offset */
@@ -2855,6 +2849,98 @@ out:
 	return sector;
 	return sector;
 }
 }
 
 
+int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+		__u64 start, __u64 len, get_extent_t *get_extent)
+{
+	int ret;
+	u64 off = start;
+	u64 max = start + len;
+	u32 flags = 0;
+	u64 disko = 0;
+	struct extent_map *em = NULL;
+	int end = 0;
+	u64 em_start = 0, em_len = 0;
+	unsigned long emflags;
+	ret = 0;
+
+	if (len == 0)
+		return -EINVAL;
+
+	lock_extent(&BTRFS_I(inode)->io_tree, start, start + len,
+		GFP_NOFS);
+	em = get_extent(inode, NULL, 0, off, max - off, 0);
+	if (!em)
+		goto out;
+	if (IS_ERR(em)) {
+		ret = PTR_ERR(em);
+		goto out;
+	}
+	while (!end) {
+		off = em->start + em->len;
+		if (off >= max)
+			end = 1;
+
+		em_start = em->start;
+		em_len = em->len;
+
+		disko = 0;
+		flags = 0;
+
+		switch (em->block_start) {
+		case EXTENT_MAP_LAST_BYTE:
+			end = 1;
+			flags |= FIEMAP_EXTENT_LAST;
+			break;
+		case EXTENT_MAP_HOLE:
+			flags |= FIEMAP_EXTENT_UNWRITTEN;
+			break;
+		case EXTENT_MAP_INLINE:
+			flags |= (FIEMAP_EXTENT_DATA_INLINE |
+				  FIEMAP_EXTENT_NOT_ALIGNED);
+			break;
+		case EXTENT_MAP_DELALLOC:
+			flags |= (FIEMAP_EXTENT_DELALLOC |
+				  FIEMAP_EXTENT_UNKNOWN);
+			break;
+		default:
+			disko = em->block_start;
+			break;
+		}
+		if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags))
+			flags |= FIEMAP_EXTENT_ENCODED;
+
+		emflags = em->flags;
+		free_extent_map(em);
+		em = NULL;
+
+		if (!end) {
+			em = get_extent(inode, NULL, 0, off, max - off, 0);
+			if (!em)
+				goto out;
+			if (IS_ERR(em)) {
+				ret = PTR_ERR(em);
+				goto out;
+			}
+			emflags = em->flags;
+		}
+		if (test_bit(EXTENT_FLAG_VACANCY, &emflags)) {
+			flags |= FIEMAP_EXTENT_LAST;
+			end = 1;
+		}
+
+		ret = fiemap_fill_next_extent(fieinfo, em_start, disko,
+					em_len, flags);
+		if (ret)
+			goto out_free;
+	}
+out_free:
+	free_extent_map(em);
+out:
+	unlock_extent(&BTRFS_I(inode)->io_tree, start, start + len,
+			GFP_NOFS);
+	return ret;
+}
+
 static inline struct page *extent_buffer_page(struct extent_buffer *eb,
 static inline struct page *extent_buffer_page(struct extent_buffer *eb,
 					      unsigned long i)
 					      unsigned long i)
 {
 {
@@ -2892,15 +2978,17 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
 						   gfp_t mask)
 						   gfp_t mask)
 {
 {
 	struct extent_buffer *eb = NULL;
 	struct extent_buffer *eb = NULL;
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
 	unsigned long flags;
 	unsigned long flags;
 #endif
 #endif
 
 
 	eb = kmem_cache_zalloc(extent_buffer_cache, mask);
 	eb = kmem_cache_zalloc(extent_buffer_cache, mask);
 	eb->start = start;
 	eb->start = start;
 	eb->len = len;
 	eb->len = len;
-	mutex_init(&eb->mutex);
-#ifdef LEAK_DEBUG
+	spin_lock_init(&eb->lock);
+	init_waitqueue_head(&eb->lock_wq);
+
+#if LEAK_DEBUG
 	spin_lock_irqsave(&leak_lock, flags);
 	spin_lock_irqsave(&leak_lock, flags);
 	list_add(&eb->leak_list, &buffers);
 	list_add(&eb->leak_list, &buffers);
 	spin_unlock_irqrestore(&leak_lock, flags);
 	spin_unlock_irqrestore(&leak_lock, flags);
@@ -2912,7 +3000,7 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
 
 
 static void __free_extent_buffer(struct extent_buffer *eb)
 static void __free_extent_buffer(struct extent_buffer *eb)
 {
 {
-#ifdef LEAK_DEBUG
+#if LEAK_DEBUG
 	unsigned long flags;
 	unsigned long flags;
 	spin_lock_irqsave(&leak_lock, flags);
 	spin_lock_irqsave(&leak_lock, flags);
 	list_del(&eb->leak_list);
 	list_del(&eb->leak_list);
@@ -2980,8 +3068,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,
 		unlock_page(p);
 		unlock_page(p);
 	}
 	}
 	if (uptodate)
 	if (uptodate)
-		eb->flags |= EXTENT_UPTODATE;
-	eb->flags |= EXTENT_BUFFER_FILLED;
+		set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
 
 
 	spin_lock(&tree->buffer_lock);
 	spin_lock(&tree->buffer_lock);
 	exists = buffer_tree_insert(tree, start, &eb->rb_node);
 	exists = buffer_tree_insert(tree, start, &eb->rb_node);
@@ -3135,7 +3222,7 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
 	unsigned long num_pages;
 	unsigned long num_pages;
 
 
 	num_pages = num_extent_pages(eb->start, eb->len);
 	num_pages = num_extent_pages(eb->start, eb->len);
-	eb->flags &= ~EXTENT_UPTODATE;
+	clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
 
 
 	clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
 	clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
 			      GFP_NOFS);
 			      GFP_NOFS);
@@ -3206,7 +3293,7 @@ int extent_buffer_uptodate(struct extent_io_tree *tree,
 	struct page *page;
 	struct page *page;
 	int pg_uptodate = 1;
 	int pg_uptodate = 1;
 
 
-	if (eb->flags & EXTENT_UPTODATE)
+	if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
 		return 1;
 		return 1;
 
 
 	ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1,
 	ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1,
@@ -3242,7 +3329,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
 	struct bio *bio = NULL;
 	struct bio *bio = NULL;
 	unsigned long bio_flags = 0;
 	unsigned long bio_flags = 0;
 
 
-	if (eb->flags & EXTENT_UPTODATE)
+	if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
 		return 0;
 		return 0;
 
 
 	if (test_range_bit(tree, eb->start, eb->start + eb->len - 1,
 	if (test_range_bit(tree, eb->start, eb->start + eb->len - 1,
@@ -3273,7 +3360,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
 	}
 	}
 	if (all_uptodate) {
 	if (all_uptodate) {
 		if (start_i == 0)
 		if (start_i == 0)
-			eb->flags |= EXTENT_UPTODATE;
+			set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
 		goto unlock_exit;
 		goto unlock_exit;
 	}
 	}
 
 
@@ -3309,7 +3396,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
 	}
 	}
 
 
 	if (!ret)
 	if (!ret)
-		eb->flags |= EXTENT_UPTODATE;
+		set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
 	return ret;
 	return ret;
 
 
 unlock_exit:
 unlock_exit:
@@ -3406,7 +3493,6 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
 		unmap_extent_buffer(eb, eb->map_token, km);
 		unmap_extent_buffer(eb, eb->map_token, km);
 		eb->map_token = NULL;
 		eb->map_token = NULL;
 		save = 1;
 		save = 1;
-		WARN_ON(!mutex_is_locked(&eb->mutex));
 	}
 	}
 	err = map_private_extent_buffer(eb, start, min_len, token, map,
 	err = map_private_extent_buffer(eb, start, min_len, token, map,
 				       map_start, map_len, km);
 				       map_start, map_len, km);

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä