Merge commit 'v2.6.29-rc4' into tracing/core
This commit is contained in:
		
				commit
				
					
						4ad476e11f
					
				
			
		
					 162 changed files with 3103 additions and 2049 deletions
				
			
		
							
								
								
									
										4
									
								
								.mailmap
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								.mailmap
									
										
									
									
									
								
							|  | @ -92,6 +92,7 @@ Rudolf Marek <R.Marek@sh.cvut.cz> | |||
| Rui Saraiva <rmps@joel.ist.utl.pt> | ||||
| Sachin P Sant <ssant@in.ibm.com> | ||||
| Sam Ravnborg <sam@mars.ravnborg.org> | ||||
| Sascha Hauer <s.hauer@pengutronix.de> | ||||
| S.Çağlar Onur <caglar@pardus.org.tr> | ||||
| Simon Kelley <simon@thekelleys.org.uk> | ||||
| Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr> | ||||
|  | @ -100,6 +101,7 @@ Tejun Heo <htejun@gmail.com> | |||
| Thomas Graf <tgraf@suug.ch> | ||||
| Tony Luck <tony.luck@intel.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 <ukl@pengutronix.de> | ||||
| Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com> | ||||
| Valdis Kletnieks <Valdis.Kletnieks@vt.edu> | ||||
|  |  | |||
|  | @ -195,19 +195,3 @@ scaling_setspeed.		By "echoing" a new frequency into this | |||
| 				you can change the speed of the CPU, | ||||
| 				but only within the limits of | ||||
| 				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. | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ that support it.  For example, a given bus might look like this: | |||
|      |   |-- class | ||||
|      |   |-- config | ||||
|      |   |-- device | ||||
|      |   |-- enable | ||||
|      |   |-- irq | ||||
|      |   |-- local_cpus | ||||
|      |   |-- resource | ||||
|  | @ -32,6 +33,7 @@ files, each with their own function. | |||
|        class		   PCI class (ascii, ro) | ||||
|        config		   PCI config space (binary, rw) | ||||
|        device		   PCI device (ascii, ro) | ||||
|        enable	           Whether the device is enabled (ascii, rw) | ||||
|        irq		   IRQ number (ascii, ro) | ||||
|        local_cpus	   nearby CPU mask (cpumask, 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 | ||||
| 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 | ||||
| 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 | ||||
| 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 | ||||
| ---------------------------------------- | ||||
|  |  | |||
							
								
								
									
										11
									
								
								MAINTAINERS
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								MAINTAINERS
									
										
									
									
									
								
							|  | @ -1021,6 +1021,14 @@ M:	mb@bu3sch.de | |||
| W:	http://bu3sch.de/btgpio.php | ||||
| 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 | ||||
| P:	Mauro Carvalho Chehab | ||||
| M:	mchehab@infradead.org | ||||
|  | @ -2212,7 +2220,7 @@ P:	Sean Hefty | |||
| M:	sean.hefty@intel.com | ||||
| P:	Hal Rosenstock | ||||
| M:	hal.rosenstock@gmail.com | ||||
| L:	general@lists.openfabrics.org | ||||
| L:	general@lists.openfabrics.org (moderated for non-subscribers) | ||||
| W:	http://www.openib.org/ | ||||
| T:	git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git | ||||
| S:	Supported | ||||
|  | @ -4847,6 +4855,7 @@ P:	Ingo Molnar | |||
| M:	mingo@redhat.com | ||||
| P:	H. Peter Anvin | ||||
| M:	hpa@zytor.com | ||||
| M:	x86@kernel.org | ||||
| L:	linux-kernel@vger.kernel.org | ||||
| T:	git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git | ||||
| S:	Maintained | ||||
|  |  | |||
							
								
								
									
										2
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -1,7 +1,7 @@ | |||
| VERSION = 2 | ||||
| PATCHLEVEL = 6 | ||||
| SUBLEVEL = 29 | ||||
| EXTRAVERSION = -rc3 | ||||
| EXTRAVERSION = -rc4 | ||||
| NAME = Erotic Pickled Herring | ||||
| 
 | ||||
| # *DOCUMENTATION*
 | ||||
|  |  | |||
|  | @ -8,12 +8,12 @@ | |||
| 
 | ||||
| /* ??? 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.  */ | ||||
| #define BUG()	{							\ | ||||
| #define BUG()	do {							\ | ||||
| 	__asm__ __volatile__(						\ | ||||
| 		"call_pal %0  # bugchk\n\t"				\ | ||||
| 		".long %1\n\t.8byte %2"					\ | ||||
| 		: : "i"(PAL_bugchk), "i"(__LINE__), "i"(__FILE__));	\ | ||||
| 	for ( ; ; ); } | ||||
| 	for ( ; ; ); } while (0) | ||||
| 
 | ||||
| #define HAVE_ARCH_BUG | ||||
| #endif | ||||
|  |  | |||
|  | @ -443,7 +443,7 @@ sn_acpi_slot_fixup(struct pci_dev *dev) | |||
| 		size = pci_resource_len(dev, PCI_ROM_RESOURCE); | ||||
| 		addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE], | ||||
| 			       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].end = | ||||
| 					(unsigned long) addr + image_size - 1; | ||||
|  |  | |||
|  | @ -269,7 +269,7 @@ sn_io_slot_fixup(struct pci_dev *dev) | |||
| 
 | ||||
| 			rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE), | ||||
| 				      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].start + | ||||
| 				image_size - 1; | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ | |||
| #include <linux/gpio.h> | ||||
| #include <linux/spi/spi.h> | ||||
| #include <linux/spi/spi_gpio.h> | ||||
| #include <media/ov772x.h> | ||||
| #include <media/soc_camera_platform.h> | ||||
| #include <media/sh_mobile_ceu.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 | ||||
| /* support for the old ncm03j camera */ | ||||
| static unsigned char camera_ncm03j_magic[] = | ||||
| { | ||||
| 	0x87, 0x00, 0x88, 0x08, 0x89, 0x01, 0x8A, 0xE8, | ||||
|  | @ -237,6 +245,23 @@ static unsigned char camera_ncm03j_magic[] = | |||
| 	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, | ||||
| 			      int enable) | ||||
| { | ||||
|  | @ -245,9 +270,11 @@ static int camera_set_capture(struct soc_camera_platform_info *info, | |||
| 	int ret = 0; | ||||
| 	int i; | ||||
| 
 | ||||
| 	camera_power(0); | ||||
| 	if (!enable) | ||||
| 		return 0; /* no disable for now */ | ||||
| 
 | ||||
| 	camera_power(1); | ||||
| 	for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) { | ||||
| 		u_int8_t buf[8]; | ||||
| 
 | ||||
|  | @ -286,8 +313,35 @@ static struct platform_device camera_device = { | |||
| 		.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 */ | ||||
| 
 | ||||
| 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 = { | ||||
| 	.flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | | ||||
| 	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8, | ||||
|  | @ -338,9 +392,6 @@ static struct platform_device *ap325rxa_devices[] __initdata = { | |||
| 	&ap325rxa_nor_flash_device, | ||||
| 	&lcdc_device, | ||||
| 	&ceu_device, | ||||
| #ifdef CONFIG_I2C | ||||
| 	&camera_device, | ||||
| #endif | ||||
| 	&nand_flash_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("ov772x", 0x21), | ||||
| 		.platform_data = &ov7725_info, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| 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_direction_output(GPIO_PTZ6, 0); /* STBY_CAM */ | ||||
| 	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_direction_output(GPIO_PTZ4, 0); /* SADDR */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| # | ||||
| # 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_SUPERH32=y | ||||
|  | @ -45,12 +45,12 @@ CONFIG_BSD_PROCESS_ACCT=y | |||
| # CONFIG_AUDIT is not set | ||||
| # CONFIG_IKCONFIG is not set | ||||
| CONFIG_LOG_BUF_SHIFT=14 | ||||
| # CONFIG_CGROUPS is not set | ||||
| CONFIG_GROUP_SCHED=y | ||||
| CONFIG_FAIR_GROUP_SCHED=y | ||||
| # CONFIG_RT_GROUP_SCHED is not set | ||||
| CONFIG_USER_SCHED=y | ||||
| # CONFIG_CGROUP_SCHED is not set | ||||
| # CONFIG_CGROUPS is not set | ||||
| CONFIG_SYSFS_DEPRECATED=y | ||||
| CONFIG_SYSFS_DEPRECATED_V2=y | ||||
| # CONFIG_RELAY is not set | ||||
|  | @ -378,6 +378,7 @@ CONFIG_WIRELESS=y | |||
| # CONFIG_WIRELESS_EXT is not set | ||||
| # CONFIG_LIB80211 is not set | ||||
| # CONFIG_MAC80211 is not set | ||||
| # CONFIG_WIMAX is not set | ||||
| # CONFIG_RFKILL is not set | ||||
| # CONFIG_NET_9P is not set | ||||
| 
 | ||||
|  | @ -400,6 +401,7 @@ CONFIG_MTD=y | |||
| # CONFIG_MTD_DEBUG is not set | ||||
| CONFIG_MTD_CONCAT=y | ||||
| CONFIG_MTD_PARTITIONS=y | ||||
| # CONFIG_MTD_TESTS is not set | ||||
| # CONFIG_MTD_REDBOOT_PARTS is not set | ||||
| CONFIG_MTD_CMDLINE_PARTS=y | ||||
| # 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_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 | ||||
| 
 | ||||
| # | ||||
|  | @ -479,6 +479,12 @@ CONFIG_MTD_NAND_IDS=y | |||
| CONFIG_MTD_NAND_SH_FLCTL=y | ||||
| # 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 | ||||
| # | ||||
|  | @ -607,6 +613,10 @@ CONFIG_SMSC911X=y | |||
| # CONFIG_WLAN_PRE80211 is not set | ||||
| # CONFIG_WLAN_80211 is not set | ||||
| # CONFIG_IWLWIFI_LEDS is not set | ||||
| 
 | ||||
| # | ||||
| # Enable WiMAX (Networking options) to see the WiMAX drivers | ||||
| # | ||||
| # CONFIG_WAN is not set | ||||
| # CONFIG_PPP is not set | ||||
| # CONFIG_SLIP is not set | ||||
|  | @ -790,6 +800,7 @@ CONFIG_SSB_POSSIBLE=y | |||
| # CONFIG_PMIC_DA903X is not set | ||||
| # CONFIG_MFD_WM8400 is not set | ||||
| # CONFIG_MFD_WM8350_I2C is not set | ||||
| # CONFIG_MFD_PCF50633 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_TW9910 is not set | ||||
| CONFIG_SOC_CAMERA_PLATFORM=y | ||||
| # CONFIG_SOC_CAMERA_OV772X is not set | ||||
| CONFIG_SOC_CAMERA_OV772X=y | ||||
| CONFIG_VIDEO_SH_MOBILE_CEU=y | ||||
| # CONFIG_RADIO_ADAPTERS is not set | ||||
| # CONFIG_DAB is not set | ||||
|  | @ -1012,6 +1023,7 @@ CONFIG_FS_POSIX_ACL=y | |||
| CONFIG_FILE_LOCKING=y | ||||
| # CONFIG_XFS_FS is not set | ||||
| # CONFIG_OCFS2_FS is not set | ||||
| # CONFIG_BTRFS_FS is not set | ||||
| CONFIG_DNOTIFY=y | ||||
| CONFIG_INOTIFY=y | ||||
| CONFIG_INOTIFY_USER=y | ||||
|  | @ -1060,6 +1072,7 @@ CONFIG_MISC_FILESYSTEMS=y | |||
| # CONFIG_JFFS2_FS is not set | ||||
| # CONFIG_UBIFS_FS is not set | ||||
| # CONFIG_CRAMFS is not set | ||||
| # CONFIG_SQUASHFS is not set | ||||
| # CONFIG_VXFS_FS is not set | ||||
| # CONFIG_MINIX_FS is not set | ||||
| # CONFIG_OMFS_FS is not set | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| # | ||||
| # 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_SUPERH32=y | ||||
|  | @ -45,8 +45,12 @@ CONFIG_SYSVIPC_SYSCTL=y | |||
| CONFIG_IKCONFIG=y | ||||
| CONFIG_IKCONFIG_PROC=y | ||||
| CONFIG_LOG_BUF_SHIFT=14 | ||||
| # CONFIG_CGROUPS is not set | ||||
| # CONFIG_GROUP_SCHED is not set | ||||
| 
 | ||||
| # | ||||
| # Control Group support | ||||
| # | ||||
| # CONFIG_CGROUPS is not set | ||||
| CONFIG_SYSFS_DEPRECATED=y | ||||
| CONFIG_SYSFS_DEPRECATED_V2=y | ||||
| # CONFIG_RELAY is not set | ||||
|  | @ -389,6 +393,7 @@ CONFIG_WIRELESS_EXT=y | |||
| CONFIG_WIRELESS_EXT_SYSFS=y | ||||
| # CONFIG_LIB80211 is not set | ||||
| # CONFIG_MAC80211 is not set | ||||
| # CONFIG_WIMAX is not set | ||||
| # CONFIG_RFKILL is not set | ||||
| # CONFIG_NET_9P is not set | ||||
| 
 | ||||
|  | @ -411,6 +416,7 @@ CONFIG_MTD=y | |||
| # CONFIG_MTD_DEBUG is not set | ||||
| CONFIG_MTD_CONCAT=y | ||||
| CONFIG_MTD_PARTITIONS=y | ||||
| # CONFIG_MTD_TESTS is not set | ||||
| # CONFIG_MTD_REDBOOT_PARTS is not set | ||||
| CONFIG_MTD_CMDLINE_PARTS=y | ||||
| # 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_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 | ||||
| 
 | ||||
| # | ||||
|  | @ -487,6 +491,12 @@ CONFIG_MTD_NAND_IDS=y | |||
| CONFIG_MTD_NAND_PLATFORM=y | ||||
| # 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 | ||||
| # | ||||
|  | @ -587,6 +597,10 @@ CONFIG_SMC91X=y | |||
| # CONFIG_WLAN_PRE80211 is not set | ||||
| # CONFIG_WLAN_80211 is not set | ||||
| # CONFIG_IWLWIFI_LEDS is not set | ||||
| 
 | ||||
| # | ||||
| # Enable WiMAX (Networking options) to see the WiMAX drivers | ||||
| # | ||||
| # CONFIG_WAN is not set | ||||
| # CONFIG_PPP is not set | ||||
| # CONFIG_SLIP is not set | ||||
|  | @ -761,6 +775,7 @@ CONFIG_SSB_POSSIBLE=y | |||
| # CONFIG_PMIC_DA903X is not set | ||||
| # CONFIG_MFD_WM8400 is not set | ||||
| # CONFIG_MFD_WM8350_I2C is not set | ||||
| # CONFIG_MFD_PCF50633 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_MT9T031 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_RADIO_ADAPTERS 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_PXA27X is not set | ||||
| # CONFIG_USB_GADGET_S3C2410 is not set | ||||
| # CONFIG_USB_GADGET_IMX is not set | ||||
| CONFIG_USB_GADGET_M66592=y | ||||
| CONFIG_USB_M66592=y | ||||
| CONFIG_SUPERH_BUILT_IN_M66592=y | ||||
| # CONFIG_USB_GADGET_AMD5536UDC 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_GOKU 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_G_PRINTER 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_MEMSTICK is not set | ||||
| # CONFIG_NEW_LEDS is not set | ||||
|  | @ -961,6 +983,7 @@ CONFIG_UIO_PDRV_GENIRQ=y | |||
| CONFIG_FILE_LOCKING=y | ||||
| # CONFIG_XFS_FS is not set | ||||
| # CONFIG_OCFS2_FS is not set | ||||
| # CONFIG_BTRFS_FS is not set | ||||
| # CONFIG_DNOTIFY is not set | ||||
| # CONFIG_INOTIFY is not set | ||||
| # CONFIG_QUOTA is not set | ||||
|  | @ -1004,6 +1027,7 @@ CONFIG_MISC_FILESYSTEMS=y | |||
| # CONFIG_EFS_FS is not set | ||||
| # CONFIG_JFFS2_FS is not set | ||||
| # CONFIG_CRAMFS is not set | ||||
| # CONFIG_SQUASHFS is not set | ||||
| # CONFIG_VXFS_FS is not set | ||||
| # CONFIG_MINIX_FS is not set | ||||
| # CONFIG_OMFS_FS is not set | ||||
|  |  | |||
|  | @ -21,38 +21,36 @@ | |||
| static inline void | ||||
| __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) | ||||
| { | ||||
| 	int __ex_flag, __res; | ||||
| 	int __done, __res; | ||||
| 
 | ||||
| 	__asm__ __volatile__ ( | ||||
| 		"movli.l	@%2, %0	\n" | ||||
| 		"add		#-1, %0	\n" | ||||
| 		"movco.l	%0, @%2	\n" | ||||
| 		"movt		%1	\n" | ||||
| 		: "=&z" (__res), "=&r" (__ex_flag) | ||||
| 		: "=&z" (__res), "=&r" (__done) | ||||
| 		: "r" (&(count)->counter) | ||||
| 		: "t"); | ||||
| 
 | ||||
| 	__res |= !__ex_flag; | ||||
| 	if (unlikely(__res != 0)) | ||||
| 	if (unlikely(!__done || __res != 0)) | ||||
| 		fail_fn(count); | ||||
| } | ||||
| 
 | ||||
| static inline int | ||||
| __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) | ||||
| { | ||||
| 	int __ex_flag, __res; | ||||
| 	int __done, __res; | ||||
| 
 | ||||
| 	__asm__ __volatile__ ( | ||||
| 		"movli.l	@%2, %0	\n" | ||||
| 		"add		#-1, %0	\n" | ||||
| 		"movco.l	%0, @%2	\n" | ||||
| 		"movt		%1	\n" | ||||
| 		: "=&z" (__res), "=&r" (__ex_flag) | ||||
| 		: "=&z" (__res), "=&r" (__done) | ||||
| 		: "r" (&(count)->counter) | ||||
| 		: "t"); | ||||
| 
 | ||||
| 	__res |= !__ex_flag; | ||||
| 	if (unlikely(__res != 0)) | ||||
| 	if (unlikely(!__done || __res != 0)) | ||||
| 		__res = fail_fn(count); | ||||
| 
 | ||||
| 	return __res; | ||||
|  | @ -61,19 +59,18 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) | |||
| static inline void | ||||
| __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) | ||||
| { | ||||
| 	int __ex_flag, __res; | ||||
| 	int __done, __res; | ||||
| 
 | ||||
| 	__asm__ __volatile__ ( | ||||
| 		"movli.l	@%2, %0	\n\t" | ||||
| 		"add		#1, %0	\n\t" | ||||
| 		"movco.l	%0, @%2 \n\t" | ||||
| 		"movt		%1	\n\t" | ||||
| 		: "=&z" (__res), "=&r" (__ex_flag) | ||||
| 		: "=&z" (__res), "=&r" (__done) | ||||
| 		: "r" (&(count)->counter) | ||||
| 		: "t"); | ||||
| 
 | ||||
| 	__res |= !__ex_flag; | ||||
| 	if (unlikely(__res <= 0)) | ||||
| 	if (unlikely(!__done || __res <= 0)) | ||||
| 		fail_fn(count); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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, | ||||
| 				     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, | ||||
|  | @ -50,13 +37,10 @@ static inline void syscall_set_return_value(struct task_struct *task, | |||
| 					    struct pt_regs *regs, | ||||
| 					    int error, long val) | ||||
| { | ||||
| 	if (error) { | ||||
| 		syscall_set_error(regs); | ||||
| 	if (error) | ||||
| 		regs->regs[0] = -error; | ||||
| 	} else { | ||||
| 		syscall_clear_error(regs); | ||||
| 	else | ||||
| 		regs->regs[0] = val; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static inline void syscall_get_arguments(struct task_struct *task, | ||||
|  |  | |||
|  | @ -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, | ||||
| 				     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, | ||||
|  | @ -50,13 +37,10 @@ static inline void syscall_set_return_value(struct task_struct *task, | |||
| 					    struct pt_regs *regs, | ||||
| 					    int error, long val) | ||||
| { | ||||
| 	if (error) { | ||||
| 		syscall_set_error(regs); | ||||
| 	if (error) | ||||
| 		regs->regs[9] = -error; | ||||
| 	} else { | ||||
| 		syscall_clear_error(regs); | ||||
| 	else | ||||
| 		regs->regs[9] = val; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static inline void syscall_get_arguments(struct task_struct *task, | ||||
|  |  | |||
|  | @ -423,7 +423,7 @@ static int ieee_fpe_handler(struct pt_regs *regs) | |||
| 		int m; | ||||
| 		unsigned int hx; | ||||
| 
 | ||||
| 		m = (finsn >> 9) & 0x7; | ||||
| 		m = (finsn >> 8) & 0x7; | ||||
| 		hx = tsk->thread.fpu.hard.fp_regs[m]; | ||||
| 
 | ||||
| 		if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR) | ||||
|  |  | |||
|  | @ -262,11 +262,11 @@ void __init setup_bootmem_allocator(unsigned long free_pfn) | |||
| 			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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -510,7 +510,6 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs, | |||
| 		case -ERESTARTNOHAND: | ||||
| 		no_system_call_restart: | ||||
| 			regs->regs[0] = -EINTR; | ||||
| 			regs->sr |= 1; | ||||
| 			break; | ||||
| 
 | ||||
| 		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); | ||||
| 	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.  */ | ||||
| 		if (handle_signal(signr, &ka, &info, oldset, | ||||
|  |  | |||
|  | @ -60,7 +60,6 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) | |||
| 		case -ERESTARTNOHAND: | ||||
| 		no_system_call_restart: | ||||
| 			regs->regs[REG_RET] = -EINTR; | ||||
| 			regs->sr |= 1; | ||||
| 			break; | ||||
| 
 | ||||
| 		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); | ||||
| 	if (signr > 0) { | ||||
| 		if (regs->sr & 1) | ||||
| 			handle_syscall_restart(regs, &ka.sa); | ||||
| 		handle_syscall_restart(regs, &ka.sa); | ||||
| 
 | ||||
| 		/* Whee!  Actually deliver the signal.  */ | ||||
| 		if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | ||||
|  |  | |||
|  | @ -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 | ||||
|  | @ -49,11 +48,31 @@ ENTRY(csum_partial) | |||
| 	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte | ||||
| 	   * alignment for the unrolled loop. | ||||
| 	   */ | ||||
| 	mov	r5, r1 | ||||
| 	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. | ||||
| 	cmp/pz	r5		! | ||||
| 	bt/s	1f		! Jump if we had at least two bytes. | ||||
|  | @ -61,16 +80,17 @@ ENTRY(csum_partial) | |||
| 	bra	6f | ||||
| 	 add	#2, r5		! r5 was < 2.  Deal with it. | ||||
| 1: | ||||
| 	mov	r5, r1		! Save new len for later use. | ||||
| 	mov.w	@r4+, r0
 | ||||
| 	extu.w	r0, r0 | ||||
| 	addc	r0, r6 | ||||
| 	bf	2f | ||||
| 	add	#1, r6 | ||||
| 2: | ||||
| 	! buf is 4 byte aligned (len could be 0) | ||||
| 	mov	r5, r1 | ||||
| 	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 | ||||
| 	 clrt | ||||
| 	.align	2
 | ||||
|  | @ -92,30 +112,31 @@ ENTRY(csum_partial) | |||
| 	addc	r0, r6 | ||||
| 	addc	r2, r6 | ||||
| 	movt	r0 | ||||
| 	dt	r5 | ||||
| 	dt	r1 | ||||
| 	bf/s	3b | ||||
| 	 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: | ||||
| 	mov	r1, r0 | ||||
| 	mov	r5, r0 | ||||
| 	and	#0x1c, 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 | ||||
| 5: | ||||
| 	addc	r2, r6 | ||||
| 	mov.l	@r4+, r2
 | ||||
| 	movt	r0 | ||||
| 	dt	r5 | ||||
| 	dt	r1 | ||||
| 	bf/s	5b | ||||
| 	 cmp/eq	#1, r0 | ||||
| 	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: | ||||
| 	mov	r1, r5 | ||||
| 	! 3 bytes or less remaining | ||||
| 	mov	#3, r0 | ||||
| 	and	r0, r5 | ||||
| 	tst	r5, r5 | ||||
|  | @ -141,6 +162,16 @@ ENTRY(csum_partial) | |||
| 	mov	#0, r0 | ||||
| 	addc	r0, r6 | ||||
| 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 | ||||
| 	 mov	r6, r0 | ||||
| 
 | ||||
|  |  | |||
|  | @ -418,9 +418,9 @@ ENTRY(ia32_syscall) | |||
| 	orl   $TS_COMPAT,TI_status(%r10) | ||||
| 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | ||||
| 	jnz ia32_tracesys | ||||
| ia32_do_syscall:	 | ||||
| 	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 | ||||
| 	call *ia32_sys_call_table(,%rax,8) # xxx: rip relative | ||||
| ia32_sysret: | ||||
|  | @ -435,7 +435,9 @@ ia32_tracesys: | |||
| 	call syscall_trace_enter | ||||
| 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */ | ||||
| 	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) | ||||
| 
 | ||||
| ia32_badsys: | ||||
|  |  | |||
|  | @ -156,11 +156,11 @@ static int __init acpi_sleep_setup(char *str) | |||
| #ifdef CONFIG_HIBERNATION | ||||
| 		if (strncmp(str, "s4_nohwsig", 10) == 0) | ||||
| 			acpi_no_s4_hw_signature(); | ||||
| 		if (strncmp(str, "s4_nonvs", 8) == 0) | ||||
| 			acpi_s4_no_nvs(); | ||||
| #endif | ||||
| 		if (strncmp(str, "old_ordering", 12) == 0) | ||||
| 			acpi_old_suspend_ordering(); | ||||
| 		if (strncmp(str, "s4_nonvs", 8) == 0) | ||||
| 			acpi_s4_no_nvs(); | ||||
| 		str = strchr(str, ','); | ||||
| 		if (str != NULL) | ||||
| 			str += strspn(str, ", \t"); | ||||
|  |  | |||
|  | @ -1436,7 +1436,7 @@ static int __init detect_init_APIC(void) | |||
| 	switch (boot_cpu_data.x86_vendor) { | ||||
| 	case X86_VENDOR_AMD: | ||||
| 		if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) || | ||||
| 		    (boot_cpu_data.x86 == 15)) | ||||
| 		    (boot_cpu_data.x86 >= 15)) | ||||
| 			break; | ||||
| 		goto no_apic; | ||||
| 	case X86_VENDOR_INTEL: | ||||
|  |  | |||
|  | @ -245,17 +245,6 @@ config X86_E_POWERSAVER | |||
| 
 | ||||
| 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 | ||||
| 	tristate | ||||
| 	default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD) | ||||
|  |  | |||
|  | @ -36,8 +36,11 @@ static struct _cache_table cache_table[] __cpuinitdata = | |||
| { | ||||
| 	{ 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 */ | ||||
| 	{ 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 */ | ||||
| 	{ 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 */ | ||||
| 	{ 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 */ | ||||
|  | @ -85,6 +88,18 @@ static struct _cache_table cache_table[] __cpuinitdata = | |||
| 	{ 0x85, LVL_2,    2048 },	/* 8-way set assoc, 32 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 */ | ||||
| 	{ 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} | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -346,6 +346,7 @@ ENTRY(save_args) | |||
| 	popq_cfi %rax			/* move return address... */ | ||||
| 	mov %gs:pda_irqstackptr,%rsp | ||||
| 	EMPTY_FRAME 0 | ||||
| 	pushq_cfi %rbp			/* backlink for unwinder */ | ||||
| 	pushq_cfi %rax			/* ... to the new stack */ | ||||
| 	/* | ||||
| 	 * We entered an interrupt context - irqs are off: | ||||
|  |  | |||
|  | @ -2528,14 +2528,15 @@ static void irq_complete_move(struct irq_desc **descp) | |||
| 
 | ||||
| 	vector = ~get_irq_regs()->orig_ax; | ||||
| 	me = smp_processor_id(); | ||||
| 
 | ||||
| 	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) { | ||||
| #ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC | ||||
| 		*descp = desc = move_irq_desc(desc, me); | ||||
| 		/* get the new one */ | ||||
| 		cfg = desc->chip_data; | ||||
| #endif | ||||
| 
 | ||||
| 	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) | ||||
| 		send_cleanup_vector(cfg); | ||||
| 	} | ||||
| } | ||||
| #else | ||||
| static inline void irq_complete_move(struct irq_desc **descp) {} | ||||
|  |  | |||
|  | @ -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) = { | ||||
| 	[0 ... IRQ0_VECTOR - 1] = -1, | ||||
| 	[IRQ0_VECTOR] = 0, | ||||
|  | @ -178,9 +169,6 @@ void __init native_init_IRQ(void) | |||
| 	alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); | ||||
| #endif | ||||
| 
 | ||||
| 	if (!acpi_ioapic) | ||||
| 		setup_irq(2, &irq2); | ||||
| 
 | ||||
| 	/* setup after call gates are initialised (usually add in
 | ||||
| 	 * the architecture specific gates) | ||||
| 	 */ | ||||
|  |  | |||
|  | @ -38,6 +38,15 @@ void __init pre_intr_init_hook(void) | |||
| 	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 | ||||
|  * | ||||
|  | @ -53,6 +62,9 @@ void __init intr_init_hook(void) | |||
| 		if (x86_quirks->arch_intr_init()) | ||||
| 			return; | ||||
| 	} | ||||
| 	if (!acpi_ioapic) | ||||
| 		setup_irq(2, &irq2); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -33,13 +33,23 @@ void __init intr_init_hook(void) | |||
| 	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
 | ||||
| 	 * the TSC code because we can't sync them */ | ||||
| 	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) | ||||
| { | ||||
| } | ||||
|  |  | |||
|  | @ -81,7 +81,7 @@ static void enable_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 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 vic_enable_cpi(void); | ||||
| 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; | ||||
| 
 | ||||
| /* 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) */ | ||||
| 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] |= | ||||
| 	    voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK + | ||||
| 				       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", | ||||
| 	       cpus_addr(phys_cpu_present_map)[0]); | ||||
| 	/* 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 | ||||
|  * 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 */ | ||||
| 	unsigned long real_mask; | ||||
| 	unsigned long irq_mask = 1 << irq; | ||||
| 	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
 | ||||
| 		 * bad things will happen */ | ||||
| 		return; | ||||
|  | @ -1750,10 +1748,11 @@ static void __cpuinit voyager_smp_prepare_boot_cpu(void) | |||
| 	init_gdt(smp_processor_id()); | ||||
| 	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) | ||||
|  | @ -1783,9 +1782,9 @@ void __init smp_setup_processor_id(void) | |||
| 	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); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -603,8 +603,6 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
| 
 | ||||
| 	si_code = SEGV_MAPERR; | ||||
| 
 | ||||
| 	if (notify_page_fault(regs)) | ||||
| 		return; | ||||
| 	if (unlikely(kmmio_fault(regs, address))) | ||||
| 		return; | ||||
| 
 | ||||
|  | @ -634,6 +632,9 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
| 		if (spurious_fault(address, error_code)) | ||||
| 			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 | ||||
| 		 * 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; | ||||
| 	} | ||||
| 
 | ||||
| 	/* 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 | ||||
|  |  | |||
|  | @ -19,8 +19,10 @@ DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags); | |||
|    paired with xen_mc_issue() */ | ||||
| static inline void xen_mc_batch(void) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| 	/* 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) | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ menuconfig ACPI | |||
| 	depends on PCI | ||||
| 	depends on PM | ||||
| 	select PNP | ||||
| 	select CPU_IDLE | ||||
| 	default y | ||||
| 	---help--- | ||||
| 	  Advanced Configuration and Power Interface (ACPI) support for  | ||||
|  | @ -287,7 +288,7 @@ config ACPI_CONTAINER | |||
| 	  support physical cpu/memory hot-plug. | ||||
| 
 | ||||
| 	  If one selects "m", this driver can be loaded with | ||||
| 	  "modprobe acpi_container". | ||||
| 	  "modprobe container". | ||||
| 
 | ||||
| config ACPI_HOTPLUG_MEMORY | ||||
| 	tristate "Memory Hotplug" | ||||
|  |  | |||
|  | @ -538,10 +538,9 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) | |||
| 			if (ACPI_FAILURE(status)) { | ||||
| 				ACPI_WARNING((AE_INFO, | ||||
| 					      "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; | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -116,9 +116,9 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) | |||
| 		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; | ||||
| 
 | ||||
| 	/* 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 | ||||
| 		    (string_desc->string.pointer, | ||||
| 		     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); | ||||
| 	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); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -163,7 +163,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) | |||
| 	case ACPI_NOTIFY_BUS_CHECK: | ||||
| 		/* Fall through */ | ||||
| 	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) ? | ||||
| 		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"); | ||||
| 		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, | ||||
| 						       KOBJ_ONLINE); | ||||
| 				else | ||||
| 					printk("Failed to add container\n"); | ||||
| 					printk(KERN_WARNING | ||||
| 					       "Failed to add container\n"); | ||||
| 			} | ||||
| 		} else { | ||||
| 			if (ACPI_SUCCESS(status)) { | ||||
|  |  | |||
|  | @ -855,10 +855,14 @@ fdd_out: | |||
| static ssize_t show_docked(struct device *dev, | ||||
| 			   struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct acpi_device *tmp; | ||||
| 
 | ||||
| 	struct dock_station *dock_station = *((struct dock_station **) | ||||
| 		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); | ||||
| 
 | ||||
|  | @ -984,7 +988,7 @@ static int dock_add(acpi_handle handle) | |||
| 
 | ||||
| 	ret = device_create_file(&dock_device->dev, &dev_attr_docked); | ||||
| 	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); | ||||
| 		kfree(dock_station); | ||||
| 		dock_station = NULL; | ||||
|  | @ -992,7 +996,7 @@ static int dock_add(acpi_handle handle) | |||
| 	} | ||||
| 	ret = device_create_file(&dock_device->dev, &dev_attr_undock); | ||||
| 	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); | ||||
| 		platform_device_unregister(dock_device); | ||||
| 		kfree(dock_station); | ||||
|  | @ -1001,7 +1005,7 @@ static int dock_add(acpi_handle handle) | |||
| 	} | ||||
| 	ret = device_create_file(&dock_device->dev, &dev_attr_uid); | ||||
| 	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_undock); | ||||
| 		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); | ||||
| 	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_undock); | ||||
| 		device_remove_file(&dock_device->dev, &dev_attr_uid); | ||||
|  |  | |||
|  | @ -982,7 +982,7 @@ int __init acpi_ec_ecdt_probe(void) | |||
| 		saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); | ||||
| 		if (!saved_ec) | ||||
| 			return -ENOMEM; | ||||
| 		memcpy(&saved_ec, boot_ec, sizeof(saved_ec)); | ||||
| 		memcpy(saved_ec, boot_ec, sizeof(*saved_ec)); | ||||
| 	/* fall through */ | ||||
| 	} | ||||
| 	/* This workaround is needed only on some broken machines,
 | ||||
|  |  | |||
|  | @ -255,12 +255,12 @@ static int acpi_platform_notify(struct device *dev) | |||
| 	} | ||||
| 	type = acpi_get_bus_type(dev->bus); | ||||
| 	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; | ||||
| 		goto end; | ||||
| 	} | ||||
| 	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: | ||||
| 	if (!ret) | ||||
| 		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_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); | ||||
| 	} else | ||||
| 		DBG("Device %s -> No ACPI support\n", dev->bus_id); | ||||
| 		DBG("Device %s -> No ACPI support\n", dev_name(dev)); | ||||
| #endif | ||||
| 
 | ||||
| 	return ret; | ||||
|  |  | |||
|  | @ -228,10 +228,10 @@ void acpi_os_vprintf(const char *fmt, va_list args) | |||
| 	if (acpi_in_debugger) { | ||||
| 		kdb_printf("%s", buffer); | ||||
| 	} else { | ||||
| 		printk("%s", buffer); | ||||
| 		printk(KERN_CONT "%s", buffer); | ||||
| 	} | ||||
| #else | ||||
| 	printk("%s", buffer); | ||||
| 	printk(KERN_CONT "%s", buffer); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
|  | @ -1317,6 +1317,54 @@ acpi_os_validate_interface (char *interface) | |||
| 	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 | ||||
|  | @ -1346,6 +1394,8 @@ acpi_os_validate_address ( | |||
| 
 | ||||
| 	switch (space_id) { | ||||
| 	case ACPI_ADR_SPACE_SYSTEM_IO: | ||||
| 		if (!valid_aml_io_address(address, length)) | ||||
| 			return AE_AML_ILLEGAL_ADDRESS; | ||||
| 	case ACPI_ADR_SPACE_SYSTEM_MEMORY: | ||||
| 		/* Only interference checks against SystemIO and SytemMemory
 | ||||
| 		   are needed */ | ||||
|  |  | |||
|  | @ -593,7 +593,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) | |||
| 		return -ENODEV; | ||||
| 	} else { | ||||
| 		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_bid(link->device), link->irq.active); | ||||
| 	} | ||||
|  |  | |||
|  | @ -66,43 +66,17 @@ ACPI_MODULE_NAME("processor_idle"); | |||
| #define ACPI_PROCESSOR_FILE_POWER	"power" | ||||
| #define US_TO_PM_TIMER_TICKS(t)		((t * (PM_TIMER_FREQUENCY/1000)) / 1000) | ||||
| #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 C3_OVERHEAD			1	/* 1us */ | ||||
| #endif | ||||
| #define PM_TIMER_TICKS_TO_US(p)		(((p) * 1000)/(PM_TIMER_FREQUENCY/1000)) | ||||
| 
 | ||||
| static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER; | ||||
| #ifdef CONFIG_CPU_IDLE | ||||
| module_param(max_cstate, uint, 0000); | ||||
| #else | ||||
| module_param(max_cstate, uint, 0644); | ||||
| #endif | ||||
| static unsigned int nocst __read_mostly; | ||||
| 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; | ||||
| module_param(latency_factor, uint, 0644); | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * 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; | ||||
| } | ||||
| 
 | ||||
| #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 | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -390,421 +299,6 @@ static int tsc_halts_in_c(int state) | |||
| } | ||||
| #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) | ||||
| { | ||||
| 
 | ||||
|  | @ -1047,11 +541,7 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) | |||
| 	 */ | ||||
| 	cx->valid = 1; | ||||
| 
 | ||||
| #ifndef CONFIG_CPU_IDLE | ||||
| 	cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency); | ||||
| #else | ||||
| 	cx->latency_ticks = cx->latency; | ||||
| #endif | ||||
| 
 | ||||
| 	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")); | ||||
| 			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; | ||||
| 
 | ||||
| #ifndef CONFIG_CPU_IDLE | ||||
| 	cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency); | ||||
| #else | ||||
| 	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; | ||||
| } | ||||
|  | @ -1201,20 +695,6 @@ static int acpi_processor_get_power_info(struct acpi_processor *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 | ||||
| 	 * CPU as being "idle manageable" | ||||
|  | @ -1312,69 +792,6 @@ static const struct file_operations acpi_processor_power_fops = { | |||
| 	.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 | ||||
|  | @ -1383,7 +800,7 @@ static int acpi_idle_bm_check(void) | |||
| { | ||||
| 	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) | ||||
| 		acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); | ||||
| 	/*
 | ||||
|  | @ -1399,25 +816,6 @@ static int acpi_idle_bm_check(void) | |||
| 	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 | ||||
|  * @cx: cstate data | ||||
|  | @ -1473,9 +871,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	if (pr->flags.bm_check) | ||||
| 		acpi_idle_update_bm_rld(pr, cx); | ||||
| 
 | ||||
| 	t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); | ||||
| 	acpi_idle_do_entry(cx); | ||||
| 	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); | ||||
| 
 | ||||
| 	if (pr->flags.bm_check) | ||||
| 		acpi_idle_update_bm_rld(pr, cx); | ||||
| 
 | ||||
| 	if (cx->type == ACPI_STATE_C3) | ||||
| 		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_idle_update_bm_rld(pr, cx); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * disable bus master | ||||
| 	 * bm_check implies we need ARB_DIS | ||||
|  | @ -1795,8 +1185,6 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| #endif /* CONFIG_CPU_IDLE */ | ||||
| 
 | ||||
| int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | ||||
| 			      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", | ||||
| 			       max_cstate); | ||||
| 		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) | ||||
|  | @ -1852,11 +1236,9 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
| 	 * platforms that only support C1. | ||||
| 	 */ | ||||
| 	if (pr->flags.power) { | ||||
| #ifdef CONFIG_CPU_IDLE | ||||
| 		acpi_processor_setup_cpuidle(pr); | ||||
| 		if (cpuidle_register_device(&pr->power.dev)) | ||||
| 			return -EIO; | ||||
| #endif | ||||
| 
 | ||||
| 		printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id); | ||||
| 		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, | ||||
| 				       pr->power.states[i].type); | ||||
| 		printk(")\n"); | ||||
| 
 | ||||
| #ifndef CONFIG_CPU_IDLE | ||||
| 		if (pr->id == 0) { | ||||
| 			pm_idle_save = pm_idle; | ||||
| 			pm_idle = acpi_processor_idle; | ||||
| 		} | ||||
| #endif | ||||
| 	} | ||||
| 
 | ||||
| 	/* 'power' [R] */ | ||||
|  | @ -1889,34 +1264,12 @@ int acpi_processor_power_exit(struct acpi_processor *pr, | |||
| 	if (boot_option_idle_override) | ||||
| 		return 0; | ||||
| 
 | ||||
| #ifdef CONFIG_CPU_IDLE | ||||
| 	cpuidle_unregister_device(&pr->power.dev); | ||||
| #endif | ||||
| 	pr->flags.power_setup_done = 0; | ||||
| 
 | ||||
| 	if (acpi_device_dir(device)) | ||||
| 		remove_proc_entry(ACPI_PROCESSOR_FILE_POWER, | ||||
| 				  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; | ||||
| } | ||||
|  |  | |||
|  | @ -31,14 +31,6 @@ | |||
| #include <linux/init.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 | ||||
| #include <asm/cpufeature.h> | ||||
| #endif | ||||
|  | @ -434,96 +426,6 @@ int acpi_processor_notify_smm(struct module *calling_module) | |||
| 
 | ||||
| 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) | ||||
| { | ||||
| 	int result = 0; | ||||
|  | @ -747,14 +649,12 @@ err_ret: | |||
| } | ||||
| EXPORT_SYMBOL(acpi_processor_preregister_performance); | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| acpi_processor_register_performance(struct acpi_processor_performance | ||||
| 				    *performance, unsigned int cpu) | ||||
| { | ||||
| 	struct acpi_processor *pr; | ||||
| 
 | ||||
| 
 | ||||
| 	if (!(acpi_processor_ppc_status & PPC_REGISTERED)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
|  | @ -781,8 +681,6 @@ acpi_processor_register_performance(struct acpi_processor_performance | |||
| 		return -EIO; | ||||
| 	} | ||||
| 
 | ||||
| 	acpi_cpufreq_add_file(pr); | ||||
| 
 | ||||
| 	mutex_unlock(&performance_mutex); | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -795,7 +693,6 @@ acpi_processor_unregister_performance(struct acpi_processor_performance | |||
| { | ||||
| 	struct acpi_processor *pr; | ||||
| 
 | ||||
| 
 | ||||
| 	mutex_lock(&performance_mutex); | ||||
| 
 | ||||
| 	pr = per_cpu(processors, cpu); | ||||
|  | @ -808,8 +705,6 @@ acpi_processor_unregister_performance(struct acpi_processor_performance | |||
| 		kfree(pr->performance->states); | ||||
| 	pr->performance = NULL; | ||||
| 
 | ||||
| 	acpi_cpufreq_remove_file(pr); | ||||
| 
 | ||||
| 	mutex_unlock(&performance_mutex); | ||||
| 
 | ||||
| 	return; | ||||
|  |  | |||
|  | @ -90,31 +90,6 @@ void __init acpi_old_suspend_ordering(void) | |||
| 	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. | ||||
|  */ | ||||
|  | @ -193,6 +168,18 @@ static void acpi_pm_end(void) | |||
| #endif /* CONFIG_ACPI_SLEEP */ | ||||
| 
 | ||||
| #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); | ||||
| 
 | ||||
| static u32 acpi_suspend_states[] = { | ||||
|  | @ -396,6 +383,20 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
| #endif /* CONFIG_SUSPEND */ | ||||
| 
 | ||||
| #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 struct acpi_table_facs *facs; | ||||
| static bool nosigcheck; | ||||
|  | @ -679,7 +680,7 @@ static void acpi_power_off_prepare(void) | |||
| static void acpi_power_off(void) | ||||
| { | ||||
| 	/* 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(); | ||||
| 	acpi_enable_wakeup_device(ACPI_STATE_S5); | ||||
| 	acpi_enter_sleep_state(ACPI_STATE_S5); | ||||
|  |  | |||
|  | @ -293,7 +293,12 @@ static void __init check_multiple_madt(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(); | ||||
| 	return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -1020,7 +1020,7 @@ acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset) | |||
| 	} | ||||
| 
 | ||||
| 	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, "\ncurrent: %d\n", dev->brightness->curr); | ||||
| 
 | ||||
|  | @ -1059,7 +1059,7 @@ acpi_video_device_write_brightness(struct file *file, | |||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	/* 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 (ACPI_SUCCESS | ||||
| 			    (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 | ||||
| 			       "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>"); | ||||
| 		if (options & 2) | ||||
| 			seq_printf(seq, " <PCI video>"); | ||||
|  | @ -1712,7 +1712,7 @@ acpi_video_get_next_level(struct acpi_video_device *device, | |||
| 	max = max_below = 0; | ||||
| 	min = min_above = 255; | ||||
| 	/* 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]; | ||||
| 		if (abs(l - level_current) < abs(delta)) { | ||||
| 			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 */ | ||||
| 	level_current += delta; | ||||
| 	for (i = 0; i < device->brightness->count; i++) { | ||||
| 	for (i = 2; i < device->brightness->count; i++) { | ||||
| 		l = device->brightness->levels[i]; | ||||
| 		if (l < min) | ||||
| 			min = l; | ||||
|  | @ -2006,6 +2006,12 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
| 			device->pnp.bus_id[3] = '0' + 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; | ||||
| 	strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); | ||||
|  |  | |||
|  | @ -1713,8 +1713,8 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, | |||
| 		for (i = 0; i < SX_NBOARDS; i++) | ||||
| 			sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); | ||||
| 		sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); | ||||
| 		unlock_kernel(); | ||||
| 		return -EIO; | ||||
| 		rc = -EIO; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	switch (cmd) { | ||||
|  | @ -1747,7 +1747,8 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, | |||
| 		break; | ||||
| 	case SXIO_DO_RAMTEST: | ||||
| 		if (sx_initialized)	/* Already initialized: better not ramtest the board.  */ | ||||
| 			return -EPERM; | ||||
| 			rc = -EPERM; | ||||
| 			break; | ||||
| 		if (IS_SX_BOARD(board)) { | ||||
| 			rc = do_memtest(board, 0, 0x7000); | ||||
| 			if (!rc) | ||||
|  | @ -1844,6 +1845,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, | |||
| 		rc = -ENOTTY; | ||||
| 		break; | ||||
| 	} | ||||
| out: | ||||
| 	unlock_kernel(); | ||||
| 	func_exit(); | ||||
| 	return rc; | ||||
|  |  | |||
|  | @ -412,6 +412,7 @@ fw_card_add(struct fw_card *card, | |||
| { | ||||
| 	u32 *config_rom; | ||||
| 	size_t length; | ||||
| 	int err; | ||||
| 
 | ||||
| 	card->max_receive = max_receive; | ||||
| 	card->link_speed = link_speed; | ||||
|  | @ -422,7 +423,13 @@ fw_card_add(struct fw_card *card, | |||
| 	list_add_tail(&card->link, &card_list); | ||||
| 	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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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_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_usd = {-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) {		\ | ||||
| 	.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("NC8510", "HP Compaq 8510", xy_swap_inverted), | ||||
| 	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, } | ||||
| /* Laptop models without axis info (yet):
 | ||||
|  * "NC651xx" "HP Compaq 651" | ||||
|  * "NC671xx" "HP Compaq 671" | ||||
|  * "NC6910" "HP Compaq 6910" | ||||
|  * HP Compaq 8710x Notebook PC / Mobile Workstation | ||||
|  * "NC2400" "HP Compaq nc2400" | ||||
|  |  | |||
|  | @ -1823,6 +1823,10 @@ static int dv1394_open(struct inode *inode, struct file *file) | |||
| 
 | ||||
| #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; | ||||
| } | ||||
| 
 | ||||
|  | @ -2567,10 +2571,6 @@ static int __init dv1394_init_module(void) | |||
| { | ||||
| 	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); | ||||
| 	dv1394_cdev.owner = THIS_MODULE; | ||||
| 	ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16); | ||||
|  |  | |||
|  | @ -25,13 +25,13 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector) | |||
| { | ||||
| 	dev_info_t *hash; | ||||
| 	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 >>= 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) | ||||
| 		hash++; | ||||
|  |  | |||
|  | @ -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)) | ||||
| 			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); | ||||
| 	while ( (s=strchr(b, '/')) != NULL) | ||||
| 		*s = '!'; | ||||
|  | @ -2441,6 +2446,15 @@ static void analyze_sbs(mddev_t * mddev) | |||
| 
 | ||||
| 	i = 0; | ||||
| 	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 (super_types[mddev->major_version]. | ||||
| 			    validate_super(mddev, rdev)) { | ||||
|  | @ -4614,13 +4628,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) | |||
| 	 * 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; | ||||
| 
 | ||||
| 	md_update_sb(mddev, 1); | ||||
|  | @ -4634,9 +4641,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) | |||
| 	md_new_event(mddev); | ||||
| 	return 0; | ||||
| 
 | ||||
| abort_unbind_export: | ||||
| 	unbind_rdev_from_array(rdev); | ||||
| 
 | ||||
| abort_export: | ||||
| 	export_rdev(rdev); | ||||
| 	return err; | ||||
|  |  | |||
|  | @ -1640,7 +1640,8 @@ static void raid1d(mddev_t *mddev) | |||
| 			} | ||||
| 
 | ||||
| 			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" | ||||
| 				       " read error for block %llu\n", | ||||
| 				       bdevname(bio->bi_bdev,b), | ||||
|  |  | |||
|  | @ -217,6 +217,7 @@ config DELL_LAPTOP | |||
| 	depends on EXPERIMENTAL | ||||
| 	depends on BACKLIGHT_CLASS_DEVICE | ||||
| 	depends on RFKILL | ||||
| 	depends on POWER_SUPPLY | ||||
| 	default n | ||||
| 	---help--- | ||||
| 	This driver adds support for rfkill and backlight control to Dell | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ struct ssc_device *ssc_request(unsigned int ssc_num) | |||
| 
 | ||||
| 	if (!ssc_valid) { | ||||
| 		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); | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -207,7 +207,7 @@ static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data) | |||
| 		  &device_ccb->recv_ctrl); | ||||
| 
 | ||||
| 	/* 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); | ||||
| 		udelay(1); | ||||
| 		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); | ||||
| 
 | ||||
| 	/* 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)) | ||||
| 			break; | ||||
| 		udelay(1); | ||||
|  | @ -326,7 +326,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) | |||
| 
 | ||||
| 	return 0; | ||||
| free: | ||||
| 	pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa); | ||||
| 	ilo_ccb_close(pdev, data); | ||||
| out: | ||||
| 	return error; | ||||
| } | ||||
|  |  | |||
|  | @ -19,6 +19,8 @@ | |||
| #define MAX_ILO_DEV	1 | ||||
| /* max number of files */ | ||||
| #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. | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
|  * License.  See the file "COPYING" in the main directory of this archive | ||||
|  * 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 */ | ||||
| 
 | ||||
| 	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 recv_msg_list;	/* deliverable payloads */ | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
|  * License.  See the file "COPYING" in the main directory of this archive | ||||
|  * 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; | ||||
| 
 | ||||
| 		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; | ||||
| 		} | ||||
|  | @ -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 */ | ||||
| 	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_slot->hdr.size != 0); | ||||
|  |  | |||
|  | @ -2276,8 +2276,7 @@ no_mem: | |||
| 		} else if ((len = ntohl(r->len_cq)) != 0) { | ||||
| 			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]; | ||||
| 			if (fl->use_pages) { | ||||
|  |  | |||
|  | @ -351,6 +351,9 @@ static int gfar_probe(struct of_device *ofdev, | |||
| 	/* Reset MAC layer */ | ||||
| 	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); | ||||
| 	gfar_write(&priv->regs->maccfg1, tempval); | ||||
| 
 | ||||
|  |  | |||
|  | @ -312,7 +312,7 @@ extern const char gfar_driver_version[]; | |||
| #define ATTRELI_EI(x) (x) | ||||
| 
 | ||||
| #define BD_LFLAG(flags) ((flags) << 16) | ||||
| #define BD_LENGTH_MASK		0x00ff | ||||
| #define BD_LENGTH_MASK		0x0000ffff | ||||
| 
 | ||||
| /* TxBD status field bits */ | ||||
| #define TXBD_READY		0x8000 | ||||
|  |  | |||
|  | @ -4042,6 +4042,7 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 		priv->is_open = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	pci_save_state(pdev); | ||||
| 	pci_set_power_state(pdev, PCI_D3hot); | ||||
| 
 | ||||
| 	return 0; | ||||
|  | @ -4052,6 +4053,7 @@ static int iwl_pci_resume(struct pci_dev *pdev) | |||
| 	struct iwl_priv *priv = pci_get_drvdata(pdev); | ||||
| 
 | ||||
| 	pci_set_power_state(pdev, PCI_D0); | ||||
| 	pci_restore_state(pdev); | ||||
| 
 | ||||
| 	if (priv->is_open) | ||||
| 		iwl_mac_start(priv->hw); | ||||
|  |  | |||
|  | @ -480,6 +480,9 @@ void iwl_clear_stations_table(struct iwl_priv *priv) | |||
| 	priv->num_stations = 0; | ||||
| 	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); | ||||
| } | ||||
| EXPORT_SYMBOL(iwl_clear_stations_table); | ||||
|  |  | |||
|  | @ -8143,6 +8143,7 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 		priv->is_open = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	pci_save_state(pdev); | ||||
| 	pci_set_power_state(pdev, PCI_D3hot); | ||||
| 
 | ||||
| 	return 0; | ||||
|  | @ -8153,6 +8154,7 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) | |||
| 	struct iwl3945_priv *priv = pci_get_drvdata(pdev); | ||||
| 
 | ||||
| 	pci_set_power_state(pdev, PCI_D0); | ||||
| 	pci_restore_state(pdev); | ||||
| 
 | ||||
| 	if (priv->is_open) | ||||
| 		iwl3945_mac_start(priv->hw); | ||||
|  |  | |||
|  | @ -355,6 +355,8 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state) | |||
| 	int i = 0; | ||||
| 
 | ||||
| 	if (drv && drv->suspend) { | ||||
| 		pci_power_t prev = pci_dev->current_state; | ||||
| 
 | ||||
| 		pci_dev->state_saved = false; | ||||
| 
 | ||||
| 		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) | ||||
| 			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; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	pci_save_state(pci_dev); | ||||
| 	pci_dev->state_saved = true; | ||||
| 	/*
 | ||||
| 	 * 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); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| 
 | ||||
| 	if (!pci_is_bridge(pci_dev)) | ||||
| 		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) | ||||
| { | ||||
| 	pci_pm_default_suspend_generic(pci_dev); | ||||
| 
 | ||||
| 	/* Disable non-bridge devices without PM support */ | ||||
| 	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) | ||||
|  | @ -497,21 +488,49 @@ static void pci_pm_complete(struct device *dev) | |||
| static int pci_pm_suspend(struct device *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)) | ||||
| 		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) | ||||
|  | @ -554,7 +573,7 @@ static int pci_pm_resume_noirq(struct device *dev) | |||
| static int pci_pm_resume(struct device *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; | ||||
| 
 | ||||
| 	/*
 | ||||
|  | @ -567,12 +586,16 @@ static int pci_pm_resume(struct device *dev) | |||
| 	if (pci_has_legacy_pm_support(pci_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 */ | ||||
|  | @ -589,21 +612,31 @@ static int pci_pm_resume(struct device *dev) | |||
| static int pci_pm_freeze(struct device *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)) | ||||
| 		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) | ||||
|  | @ -646,16 +679,18 @@ static int pci_pm_thaw_noirq(struct device *dev) | |||
| static int pci_pm_thaw(struct device *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; | ||||
| 
 | ||||
| 	if (pci_has_legacy_pm_support(pci_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; | ||||
| } | ||||
|  | @ -663,22 +698,29 @@ static int pci_pm_thaw(struct device *dev) | |||
| static int pci_pm_poweroff(struct device *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; | ||||
| 
 | ||||
| 	if (pci_has_legacy_pm_support(pci_dev)) | ||||
| 		return pci_legacy_suspend(dev, PMSG_HIBERNATE); | ||||
| 
 | ||||
| 	if (!drv || !drv->pm) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (drv->pm->poweroff) { | ||||
| 		error = drv->pm->poweroff(dev); | ||||
| 		suspend_report_result(drv->pm->poweroff, error); | ||||
| 	if (!pm) { | ||||
| 		pci_pm_default_suspend(pci_dev); | ||||
| 		goto Fixup; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!error) | ||||
| 		pci_pm_default_suspend(pci_dev); | ||||
| 	pci_dev->state_saved = false; | ||||
| 
 | ||||
| 	if (pm->poweroff) { | ||||
| 		error = pm->poweroff(dev); | ||||
| 		suspend_report_result(pm->poweroff, error); | ||||
| 	} | ||||
| 
 | ||||
| 	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; | ||||
| } | ||||
|  | @ -719,7 +761,7 @@ static int pci_pm_restore_noirq(struct device *dev) | |||
| static int pci_pm_restore(struct device *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; | ||||
| 
 | ||||
| 	/*
 | ||||
|  | @ -732,10 +774,14 @@ static int pci_pm_restore(struct device *dev) | |||
| 	if (pci_has_legacy_pm_support(pci_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; | ||||
| } | ||||
|  |  | |||
|  | @ -768,8 +768,8 @@ pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
| 		return -EINVAL; | ||||
| 	 | ||||
| 	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) | ||||
| 		count = 0; | ||||
|  |  | |||
|  | @ -1418,10 +1418,10 @@ int pci_restore_standard_config(struct pci_dev *dev) | |||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	dev->current_state = PCI_D0; | ||||
| 	pci_update_current_state(dev, PCI_D0); | ||||
| 
 | ||||
|  Restore: | ||||
| 	return pci_restore_state(dev); | ||||
| 	return dev->state_saved ? pci_restore_state(dev) : 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -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 | ||||
| 	 * 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; | ||||
| 
 | ||||
| 	/* All functions are removed, so just disable ASPM for the link */ | ||||
|  |  | |||
|  | @ -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) | ||||
| { | ||||
| 	pcie_portdrv_restore_config(dev); | ||||
| 	pci_set_master(dev); | ||||
| 	return pcie_port_device_resume(dev); | ||||
| } | ||||
| #else | ||||
| #define pcie_portdrv_suspend NULL | ||||
| #define pcie_portdrv_suspend_late NULL | ||||
| #define pcie_portdrv_resume_early NULL | ||||
| #define pcie_portdrv_resume NULL | ||||
| #endif | ||||
| 
 | ||||
|  | @ -292,8 +280,6 @@ static struct pci_driver pcie_portdriver = { | |||
| 	.remove		= pcie_portdrv_remove, | ||||
| 
 | ||||
| 	.suspend	= pcie_portdrv_suspend, | ||||
| 	.suspend_late	= pcie_portdrv_suspend_late, | ||||
| 	.resume_early	= pcie_portdrv_resume_early, | ||||
| 	.resume		= pcie_portdrv_resume, | ||||
| 
 | ||||
| 	.err_handler 	= &pcie_portdrv_err_handler, | ||||
|  |  | |||
|  | @ -63,7 +63,7 @@ void pci_disable_rom(struct pci_dev *pdev) | |||
|  * The PCI window size could be much larger than the | ||||
|  * 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; | ||||
| 	int last_image; | ||||
|  | @ -72,8 +72,10 @@ size_t pci_get_rom_size(void __iomem *rom, size_t size) | |||
| 	do { | ||||
| 		void __iomem *pds; | ||||
| 		/* 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; | ||||
| 		} | ||||
| 		if (readb(image + 1) != 0xAA) | ||||
| 			break; | ||||
| 		/* 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. | ||||
| 	 * 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; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -42,6 +42,7 @@ config ASUS_LAPTOP | |||
| 	depends on LEDS_CLASS | ||||
| 	depends on NEW_LEDS | ||||
| 	depends on BACKLIGHT_CLASS_DEVICE | ||||
| 	depends on INPUT | ||||
| 	---help--- | ||||
| 	  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 | ||||
|  |  | |||
|  | @ -46,6 +46,7 @@ | |||
| #include <acpi/acpi_drivers.h> | ||||
| #include <acpi/acpi_bus.h> | ||||
| #include <asm/uaccess.h> | ||||
| #include <linux/input.h> | ||||
| 
 | ||||
| #define ASUS_LAPTOP_VERSION "0.42" | ||||
| 
 | ||||
|  | @ -181,6 +182,8 @@ struct asus_hotk { | |||
| 	u8 light_level;		//light sensor level
 | ||||
| 	u8 light_switch;	//light sensor switch value
 | ||||
| 	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(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 | ||||
|  * 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); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 struct key_entry *key; | ||||
| 
 | ||||
| 	/* TODO Find a better way to handle events count. */ | ||||
| 	if (!hotk) | ||||
| 		return; | ||||
|  | @ -738,10 +832,24 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
| 		lcd_blank(FB_BLANK_POWERDOWN); | ||||
| 	} | ||||
| 
 | ||||
| 	acpi_bus_generate_proc_event(hotk->device, event, | ||||
| 				hotk->event_count[event % 128]++); | ||||
| 	acpi_bus_generate_netlink_event(hotk->device->pnp.device_class, | ||||
| 					dev_name(&hotk->device->dev), event, | ||||
| 					hotk->event_count[event % 128]++); | ||||
| 
 | ||||
| 	return; | ||||
| 	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)					\ | ||||
|  | @ -959,6 +1067,38 @@ static int asus_hotk_get_info(void) | |||
| 	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) | ||||
| { | ||||
| 	int result = 0; | ||||
|  | @ -1044,7 +1184,7 @@ static int asus_hotk_add(struct acpi_device *device) | |||
| 	/* GPS is on by default */ | ||||
| 	write_status(NULL, 1, GPS_ON); | ||||
| 
 | ||||
|       end: | ||||
| end: | ||||
| 	if (result) { | ||||
| 		kfree(hotk->name); | ||||
| 		kfree(hotk); | ||||
|  | @ -1091,10 +1231,17 @@ static void asus_led_exit(void) | |||
| 	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) | ||||
| { | ||||
| 	asus_backlight_exit(); | ||||
| 	asus_led_exit(); | ||||
| 	asus_input_exit(); | ||||
| 
 | ||||
| 	acpi_bus_unregister_driver(&asus_hotk_driver); | ||||
| 	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 " | ||||
| 		       "ACPI video driver\n"); | ||||
| 
 | ||||
| 	result = asus_input_init(); | ||||
| 	if (result) | ||||
| 		goto fail_input; | ||||
| 
 | ||||
| 	result = asus_led_init(dev); | ||||
| 	if (result) | ||||
| 		goto fail_led; | ||||
|  | @ -1242,22 +1393,25 @@ static int __init asus_laptop_init(void) | |||
| 
 | ||||
| 	return 0; | ||||
| 
 | ||||
|       fail_sysfs: | ||||
| fail_sysfs: | ||||
| 	platform_device_del(asuspf_device); | ||||
| 
 | ||||
|       fail_platform_device2: | ||||
| fail_platform_device2: | ||||
| 	platform_device_put(asuspf_device); | ||||
| 
 | ||||
|       fail_platform_device1: | ||||
| fail_platform_device1: | ||||
| 	platform_driver_unregister(&asuspf_driver); | ||||
| 
 | ||||
|       fail_platform_driver: | ||||
| fail_platform_driver: | ||||
| 	asus_led_exit(); | ||||
| 
 | ||||
|       fail_led: | ||||
| fail_led: | ||||
| 	asus_input_exit(); | ||||
| 
 | ||||
| fail_input: | ||||
| 	asus_backlight_exit(); | ||||
| 
 | ||||
|       fail_backlight: | ||||
| fail_backlight: | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
|  |  | |||
|  | @ -143,6 +143,7 @@ struct asus_hotk { | |||
| 							 S1300N, S5200N*/ | ||||
| 		A4S,            /* Z81sp */ | ||||
| 		F3Sa,		/* (Centrino) */ | ||||
| 		R1F, | ||||
| 		END_MODEL | ||||
| 	} model;		/* Models currently supported */ | ||||
| 	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_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 */ | ||||
|  | @ -1165,6 +1177,8 @@ static int asus_model_match(char *model) | |||
| 		return W3V; | ||||
| 	else if (strncmp(model, "W5A", 3) == 0) | ||||
| 		return W5A; | ||||
| 	else if (strncmp(model, "R1F", 3) == 0) | ||||
| 		return R1F; | ||||
| 	else if (strncmp(model, "A4S", 3) == 0) | ||||
| 		return A4S; | ||||
| 	else if (strncmp(model, "F3Sa", 4) == 0) | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ | |||
| #include <linux/uaccess.h> | ||||
| #include <linux/input.h> | ||||
| #include <linux/rfkill.h> | ||||
| #include <linux/pci.h> | ||||
| 
 | ||||
| #define EEEPC_LAPTOP_VERSION	"0.1" | ||||
| 
 | ||||
|  | @ -161,6 +162,10 @@ static struct key_entry eeepc_keymap[] = { | |||
| 	{KE_KEY, 0x13, KEY_MUTE }, | ||||
| 	{KE_KEY, 0x14, KEY_VOLUMEDOWN }, | ||||
| 	{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, 0x31, KEY_SWITCHVIDEOMODE }, | ||||
| 	{KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, | ||||
|  | @ -510,7 +515,43 @@ static int eeepc_hotk_check(void) | |||
| static void notify_brn(void) | ||||
| { | ||||
| 	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) | ||||
|  | @ -520,8 +561,9 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
| 		return; | ||||
| 	if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) | ||||
| 		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) { | ||||
| 		key = eepc_get_entry_by_scancode(event); | ||||
| 		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) | ||||
| { | ||||
| 	acpi_status status = AE_OK; | ||||
|  | @ -558,7 +639,7 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
| 	ehotk->device = device; | ||||
| 	result = eeepc_hotk_check(); | ||||
| 	if (result) | ||||
| 		goto end; | ||||
| 		goto ehotk_fail; | ||||
| 	status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, | ||||
| 					     eeepc_hotk_notify, ehotk); | ||||
| 	if (ACPI_FAILURE(status)) | ||||
|  | @ -569,18 +650,25 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
| 							   RFKILL_TYPE_WLAN); | ||||
| 
 | ||||
| 		if (!ehotk->eeepc_wlan_rfkill) | ||||
| 			goto end; | ||||
| 			goto wlan_fail; | ||||
| 
 | ||||
| 		ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; | ||||
| 		ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; | ||||
| 		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 = | ||||
| 				RFKILL_STATE_UNBLOCKED; | ||||
| 		else | ||||
| 			rfkill_set_default(RFKILL_TYPE_WLAN, | ||||
| 					   RFKILL_STATE_UNBLOCKED); | ||||
| 		} else { | ||||
| 			ehotk->eeepc_wlan_rfkill->state = | ||||
| 				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) { | ||||
|  | @ -588,27 +676,47 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
| 			rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); | ||||
| 
 | ||||
| 		if (!ehotk->eeepc_bluetooth_rfkill) | ||||
| 			goto end; | ||||
| 			goto bluetooth_fail; | ||||
| 
 | ||||
| 		ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; | ||||
| 		ehotk->eeepc_bluetooth_rfkill->toggle_radio = | ||||
| 			eeepc_bluetooth_rfkill_set; | ||||
| 		ehotk->eeepc_bluetooth_rfkill->get_state = | ||||
| 			eeepc_bluetooth_rfkill_state; | ||||
| 		if (get_acpi(CM_ASL_BLUETOOTH) == 1) | ||||
| 		if (get_acpi(CM_ASL_BLUETOOTH) == 1) { | ||||
| 			ehotk->eeepc_bluetooth_rfkill->state = | ||||
| 				RFKILL_STATE_UNBLOCKED; | ||||
| 		else | ||||
| 			rfkill_set_default(RFKILL_TYPE_BLUETOOTH, | ||||
| 					   RFKILL_STATE_UNBLOCKED); | ||||
| 		} else { | ||||
| 			ehotk->eeepc_bluetooth_rfkill->state = | ||||
| 				RFKILL_STATE_SOFT_BLOCKED; | ||||
| 		rfkill_register(ehotk->eeepc_bluetooth_rfkill); | ||||
| 			rfkill_set_default(RFKILL_TYPE_BLUETOOTH, | ||||
| 					   RFKILL_STATE_SOFT_BLOCKED); | ||||
| 		} | ||||
| 
 | ||||
| 		result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); | ||||
| 		if (result) | ||||
| 			goto bluetooth_fail; | ||||
| 	} | ||||
| 
 | ||||
|  end: | ||||
| 	if (result) { | ||||
| 		kfree(ehotk); | ||||
| 		ehotk = NULL; | ||||
| 	} | ||||
| 	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; | ||||
| } | ||||
| 
 | ||||
|  | @ -622,6 +730,10 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) | |||
| 					    eeepc_hotk_notify); | ||||
| 	if (ACPI_FAILURE(status)) | ||||
| 		printk(EEEPC_ERR "Error removing notify handler\n"); | ||||
| 
 | ||||
| 	eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||||
| 	eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||||
| 
 | ||||
| 	kfree(ehotk); | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -737,13 +849,21 @@ static void eeepc_backlight_exit(void) | |||
| { | ||||
| 	if (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) | ||||
| 		rfkill_unregister(ehotk->eeepc_wlan_rfkill); | ||||
| 	if (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) | ||||
|  | @ -762,6 +882,8 @@ static void eeepc_hwmon_exit(void) | |||
| static void __exit eeepc_laptop_exit(void) | ||||
| { | ||||
| 	eeepc_backlight_exit(); | ||||
| 	eeepc_rfkill_exit(); | ||||
| 	eeepc_input_exit(); | ||||
| 	eeepc_hwmon_exit(); | ||||
| 	acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||||
| 	sysfs_remove_group(&platform_device->dev.kobj, | ||||
|  | @ -865,6 +987,8 @@ fail_platform_driver: | |||
| fail_hwmon: | ||||
| 	eeepc_backlight_exit(); | ||||
| fail_backlight: | ||||
| 	eeepc_input_exit(); | ||||
| 	eeepc_rfkill_exit(); | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -463,9 +463,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) | |||
| 
 | ||||
| 	return 0; | ||||
| register_wwan_err: | ||||
| 	rfkill_unregister(bluetooth_rfkill); | ||||
| 	if (bluetooth_rfkill) | ||||
| 		rfkill_unregister(bluetooth_rfkill); | ||||
| register_bluetooth_error: | ||||
| 	rfkill_unregister(wifi_rfkill); | ||||
| 	if (wifi_rfkill) | ||||
| 		rfkill_unregister(wifi_rfkill); | ||||
| add_sysfs_error: | ||||
| 	cleanup_sysfs(device); | ||||
| 	return err; | ||||
|  |  | |||
|  | @ -507,7 +507,7 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) | |||
| 
 | ||||
| 	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, | ||||
| 				  "hotkey number out of range: %d\n", | ||||
| 				  hkey_num)); | ||||
|  |  | |||
|  | @ -241,6 +241,12 @@ config RTC_DRV_M41T80_WDT | |||
| 	  If you say Y here you will get support for the | ||||
| 	  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 | ||||
| 	boolean "TI TWL92330/Menelaus" | ||||
| 	depends on MENELAUS | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91SAM9)	+= rtc-at91sam9.o | |||
| obj-$(CONFIG_RTC_DRV_AU1XXX)	+= rtc-au1xxx.o | ||||
| obj-$(CONFIG_RTC_DRV_BFIN)	+= rtc-bfin.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_DS1286)	+= rtc-ds1286.o | ||||
| obj-$(CONFIG_RTC_DRV_DS1302)	+= rtc-ds1302.o | ||||
|  |  | |||
							
								
								
									
										175
									
								
								drivers/rtc/rtc-dm355evm.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								drivers/rtc/rtc-dm355evm.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -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"); | ||||
|  | @ -122,7 +122,6 @@ static const struct rtc_class_ops ds1390_rtc_ops = { | |||
| 
 | ||||
| static int __devinit ds1390_probe(struct spi_device *spi) | ||||
| { | ||||
| 	struct rtc_device *rtc; | ||||
| 	unsigned char tmp; | ||||
| 	struct ds1390 *chip; | ||||
| 	int res; | ||||
|  |  | |||
|  | @ -1475,7 +1475,7 @@ static int aty128fb_set_par(struct fb_info *info) | |||
| 	aty128_set_pll(&par->pll, 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 (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 */ | ||||
| #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 */ | ||||
| 
 | ||||
| 	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; | ||||
| 
 | ||||
| 	/* 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 "); | ||||
| 	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 */ | ||||
| 	// 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 */ | ||||
| 	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,
 | ||||
| 	 * D3 would require a complete re-initialisation of the chip, | ||||
| 	 * including PCI config registers, clocks, AGP configuration, ...) | ||||
| 	 * | ||||
| 	 * For resume, the core will have already brought us back to D0 | ||||
| 	 */ | ||||
| 	if (suspend) { | ||||
| 		/* 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(MEM_POWER_MISC, 0x0c830000); | ||||
| 		mdelay(100); | ||||
| 		pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); | ||||
| 
 | ||||
| 		/* 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 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 may want to change that. How do we know if the BIOS | ||||
| 	 * 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) | ||||
| 		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 */ | ||||
| 	aty128_set_suspend(par, 0); | ||||
| 	par->asleep = 0; | ||||
|  |  | |||
|  | @ -135,7 +135,7 @@ | |||
| #if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ | ||||
| defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT) | ||||
| static const u32 lt_lcd_regs[] = { | ||||
| 	CONFIG_PANEL_LG, | ||||
| 	CNFG_PANEL_LG, | ||||
| 	LCD_GEN_CNTL_LG, | ||||
| 	DSTN_CONTROL_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->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; | ||||
| 	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); | ||||
| 		    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); | ||||
| 
 | ||||
| 
 | ||||
|  | @ -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); | ||||
| 
 | ||||
| 		/* 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 & | ||||
| 			~(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)) | ||||
| 			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 &= | ||||
|  | @ -1978,7 +1978,7 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par) | |||
| 
 | ||||
| 	return timeout ? 0 : -EIO; | ||||
| } | ||||
| #endif | ||||
| #endif /* CONFIG_PPC_PMAC */ | ||||
| 
 | ||||
| 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->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 | ||||
| 	/* Set chip to "suspend" mode */ | ||||
| 	if (aty_power_mgmt(1, par)) { | ||||
| 	if (machine_is(powermac) && aty_power_mgmt(1, par)) { | ||||
| 		par->asleep = 0; | ||||
| 		par->lock_blank = 0; | ||||
| 		atyfb_blank(FB_BLANK_UNBLANK, info); | ||||
|  | @ -2047,11 +2053,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev) | |||
| 
 | ||||
| 	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 | ||||
| 	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); | ||||
| #else | ||||
| 	pci_set_power_state(pdev, PCI_D0); | ||||
| #endif | ||||
| 
 | ||||
| 	aty_resume_chip(info); | ||||
|  | @ -2254,7 +2264,7 @@ static int __devinit aty_init(struct fb_info *info) | |||
| 	if (!M64_HAS(INTEGRATED)) { | ||||
| 		u32 stat0; | ||||
| 		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->ram_type = (stat0 >> 3) & 0x07; | ||||
| 		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->pll_ops = &aty_pll_ct; | ||||
| 		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]; | ||||
| 		/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ | ||||
| 		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 (aty_ld_le32(CONFIG_STAT1, par) & 0x40000000) | ||||
| 		if (aty_ld_le32(CNFG_STAT1, par) & 0x40000000) | ||||
| 			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... | ||||
| 		 */ | ||||
| 		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)) { | ||||
| 			switch (mem & 0x0f) { | ||||
| 			case 3: | ||||
|  | @ -2964,7 +2974,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, | |||
| 			default: | ||||
| 				break; | ||||
| 			} | ||||
| 			if ((aty_ld_le32(CONFIG_STAT0, par) & 7) >= SDRAM) | ||||
| 			if ((aty_ld_le32(CNFG_STAT0, par) & 7) >= SDRAM) | ||||
| 				mem &= ~(0x00700000); | ||||
| 		} | ||||
| 		mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */ | ||||
|  | @ -3572,7 +3582,7 @@ static int __init atyfb_atari_probe(void) | |||
| 		} | ||||
| 
 | ||||
| 		/* 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: | ||||
| 			par->pci_id = PCI_CHIP_MACH64GX; | ||||
| 			break; | ||||
|  |  | |||
|  | @ -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); | ||||
| 	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 | ||||
| 	/* 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); | ||||
|           } | ||||
|         } else { | ||||
|           tmp = INREG(CONFIG_MEMSIZE); | ||||
|           tmp = INREG(CNFG_MEMSIZE); | ||||
|         } | ||||
| 
 | ||||
| 	/* 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 | ||||
|  | @ -2228,7 +2228,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev, | |||
| 	 */ | ||||
| 	rinfo->errata = 0; | ||||
| 	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) | ||||
| 		rinfo->errata |= CHIP_ERRATA_R300_CG; | ||||
| 
 | ||||
|  |  | |||
|  | @ -333,7 +333,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) | |||
| 	if (!rinfo->has_CRTC2) { | ||||
|                 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_HDP		| SCLK_CNTL__FORCE_DISP1 | | ||||
| 			 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*/ | ||||
| 	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) && | ||||
| 	     ((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_VIP; | ||||
| 	} | ||||
|  | @ -486,7 +486,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) | |||
| 		/* RV200::A11 A12 RV250::A11 A12 */ | ||||
| 		if (((rinfo->family == CHIP_FAMILY_RV200) || | ||||
| 		     (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; | ||||
| 
 | ||||
| 		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 */ | ||||
| 	if (((rinfo->family == CHIP_FAMILY_RV200) || | ||||
| 	     (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 |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE; | ||||
| 		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(MC_AGP_LOCATION, rinfo->save_regs[32]); | ||||
| 	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_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(MC_FB_LOCATION, rinfo->save_regs[30]); | ||||
| 	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_CNTL1, rinfo->save_regs[14]); | ||||
| 	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_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/); | ||||
| 	OUTREG(MC_IND_INDEX, 0); | ||||
| 	OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); | ||||
| 	OUTREG(CNFG_MEMSIZE, rinfo->video_ram); | ||||
| 
 | ||||
| 	mdelay(20); | ||||
| } | ||||
|  | @ -2361,7 +2361,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) | |||
| 	OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249); | ||||
| 	OUTREG(MC_IND_INDEX, 0); | ||||
| 
 | ||||
| 	OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); | ||||
| 	OUTREG(CNFG_MEMSIZE, rinfo->video_ram); | ||||
| 
 | ||||
| 	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) | ||||
| { | ||||
| 	u16 pwr_cmd; | ||||
| 	u32 tmp; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (!rinfo->pm_reg) | ||||
| 		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. */ | ||||
| 		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 { | ||||
| 		printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", | ||||
| 		       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) { | ||||
| 			/* Reset the SDRAM controller  */ | ||||
| 			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) | ||||
| { | ||||
|         struct fb_info *info = pci_get_drvdata(pdev); | ||||
|         struct radeonfb_info *rinfo = info->par; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (mesg.event == pdev->dev.power.power_state.event) | ||||
| 		return 0; | ||||
|  | @ -2674,6 +2627,11 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) | |||
| 	pmac_suspend_agp_for_card(pdev); | ||||
| #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
 | ||||
| 	 * space | ||||
| 	 */ | ||||
|  | @ -2698,9 +2656,6 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) | |||
| 			mdelay(20); | ||||
| 			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); | ||||
| 	} | ||||
| 	/* 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; | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
|         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", | ||||
| 	       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) { | ||||
| 		/* 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) | ||||
| 				rinfo->reinit_func(rinfo); | ||||
| 			else { | ||||
|  |  | |||
|  | @ -361,8 +361,6 @@ struct radeonfb_info { | |||
| #ifdef CONFIG_FB_RADEON_I2C | ||||
| 	struct radeon_i2c_chan 	i2c[4]; | ||||
| #endif | ||||
| 
 | ||||
| 	u32			cfg_save[64]; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ obj-$(CONFIG_BACKLIGHT_OMAP1)	+= omap1_bl.o | |||
| obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o | ||||
| obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.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_TOSA)	+= tosa_bl.o | ||||
| obj-$(CONFIG_BACKLIGHT_SAHARA)	+= kb3886_bl.o | ||||
|  |  | |||
|  | @ -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); | ||||
| 	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)); | ||||
| 	rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL); | ||||
| 	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.blue, cmap->blue, 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; | ||||
| 	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); | ||||
| out1: | ||||
| 	unlock_fb_info(info); | ||||
| out: | ||||
| 	fb_dealloc_cmap(&umap); | ||||
| 	return rc; | ||||
| } | ||||
|  |  | |||
|  | @ -1013,132 +1013,139 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
| 	struct fb_var_screeninfo var; | ||||
| 	struct fb_fix_screeninfo fix; | ||||
| 	struct fb_con2fbmap con2fb; | ||||
| 	struct fb_cmap cmap_from; | ||||
| 	struct fb_cmap_user cmap; | ||||
| 	struct fb_event event; | ||||
| 	void __user *argp = (void __user *)arg; | ||||
| 	long ret = 0; | ||||
| 
 | ||||
| 	fb = info->fbops; | ||||
| 	if (!fb) | ||||
| 		return -ENODEV; | ||||
| 
 | ||||
| 	switch (cmd) { | ||||
| 	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; | ||||
| 	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(); | ||||
| 		info->flags |= FBINFO_MISC_USEREVENT; | ||||
| 		ret = fb_set_var(info, &var); | ||||
| 		info->flags &= ~FBINFO_MISC_USEREVENT; | ||||
| 		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; | ||||
| 		break; | ||||
| 	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; | ||||
| 	case FBIOPUTCMAP: | ||||
| 		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; | ||||
| 	case FBIOGETCMAP: | ||||
| 		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; | ||||
| 	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(); | ||||
| 		ret = fb_pan_display(info, &var); | ||||
| 		release_console_sem(); | ||||
| 		unlock_fb_info(info); | ||||
| 		if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) | ||||
| 			ret = -EFAULT; | ||||
| 			return -EFAULT; | ||||
| 		break; | ||||
| 	case FBIO_CURSOR: | ||||
| 		ret = -EINVAL; | ||||
| 		break; | ||||
| 	case FBIOGET_CON2FBMAP: | ||||
| 		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; | ||||
| 	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]) | ||||
| 			request_module("fb%d", con2fb.framebuffer); | ||||
| 		if (!registered_fb[con2fb.framebuffer]) { | ||||
| 			ret = -EINVAL; | ||||
| 			break; | ||||
| 		} | ||||
| 		event.info = info; | ||||
| 		event.data = &con2fb; | ||||
| 		if (!lock_fb_info(info)) | ||||
| 			return -ENODEV; | ||||
| 		event.info = info; | ||||
| 		ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, | ||||
| 					      &event); | ||||
| 		unlock_fb_info(info); | ||||
| 		break; | ||||
| 	case FBIOBLANK: | ||||
| 		if (!lock_fb_info(info)) | ||||
| 			return -ENODEV; | ||||
| 		acquire_console_sem(); | ||||
| 		info->flags |= FBINFO_MISC_USEREVENT; | ||||
| 		ret = fb_blank(info, arg); | ||||
| 		info->flags &= ~FBINFO_MISC_USEREVENT; | ||||
| 		release_console_sem(); | ||||
| 		break;; | ||||
| 		unlock_fb_info(info); | ||||
| 		break; | ||||
| 	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); | ||||
| 		else | ||||
| 			ret = -ENOTTY; | ||||
| 		unlock_fb_info(info); | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| 	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 | ||||
|  | @ -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, | ||||
| 			    unsigned long arg) | ||||
| __acquires(&info->lock) | ||||
| __releases(&info->lock) | ||||
| { | ||||
| 	struct inode *inode = file->f_path.dentry->d_inode; | ||||
| 	int fbidx = iminor(inode); | ||||
|  | @ -1266,7 +1271,6 @@ __releases(&info->lock) | |||
| 	struct fb_ops *fb = info->fbops; | ||||
| 	long ret = -ENOIOCTLCMD; | ||||
| 
 | ||||
| 	mutex_lock(&info->lock); | ||||
| 	switch(cmd) { | ||||
| 	case FBIOGET_VSCREENINFO: | ||||
| 	case FBIOPUT_VSCREENINFO: | ||||
|  | @ -1292,7 +1296,6 @@ __releases(&info->lock) | |||
| 			ret = fb->fb_compat_ioctl(info, cmd, arg); | ||||
| 		break; | ||||
| 	} | ||||
| 	mutex_unlock(&info->lock); | ||||
| 	return ret; | ||||
| } | ||||
| #endif | ||||
|  |  | |||
|  | @ -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 | ||||
| 	 * 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 word; | ||||
| 		mm_segment_t fs = get_fs(); | ||||
| 		/*
 | ||||
| 		 * 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_MAG2] = ELFMAG2; | ||||
| 		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; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,3 +16,16 @@ config BTRFS_FS | |||
| 	  module will be called btrfs. | ||||
| 
 | ||||
| 	  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 | ||||
|  |  | |||
|  | @ -16,11 +16,11 @@ | |||
|  * Boston, MA 021110-1307, USA. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/version.h> | ||||
| #include <linux/kthread.h> | ||||
| #include <linux/list.h> | ||||
| #include <linux/spinlock.h> | ||||
| # include <linux/freezer.h> | ||||
| #include <linux/freezer.h> | ||||
| #include <linux/ftrace.h> | ||||
| #include "async-thread.h" | ||||
| 
 | ||||
| #define WORK_QUEUED_BIT 0 | ||||
|  | @ -143,6 +143,7 @@ static int worker_loop(void *arg) | |||
| 	struct btrfs_work *work; | ||||
| 	do { | ||||
| 		spin_lock_irq(&worker->lock); | ||||
| again_locked: | ||||
| 		while (!list_empty(&worker->pending)) { | ||||
| 			cur = worker->pending.next; | ||||
| 			work = list_entry(cur, struct btrfs_work, list); | ||||
|  | @ -165,14 +166,50 @@ static int worker_loop(void *arg) | |||
| 			check_idle_worker(worker); | ||||
| 
 | ||||
| 		} | ||||
| 		worker->working = 0; | ||||
| 		if (freezing(current)) { | ||||
| 			worker->working = 0; | ||||
| 			spin_unlock_irq(&worker->lock); | ||||
| 			refrigerator(); | ||||
| 		} else { | ||||
| 			set_current_state(TASK_INTERRUPTIBLE); | ||||
| 			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(); | ||||
| 			} | ||||
| 			__set_current_state(TASK_RUNNING); | ||||
| 		} | ||||
| 	} while (!kthread_should_stop()); | ||||
|  | @ -350,13 +387,14 @@ int btrfs_requeue_work(struct btrfs_work *work) | |||
| { | ||||
| 	struct btrfs_worker_thread *worker = work->worker; | ||||
| 	unsigned long flags; | ||||
| 	int wake = 0; | ||||
| 
 | ||||
| 	if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags)) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	spin_lock_irqsave(&worker->lock, flags); | ||||
| 	atomic_inc(&worker->num_pending); | ||||
| 	list_add_tail(&work->list, &worker->pending); | ||||
| 	atomic_inc(&worker->num_pending); | ||||
| 
 | ||||
| 	/* by definition we're busy, take ourselves off the idle
 | ||||
| 	 * list | ||||
|  | @ -368,10 +406,16 @@ int btrfs_requeue_work(struct btrfs_work *work) | |||
| 			       &worker->workers->worker_list); | ||||
| 		spin_unlock_irqrestore(&worker->workers->lock, flags); | ||||
| 	} | ||||
| 	if (!worker->working) { | ||||
| 		wake = 1; | ||||
| 		worker->working = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	spin_unlock_irqrestore(&worker->lock, flags); | ||||
| 
 | ||||
| 	if (wake) | ||||
| 		wake_up_process(worker->task); | ||||
| out: | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -398,9 +442,10 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) | |||
| 	} | ||||
| 
 | ||||
| 	spin_lock_irqsave(&worker->lock, flags); | ||||
| 
 | ||||
| 	list_add_tail(&work->list, &worker->pending); | ||||
| 	atomic_inc(&worker->num_pending); | ||||
| 	check_busy_worker(worker); | ||||
| 	list_add_tail(&work->list, &worker->pending); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * avoid calling into wake_up_process if this thread has already | ||||
|  |  | |||
|  | @ -32,7 +32,6 @@ | |||
| #include <linux/swap.h> | ||||
| #include <linux/writeback.h> | ||||
| #include <linux/bit_spinlock.h> | ||||
| #include <linux/version.h> | ||||
| #include <linux/pagevec.h> | ||||
| #include "compat.h" | ||||
| #include "ctree.h" | ||||
|  |  | |||
							
								
								
									
										280
									
								
								fs/btrfs/ctree.c
									
										
									
									
									
								
							
							
						
						
									
										280
									
								
								fs/btrfs/ctree.c
									
										
									
									
									
								
							|  | @ -54,6 +54,31 @@ struct btrfs_path *btrfs_alloc_path(void) | |||
| 	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 */ | ||||
| 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)) | ||||
| 		return PTR_ERR(cow); | ||||
| 
 | ||||
| 	/* cow is set to blocking by btrfs_init_new_buffer */ | ||||
| 
 | ||||
| 	copy_extent_buffer(cow, buf, 0, 0, cow->len); | ||||
| 	btrfs_set_header_bytenr(cow, cow->start); | ||||
| 	btrfs_set_header_generation(cow, trans->transid); | ||||
|  | @ -388,17 +415,20 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
| 		WARN_ON(1); | ||||
| 	} | ||||
| 
 | ||||
| 	spin_lock(&root->fs_info->hash_lock); | ||||
| 	if (btrfs_header_generation(buf) == trans->transid && | ||||
| 	    btrfs_header_owner(buf) == root->root_key.objectid && | ||||
| 	    !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { | ||||
| 		*cow_ret = buf; | ||||
| 		spin_unlock(&root->fs_info->hash_lock); | ||||
| 		WARN_ON(prealloc_dest); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	spin_unlock(&root->fs_info->hash_lock); | ||||
| 
 | ||||
| 	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, | ||||
| 				 parent_slot, cow_ret, search_start, 0, | ||||
| 				 prealloc_dest); | ||||
|  | @ -504,6 +534,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
| 	if (parent_nritems == 1) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	btrfs_set_lock_blocking(parent); | ||||
| 
 | ||||
| 	for (i = start_slot; i < end_slot; i++) { | ||||
| 		int close = 1; | ||||
| 
 | ||||
|  | @ -564,6 +596,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
| 			search_start = last_block; | ||||
| 
 | ||||
| 		btrfs_tree_lock(cur); | ||||
| 		btrfs_set_lock_blocking(cur); | ||||
| 		err = __btrfs_cow_block(trans, root, cur, parent, i, | ||||
| 					&cur, search_start, | ||||
| 					min(16 * blocksize, | ||||
|  | @ -862,6 +895,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 		return 0; | ||||
| 
 | ||||
| 	mid = path->nodes[level]; | ||||
| 
 | ||||
| 	WARN_ON(!path->locks[level]); | ||||
| 	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 */ | ||||
| 		child = read_node_slot(root, mid, 0); | ||||
| 		btrfs_tree_lock(child); | ||||
| 		btrfs_set_lock_blocking(child); | ||||
| 		BUG_ON(!child); | ||||
| 		ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0); | ||||
| 		BUG_ON(ret); | ||||
|  | @ -900,6 +935,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 
 | ||||
| 		add_root_to_dirty_list(root); | ||||
| 		btrfs_tree_unlock(child); | ||||
| 
 | ||||
| 		path->locks[level] = 0; | ||||
| 		path->nodes[level] = NULL; | ||||
| 		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); | ||||
| 	if (left) { | ||||
| 		btrfs_tree_lock(left); | ||||
| 		btrfs_set_lock_blocking(left); | ||||
| 		wret = btrfs_cow_block(trans, root, left, | ||||
| 				       parent, pslot - 1, &left, 0); | ||||
| 		if (wret) { | ||||
|  | @ -934,6 +971,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 	right = read_node_slot(root, parent, pslot + 1); | ||||
| 	if (right) { | ||||
| 		btrfs_tree_lock(right); | ||||
| 		btrfs_set_lock_blocking(right); | ||||
| 		wret = btrfs_cow_block(trans, root, right, | ||||
| 				       parent, pslot + 1, &right, 0); | ||||
| 		if (wret) { | ||||
|  | @ -1109,6 +1147,8 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
| 		u32 left_nr; | ||||
| 
 | ||||
| 		btrfs_tree_lock(left); | ||||
| 		btrfs_set_lock_blocking(left); | ||||
| 
 | ||||
| 		left_nr = btrfs_header_nritems(left); | ||||
| 		if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { | ||||
| 			wret = 1; | ||||
|  | @ -1155,7 +1195,10 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
| 	 */ | ||||
| 	if (right) { | ||||
| 		u32 right_nr; | ||||
| 
 | ||||
| 		btrfs_tree_lock(right); | ||||
| 		btrfs_set_lock_blocking(right); | ||||
| 
 | ||||
| 		right_nr = btrfs_header_nritems(right); | ||||
| 		if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { | ||||
| 			wret = 1; | ||||
|  | @ -1210,8 +1253,7 @@ static noinline void reada_for_search(struct btrfs_root *root, | |||
| 	struct btrfs_disk_key disk_key; | ||||
| 	u32 nritems; | ||||
| 	u64 search; | ||||
| 	u64 lowest_read; | ||||
| 	u64 highest_read; | ||||
| 	u64 target; | ||||
| 	u64 nread = 0; | ||||
| 	int direction = path->reada; | ||||
| 	struct extent_buffer *eb; | ||||
|  | @ -1235,8 +1277,7 @@ static noinline void reada_for_search(struct btrfs_root *root, | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	highest_read = search; | ||||
| 	lowest_read = search; | ||||
| 	target = search; | ||||
| 
 | ||||
| 	nritems = btrfs_header_nritems(node); | ||||
| 	nr = slot; | ||||
|  | @ -1256,27 +1297,80 @@ static noinline void reada_for_search(struct btrfs_root *root, | |||
| 				break; | ||||
| 		} | ||||
| 		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, | ||||
| 				     btrfs_node_ptr_generation(node, nr)); | ||||
| 			nread += blocksize; | ||||
| 		} | ||||
| 		nscan++; | ||||
| 		if (path->reada < 2 && (nread > (64 * 1024) || nscan > 32)) | ||||
| 		if ((nread > 65536 || nscan > 32)) | ||||
| 			break; | ||||
| 
 | ||||
| 		if (nread > (256 * 1024) || nscan > 128) | ||||
| 			break; | ||||
| 
 | ||||
| 		if (search < lowest_read) | ||||
| 			lowest_read = search; | ||||
| 		if (search > highest_read) | ||||
| 			highest_read = search; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 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; | ||||
| 
 | ||||
| 	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 | ||||
|  * 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 | ||||
|  * if key is found, we return zero and you can find the item in the leaf | ||||
|  | @ -1387,31 +1507,30 @@ again: | |||
| 			int wret; | ||||
| 
 | ||||
| 			/* is a cow on this block not required */ | ||||
| 			spin_lock(&root->fs_info->hash_lock); | ||||
| 			if (btrfs_header_generation(b) == trans->transid && | ||||
| 			    btrfs_header_owner(b) == root->root_key.objectid && | ||||
| 			    !btrfs_header_flag(b, BTRFS_HEADER_FLAG_WRITTEN)) { | ||||
| 				spin_unlock(&root->fs_info->hash_lock); | ||||
| 				goto cow_done; | ||||
| 			} | ||||
| 			spin_unlock(&root->fs_info->hash_lock); | ||||
| 
 | ||||
| 			/* ok, we have to cow, is our old prealloc the right
 | ||||
| 			 * size? | ||||
| 			 */ | ||||
| 			if (prealloc_block.objectid && | ||||
| 			    prealloc_block.offset != b->len) { | ||||
| 				btrfs_release_path(root, p); | ||||
| 				btrfs_free_reserved_extent(root, | ||||
| 					   prealloc_block.objectid, | ||||
| 					   prealloc_block.offset); | ||||
| 				prealloc_block.objectid = 0; | ||||
| 				goto again; | ||||
| 			} | ||||
| 
 | ||||
| 			/*
 | ||||
| 			 * for higher level blocks, try not to allocate blocks | ||||
| 			 * 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)) { | ||||
| 				u32 size = b->len; | ||||
| 				u64 hint = b->start; | ||||
|  | @ -1425,6 +1544,8 @@ again: | |||
| 				goto again; | ||||
| 			} | ||||
| 
 | ||||
| 			btrfs_set_path_blocking(p); | ||||
| 
 | ||||
| 			wret = btrfs_cow_block(trans, root, b, | ||||
| 					       p->nodes[level + 1], | ||||
| 					       p->slots[level + 1], | ||||
|  | @ -1446,6 +1567,22 @@ cow_done: | |||
| 		if (!p->skip_locking) | ||||
| 			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); | ||||
| 		if (ret) { | ||||
| 			ret = -1; | ||||
|  | @ -1453,6 +1590,7 @@ cow_done: | |||
| 		} | ||||
| 
 | ||||
| 		ret = bin_search(b, key, level, &slot); | ||||
| 
 | ||||
| 		if (level != 0) { | ||||
| 			if (ret && slot > 0) | ||||
| 				slot -= 1; | ||||
|  | @ -1460,7 +1598,16 @@ cow_done: | |||
| 			if ((p->search_for_split || ins_len > 0) && | ||||
| 			    btrfs_header_nritems(b) >= | ||||
| 			    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); | ||||
| 				if (sret) { | ||||
| 					ret = sret; | ||||
|  | @ -1468,9 +1615,19 @@ cow_done: | |||
| 				} | ||||
| 				b = p->nodes[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) { | ||||
| 					ret = sret; | ||||
| 					goto done; | ||||
|  | @ -1504,7 +1661,7 @@ cow_done: | |||
| 				 * of the btree by dropping locks before | ||||
| 				 * we read. | ||||
| 				 */ | ||||
| 				if (level > 1) { | ||||
| 				if (level > 0) { | ||||
| 					btrfs_release_path(NULL, p); | ||||
| 					if (tmp) | ||||
| 						free_extent_buffer(tmp); | ||||
|  | @ -1519,6 +1676,7 @@ cow_done: | |||
| 						free_extent_buffer(tmp); | ||||
| 					goto again; | ||||
| 				} else { | ||||
| 					btrfs_set_path_blocking(p); | ||||
| 					if (tmp) | ||||
| 						free_extent_buffer(tmp); | ||||
| 					if (should_reada) | ||||
|  | @ -1528,14 +1686,29 @@ cow_done: | |||
| 					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 { | ||||
| 			p->slots[level] = slot; | ||||
| 			if (ins_len > 0 && | ||||
| 			    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); | ||||
| 				btrfs_clear_path_blocking(p); | ||||
| 
 | ||||
| 				BUG_ON(sret > 0); | ||||
| 				if (sret) { | ||||
| 					ret = sret; | ||||
|  | @ -1549,12 +1722,16 @@ cow_done: | |||
| 	} | ||||
| 	ret = 1; | ||||
| 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) { | ||||
| 		btrfs_free_reserved_extent(root, | ||||
| 			   prealloc_block.objectid, | ||||
| 			   prealloc_block.offset); | ||||
| 	} | ||||
| 
 | ||||
| 	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); | ||||
| 	BUG_ON(ret); | ||||
| 
 | ||||
| 	btrfs_set_lock_blocking(eb); | ||||
| 
 | ||||
| 	parent = eb; | ||||
| 	while (1) { | ||||
| 		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, | ||||
| 					     generation); | ||||
| 			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, | ||||
| 						generation); | ||||
| 				btrfs_tree_lock(eb); | ||||
| 				btrfs_set_lock_blocking(eb); | ||||
| 			} | ||||
| 
 | ||||
| 			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); | ||||
| 	btrfs_tree_lock(right); | ||||
| 	btrfs_set_lock_blocking(right); | ||||
| 
 | ||||
| 	free_space = btrfs_leaf_free_space(root, right); | ||||
| 	if (free_space < data_size) | ||||
| 		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); | ||||
| 	btrfs_tree_lock(left); | ||||
| 	btrfs_set_lock_blocking(left); | ||||
| 
 | ||||
| 	free_space = btrfs_leaf_free_space(root, left); | ||||
| 	if (free_space < data_size) { | ||||
| 		ret = 1; | ||||
|  | @ -2825,6 +3010,12 @@ int btrfs_split_item(struct btrfs_trans_handle *trans, | |||
| 	path->keep_locks = 0; | ||||
| 	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]; | ||||
| 	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(); | ||||
| 	} | ||||
| out: | ||||
| 	btrfs_unlock_up_safe(path, 1); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
|  | @ -3441,15 +3633,22 @@ noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans, | |||
| { | ||||
| 	int ret; | ||||
| 	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]); | ||||
| 	if (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, | ||||
| 				btrfs_level_size(root, 0), | ||||
| 				path->nodes[1]->start, | ||||
| 				btrfs_header_owner(path->nodes[1]), | ||||
| 				parent_start, parent_owner, | ||||
| 				root_gen, 0, 1); | ||||
| 	return ret; | ||||
| } | ||||
|  | @ -3721,12 +3920,14 @@ find_next_key: | |||
| 		 */ | ||||
| 		if (slot >= nritems) { | ||||
| 			path->slots[level] = slot; | ||||
| 			btrfs_set_path_blocking(path); | ||||
| 			sret = btrfs_find_next_key(root, path, min_key, level, | ||||
| 						  cache_only, min_trans); | ||||
| 			if (sret == 0) { | ||||
| 				btrfs_release_path(root, path); | ||||
| 				goto again; | ||||
| 			} else { | ||||
| 				btrfs_clear_path_blocking(path); | ||||
| 				goto out; | ||||
| 			} | ||||
| 		} | ||||
|  | @ -3738,16 +3939,20 @@ find_next_key: | |||
| 			unlock_up(path, level, 1); | ||||
| 			goto out; | ||||
| 		} | ||||
| 		btrfs_set_path_blocking(path); | ||||
| 		cur = read_node_slot(root, cur, slot); | ||||
| 
 | ||||
| 		btrfs_tree_lock(cur); | ||||
| 
 | ||||
| 		path->locks[level - 1] = 1; | ||||
| 		path->nodes[level - 1] = cur; | ||||
| 		unlock_up(path, level, 1); | ||||
| 		btrfs_clear_path_blocking(path); | ||||
| 	} | ||||
| out: | ||||
| 	if (ret == 0) | ||||
| 		memcpy(min_key, &found_key, sizeof(found_key)); | ||||
| 	btrfs_set_path_blocking(path); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
|  | @ -3843,6 +4048,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	btrfs_set_path_blocking(path); | ||||
| 	nritems = btrfs_header_nritems(path->nodes[0]); | ||||
| 	/*
 | ||||
| 	 * 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); | ||||
| 		} | ||||
| 
 | ||||
| 		/* the path was set to blocking above */ | ||||
| 		if (level == 1 && (path->locks[1] || path->skip_locking) && | ||||
| 		    path->reada) | ||||
| 			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) { | ||||
| 			WARN_ON(!btrfs_tree_locked(c)); | ||||
| 			btrfs_tree_lock(next); | ||||
| 			btrfs_set_lock_blocking(next); | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
|  | @ -3897,12 +4105,15 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
| 			path->locks[level] = 1; | ||||
| 		if (!level) | ||||
| 			break; | ||||
| 
 | ||||
| 		btrfs_set_path_blocking(path); | ||||
| 		if (level == 1 && path->locks[1] && path->reada) | ||||
| 			reada_for_search(root, path, level, slot, 0); | ||||
| 		next = read_node_slot(root, next, 0); | ||||
| 		if (!path->skip_locking) { | ||||
| 			WARN_ON(!btrfs_tree_locked(path->nodes[level])); | ||||
| 			btrfs_tree_lock(next); | ||||
| 			btrfs_set_lock_blocking(next); | ||||
| 		} | ||||
| 	} | ||||
| done: | ||||
|  | @ -3927,6 +4138,7 @@ int btrfs_previous_item(struct btrfs_root *root, | |||
| 
 | ||||
| 	while (1) { | ||||
| 		if (path->slots[0] == 0) { | ||||
| 			btrfs_set_path_blocking(path); | ||||
| 			ret = btrfs_prev_leaf(root, path); | ||||
| 			if (ret != 0) | ||||
| 				return ret; | ||||
|  |  | |||
|  | @ -454,17 +454,11 @@ struct btrfs_timespec { | |||
| 	__le32 nsec; | ||||
| } __attribute__ ((__packed__)); | ||||
| 
 | ||||
| typedef enum { | ||||
| enum btrfs_compression_type { | ||||
| 	BTRFS_COMPRESS_NONE = 0, | ||||
| 	BTRFS_COMPRESS_ZLIB = 1, | ||||
| 	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 { | ||||
| 	/* nfs style generation number */ | ||||
|  | @ -701,9 +695,7 @@ struct btrfs_fs_info { | |||
| 	struct btrfs_transaction *running_transaction; | ||||
| 	wait_queue_head_t transaction_throttle; | ||||
| 	wait_queue_head_t transaction_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_for_commit; | ||||
|  | @ -711,7 +703,6 @@ struct btrfs_fs_info { | |||
| 	struct super_block *sb; | ||||
| 	struct inode *btree_inode; | ||||
| 	struct backing_dev_info bdi; | ||||
| 	spinlock_t hash_lock; | ||||
| 	struct mutex trans_mutex; | ||||
| 	struct mutex tree_log_mutex; | ||||
| 	struct mutex transaction_kthread_mutex; | ||||
|  | @ -730,10 +721,6 @@ struct btrfs_fs_info { | |||
| 	atomic_t async_submit_draining; | ||||
| 	atomic_t nr_async_bios; | ||||
| 	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 | ||||
|  | @ -833,7 +820,14 @@ struct btrfs_root { | |||
| 	struct kobject root_kobj; | ||||
| 	struct completion kobj_unregister; | ||||
| 	struct mutex objectid_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 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); | ||||
| void btrfs_free_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, | ||||
| 		   struct btrfs_path *path, int slot, int nr); | ||||
| int btrfs_del_leaf(struct btrfs_trans_handle *trans, | ||||
|  |  | |||
|  | @ -16,7 +16,6 @@ | |||
|  * Boston, MA 021110-1307, USA. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/version.h> | ||||
| #include <linux/fs.h> | ||||
| #include <linux/blkdev.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); | ||||
| 
 | ||||
| 	if (ret == 0) | ||||
| 		buf->flags |= EXTENT_UPTODATE; | ||||
| 		set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags); | ||||
| 	else | ||||
| 		WARN_ON(1); | ||||
| 	return buf; | ||||
|  | @ -814,6 +813,10 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 	if (btrfs_header_generation(buf) == | ||||
| 	    root->fs_info->running_transaction->transid) { | ||||
| 		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, | ||||
| 					  buf); | ||||
| 	} | ||||
|  | @ -850,6 +853,14 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
| 	spin_lock_init(&root->list_lock); | ||||
| 	mutex_init(&root->objectid_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, | ||||
| 			     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; | ||||
| } | ||||
| 
 | ||||
| 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 *tree_root = fs_info->tree_root; | ||||
| 	struct extent_buffer *leaf; | ||||
| 
 | ||||
| 	root = kzalloc(sizeof(*root), GFP_NOFS); | ||||
| 	if (!root) | ||||
| 		return -ENOMEM; | ||||
| 		return ERR_PTR(-ENOMEM); | ||||
| 
 | ||||
| 	__setup_root(tree_root->nodesize, tree_root->leafsize, | ||||
| 		     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.type = BTRFS_ROOT_ITEM_KEY; | ||||
| 	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->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_level(root->node, 0); | ||||
| 	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_mark_buffer_dirty(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; | ||||
| } | ||||
| 
 | ||||
|  | @ -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; | ||||
| 	int ret = 0; | ||||
| 	struct list_head *cur; | ||||
| 	struct btrfs_device *device; | ||||
| 	struct backing_dev_info *bdi; | ||||
| #if 0 | ||||
|  | @ -1144,8 +1207,7 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) | |||
| 	    btrfs_congested_async(info, 0)) | ||||
| 		return 1; | ||||
| #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) | ||||
| 			continue; | ||||
| 		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) | ||||
| { | ||||
| 	struct list_head *cur; | ||||
| 	struct btrfs_device *device; | ||||
| 	struct btrfs_fs_info *info; | ||||
| 
 | ||||
| 	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) | ||||
| 			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->hashers); | ||||
| 	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->new_trans_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_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, | ||||
| 		     fs_info, BTRFS_ROOT_TREE_OBJECTID); | ||||
|  | @ -1627,6 +1682,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 	 * low idle thresh | ||||
| 	 */ | ||||
| 	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_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->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, | ||||
| 					       "btrfs-cleaner"); | ||||
| 	if (!fs_info->cleaner_kthread) | ||||
| 	if (IS_ERR(fs_info->cleaner_kthread)) | ||||
| 		goto fail_csum_root; | ||||
| 
 | ||||
| 	fs_info->transaction_kthread = kthread_run(transaction_kthread, | ||||
| 						   tree_root, | ||||
| 						   "btrfs-transaction"); | ||||
| 	if (!fs_info->transaction_kthread) | ||||
| 	if (IS_ERR(fs_info->transaction_kthread)) | ||||
| 		goto fail_cleaner; | ||||
| 
 | ||||
| 	if (btrfs_super_log_root(disk_super) != 0) { | ||||
|  | @ -1828,13 +1885,14 @@ fail_sb_buffer: | |||
| fail_iput: | ||||
| 	invalidate_inode_pages2(fs_info->btree_inode->i_mapping); | ||||
| 	iput(fs_info->btree_inode); | ||||
| fail: | ||||
| 
 | ||||
| 	btrfs_close_devices(fs_info->fs_devices); | ||||
| 	btrfs_mapping_tree_free(&fs_info->mapping_tree); | ||||
| 	bdi_destroy(&fs_info->bdi); | ||||
| 
 | ||||
| fail: | ||||
| 	kfree(extent_root); | ||||
| 	kfree(tree_root); | ||||
| 	bdi_destroy(&fs_info->bdi); | ||||
| 	kfree(fs_info); | ||||
| 	kfree(chunk_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) | ||||
| { | ||||
| 	struct list_head *cur; | ||||
| 	struct list_head *head = &root->fs_info->fs_devices->devices; | ||||
| 	struct btrfs_device *dev; | ||||
| 	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; | ||||
| 	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) { | ||||
| 			total_errors++; | ||||
| 			continue; | ||||
|  | @ -2045,8 +2101,7 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors) | |||
| 	} | ||||
| 
 | ||||
| 	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) | ||||
| 			continue; | ||||
| 		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); | ||||
| 	struct inode *btree_inode = root->fs_info->btree_inode; | ||||
| 
 | ||||
| 	btrfs_set_lock_blocking(buf); | ||||
| 
 | ||||
| 	WARN_ON(!btrfs_tree_locked(buf)); | ||||
| 	if (transid != root->fs_info->generation) { | ||||
| 		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; | ||||
| 	ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid); | ||||
| 	if (ret == 0) | ||||
| 		buf->flags |= EXTENT_UPTODATE; | ||||
| 		set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int btree_lock_page_hook(struct page *page) | ||||
| { | ||||
| 	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_buffer *eb; | ||||
| 	unsigned long len; | ||||
|  | @ -2324,9 +2380,7 @@ int btree_lock_page_hook(struct page *page) | |||
| 		goto out; | ||||
| 
 | ||||
| 	btrfs_tree_lock(eb); | ||||
| 	spin_lock(&root->fs_info->hash_lock); | ||||
| 	btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); | ||||
| 	spin_unlock(&root->fs_info->hash_lock); | ||||
| 	btrfs_tree_unlock(eb); | ||||
| 	free_extent_buffer(eb); | ||||
| out: | ||||
|  |  | |||
|  | @ -98,5 +98,7 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans, | |||
| 			     struct btrfs_fs_info *fs_info); | ||||
| int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, | ||||
| 			     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); | ||||
| #endif | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ | |||
| #include <linux/pagemap.h> | ||||
| #include <linux/writeback.h> | ||||
| #include <linux/blkdev.h> | ||||
| #include <linux/version.h> | ||||
| #include <linux/sort.h> | ||||
| #include "compat.h" | ||||
| #include "hash.h" | ||||
| #include "crc32c.h" | ||||
|  | @ -30,7 +30,6 @@ | |||
| #include "volumes.h" | ||||
| #include "locking.h" | ||||
| #include "ref-cache.h" | ||||
| #include "compat.h" | ||||
| 
 | ||||
| #define PENDING_EXTENT_INSERT 0 | ||||
| #define PENDING_EXTENT_DELETE 1 | ||||
|  | @ -326,10 +325,8 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, | |||
| 						  u64 flags) | ||||
| { | ||||
| 	struct list_head *head = &info->space_info; | ||||
| 	struct list_head *cur; | ||||
| 	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) | ||||
| 			return found; | ||||
| 	} | ||||
|  | @ -1525,15 +1522,55 @@ out: | |||
| 	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 ref_root; | ||||
| 	u64 orig_root; | ||||
| 	u64 ref_generation; | ||||
| 	u64 orig_generation; | ||||
| 	struct refsort *sorted; | ||||
| 	u32 nritems; | ||||
| 	u32 nr_file_extents = 0; | ||||
| 	struct btrfs_key key; | ||||
|  | @ -1542,6 +1579,8 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 	int level; | ||||
| 	int ret = 0; | ||||
| 	int faili = 0; | ||||
| 	int refi = 0; | ||||
| 	int slot; | ||||
| 	int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *, | ||||
| 			    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); | ||||
| 	level = btrfs_header_level(buf); | ||||
| 
 | ||||
| 	sorted = kmalloc(sizeof(struct refsort) * nritems, GFP_NOFS); | ||||
| 	BUG_ON(!sorted); | ||||
| 
 | ||||
| 	if (root->ref_cows) { | ||||
| 		process_func = __btrfs_inc_extent_ref; | ||||
| 	} else { | ||||
|  | @ -1565,6 +1607,11 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 		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++) { | ||||
| 		cond_resched(); | ||||
| 		if (level == 0) { | ||||
|  | @ -1581,6 +1628,32 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 				continue; | ||||
| 
 | ||||
| 			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, | ||||
| 					   orig_buf->start, buf->start, | ||||
|  | @ -1589,25 +1662,25 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 					   key.objectid); | ||||
| 
 | ||||
| 			if (ret) { | ||||
| 				faili = i; | ||||
| 				faili = slot; | ||||
| 				WARN_ON(1); | ||||
| 				goto fail; | ||||
| 			} | ||||
| 		} else { | ||||
| 			bytenr = btrfs_node_blockptr(buf, i); | ||||
| 			ret = process_func(trans, root, bytenr, | ||||
| 					   orig_buf->start, buf->start, | ||||
| 					   orig_root, ref_root, | ||||
| 					   orig_generation, ref_generation, | ||||
| 					   level - 1); | ||||
| 			if (ret) { | ||||
| 				faili = i; | ||||
| 				faili = slot; | ||||
| 				WARN_ON(1); | ||||
| 				goto fail; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| out: | ||||
| 	kfree(sorted); | ||||
| 	if (nr_extents) { | ||||
| 		if (level == 0) | ||||
| 			*nr_extents = nr_file_extents; | ||||
|  | @ -1616,6 +1689,7 @@ out: | |||
| 	} | ||||
| 	return 0; | ||||
| fail: | ||||
| 	kfree(sorted); | ||||
| 	WARN_ON(1); | ||||
| 	return ret; | ||||
| } | ||||
|  | @ -2159,7 +2233,8 @@ again: | |||
| 		ret = find_first_extent_bit(&info->extent_ins, search, &start, | ||||
| 					    &end, EXTENT_WRITEBACK); | ||||
| 		if (ret) { | ||||
| 			if (skipped && all && !num_inserts) { | ||||
| 			if (skipped && all && !num_inserts && | ||||
| 			    list_empty(&update_list)) { | ||||
| 				skipped = 0; | ||||
| 				search = 0; | ||||
| 				continue; | ||||
|  | @ -2547,6 +2622,7 @@ again: | |||
| 		if (ret) { | ||||
| 			if (all && skipped && !nr) { | ||||
| 				search = 0; | ||||
| 				skipped = 0; | ||||
| 				continue; | ||||
| 			} | ||||
| 			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 (owner_objectid < BTRFS_FIRST_FREE_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); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | @ -3014,7 +3086,6 @@ loop_check: | |||
| static void dump_space_info(struct btrfs_space_info *info, u64 bytes) | ||||
| { | ||||
| 	struct btrfs_block_group_cache *cache; | ||||
| 	struct list_head *l; | ||||
| 
 | ||||
| 	printk(KERN_INFO "space_info has %llu free, is %sfull\n", | ||||
| 	       (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 "); | ||||
| 
 | ||||
| 	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); | ||||
| 		printk(KERN_INFO "block group %llu has %llu bytes, %llu used " | ||||
| 		       "%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_tree_lock(buf); | ||||
| 	clean_tree_block(trans, root, buf); | ||||
| 
 | ||||
| 	btrfs_set_lock_blocking(buf); | ||||
| 	btrfs_set_buffer_uptodate(buf); | ||||
| 
 | ||||
| 	if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) { | ||||
| 		set_extent_dirty(&root->dirty_log_pages, buf->start, | ||||
| 			 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); | ||||
| 	} | ||||
| 	trans->blocks_used++; | ||||
| 	/* this returns a buffer locked for blocking */ | ||||
| 	return buf; | ||||
| } | ||||
| 
 | ||||
|  | @ -3388,36 +3462,73 @@ int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans, | |||
| { | ||||
| 	u64 leaf_owner; | ||||
| 	u64 leaf_generation; | ||||
| 	struct refsort *sorted; | ||||
| 	struct btrfs_key key; | ||||
| 	struct btrfs_file_extent_item *fi; | ||||
| 	int i; | ||||
| 	int nritems; | ||||
| 	int ret; | ||||
| 	int refi = 0; | ||||
| 	int slot; | ||||
| 
 | ||||
| 	BUG_ON(!btrfs_is_leaf(leaf)); | ||||
| 	nritems = btrfs_header_nritems(leaf); | ||||
| 	leaf_owner = btrfs_header_owner(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++) { | ||||
| 		u64 disk_bytenr; | ||||
| 		cond_resched(); | ||||
| 
 | ||||
| 		btrfs_item_key_to_cpu(leaf, &key, i); | ||||
| 
 | ||||
| 		/* only extents have references, skip everything else */ | ||||
| 		if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY) | ||||
| 			continue; | ||||
| 
 | ||||
| 		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) == | ||||
| 		    BTRFS_FILE_EXTENT_INLINE) | ||||
| 			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); | ||||
| 
 | ||||
| 		/* holes don't have refs */ | ||||
| 		if (disk_bytenr == 0) | ||||
| 			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, | ||||
| 				btrfs_file_extent_disk_num_bytes(leaf, fi), | ||||
| 				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); | ||||
| 		cond_resched(); | ||||
| 	} | ||||
| out: | ||||
| 	kfree(sorted); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -3437,9 +3550,25 @@ static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans, | |||
| { | ||||
| 	int i; | ||||
| 	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++) { | ||||
| 		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, | ||||
| 					  info->num_bytes, ref->bytenr, | ||||
| 					  ref->owner, ref->generation, | ||||
|  | @ -3453,6 +3582,7 @@ static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans, | |||
| 		info++; | ||||
| 	} | ||||
| 
 | ||||
| 	kfree(sorted); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -3496,6 +3626,152 @@ static int drop_snap_lookup_refcount(struct btrfs_root *root, u64 start, | |||
| 	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 | ||||
|  * 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 *cur; | ||||
| 	struct extent_buffer *parent; | ||||
| 	struct btrfs_leaf_ref *ref; | ||||
| 	u32 blocksize; | ||||
| 	int ret; | ||||
| 	u32 refs; | ||||
|  | @ -3538,17 +3813,46 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans, | |||
| 		if (path->slots[*level] >= | ||||
| 		    btrfs_header_nritems(cur)) | ||||
| 			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) { | ||||
| 			ret = btrfs_drop_leaf_ref(trans, root, cur); | ||||
| 			BUG_ON(ret); | ||||
| 			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]); | ||||
| 		ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]); | ||||
| 		blocksize = btrfs_level_size(root, *level - 1); | ||||
| 
 | ||||
| 		ret = drop_snap_lookup_refcount(root, bytenr, blocksize, &refs); | ||||
| 		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) { | ||||
| 			parent = path->nodes[*level]; | ||||
| 			root_owner = btrfs_header_owner(parent); | ||||
|  | @ -3567,46 +3871,12 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans, | |||
| 
 | ||||
| 			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 | ||||
| 		 */ | ||||
| 		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 | ||||
| 		} | ||||
| 		/*
 | ||||
| 		 * we need to keep freeing things in the next level down. | ||||
| 		 * read the block and loop around to process it | ||||
| 		 */ | ||||
| 		next = read_tree_block(root, bytenr, blocksize, ptr_gen); | ||||
| 		WARN_ON(*level <= 0); | ||||
| 		if (path->nodes[*level-1]) | ||||
| 			free_extent_buffer(path->nodes[*level-1]); | ||||
|  | @ -3631,11 +3901,16 @@ out: | |||
| 	root_owner = btrfs_header_owner(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, | ||||
| 				  parent->start, root_owner, root_gen, | ||||
| 				  *level, 1); | ||||
| 	free_extent_buffer(path->nodes[*level]); | ||||
| 	path->nodes[*level] = NULL; | ||||
| 
 | ||||
| 	*level += 1; | ||||
| 	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); | ||||
| 		btrfs_tree_lock(next); | ||||
| 		btrfs_set_lock_blocking(next); | ||||
| 
 | ||||
| 		ret = btrfs_lookup_extent_ref(trans, root, bytenr, blocksize, | ||||
| 					      &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) { | ||||
| 			struct extent_buffer *node; | ||||
| 			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]; | ||||
| 			path->slots[i]++; | ||||
| 			*level = i; | ||||
|  | @ -3765,6 +4048,11 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans, | |||
| 			return 0; | ||||
| 		} else { | ||||
| 			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) | ||||
| 				parent = path->nodes[*level]; | ||||
| 			else | ||||
|  | @ -4444,7 +4732,7 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans, | |||
| 	u64 lock_end = 0; | ||||
| 	u64 num_bytes; | ||||
| 	u64 ext_offset; | ||||
| 	u64 first_pos; | ||||
| 	u64 search_end = (u64)-1; | ||||
| 	u32 nritems; | ||||
| 	int nr_scaned = 0; | ||||
| 	int extent_locked = 0; | ||||
|  | @ -4452,7 +4740,6 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans, | |||
| 	int ret; | ||||
| 
 | ||||
| 	memcpy(&key, leaf_key, sizeof(key)); | ||||
| 	first_pos = INT_LIMIT(loff_t) - extent_key->offset; | ||||
| 	if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS) { | ||||
| 		if (key.objectid < ref_path->owner_objectid || | ||||
| 		    (key.objectid == ref_path->owner_objectid && | ||||
|  | @ -4501,7 +4788,7 @@ next: | |||
| 			if ((key.objectid > ref_path->owner_objectid) || | ||||
| 			    (key.objectid == ref_path->owner_objectid && | ||||
| 			     key.type > BTRFS_EXTENT_DATA_KEY) || | ||||
| 			    (key.offset >= first_pos + extent_key->offset)) | ||||
| 			    key.offset >= search_end) | ||||
| 				break; | ||||
| 		} | ||||
| 
 | ||||
|  | @ -4534,8 +4821,10 @@ next: | |||
| 		num_bytes = btrfs_file_extent_num_bytes(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) { | ||||
| 			lock_start = key.offset; | ||||
|  | @ -4724,7 +5013,7 @@ next: | |||
| 		} | ||||
| skip: | ||||
| 		if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS && | ||||
| 		    key.offset >= first_pos + extent_key->offset) | ||||
| 		    key.offset >= search_end) | ||||
| 			break; | ||||
| 
 | ||||
| 		cond_resched(); | ||||
|  | @ -4778,6 +5067,7 @@ int btrfs_reloc_tree_cache_ref(struct btrfs_trans_handle *trans, | |||
| 		ref->bytenr = buf->start; | ||||
| 		ref->owner = btrfs_header_owner(buf); | ||||
| 		ref->generation = btrfs_header_generation(buf); | ||||
| 
 | ||||
| 		ret = btrfs_add_leaf_ref(root, ref, 0); | ||||
| 		WARN_ON(ret); | ||||
| 		btrfs_free_leaf_ref(root, ref); | ||||
|  | @ -5957,9 +6247,11 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
| 	path = btrfs_alloc_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, | ||||
| 		 &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); | ||||
| 	list_del(&block_group->list); | ||||
| 	up_write(&block_group->space_info->groups_sem); | ||||
|  |  | |||
|  | @ -9,7 +9,6 @@ | |||
| #include <linux/spinlock.h> | ||||
| #include <linux/blkdev.h> | ||||
| #include <linux/swap.h> | ||||
| #include <linux/version.h> | ||||
| #include <linux/writeback.h> | ||||
| #include <linux/pagevec.h> | ||||
| #include "extent_io.h" | ||||
|  | @ -31,7 +30,7 @@ static LIST_HEAD(buffers); | |||
| static LIST_HEAD(states); | ||||
| 
 | ||||
| #define LEAK_DEBUG 0 | ||||
| #ifdef LEAK_DEBUG | ||||
| #if LEAK_DEBUG | ||||
| static DEFINE_SPINLOCK(leak_lock); | ||||
| #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) | ||||
| { | ||||
| 	struct extent_state *state; | ||||
| #ifdef LEAK_DEBUG | ||||
| #if LEAK_DEBUG | ||||
| 	unsigned long flags; | ||||
| #endif | ||||
| 
 | ||||
|  | @ -130,7 +129,7 @@ static struct extent_state *alloc_extent_state(gfp_t mask) | |||
| 	state->state = 0; | ||||
| 	state->private = 0; | ||||
| 	state->tree = NULL; | ||||
| #ifdef LEAK_DEBUG | ||||
| #if LEAK_DEBUG | ||||
| 	spin_lock_irqsave(&leak_lock, flags); | ||||
| 	list_add(&state->leak_list, &states); | ||||
| 	spin_unlock_irqrestore(&leak_lock, flags); | ||||
|  | @ -145,11 +144,11 @@ static void free_extent_state(struct extent_state *state) | |||
| 	if (!state) | ||||
| 		return; | ||||
| 	if (atomic_dec_and_test(&state->refs)) { | ||||
| #ifdef LEAK_DEBUG | ||||
| #if LEAK_DEBUG | ||||
| 		unsigned long flags; | ||||
| #endif | ||||
| 		WARN_ON(state->tree); | ||||
| #ifdef LEAK_DEBUG | ||||
| #if LEAK_DEBUG | ||||
| 		spin_lock_irqsave(&leak_lock, flags); | ||||
| 		list_del(&state->leak_list); | ||||
| 		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 range_whole = 0; | ||||
| 
 | ||||
| 	if (wbc->nonblocking && bdi_write_congested(bdi)) { | ||||
| 		wbc->encountered_congestion = 1; | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	pagevec_init(&pvec, 0); | ||||
| 	if (wbc->range_cyclic) { | ||||
| 		index = mapping->writeback_index; /* Start from prev offset */ | ||||
|  | @ -2855,6 +2849,98 @@ out: | |||
| 	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, | ||||
| 					      unsigned long i) | ||||
| { | ||||
|  | @ -2892,15 +2978,17 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, | |||
| 						   gfp_t mask) | ||||
| { | ||||
| 	struct extent_buffer *eb = NULL; | ||||
| #ifdef LEAK_DEBUG | ||||
| #if LEAK_DEBUG | ||||
| 	unsigned long flags; | ||||
| #endif | ||||
| 
 | ||||
| 	eb = kmem_cache_zalloc(extent_buffer_cache, mask); | ||||
| 	eb->start = start; | ||||
| 	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); | ||||
| 	list_add(&eb->leak_list, &buffers); | ||||
| 	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) | ||||
| { | ||||
| #ifdef LEAK_DEBUG | ||||
| #if LEAK_DEBUG | ||||
| 	unsigned long flags; | ||||
| 	spin_lock_irqsave(&leak_lock, flags); | ||||
| 	list_del(&eb->leak_list); | ||||
|  | @ -2980,8 +3068,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, | |||
| 		unlock_page(p); | ||||
| 	} | ||||
| 	if (uptodate) | ||||
| 		eb->flags |= EXTENT_UPTODATE; | ||||
| 	eb->flags |= EXTENT_BUFFER_FILLED; | ||||
| 		set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); | ||||
| 
 | ||||
| 	spin_lock(&tree->buffer_lock); | ||||
| 	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; | ||||
| 
 | ||||
| 	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, | ||||
| 			      GFP_NOFS); | ||||
|  | @ -3206,7 +3293,7 @@ int extent_buffer_uptodate(struct extent_io_tree *tree, | |||
| 	struct page *page; | ||||
| 	int pg_uptodate = 1; | ||||
| 
 | ||||
| 	if (eb->flags & EXTENT_UPTODATE) | ||||
| 	if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) | ||||
| 		return 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; | ||||
| 	unsigned long bio_flags = 0; | ||||
| 
 | ||||
| 	if (eb->flags & EXTENT_UPTODATE) | ||||
| 	if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	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 (start_i == 0) | ||||
| 			eb->flags |= EXTENT_UPTODATE; | ||||
| 			set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); | ||||
| 		goto unlock_exit; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -3309,7 +3396,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, | |||
| 	} | ||||
| 
 | ||||
| 	if (!ret) | ||||
| 		eb->flags |= EXTENT_UPTODATE; | ||||
| 		set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); | ||||
| 	return ret; | ||||
| 
 | ||||
| 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); | ||||
| 		eb->map_token = NULL; | ||||
| 		save = 1; | ||||
| 		WARN_ON(!mutex_is_locked(&eb->mutex)); | ||||
| 	} | ||||
| 	err = map_private_extent_buffer(eb, start, min_len, token, map, | ||||
| 				       map_start, map_len, km); | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Ingo Molnar
				Ingo Molnar