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>
|
Rui Saraiva <rmps@joel.ist.utl.pt>
|
||||||
Sachin P Sant <ssant@in.ibm.com>
|
Sachin P Sant <ssant@in.ibm.com>
|
||||||
Sam Ravnborg <sam@mars.ravnborg.org>
|
Sam Ravnborg <sam@mars.ravnborg.org>
|
||||||
|
Sascha Hauer <s.hauer@pengutronix.de>
|
||||||
S.Çağlar Onur <caglar@pardus.org.tr>
|
S.Çağlar Onur <caglar@pardus.org.tr>
|
||||||
Simon Kelley <simon@thekelleys.org.uk>
|
Simon Kelley <simon@thekelleys.org.uk>
|
||||||
Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
|
Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
|
||||||
|
|
@ -100,6 +101,7 @@ Tejun Heo <htejun@gmail.com>
|
||||||
Thomas Graf <tgraf@suug.ch>
|
Thomas Graf <tgraf@suug.ch>
|
||||||
Tony Luck <tony.luck@intel.com>
|
Tony Luck <tony.luck@intel.com>
|
||||||
Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
|
Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
|
||||||
Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
|
|
||||||
Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
|
Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
|
||||||
|
Uwe Kleine-König <ukl@pengutronix.de>
|
||||||
|
Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
|
||||||
Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
|
Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
|
||||||
|
|
|
||||||
|
|
@ -195,19 +195,3 @@ scaling_setspeed. By "echoing" a new frequency into this
|
||||||
you can change the speed of the CPU,
|
you can change the speed of the CPU,
|
||||||
but only within the limits of
|
but only within the limits of
|
||||||
scaling_min_freq and scaling_max_freq.
|
scaling_min_freq and scaling_max_freq.
|
||||||
|
|
||||||
|
|
||||||
3.2 Deprecated Interfaces
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Depending on your kernel configuration, you might find the following
|
|
||||||
cpufreq-related files:
|
|
||||||
/proc/cpufreq
|
|
||||||
/proc/sys/cpu/*/speed
|
|
||||||
/proc/sys/cpu/*/speed-min
|
|
||||||
/proc/sys/cpu/*/speed-max
|
|
||||||
|
|
||||||
These are files for deprecated interfaces to cpufreq, which offer far
|
|
||||||
less functionality. Because of this, these interfaces aren't described
|
|
||||||
here.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ that support it. For example, a given bus might look like this:
|
||||||
| |-- class
|
| |-- class
|
||||||
| |-- config
|
| |-- config
|
||||||
| |-- device
|
| |-- device
|
||||||
|
| |-- enable
|
||||||
| |-- irq
|
| |-- irq
|
||||||
| |-- local_cpus
|
| |-- local_cpus
|
||||||
| |-- resource
|
| |-- resource
|
||||||
|
|
@ -32,6 +33,7 @@ files, each with their own function.
|
||||||
class PCI class (ascii, ro)
|
class PCI class (ascii, ro)
|
||||||
config PCI config space (binary, rw)
|
config PCI config space (binary, rw)
|
||||||
device PCI device (ascii, ro)
|
device PCI device (ascii, ro)
|
||||||
|
enable Whether the device is enabled (ascii, rw)
|
||||||
irq IRQ number (ascii, ro)
|
irq IRQ number (ascii, ro)
|
||||||
local_cpus nearby CPU mask (cpumask, ro)
|
local_cpus nearby CPU mask (cpumask, ro)
|
||||||
resource PCI resource host addresses (ascii, ro)
|
resource PCI resource host addresses (ascii, ro)
|
||||||
|
|
@ -57,10 +59,19 @@ used to do actual device programming from userspace. Note that some platforms
|
||||||
don't support mmapping of certain resources, so be sure to check the return
|
don't support mmapping of certain resources, so be sure to check the return
|
||||||
value from any attempted mmap.
|
value from any attempted mmap.
|
||||||
|
|
||||||
|
The 'enable' file provides a counter that indicates how many times the device
|
||||||
|
has been enabled. If the 'enable' file currently returns '4', and a '1' is
|
||||||
|
echoed into it, it will then return '5'. Echoing a '0' into it will decrease
|
||||||
|
the count. Even when it returns to 0, though, some of the initialisation
|
||||||
|
may not be reversed.
|
||||||
|
|
||||||
The 'rom' file is special in that it provides read-only access to the device's
|
The 'rom' file is special in that it provides read-only access to the device's
|
||||||
ROM file, if available. It's disabled by default, however, so applications
|
ROM file, if available. It's disabled by default, however, so applications
|
||||||
should write the string "1" to the file to enable it before attempting a read
|
should write the string "1" to the file to enable it before attempting a read
|
||||||
call, and disable it following the access by writing "0" to the file.
|
call, and disable it following the access by writing "0" to the file. Note
|
||||||
|
that the device must be enabled for a rom read to return data succesfully.
|
||||||
|
In the event a driver is not bound to the device, it can be enabled using the
|
||||||
|
'enable' file, documented above.
|
||||||
|
|
||||||
Accessing legacy resources through sysfs
|
Accessing legacy resources through sysfs
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
|
||||||
11
MAINTAINERS
11
MAINTAINERS
|
|
@ -1021,6 +1021,14 @@ M: mb@bu3sch.de
|
||||||
W: http://bu3sch.de/btgpio.php
|
W: http://bu3sch.de/btgpio.php
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
BTRFS FILE SYSTEM
|
||||||
|
P: Chris Mason
|
||||||
|
M: chris.mason@oracle.com
|
||||||
|
L: linux-btrfs@vger.kernel.org
|
||||||
|
W: http://btrfs.wiki.kernel.org/
|
||||||
|
T: git kernel.org:/pub/scm/linux/kernel/git/mason/btrfs-unstable.git
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
BTTV VIDEO4LINUX DRIVER
|
BTTV VIDEO4LINUX DRIVER
|
||||||
P: Mauro Carvalho Chehab
|
P: Mauro Carvalho Chehab
|
||||||
M: mchehab@infradead.org
|
M: mchehab@infradead.org
|
||||||
|
|
@ -2212,7 +2220,7 @@ P: Sean Hefty
|
||||||
M: sean.hefty@intel.com
|
M: sean.hefty@intel.com
|
||||||
P: Hal Rosenstock
|
P: Hal Rosenstock
|
||||||
M: hal.rosenstock@gmail.com
|
M: hal.rosenstock@gmail.com
|
||||||
L: general@lists.openfabrics.org
|
L: general@lists.openfabrics.org (moderated for non-subscribers)
|
||||||
W: http://www.openib.org/
|
W: http://www.openib.org/
|
||||||
T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
|
T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
@ -4847,6 +4855,7 @@ P: Ingo Molnar
|
||||||
M: mingo@redhat.com
|
M: mingo@redhat.com
|
||||||
P: H. Peter Anvin
|
P: H. Peter Anvin
|
||||||
M: hpa@zytor.com
|
M: hpa@zytor.com
|
||||||
|
M: x86@kernel.org
|
||||||
L: linux-kernel@vger.kernel.org
|
L: linux-kernel@vger.kernel.org
|
||||||
T: git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
|
T: git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
|
||||||
2
Makefile
2
Makefile
|
|
@ -1,7 +1,7 @@
|
||||||
VERSION = 2
|
VERSION = 2
|
||||||
PATCHLEVEL = 6
|
PATCHLEVEL = 6
|
||||||
SUBLEVEL = 29
|
SUBLEVEL = 29
|
||||||
EXTRAVERSION = -rc3
|
EXTRAVERSION = -rc4
|
||||||
NAME = Erotic Pickled Herring
|
NAME = Erotic Pickled Herring
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,12 @@
|
||||||
|
|
||||||
/* ??? Would be nice to use .gprel32 here, but we can't be sure that the
|
/* ??? Would be nice to use .gprel32 here, but we can't be sure that the
|
||||||
function loaded the GP, so this could fail in modules. */
|
function loaded the GP, so this could fail in modules. */
|
||||||
#define BUG() { \
|
#define BUG() do { \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
"call_pal %0 # bugchk\n\t" \
|
"call_pal %0 # bugchk\n\t" \
|
||||||
".long %1\n\t.8byte %2" \
|
".long %1\n\t.8byte %2" \
|
||||||
: : "i"(PAL_bugchk), "i"(__LINE__), "i"(__FILE__)); \
|
: : "i"(PAL_bugchk), "i"(__LINE__), "i"(__FILE__)); \
|
||||||
for ( ; ; ); }
|
for ( ; ; ); } while (0)
|
||||||
|
|
||||||
#define HAVE_ARCH_BUG
|
#define HAVE_ARCH_BUG
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -443,7 +443,7 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
|
||||||
size = pci_resource_len(dev, PCI_ROM_RESOURCE);
|
size = pci_resource_len(dev, PCI_ROM_RESOURCE);
|
||||||
addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
|
addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
|
||||||
size);
|
size);
|
||||||
image_size = pci_get_rom_size(addr, size);
|
image_size = pci_get_rom_size(dev, addr, size);
|
||||||
dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
|
dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
|
||||||
dev->resource[PCI_ROM_RESOURCE].end =
|
dev->resource[PCI_ROM_RESOURCE].end =
|
||||||
(unsigned long) addr + image_size - 1;
|
(unsigned long) addr + image_size - 1;
|
||||||
|
|
|
||||||
|
|
@ -269,7 +269,7 @@ sn_io_slot_fixup(struct pci_dev *dev)
|
||||||
|
|
||||||
rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE),
|
rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE),
|
||||||
size + 1);
|
size + 1);
|
||||||
image_size = pci_get_rom_size(rom, size + 1);
|
image_size = pci_get_rom_size(dev, rom, size + 1);
|
||||||
dev->resource[PCI_ROM_RESOURCE].end =
|
dev->resource[PCI_ROM_RESOURCE].end =
|
||||||
dev->resource[PCI_ROM_RESOURCE].start +
|
dev->resource[PCI_ROM_RESOURCE].start +
|
||||||
image_size - 1;
|
image_size - 1;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
#include <linux/spi/spi_gpio.h>
|
#include <linux/spi/spi_gpio.h>
|
||||||
|
#include <media/ov772x.h>
|
||||||
#include <media/soc_camera_platform.h>
|
#include <media/soc_camera_platform.h>
|
||||||
#include <media/sh_mobile_ceu.h>
|
#include <media/sh_mobile_ceu.h>
|
||||||
#include <video/sh_mobile_lcdc.h>
|
#include <video/sh_mobile_lcdc.h>
|
||||||
|
|
@ -216,7 +217,14 @@ static struct platform_device lcdc_device = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void camera_power(int val)
|
||||||
|
{
|
||||||
|
gpio_set_value(GPIO_PTZ5, val); /* RST_CAM/RSTB */
|
||||||
|
mdelay(10);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_I2C
|
#ifdef CONFIG_I2C
|
||||||
|
/* support for the old ncm03j camera */
|
||||||
static unsigned char camera_ncm03j_magic[] =
|
static unsigned char camera_ncm03j_magic[] =
|
||||||
{
|
{
|
||||||
0x87, 0x00, 0x88, 0x08, 0x89, 0x01, 0x8A, 0xE8,
|
0x87, 0x00, 0x88, 0x08, 0x89, 0x01, 0x8A, 0xE8,
|
||||||
|
|
@ -237,6 +245,23 @@ static unsigned char camera_ncm03j_magic[] =
|
||||||
0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
|
0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int camera_probe(void)
|
||||||
|
{
|
||||||
|
struct i2c_adapter *a = i2c_get_adapter(0);
|
||||||
|
struct i2c_msg msg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
camera_power(1);
|
||||||
|
msg.addr = 0x6e;
|
||||||
|
msg.buf = camera_ncm03j_magic;
|
||||||
|
msg.len = 2;
|
||||||
|
msg.flags = 0;
|
||||||
|
ret = i2c_transfer(a, &msg, 1);
|
||||||
|
camera_power(0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int camera_set_capture(struct soc_camera_platform_info *info,
|
static int camera_set_capture(struct soc_camera_platform_info *info,
|
||||||
int enable)
|
int enable)
|
||||||
{
|
{
|
||||||
|
|
@ -245,9 +270,11 @@ static int camera_set_capture(struct soc_camera_platform_info *info,
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
camera_power(0);
|
||||||
if (!enable)
|
if (!enable)
|
||||||
return 0; /* no disable for now */
|
return 0; /* no disable for now */
|
||||||
|
|
||||||
|
camera_power(1);
|
||||||
for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) {
|
for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) {
|
||||||
u_int8_t buf[8];
|
u_int8_t buf[8];
|
||||||
|
|
||||||
|
|
@ -286,8 +313,35 @@ static struct platform_device camera_device = {
|
||||||
.platform_data = &camera_info,
|
.platform_data = &camera_info,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int __init camera_setup(void)
|
||||||
|
{
|
||||||
|
if (camera_probe() > 0)
|
||||||
|
platform_device_register(&camera_device);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
late_initcall(camera_setup);
|
||||||
|
|
||||||
#endif /* CONFIG_I2C */
|
#endif /* CONFIG_I2C */
|
||||||
|
|
||||||
|
static int ov7725_power(struct device *dev, int mode)
|
||||||
|
{
|
||||||
|
camera_power(0);
|
||||||
|
if (mode)
|
||||||
|
camera_power(1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ov772x_camera_info ov7725_info = {
|
||||||
|
.buswidth = SOCAM_DATAWIDTH_8,
|
||||||
|
.flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
|
||||||
|
.link = {
|
||||||
|
.power = ov7725_power,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
|
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
|
||||||
.flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
|
.flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
|
||||||
SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
|
SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
|
||||||
|
|
@ -338,9 +392,6 @@ static struct platform_device *ap325rxa_devices[] __initdata = {
|
||||||
&ap325rxa_nor_flash_device,
|
&ap325rxa_nor_flash_device,
|
||||||
&lcdc_device,
|
&lcdc_device,
|
||||||
&ceu_device,
|
&ceu_device,
|
||||||
#ifdef CONFIG_I2C
|
|
||||||
&camera_device,
|
|
||||||
#endif
|
|
||||||
&nand_flash_device,
|
&nand_flash_device,
|
||||||
&sdcard_cn3_device,
|
&sdcard_cn3_device,
|
||||||
};
|
};
|
||||||
|
|
@ -349,6 +400,10 @@ static struct i2c_board_info __initdata ap325rxa_i2c_devices[] = {
|
||||||
{
|
{
|
||||||
I2C_BOARD_INFO("pcf8563", 0x51),
|
I2C_BOARD_INFO("pcf8563", 0x51),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
I2C_BOARD_INFO("ov772x", 0x21),
|
||||||
|
.platform_data = &ov7725_info,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct spi_board_info ap325rxa_spi_devices[] = {
|
static struct spi_board_info ap325rxa_spi_devices[] = {
|
||||||
|
|
@ -426,7 +481,7 @@ static int __init ap325rxa_devices_setup(void)
|
||||||
gpio_request(GPIO_PTZ6, NULL);
|
gpio_request(GPIO_PTZ6, NULL);
|
||||||
gpio_direction_output(GPIO_PTZ6, 0); /* STBY_CAM */
|
gpio_direction_output(GPIO_PTZ6, 0); /* STBY_CAM */
|
||||||
gpio_request(GPIO_PTZ5, NULL);
|
gpio_request(GPIO_PTZ5, NULL);
|
||||||
gpio_direction_output(GPIO_PTZ5, 1); /* RST_CAM */
|
gpio_direction_output(GPIO_PTZ5, 0); /* RST_CAM */
|
||||||
gpio_request(GPIO_PTZ4, NULL);
|
gpio_request(GPIO_PTZ4, NULL);
|
||||||
gpio_direction_output(GPIO_PTZ4, 0); /* SADDR */
|
gpio_direction_output(GPIO_PTZ4, 0); /* SADDR */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
# Automatically generated make config: don't edit
|
# Automatically generated make config: don't edit
|
||||||
# Linux kernel version: 2.6.28
|
# Linux kernel version: 2.6.29-rc2
|
||||||
# Fri Jan 9 16:54:19 2009
|
# Tue Jan 27 11:45:08 2009
|
||||||
#
|
#
|
||||||
CONFIG_SUPERH=y
|
CONFIG_SUPERH=y
|
||||||
CONFIG_SUPERH32=y
|
CONFIG_SUPERH32=y
|
||||||
|
|
@ -45,12 +45,12 @@ CONFIG_BSD_PROCESS_ACCT=y
|
||||||
# CONFIG_AUDIT is not set
|
# CONFIG_AUDIT is not set
|
||||||
# CONFIG_IKCONFIG is not set
|
# CONFIG_IKCONFIG is not set
|
||||||
CONFIG_LOG_BUF_SHIFT=14
|
CONFIG_LOG_BUF_SHIFT=14
|
||||||
# CONFIG_CGROUPS is not set
|
|
||||||
CONFIG_GROUP_SCHED=y
|
CONFIG_GROUP_SCHED=y
|
||||||
CONFIG_FAIR_GROUP_SCHED=y
|
CONFIG_FAIR_GROUP_SCHED=y
|
||||||
# CONFIG_RT_GROUP_SCHED is not set
|
# CONFIG_RT_GROUP_SCHED is not set
|
||||||
CONFIG_USER_SCHED=y
|
CONFIG_USER_SCHED=y
|
||||||
# CONFIG_CGROUP_SCHED is not set
|
# CONFIG_CGROUP_SCHED is not set
|
||||||
|
# CONFIG_CGROUPS is not set
|
||||||
CONFIG_SYSFS_DEPRECATED=y
|
CONFIG_SYSFS_DEPRECATED=y
|
||||||
CONFIG_SYSFS_DEPRECATED_V2=y
|
CONFIG_SYSFS_DEPRECATED_V2=y
|
||||||
# CONFIG_RELAY is not set
|
# CONFIG_RELAY is not set
|
||||||
|
|
@ -378,6 +378,7 @@ CONFIG_WIRELESS=y
|
||||||
# CONFIG_WIRELESS_EXT is not set
|
# CONFIG_WIRELESS_EXT is not set
|
||||||
# CONFIG_LIB80211 is not set
|
# CONFIG_LIB80211 is not set
|
||||||
# CONFIG_MAC80211 is not set
|
# CONFIG_MAC80211 is not set
|
||||||
|
# CONFIG_WIMAX is not set
|
||||||
# CONFIG_RFKILL is not set
|
# CONFIG_RFKILL is not set
|
||||||
# CONFIG_NET_9P is not set
|
# CONFIG_NET_9P is not set
|
||||||
|
|
||||||
|
|
@ -400,6 +401,7 @@ CONFIG_MTD=y
|
||||||
# CONFIG_MTD_DEBUG is not set
|
# CONFIG_MTD_DEBUG is not set
|
||||||
CONFIG_MTD_CONCAT=y
|
CONFIG_MTD_CONCAT=y
|
||||||
CONFIG_MTD_PARTITIONS=y
|
CONFIG_MTD_PARTITIONS=y
|
||||||
|
# CONFIG_MTD_TESTS is not set
|
||||||
# CONFIG_MTD_REDBOOT_PARTS is not set
|
# CONFIG_MTD_REDBOOT_PARTS is not set
|
||||||
CONFIG_MTD_CMDLINE_PARTS=y
|
CONFIG_MTD_CMDLINE_PARTS=y
|
||||||
# CONFIG_MTD_AR7_PARTS is not set
|
# CONFIG_MTD_AR7_PARTS is not set
|
||||||
|
|
@ -447,9 +449,7 @@ CONFIG_MTD_CFI_UTIL=y
|
||||||
#
|
#
|
||||||
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
|
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
|
||||||
CONFIG_MTD_PHYSMAP=y
|
CONFIG_MTD_PHYSMAP=y
|
||||||
CONFIG_MTD_PHYSMAP_START=0xffffffff
|
# CONFIG_MTD_PHYSMAP_COMPAT is not set
|
||||||
CONFIG_MTD_PHYSMAP_LEN=0
|
|
||||||
CONFIG_MTD_PHYSMAP_BANKWIDTH=0
|
|
||||||
# CONFIG_MTD_PLATRAM is not set
|
# CONFIG_MTD_PLATRAM is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
@ -479,6 +479,12 @@ CONFIG_MTD_NAND_IDS=y
|
||||||
CONFIG_MTD_NAND_SH_FLCTL=y
|
CONFIG_MTD_NAND_SH_FLCTL=y
|
||||||
# CONFIG_MTD_ONENAND is not set
|
# CONFIG_MTD_ONENAND is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# LPDDR flash memory drivers
|
||||||
|
#
|
||||||
|
# CONFIG_MTD_LPDDR is not set
|
||||||
|
# CONFIG_MTD_QINFO_PROBE is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# UBI - Unsorted block images
|
# UBI - Unsorted block images
|
||||||
#
|
#
|
||||||
|
|
@ -607,6 +613,10 @@ CONFIG_SMSC911X=y
|
||||||
# CONFIG_WLAN_PRE80211 is not set
|
# CONFIG_WLAN_PRE80211 is not set
|
||||||
# CONFIG_WLAN_80211 is not set
|
# CONFIG_WLAN_80211 is not set
|
||||||
# CONFIG_IWLWIFI_LEDS is not set
|
# CONFIG_IWLWIFI_LEDS is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Enable WiMAX (Networking options) to see the WiMAX drivers
|
||||||
|
#
|
||||||
# CONFIG_WAN is not set
|
# CONFIG_WAN is not set
|
||||||
# CONFIG_PPP is not set
|
# CONFIG_PPP is not set
|
||||||
# CONFIG_SLIP is not set
|
# CONFIG_SLIP is not set
|
||||||
|
|
@ -790,6 +800,7 @@ CONFIG_SSB_POSSIBLE=y
|
||||||
# CONFIG_PMIC_DA903X is not set
|
# CONFIG_PMIC_DA903X is not set
|
||||||
# CONFIG_MFD_WM8400 is not set
|
# CONFIG_MFD_WM8400 is not set
|
||||||
# CONFIG_MFD_WM8350_I2C is not set
|
# CONFIG_MFD_WM8350_I2C is not set
|
||||||
|
# CONFIG_MFD_PCF50633 is not set
|
||||||
# CONFIG_REGULATOR is not set
|
# CONFIG_REGULATOR is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
@ -837,7 +848,7 @@ CONFIG_SOC_CAMERA=y
|
||||||
# CONFIG_SOC_CAMERA_MT9V022 is not set
|
# CONFIG_SOC_CAMERA_MT9V022 is not set
|
||||||
# CONFIG_SOC_CAMERA_TW9910 is not set
|
# CONFIG_SOC_CAMERA_TW9910 is not set
|
||||||
CONFIG_SOC_CAMERA_PLATFORM=y
|
CONFIG_SOC_CAMERA_PLATFORM=y
|
||||||
# CONFIG_SOC_CAMERA_OV772X is not set
|
CONFIG_SOC_CAMERA_OV772X=y
|
||||||
CONFIG_VIDEO_SH_MOBILE_CEU=y
|
CONFIG_VIDEO_SH_MOBILE_CEU=y
|
||||||
# CONFIG_RADIO_ADAPTERS is not set
|
# CONFIG_RADIO_ADAPTERS is not set
|
||||||
# CONFIG_DAB is not set
|
# CONFIG_DAB is not set
|
||||||
|
|
@ -1012,6 +1023,7 @@ CONFIG_FS_POSIX_ACL=y
|
||||||
CONFIG_FILE_LOCKING=y
|
CONFIG_FILE_LOCKING=y
|
||||||
# CONFIG_XFS_FS is not set
|
# CONFIG_XFS_FS is not set
|
||||||
# CONFIG_OCFS2_FS is not set
|
# CONFIG_OCFS2_FS is not set
|
||||||
|
# CONFIG_BTRFS_FS is not set
|
||||||
CONFIG_DNOTIFY=y
|
CONFIG_DNOTIFY=y
|
||||||
CONFIG_INOTIFY=y
|
CONFIG_INOTIFY=y
|
||||||
CONFIG_INOTIFY_USER=y
|
CONFIG_INOTIFY_USER=y
|
||||||
|
|
@ -1060,6 +1072,7 @@ CONFIG_MISC_FILESYSTEMS=y
|
||||||
# CONFIG_JFFS2_FS is not set
|
# CONFIG_JFFS2_FS is not set
|
||||||
# CONFIG_UBIFS_FS is not set
|
# CONFIG_UBIFS_FS is not set
|
||||||
# CONFIG_CRAMFS is not set
|
# CONFIG_CRAMFS is not set
|
||||||
|
# CONFIG_SQUASHFS is not set
|
||||||
# CONFIG_VXFS_FS is not set
|
# CONFIG_VXFS_FS is not set
|
||||||
# CONFIG_MINIX_FS is not set
|
# CONFIG_MINIX_FS is not set
|
||||||
# CONFIG_OMFS_FS is not set
|
# CONFIG_OMFS_FS is not set
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
# Automatically generated make config: don't edit
|
# Automatically generated make config: don't edit
|
||||||
# Linux kernel version: 2.6.28
|
# Linux kernel version: 2.6.29-rc1
|
||||||
# Fri Jan 9 17:09:35 2009
|
# Thu Jan 22 09:16:16 2009
|
||||||
#
|
#
|
||||||
CONFIG_SUPERH=y
|
CONFIG_SUPERH=y
|
||||||
CONFIG_SUPERH32=y
|
CONFIG_SUPERH32=y
|
||||||
|
|
@ -45,8 +45,12 @@ CONFIG_SYSVIPC_SYSCTL=y
|
||||||
CONFIG_IKCONFIG=y
|
CONFIG_IKCONFIG=y
|
||||||
CONFIG_IKCONFIG_PROC=y
|
CONFIG_IKCONFIG_PROC=y
|
||||||
CONFIG_LOG_BUF_SHIFT=14
|
CONFIG_LOG_BUF_SHIFT=14
|
||||||
# CONFIG_CGROUPS is not set
|
|
||||||
# CONFIG_GROUP_SCHED is not set
|
# CONFIG_GROUP_SCHED is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Control Group support
|
||||||
|
#
|
||||||
|
# CONFIG_CGROUPS is not set
|
||||||
CONFIG_SYSFS_DEPRECATED=y
|
CONFIG_SYSFS_DEPRECATED=y
|
||||||
CONFIG_SYSFS_DEPRECATED_V2=y
|
CONFIG_SYSFS_DEPRECATED_V2=y
|
||||||
# CONFIG_RELAY is not set
|
# CONFIG_RELAY is not set
|
||||||
|
|
@ -389,6 +393,7 @@ CONFIG_WIRELESS_EXT=y
|
||||||
CONFIG_WIRELESS_EXT_SYSFS=y
|
CONFIG_WIRELESS_EXT_SYSFS=y
|
||||||
# CONFIG_LIB80211 is not set
|
# CONFIG_LIB80211 is not set
|
||||||
# CONFIG_MAC80211 is not set
|
# CONFIG_MAC80211 is not set
|
||||||
|
# CONFIG_WIMAX is not set
|
||||||
# CONFIG_RFKILL is not set
|
# CONFIG_RFKILL is not set
|
||||||
# CONFIG_NET_9P is not set
|
# CONFIG_NET_9P is not set
|
||||||
|
|
||||||
|
|
@ -411,6 +416,7 @@ CONFIG_MTD=y
|
||||||
# CONFIG_MTD_DEBUG is not set
|
# CONFIG_MTD_DEBUG is not set
|
||||||
CONFIG_MTD_CONCAT=y
|
CONFIG_MTD_CONCAT=y
|
||||||
CONFIG_MTD_PARTITIONS=y
|
CONFIG_MTD_PARTITIONS=y
|
||||||
|
# CONFIG_MTD_TESTS is not set
|
||||||
# CONFIG_MTD_REDBOOT_PARTS is not set
|
# CONFIG_MTD_REDBOOT_PARTS is not set
|
||||||
CONFIG_MTD_CMDLINE_PARTS=y
|
CONFIG_MTD_CMDLINE_PARTS=y
|
||||||
# CONFIG_MTD_AR7_PARTS is not set
|
# CONFIG_MTD_AR7_PARTS is not set
|
||||||
|
|
@ -458,9 +464,7 @@ CONFIG_MTD_CFI_UTIL=y
|
||||||
#
|
#
|
||||||
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
|
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
|
||||||
CONFIG_MTD_PHYSMAP=y
|
CONFIG_MTD_PHYSMAP=y
|
||||||
CONFIG_MTD_PHYSMAP_START=0xffffffff
|
# CONFIG_MTD_PHYSMAP_COMPAT is not set
|
||||||
CONFIG_MTD_PHYSMAP_LEN=0
|
|
||||||
CONFIG_MTD_PHYSMAP_BANKWIDTH=0
|
|
||||||
# CONFIG_MTD_PLATRAM is not set
|
# CONFIG_MTD_PLATRAM is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
@ -487,6 +491,12 @@ CONFIG_MTD_NAND_IDS=y
|
||||||
CONFIG_MTD_NAND_PLATFORM=y
|
CONFIG_MTD_NAND_PLATFORM=y
|
||||||
# CONFIG_MTD_ONENAND is not set
|
# CONFIG_MTD_ONENAND is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# LPDDR flash memory drivers
|
||||||
|
#
|
||||||
|
# CONFIG_MTD_LPDDR is not set
|
||||||
|
# CONFIG_MTD_QINFO_PROBE is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# UBI - Unsorted block images
|
# UBI - Unsorted block images
|
||||||
#
|
#
|
||||||
|
|
@ -587,6 +597,10 @@ CONFIG_SMC91X=y
|
||||||
# CONFIG_WLAN_PRE80211 is not set
|
# CONFIG_WLAN_PRE80211 is not set
|
||||||
# CONFIG_WLAN_80211 is not set
|
# CONFIG_WLAN_80211 is not set
|
||||||
# CONFIG_IWLWIFI_LEDS is not set
|
# CONFIG_IWLWIFI_LEDS is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# Enable WiMAX (Networking options) to see the WiMAX drivers
|
||||||
|
#
|
||||||
# CONFIG_WAN is not set
|
# CONFIG_WAN is not set
|
||||||
# CONFIG_PPP is not set
|
# CONFIG_PPP is not set
|
||||||
# CONFIG_SLIP is not set
|
# CONFIG_SLIP is not set
|
||||||
|
|
@ -761,6 +775,7 @@ CONFIG_SSB_POSSIBLE=y
|
||||||
# CONFIG_PMIC_DA903X is not set
|
# CONFIG_PMIC_DA903X is not set
|
||||||
# CONFIG_MFD_WM8400 is not set
|
# CONFIG_MFD_WM8400 is not set
|
||||||
# CONFIG_MFD_WM8350_I2C is not set
|
# CONFIG_MFD_WM8350_I2C is not set
|
||||||
|
# CONFIG_MFD_PCF50633 is not set
|
||||||
# CONFIG_REGULATOR is not set
|
# CONFIG_REGULATOR is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
@ -806,9 +821,9 @@ CONFIG_SOC_CAMERA=y
|
||||||
# CONFIG_SOC_CAMERA_MT9M111 is not set
|
# CONFIG_SOC_CAMERA_MT9M111 is not set
|
||||||
# CONFIG_SOC_CAMERA_MT9T031 is not set
|
# CONFIG_SOC_CAMERA_MT9T031 is not set
|
||||||
# CONFIG_SOC_CAMERA_MT9V022 is not set
|
# CONFIG_SOC_CAMERA_MT9V022 is not set
|
||||||
# CONFIG_SOC_CAMERA_TW9910 is not set
|
CONFIG_SOC_CAMERA_TW9910=y
|
||||||
CONFIG_SOC_CAMERA_PLATFORM=y
|
# CONFIG_SOC_CAMERA_PLATFORM is not set
|
||||||
# CONFIG_SOC_CAMERA_OV772X is not set
|
CONFIG_SOC_CAMERA_OV772X=y
|
||||||
CONFIG_VIDEO_SH_MOBILE_CEU=y
|
CONFIG_VIDEO_SH_MOBILE_CEU=y
|
||||||
# CONFIG_RADIO_ADAPTERS is not set
|
# CONFIG_RADIO_ADAPTERS is not set
|
||||||
# CONFIG_DAB is not set
|
# CONFIG_DAB is not set
|
||||||
|
|
@ -866,11 +881,13 @@ CONFIG_USB_GADGET_SELECTED=y
|
||||||
# CONFIG_USB_GADGET_PXA25X is not set
|
# CONFIG_USB_GADGET_PXA25X is not set
|
||||||
# CONFIG_USB_GADGET_PXA27X is not set
|
# CONFIG_USB_GADGET_PXA27X is not set
|
||||||
# CONFIG_USB_GADGET_S3C2410 is not set
|
# CONFIG_USB_GADGET_S3C2410 is not set
|
||||||
|
# CONFIG_USB_GADGET_IMX is not set
|
||||||
CONFIG_USB_GADGET_M66592=y
|
CONFIG_USB_GADGET_M66592=y
|
||||||
CONFIG_USB_M66592=y
|
CONFIG_USB_M66592=y
|
||||||
CONFIG_SUPERH_BUILT_IN_M66592=y
|
CONFIG_SUPERH_BUILT_IN_M66592=y
|
||||||
# CONFIG_USB_GADGET_AMD5536UDC is not set
|
# CONFIG_USB_GADGET_AMD5536UDC is not set
|
||||||
# CONFIG_USB_GADGET_FSL_QE is not set
|
# CONFIG_USB_GADGET_FSL_QE is not set
|
||||||
|
# CONFIG_USB_GADGET_CI13XXX is not set
|
||||||
# CONFIG_USB_GADGET_NET2280 is not set
|
# CONFIG_USB_GADGET_NET2280 is not set
|
||||||
# CONFIG_USB_GADGET_GOKU is not set
|
# CONFIG_USB_GADGET_GOKU is not set
|
||||||
# CONFIG_USB_GADGET_DUMMY_HCD is not set
|
# CONFIG_USB_GADGET_DUMMY_HCD is not set
|
||||||
|
|
@ -883,6 +900,11 @@ CONFIG_USB_G_SERIAL=y
|
||||||
# CONFIG_USB_MIDI_GADGET is not set
|
# CONFIG_USB_MIDI_GADGET is not set
|
||||||
# CONFIG_USB_G_PRINTER is not set
|
# CONFIG_USB_G_PRINTER is not set
|
||||||
# CONFIG_USB_CDC_COMPOSITE is not set
|
# CONFIG_USB_CDC_COMPOSITE is not set
|
||||||
|
|
||||||
|
#
|
||||||
|
# OTG and related infrastructure
|
||||||
|
#
|
||||||
|
# CONFIG_USB_GPIO_VBUS is not set
|
||||||
# CONFIG_MMC is not set
|
# CONFIG_MMC is not set
|
||||||
# CONFIG_MEMSTICK is not set
|
# CONFIG_MEMSTICK is not set
|
||||||
# CONFIG_NEW_LEDS is not set
|
# CONFIG_NEW_LEDS is not set
|
||||||
|
|
@ -961,6 +983,7 @@ CONFIG_UIO_PDRV_GENIRQ=y
|
||||||
CONFIG_FILE_LOCKING=y
|
CONFIG_FILE_LOCKING=y
|
||||||
# CONFIG_XFS_FS is not set
|
# CONFIG_XFS_FS is not set
|
||||||
# CONFIG_OCFS2_FS is not set
|
# CONFIG_OCFS2_FS is not set
|
||||||
|
# CONFIG_BTRFS_FS is not set
|
||||||
# CONFIG_DNOTIFY is not set
|
# CONFIG_DNOTIFY is not set
|
||||||
# CONFIG_INOTIFY is not set
|
# CONFIG_INOTIFY is not set
|
||||||
# CONFIG_QUOTA is not set
|
# CONFIG_QUOTA is not set
|
||||||
|
|
@ -1004,6 +1027,7 @@ CONFIG_MISC_FILESYSTEMS=y
|
||||||
# CONFIG_EFS_FS is not set
|
# CONFIG_EFS_FS is not set
|
||||||
# CONFIG_JFFS2_FS is not set
|
# CONFIG_JFFS2_FS is not set
|
||||||
# CONFIG_CRAMFS is not set
|
# CONFIG_CRAMFS is not set
|
||||||
|
# CONFIG_SQUASHFS is not set
|
||||||
# CONFIG_VXFS_FS is not set
|
# CONFIG_VXFS_FS is not set
|
||||||
# CONFIG_MINIX_FS is not set
|
# CONFIG_MINIX_FS is not set
|
||||||
# CONFIG_OMFS_FS is not set
|
# CONFIG_OMFS_FS is not set
|
||||||
|
|
|
||||||
|
|
@ -21,38 +21,36 @@
|
||||||
static inline void
|
static inline void
|
||||||
__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
|
__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
|
||||||
{
|
{
|
||||||
int __ex_flag, __res;
|
int __done, __res;
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"movli.l @%2, %0 \n"
|
"movli.l @%2, %0 \n"
|
||||||
"add #-1, %0 \n"
|
"add #-1, %0 \n"
|
||||||
"movco.l %0, @%2 \n"
|
"movco.l %0, @%2 \n"
|
||||||
"movt %1 \n"
|
"movt %1 \n"
|
||||||
: "=&z" (__res), "=&r" (__ex_flag)
|
: "=&z" (__res), "=&r" (__done)
|
||||||
: "r" (&(count)->counter)
|
: "r" (&(count)->counter)
|
||||||
: "t");
|
: "t");
|
||||||
|
|
||||||
__res |= !__ex_flag;
|
if (unlikely(!__done || __res != 0))
|
||||||
if (unlikely(__res != 0))
|
|
||||||
fail_fn(count);
|
fail_fn(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
|
__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
|
||||||
{
|
{
|
||||||
int __ex_flag, __res;
|
int __done, __res;
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"movli.l @%2, %0 \n"
|
"movli.l @%2, %0 \n"
|
||||||
"add #-1, %0 \n"
|
"add #-1, %0 \n"
|
||||||
"movco.l %0, @%2 \n"
|
"movco.l %0, @%2 \n"
|
||||||
"movt %1 \n"
|
"movt %1 \n"
|
||||||
: "=&z" (__res), "=&r" (__ex_flag)
|
: "=&z" (__res), "=&r" (__done)
|
||||||
: "r" (&(count)->counter)
|
: "r" (&(count)->counter)
|
||||||
: "t");
|
: "t");
|
||||||
|
|
||||||
__res |= !__ex_flag;
|
if (unlikely(!__done || __res != 0))
|
||||||
if (unlikely(__res != 0))
|
|
||||||
__res = fail_fn(count);
|
__res = fail_fn(count);
|
||||||
|
|
||||||
return __res;
|
return __res;
|
||||||
|
|
@ -61,19 +59,18 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
|
||||||
static inline void
|
static inline void
|
||||||
__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
|
__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
|
||||||
{
|
{
|
||||||
int __ex_flag, __res;
|
int __done, __res;
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"movli.l @%2, %0 \n\t"
|
"movli.l @%2, %0 \n\t"
|
||||||
"add #1, %0 \n\t"
|
"add #1, %0 \n\t"
|
||||||
"movco.l %0, @%2 \n\t"
|
"movco.l %0, @%2 \n\t"
|
||||||
"movt %1 \n\t"
|
"movt %1 \n\t"
|
||||||
: "=&z" (__res), "=&r" (__ex_flag)
|
: "=&z" (__res), "=&r" (__done)
|
||||||
: "r" (&(count)->counter)
|
: "r" (&(count)->counter)
|
||||||
: "t");
|
: "t");
|
||||||
|
|
||||||
__res |= !__ex_flag;
|
if (unlikely(!__done || __res <= 0))
|
||||||
if (unlikely(__res <= 0))
|
|
||||||
fail_fn(count);
|
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,
|
static inline long syscall_get_error(struct task_struct *task,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
return syscall_has_error(regs) ? regs->regs[0] : 0;
|
return IS_ERR_VALUE(regs->regs[0]) ? regs->regs[0] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline long syscall_get_return_value(struct task_struct *task,
|
static inline long syscall_get_return_value(struct task_struct *task,
|
||||||
|
|
@ -50,13 +37,10 @@ static inline void syscall_set_return_value(struct task_struct *task,
|
||||||
struct pt_regs *regs,
|
struct pt_regs *regs,
|
||||||
int error, long val)
|
int error, long val)
|
||||||
{
|
{
|
||||||
if (error) {
|
if (error)
|
||||||
syscall_set_error(regs);
|
|
||||||
regs->regs[0] = -error;
|
regs->regs[0] = -error;
|
||||||
} else {
|
else
|
||||||
syscall_clear_error(regs);
|
|
||||||
regs->regs[0] = val;
|
regs->regs[0] = val;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void syscall_get_arguments(struct task_struct *task,
|
static inline void syscall_get_arguments(struct task_struct *task,
|
||||||
|
|
|
||||||
|
|
@ -21,23 +21,10 @@ static inline void syscall_rollback(struct task_struct *task,
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool syscall_has_error(struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
return (regs->sr & 0x1) ? true : false;
|
|
||||||
}
|
|
||||||
static inline void syscall_set_error(struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
regs->sr |= 0x1;
|
|
||||||
}
|
|
||||||
static inline void syscall_clear_error(struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
regs->sr &= ~0x1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline long syscall_get_error(struct task_struct *task,
|
static inline long syscall_get_error(struct task_struct *task,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
return syscall_has_error(regs) ? regs->regs[9] : 0;
|
return IS_ERR_VALUE(regs->regs[9]) ? regs->regs[9] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline long syscall_get_return_value(struct task_struct *task,
|
static inline long syscall_get_return_value(struct task_struct *task,
|
||||||
|
|
@ -50,13 +37,10 @@ static inline void syscall_set_return_value(struct task_struct *task,
|
||||||
struct pt_regs *regs,
|
struct pt_regs *regs,
|
||||||
int error, long val)
|
int error, long val)
|
||||||
{
|
{
|
||||||
if (error) {
|
if (error)
|
||||||
syscall_set_error(regs);
|
|
||||||
regs->regs[9] = -error;
|
regs->regs[9] = -error;
|
||||||
} else {
|
else
|
||||||
syscall_clear_error(regs);
|
|
||||||
regs->regs[9] = val;
|
regs->regs[9] = val;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void syscall_get_arguments(struct task_struct *task,
|
static inline void syscall_get_arguments(struct task_struct *task,
|
||||||
|
|
|
||||||
|
|
@ -423,7 +423,7 @@ static int ieee_fpe_handler(struct pt_regs *regs)
|
||||||
int m;
|
int m;
|
||||||
unsigned int hx;
|
unsigned int hx;
|
||||||
|
|
||||||
m = (finsn >> 9) & 0x7;
|
m = (finsn >> 8) & 0x7;
|
||||||
hx = tsk->thread.fpu.hard.fp_regs[m];
|
hx = tsk->thread.fpu.hard.fp_regs[m];
|
||||||
|
|
||||||
if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR)
|
if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR)
|
||||||
|
|
|
||||||
|
|
@ -262,9 +262,9 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
|
||||||
BOOTMEM_DEFAULT);
|
BOOTMEM_DEFAULT);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* reserve physical page 0 - it's a special BIOS page on many boxes,
|
* Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
|
||||||
* enabling clean reboots, SMP operation, laptop functions.
|
|
||||||
*/
|
*/
|
||||||
|
if (CONFIG_ZERO_PAGE_OFFSET != 0)
|
||||||
reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET,
|
reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET,
|
||||||
BOOTMEM_DEFAULT);
|
BOOTMEM_DEFAULT);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -510,7 +510,6 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs,
|
||||||
case -ERESTARTNOHAND:
|
case -ERESTARTNOHAND:
|
||||||
no_system_call_restart:
|
no_system_call_restart:
|
||||||
regs->regs[0] = -EINTR;
|
regs->regs[0] = -EINTR;
|
||||||
regs->sr |= 1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case -ERESTARTSYS:
|
case -ERESTARTSYS:
|
||||||
|
|
@ -589,7 +588,6 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
|
||||||
|
|
||||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||||
if (signr > 0) {
|
if (signr > 0) {
|
||||||
if (regs->sr & 1)
|
|
||||||
handle_syscall_restart(save_r0, regs, &ka.sa);
|
handle_syscall_restart(save_r0, regs, &ka.sa);
|
||||||
|
|
||||||
/* Whee! Actually deliver the signal. */
|
/* Whee! Actually deliver the signal. */
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
|
||||||
case -ERESTARTNOHAND:
|
case -ERESTARTNOHAND:
|
||||||
no_system_call_restart:
|
no_system_call_restart:
|
||||||
regs->regs[REG_RET] = -EINTR;
|
regs->regs[REG_RET] = -EINTR;
|
||||||
regs->sr |= 1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case -ERESTARTSYS:
|
case -ERESTARTSYS:
|
||||||
|
|
@ -109,7 +108,6 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
||||||
|
|
||||||
signr = get_signal_to_deliver(&info, &ka, regs, 0);
|
signr = get_signal_to_deliver(&info, &ka, regs, 0);
|
||||||
if (signr > 0) {
|
if (signr > 0) {
|
||||||
if (regs->sr & 1)
|
|
||||||
handle_syscall_restart(regs, &ka.sa);
|
handle_syscall_restart(regs, &ka.sa);
|
||||||
|
|
||||||
/* Whee! Actually deliver the signal. */
|
/* Whee! Actually deliver the signal. */
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* unsigned int csum_partial(const unsigned char *buf, int len,
|
* asmlinkage __wsum csum_partial(const void *buf, int len, __wsum sum);
|
||||||
* unsigned int sum);
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|
@ -49,11 +48,31 @@ ENTRY(csum_partial)
|
||||||
* Fortunately, it is easy to convert 2-byte alignment to 4-byte
|
* Fortunately, it is easy to convert 2-byte alignment to 4-byte
|
||||||
* alignment for the unrolled loop.
|
* alignment for the unrolled loop.
|
||||||
*/
|
*/
|
||||||
mov r5, r1
|
|
||||||
mov r4, r0
|
mov r4, r0
|
||||||
tst #2, r0 ! Check alignment.
|
tst #3, r0 ! Check alignment.
|
||||||
bt 2f ! Jump if alignment is ok.
|
bt/s 2f ! Jump if alignment is ok.
|
||||||
|
mov r4, r7 ! Keep a copy to check for alignment
|
||||||
!
|
!
|
||||||
|
tst #1, r0 ! Check alignment.
|
||||||
|
bt 21f ! Jump if alignment is boundary of 2bytes.
|
||||||
|
|
||||||
|
! buf is odd
|
||||||
|
tst r5, r5
|
||||||
|
add #-1, r5
|
||||||
|
bt 9f
|
||||||
|
mov.b @r4+, r0
|
||||||
|
extu.b r0, r0
|
||||||
|
addc r0, r6 ! t=0 from previous tst
|
||||||
|
mov r6, r0
|
||||||
|
shll8 r6
|
||||||
|
shlr16 r0
|
||||||
|
shlr8 r0
|
||||||
|
or r0, r6
|
||||||
|
mov r4, r0
|
||||||
|
tst #2, r0
|
||||||
|
bt 2f
|
||||||
|
21:
|
||||||
|
! buf is 2 byte aligned (len could be 0)
|
||||||
add #-2, r5 ! Alignment uses up two bytes.
|
add #-2, r5 ! Alignment uses up two bytes.
|
||||||
cmp/pz r5 !
|
cmp/pz r5 !
|
||||||
bt/s 1f ! Jump if we had at least two bytes.
|
bt/s 1f ! Jump if we had at least two bytes.
|
||||||
|
|
@ -61,16 +80,17 @@ ENTRY(csum_partial)
|
||||||
bra 6f
|
bra 6f
|
||||||
add #2, r5 ! r5 was < 2. Deal with it.
|
add #2, r5 ! r5 was < 2. Deal with it.
|
||||||
1:
|
1:
|
||||||
mov r5, r1 ! Save new len for later use.
|
|
||||||
mov.w @r4+, r0
|
mov.w @r4+, r0
|
||||||
extu.w r0, r0
|
extu.w r0, r0
|
||||||
addc r0, r6
|
addc r0, r6
|
||||||
bf 2f
|
bf 2f
|
||||||
add #1, r6
|
add #1, r6
|
||||||
2:
|
2:
|
||||||
|
! buf is 4 byte aligned (len could be 0)
|
||||||
|
mov r5, r1
|
||||||
mov #-5, r0
|
mov #-5, r0
|
||||||
shld r0, r5
|
shld r0, r1
|
||||||
tst r5, r5
|
tst r1, r1
|
||||||
bt/s 4f ! if it's =0, go to 4f
|
bt/s 4f ! if it's =0, go to 4f
|
||||||
clrt
|
clrt
|
||||||
.align 2
|
.align 2
|
||||||
|
|
@ -92,30 +112,31 @@ ENTRY(csum_partial)
|
||||||
addc r0, r6
|
addc r0, r6
|
||||||
addc r2, r6
|
addc r2, r6
|
||||||
movt r0
|
movt r0
|
||||||
dt r5
|
dt r1
|
||||||
bf/s 3b
|
bf/s 3b
|
||||||
cmp/eq #1, r0
|
cmp/eq #1, r0
|
||||||
! here, we know r5==0
|
! here, we know r1==0
|
||||||
addc r5, r6 ! add carry to r6
|
addc r1, r6 ! add carry to r6
|
||||||
4:
|
4:
|
||||||
mov r1, r0
|
mov r5, r0
|
||||||
and #0x1c, r0
|
and #0x1c, r0
|
||||||
tst r0, r0
|
tst r0, r0
|
||||||
bt/s 6f
|
bt 6f
|
||||||
mov r0, r5
|
! 4 bytes or more remaining
|
||||||
shlr2 r5
|
mov r0, r1
|
||||||
|
shlr2 r1
|
||||||
mov #0, r2
|
mov #0, r2
|
||||||
5:
|
5:
|
||||||
addc r2, r6
|
addc r2, r6
|
||||||
mov.l @r4+, r2
|
mov.l @r4+, r2
|
||||||
movt r0
|
movt r0
|
||||||
dt r5
|
dt r1
|
||||||
bf/s 5b
|
bf/s 5b
|
||||||
cmp/eq #1, r0
|
cmp/eq #1, r0
|
||||||
addc r2, r6
|
addc r2, r6
|
||||||
addc r5, r6 ! r5==0 here, so it means add carry-bit
|
addc r1, r6 ! r1==0 here, so it means add carry-bit
|
||||||
6:
|
6:
|
||||||
mov r1, r5
|
! 3 bytes or less remaining
|
||||||
mov #3, r0
|
mov #3, r0
|
||||||
and r0, r5
|
and r0, r5
|
||||||
tst r5, r5
|
tst r5, r5
|
||||||
|
|
@ -141,6 +162,16 @@ ENTRY(csum_partial)
|
||||||
mov #0, r0
|
mov #0, r0
|
||||||
addc r0, r6
|
addc r0, r6
|
||||||
9:
|
9:
|
||||||
|
! Check if the buffer was misaligned, if so realign sum
|
||||||
|
mov r7, r0
|
||||||
|
tst #1, r0
|
||||||
|
bt 10f
|
||||||
|
mov r6, r0
|
||||||
|
shll8 r6
|
||||||
|
shlr16 r0
|
||||||
|
shlr8 r0
|
||||||
|
or r0, r6
|
||||||
|
10:
|
||||||
rts
|
rts
|
||||||
mov r6, r0
|
mov r6, r0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -418,9 +418,9 @@ ENTRY(ia32_syscall)
|
||||||
orl $TS_COMPAT,TI_status(%r10)
|
orl $TS_COMPAT,TI_status(%r10)
|
||||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||||
jnz ia32_tracesys
|
jnz ia32_tracesys
|
||||||
ia32_do_syscall:
|
|
||||||
cmpl $(IA32_NR_syscalls-1),%eax
|
cmpl $(IA32_NR_syscalls-1),%eax
|
||||||
ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
|
ja ia32_badsys
|
||||||
|
ia32_do_call:
|
||||||
IA32_ARG_FIXUP
|
IA32_ARG_FIXUP
|
||||||
call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
|
call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
|
||||||
ia32_sysret:
|
ia32_sysret:
|
||||||
|
|
@ -435,7 +435,9 @@ ia32_tracesys:
|
||||||
call syscall_trace_enter
|
call syscall_trace_enter
|
||||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||||
RESTORE_REST
|
RESTORE_REST
|
||||||
jmp ia32_do_syscall
|
cmpl $(IA32_NR_syscalls-1),%eax
|
||||||
|
ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
|
||||||
|
jmp ia32_do_call
|
||||||
END(ia32_syscall)
|
END(ia32_syscall)
|
||||||
|
|
||||||
ia32_badsys:
|
ia32_badsys:
|
||||||
|
|
|
||||||
|
|
@ -156,11 +156,11 @@ static int __init acpi_sleep_setup(char *str)
|
||||||
#ifdef CONFIG_HIBERNATION
|
#ifdef CONFIG_HIBERNATION
|
||||||
if (strncmp(str, "s4_nohwsig", 10) == 0)
|
if (strncmp(str, "s4_nohwsig", 10) == 0)
|
||||||
acpi_no_s4_hw_signature();
|
acpi_no_s4_hw_signature();
|
||||||
|
if (strncmp(str, "s4_nonvs", 8) == 0)
|
||||||
|
acpi_s4_no_nvs();
|
||||||
#endif
|
#endif
|
||||||
if (strncmp(str, "old_ordering", 12) == 0)
|
if (strncmp(str, "old_ordering", 12) == 0)
|
||||||
acpi_old_suspend_ordering();
|
acpi_old_suspend_ordering();
|
||||||
if (strncmp(str, "s4_nonvs", 8) == 0)
|
|
||||||
acpi_s4_no_nvs();
|
|
||||||
str = strchr(str, ',');
|
str = strchr(str, ',');
|
||||||
if (str != NULL)
|
if (str != NULL)
|
||||||
str += strspn(str, ", \t");
|
str += strspn(str, ", \t");
|
||||||
|
|
|
||||||
|
|
@ -1436,7 +1436,7 @@ static int __init detect_init_APIC(void)
|
||||||
switch (boot_cpu_data.x86_vendor) {
|
switch (boot_cpu_data.x86_vendor) {
|
||||||
case X86_VENDOR_AMD:
|
case X86_VENDOR_AMD:
|
||||||
if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
|
if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
|
||||||
(boot_cpu_data.x86 == 15))
|
(boot_cpu_data.x86 >= 15))
|
||||||
break;
|
break;
|
||||||
goto no_apic;
|
goto no_apic;
|
||||||
case X86_VENDOR_INTEL:
|
case X86_VENDOR_INTEL:
|
||||||
|
|
|
||||||
|
|
@ -245,17 +245,6 @@ config X86_E_POWERSAVER
|
||||||
|
|
||||||
comment "shared options"
|
comment "shared options"
|
||||||
|
|
||||||
config X86_ACPI_CPUFREQ_PROC_INTF
|
|
||||||
bool "/proc/acpi/processor/../performance interface (deprecated)"
|
|
||||||
depends on PROC_FS
|
|
||||||
depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
|
|
||||||
help
|
|
||||||
This enables the deprecated /proc/acpi/processor/../performance
|
|
||||||
interface. While it is helpful for debugging, the generic,
|
|
||||||
cross-architecture cpufreq interfaces should be used.
|
|
||||||
|
|
||||||
If in doubt, say N.
|
|
||||||
|
|
||||||
config X86_SPEEDSTEP_LIB
|
config X86_SPEEDSTEP_LIB
|
||||||
tristate
|
tristate
|
||||||
default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
|
default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,11 @@ static struct _cache_table cache_table[] __cpuinitdata =
|
||||||
{
|
{
|
||||||
{ 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */
|
{ 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */
|
||||||
{ 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */
|
{ 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */
|
||||||
|
{ 0x09, LVL_1_INST, 32 }, /* 4-way set assoc, 64 byte line size */
|
||||||
{ 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */
|
{ 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */
|
||||||
{ 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */
|
{ 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */
|
||||||
|
{ 0x0d, LVL_1_DATA, 16 }, /* 4-way set assoc, 64 byte line size */
|
||||||
|
{ 0x21, LVL_2, 256 }, /* 8-way set assoc, 64 byte line size */
|
||||||
{ 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */
|
{ 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */
|
||||||
{ 0x23, LVL_3, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */
|
{ 0x23, LVL_3, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */
|
||||||
{ 0x25, LVL_3, 2048 }, /* 8-way set assoc, sectored cache, 64 byte line size */
|
{ 0x25, LVL_3, 2048 }, /* 8-way set assoc, sectored cache, 64 byte line size */
|
||||||
|
|
@ -85,6 +88,18 @@ static struct _cache_table cache_table[] __cpuinitdata =
|
||||||
{ 0x85, LVL_2, 2048 }, /* 8-way set assoc, 32 byte line size */
|
{ 0x85, LVL_2, 2048 }, /* 8-way set assoc, 32 byte line size */
|
||||||
{ 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */
|
{ 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */
|
||||||
{ 0x87, LVL_2, 1024 }, /* 8-way set assoc, 64 byte line size */
|
{ 0x87, LVL_2, 1024 }, /* 8-way set assoc, 64 byte line size */
|
||||||
|
{ 0xd0, LVL_3, 512 }, /* 4-way set assoc, 64 byte line size */
|
||||||
|
{ 0xd1, LVL_3, 1024 }, /* 4-way set assoc, 64 byte line size */
|
||||||
|
{ 0xd2, LVL_3, 2048 }, /* 4-way set assoc, 64 byte line size */
|
||||||
|
{ 0xd6, LVL_3, 1024 }, /* 8-way set assoc, 64 byte line size */
|
||||||
|
{ 0xd7, LVL_3, 2038 }, /* 8-way set assoc, 64 byte line size */
|
||||||
|
{ 0xd8, LVL_3, 4096 }, /* 12-way set assoc, 64 byte line size */
|
||||||
|
{ 0xdc, LVL_3, 2048 }, /* 12-way set assoc, 64 byte line size */
|
||||||
|
{ 0xdd, LVL_3, 4096 }, /* 12-way set assoc, 64 byte line size */
|
||||||
|
{ 0xde, LVL_3, 8192 }, /* 12-way set assoc, 64 byte line size */
|
||||||
|
{ 0xe2, LVL_3, 2048 }, /* 16-way set assoc, 64 byte line size */
|
||||||
|
{ 0xe3, LVL_3, 4096 }, /* 16-way set assoc, 64 byte line size */
|
||||||
|
{ 0xe4, LVL_3, 8192 }, /* 16-way set assoc, 64 byte line size */
|
||||||
{ 0x00, 0, 0}
|
{ 0x00, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -346,6 +346,7 @@ ENTRY(save_args)
|
||||||
popq_cfi %rax /* move return address... */
|
popq_cfi %rax /* move return address... */
|
||||||
mov %gs:pda_irqstackptr,%rsp
|
mov %gs:pda_irqstackptr,%rsp
|
||||||
EMPTY_FRAME 0
|
EMPTY_FRAME 0
|
||||||
|
pushq_cfi %rbp /* backlink for unwinder */
|
||||||
pushq_cfi %rax /* ... to the new stack */
|
pushq_cfi %rax /* ... to the new stack */
|
||||||
/*
|
/*
|
||||||
* We entered an interrupt context - irqs are off:
|
* We entered an interrupt context - irqs are off:
|
||||||
|
|
|
||||||
|
|
@ -2528,14 +2528,15 @@ static void irq_complete_move(struct irq_desc **descp)
|
||||||
|
|
||||||
vector = ~get_irq_regs()->orig_ax;
|
vector = ~get_irq_regs()->orig_ax;
|
||||||
me = smp_processor_id();
|
me = smp_processor_id();
|
||||||
|
|
||||||
|
if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) {
|
||||||
#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
|
#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
|
||||||
*descp = desc = move_irq_desc(desc, me);
|
*descp = desc = move_irq_desc(desc, me);
|
||||||
/* get the new one */
|
/* get the new one */
|
||||||
cfg = desc->chip_data;
|
cfg = desc->chip_data;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
|
|
||||||
send_cleanup_vector(cfg);
|
send_cleanup_vector(cfg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline void irq_complete_move(struct irq_desc **descp) {}
|
static inline void irq_complete_move(struct irq_desc **descp) {}
|
||||||
|
|
|
||||||
|
|
@ -78,15 +78,6 @@ void __init init_ISA_irqs(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* IRQ2 is cascade interrupt to second interrupt controller
|
|
||||||
*/
|
|
||||||
static struct irqaction irq2 = {
|
|
||||||
.handler = no_action,
|
|
||||||
.mask = CPU_MASK_NONE,
|
|
||||||
.name = "cascade",
|
|
||||||
};
|
|
||||||
|
|
||||||
DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
|
DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
|
||||||
[0 ... IRQ0_VECTOR - 1] = -1,
|
[0 ... IRQ0_VECTOR - 1] = -1,
|
||||||
[IRQ0_VECTOR] = 0,
|
[IRQ0_VECTOR] = 0,
|
||||||
|
|
@ -178,9 +169,6 @@ void __init native_init_IRQ(void)
|
||||||
alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
|
alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!acpi_ioapic)
|
|
||||||
setup_irq(2, &irq2);
|
|
||||||
|
|
||||||
/* setup after call gates are initialised (usually add in
|
/* setup after call gates are initialised (usually add in
|
||||||
* the architecture specific gates)
|
* the architecture specific gates)
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,15 @@ void __init pre_intr_init_hook(void)
|
||||||
init_ISA_irqs();
|
init_ISA_irqs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IRQ2 is cascade interrupt to second interrupt controller
|
||||||
|
*/
|
||||||
|
static struct irqaction irq2 = {
|
||||||
|
.handler = no_action,
|
||||||
|
.mask = CPU_MASK_NONE,
|
||||||
|
.name = "cascade",
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* intr_init_hook - post gate setup interrupt initialisation
|
* intr_init_hook - post gate setup interrupt initialisation
|
||||||
*
|
*
|
||||||
|
|
@ -53,6 +62,9 @@ void __init intr_init_hook(void)
|
||||||
if (x86_quirks->arch_intr_init())
|
if (x86_quirks->arch_intr_init())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!acpi_ioapic)
|
||||||
|
setup_irq(2, &irq2);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,23 @@ void __init intr_init_hook(void)
|
||||||
setup_irq(2, &irq2);
|
setup_irq(2, &irq2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init pre_setup_arch_hook(void)
|
static void voyager_disable_tsc(void)
|
||||||
{
|
{
|
||||||
/* Voyagers run their CPUs from independent clocks, so disable
|
/* Voyagers run their CPUs from independent clocks, so disable
|
||||||
* the TSC code because we can't sync them */
|
* the TSC code because we can't sync them */
|
||||||
setup_clear_cpu_cap(X86_FEATURE_TSC);
|
setup_clear_cpu_cap(X86_FEATURE_TSC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __init pre_setup_arch_hook(void)
|
||||||
|
{
|
||||||
|
voyager_disable_tsc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init pre_time_init_hook(void)
|
||||||
|
{
|
||||||
|
voyager_disable_tsc();
|
||||||
|
}
|
||||||
|
|
||||||
void __init trap_init_hook(void)
|
void __init trap_init_hook(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ static void enable_local_vic_irq(unsigned int irq);
|
||||||
static void disable_local_vic_irq(unsigned int irq);
|
static void disable_local_vic_irq(unsigned int irq);
|
||||||
static void before_handle_vic_irq(unsigned int irq);
|
static void before_handle_vic_irq(unsigned int irq);
|
||||||
static void after_handle_vic_irq(unsigned int irq);
|
static void after_handle_vic_irq(unsigned int irq);
|
||||||
static void set_vic_irq_affinity(unsigned int irq, cpumask_t mask);
|
static void set_vic_irq_affinity(unsigned int irq, const struct cpumask *mask);
|
||||||
static void ack_vic_irq(unsigned int irq);
|
static void ack_vic_irq(unsigned int irq);
|
||||||
static void vic_enable_cpi(void);
|
static void vic_enable_cpi(void);
|
||||||
static void do_boot_cpu(__u8 cpuid);
|
static void do_boot_cpu(__u8 cpuid);
|
||||||
|
|
@ -211,8 +211,6 @@ static __u32 cpu_booted_map;
|
||||||
static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
|
static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
|
||||||
|
|
||||||
/* This is for the new dynamic CPU boot code */
|
/* This is for the new dynamic CPU boot code */
|
||||||
cpumask_t cpu_callin_map = CPU_MASK_NONE;
|
|
||||||
cpumask_t cpu_callout_map = CPU_MASK_NONE;
|
|
||||||
|
|
||||||
/* The per processor IRQ masks (these are usually kept in sync) */
|
/* The per processor IRQ masks (these are usually kept in sync) */
|
||||||
static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned;
|
static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned;
|
||||||
|
|
@ -378,7 +376,7 @@ void __init find_smp_config(void)
|
||||||
cpus_addr(phys_cpu_present_map)[0] |=
|
cpus_addr(phys_cpu_present_map)[0] |=
|
||||||
voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK +
|
voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK +
|
||||||
3) << 24;
|
3) << 24;
|
||||||
cpu_possible_map = phys_cpu_present_map;
|
init_cpu_possible(&phys_cpu_present_map);
|
||||||
printk("VOYAGER SMP: phys_cpu_present_map = 0x%lx\n",
|
printk("VOYAGER SMP: phys_cpu_present_map = 0x%lx\n",
|
||||||
cpus_addr(phys_cpu_present_map)[0]);
|
cpus_addr(phys_cpu_present_map)[0]);
|
||||||
/* Here we set up the VIC to enable SMP */
|
/* Here we set up the VIC to enable SMP */
|
||||||
|
|
@ -1599,16 +1597,16 @@ static void after_handle_vic_irq(unsigned int irq)
|
||||||
* change the mask and then do an interrupt enable CPI to re-enable on
|
* change the mask and then do an interrupt enable CPI to re-enable on
|
||||||
* the selected processors */
|
* the selected processors */
|
||||||
|
|
||||||
void set_vic_irq_affinity(unsigned int irq, cpumask_t mask)
|
void set_vic_irq_affinity(unsigned int irq, const struct cpumask *mask)
|
||||||
{
|
{
|
||||||
/* Only extended processors handle interrupts */
|
/* Only extended processors handle interrupts */
|
||||||
unsigned long real_mask;
|
unsigned long real_mask;
|
||||||
unsigned long irq_mask = 1 << irq;
|
unsigned long irq_mask = 1 << irq;
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
||||||
real_mask = cpus_addr(mask)[0] & voyager_extended_vic_processors;
|
real_mask = cpus_addr(*mask)[0] & voyager_extended_vic_processors;
|
||||||
|
|
||||||
if (cpus_addr(mask)[0] == 0)
|
if (cpus_addr(*mask)[0] == 0)
|
||||||
/* can't have no CPUs to accept the interrupt -- extremely
|
/* can't have no CPUs to accept the interrupt -- extremely
|
||||||
* bad things will happen */
|
* bad things will happen */
|
||||||
return;
|
return;
|
||||||
|
|
@ -1750,10 +1748,11 @@ static void __cpuinit voyager_smp_prepare_boot_cpu(void)
|
||||||
init_gdt(smp_processor_id());
|
init_gdt(smp_processor_id());
|
||||||
switch_to_new_gdt();
|
switch_to_new_gdt();
|
||||||
|
|
||||||
cpu_set(smp_processor_id(), cpu_online_map);
|
cpu_online_map = cpumask_of_cpu(smp_processor_id());
|
||||||
cpu_set(smp_processor_id(), cpu_callout_map);
|
cpu_callout_map = cpumask_of_cpu(smp_processor_id());
|
||||||
cpu_set(smp_processor_id(), cpu_possible_map);
|
cpu_callin_map = CPU_MASK_NONE;
|
||||||
cpu_set(smp_processor_id(), cpu_present_map);
|
cpu_present_map = cpumask_of_cpu(smp_processor_id());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __cpuinit voyager_cpu_up(unsigned int cpu)
|
static int __cpuinit voyager_cpu_up(unsigned int cpu)
|
||||||
|
|
@ -1783,9 +1782,9 @@ void __init smp_setup_processor_id(void)
|
||||||
x86_write_percpu(cpu_number, hard_smp_processor_id());
|
x86_write_percpu(cpu_number, hard_smp_processor_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void voyager_send_call_func(cpumask_t callmask)
|
static void voyager_send_call_func(const struct cpumask *callmask)
|
||||||
{
|
{
|
||||||
__u32 mask = cpus_addr(callmask)[0] & ~(1 << smp_processor_id());
|
__u32 mask = cpus_addr(*callmask)[0] & ~(1 << smp_processor_id());
|
||||||
send_CPI(mask, VIC_CALL_FUNCTION_CPI);
|
send_CPI(mask, VIC_CALL_FUNCTION_CPI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -603,8 +603,6 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||||
|
|
||||||
si_code = SEGV_MAPERR;
|
si_code = SEGV_MAPERR;
|
||||||
|
|
||||||
if (notify_page_fault(regs))
|
|
||||||
return;
|
|
||||||
if (unlikely(kmmio_fault(regs, address)))
|
if (unlikely(kmmio_fault(regs, address)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -634,6 +632,9 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||||
if (spurious_fault(address, error_code))
|
if (spurious_fault(address, error_code))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* kprobes don't want to hook the spurious faults. */
|
||||||
|
if (notify_page_fault(regs))
|
||||||
|
return;
|
||||||
/*
|
/*
|
||||||
* Don't take the mm semaphore here. If we fixup a prefetch
|
* Don't take the mm semaphore here. If we fixup a prefetch
|
||||||
* fault we could otherwise deadlock.
|
* fault we could otherwise deadlock.
|
||||||
|
|
@ -641,6 +642,9 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||||
goto bad_area_nosemaphore;
|
goto bad_area_nosemaphore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* kprobes don't want to hook the spurious faults. */
|
||||||
|
if (notify_page_fault(regs))
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It's safe to allow irq's after cr2 has been saved and the
|
* It's safe to allow irq's after cr2 has been saved and the
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,10 @@ DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags);
|
||||||
paired with xen_mc_issue() */
|
paired with xen_mc_issue() */
|
||||||
static inline void xen_mc_batch(void)
|
static inline void xen_mc_batch(void)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
/* need to disable interrupts until this entry is complete */
|
/* need to disable interrupts until this entry is complete */
|
||||||
local_irq_save(__get_cpu_var(xen_mc_irq_flags));
|
local_irq_save(flags);
|
||||||
|
__get_cpu_var(xen_mc_irq_flags) = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct multicall_space xen_mc_entry(size_t args)
|
static inline struct multicall_space xen_mc_entry(size_t args)
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ menuconfig ACPI
|
||||||
depends on PCI
|
depends on PCI
|
||||||
depends on PM
|
depends on PM
|
||||||
select PNP
|
select PNP
|
||||||
|
select CPU_IDLE
|
||||||
default y
|
default y
|
||||||
---help---
|
---help---
|
||||||
Advanced Configuration and Power Interface (ACPI) support for
|
Advanced Configuration and Power Interface (ACPI) support for
|
||||||
|
|
@ -287,7 +288,7 @@ config ACPI_CONTAINER
|
||||||
support physical cpu/memory hot-plug.
|
support physical cpu/memory hot-plug.
|
||||||
|
|
||||||
If one selects "m", this driver can be loaded with
|
If one selects "m", this driver can be loaded with
|
||||||
"modprobe acpi_container".
|
"modprobe container".
|
||||||
|
|
||||||
config ACPI_HOTPLUG_MEMORY
|
config ACPI_HOTPLUG_MEMORY
|
||||||
tristate "Memory Hotplug"
|
tristate "Memory Hotplug"
|
||||||
|
|
|
||||||
|
|
@ -538,10 +538,9 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
ACPI_WARNING((AE_INFO,
|
ACPI_WARNING((AE_INFO,
|
||||||
"Truncating %u table entries!",
|
"Truncating %u table entries!",
|
||||||
(unsigned)
|
(unsigned) (table_count -
|
||||||
(acpi_gbl_root_table_list.size -
|
(acpi_gbl_root_table_list.
|
||||||
acpi_gbl_root_table_list.
|
count - 2))));
|
||||||
count)));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -116,9 +116,9 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
|
||||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default return value is SUPPORTED */
|
/* Default return value is 0, NOT-SUPPORTED */
|
||||||
|
|
||||||
return_desc->integer.value = ACPI_UINT32_MAX;
|
return_desc->integer.value = 0;
|
||||||
walk_state->return_desc = return_desc;
|
walk_state->return_desc = return_desc;
|
||||||
|
|
||||||
/* Compare input string to static table of supported interfaces */
|
/* Compare input string to static table of supported interfaces */
|
||||||
|
|
@ -127,10 +127,8 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
|
||||||
if (!ACPI_STRCMP
|
if (!ACPI_STRCMP
|
||||||
(string_desc->string.pointer,
|
(string_desc->string.pointer,
|
||||||
acpi_interfaces_supported[i])) {
|
acpi_interfaces_supported[i])) {
|
||||||
|
return_desc->integer.value = ACPI_UINT32_MAX;
|
||||||
/* The interface is supported */
|
goto done;
|
||||||
|
|
||||||
return_ACPI_STATUS(AE_OK);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,15 +139,14 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
|
||||||
*/
|
*/
|
||||||
status = acpi_os_validate_interface(string_desc->string.pointer);
|
status = acpi_os_validate_interface(string_desc->string.pointer);
|
||||||
if (ACPI_SUCCESS(status)) {
|
if (ACPI_SUCCESS(status)) {
|
||||||
|
return_desc->integer.value = ACPI_UINT32_MAX;
|
||||||
/* The interface is supported */
|
|
||||||
|
|
||||||
return_ACPI_STATUS(AE_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The interface is not supported */
|
done:
|
||||||
|
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, "ACPI: BIOS _OSI(%s) %ssupported\n",
|
||||||
|
string_desc->string.pointer,
|
||||||
|
return_desc->integer.value == 0 ? "not-" : ""));
|
||||||
|
|
||||||
return_desc->integer.value = 0;
|
|
||||||
return_ACPI_STATUS(AE_OK);
|
return_ACPI_STATUS(AE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
|
||||||
case ACPI_NOTIFY_BUS_CHECK:
|
case ACPI_NOTIFY_BUS_CHECK:
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||||
printk("Container driver received %s event\n",
|
printk(KERN_WARNING "Container driver received %s event\n",
|
||||||
(type == ACPI_NOTIFY_BUS_CHECK) ?
|
(type == ACPI_NOTIFY_BUS_CHECK) ?
|
||||||
"ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
|
"ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
|
||||||
status = acpi_bus_get_device(handle, &device);
|
status = acpi_bus_get_device(handle, &device);
|
||||||
|
|
@ -174,7 +174,8 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
|
||||||
kobject_uevent(&device->dev.kobj,
|
kobject_uevent(&device->dev.kobj,
|
||||||
KOBJ_ONLINE);
|
KOBJ_ONLINE);
|
||||||
else
|
else
|
||||||
printk("Failed to add container\n");
|
printk(KERN_WARNING
|
||||||
|
"Failed to add container\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ACPI_SUCCESS(status)) {
|
if (ACPI_SUCCESS(status)) {
|
||||||
|
|
|
||||||
|
|
@ -855,10 +855,14 @@ fdd_out:
|
||||||
static ssize_t show_docked(struct device *dev,
|
static ssize_t show_docked(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
|
struct acpi_device *tmp;
|
||||||
|
|
||||||
struct dock_station *dock_station = *((struct dock_station **)
|
struct dock_station *dock_station = *((struct dock_station **)
|
||||||
dev->platform_data);
|
dev->platform_data);
|
||||||
return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
|
|
||||||
|
|
||||||
|
if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp)))
|
||||||
|
return snprintf(buf, PAGE_SIZE, "1\n");
|
||||||
|
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
|
static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
|
||||||
|
|
||||||
|
|
@ -984,7 +988,7 @@ static int dock_add(acpi_handle handle)
|
||||||
|
|
||||||
ret = device_create_file(&dock_device->dev, &dev_attr_docked);
|
ret = device_create_file(&dock_device->dev, &dev_attr_docked);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk("Error %d adding sysfs file\n", ret);
|
printk(KERN_ERR "Error %d adding sysfs file\n", ret);
|
||||||
platform_device_unregister(dock_device);
|
platform_device_unregister(dock_device);
|
||||||
kfree(dock_station);
|
kfree(dock_station);
|
||||||
dock_station = NULL;
|
dock_station = NULL;
|
||||||
|
|
@ -992,7 +996,7 @@ static int dock_add(acpi_handle handle)
|
||||||
}
|
}
|
||||||
ret = device_create_file(&dock_device->dev, &dev_attr_undock);
|
ret = device_create_file(&dock_device->dev, &dev_attr_undock);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk("Error %d adding sysfs file\n", ret);
|
printk(KERN_ERR "Error %d adding sysfs file\n", ret);
|
||||||
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
||||||
platform_device_unregister(dock_device);
|
platform_device_unregister(dock_device);
|
||||||
kfree(dock_station);
|
kfree(dock_station);
|
||||||
|
|
@ -1001,7 +1005,7 @@ static int dock_add(acpi_handle handle)
|
||||||
}
|
}
|
||||||
ret = device_create_file(&dock_device->dev, &dev_attr_uid);
|
ret = device_create_file(&dock_device->dev, &dev_attr_uid);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk("Error %d adding sysfs file\n", ret);
|
printk(KERN_ERR "Error %d adding sysfs file\n", ret);
|
||||||
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
||||||
device_remove_file(&dock_device->dev, &dev_attr_undock);
|
device_remove_file(&dock_device->dev, &dev_attr_undock);
|
||||||
platform_device_unregister(dock_device);
|
platform_device_unregister(dock_device);
|
||||||
|
|
@ -1011,7 +1015,7 @@ static int dock_add(acpi_handle handle)
|
||||||
}
|
}
|
||||||
ret = device_create_file(&dock_device->dev, &dev_attr_flags);
|
ret = device_create_file(&dock_device->dev, &dev_attr_flags);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk("Error %d adding sysfs file\n", ret);
|
printk(KERN_ERR "Error %d adding sysfs file\n", ret);
|
||||||
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
||||||
device_remove_file(&dock_device->dev, &dev_attr_undock);
|
device_remove_file(&dock_device->dev, &dev_attr_undock);
|
||||||
device_remove_file(&dock_device->dev, &dev_attr_uid);
|
device_remove_file(&dock_device->dev, &dev_attr_uid);
|
||||||
|
|
|
||||||
|
|
@ -982,7 +982,7 @@ int __init acpi_ec_ecdt_probe(void)
|
||||||
saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
|
saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
|
||||||
if (!saved_ec)
|
if (!saved_ec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
memcpy(&saved_ec, boot_ec, sizeof(saved_ec));
|
memcpy(saved_ec, boot_ec, sizeof(*saved_ec));
|
||||||
/* fall through */
|
/* fall through */
|
||||||
}
|
}
|
||||||
/* This workaround is needed only on some broken machines,
|
/* This workaround is needed only on some broken machines,
|
||||||
|
|
|
||||||
|
|
@ -255,12 +255,12 @@ static int acpi_platform_notify(struct device *dev)
|
||||||
}
|
}
|
||||||
type = acpi_get_bus_type(dev->bus);
|
type = acpi_get_bus_type(dev->bus);
|
||||||
if (!type) {
|
if (!type) {
|
||||||
DBG("No ACPI bus support for %s\n", dev->bus_id);
|
DBG("No ACPI bus support for %s\n", dev_name(dev));
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
if ((ret = type->find_device(dev, &handle)) != 0)
|
if ((ret = type->find_device(dev, &handle)) != 0)
|
||||||
DBG("Can't get handler for %s\n", dev->bus_id);
|
DBG("Can't get handler for %s\n", dev_name(dev));
|
||||||
end:
|
end:
|
||||||
if (!ret)
|
if (!ret)
|
||||||
acpi_bind_one(dev, handle);
|
acpi_bind_one(dev, handle);
|
||||||
|
|
@ -271,10 +271,10 @@ static int acpi_platform_notify(struct device *dev)
|
||||||
|
|
||||||
acpi_get_name(dev->archdata.acpi_handle,
|
acpi_get_name(dev->archdata.acpi_handle,
|
||||||
ACPI_FULL_PATHNAME, &buffer);
|
ACPI_FULL_PATHNAME, &buffer);
|
||||||
DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer);
|
DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer);
|
||||||
kfree(buffer.pointer);
|
kfree(buffer.pointer);
|
||||||
} else
|
} else
|
||||||
DBG("Device %s -> No ACPI support\n", dev->bus_id);
|
DBG("Device %s -> No ACPI support\n", dev_name(dev));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -228,10 +228,10 @@ void acpi_os_vprintf(const char *fmt, va_list args)
|
||||||
if (acpi_in_debugger) {
|
if (acpi_in_debugger) {
|
||||||
kdb_printf("%s", buffer);
|
kdb_printf("%s", buffer);
|
||||||
} else {
|
} else {
|
||||||
printk("%s", buffer);
|
printk(KERN_CONT "%s", buffer);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
printk("%s", buffer);
|
printk(KERN_CONT "%s", buffer);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1317,6 +1317,54 @@ acpi_os_validate_interface (char *interface)
|
||||||
return AE_SUPPORT;
|
return AE_SUPPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86
|
||||||
|
|
||||||
|
struct aml_port_desc {
|
||||||
|
uint start;
|
||||||
|
uint end;
|
||||||
|
char* name;
|
||||||
|
char warned;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct aml_port_desc aml_invalid_port_list[] = {
|
||||||
|
{0x20, 0x21, "PIC0", 0},
|
||||||
|
{0xA0, 0xA1, "PIC1", 0},
|
||||||
|
{0x4D0, 0x4D1, "ELCR", 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* valid_aml_io_address()
|
||||||
|
*
|
||||||
|
* if valid, return true
|
||||||
|
* else invalid, warn once, return false
|
||||||
|
*/
|
||||||
|
static bool valid_aml_io_address(uint address, uint length)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int entries = sizeof(aml_invalid_port_list) / sizeof(struct aml_port_desc);
|
||||||
|
|
||||||
|
for (i = 0; i < entries; ++i) {
|
||||||
|
if ((address >= aml_invalid_port_list[i].start &&
|
||||||
|
address <= aml_invalid_port_list[i].end) ||
|
||||||
|
(address + length >= aml_invalid_port_list[i].start &&
|
||||||
|
address + length <= aml_invalid_port_list[i].end))
|
||||||
|
{
|
||||||
|
if (!aml_invalid_port_list[i].warned)
|
||||||
|
{
|
||||||
|
printk(KERN_ERR "ACPI: Denied BIOS AML access"
|
||||||
|
" to invalid port 0x%x+0x%x (%s)\n",
|
||||||
|
address, length,
|
||||||
|
aml_invalid_port_list[i].name);
|
||||||
|
aml_invalid_port_list[i].warned = 1;
|
||||||
|
}
|
||||||
|
return false; /* invalid */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true; /* valid */
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline bool valid_aml_io_address(uint address, uint length) { return true; }
|
||||||
|
#endif
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* FUNCTION: acpi_os_validate_address
|
* FUNCTION: acpi_os_validate_address
|
||||||
|
|
@ -1346,6 +1394,8 @@ acpi_os_validate_address (
|
||||||
|
|
||||||
switch (space_id) {
|
switch (space_id) {
|
||||||
case ACPI_ADR_SPACE_SYSTEM_IO:
|
case ACPI_ADR_SPACE_SYSTEM_IO:
|
||||||
|
if (!valid_aml_io_address(address, length))
|
||||||
|
return AE_AML_ILLEGAL_ADDRESS;
|
||||||
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
||||||
/* Only interference checks against SystemIO and SytemMemory
|
/* Only interference checks against SystemIO and SytemMemory
|
||||||
are needed */
|
are needed */
|
||||||
|
|
|
||||||
|
|
@ -593,7 +593,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
} else {
|
} else {
|
||||||
acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
|
acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
|
||||||
printk(PREFIX "%s [%s] enabled at IRQ %d\n",
|
printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
|
||||||
acpi_device_name(link->device),
|
acpi_device_name(link->device),
|
||||||
acpi_device_bid(link->device), link->irq.active);
|
acpi_device_bid(link->device), link->irq.active);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,43 +66,17 @@ ACPI_MODULE_NAME("processor_idle");
|
||||||
#define ACPI_PROCESSOR_FILE_POWER "power"
|
#define ACPI_PROCESSOR_FILE_POWER "power"
|
||||||
#define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
|
#define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
|
||||||
#define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY)
|
#define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY)
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
#define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */
|
|
||||||
#define C3_OVERHEAD 4 /* 1us (3.579 ticks per us) */
|
|
||||||
static void (*pm_idle_save) (void) __read_mostly;
|
|
||||||
#else
|
|
||||||
#define C2_OVERHEAD 1 /* 1us */
|
#define C2_OVERHEAD 1 /* 1us */
|
||||||
#define C3_OVERHEAD 1 /* 1us */
|
#define C3_OVERHEAD 1 /* 1us */
|
||||||
#endif
|
|
||||||
#define PM_TIMER_TICKS_TO_US(p) (((p) * 1000)/(PM_TIMER_FREQUENCY/1000))
|
#define PM_TIMER_TICKS_TO_US(p) (((p) * 1000)/(PM_TIMER_FREQUENCY/1000))
|
||||||
|
|
||||||
static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;
|
static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;
|
||||||
#ifdef CONFIG_CPU_IDLE
|
|
||||||
module_param(max_cstate, uint, 0000);
|
module_param(max_cstate, uint, 0000);
|
||||||
#else
|
|
||||||
module_param(max_cstate, uint, 0644);
|
|
||||||
#endif
|
|
||||||
static unsigned int nocst __read_mostly;
|
static unsigned int nocst __read_mostly;
|
||||||
module_param(nocst, uint, 0000);
|
module_param(nocst, uint, 0000);
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
/*
|
|
||||||
* bm_history -- bit-mask with a bit per jiffy of bus-master activity
|
|
||||||
* 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms
|
|
||||||
* 800 HZ: 0xFFFFFFFF: 32 jiffies = 40ms
|
|
||||||
* 100 HZ: 0x0000000F: 4 jiffies = 40ms
|
|
||||||
* reduce history for more aggressive entry into C3
|
|
||||||
*/
|
|
||||||
static unsigned int bm_history __read_mostly =
|
|
||||||
(HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
|
|
||||||
module_param(bm_history, uint, 0644);
|
|
||||||
|
|
||||||
static int acpi_processor_set_power_policy(struct acpi_processor *pr);
|
|
||||||
|
|
||||||
#else /* CONFIG_CPU_IDLE */
|
|
||||||
static unsigned int latency_factor __read_mostly = 2;
|
static unsigned int latency_factor __read_mostly = 2;
|
||||||
module_param(latency_factor, uint, 0644);
|
module_param(latency_factor, uint, 0644);
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
|
* IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
|
||||||
|
|
@ -224,71 +198,6 @@ static void acpi_safe_halt(void)
|
||||||
current_thread_info()->status |= TS_POLLING;
|
current_thread_info()->status |= TS_POLLING;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
|
|
||||||
static void
|
|
||||||
acpi_processor_power_activate(struct acpi_processor *pr,
|
|
||||||
struct acpi_processor_cx *new)
|
|
||||||
{
|
|
||||||
struct acpi_processor_cx *old;
|
|
||||||
|
|
||||||
if (!pr || !new)
|
|
||||||
return;
|
|
||||||
|
|
||||||
old = pr->power.state;
|
|
||||||
|
|
||||||
if (old)
|
|
||||||
old->promotion.count = 0;
|
|
||||||
new->demotion.count = 0;
|
|
||||||
|
|
||||||
/* Cleanup from old state. */
|
|
||||||
if (old) {
|
|
||||||
switch (old->type) {
|
|
||||||
case ACPI_STATE_C3:
|
|
||||||
/* Disable bus master reload */
|
|
||||||
if (new->type != ACPI_STATE_C3 && pr->flags.bm_check)
|
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare to use new state. */
|
|
||||||
switch (new->type) {
|
|
||||||
case ACPI_STATE_C3:
|
|
||||||
/* Enable bus master reload */
|
|
||||||
if (old->type != ACPI_STATE_C3 && pr->flags.bm_check)
|
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr->power.state = new;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static atomic_t c3_cpu_count;
|
|
||||||
|
|
||||||
/* Common C-state entry for C2, C3, .. */
|
|
||||||
static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
|
|
||||||
{
|
|
||||||
/* Don't trace irqs off for idle */
|
|
||||||
stop_critical_timings();
|
|
||||||
if (cstate->entry_method == ACPI_CSTATE_FFH) {
|
|
||||||
/* Call into architectural FFH based C-state */
|
|
||||||
acpi_processor_ffh_cstate_enter(cstate);
|
|
||||||
} else {
|
|
||||||
int unused;
|
|
||||||
/* IO port based C-state */
|
|
||||||
inb(cstate->address);
|
|
||||||
/* Dummy wait op - must do something useless after P_LVL2 read
|
|
||||||
because chipsets cannot guarantee that STPCLK# signal
|
|
||||||
gets asserted in time to freeze execution properly. */
|
|
||||||
unused = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
|
||||||
}
|
|
||||||
start_critical_timings();
|
|
||||||
}
|
|
||||||
#endif /* !CONFIG_CPU_IDLE */
|
|
||||||
|
|
||||||
#ifdef ARCH_APICTIMER_STOPS_ON_C3
|
#ifdef ARCH_APICTIMER_STOPS_ON_C3
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -390,421 +299,6 @@ static int tsc_halts_in_c(int state)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
static void acpi_processor_idle(void)
|
|
||||||
{
|
|
||||||
struct acpi_processor *pr = NULL;
|
|
||||||
struct acpi_processor_cx *cx = NULL;
|
|
||||||
struct acpi_processor_cx *next_state = NULL;
|
|
||||||
int sleep_ticks = 0;
|
|
||||||
u32 t1, t2 = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Interrupts must be disabled during bus mastering calculations and
|
|
||||||
* for C2/C3 transitions.
|
|
||||||
*/
|
|
||||||
local_irq_disable();
|
|
||||||
|
|
||||||
pr = __get_cpu_var(processors);
|
|
||||||
if (!pr) {
|
|
||||||
local_irq_enable();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check whether we truly need to go idle, or should
|
|
||||||
* reschedule:
|
|
||||||
*/
|
|
||||||
if (unlikely(need_resched())) {
|
|
||||||
local_irq_enable();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cx = pr->power.state;
|
|
||||||
if (!cx || acpi_idle_suspend) {
|
|
||||||
if (pm_idle_save) {
|
|
||||||
pm_idle_save(); /* enables IRQs */
|
|
||||||
} else {
|
|
||||||
acpi_safe_halt();
|
|
||||||
local_irq_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check BM Activity
|
|
||||||
* -----------------
|
|
||||||
* Check for bus mastering activity (if required), record, and check
|
|
||||||
* for demotion.
|
|
||||||
*/
|
|
||||||
if (pr->flags.bm_check) {
|
|
||||||
u32 bm_status = 0;
|
|
||||||
unsigned long diff = jiffies - pr->power.bm_check_timestamp;
|
|
||||||
|
|
||||||
if (diff > 31)
|
|
||||||
diff = 31;
|
|
||||||
|
|
||||||
pr->power.bm_activity <<= diff;
|
|
||||||
|
|
||||||
acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
|
|
||||||
if (bm_status) {
|
|
||||||
pr->power.bm_activity |= 0x1;
|
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
|
|
||||||
* the true state of bus mastering activity; forcing us to
|
|
||||||
* manually check the BMIDEA bit of each IDE channel.
|
|
||||||
*/
|
|
||||||
else if (errata.piix4.bmisx) {
|
|
||||||
if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01)
|
|
||||||
|| (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
|
|
||||||
pr->power.bm_activity |= 0x1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr->power.bm_check_timestamp = jiffies;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If bus mastering is or was active this jiffy, demote
|
|
||||||
* to avoid a faulty transition. Note that the processor
|
|
||||||
* won't enter a low-power state during this call (to this
|
|
||||||
* function) but should upon the next.
|
|
||||||
*
|
|
||||||
* TBD: A better policy might be to fallback to the demotion
|
|
||||||
* state (use it for this quantum only) istead of
|
|
||||||
* demoting -- and rely on duration as our sole demotion
|
|
||||||
* qualification. This may, however, introduce DMA
|
|
||||||
* issues (e.g. floppy DMA transfer overrun/underrun).
|
|
||||||
*/
|
|
||||||
if ((pr->power.bm_activity & 0x1) &&
|
|
||||||
cx->demotion.threshold.bm) {
|
|
||||||
local_irq_enable();
|
|
||||||
next_state = cx->demotion.state;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
/*
|
|
||||||
* Check for P_LVL2_UP flag before entering C2 and above on
|
|
||||||
* an SMP system. We do it here instead of doing it at _CST/P_LVL
|
|
||||||
* detection phase, to work cleanly with logical CPU hotplug.
|
|
||||||
*/
|
|
||||||
if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
|
|
||||||
!pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
|
|
||||||
cx = &pr->power.states[ACPI_STATE_C1];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sleep:
|
|
||||||
* ------
|
|
||||||
* Invoke the current Cx state to put the processor to sleep.
|
|
||||||
*/
|
|
||||||
if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) {
|
|
||||||
current_thread_info()->status &= ~TS_POLLING;
|
|
||||||
/*
|
|
||||||
* TS_POLLING-cleared state must be visible before we
|
|
||||||
* test NEED_RESCHED:
|
|
||||||
*/
|
|
||||||
smp_mb();
|
|
||||||
if (need_resched()) {
|
|
||||||
current_thread_info()->status |= TS_POLLING;
|
|
||||||
local_irq_enable();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (cx->type) {
|
|
||||||
|
|
||||||
case ACPI_STATE_C1:
|
|
||||||
/*
|
|
||||||
* Invoke C1.
|
|
||||||
* Use the appropriate idle routine, the one that would
|
|
||||||
* be used without acpi C-states.
|
|
||||||
*/
|
|
||||||
if (pm_idle_save) {
|
|
||||||
pm_idle_save(); /* enables IRQs */
|
|
||||||
} else {
|
|
||||||
acpi_safe_halt();
|
|
||||||
local_irq_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TBD: Can't get time duration while in C1, as resumes
|
|
||||||
* go to an ISR rather than here. Need to instrument
|
|
||||||
* base interrupt handler.
|
|
||||||
*
|
|
||||||
* Note: the TSC better not stop in C1, sched_clock() will
|
|
||||||
* skew otherwise.
|
|
||||||
*/
|
|
||||||
sleep_ticks = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACPI_STATE_C2:
|
|
||||||
/* Get start time (ticks) */
|
|
||||||
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
|
||||||
/* Tell the scheduler that we are going deep-idle: */
|
|
||||||
sched_clock_idle_sleep_event();
|
|
||||||
/* Invoke C2 */
|
|
||||||
acpi_state_timer_broadcast(pr, cx, 1);
|
|
||||||
acpi_cstate_enter(cx);
|
|
||||||
/* Get end time (ticks) */
|
|
||||||
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
|
||||||
|
|
||||||
#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
|
|
||||||
/* TSC halts in C2, so notify users */
|
|
||||||
if (tsc_halts_in_c(ACPI_STATE_C2))
|
|
||||||
mark_tsc_unstable("possible TSC halt in C2");
|
|
||||||
#endif
|
|
||||||
/* Compute time (ticks) that we were actually asleep */
|
|
||||||
sleep_ticks = ticks_elapsed(t1, t2);
|
|
||||||
|
|
||||||
/* Tell the scheduler how much we idled: */
|
|
||||||
sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
|
|
||||||
|
|
||||||
/* Re-enable interrupts */
|
|
||||||
local_irq_enable();
|
|
||||||
/* Do not account our idle-switching overhead: */
|
|
||||||
sleep_ticks -= cx->latency_ticks + C2_OVERHEAD;
|
|
||||||
|
|
||||||
current_thread_info()->status |= TS_POLLING;
|
|
||||||
acpi_state_timer_broadcast(pr, cx, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACPI_STATE_C3:
|
|
||||||
acpi_unlazy_tlb(smp_processor_id());
|
|
||||||
/*
|
|
||||||
* Must be done before busmaster disable as we might
|
|
||||||
* need to access HPET !
|
|
||||||
*/
|
|
||||||
acpi_state_timer_broadcast(pr, cx, 1);
|
|
||||||
/*
|
|
||||||
* disable bus master
|
|
||||||
* bm_check implies we need ARB_DIS
|
|
||||||
* !bm_check implies we need cache flush
|
|
||||||
* bm_control implies whether we can do ARB_DIS
|
|
||||||
*
|
|
||||||
* That leaves a case where bm_check is set and bm_control is
|
|
||||||
* not set. In that case we cannot do much, we enter C3
|
|
||||||
* without doing anything.
|
|
||||||
*/
|
|
||||||
if (pr->flags.bm_check && pr->flags.bm_control) {
|
|
||||||
if (atomic_inc_return(&c3_cpu_count) ==
|
|
||||||
num_online_cpus()) {
|
|
||||||
/*
|
|
||||||
* All CPUs are trying to go to C3
|
|
||||||
* Disable bus master arbitration
|
|
||||||
*/
|
|
||||||
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
|
|
||||||
}
|
|
||||||
} else if (!pr->flags.bm_check) {
|
|
||||||
/* SMP with no shared cache... Invalidate cache */
|
|
||||||
ACPI_FLUSH_CPU_CACHE();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get start time (ticks) */
|
|
||||||
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
|
||||||
/* Invoke C3 */
|
|
||||||
/* Tell the scheduler that we are going deep-idle: */
|
|
||||||
sched_clock_idle_sleep_event();
|
|
||||||
acpi_cstate_enter(cx);
|
|
||||||
/* Get end time (ticks) */
|
|
||||||
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
|
||||||
if (pr->flags.bm_check && pr->flags.bm_control) {
|
|
||||||
/* Enable bus master arbitration */
|
|
||||||
atomic_dec(&c3_cpu_count);
|
|
||||||
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
|
|
||||||
/* TSC halts in C3, so notify users */
|
|
||||||
if (tsc_halts_in_c(ACPI_STATE_C3))
|
|
||||||
mark_tsc_unstable("TSC halts in C3");
|
|
||||||
#endif
|
|
||||||
/* Compute time (ticks) that we were actually asleep */
|
|
||||||
sleep_ticks = ticks_elapsed(t1, t2);
|
|
||||||
/* Tell the scheduler how much we idled: */
|
|
||||||
sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
|
|
||||||
|
|
||||||
/* Re-enable interrupts */
|
|
||||||
local_irq_enable();
|
|
||||||
/* Do not account our idle-switching overhead: */
|
|
||||||
sleep_ticks -= cx->latency_ticks + C3_OVERHEAD;
|
|
||||||
|
|
||||||
current_thread_info()->status |= TS_POLLING;
|
|
||||||
acpi_state_timer_broadcast(pr, cx, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
local_irq_enable();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cx->usage++;
|
|
||||||
if ((cx->type != ACPI_STATE_C1) && (sleep_ticks > 0))
|
|
||||||
cx->time += sleep_ticks;
|
|
||||||
|
|
||||||
next_state = pr->power.state;
|
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
/* Don't do promotion/demotion */
|
|
||||||
if ((cx->type == ACPI_STATE_C1) && (num_online_cpus() > 1) &&
|
|
||||||
!pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) {
|
|
||||||
next_state = cx;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Promotion?
|
|
||||||
* ----------
|
|
||||||
* Track the number of longs (time asleep is greater than threshold)
|
|
||||||
* and promote when the count threshold is reached. Note that bus
|
|
||||||
* mastering activity may prevent promotions.
|
|
||||||
* Do not promote above max_cstate.
|
|
||||||
*/
|
|
||||||
if (cx->promotion.state &&
|
|
||||||
((cx->promotion.state - pr->power.states) <= max_cstate)) {
|
|
||||||
if (sleep_ticks > cx->promotion.threshold.ticks &&
|
|
||||||
cx->promotion.state->latency <=
|
|
||||||
pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) {
|
|
||||||
cx->promotion.count++;
|
|
||||||
cx->demotion.count = 0;
|
|
||||||
if (cx->promotion.count >=
|
|
||||||
cx->promotion.threshold.count) {
|
|
||||||
if (pr->flags.bm_check) {
|
|
||||||
if (!
|
|
||||||
(pr->power.bm_activity & cx->
|
|
||||||
promotion.threshold.bm)) {
|
|
||||||
next_state =
|
|
||||||
cx->promotion.state;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
next_state = cx->promotion.state;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Demotion?
|
|
||||||
* ---------
|
|
||||||
* Track the number of shorts (time asleep is less than time threshold)
|
|
||||||
* and demote when the usage threshold is reached.
|
|
||||||
*/
|
|
||||||
if (cx->demotion.state) {
|
|
||||||
if (sleep_ticks < cx->demotion.threshold.ticks) {
|
|
||||||
cx->demotion.count++;
|
|
||||||
cx->promotion.count = 0;
|
|
||||||
if (cx->demotion.count >= cx->demotion.threshold.count) {
|
|
||||||
next_state = cx->demotion.state;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
/*
|
|
||||||
* Demote if current state exceeds max_cstate
|
|
||||||
* or if the latency of the current state is unacceptable
|
|
||||||
*/
|
|
||||||
if ((pr->power.state - pr->power.states) > max_cstate ||
|
|
||||||
pr->power.state->latency >
|
|
||||||
pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) {
|
|
||||||
if (cx->demotion.state)
|
|
||||||
next_state = cx->demotion.state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* New Cx State?
|
|
||||||
* -------------
|
|
||||||
* If we're going to start using a new Cx state we must clean up
|
|
||||||
* from the previous and prepare to use the new.
|
|
||||||
*/
|
|
||||||
if (next_state != pr->power.state)
|
|
||||||
acpi_processor_power_activate(pr, next_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int acpi_processor_set_power_policy(struct acpi_processor *pr)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
unsigned int state_is_set = 0;
|
|
||||||
struct acpi_processor_cx *lower = NULL;
|
|
||||||
struct acpi_processor_cx *higher = NULL;
|
|
||||||
struct acpi_processor_cx *cx;
|
|
||||||
|
|
||||||
|
|
||||||
if (!pr)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function sets the default Cx state policy (OS idle handler).
|
|
||||||
* Our scheme is to promote quickly to C2 but more conservatively
|
|
||||||
* to C3. We're favoring C2 for its characteristics of low latency
|
|
||||||
* (quick response), good power savings, and ability to allow bus
|
|
||||||
* mastering activity. Note that the Cx state policy is completely
|
|
||||||
* customizable and can be altered dynamically.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* startup state */
|
|
||||||
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
|
|
||||||
cx = &pr->power.states[i];
|
|
||||||
if (!cx->valid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!state_is_set)
|
|
||||||
pr->power.state = cx;
|
|
||||||
state_is_set++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!state_is_set)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
/* demotion */
|
|
||||||
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
|
|
||||||
cx = &pr->power.states[i];
|
|
||||||
if (!cx->valid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (lower) {
|
|
||||||
cx->demotion.state = lower;
|
|
||||||
cx->demotion.threshold.ticks = cx->latency_ticks;
|
|
||||||
cx->demotion.threshold.count = 1;
|
|
||||||
if (cx->type == ACPI_STATE_C3)
|
|
||||||
cx->demotion.threshold.bm = bm_history;
|
|
||||||
}
|
|
||||||
|
|
||||||
lower = cx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* promotion */
|
|
||||||
for (i = (ACPI_PROCESSOR_MAX_POWER - 1); i > 0; i--) {
|
|
||||||
cx = &pr->power.states[i];
|
|
||||||
if (!cx->valid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (higher) {
|
|
||||||
cx->promotion.state = higher;
|
|
||||||
cx->promotion.threshold.ticks = cx->latency_ticks;
|
|
||||||
if (cx->type >= ACPI_STATE_C2)
|
|
||||||
cx->promotion.threshold.count = 4;
|
|
||||||
else
|
|
||||||
cx->promotion.threshold.count = 10;
|
|
||||||
if (higher->type == ACPI_STATE_C3)
|
|
||||||
cx->promotion.threshold.bm = bm_history;
|
|
||||||
}
|
|
||||||
|
|
||||||
higher = cx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* !CONFIG_CPU_IDLE */
|
|
||||||
|
|
||||||
static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
|
static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -1047,11 +541,7 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
|
||||||
*/
|
*/
|
||||||
cx->valid = 1;
|
cx->valid = 1;
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
|
|
||||||
#else
|
|
||||||
cx->latency_ticks = cx->latency;
|
cx->latency_ticks = cx->latency;
|
||||||
#endif
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1121,7 +611,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
|
||||||
" for C3 to be enabled on SMP systems\n"));
|
" for C3 to be enabled on SMP systems\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1132,11 +621,16 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
|
||||||
*/
|
*/
|
||||||
cx->valid = 1;
|
cx->valid = 1;
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
|
|
||||||
#else
|
|
||||||
cx->latency_ticks = cx->latency;
|
cx->latency_ticks = cx->latency;
|
||||||
#endif
|
/*
|
||||||
|
* On older chipsets, BM_RLD needs to be set
|
||||||
|
* in order for Bus Master activity to wake the
|
||||||
|
* system from C3. Newer chipsets handle DMA
|
||||||
|
* during C3 automatically and BM_RLD is a NOP.
|
||||||
|
* In either case, the proper way to
|
||||||
|
* handle BM_RLD is to set it and leave it set.
|
||||||
|
*/
|
||||||
|
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1201,20 +695,6 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
|
||||||
|
|
||||||
pr->power.count = acpi_processor_power_verify(pr);
|
pr->power.count = acpi_processor_power_verify(pr);
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
/*
|
|
||||||
* Set Default Policy
|
|
||||||
* ------------------
|
|
||||||
* Now that we know which states are supported, set the default
|
|
||||||
* policy. Note that this policy can be changed dynamically
|
|
||||||
* (e.g. encourage deeper sleeps to conserve battery life when
|
|
||||||
* not on AC).
|
|
||||||
*/
|
|
||||||
result = acpi_processor_set_power_policy(pr);
|
|
||||||
if (result)
|
|
||||||
return result;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if one state of type C2 or C3 is available, mark this
|
* if one state of type C2 or C3 is available, mark this
|
||||||
* CPU as being "idle manageable"
|
* CPU as being "idle manageable"
|
||||||
|
|
@ -1312,69 +792,6 @@ static const struct file_operations acpi_processor_power_fops = {
|
||||||
.release = single_release,
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
|
|
||||||
int acpi_processor_cst_has_changed(struct acpi_processor *pr)
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
if (boot_option_idle_override)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!pr)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (nocst) {
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pr->flags.power_setup_done)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fall back to the default idle loop, when pm_idle_save had
|
|
||||||
* been initialized.
|
|
||||||
*/
|
|
||||||
if (pm_idle_save) {
|
|
||||||
pm_idle = pm_idle_save;
|
|
||||||
/* Relies on interrupts forcing exit from idle. */
|
|
||||||
synchronize_sched();
|
|
||||||
}
|
|
||||||
|
|
||||||
pr->flags.power = 0;
|
|
||||||
result = acpi_processor_get_power_info(pr);
|
|
||||||
if ((pr->flags.power == 1) && (pr->flags.power_setup_done))
|
|
||||||
pm_idle = acpi_processor_idle;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
static void smp_callback(void *v)
|
|
||||||
{
|
|
||||||
/* we already woke the CPU up, nothing more to do */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function gets called when a part of the kernel has a new latency
|
|
||||||
* requirement. This means we need to get all processors out of their C-state,
|
|
||||||
* and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that
|
|
||||||
* wakes them all right up.
|
|
||||||
*/
|
|
||||||
static int acpi_processor_latency_notify(struct notifier_block *b,
|
|
||||||
unsigned long l, void *v)
|
|
||||||
{
|
|
||||||
smp_call_function(smp_callback, NULL, 1);
|
|
||||||
return NOTIFY_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct notifier_block acpi_processor_latency_notifier = {
|
|
||||||
.notifier_call = acpi_processor_latency_notify,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else /* CONFIG_CPU_IDLE */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* acpi_idle_bm_check - checks if bus master activity was detected
|
* acpi_idle_bm_check - checks if bus master activity was detected
|
||||||
|
|
@ -1383,7 +800,7 @@ static int acpi_idle_bm_check(void)
|
||||||
{
|
{
|
||||||
u32 bm_status = 0;
|
u32 bm_status = 0;
|
||||||
|
|
||||||
acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
|
acpi_get_register_unlocked(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
|
||||||
if (bm_status)
|
if (bm_status)
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
|
acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
|
||||||
/*
|
/*
|
||||||
|
|
@ -1399,25 +816,6 @@ static int acpi_idle_bm_check(void)
|
||||||
return bm_status;
|
return bm_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* acpi_idle_update_bm_rld - updates the BM_RLD bit depending on target state
|
|
||||||
* @pr: the processor
|
|
||||||
* @target: the new target state
|
|
||||||
*/
|
|
||||||
static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr,
|
|
||||||
struct acpi_processor_cx *target)
|
|
||||||
{
|
|
||||||
if (pr->flags.bm_rld_set && target->type != ACPI_STATE_C3) {
|
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
|
|
||||||
pr->flags.bm_rld_set = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pr->flags.bm_rld_set && target->type == ACPI_STATE_C3) {
|
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
|
|
||||||
pr->flags.bm_rld_set = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* acpi_idle_do_entry - a helper function that does C2 and C3 type entry
|
* acpi_idle_do_entry - a helper function that does C2 and C3 type entry
|
||||||
* @cx: cstate data
|
* @cx: cstate data
|
||||||
|
|
@ -1473,9 +871,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pr->flags.bm_check)
|
|
||||||
acpi_idle_update_bm_rld(pr, cx);
|
|
||||||
|
|
||||||
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
||||||
acpi_idle_do_entry(cx);
|
acpi_idle_do_entry(cx);
|
||||||
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
||||||
|
|
@ -1527,9 +922,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
|
||||||
*/
|
*/
|
||||||
acpi_state_timer_broadcast(pr, cx, 1);
|
acpi_state_timer_broadcast(pr, cx, 1);
|
||||||
|
|
||||||
if (pr->flags.bm_check)
|
|
||||||
acpi_idle_update_bm_rld(pr, cx);
|
|
||||||
|
|
||||||
if (cx->type == ACPI_STATE_C3)
|
if (cx->type == ACPI_STATE_C3)
|
||||||
ACPI_FLUSH_CPU_CACHE();
|
ACPI_FLUSH_CPU_CACHE();
|
||||||
|
|
||||||
|
|
@ -1621,8 +1013,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
|
||||||
*/
|
*/
|
||||||
acpi_state_timer_broadcast(pr, cx, 1);
|
acpi_state_timer_broadcast(pr, cx, 1);
|
||||||
|
|
||||||
acpi_idle_update_bm_rld(pr, cx);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* disable bus master
|
* disable bus master
|
||||||
* bm_check implies we need ARB_DIS
|
* bm_check implies we need ARB_DIS
|
||||||
|
|
@ -1795,8 +1185,6 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_CPU_IDLE */
|
|
||||||
|
|
||||||
int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
||||||
struct acpi_device *device)
|
struct acpi_device *device)
|
||||||
{
|
{
|
||||||
|
|
@ -1825,10 +1213,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
||||||
"ACPI: processor limited to max C-state %d\n",
|
"ACPI: processor limited to max C-state %d\n",
|
||||||
max_cstate);
|
max_cstate);
|
||||||
first_run++;
|
first_run++;
|
||||||
#if !defined(CONFIG_CPU_IDLE) && defined(CONFIG_SMP)
|
|
||||||
pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY,
|
|
||||||
&acpi_processor_latency_notifier);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pr)
|
if (!pr)
|
||||||
|
|
@ -1852,11 +1236,9 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
||||||
* platforms that only support C1.
|
* platforms that only support C1.
|
||||||
*/
|
*/
|
||||||
if (pr->flags.power) {
|
if (pr->flags.power) {
|
||||||
#ifdef CONFIG_CPU_IDLE
|
|
||||||
acpi_processor_setup_cpuidle(pr);
|
acpi_processor_setup_cpuidle(pr);
|
||||||
if (cpuidle_register_device(&pr->power.dev))
|
if (cpuidle_register_device(&pr->power.dev))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
#endif
|
|
||||||
|
|
||||||
printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id);
|
printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id);
|
||||||
for (i = 1; i <= pr->power.count; i++)
|
for (i = 1; i <= pr->power.count; i++)
|
||||||
|
|
@ -1864,13 +1246,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
||||||
printk(" C%d[C%d]", i,
|
printk(" C%d[C%d]", i,
|
||||||
pr->power.states[i].type);
|
pr->power.states[i].type);
|
||||||
printk(")\n");
|
printk(")\n");
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
if (pr->id == 0) {
|
|
||||||
pm_idle_save = pm_idle;
|
|
||||||
pm_idle = acpi_processor_idle;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 'power' [R] */
|
/* 'power' [R] */
|
||||||
|
|
@ -1889,34 +1264,12 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
|
||||||
if (boot_option_idle_override)
|
if (boot_option_idle_override)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_IDLE
|
|
||||||
cpuidle_unregister_device(&pr->power.dev);
|
cpuidle_unregister_device(&pr->power.dev);
|
||||||
#endif
|
|
||||||
pr->flags.power_setup_done = 0;
|
pr->flags.power_setup_done = 0;
|
||||||
|
|
||||||
if (acpi_device_dir(device))
|
if (acpi_device_dir(device))
|
||||||
remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,
|
remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,
|
||||||
acpi_device_dir(device));
|
acpi_device_dir(device));
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
|
|
||||||
/* Unregister the idle handler when processor #0 is removed. */
|
|
||||||
if (pr->id == 0) {
|
|
||||||
if (pm_idle_save)
|
|
||||||
pm_idle = pm_idle_save;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We are about to unload the current idle thread pm callback
|
|
||||||
* (pm_idle), Wait for all processors to update cached/local
|
|
||||||
* copies of pm_idle before proceeding.
|
|
||||||
*/
|
|
||||||
cpu_idle_wait();
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY,
|
|
||||||
&acpi_processor_latency_notifier);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,6 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/cpufreq.h>
|
#include <linux/cpufreq.h>
|
||||||
|
|
||||||
#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
|
|
||||||
#include <linux/proc_fs.h>
|
|
||||||
#include <linux/seq_file.h>
|
|
||||||
#include <linux/mutex.h>
|
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86
|
#ifdef CONFIG_X86
|
||||||
#include <asm/cpufeature.h>
|
#include <asm/cpufeature.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -434,96 +426,6 @@ int acpi_processor_notify_smm(struct module *calling_module)
|
||||||
|
|
||||||
EXPORT_SYMBOL(acpi_processor_notify_smm);
|
EXPORT_SYMBOL(acpi_processor_notify_smm);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
|
|
||||||
/* /proc/acpi/processor/../performance interface (DEPRECATED) */
|
|
||||||
|
|
||||||
static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
|
|
||||||
static struct file_operations acpi_processor_perf_fops = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.open = acpi_processor_perf_open_fs,
|
|
||||||
.read = seq_read,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = single_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
|
|
||||||
{
|
|
||||||
struct acpi_processor *pr = seq->private;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
|
|
||||||
if (!pr)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
if (!pr->performance) {
|
|
||||||
seq_puts(seq, "<not supported>\n");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
seq_printf(seq, "state count: %d\n"
|
|
||||||
"active state: P%d\n",
|
|
||||||
pr->performance->state_count, pr->performance->state);
|
|
||||||
|
|
||||||
seq_puts(seq, "states:\n");
|
|
||||||
for (i = 0; i < pr->performance->state_count; i++)
|
|
||||||
seq_printf(seq,
|
|
||||||
" %cP%d: %d MHz, %d mW, %d uS\n",
|
|
||||||
(i == pr->performance->state ? '*' : ' '), i,
|
|
||||||
(u32) pr->performance->states[i].core_frequency,
|
|
||||||
(u32) pr->performance->states[i].power,
|
|
||||||
(u32) pr->performance->states[i].transition_latency);
|
|
||||||
|
|
||||||
end:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
|
|
||||||
{
|
|
||||||
return single_open(file, acpi_processor_perf_seq_show,
|
|
||||||
PDE(inode)->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void acpi_cpufreq_add_file(struct acpi_processor *pr)
|
|
||||||
{
|
|
||||||
struct acpi_device *device = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
if (acpi_bus_get_device(pr->handle, &device))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* add file 'performance' [R/W] */
|
|
||||||
proc_create_data(ACPI_PROCESSOR_FILE_PERFORMANCE, S_IFREG | S_IRUGO,
|
|
||||||
acpi_device_dir(device),
|
|
||||||
&acpi_processor_perf_fops, acpi_driver_data(device));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
|
|
||||||
{
|
|
||||||
struct acpi_device *device = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
if (acpi_bus_get_device(pr->handle, &device))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* remove file 'performance' */
|
|
||||||
remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
|
|
||||||
acpi_device_dir(device));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
static void acpi_cpufreq_add_file(struct acpi_processor *pr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
|
|
||||||
|
|
||||||
static int acpi_processor_get_psd(struct acpi_processor *pr)
|
static int acpi_processor_get_psd(struct acpi_processor *pr)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
@ -747,14 +649,12 @@ err_ret:
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(acpi_processor_preregister_performance);
|
EXPORT_SYMBOL(acpi_processor_preregister_performance);
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
acpi_processor_register_performance(struct acpi_processor_performance
|
acpi_processor_register_performance(struct acpi_processor_performance
|
||||||
*performance, unsigned int cpu)
|
*performance, unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct acpi_processor *pr;
|
struct acpi_processor *pr;
|
||||||
|
|
||||||
|
|
||||||
if (!(acpi_processor_ppc_status & PPC_REGISTERED))
|
if (!(acpi_processor_ppc_status & PPC_REGISTERED))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
@ -781,8 +681,6 @@ acpi_processor_register_performance(struct acpi_processor_performance
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
acpi_cpufreq_add_file(pr);
|
|
||||||
|
|
||||||
mutex_unlock(&performance_mutex);
|
mutex_unlock(&performance_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -795,7 +693,6 @@ acpi_processor_unregister_performance(struct acpi_processor_performance
|
||||||
{
|
{
|
||||||
struct acpi_processor *pr;
|
struct acpi_processor *pr;
|
||||||
|
|
||||||
|
|
||||||
mutex_lock(&performance_mutex);
|
mutex_lock(&performance_mutex);
|
||||||
|
|
||||||
pr = per_cpu(processors, cpu);
|
pr = per_cpu(processors, cpu);
|
||||||
|
|
@ -808,8 +705,6 @@ acpi_processor_unregister_performance(struct acpi_processor_performance
|
||||||
kfree(pr->performance->states);
|
kfree(pr->performance->states);
|
||||||
pr->performance = NULL;
|
pr->performance = NULL;
|
||||||
|
|
||||||
acpi_cpufreq_remove_file(pr);
|
|
||||||
|
|
||||||
mutex_unlock(&performance_mutex);
|
mutex_unlock(&performance_mutex);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -90,31 +90,6 @@ void __init acpi_old_suspend_ordering(void)
|
||||||
old_suspend_ordering = true;
|
old_suspend_ordering = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* According to the ACPI specification the BIOS should make sure that ACPI is
|
|
||||||
* enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still,
|
|
||||||
* some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI
|
|
||||||
* on such systems during resume. Unfortunately that doesn't help in
|
|
||||||
* particularly pathological cases in which SCI_EN has to be set directly on
|
|
||||||
* resume, although the specification states very clearly that this flag is
|
|
||||||
* owned by the hardware. The set_sci_en_on_resume variable will be set in such
|
|
||||||
* cases.
|
|
||||||
*/
|
|
||||||
static bool set_sci_en_on_resume;
|
|
||||||
/*
|
|
||||||
* The ACPI specification wants us to save NVS memory regions during hibernation
|
|
||||||
* and to restore them during the subsequent resume. However, it is not certain
|
|
||||||
* if this mechanism is going to work on all machines, so we allow the user to
|
|
||||||
* disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line
|
|
||||||
* option.
|
|
||||||
*/
|
|
||||||
static bool s4_no_nvs;
|
|
||||||
|
|
||||||
void __init acpi_s4_no_nvs(void)
|
|
||||||
{
|
|
||||||
s4_no_nvs = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* acpi_pm_disable_gpes - Disable the GPEs.
|
* acpi_pm_disable_gpes - Disable the GPEs.
|
||||||
*/
|
*/
|
||||||
|
|
@ -193,6 +168,18 @@ static void acpi_pm_end(void)
|
||||||
#endif /* CONFIG_ACPI_SLEEP */
|
#endif /* CONFIG_ACPI_SLEEP */
|
||||||
|
|
||||||
#ifdef CONFIG_SUSPEND
|
#ifdef CONFIG_SUSPEND
|
||||||
|
/*
|
||||||
|
* According to the ACPI specification the BIOS should make sure that ACPI is
|
||||||
|
* enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still,
|
||||||
|
* some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI
|
||||||
|
* on such systems during resume. Unfortunately that doesn't help in
|
||||||
|
* particularly pathological cases in which SCI_EN has to be set directly on
|
||||||
|
* resume, although the specification states very clearly that this flag is
|
||||||
|
* owned by the hardware. The set_sci_en_on_resume variable will be set in such
|
||||||
|
* cases.
|
||||||
|
*/
|
||||||
|
static bool set_sci_en_on_resume;
|
||||||
|
|
||||||
extern void do_suspend_lowlevel(void);
|
extern void do_suspend_lowlevel(void);
|
||||||
|
|
||||||
static u32 acpi_suspend_states[] = {
|
static u32 acpi_suspend_states[] = {
|
||||||
|
|
@ -396,6 +383,20 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
|
||||||
#endif /* CONFIG_SUSPEND */
|
#endif /* CONFIG_SUSPEND */
|
||||||
|
|
||||||
#ifdef CONFIG_HIBERNATION
|
#ifdef CONFIG_HIBERNATION
|
||||||
|
/*
|
||||||
|
* The ACPI specification wants us to save NVS memory regions during hibernation
|
||||||
|
* and to restore them during the subsequent resume. However, it is not certain
|
||||||
|
* if this mechanism is going to work on all machines, so we allow the user to
|
||||||
|
* disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line
|
||||||
|
* option.
|
||||||
|
*/
|
||||||
|
static bool s4_no_nvs;
|
||||||
|
|
||||||
|
void __init acpi_s4_no_nvs(void)
|
||||||
|
{
|
||||||
|
s4_no_nvs = true;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned long s4_hardware_signature;
|
static unsigned long s4_hardware_signature;
|
||||||
static struct acpi_table_facs *facs;
|
static struct acpi_table_facs *facs;
|
||||||
static bool nosigcheck;
|
static bool nosigcheck;
|
||||||
|
|
@ -679,7 +680,7 @@ static void acpi_power_off_prepare(void)
|
||||||
static void acpi_power_off(void)
|
static void acpi_power_off(void)
|
||||||
{
|
{
|
||||||
/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
|
/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
|
||||||
printk("%s called\n", __func__);
|
printk(KERN_DEBUG "%s called\n", __func__);
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
acpi_enable_wakeup_device(ACPI_STATE_S5);
|
acpi_enable_wakeup_device(ACPI_STATE_S5);
|
||||||
acpi_enter_sleep_state(ACPI_STATE_S5);
|
acpi_enter_sleep_state(ACPI_STATE_S5);
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,12 @@ static void __init check_multiple_madt(void)
|
||||||
|
|
||||||
int __init acpi_table_init(void)
|
int __init acpi_table_init(void)
|
||||||
{
|
{
|
||||||
acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
|
acpi_status status;
|
||||||
|
|
||||||
|
status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
return 1;
|
||||||
|
|
||||||
check_multiple_madt();
|
check_multiple_madt();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1020,7 +1020,7 @@ acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
seq_printf(seq, "levels: ");
|
seq_printf(seq, "levels: ");
|
||||||
for (i = 0; i < dev->brightness->count; i++)
|
for (i = 2; i < dev->brightness->count; i++)
|
||||||
seq_printf(seq, " %d", dev->brightness->levels[i]);
|
seq_printf(seq, " %d", dev->brightness->levels[i]);
|
||||||
seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
|
seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
|
||||||
|
|
||||||
|
|
@ -1059,7 +1059,7 @@ acpi_video_device_write_brightness(struct file *file,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
/* validate through the list of available levels */
|
/* validate through the list of available levels */
|
||||||
for (i = 0; i < dev->brightness->count; i++)
|
for (i = 2; i < dev->brightness->count; i++)
|
||||||
if (level == dev->brightness->levels[i]) {
|
if (level == dev->brightness->levels[i]) {
|
||||||
if (ACPI_SUCCESS
|
if (ACPI_SUCCESS
|
||||||
(acpi_video_device_lcd_set_level(dev, level)))
|
(acpi_video_device_lcd_set_level(dev, level)))
|
||||||
|
|
@ -1260,7 +1260,7 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
|
||||||
printk(KERN_WARNING PREFIX
|
printk(KERN_WARNING PREFIX
|
||||||
"This indicates a BIOS bug. Please contact the manufacturer.\n");
|
"This indicates a BIOS bug. Please contact the manufacturer.\n");
|
||||||
}
|
}
|
||||||
printk("%llx\n", options);
|
printk(KERN_WARNING "%llx\n", options);
|
||||||
seq_printf(seq, "can POST: <integrated video>");
|
seq_printf(seq, "can POST: <integrated video>");
|
||||||
if (options & 2)
|
if (options & 2)
|
||||||
seq_printf(seq, " <PCI video>");
|
seq_printf(seq, " <PCI video>");
|
||||||
|
|
@ -1712,7 +1712,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
|
||||||
max = max_below = 0;
|
max = max_below = 0;
|
||||||
min = min_above = 255;
|
min = min_above = 255;
|
||||||
/* Find closest level to level_current */
|
/* Find closest level to level_current */
|
||||||
for (i = 0; i < device->brightness->count; i++) {
|
for (i = 2; i < device->brightness->count; i++) {
|
||||||
l = device->brightness->levels[i];
|
l = device->brightness->levels[i];
|
||||||
if (abs(l - level_current) < abs(delta)) {
|
if (abs(l - level_current) < abs(delta)) {
|
||||||
delta = l - level_current;
|
delta = l - level_current;
|
||||||
|
|
@ -1722,7 +1722,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
|
||||||
}
|
}
|
||||||
/* Ajust level_current to closest available level */
|
/* Ajust level_current to closest available level */
|
||||||
level_current += delta;
|
level_current += delta;
|
||||||
for (i = 0; i < device->brightness->count; i++) {
|
for (i = 2; i < device->brightness->count; i++) {
|
||||||
l = device->brightness->levels[i];
|
l = device->brightness->levels[i];
|
||||||
if (l < min)
|
if (l < min)
|
||||||
min = l;
|
min = l;
|
||||||
|
|
@ -2006,6 +2006,12 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
||||||
device->pnp.bus_id[3] = '0' + instance;
|
device->pnp.bus_id[3] = '0' + instance;
|
||||||
instance ++;
|
instance ++;
|
||||||
}
|
}
|
||||||
|
/* a hack to fix the duplicate name "VGA" problem on Pa 3553 */
|
||||||
|
if (!strcmp(device->pnp.bus_id, "VGA")) {
|
||||||
|
if (instance)
|
||||||
|
device->pnp.bus_id[3] = '0' + instance;
|
||||||
|
instance++;
|
||||||
|
}
|
||||||
|
|
||||||
video->device = device;
|
video->device = device;
|
||||||
strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
|
strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
|
||||||
|
|
|
||||||
|
|
@ -1713,8 +1713,8 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
|
||||||
for (i = 0; i < SX_NBOARDS; i++)
|
for (i = 0; i < SX_NBOARDS; i++)
|
||||||
sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
|
sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
|
||||||
sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
|
sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
|
||||||
unlock_kernel();
|
rc = -EIO;
|
||||||
return -EIO;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
|
@ -1747,7 +1747,8 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
|
||||||
break;
|
break;
|
||||||
case SXIO_DO_RAMTEST:
|
case SXIO_DO_RAMTEST:
|
||||||
if (sx_initialized) /* Already initialized: better not ramtest the board. */
|
if (sx_initialized) /* Already initialized: better not ramtest the board. */
|
||||||
return -EPERM;
|
rc = -EPERM;
|
||||||
|
break;
|
||||||
if (IS_SX_BOARD(board)) {
|
if (IS_SX_BOARD(board)) {
|
||||||
rc = do_memtest(board, 0, 0x7000);
|
rc = do_memtest(board, 0, 0x7000);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
|
|
@ -1844,6 +1845,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
|
||||||
rc = -ENOTTY;
|
rc = -ENOTTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
unlock_kernel();
|
unlock_kernel();
|
||||||
func_exit();
|
func_exit();
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
||||||
|
|
@ -412,6 +412,7 @@ fw_card_add(struct fw_card *card,
|
||||||
{
|
{
|
||||||
u32 *config_rom;
|
u32 *config_rom;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
int err;
|
||||||
|
|
||||||
card->max_receive = max_receive;
|
card->max_receive = max_receive;
|
||||||
card->link_speed = link_speed;
|
card->link_speed = link_speed;
|
||||||
|
|
@ -422,7 +423,13 @@ fw_card_add(struct fw_card *card,
|
||||||
list_add_tail(&card->link, &card_list);
|
list_add_tail(&card->link, &card_list);
|
||||||
mutex_unlock(&card_mutex);
|
mutex_unlock(&card_mutex);
|
||||||
|
|
||||||
return card->driver->enable(card, config_rom, length);
|
err = card->driver->enable(card, config_rom, length);
|
||||||
|
if (err < 0) {
|
||||||
|
mutex_lock(&card_mutex);
|
||||||
|
list_del(&card->link);
|
||||||
|
mutex_unlock(&card_mutex);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(fw_card_add);
|
EXPORT_SYMBOL(fw_card_add);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,10 @@ static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3};
|
||||||
static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
|
static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
|
||||||
static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
|
static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
|
||||||
static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
|
static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
|
||||||
|
static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3};
|
||||||
static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
|
static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
|
||||||
|
static struct axis_conversion lis3lv02d_axis_xy_rotated_right = {2, -1, 3};
|
||||||
|
static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3};
|
||||||
|
|
||||||
#define AXIS_DMI_MATCH(_ident, _name, _axis) { \
|
#define AXIS_DMI_MATCH(_ident, _name, _axis) { \
|
||||||
.ident = _ident, \
|
.ident = _ident, \
|
||||||
|
|
@ -172,10 +175,12 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
|
||||||
AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
|
AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
|
||||||
AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
|
AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
|
||||||
AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
|
AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
|
||||||
|
AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
|
||||||
|
AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd),
|
||||||
|
AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
|
||||||
|
AXIS_DMI_MATCH("NC671xx", "HP Compaq 671", xy_swap_yz_inverted),
|
||||||
{ NULL, }
|
{ NULL, }
|
||||||
/* Laptop models without axis info (yet):
|
/* Laptop models without axis info (yet):
|
||||||
* "NC651xx" "HP Compaq 651"
|
|
||||||
* "NC671xx" "HP Compaq 671"
|
|
||||||
* "NC6910" "HP Compaq 6910"
|
* "NC6910" "HP Compaq 6910"
|
||||||
* HP Compaq 8710x Notebook PC / Mobile Workstation
|
* HP Compaq 8710x Notebook PC / Mobile Workstation
|
||||||
* "NC2400" "HP Compaq nc2400"
|
* "NC2400" "HP Compaq nc2400"
|
||||||
|
|
|
||||||
|
|
@ -1823,6 +1823,10 @@ static int dv1394_open(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
printk(KERN_INFO "%s: NOTE, the dv1394 interface is unsupported "
|
||||||
|
"and will not be available in the new firewire driver stack. "
|
||||||
|
"Try libraw1394 based programs instead.\n", current->comm);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2567,10 +2571,6 @@ static int __init dv1394_init_module(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
printk(KERN_WARNING
|
|
||||||
"NOTE: The dv1394 driver is unsupported and may be removed in a "
|
|
||||||
"future Linux release. Use raw1394 instead.\n");
|
|
||||||
|
|
||||||
cdev_init(&dv1394_cdev, &dv1394_fops);
|
cdev_init(&dv1394_cdev, &dv1394_fops);
|
||||||
dv1394_cdev.owner = THIS_MODULE;
|
dv1394_cdev.owner = THIS_MODULE;
|
||||||
ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16);
|
ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16);
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,13 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
|
||||||
{
|
{
|
||||||
dev_info_t *hash;
|
dev_info_t *hash;
|
||||||
linear_conf_t *conf = mddev_to_conf(mddev);
|
linear_conf_t *conf = mddev_to_conf(mddev);
|
||||||
|
sector_t idx = sector >> conf->sector_shift;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sector_div(a,b) returns the remainer and sets a to a/b
|
* sector_div(a,b) returns the remainer and sets a to a/b
|
||||||
*/
|
*/
|
||||||
sector >>= conf->sector_shift;
|
(void)sector_div(idx, conf->spacing);
|
||||||
(void)sector_div(sector, conf->spacing);
|
hash = conf->hash_table[idx];
|
||||||
hash = conf->hash_table[sector];
|
|
||||||
|
|
||||||
while (sector >= hash->num_sectors + hash->start_sector)
|
while (sector >= hash->num_sectors + hash->start_sector)
|
||||||
hash++;
|
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))
|
if (find_rdev_nr(mddev, rdev->desc_nr))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
if (mddev->max_disks && rdev->desc_nr >= mddev->max_disks) {
|
||||||
|
printk(KERN_WARNING "md: %s: array is limited to %d devices\n",
|
||||||
|
mdname(mddev), mddev->max_disks);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
bdevname(rdev->bdev,b);
|
bdevname(rdev->bdev,b);
|
||||||
while ( (s=strchr(b, '/')) != NULL)
|
while ( (s=strchr(b, '/')) != NULL)
|
||||||
*s = '!';
|
*s = '!';
|
||||||
|
|
@ -2441,6 +2446,15 @@ static void analyze_sbs(mddev_t * mddev)
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
rdev_for_each(rdev, tmp, mddev) {
|
rdev_for_each(rdev, tmp, mddev) {
|
||||||
|
if (rdev->desc_nr >= mddev->max_disks ||
|
||||||
|
i > mddev->max_disks) {
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"md: %s: %s: only %d devices permitted\n",
|
||||||
|
mdname(mddev), bdevname(rdev->bdev, b),
|
||||||
|
mddev->max_disks);
|
||||||
|
kick_rdev_from_array(rdev);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (rdev != freshest)
|
if (rdev != freshest)
|
||||||
if (super_types[mddev->major_version].
|
if (super_types[mddev->major_version].
|
||||||
validate_super(mddev, rdev)) {
|
validate_super(mddev, rdev)) {
|
||||||
|
|
@ -4614,13 +4628,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
|
||||||
* noticed in interrupt contexts ...
|
* noticed in interrupt contexts ...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (rdev->desc_nr == mddev->max_disks) {
|
|
||||||
printk(KERN_WARNING "%s: can not hot-add to full array!\n",
|
|
||||||
mdname(mddev));
|
|
||||||
err = -EBUSY;
|
|
||||||
goto abort_unbind_export;
|
|
||||||
}
|
|
||||||
|
|
||||||
rdev->raid_disk = -1;
|
rdev->raid_disk = -1;
|
||||||
|
|
||||||
md_update_sb(mddev, 1);
|
md_update_sb(mddev, 1);
|
||||||
|
|
@ -4634,9 +4641,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
|
||||||
md_new_event(mddev);
|
md_new_event(mddev);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
abort_unbind_export:
|
|
||||||
unbind_rdev_from_array(rdev);
|
|
||||||
|
|
||||||
abort_export:
|
abort_export:
|
||||||
export_rdev(rdev);
|
export_rdev(rdev);
|
||||||
return err;
|
return err;
|
||||||
|
|
|
||||||
|
|
@ -1640,7 +1640,8 @@ static void raid1d(mddev_t *mddev)
|
||||||
}
|
}
|
||||||
|
|
||||||
bio = r1_bio->bios[r1_bio->read_disk];
|
bio = r1_bio->bios[r1_bio->read_disk];
|
||||||
if ((disk=read_balance(conf, r1_bio)) == -1) {
|
if ((disk=read_balance(conf, r1_bio)) == -1 ||
|
||||||
|
disk == r1_bio->read_disk) {
|
||||||
printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
|
printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
|
||||||
" read error for block %llu\n",
|
" read error for block %llu\n",
|
||||||
bdevname(bio->bi_bdev,b),
|
bdevname(bio->bi_bdev,b),
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,7 @@ config DELL_LAPTOP
|
||||||
depends on EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
depends on BACKLIGHT_CLASS_DEVICE
|
depends on BACKLIGHT_CLASS_DEVICE
|
||||||
depends on RFKILL
|
depends on RFKILL
|
||||||
|
depends on POWER_SUPPLY
|
||||||
default n
|
default n
|
||||||
---help---
|
---help---
|
||||||
This driver adds support for rfkill and backlight control to Dell
|
This driver adds support for rfkill and backlight control to Dell
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
|
||||||
|
|
||||||
if (!ssc_valid) {
|
if (!ssc_valid) {
|
||||||
spin_unlock(&user_lock);
|
spin_unlock(&user_lock);
|
||||||
dev_dbg(&ssc->pdev->dev, "could not find requested device\n");
|
pr_err("ssc: ssc%d platform device is missing\n", ssc_num);
|
||||||
return ERR_PTR(-ENODEV);
|
return ERR_PTR(-ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data)
|
||||||
&device_ccb->recv_ctrl);
|
&device_ccb->recv_ctrl);
|
||||||
|
|
||||||
/* give iLO some time to process stop request */
|
/* give iLO some time to process stop request */
|
||||||
for (retries = 1000; retries > 0; retries--) {
|
for (retries = MAX_WAIT; retries > 0; retries--) {
|
||||||
doorbell_set(driver_ccb);
|
doorbell_set(driver_ccb);
|
||||||
udelay(1);
|
udelay(1);
|
||||||
if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A))
|
if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A))
|
||||||
|
|
@ -309,7 +309,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
|
||||||
doorbell_clr(driver_ccb);
|
doorbell_clr(driver_ccb);
|
||||||
|
|
||||||
/* make sure iLO is really handling requests */
|
/* make sure iLO is really handling requests */
|
||||||
for (i = 1000; i > 0; i--) {
|
for (i = MAX_WAIT; i > 0; i--) {
|
||||||
if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL))
|
if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL))
|
||||||
break;
|
break;
|
||||||
udelay(1);
|
udelay(1);
|
||||||
|
|
@ -326,7 +326,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
free:
|
free:
|
||||||
pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa);
|
ilo_ccb_close(pdev, data);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@
|
||||||
#define MAX_ILO_DEV 1
|
#define MAX_ILO_DEV 1
|
||||||
/* max number of files */
|
/* max number of files */
|
||||||
#define MAX_OPEN (MAX_CCB * MAX_ILO_DEV)
|
#define MAX_OPEN (MAX_CCB * MAX_ILO_DEV)
|
||||||
|
/* spin counter for open/close delay */
|
||||||
|
#define MAX_WAIT 10000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Per device, used to track global memory allocations.
|
* Per device, used to track global memory allocations.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* License. See the file "COPYING" in the main directory of this archive
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
* for more details.
|
* for more details.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved.
|
* Copyright (c) 2004-2009 Silicon Graphics, Inc. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -514,7 +514,8 @@ struct xpc_channel_uv {
|
||||||
/* partition's notify mq */
|
/* partition's notify mq */
|
||||||
|
|
||||||
struct xpc_send_msg_slot_uv *send_msg_slots;
|
struct xpc_send_msg_slot_uv *send_msg_slots;
|
||||||
struct xpc_notify_mq_msg_uv *recv_msg_slots;
|
void *recv_msg_slots; /* each slot will hold a xpc_notify_mq_msg_uv */
|
||||||
|
/* structure plus the user's payload */
|
||||||
|
|
||||||
struct xpc_fifo_head_uv msg_slot_free_list;
|
struct xpc_fifo_head_uv msg_slot_free_list;
|
||||||
struct xpc_fifo_head_uv recv_msg_list; /* deliverable payloads */
|
struct xpc_fifo_head_uv recv_msg_list; /* deliverable payloads */
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* License. See the file "COPYING" in the main directory of this archive
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
* for more details.
|
* for more details.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
|
* Copyright (c) 2008-2009 Silicon Graphics, Inc. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1010,8 +1010,8 @@ xpc_allocate_recv_msg_slot_uv(struct xpc_channel *ch)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (entry = 0; entry < nentries; entry++) {
|
for (entry = 0; entry < nentries; entry++) {
|
||||||
msg_slot = ch_uv->recv_msg_slots + entry *
|
msg_slot = ch_uv->recv_msg_slots +
|
||||||
ch->entry_size;
|
entry * ch->entry_size;
|
||||||
|
|
||||||
msg_slot->hdr.msg_slot_number = entry;
|
msg_slot->hdr.msg_slot_number = entry;
|
||||||
}
|
}
|
||||||
|
|
@ -1308,9 +1308,8 @@ xpc_handle_notify_mq_msg_uv(struct xpc_partition *part,
|
||||||
/* we're dealing with a normal message sent via the notify_mq */
|
/* we're dealing with a normal message sent via the notify_mq */
|
||||||
ch_uv = &ch->sn.uv;
|
ch_uv = &ch->sn.uv;
|
||||||
|
|
||||||
msg_slot = (struct xpc_notify_mq_msg_uv *)((u64)ch_uv->recv_msg_slots +
|
msg_slot = ch_uv->recv_msg_slots +
|
||||||
(msg->hdr.msg_slot_number % ch->remote_nentries) *
|
(msg->hdr.msg_slot_number % ch->remote_nentries) * ch->entry_size;
|
||||||
ch->entry_size);
|
|
||||||
|
|
||||||
BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number);
|
BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number);
|
||||||
BUG_ON(msg_slot->hdr.size != 0);
|
BUG_ON(msg_slot->hdr.size != 0);
|
||||||
|
|
|
||||||
|
|
@ -2276,8 +2276,7 @@ no_mem:
|
||||||
} else if ((len = ntohl(r->len_cq)) != 0) {
|
} else if ((len = ntohl(r->len_cq)) != 0) {
|
||||||
struct sge_fl *fl;
|
struct sge_fl *fl;
|
||||||
|
|
||||||
if (eth)
|
lro &= eth && is_eth_tcp(rss_hi);
|
||||||
lro = qs->lro_enabled && is_eth_tcp(rss_hi);
|
|
||||||
|
|
||||||
fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
|
fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
|
||||||
if (fl->use_pages) {
|
if (fl->use_pages) {
|
||||||
|
|
|
||||||
|
|
@ -351,6 +351,9 @@ static int gfar_probe(struct of_device *ofdev,
|
||||||
/* Reset MAC layer */
|
/* Reset MAC layer */
|
||||||
gfar_write(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
|
gfar_write(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
|
||||||
|
|
||||||
|
/* We need to delay at least 3 TX clocks */
|
||||||
|
udelay(2);
|
||||||
|
|
||||||
tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
|
tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
|
||||||
gfar_write(&priv->regs->maccfg1, tempval);
|
gfar_write(&priv->regs->maccfg1, tempval);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -312,7 +312,7 @@ extern const char gfar_driver_version[];
|
||||||
#define ATTRELI_EI(x) (x)
|
#define ATTRELI_EI(x) (x)
|
||||||
|
|
||||||
#define BD_LFLAG(flags) ((flags) << 16)
|
#define BD_LFLAG(flags) ((flags) << 16)
|
||||||
#define BD_LENGTH_MASK 0x00ff
|
#define BD_LENGTH_MASK 0x0000ffff
|
||||||
|
|
||||||
/* TxBD status field bits */
|
/* TxBD status field bits */
|
||||||
#define TXBD_READY 0x8000
|
#define TXBD_READY 0x8000
|
||||||
|
|
|
||||||
|
|
@ -4042,6 +4042,7 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||||
priv->is_open = 1;
|
priv->is_open = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pci_save_state(pdev);
|
||||||
pci_set_power_state(pdev, PCI_D3hot);
|
pci_set_power_state(pdev, PCI_D3hot);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -4052,6 +4053,7 @@ static int iwl_pci_resume(struct pci_dev *pdev)
|
||||||
struct iwl_priv *priv = pci_get_drvdata(pdev);
|
struct iwl_priv *priv = pci_get_drvdata(pdev);
|
||||||
|
|
||||||
pci_set_power_state(pdev, PCI_D0);
|
pci_set_power_state(pdev, PCI_D0);
|
||||||
|
pci_restore_state(pdev);
|
||||||
|
|
||||||
if (priv->is_open)
|
if (priv->is_open)
|
||||||
iwl_mac_start(priv->hw);
|
iwl_mac_start(priv->hw);
|
||||||
|
|
|
||||||
|
|
@ -480,6 +480,9 @@ void iwl_clear_stations_table(struct iwl_priv *priv)
|
||||||
priv->num_stations = 0;
|
priv->num_stations = 0;
|
||||||
memset(priv->stations, 0, sizeof(priv->stations));
|
memset(priv->stations, 0, sizeof(priv->stations));
|
||||||
|
|
||||||
|
/* clean ucode key table bit map */
|
||||||
|
priv->ucode_key_table = 0;
|
||||||
|
|
||||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iwl_clear_stations_table);
|
EXPORT_SYMBOL(iwl_clear_stations_table);
|
||||||
|
|
|
||||||
|
|
@ -8143,6 +8143,7 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||||
priv->is_open = 1;
|
priv->is_open = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pci_save_state(pdev);
|
||||||
pci_set_power_state(pdev, PCI_D3hot);
|
pci_set_power_state(pdev, PCI_D3hot);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -8153,6 +8154,7 @@ static int iwl3945_pci_resume(struct pci_dev *pdev)
|
||||||
struct iwl3945_priv *priv = pci_get_drvdata(pdev);
|
struct iwl3945_priv *priv = pci_get_drvdata(pdev);
|
||||||
|
|
||||||
pci_set_power_state(pdev, PCI_D0);
|
pci_set_power_state(pdev, PCI_D0);
|
||||||
|
pci_restore_state(pdev);
|
||||||
|
|
||||||
if (priv->is_open)
|
if (priv->is_open)
|
||||||
iwl3945_mac_start(priv->hw);
|
iwl3945_mac_start(priv->hw);
|
||||||
|
|
|
||||||
|
|
@ -355,6 +355,8 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
if (drv && drv->suspend) {
|
if (drv && drv->suspend) {
|
||||||
|
pci_power_t prev = pci_dev->current_state;
|
||||||
|
|
||||||
pci_dev->state_saved = false;
|
pci_dev->state_saved = false;
|
||||||
|
|
||||||
i = drv->suspend(pci_dev, state);
|
i = drv->suspend(pci_dev, state);
|
||||||
|
|
@ -365,12 +367,16 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
|
||||||
if (pci_dev->state_saved)
|
if (pci_dev->state_saved)
|
||||||
goto Fixup;
|
goto Fixup;
|
||||||
|
|
||||||
if (WARN_ON_ONCE(pci_dev->current_state != PCI_D0))
|
if (pci_dev->current_state != PCI_D0
|
||||||
|
&& pci_dev->current_state != PCI_UNKNOWN) {
|
||||||
|
WARN_ONCE(pci_dev->current_state != prev,
|
||||||
|
"PCI PM: Device state not saved by %pF\n",
|
||||||
|
drv->suspend);
|
||||||
goto Fixup;
|
goto Fixup;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pci_save_state(pci_dev);
|
pci_save_state(pci_dev);
|
||||||
pci_dev->state_saved = true;
|
|
||||||
/*
|
/*
|
||||||
* This is for compatibility with existing code with legacy PM support.
|
* This is for compatibility with existing code with legacy PM support.
|
||||||
*/
|
*/
|
||||||
|
|
@ -424,35 +430,20 @@ static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
|
||||||
pci_fixup_device(pci_fixup_resume_early, pci_dev);
|
pci_fixup_device(pci_fixup_resume_early, pci_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pci_pm_default_resume(struct pci_dev *pci_dev)
|
static void pci_pm_default_resume(struct pci_dev *pci_dev)
|
||||||
{
|
{
|
||||||
pci_fixup_device(pci_fixup_resume, pci_dev);
|
pci_fixup_device(pci_fixup_resume, pci_dev);
|
||||||
|
|
||||||
if (!pci_is_bridge(pci_dev))
|
if (!pci_is_bridge(pci_dev))
|
||||||
pci_enable_wake(pci_dev, PCI_D0, false);
|
pci_enable_wake(pci_dev, PCI_D0, false);
|
||||||
|
|
||||||
return pci_pm_reenable_device(pci_dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pci_pm_default_suspend_generic(struct pci_dev *pci_dev)
|
|
||||||
{
|
|
||||||
/* If device is enabled at this point, disable it */
|
|
||||||
pci_disable_enabled_device(pci_dev);
|
|
||||||
/*
|
|
||||||
* Save state with interrupts enabled, because in principle the bus the
|
|
||||||
* device is on may be put into a low power state after this code runs.
|
|
||||||
*/
|
|
||||||
pci_save_state(pci_dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pci_pm_default_suspend(struct pci_dev *pci_dev)
|
static void pci_pm_default_suspend(struct pci_dev *pci_dev)
|
||||||
{
|
{
|
||||||
pci_pm_default_suspend_generic(pci_dev);
|
/* Disable non-bridge devices without PM support */
|
||||||
|
|
||||||
if (!pci_is_bridge(pci_dev))
|
if (!pci_is_bridge(pci_dev))
|
||||||
pci_prepare_to_sleep(pci_dev);
|
pci_disable_enabled_device(pci_dev);
|
||||||
|
pci_save_state(pci_dev);
|
||||||
pci_fixup_device(pci_fixup_suspend, pci_dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
|
static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
|
||||||
|
|
@ -497,21 +488,49 @@ static void pci_pm_complete(struct device *dev)
|
||||||
static int pci_pm_suspend(struct device *dev)
|
static int pci_pm_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||||
struct device_driver *drv = dev->driver;
|
struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
if (pci_has_legacy_pm_support(pci_dev))
|
if (pci_has_legacy_pm_support(pci_dev))
|
||||||
return pci_legacy_suspend(dev, PMSG_SUSPEND);
|
return pci_legacy_suspend(dev, PMSG_SUSPEND);
|
||||||
|
|
||||||
if (drv && drv->pm && drv->pm->suspend) {
|
if (!pm) {
|
||||||
error = drv->pm->suspend(dev);
|
pci_pm_default_suspend(pci_dev);
|
||||||
suspend_report_result(drv->pm->suspend, error);
|
goto Fixup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error)
|
pci_dev->state_saved = false;
|
||||||
pci_pm_default_suspend(pci_dev);
|
|
||||||
|
|
||||||
|
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;
|
return error;
|
||||||
|
|
||||||
|
if (pci_dev->state_saved)
|
||||||
|
goto Fixup;
|
||||||
|
|
||||||
|
if (pci_dev->current_state != PCI_D0
|
||||||
|
&& pci_dev->current_state != PCI_UNKNOWN) {
|
||||||
|
WARN_ONCE(pci_dev->current_state != prev,
|
||||||
|
"PCI PM: State of device not saved by %pF\n",
|
||||||
|
pm->suspend);
|
||||||
|
goto Fixup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pci_dev->state_saved) {
|
||||||
|
pci_save_state(pci_dev);
|
||||||
|
if (!pci_is_bridge(pci_dev))
|
||||||
|
pci_prepare_to_sleep(pci_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
Fixup:
|
||||||
|
pci_fixup_device(pci_fixup_suspend, pci_dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pci_pm_suspend_noirq(struct device *dev)
|
static int pci_pm_suspend_noirq(struct device *dev)
|
||||||
|
|
@ -554,7 +573,7 @@ static int pci_pm_resume_noirq(struct device *dev)
|
||||||
static int pci_pm_resume(struct device *dev)
|
static int pci_pm_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||||
struct device_driver *drv = dev->driver;
|
struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -567,12 +586,16 @@ static int pci_pm_resume(struct device *dev)
|
||||||
if (pci_has_legacy_pm_support(pci_dev))
|
if (pci_has_legacy_pm_support(pci_dev))
|
||||||
return pci_legacy_resume(dev);
|
return pci_legacy_resume(dev);
|
||||||
|
|
||||||
error = pci_pm_default_resume(pci_dev);
|
pci_pm_default_resume(pci_dev);
|
||||||
|
|
||||||
if (!error && drv && drv->pm && drv->pm->resume)
|
if (pm) {
|
||||||
error = drv->pm->resume(dev);
|
if (pm->resume)
|
||||||
|
error = pm->resume(dev);
|
||||||
|
} else {
|
||||||
|
pci_pm_reenable_device(pci_dev);
|
||||||
|
}
|
||||||
|
|
||||||
return error;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !CONFIG_SUSPEND */
|
#else /* !CONFIG_SUSPEND */
|
||||||
|
|
@ -589,21 +612,31 @@ static int pci_pm_resume(struct device *dev)
|
||||||
static int pci_pm_freeze(struct device *dev)
|
static int pci_pm_freeze(struct device *dev)
|
||||||
{
|
{
|
||||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||||
struct device_driver *drv = dev->driver;
|
struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
if (pci_has_legacy_pm_support(pci_dev))
|
if (pci_has_legacy_pm_support(pci_dev))
|
||||||
return pci_legacy_suspend(dev, PMSG_FREEZE);
|
return pci_legacy_suspend(dev, PMSG_FREEZE);
|
||||||
|
|
||||||
if (drv && drv->pm && drv->pm->freeze) {
|
if (!pm) {
|
||||||
error = drv->pm->freeze(dev);
|
pci_pm_default_suspend(pci_dev);
|
||||||
suspend_report_result(drv->pm->freeze, error);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error)
|
pci_dev->state_saved = false;
|
||||||
pci_pm_default_suspend_generic(pci_dev);
|
|
||||||
|
|
||||||
|
if (pm->freeze) {
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = pm->freeze(dev);
|
||||||
|
suspend_report_result(pm->freeze, error);
|
||||||
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pci_dev->state_saved)
|
||||||
|
pci_save_state(pci_dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pci_pm_freeze_noirq(struct device *dev)
|
static int pci_pm_freeze_noirq(struct device *dev)
|
||||||
|
|
@ -646,16 +679,18 @@ static int pci_pm_thaw_noirq(struct device *dev)
|
||||||
static int pci_pm_thaw(struct device *dev)
|
static int pci_pm_thaw(struct device *dev)
|
||||||
{
|
{
|
||||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||||
struct device_driver *drv = dev->driver;
|
struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (pci_has_legacy_pm_support(pci_dev))
|
if (pci_has_legacy_pm_support(pci_dev))
|
||||||
return pci_legacy_resume(dev);
|
return pci_legacy_resume(dev);
|
||||||
|
|
||||||
|
if (pm) {
|
||||||
|
if (pm->thaw)
|
||||||
|
error = pm->thaw(dev);
|
||||||
|
} else {
|
||||||
pci_pm_reenable_device(pci_dev);
|
pci_pm_reenable_device(pci_dev);
|
||||||
|
}
|
||||||
if (drv && drv->pm && drv->pm->thaw)
|
|
||||||
error = drv->pm->thaw(dev);
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
@ -663,22 +698,29 @@ static int pci_pm_thaw(struct device *dev)
|
||||||
static int pci_pm_poweroff(struct device *dev)
|
static int pci_pm_poweroff(struct device *dev)
|
||||||
{
|
{
|
||||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||||
struct device_driver *drv = dev->driver;
|
struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (pci_has_legacy_pm_support(pci_dev))
|
if (pci_has_legacy_pm_support(pci_dev))
|
||||||
return pci_legacy_suspend(dev, PMSG_HIBERNATE);
|
return pci_legacy_suspend(dev, PMSG_HIBERNATE);
|
||||||
|
|
||||||
if (!drv || !drv->pm)
|
if (!pm) {
|
||||||
return 0;
|
pci_pm_default_suspend(pci_dev);
|
||||||
|
goto Fixup;
|
||||||
if (drv->pm->poweroff) {
|
|
||||||
error = drv->pm->poweroff(dev);
|
|
||||||
suspend_report_result(drv->pm->poweroff, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error)
|
pci_dev->state_saved = false;
|
||||||
pci_pm_default_suspend(pci_dev);
|
|
||||||
|
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;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
@ -719,7 +761,7 @@ static int pci_pm_restore_noirq(struct device *dev)
|
||||||
static int pci_pm_restore(struct device *dev)
|
static int pci_pm_restore(struct device *dev)
|
||||||
{
|
{
|
||||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||||
struct device_driver *drv = dev->driver;
|
struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -732,10 +774,14 @@ static int pci_pm_restore(struct device *dev)
|
||||||
if (pci_has_legacy_pm_support(pci_dev))
|
if (pci_has_legacy_pm_support(pci_dev))
|
||||||
return pci_legacy_resume(dev);
|
return pci_legacy_resume(dev);
|
||||||
|
|
||||||
error = pci_pm_default_resume(pci_dev);
|
pci_pm_default_resume(pci_dev);
|
||||||
|
|
||||||
if (!error && drv && drv->pm && drv->pm->restore)
|
if (pm) {
|
||||||
error = drv->pm->restore(dev);
|
if (pm->restore)
|
||||||
|
error = pm->restore(dev);
|
||||||
|
} else {
|
||||||
|
pci_pm_reenable_device(pci_dev);
|
||||||
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -768,8 +768,8 @@ pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
rom = pci_map_rom(pdev, &size); /* size starts out as PCI window size */
|
rom = pci_map_rom(pdev, &size); /* size starts out as PCI window size */
|
||||||
if (!rom)
|
if (!rom || !size)
|
||||||
return 0;
|
return -EIO;
|
||||||
|
|
||||||
if (off >= size)
|
if (off >= size)
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
|
||||||
|
|
@ -1418,10 +1418,10 @@ int pci_restore_standard_config(struct pci_dev *dev)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->current_state = PCI_D0;
|
pci_update_current_state(dev, PCI_D0);
|
||||||
|
|
||||||
Restore:
|
Restore:
|
||||||
return pci_restore_state(dev);
|
return dev->state_saved ? pci_restore_state(dev) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -718,9 +718,9 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All PCIe functions are in one slot, remove one function will remove
|
* All PCIe functions are in one slot, remove one function will remove
|
||||||
* the the whole slot, so just wait
|
* the whole slot, so just wait until we are the last function left.
|
||||||
*/
|
*/
|
||||||
if (!list_empty(&parent->subordinate->devices))
|
if (!list_is_last(&pdev->bus_list, &parent->subordinate->devices))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* All functions are removed, so just disable ASPM for the link */
|
/* All functions are removed, so just disable ASPM for the link */
|
||||||
|
|
|
||||||
|
|
@ -55,25 +55,13 @@ static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state)
|
|
||||||
{
|
|
||||||
return pci_save_state(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pcie_portdrv_resume_early(struct pci_dev *dev)
|
|
||||||
{
|
|
||||||
return pci_restore_state(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pcie_portdrv_resume(struct pci_dev *dev)
|
static int pcie_portdrv_resume(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
pcie_portdrv_restore_config(dev);
|
pci_set_master(dev);
|
||||||
return pcie_port_device_resume(dev);
|
return pcie_port_device_resume(dev);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define pcie_portdrv_suspend NULL
|
#define pcie_portdrv_suspend NULL
|
||||||
#define pcie_portdrv_suspend_late NULL
|
|
||||||
#define pcie_portdrv_resume_early NULL
|
|
||||||
#define pcie_portdrv_resume NULL
|
#define pcie_portdrv_resume NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -292,8 +280,6 @@ static struct pci_driver pcie_portdriver = {
|
||||||
.remove = pcie_portdrv_remove,
|
.remove = pcie_portdrv_remove,
|
||||||
|
|
||||||
.suspend = pcie_portdrv_suspend,
|
.suspend = pcie_portdrv_suspend,
|
||||||
.suspend_late = pcie_portdrv_suspend_late,
|
|
||||||
.resume_early = pcie_portdrv_resume_early,
|
|
||||||
.resume = pcie_portdrv_resume,
|
.resume = pcie_portdrv_resume,
|
||||||
|
|
||||||
.err_handler = &pcie_portdrv_err_handler,
|
.err_handler = &pcie_portdrv_err_handler,
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ void pci_disable_rom(struct pci_dev *pdev)
|
||||||
* The PCI window size could be much larger than the
|
* The PCI window size could be much larger than the
|
||||||
* actual image size.
|
* actual image size.
|
||||||
*/
|
*/
|
||||||
size_t pci_get_rom_size(void __iomem *rom, size_t size)
|
size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
|
||||||
{
|
{
|
||||||
void __iomem *image;
|
void __iomem *image;
|
||||||
int last_image;
|
int last_image;
|
||||||
|
|
@ -72,8 +72,10 @@ size_t pci_get_rom_size(void __iomem *rom, size_t size)
|
||||||
do {
|
do {
|
||||||
void __iomem *pds;
|
void __iomem *pds;
|
||||||
/* Standard PCI ROMs start out with these bytes 55 AA */
|
/* Standard PCI ROMs start out with these bytes 55 AA */
|
||||||
if (readb(image) != 0x55)
|
if (readb(image) != 0x55) {
|
||||||
|
dev_err(&pdev->dev, "Invalid ROM contents\n");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
if (readb(image + 1) != 0xAA)
|
if (readb(image + 1) != 0xAA)
|
||||||
break;
|
break;
|
||||||
/* get the PCI data structure and check its signature */
|
/* get the PCI data structure and check its signature */
|
||||||
|
|
@ -159,7 +161,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
|
||||||
* size is much larger than the actual size of the ROM.
|
* size is much larger than the actual size of the ROM.
|
||||||
* True size is important if the ROM is going to be copied.
|
* True size is important if the ROM is going to be copied.
|
||||||
*/
|
*/
|
||||||
*size = pci_get_rom_size(rom, *size);
|
*size = pci_get_rom_size(pdev, rom, *size);
|
||||||
return rom;
|
return rom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ config ASUS_LAPTOP
|
||||||
depends on LEDS_CLASS
|
depends on LEDS_CLASS
|
||||||
depends on NEW_LEDS
|
depends on NEW_LEDS
|
||||||
depends on BACKLIGHT_CLASS_DEVICE
|
depends on BACKLIGHT_CLASS_DEVICE
|
||||||
|
depends on INPUT
|
||||||
---help---
|
---help---
|
||||||
This is the new Linux driver for Asus laptops. It may also support some
|
This is the new Linux driver for Asus laptops. It may also support some
|
||||||
MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
|
MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@
|
||||||
#include <acpi/acpi_drivers.h>
|
#include <acpi/acpi_drivers.h>
|
||||||
#include <acpi/acpi_bus.h>
|
#include <acpi/acpi_bus.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
|
||||||
#define ASUS_LAPTOP_VERSION "0.42"
|
#define ASUS_LAPTOP_VERSION "0.42"
|
||||||
|
|
||||||
|
|
@ -181,6 +182,8 @@ struct asus_hotk {
|
||||||
u8 light_level; //light sensor level
|
u8 light_level; //light sensor level
|
||||||
u8 light_switch; //light sensor switch value
|
u8 light_switch; //light sensor switch value
|
||||||
u16 event_count[128]; //count for each event TODO make this better
|
u16 event_count[128]; //count for each event TODO make this better
|
||||||
|
struct input_dev *inputdev;
|
||||||
|
u16 *keycode_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -250,6 +253,37 @@ ASUS_LED(rled, "record");
|
||||||
ASUS_LED(pled, "phone");
|
ASUS_LED(pled, "phone");
|
||||||
ASUS_LED(gled, "gaming");
|
ASUS_LED(gled, "gaming");
|
||||||
|
|
||||||
|
struct key_entry {
|
||||||
|
char type;
|
||||||
|
u8 code;
|
||||||
|
u16 keycode;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum { KE_KEY, KE_END };
|
||||||
|
|
||||||
|
static struct key_entry asus_keymap[] = {
|
||||||
|
{KE_KEY, 0x30, KEY_VOLUMEUP},
|
||||||
|
{KE_KEY, 0x31, KEY_VOLUMEDOWN},
|
||||||
|
{KE_KEY, 0x32, KEY_MUTE},
|
||||||
|
{KE_KEY, 0x33, KEY_SWITCHVIDEOMODE},
|
||||||
|
{KE_KEY, 0x34, KEY_SWITCHVIDEOMODE},
|
||||||
|
{KE_KEY, 0x40, KEY_PREVIOUSSONG},
|
||||||
|
{KE_KEY, 0x41, KEY_NEXTSONG},
|
||||||
|
{KE_KEY, 0x43, KEY_STOP},
|
||||||
|
{KE_KEY, 0x45, KEY_PLAYPAUSE},
|
||||||
|
{KE_KEY, 0x50, KEY_EMAIL},
|
||||||
|
{KE_KEY, 0x51, KEY_WWW},
|
||||||
|
{KE_KEY, 0x5C, BTN_EXTRA}, /* Performance */
|
||||||
|
{KE_KEY, 0x5D, KEY_WLAN},
|
||||||
|
{KE_KEY, 0x61, KEY_SWITCHVIDEOMODE},
|
||||||
|
{KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */
|
||||||
|
{KE_KEY, 0x82, KEY_CAMERA},
|
||||||
|
{KE_KEY, 0x8A, KEY_TV},
|
||||||
|
{KE_KEY, 0x95, KEY_MEDIA},
|
||||||
|
{KE_KEY, 0x99, KEY_PHONE},
|
||||||
|
{KE_END, 0},
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function evaluates an ACPI method, given an int as parameter, the
|
* This function evaluates an ACPI method, given an int as parameter, the
|
||||||
* method is searched within the scope of the handle, can be NULL. The output
|
* method is searched within the scope of the handle, can be NULL. The output
|
||||||
|
|
@ -720,8 +754,68 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
|
||||||
return store_status(buf, count, NULL, GPS_ON);
|
return store_status(buf, count, NULL, GPS_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hotkey functions
|
||||||
|
*/
|
||||||
|
static struct key_entry *asus_get_entry_by_scancode(int code)
|
||||||
|
{
|
||||||
|
struct key_entry *key;
|
||||||
|
|
||||||
|
for (key = asus_keymap; key->type != KE_END; key++)
|
||||||
|
if (code == key->code)
|
||||||
|
return key;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct key_entry *asus_get_entry_by_keycode(int code)
|
||||||
|
{
|
||||||
|
struct key_entry *key;
|
||||||
|
|
||||||
|
for (key = asus_keymap; key->type != KE_END; key++)
|
||||||
|
if (code == key->keycode && key->type == KE_KEY)
|
||||||
|
return key;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode)
|
||||||
|
{
|
||||||
|
struct key_entry *key = asus_get_entry_by_scancode(scancode);
|
||||||
|
|
||||||
|
if (key && key->type == KE_KEY) {
|
||||||
|
*keycode = key->keycode;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
|
||||||
|
{
|
||||||
|
struct key_entry *key;
|
||||||
|
int old_keycode;
|
||||||
|
|
||||||
|
if (keycode < 0 || keycode > KEY_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
key = asus_get_entry_by_scancode(scancode);
|
||||||
|
if (key && key->type == KE_KEY) {
|
||||||
|
old_keycode = key->keycode;
|
||||||
|
key->keycode = keycode;
|
||||||
|
set_bit(keycode, dev->keybit);
|
||||||
|
if (!asus_get_entry_by_keycode(old_keycode))
|
||||||
|
clear_bit(old_keycode, dev->keybit);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
|
static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
|
||||||
{
|
{
|
||||||
|
static struct key_entry *key;
|
||||||
|
|
||||||
/* TODO Find a better way to handle events count. */
|
/* TODO Find a better way to handle events count. */
|
||||||
if (!hotk)
|
if (!hotk)
|
||||||
return;
|
return;
|
||||||
|
|
@ -738,10 +832,24 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
|
||||||
lcd_blank(FB_BLANK_POWERDOWN);
|
lcd_blank(FB_BLANK_POWERDOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
acpi_bus_generate_proc_event(hotk->device, event,
|
acpi_bus_generate_netlink_event(hotk->device->pnp.device_class,
|
||||||
|
dev_name(&hotk->device->dev), event,
|
||||||
hotk->event_count[event % 128]++);
|
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) \
|
#define ASUS_CREATE_DEVICE_ATTR(_name) \
|
||||||
|
|
@ -959,6 +1067,38 @@ static int asus_hotk_get_info(void)
|
||||||
return AE_OK;
|
return AE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int asus_input_init(void)
|
||||||
|
{
|
||||||
|
const struct key_entry *key;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
hotk->inputdev = input_allocate_device();
|
||||||
|
if (!hotk->inputdev) {
|
||||||
|
printk(ASUS_INFO "Unable to allocate input device\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
hotk->inputdev->name = "Asus Laptop extra buttons";
|
||||||
|
hotk->inputdev->phys = ASUS_HOTK_FILE "/input0";
|
||||||
|
hotk->inputdev->id.bustype = BUS_HOST;
|
||||||
|
hotk->inputdev->getkeycode = asus_getkeycode;
|
||||||
|
hotk->inputdev->setkeycode = asus_setkeycode;
|
||||||
|
|
||||||
|
for (key = asus_keymap; key->type != KE_END; key++) {
|
||||||
|
switch (key->type) {
|
||||||
|
case KE_KEY:
|
||||||
|
set_bit(EV_KEY, hotk->inputdev->evbit);
|
||||||
|
set_bit(key->keycode, hotk->inputdev->keybit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = input_register_device(hotk->inputdev);
|
||||||
|
if (result) {
|
||||||
|
printk(ASUS_INFO "Unable to register input device\n");
|
||||||
|
input_free_device(hotk->inputdev);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static int asus_hotk_check(void)
|
static int asus_hotk_check(void)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
@ -1044,7 +1184,7 @@ static int asus_hotk_add(struct acpi_device *device)
|
||||||
/* GPS is on by default */
|
/* GPS is on by default */
|
||||||
write_status(NULL, 1, GPS_ON);
|
write_status(NULL, 1, GPS_ON);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (result) {
|
if (result) {
|
||||||
kfree(hotk->name);
|
kfree(hotk->name);
|
||||||
kfree(hotk);
|
kfree(hotk);
|
||||||
|
|
@ -1091,10 +1231,17 @@ static void asus_led_exit(void)
|
||||||
ASUS_LED_UNREGISTER(gled);
|
ASUS_LED_UNREGISTER(gled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void asus_input_exit(void)
|
||||||
|
{
|
||||||
|
if (hotk->inputdev)
|
||||||
|
input_unregister_device(hotk->inputdev);
|
||||||
|
}
|
||||||
|
|
||||||
static void __exit asus_laptop_exit(void)
|
static void __exit asus_laptop_exit(void)
|
||||||
{
|
{
|
||||||
asus_backlight_exit();
|
asus_backlight_exit();
|
||||||
asus_led_exit();
|
asus_led_exit();
|
||||||
|
asus_input_exit();
|
||||||
|
|
||||||
acpi_bus_unregister_driver(&asus_hotk_driver);
|
acpi_bus_unregister_driver(&asus_hotk_driver);
|
||||||
sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);
|
sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);
|
||||||
|
|
@ -1216,6 +1363,10 @@ static int __init asus_laptop_init(void)
|
||||||
printk(ASUS_INFO "Brightness ignored, must be controlled by "
|
printk(ASUS_INFO "Brightness ignored, must be controlled by "
|
||||||
"ACPI video driver\n");
|
"ACPI video driver\n");
|
||||||
|
|
||||||
|
result = asus_input_init();
|
||||||
|
if (result)
|
||||||
|
goto fail_input;
|
||||||
|
|
||||||
result = asus_led_init(dev);
|
result = asus_led_init(dev);
|
||||||
if (result)
|
if (result)
|
||||||
goto fail_led;
|
goto fail_led;
|
||||||
|
|
@ -1242,22 +1393,25 @@ static int __init asus_laptop_init(void)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_sysfs:
|
fail_sysfs:
|
||||||
platform_device_del(asuspf_device);
|
platform_device_del(asuspf_device);
|
||||||
|
|
||||||
fail_platform_device2:
|
fail_platform_device2:
|
||||||
platform_device_put(asuspf_device);
|
platform_device_put(asuspf_device);
|
||||||
|
|
||||||
fail_platform_device1:
|
fail_platform_device1:
|
||||||
platform_driver_unregister(&asuspf_driver);
|
platform_driver_unregister(&asuspf_driver);
|
||||||
|
|
||||||
fail_platform_driver:
|
fail_platform_driver:
|
||||||
asus_led_exit();
|
asus_led_exit();
|
||||||
|
|
||||||
fail_led:
|
fail_led:
|
||||||
|
asus_input_exit();
|
||||||
|
|
||||||
|
fail_input:
|
||||||
asus_backlight_exit();
|
asus_backlight_exit();
|
||||||
|
|
||||||
fail_backlight:
|
fail_backlight:
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,7 @@ struct asus_hotk {
|
||||||
S1300N, S5200N*/
|
S1300N, S5200N*/
|
||||||
A4S, /* Z81sp */
|
A4S, /* Z81sp */
|
||||||
F3Sa, /* (Centrino) */
|
F3Sa, /* (Centrino) */
|
||||||
|
R1F,
|
||||||
END_MODEL
|
END_MODEL
|
||||||
} model; /* Models currently supported */
|
} model; /* Models currently supported */
|
||||||
u16 event_count[128]; /* Count for each event TODO make this better */
|
u16 event_count[128]; /* Count for each event TODO make this better */
|
||||||
|
|
@ -420,7 +421,18 @@ static struct model_data model_conf[END_MODEL] = {
|
||||||
.display_get = "\\ADVG",
|
.display_get = "\\ADVG",
|
||||||
.display_set = "SDSP",
|
.display_set = "SDSP",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "R1F",
|
||||||
|
.mt_bt_switch = "BLED",
|
||||||
|
.mt_mled = "MLED",
|
||||||
|
.mt_wled = "WLED",
|
||||||
|
.mt_lcd_switch = "\\Q10",
|
||||||
|
.lcd_status = "\\GP06",
|
||||||
|
.brightness_set = "SPLV",
|
||||||
|
.brightness_get = "GPLV",
|
||||||
|
.display_set = "SDSP",
|
||||||
|
.display_get = "\\INFB"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* procdir we use */
|
/* procdir we use */
|
||||||
|
|
@ -1165,6 +1177,8 @@ static int asus_model_match(char *model)
|
||||||
return W3V;
|
return W3V;
|
||||||
else if (strncmp(model, "W5A", 3) == 0)
|
else if (strncmp(model, "W5A", 3) == 0)
|
||||||
return W5A;
|
return W5A;
|
||||||
|
else if (strncmp(model, "R1F", 3) == 0)
|
||||||
|
return R1F;
|
||||||
else if (strncmp(model, "A4S", 3) == 0)
|
else if (strncmp(model, "A4S", 3) == 0)
|
||||||
return A4S;
|
return A4S;
|
||||||
else if (strncmp(model, "F3Sa", 4) == 0)
|
else if (strncmp(model, "F3Sa", 4) == 0)
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/rfkill.h>
|
#include <linux/rfkill.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
|
||||||
#define EEEPC_LAPTOP_VERSION "0.1"
|
#define EEEPC_LAPTOP_VERSION "0.1"
|
||||||
|
|
||||||
|
|
@ -161,6 +162,10 @@ static struct key_entry eeepc_keymap[] = {
|
||||||
{KE_KEY, 0x13, KEY_MUTE },
|
{KE_KEY, 0x13, KEY_MUTE },
|
||||||
{KE_KEY, 0x14, KEY_VOLUMEDOWN },
|
{KE_KEY, 0x14, KEY_VOLUMEDOWN },
|
||||||
{KE_KEY, 0x15, KEY_VOLUMEUP },
|
{KE_KEY, 0x15, KEY_VOLUMEUP },
|
||||||
|
{KE_KEY, 0x1a, KEY_COFFEE },
|
||||||
|
{KE_KEY, 0x1b, KEY_ZOOM },
|
||||||
|
{KE_KEY, 0x1c, KEY_PROG2 },
|
||||||
|
{KE_KEY, 0x1d, KEY_PROG3 },
|
||||||
{KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
|
{KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
|
||||||
{KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
|
{KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
|
||||||
{KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
|
{KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
|
||||||
|
|
@ -510,9 +515,45 @@ static int eeepc_hotk_check(void)
|
||||||
static void notify_brn(void)
|
static void notify_brn(void)
|
||||||
{
|
{
|
||||||
struct backlight_device *bd = eeepc_backlight_device;
|
struct backlight_device *bd = eeepc_backlight_device;
|
||||||
|
if (bd)
|
||||||
bd->props.brightness = read_brightness(bd);
|
bd->props.brightness = read_brightness(bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
|
||||||
|
{
|
||||||
|
struct pci_dev *dev;
|
||||||
|
struct pci_bus *bus = pci_find_bus(0, 1);
|
||||||
|
|
||||||
|
if (event != ACPI_NOTIFY_BUS_CHECK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!bus) {
|
||||||
|
printk(EEEPC_WARNING "Unable to find PCI bus 1?\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_acpi(CM_ASL_WLAN) == 1) {
|
||||||
|
dev = pci_get_slot(bus, 0);
|
||||||
|
if (dev) {
|
||||||
|
/* Device already present */
|
||||||
|
pci_dev_put(dev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dev = pci_scan_single_device(bus, 0);
|
||||||
|
if (dev) {
|
||||||
|
pci_bus_assign_resources(bus);
|
||||||
|
if (pci_bus_add_device(dev))
|
||||||
|
printk(EEEPC_ERR "Unable to hotplug wifi\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dev = pci_get_slot(bus, 0);
|
||||||
|
if (dev) {
|
||||||
|
pci_remove_bus_device(dev);
|
||||||
|
pci_dev_put(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
|
static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
|
||||||
{
|
{
|
||||||
static struct key_entry *key;
|
static struct key_entry *key;
|
||||||
|
|
@ -520,7 +561,8 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
|
||||||
return;
|
return;
|
||||||
if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
|
if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
|
||||||
notify_brn();
|
notify_brn();
|
||||||
acpi_bus_generate_proc_event(ehotk->device, event,
|
acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
|
||||||
|
dev_name(&ehotk->device->dev), event,
|
||||||
ehotk->event_count[event % 128]++);
|
ehotk->event_count[event % 128]++);
|
||||||
if (ehotk->inputdev) {
|
if (ehotk->inputdev) {
|
||||||
key = eepc_get_entry_by_scancode(event);
|
key = eepc_get_entry_by_scancode(event);
|
||||||
|
|
@ -539,6 +581,45 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int eeepc_register_rfkill_notifier(char *node)
|
||||||
|
{
|
||||||
|
acpi_status status = AE_OK;
|
||||||
|
acpi_handle handle;
|
||||||
|
|
||||||
|
status = acpi_get_handle(NULL, node, &handle);
|
||||||
|
|
||||||
|
if (ACPI_SUCCESS(status)) {
|
||||||
|
status = acpi_install_notify_handler(handle,
|
||||||
|
ACPI_SYSTEM_NOTIFY,
|
||||||
|
eeepc_rfkill_notify,
|
||||||
|
NULL);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
printk(EEEPC_WARNING
|
||||||
|
"Failed to register notify on %s\n", node);
|
||||||
|
} else
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eeepc_unregister_rfkill_notifier(char *node)
|
||||||
|
{
|
||||||
|
acpi_status status = AE_OK;
|
||||||
|
acpi_handle handle;
|
||||||
|
|
||||||
|
status = acpi_get_handle(NULL, node, &handle);
|
||||||
|
|
||||||
|
if (ACPI_SUCCESS(status)) {
|
||||||
|
status = acpi_remove_notify_handler(handle,
|
||||||
|
ACPI_SYSTEM_NOTIFY,
|
||||||
|
eeepc_rfkill_notify);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
printk(EEEPC_ERR
|
||||||
|
"Error removing rfkill notify handler %s\n",
|
||||||
|
node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int eeepc_hotk_add(struct acpi_device *device)
|
static int eeepc_hotk_add(struct acpi_device *device)
|
||||||
{
|
{
|
||||||
acpi_status status = AE_OK;
|
acpi_status status = AE_OK;
|
||||||
|
|
@ -558,7 +639,7 @@ static int eeepc_hotk_add(struct acpi_device *device)
|
||||||
ehotk->device = device;
|
ehotk->device = device;
|
||||||
result = eeepc_hotk_check();
|
result = eeepc_hotk_check();
|
||||||
if (result)
|
if (result)
|
||||||
goto end;
|
goto ehotk_fail;
|
||||||
status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
|
status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
|
||||||
eeepc_hotk_notify, ehotk);
|
eeepc_hotk_notify, ehotk);
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
|
|
@ -569,18 +650,25 @@ static int eeepc_hotk_add(struct acpi_device *device)
|
||||||
RFKILL_TYPE_WLAN);
|
RFKILL_TYPE_WLAN);
|
||||||
|
|
||||||
if (!ehotk->eeepc_wlan_rfkill)
|
if (!ehotk->eeepc_wlan_rfkill)
|
||||||
goto end;
|
goto wlan_fail;
|
||||||
|
|
||||||
ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan";
|
ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan";
|
||||||
ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set;
|
ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set;
|
||||||
ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
|
ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
|
||||||
if (get_acpi(CM_ASL_WLAN) == 1)
|
if (get_acpi(CM_ASL_WLAN) == 1) {
|
||||||
ehotk->eeepc_wlan_rfkill->state =
|
ehotk->eeepc_wlan_rfkill->state =
|
||||||
RFKILL_STATE_UNBLOCKED;
|
RFKILL_STATE_UNBLOCKED;
|
||||||
else
|
rfkill_set_default(RFKILL_TYPE_WLAN,
|
||||||
|
RFKILL_STATE_UNBLOCKED);
|
||||||
|
} else {
|
||||||
ehotk->eeepc_wlan_rfkill->state =
|
ehotk->eeepc_wlan_rfkill->state =
|
||||||
RFKILL_STATE_SOFT_BLOCKED;
|
RFKILL_STATE_SOFT_BLOCKED;
|
||||||
rfkill_register(ehotk->eeepc_wlan_rfkill);
|
rfkill_set_default(RFKILL_TYPE_WLAN,
|
||||||
|
RFKILL_STATE_SOFT_BLOCKED);
|
||||||
|
}
|
||||||
|
result = rfkill_register(ehotk->eeepc_wlan_rfkill);
|
||||||
|
if (result)
|
||||||
|
goto wlan_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
|
if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
|
||||||
|
|
@ -588,27 +676,47 @@ static int eeepc_hotk_add(struct acpi_device *device)
|
||||||
rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH);
|
rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH);
|
||||||
|
|
||||||
if (!ehotk->eeepc_bluetooth_rfkill)
|
if (!ehotk->eeepc_bluetooth_rfkill)
|
||||||
goto end;
|
goto bluetooth_fail;
|
||||||
|
|
||||||
ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth";
|
ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth";
|
||||||
ehotk->eeepc_bluetooth_rfkill->toggle_radio =
|
ehotk->eeepc_bluetooth_rfkill->toggle_radio =
|
||||||
eeepc_bluetooth_rfkill_set;
|
eeepc_bluetooth_rfkill_set;
|
||||||
ehotk->eeepc_bluetooth_rfkill->get_state =
|
ehotk->eeepc_bluetooth_rfkill->get_state =
|
||||||
eeepc_bluetooth_rfkill_state;
|
eeepc_bluetooth_rfkill_state;
|
||||||
if (get_acpi(CM_ASL_BLUETOOTH) == 1)
|
if (get_acpi(CM_ASL_BLUETOOTH) == 1) {
|
||||||
ehotk->eeepc_bluetooth_rfkill->state =
|
ehotk->eeepc_bluetooth_rfkill->state =
|
||||||
RFKILL_STATE_UNBLOCKED;
|
RFKILL_STATE_UNBLOCKED;
|
||||||
else
|
rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
|
||||||
|
RFKILL_STATE_UNBLOCKED);
|
||||||
|
} else {
|
||||||
ehotk->eeepc_bluetooth_rfkill->state =
|
ehotk->eeepc_bluetooth_rfkill->state =
|
||||||
RFKILL_STATE_SOFT_BLOCKED;
|
RFKILL_STATE_SOFT_BLOCKED;
|
||||||
rfkill_register(ehotk->eeepc_bluetooth_rfkill);
|
rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
|
||||||
|
RFKILL_STATE_SOFT_BLOCKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
|
||||||
if (result) {
|
if (result)
|
||||||
|
goto bluetooth_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
|
||||||
|
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bluetooth_fail:
|
||||||
|
if (ehotk->eeepc_bluetooth_rfkill)
|
||||||
|
rfkill_free(ehotk->eeepc_bluetooth_rfkill);
|
||||||
|
rfkill_unregister(ehotk->eeepc_wlan_rfkill);
|
||||||
|
ehotk->eeepc_wlan_rfkill = NULL;
|
||||||
|
wlan_fail:
|
||||||
|
if (ehotk->eeepc_wlan_rfkill)
|
||||||
|
rfkill_free(ehotk->eeepc_wlan_rfkill);
|
||||||
|
ehotk_fail:
|
||||||
kfree(ehotk);
|
kfree(ehotk);
|
||||||
ehotk = NULL;
|
ehotk = NULL;
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -622,6 +730,10 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type)
|
||||||
eeepc_hotk_notify);
|
eeepc_hotk_notify);
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
printk(EEEPC_ERR "Error removing notify handler\n");
|
printk(EEEPC_ERR "Error removing notify handler\n");
|
||||||
|
|
||||||
|
eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
|
||||||
|
eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
|
||||||
|
|
||||||
kfree(ehotk);
|
kfree(ehotk);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -737,13 +849,21 @@ static void eeepc_backlight_exit(void)
|
||||||
{
|
{
|
||||||
if (eeepc_backlight_device)
|
if (eeepc_backlight_device)
|
||||||
backlight_device_unregister(eeepc_backlight_device);
|
backlight_device_unregister(eeepc_backlight_device);
|
||||||
if (ehotk->inputdev)
|
eeepc_backlight_device = NULL;
|
||||||
input_unregister_device(ehotk->inputdev);
|
}
|
||||||
|
|
||||||
|
static void eeepc_rfkill_exit(void)
|
||||||
|
{
|
||||||
if (ehotk->eeepc_wlan_rfkill)
|
if (ehotk->eeepc_wlan_rfkill)
|
||||||
rfkill_unregister(ehotk->eeepc_wlan_rfkill);
|
rfkill_unregister(ehotk->eeepc_wlan_rfkill);
|
||||||
if (ehotk->eeepc_bluetooth_rfkill)
|
if (ehotk->eeepc_bluetooth_rfkill)
|
||||||
rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
|
rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
|
||||||
eeepc_backlight_device = NULL;
|
}
|
||||||
|
|
||||||
|
static void eeepc_input_exit(void)
|
||||||
|
{
|
||||||
|
if (ehotk->inputdev)
|
||||||
|
input_unregister_device(ehotk->inputdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void eeepc_hwmon_exit(void)
|
static void eeepc_hwmon_exit(void)
|
||||||
|
|
@ -762,6 +882,8 @@ static void eeepc_hwmon_exit(void)
|
||||||
static void __exit eeepc_laptop_exit(void)
|
static void __exit eeepc_laptop_exit(void)
|
||||||
{
|
{
|
||||||
eeepc_backlight_exit();
|
eeepc_backlight_exit();
|
||||||
|
eeepc_rfkill_exit();
|
||||||
|
eeepc_input_exit();
|
||||||
eeepc_hwmon_exit();
|
eeepc_hwmon_exit();
|
||||||
acpi_bus_unregister_driver(&eeepc_hotk_driver);
|
acpi_bus_unregister_driver(&eeepc_hotk_driver);
|
||||||
sysfs_remove_group(&platform_device->dev.kobj,
|
sysfs_remove_group(&platform_device->dev.kobj,
|
||||||
|
|
@ -865,6 +987,8 @@ fail_platform_driver:
|
||||||
fail_hwmon:
|
fail_hwmon:
|
||||||
eeepc_backlight_exit();
|
eeepc_backlight_exit();
|
||||||
fail_backlight:
|
fail_backlight:
|
||||||
|
eeepc_input_exit();
|
||||||
|
eeepc_rfkill_exit();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -463,8 +463,10 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
register_wwan_err:
|
register_wwan_err:
|
||||||
|
if (bluetooth_rfkill)
|
||||||
rfkill_unregister(bluetooth_rfkill);
|
rfkill_unregister(bluetooth_rfkill);
|
||||||
register_bluetooth_error:
|
register_bluetooth_error:
|
||||||
|
if (wifi_rfkill)
|
||||||
rfkill_unregister(wifi_rfkill);
|
rfkill_unregister(wifi_rfkill);
|
||||||
add_sysfs_error:
|
add_sysfs_error:
|
||||||
cleanup_sysfs(device);
|
cleanup_sysfs(device);
|
||||||
|
|
|
||||||
|
|
@ -507,7 +507,7 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
|
||||||
|
|
||||||
hkey_num = result & 0xf;
|
hkey_num = result & 0xf;
|
||||||
|
|
||||||
if (hkey_num < 0 || hkey_num > ARRAY_SIZE(pcc->keymap)) {
|
if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) {
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||||
"hotkey number out of range: %d\n",
|
"hotkey number out of range: %d\n",
|
||||||
hkey_num));
|
hkey_num));
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,12 @@ config RTC_DRV_M41T80_WDT
|
||||||
If you say Y here you will get support for the
|
If you say Y here you will get support for the
|
||||||
watchdog timer in the ST M41T60 and M41T80 RTC chips series.
|
watchdog timer in the ST M41T60 and M41T80 RTC chips series.
|
||||||
|
|
||||||
|
config RTC_DRV_DM355EVM
|
||||||
|
tristate "TI DaVinci DM355 EVM RTC"
|
||||||
|
depends on MFD_DM355EVM_MSP
|
||||||
|
help
|
||||||
|
Supports the RTC firmware in the MSP430 on the DM355 EVM.
|
||||||
|
|
||||||
config RTC_DRV_TWL92330
|
config RTC_DRV_TWL92330
|
||||||
boolean "TI TWL92330/Menelaus"
|
boolean "TI TWL92330/Menelaus"
|
||||||
depends on MENELAUS
|
depends on MENELAUS
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
|
||||||
obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o
|
obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o
|
||||||
obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o
|
obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o
|
||||||
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
|
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
|
||||||
|
obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o
|
||||||
obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o
|
obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o
|
||||||
obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o
|
obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o
|
||||||
obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
|
obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
|
||||||
|
|
|
||||||
175
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)
|
static int __devinit ds1390_probe(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct rtc_device *rtc;
|
|
||||||
unsigned char tmp;
|
unsigned char tmp;
|
||||||
struct ds1390 *chip;
|
struct ds1390 *chip;
|
||||||
int res;
|
int res;
|
||||||
|
|
|
||||||
|
|
@ -1475,7 +1475,7 @@ static int aty128fb_set_par(struct fb_info *info)
|
||||||
aty128_set_pll(&par->pll, par);
|
aty128_set_pll(&par->pll, par);
|
||||||
aty128_set_fifo(&par->fifo_reg, par);
|
aty128_set_fifo(&par->fifo_reg, par);
|
||||||
|
|
||||||
config = aty_ld_le32(CONFIG_CNTL) & ~3;
|
config = aty_ld_le32(CNFG_CNTL) & ~3;
|
||||||
|
|
||||||
#if defined(__BIG_ENDIAN)
|
#if defined(__BIG_ENDIAN)
|
||||||
if (par->crtc.bpp == 32)
|
if (par->crtc.bpp == 32)
|
||||||
|
|
@ -1484,7 +1484,7 @@ static int aty128fb_set_par(struct fb_info *info)
|
||||||
config |= 1; /* make aperture do 16 bit swapping */
|
config |= 1; /* make aperture do 16 bit swapping */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
aty_st_le32(CONFIG_CNTL, config);
|
aty_st_le32(CNFG_CNTL, config);
|
||||||
aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */
|
aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */
|
||||||
|
|
||||||
info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
|
info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
|
||||||
|
|
@ -1875,7 +1875,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i
|
||||||
u32 dac;
|
u32 dac;
|
||||||
|
|
||||||
/* Get the chip revision */
|
/* Get the chip revision */
|
||||||
chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
|
chip_rev = (aty_ld_le32(CNFG_CNTL) >> 16) & 0x1F;
|
||||||
|
|
||||||
strcpy(video_card, "Rage128 XX ");
|
strcpy(video_card, "Rage128 XX ");
|
||||||
video_card[8] = ent->device >> 8;
|
video_card[8] = ent->device >> 8;
|
||||||
|
|
@ -2057,7 +2057,7 @@ static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_
|
||||||
|
|
||||||
/* Grab memory size from the card */
|
/* Grab memory size from the card */
|
||||||
// How does this relate to the resource length from the PCI hardware?
|
// How does this relate to the resource length from the PCI hardware?
|
||||||
par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
|
par->vram_size = aty_ld_le32(CNFG_MEMSIZE) & 0x03FFFFFF;
|
||||||
|
|
||||||
/* Virtualize the framebuffer */
|
/* Virtualize the framebuffer */
|
||||||
info->screen_base = ioremap(fb_addr, par->vram_size);
|
info->screen_base = ioremap(fb_addr, par->vram_size);
|
||||||
|
|
@ -2374,6 +2374,8 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
|
||||||
/* Set the chip into the appropriate suspend mode (we use D2,
|
/* Set the chip into the appropriate suspend mode (we use D2,
|
||||||
* D3 would require a complete re-initialisation of the chip,
|
* D3 would require a complete re-initialisation of the chip,
|
||||||
* including PCI config registers, clocks, AGP configuration, ...)
|
* including PCI config registers, clocks, AGP configuration, ...)
|
||||||
|
*
|
||||||
|
* For resume, the core will have already brought us back to D0
|
||||||
*/
|
*/
|
||||||
if (suspend) {
|
if (suspend) {
|
||||||
/* Make sure CRTC2 is reset. Remove that the day we decide to
|
/* Make sure CRTC2 is reset. Remove that the day we decide to
|
||||||
|
|
@ -2391,17 +2393,9 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
|
||||||
aty_st_le32(BUS_CNTL1, 0x00000010);
|
aty_st_le32(BUS_CNTL1, 0x00000010);
|
||||||
aty_st_le32(MEM_POWER_MISC, 0x0c830000);
|
aty_st_le32(MEM_POWER_MISC, 0x0c830000);
|
||||||
mdelay(100);
|
mdelay(100);
|
||||||
pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command);
|
|
||||||
/* Switch PCI power management to D2 */
|
/* Switch PCI power management to D2 */
|
||||||
pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL,
|
pci_set_power_state(pdev, PCI_D2);
|
||||||
(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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2410,6 +2404,12 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||||
struct fb_info *info = pci_get_drvdata(pdev);
|
struct fb_info *info = pci_get_drvdata(pdev);
|
||||||
struct aty128fb_par *par = info->par;
|
struct aty128fb_par *par = info->par;
|
||||||
|
|
||||||
|
/* Because we may change PCI D state ourselves, we need to
|
||||||
|
* first save the config space content so the core can
|
||||||
|
* restore it properly on resume.
|
||||||
|
*/
|
||||||
|
pci_save_state(pdev);
|
||||||
|
|
||||||
/* We don't do anything but D2, for now we return 0, but
|
/* We don't do anything but D2, for now we return 0, but
|
||||||
* we may want to change that. How do we know if the BIOS
|
* we may want to change that. How do we know if the BIOS
|
||||||
* can properly take care of D3 ? Also, with swsusp, we
|
* can properly take care of D3 ? Also, with swsusp, we
|
||||||
|
|
@ -2476,6 +2476,11 @@ static int aty128_do_resume(struct pci_dev *pdev)
|
||||||
if (pdev->dev.power.power_state.event == PM_EVENT_ON)
|
if (pdev->dev.power.power_state.event == PM_EVENT_ON)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* PCI state will have been restored by the core, so
|
||||||
|
* we should be in D0 now with our config space fully
|
||||||
|
* restored
|
||||||
|
*/
|
||||||
|
|
||||||
/* Wakeup chip */
|
/* Wakeup chip */
|
||||||
aty128_set_suspend(par, 0);
|
aty128_set_suspend(par, 0);
|
||||||
par->asleep = 0;
|
par->asleep = 0;
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@
|
||||||
#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
|
#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
|
||||||
defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT)
|
defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT)
|
||||||
static const u32 lt_lcd_regs[] = {
|
static const u32 lt_lcd_regs[] = {
|
||||||
CONFIG_PANEL_LG,
|
CNFG_PANEL_LG,
|
||||||
LCD_GEN_CNTL_LG,
|
LCD_GEN_CNTL_LG,
|
||||||
DSTN_CONTROL_LG,
|
DSTN_CONTROL_LG,
|
||||||
HFB_PITCH_ADDR_LG,
|
HFB_PITCH_ADDR_LG,
|
||||||
|
|
@ -446,7 +446,7 @@ static int __devinit correct_chipset(struct atyfb_par *par)
|
||||||
par->pll_limits.ecp_max = aty_chips[i].ecp_max;
|
par->pll_limits.ecp_max = aty_chips[i].ecp_max;
|
||||||
par->features = aty_chips[i].features;
|
par->features = aty_chips[i].features;
|
||||||
|
|
||||||
chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
|
chip_id = aty_ld_le32(CNFG_CHIP_ID, par);
|
||||||
type = chip_id & CFG_CHIP_TYPE;
|
type = chip_id & CFG_CHIP_TYPE;
|
||||||
rev = (chip_id & CFG_CHIP_REV) >> 24;
|
rev = (chip_id & CFG_CHIP_REV) >> 24;
|
||||||
|
|
||||||
|
|
@ -629,7 +629,7 @@ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
|
||||||
crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
|
crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
|
||||||
aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
|
aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
|
||||||
}
|
}
|
||||||
crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par);
|
crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par);
|
||||||
crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
|
crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -676,7 +676,7 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
|
||||||
aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
|
aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
|
||||||
|
|
||||||
/* update non-shadow registers first */
|
/* update non-shadow registers first */
|
||||||
aty_st_lcd(CONFIG_PANEL, crtc->lcd_config_panel, par);
|
aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par);
|
||||||
aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
|
aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
|
||||||
~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
|
~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
|
||||||
|
|
||||||
|
|
@ -858,7 +858,7 @@ static int aty_var_to_crtc(const struct fb_info *info,
|
||||||
if (!M64_HAS(MOBIL_BUS))
|
if (!M64_HAS(MOBIL_BUS))
|
||||||
crtc->lcd_index |= CRTC2_DISPLAY_DIS;
|
crtc->lcd_index |= CRTC2_DISPLAY_DIS;
|
||||||
|
|
||||||
crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par) | 0x4000;
|
crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par) | 0x4000;
|
||||||
crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
|
crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
|
||||||
|
|
||||||
crtc->lcd_gen_cntl &=
|
crtc->lcd_gen_cntl &=
|
||||||
|
|
@ -1978,7 +1978,7 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par)
|
||||||
|
|
||||||
return timeout ? 0 : -EIO;
|
return timeout ? 0 : -EIO;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* CONFIG_PPC_PMAC */
|
||||||
|
|
||||||
static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||||
{
|
{
|
||||||
|
|
@ -2002,9 +2002,15 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||||
par->asleep = 1;
|
par->asleep = 1;
|
||||||
par->lock_blank = 1;
|
par->lock_blank = 1;
|
||||||
|
|
||||||
|
/* Because we may change PCI D state ourselves, we need to
|
||||||
|
* first save the config space content so the core can
|
||||||
|
* restore it properly on resume.
|
||||||
|
*/
|
||||||
|
pci_save_state(pdev);
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_PMAC
|
#ifdef CONFIG_PPC_PMAC
|
||||||
/* Set chip to "suspend" mode */
|
/* Set chip to "suspend" mode */
|
||||||
if (aty_power_mgmt(1, par)) {
|
if (machine_is(powermac) && aty_power_mgmt(1, par)) {
|
||||||
par->asleep = 0;
|
par->asleep = 0;
|
||||||
par->lock_blank = 0;
|
par->lock_blank = 0;
|
||||||
atyfb_blank(FB_BLANK_UNBLANK, info);
|
atyfb_blank(FB_BLANK_UNBLANK, info);
|
||||||
|
|
@ -2047,11 +2053,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
|
||||||
|
|
||||||
acquire_console_sem();
|
acquire_console_sem();
|
||||||
|
|
||||||
|
/* PCI state will have been restored by the core, so
|
||||||
|
* we should be in D0 now with our config space fully
|
||||||
|
* restored
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_PMAC
|
#ifdef CONFIG_PPC_PMAC
|
||||||
if (pdev->dev.power.power_state.event == 2)
|
if (machine_is(powermac) &&
|
||||||
|
pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)
|
||||||
aty_power_mgmt(0, par);
|
aty_power_mgmt(0, par);
|
||||||
#else
|
|
||||||
pci_set_power_state(pdev, PCI_D0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
aty_resume_chip(info);
|
aty_resume_chip(info);
|
||||||
|
|
@ -2254,7 +2264,7 @@ static int __devinit aty_init(struct fb_info *info)
|
||||||
if (!M64_HAS(INTEGRATED)) {
|
if (!M64_HAS(INTEGRATED)) {
|
||||||
u32 stat0;
|
u32 stat0;
|
||||||
u8 dac_type, dac_subtype, clk_type;
|
u8 dac_type, dac_subtype, clk_type;
|
||||||
stat0 = aty_ld_le32(CONFIG_STAT0, par);
|
stat0 = aty_ld_le32(CNFG_STAT0, par);
|
||||||
par->bus_type = (stat0 >> 0) & 0x07;
|
par->bus_type = (stat0 >> 0) & 0x07;
|
||||||
par->ram_type = (stat0 >> 3) & 0x07;
|
par->ram_type = (stat0 >> 3) & 0x07;
|
||||||
ramname = aty_gx_ram[par->ram_type];
|
ramname = aty_gx_ram[par->ram_type];
|
||||||
|
|
@ -2324,7 +2334,7 @@ static int __devinit aty_init(struct fb_info *info)
|
||||||
par->dac_ops = &aty_dac_ct;
|
par->dac_ops = &aty_dac_ct;
|
||||||
par->pll_ops = &aty_pll_ct;
|
par->pll_ops = &aty_pll_ct;
|
||||||
par->bus_type = PCI;
|
par->bus_type = PCI;
|
||||||
par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07);
|
par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07);
|
||||||
ramname = aty_ct_ram[par->ram_type];
|
ramname = aty_ct_ram[par->ram_type];
|
||||||
/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
|
/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
|
||||||
if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
|
if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
|
||||||
|
|
@ -2433,7 +2443,7 @@ static int __devinit aty_init(struct fb_info *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (M64_HAS(MAGIC_VRAM_SIZE)) {
|
if (M64_HAS(MAGIC_VRAM_SIZE)) {
|
||||||
if (aty_ld_le32(CONFIG_STAT1, par) & 0x40000000)
|
if (aty_ld_le32(CNFG_STAT1, par) & 0x40000000)
|
||||||
info->fix.smem_len += 0x400000;
|
info->fix.smem_len += 0x400000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2946,7 +2956,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
|
||||||
* Fix PROMs idea of MEM_CNTL settings...
|
* Fix PROMs idea of MEM_CNTL settings...
|
||||||
*/
|
*/
|
||||||
mem = aty_ld_le32(MEM_CNTL, par);
|
mem = aty_ld_le32(MEM_CNTL, par);
|
||||||
chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
|
chip_id = aty_ld_le32(CNFG_CHIP_ID, par);
|
||||||
if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
|
if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
|
||||||
switch (mem & 0x0f) {
|
switch (mem & 0x0f) {
|
||||||
case 3:
|
case 3:
|
||||||
|
|
@ -2964,7 +2974,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((aty_ld_le32(CONFIG_STAT0, par) & 7) >= SDRAM)
|
if ((aty_ld_le32(CNFG_STAT0, par) & 7) >= SDRAM)
|
||||||
mem &= ~(0x00700000);
|
mem &= ~(0x00700000);
|
||||||
}
|
}
|
||||||
mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */
|
mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */
|
||||||
|
|
@ -3572,7 +3582,7 @@ static int __init atyfb_atari_probe(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fake pci_id for correct_chipset() */
|
/* Fake pci_id for correct_chipset() */
|
||||||
switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) {
|
switch (aty_ld_le32(CNFG_CHIP_ID, par) & CFG_CHIP_TYPE) {
|
||||||
case 0x00d7:
|
case 0x00d7:
|
||||||
par->pci_id = PCI_CHIP_MACH64GX;
|
par->pci_id = PCI_CHIP_MACH64GX;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1936,8 +1936,8 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo)
|
||||||
OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B);
|
OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B);
|
||||||
mdelay(100);
|
mdelay(100);
|
||||||
|
|
||||||
aper_base = INREG(CONFIG_APER_0_BASE);
|
aper_base = INREG(CNFG_APER_0_BASE);
|
||||||
aper_size = INREG(CONFIG_APER_SIZE);
|
aper_size = INREG(CNFG_APER_SIZE);
|
||||||
|
|
||||||
#ifdef SET_MC_FB_FROM_APERTURE
|
#ifdef SET_MC_FB_FROM_APERTURE
|
||||||
/* Set framebuffer to be at the same address as set in PCI BAR */
|
/* Set framebuffer to be at the same address as set in PCI BAR */
|
||||||
|
|
@ -2024,11 +2024,11 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
|
||||||
~CRTC_H_CUTOFF_ACTIVE_EN);
|
~CRTC_H_CUTOFF_ACTIVE_EN);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tmp = INREG(CONFIG_MEMSIZE);
|
tmp = INREG(CNFG_MEMSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mem size is bits [28:0], mask off the rest */
|
/* mem size is bits [28:0], mask off the rest */
|
||||||
rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
|
rinfo->video_ram = tmp & CNFG_MEMSIZE_MASK;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hack to get around some busted production M6's
|
* Hack to get around some busted production M6's
|
||||||
|
|
@ -2228,7 +2228,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
|
||||||
*/
|
*/
|
||||||
rinfo->errata = 0;
|
rinfo->errata = 0;
|
||||||
if (rinfo->family == CHIP_FAMILY_R300 &&
|
if (rinfo->family == CHIP_FAMILY_R300 &&
|
||||||
(INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
|
(INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK)
|
||||||
== CFG_ATI_REV_A11)
|
== CFG_ATI_REV_A11)
|
||||||
rinfo->errata |= CHIP_ERRATA_R300_CG;
|
rinfo->errata |= CHIP_ERRATA_R300_CG;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
|
||||||
if (!rinfo->has_CRTC2) {
|
if (!rinfo->has_CRTC2) {
|
||||||
tmp = INPLL(pllSCLK_CNTL);
|
tmp = INPLL(pllSCLK_CNTL);
|
||||||
|
|
||||||
if ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13)
|
if ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13)
|
||||||
tmp &= ~(SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_RB);
|
tmp &= ~(SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_RB);
|
||||||
tmp &= ~(SCLK_CNTL__FORCE_HDP | SCLK_CNTL__FORCE_DISP1 |
|
tmp &= ~(SCLK_CNTL__FORCE_HDP | SCLK_CNTL__FORCE_DISP1 |
|
||||||
SCLK_CNTL__FORCE_TOP | SCLK_CNTL__FORCE_SE |
|
SCLK_CNTL__FORCE_TOP | SCLK_CNTL__FORCE_SE |
|
||||||
|
|
@ -468,9 +468,9 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
|
||||||
|
|
||||||
/*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
|
/*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
|
||||||
if ((rinfo->family == CHIP_FAMILY_RV250 &&
|
if ((rinfo->family == CHIP_FAMILY_RV250 &&
|
||||||
((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) ||
|
((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) ||
|
||||||
((rinfo->family == CHIP_FAMILY_RV100) &&
|
((rinfo->family == CHIP_FAMILY_RV100) &&
|
||||||
((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) {
|
((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) {
|
||||||
tmp |= SCLK_CNTL__FORCE_CP;
|
tmp |= SCLK_CNTL__FORCE_CP;
|
||||||
tmp |= SCLK_CNTL__FORCE_VIP;
|
tmp |= SCLK_CNTL__FORCE_VIP;
|
||||||
}
|
}
|
||||||
|
|
@ -486,7 +486,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
|
||||||
/* RV200::A11 A12 RV250::A11 A12 */
|
/* RV200::A11 A12 RV250::A11 A12 */
|
||||||
if (((rinfo->family == CHIP_FAMILY_RV200) ||
|
if (((rinfo->family == CHIP_FAMILY_RV200) ||
|
||||||
(rinfo->family == CHIP_FAMILY_RV250)) &&
|
(rinfo->family == CHIP_FAMILY_RV250)) &&
|
||||||
((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13))
|
((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13))
|
||||||
tmp |= SCLK_MORE_CNTL__FORCEON;
|
tmp |= SCLK_MORE_CNTL__FORCEON;
|
||||||
|
|
||||||
OUTPLL(pllSCLK_MORE_CNTL, tmp);
|
OUTPLL(pllSCLK_MORE_CNTL, tmp);
|
||||||
|
|
@ -497,7 +497,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
|
||||||
/* RV200::A11 A12, RV250::A11 A12 */
|
/* RV200::A11 A12, RV250::A11 A12 */
|
||||||
if (((rinfo->family == CHIP_FAMILY_RV200) ||
|
if (((rinfo->family == CHIP_FAMILY_RV200) ||
|
||||||
(rinfo->family == CHIP_FAMILY_RV250)) &&
|
(rinfo->family == CHIP_FAMILY_RV250)) &&
|
||||||
((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) {
|
((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) {
|
||||||
tmp = INPLL(pllPLL_PWRMGT_CNTL);
|
tmp = INPLL(pllPLL_PWRMGT_CNTL);
|
||||||
tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE;
|
tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE;
|
||||||
OUTPLL(pllPLL_PWRMGT_CNTL, tmp);
|
OUTPLL(pllPLL_PWRMGT_CNTL, tmp);
|
||||||
|
|
@ -702,7 +702,7 @@ static void radeon_pm_restore_regs(struct radeonfb_info *rinfo)
|
||||||
OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
|
OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
|
||||||
OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
|
OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
|
||||||
OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
|
OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
|
||||||
OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
|
OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
|
||||||
|
|
||||||
OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
|
OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
|
||||||
OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]);
|
OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]);
|
||||||
|
|
@ -1723,7 +1723,7 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo)
|
||||||
OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
|
OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
|
||||||
OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
|
OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
|
||||||
OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]);
|
OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]);
|
||||||
OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
|
OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
|
||||||
OUTREG(BUS_CNTL, rinfo->save_regs[36]);
|
OUTREG(BUS_CNTL, rinfo->save_regs[36]);
|
||||||
OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
|
OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
|
||||||
OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]);
|
OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]);
|
||||||
|
|
@ -1961,7 +1961,7 @@ static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo)
|
||||||
OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/);
|
OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/);
|
||||||
OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/);
|
OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/);
|
||||||
OUTREG(MC_IND_INDEX, 0);
|
OUTREG(MC_IND_INDEX, 0);
|
||||||
OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
|
OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
|
||||||
|
|
||||||
mdelay(20);
|
mdelay(20);
|
||||||
}
|
}
|
||||||
|
|
@ -2361,7 +2361,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
|
||||||
OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249);
|
OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249);
|
||||||
OUTREG(MC_IND_INDEX, 0);
|
OUTREG(MC_IND_INDEX, 0);
|
||||||
|
|
||||||
OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
|
OUTREG(CNFG_MEMSIZE, rinfo->video_ram);
|
||||||
|
|
||||||
radeon_pm_full_reset_sdram(rinfo);
|
radeon_pm_full_reset_sdram(rinfo);
|
||||||
|
|
||||||
|
|
@ -2509,9 +2509,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
|
||||||
|
|
||||||
static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
|
static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
|
||||||
{
|
{
|
||||||
u16 pwr_cmd;
|
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!rinfo->pm_reg)
|
if (!rinfo->pm_reg)
|
||||||
return;
|
return;
|
||||||
|
|
@ -2557,32 +2555,14 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 64; ++i)
|
|
||||||
pci_read_config_dword(rinfo->pdev, i * 4,
|
|
||||||
&rinfo->cfg_save[i]);
|
|
||||||
|
|
||||||
/* Switch PCI power management to D2. */
|
/* Switch PCI power management to D2. */
|
||||||
pci_disable_device(rinfo->pdev);
|
pci_disable_device(rinfo->pdev);
|
||||||
for (;;) {
|
pci_save_state(rinfo->pdev);
|
||||||
pci_read_config_word(
|
pci_set_power_state(rinfo->pdev, PCI_D2);
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
|
printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
|
||||||
pci_name(rinfo->pdev));
|
pci_name(rinfo->pdev));
|
||||||
|
|
||||||
/* Switch back PCI powermanagment to D0 */
|
|
||||||
mdelay(200);
|
|
||||||
pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0);
|
|
||||||
mdelay(500);
|
|
||||||
|
|
||||||
if (rinfo->family <= CHIP_FAMILY_RV250) {
|
if (rinfo->family <= CHIP_FAMILY_RV250) {
|
||||||
/* Reset the SDRAM controller */
|
/* Reset the SDRAM controller */
|
||||||
radeon_pm_full_reset_sdram(rinfo);
|
radeon_pm_full_reset_sdram(rinfo);
|
||||||
|
|
@ -2598,37 +2578,10 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
static u32 radeon_cfg_after_resume[64];
|
|
||||||
|
|
||||||
for (i = 0; i < 64; ++i)
|
|
||||||
pci_read_config_dword(rinfo->pdev, i * 4,
|
|
||||||
&radeon_cfg_after_resume[i]);
|
|
||||||
|
|
||||||
if (radeon_cfg_after_resume[PCI_BASE_ADDRESS_0/4]
|
|
||||||
== rinfo->cfg_save[PCI_BASE_ADDRESS_0/4])
|
|
||||||
return 0; /* assume everything is ok */
|
|
||||||
|
|
||||||
for (i = PCI_BASE_ADDRESS_0/4; i < 64; ++i) {
|
|
||||||
if (radeon_cfg_after_resume[i] != rinfo->cfg_save[i])
|
|
||||||
pci_write_config_dword(rinfo->pdev, i * 4,
|
|
||||||
rinfo->cfg_save[i]);
|
|
||||||
}
|
|
||||||
pci_write_config_word(rinfo->pdev, PCI_CACHE_LINE_SIZE,
|
|
||||||
rinfo->cfg_save[PCI_CACHE_LINE_SIZE/4]);
|
|
||||||
pci_write_config_word(rinfo->pdev, PCI_COMMAND,
|
|
||||||
rinfo->cfg_save[PCI_COMMAND/4]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
|
int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
|
||||||
{
|
{
|
||||||
struct fb_info *info = pci_get_drvdata(pdev);
|
struct fb_info *info = pci_get_drvdata(pdev);
|
||||||
struct radeonfb_info *rinfo = info->par;
|
struct radeonfb_info *rinfo = info->par;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (mesg.event == pdev->dev.power.power_state.event)
|
if (mesg.event == pdev->dev.power.power_state.event)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2674,6 +2627,11 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
|
||||||
pmac_suspend_agp_for_card(pdev);
|
pmac_suspend_agp_for_card(pdev);
|
||||||
#endif /* CONFIG_PPC_PMAC */
|
#endif /* CONFIG_PPC_PMAC */
|
||||||
|
|
||||||
|
/* It's unclear whether or when the generic code will do that, so let's
|
||||||
|
* do it ourselves. We save state before we do any power management
|
||||||
|
*/
|
||||||
|
pci_save_state(pdev);
|
||||||
|
|
||||||
/* If we support wakeup from poweroff, we save all regs we can including cfg
|
/* If we support wakeup from poweroff, we save all regs we can including cfg
|
||||||
* space
|
* space
|
||||||
*/
|
*/
|
||||||
|
|
@ -2698,9 +2656,6 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
|
||||||
mdelay(20);
|
mdelay(20);
|
||||||
OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON));
|
OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON));
|
||||||
}
|
}
|
||||||
// FIXME: Use PCI layer
|
|
||||||
for (i = 0; i < 64; ++i)
|
|
||||||
pci_read_config_dword(pdev, i * 4, &rinfo->cfg_save[i]);
|
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
}
|
}
|
||||||
/* If we support D2, we go to it (should be fixed later with a flag forcing
|
/* If we support D2, we go to it (should be fixed later with a flag forcing
|
||||||
|
|
@ -2717,6 +2672,13 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int radeon_check_power_loss(struct radeonfb_info *rinfo)
|
||||||
|
{
|
||||||
|
return rinfo->save_regs[4] != INPLL(CLK_PIN_CNTL) ||
|
||||||
|
rinfo->save_regs[2] != INPLL(MCLK_CNTL) ||
|
||||||
|
rinfo->save_regs[3] != INPLL(SCLK_CNTL);
|
||||||
|
}
|
||||||
|
|
||||||
int radeonfb_pci_resume(struct pci_dev *pdev)
|
int radeonfb_pci_resume(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
struct fb_info *info = pci_get_drvdata(pdev);
|
struct fb_info *info = pci_get_drvdata(pdev);
|
||||||
|
|
@ -2735,20 +2697,13 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
|
||||||
printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n",
|
printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n",
|
||||||
pci_name(pdev), pdev->dev.power.power_state.event);
|
pci_name(pdev), pdev->dev.power.power_state.event);
|
||||||
|
|
||||||
|
/* PCI state will have been restored by the core, so
|
||||||
if (pci_enable_device(pdev)) {
|
* we should be in D0 now with our config space fully
|
||||||
rc = -ENODEV;
|
* restored
|
||||||
printk(KERN_ERR "radeonfb (%s): can't enable PCI device !\n",
|
|
||||||
pci_name(pdev));
|
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
pci_set_master(pdev);
|
|
||||||
|
|
||||||
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)) {
|
if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
|
||||||
|
/* Wakeup chip */
|
||||||
|
if ((rinfo->pm_mode & radeon_pm_off) && radeon_check_power_loss(rinfo)) {
|
||||||
if (rinfo->reinit_func != NULL)
|
if (rinfo->reinit_func != NULL)
|
||||||
rinfo->reinit_func(rinfo);
|
rinfo->reinit_func(rinfo);
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -361,8 +361,6 @@ struct radeonfb_info {
|
||||||
#ifdef CONFIG_FB_RADEON_I2C
|
#ifdef CONFIG_FB_RADEON_I2C
|
||||||
struct radeon_i2c_chan i2c[4];
|
struct radeon_i2c_chan i2c[4];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
u32 cfg_save[64];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
|
||||||
obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
|
obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
|
||||||
obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
|
obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
|
||||||
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
|
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
|
||||||
obj-$(CONFIG_BACKLIGHT_DA903X) += da903x.o
|
obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
|
||||||
obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
|
obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
|
||||||
obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
|
obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
|
||||||
obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
|
obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
|
||||||
|
|
|
||||||
|
|
@ -250,10 +250,6 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
|
||||||
int rc, size = cmap->len * sizeof(u16);
|
int rc, size = cmap->len * sizeof(u16);
|
||||||
struct fb_cmap umap;
|
struct fb_cmap umap;
|
||||||
|
|
||||||
if (cmap->start < 0 || (!info->fbops->fb_setcolreg &&
|
|
||||||
!info->fbops->fb_setcmap))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
memset(&umap, 0, sizeof(struct fb_cmap));
|
memset(&umap, 0, sizeof(struct fb_cmap));
|
||||||
rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL);
|
rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
|
@ -262,11 +258,23 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
|
||||||
copy_from_user(umap.green, cmap->green, size) ||
|
copy_from_user(umap.green, cmap->green, size) ||
|
||||||
copy_from_user(umap.blue, cmap->blue, size) ||
|
copy_from_user(umap.blue, cmap->blue, size) ||
|
||||||
(cmap->transp && copy_from_user(umap.transp, cmap->transp, size))) {
|
(cmap->transp && copy_from_user(umap.transp, cmap->transp, size))) {
|
||||||
fb_dealloc_cmap(&umap);
|
rc = -EFAULT;
|
||||||
return -EFAULT;
|
goto out;
|
||||||
}
|
}
|
||||||
umap.start = cmap->start;
|
umap.start = cmap->start;
|
||||||
|
if (!lock_fb_info(info)) {
|
||||||
|
rc = -ENODEV;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (cmap->start < 0 || (!info->fbops->fb_setcolreg &&
|
||||||
|
!info->fbops->fb_setcmap)) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out1;
|
||||||
|
}
|
||||||
rc = fb_set_cmap(&umap, info);
|
rc = fb_set_cmap(&umap, info);
|
||||||
|
out1:
|
||||||
|
unlock_fb_info(info);
|
||||||
|
out:
|
||||||
fb_dealloc_cmap(&umap);
|
fb_dealloc_cmap(&umap);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1013,132 +1013,139 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
|
||||||
struct fb_var_screeninfo var;
|
struct fb_var_screeninfo var;
|
||||||
struct fb_fix_screeninfo fix;
|
struct fb_fix_screeninfo fix;
|
||||||
struct fb_con2fbmap con2fb;
|
struct fb_con2fbmap con2fb;
|
||||||
|
struct fb_cmap cmap_from;
|
||||||
struct fb_cmap_user cmap;
|
struct fb_cmap_user cmap;
|
||||||
struct fb_event event;
|
struct fb_event event;
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
long ret = 0;
|
long ret = 0;
|
||||||
|
|
||||||
fb = info->fbops;
|
|
||||||
if (!fb)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case FBIOGET_VSCREENINFO:
|
case FBIOGET_VSCREENINFO:
|
||||||
ret = copy_to_user(argp, &info->var,
|
if (!lock_fb_info(info))
|
||||||
sizeof(var)) ? -EFAULT : 0;
|
return -ENODEV;
|
||||||
|
var = info->var;
|
||||||
|
unlock_fb_info(info);
|
||||||
|
|
||||||
|
ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0;
|
||||||
break;
|
break;
|
||||||
case FBIOPUT_VSCREENINFO:
|
case FBIOPUT_VSCREENINFO:
|
||||||
if (copy_from_user(&var, argp, sizeof(var))) {
|
if (copy_from_user(&var, argp, sizeof(var)))
|
||||||
ret = -EFAULT;
|
return -EFAULT;
|
||||||
break;
|
if (!lock_fb_info(info))
|
||||||
}
|
return -ENODEV;
|
||||||
acquire_console_sem();
|
acquire_console_sem();
|
||||||
info->flags |= FBINFO_MISC_USEREVENT;
|
info->flags |= FBINFO_MISC_USEREVENT;
|
||||||
ret = fb_set_var(info, &var);
|
ret = fb_set_var(info, &var);
|
||||||
info->flags &= ~FBINFO_MISC_USEREVENT;
|
info->flags &= ~FBINFO_MISC_USEREVENT;
|
||||||
release_console_sem();
|
release_console_sem();
|
||||||
if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
|
unlock_fb_info(info);
|
||||||
|
if (!ret && copy_to_user(argp, &var, sizeof(var)))
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
break;
|
break;
|
||||||
case FBIOGET_FSCREENINFO:
|
case FBIOGET_FSCREENINFO:
|
||||||
ret = copy_to_user(argp, &info->fix,
|
if (!lock_fb_info(info))
|
||||||
sizeof(fix)) ? -EFAULT : 0;
|
return -ENODEV;
|
||||||
|
fix = info->fix;
|
||||||
|
unlock_fb_info(info);
|
||||||
|
|
||||||
|
ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
|
||||||
break;
|
break;
|
||||||
case FBIOPUTCMAP:
|
case FBIOPUTCMAP:
|
||||||
if (copy_from_user(&cmap, argp, sizeof(cmap)))
|
if (copy_from_user(&cmap, argp, sizeof(cmap)))
|
||||||
ret = -EFAULT;
|
return -EFAULT;
|
||||||
else
|
|
||||||
ret = fb_set_user_cmap(&cmap, info);
|
ret = fb_set_user_cmap(&cmap, info);
|
||||||
break;
|
break;
|
||||||
case FBIOGETCMAP:
|
case FBIOGETCMAP:
|
||||||
if (copy_from_user(&cmap, argp, sizeof(cmap)))
|
if (copy_from_user(&cmap, argp, sizeof(cmap)))
|
||||||
ret = -EFAULT;
|
return -EFAULT;
|
||||||
else
|
if (!lock_fb_info(info))
|
||||||
ret = fb_cmap_to_user(&info->cmap, &cmap);
|
return -ENODEV;
|
||||||
|
cmap_from = info->cmap;
|
||||||
|
unlock_fb_info(info);
|
||||||
|
ret = fb_cmap_to_user(&cmap_from, &cmap);
|
||||||
break;
|
break;
|
||||||
case FBIOPAN_DISPLAY:
|
case FBIOPAN_DISPLAY:
|
||||||
if (copy_from_user(&var, argp, sizeof(var))) {
|
if (copy_from_user(&var, argp, sizeof(var)))
|
||||||
ret = -EFAULT;
|
return -EFAULT;
|
||||||
break;
|
if (!lock_fb_info(info))
|
||||||
}
|
return -ENODEV;
|
||||||
acquire_console_sem();
|
acquire_console_sem();
|
||||||
ret = fb_pan_display(info, &var);
|
ret = fb_pan_display(info, &var);
|
||||||
release_console_sem();
|
release_console_sem();
|
||||||
|
unlock_fb_info(info);
|
||||||
if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
|
if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
|
||||||
ret = -EFAULT;
|
return -EFAULT;
|
||||||
break;
|
break;
|
||||||
case FBIO_CURSOR:
|
case FBIO_CURSOR:
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
case FBIOGET_CON2FBMAP:
|
case FBIOGET_CON2FBMAP:
|
||||||
if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
|
if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
|
||||||
ret = -EFAULT;
|
return -EFAULT;
|
||||||
else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
|
if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
else {
|
|
||||||
con2fb.framebuffer = -1;
|
con2fb.framebuffer = -1;
|
||||||
event.info = info;
|
|
||||||
event.data = &con2fb;
|
event.data = &con2fb;
|
||||||
fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP,
|
|
||||||
&event);
|
if (!lock_fb_info(info))
|
||||||
ret = copy_to_user(argp, &con2fb,
|
return -ENODEV;
|
||||||
sizeof(con2fb)) ? -EFAULT : 0;
|
event.info = info;
|
||||||
}
|
fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
|
||||||
|
unlock_fb_info(info);
|
||||||
|
|
||||||
|
ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
|
||||||
break;
|
break;
|
||||||
case FBIOPUT_CON2FBMAP:
|
case FBIOPUT_CON2FBMAP:
|
||||||
if (copy_from_user(&con2fb, argp, sizeof(con2fb))) {
|
if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
|
||||||
ret = -EFAULT;
|
return -EFAULT;
|
||||||
break;
|
if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
|
||||||
}
|
return -EINVAL;
|
||||||
if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) {
|
if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) {
|
|
||||||
ret = -EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!registered_fb[con2fb.framebuffer])
|
if (!registered_fb[con2fb.framebuffer])
|
||||||
request_module("fb%d", con2fb.framebuffer);
|
request_module("fb%d", con2fb.framebuffer);
|
||||||
if (!registered_fb[con2fb.framebuffer]) {
|
if (!registered_fb[con2fb.framebuffer]) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
event.info = info;
|
|
||||||
event.data = &con2fb;
|
event.data = &con2fb;
|
||||||
|
if (!lock_fb_info(info))
|
||||||
|
return -ENODEV;
|
||||||
|
event.info = info;
|
||||||
ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,
|
ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,
|
||||||
&event);
|
&event);
|
||||||
|
unlock_fb_info(info);
|
||||||
break;
|
break;
|
||||||
case FBIOBLANK:
|
case FBIOBLANK:
|
||||||
|
if (!lock_fb_info(info))
|
||||||
|
return -ENODEV;
|
||||||
acquire_console_sem();
|
acquire_console_sem();
|
||||||
info->flags |= FBINFO_MISC_USEREVENT;
|
info->flags |= FBINFO_MISC_USEREVENT;
|
||||||
ret = fb_blank(info, arg);
|
ret = fb_blank(info, arg);
|
||||||
info->flags &= ~FBINFO_MISC_USEREVENT;
|
info->flags &= ~FBINFO_MISC_USEREVENT;
|
||||||
release_console_sem();
|
release_console_sem();
|
||||||
break;;
|
unlock_fb_info(info);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (fb->fb_ioctl == NULL)
|
if (!lock_fb_info(info))
|
||||||
ret = -ENOTTY;
|
return -ENODEV;
|
||||||
else
|
fb = info->fbops;
|
||||||
|
if (fb->fb_ioctl)
|
||||||
ret = fb->fb_ioctl(info, cmd, arg);
|
ret = fb->fb_ioctl(info, cmd, arg);
|
||||||
|
else
|
||||||
|
ret = -ENOTTY;
|
||||||
|
unlock_fb_info(info);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
__acquires(&info->lock)
|
|
||||||
__releases(&info->lock)
|
|
||||||
{
|
{
|
||||||
struct inode *inode = file->f_path.dentry->d_inode;
|
struct inode *inode = file->f_path.dentry->d_inode;
|
||||||
int fbidx = iminor(inode);
|
int fbidx = iminor(inode);
|
||||||
struct fb_info *info;
|
struct fb_info *info = registered_fb[fbidx];
|
||||||
long ret;
|
|
||||||
|
|
||||||
info = registered_fb[fbidx];
|
return do_fb_ioctl(info, cmd, arg);
|
||||||
mutex_lock(&info->lock);
|
|
||||||
ret = do_fb_ioctl(info, cmd, arg);
|
|
||||||
mutex_unlock(&info->lock);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
|
|
@ -1257,8 +1264,6 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
|
||||||
|
|
||||||
static long fb_compat_ioctl(struct file *file, unsigned int cmd,
|
static long fb_compat_ioctl(struct file *file, unsigned int cmd,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
__acquires(&info->lock)
|
|
||||||
__releases(&info->lock)
|
|
||||||
{
|
{
|
||||||
struct inode *inode = file->f_path.dentry->d_inode;
|
struct inode *inode = file->f_path.dentry->d_inode;
|
||||||
int fbidx = iminor(inode);
|
int fbidx = iminor(inode);
|
||||||
|
|
@ -1266,7 +1271,6 @@ __releases(&info->lock)
|
||||||
struct fb_ops *fb = info->fbops;
|
struct fb_ops *fb = info->fbops;
|
||||||
long ret = -ENOIOCTLCMD;
|
long ret = -ENOIOCTLCMD;
|
||||||
|
|
||||||
mutex_lock(&info->lock);
|
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
case FBIOGET_VSCREENINFO:
|
case FBIOGET_VSCREENINFO:
|
||||||
case FBIOPUT_VSCREENINFO:
|
case FBIOPUT_VSCREENINFO:
|
||||||
|
|
@ -1292,7 +1296,6 @@ __releases(&info->lock)
|
||||||
ret = fb->fb_compat_ioctl(info, cmd, arg);
|
ret = fb->fb_compat_ioctl(info, cmd, arg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mutex_unlock(&info->lock);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1208,9 +1208,11 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
|
||||||
* check for an ELF header. If we find one, dump the first page to
|
* check for an ELF header. If we find one, dump the first page to
|
||||||
* aid in determining what was mapped here.
|
* aid in determining what was mapped here.
|
||||||
*/
|
*/
|
||||||
if (FILTER(ELF_HEADERS) && vma->vm_file != NULL && vma->vm_pgoff == 0) {
|
if (FILTER(ELF_HEADERS) &&
|
||||||
|
vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) {
|
||||||
u32 __user *header = (u32 __user *) vma->vm_start;
|
u32 __user *header = (u32 __user *) vma->vm_start;
|
||||||
u32 word;
|
u32 word;
|
||||||
|
mm_segment_t fs = get_fs();
|
||||||
/*
|
/*
|
||||||
* Doing it this way gets the constant folded by GCC.
|
* Doing it this way gets the constant folded by GCC.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1223,7 +1225,15 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
|
||||||
magic.elfmag[EI_MAG1] = ELFMAG1;
|
magic.elfmag[EI_MAG1] = ELFMAG1;
|
||||||
magic.elfmag[EI_MAG2] = ELFMAG2;
|
magic.elfmag[EI_MAG2] = ELFMAG2;
|
||||||
magic.elfmag[EI_MAG3] = ELFMAG3;
|
magic.elfmag[EI_MAG3] = ELFMAG3;
|
||||||
if (get_user(word, header) == 0 && word == magic.cmp)
|
/*
|
||||||
|
* Switch to the user "segment" for get_user(),
|
||||||
|
* then put back what elf_core_dump() had in place.
|
||||||
|
*/
|
||||||
|
set_fs(USER_DS);
|
||||||
|
if (unlikely(get_user(word, header)))
|
||||||
|
word = 0;
|
||||||
|
set_fs(fs);
|
||||||
|
if (word == magic.cmp)
|
||||||
return PAGE_SIZE;
|
return PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,3 +16,16 @@ config BTRFS_FS
|
||||||
module will be called btrfs.
|
module will be called btrfs.
|
||||||
|
|
||||||
If unsure, say N.
|
If unsure, say N.
|
||||||
|
|
||||||
|
config BTRFS_FS_POSIX_ACL
|
||||||
|
bool "Btrfs POSIX Access Control Lists"
|
||||||
|
depends on BTRFS_FS
|
||||||
|
select FS_POSIX_ACL
|
||||||
|
help
|
||||||
|
POSIX Access Control Lists (ACLs) support permissions for users and
|
||||||
|
groups beyond the owner/group/world scheme.
|
||||||
|
|
||||||
|
To learn more about Access Control Lists, visit the POSIX ACLs for
|
||||||
|
Linux website <http://acl.bestbits.at/>.
|
||||||
|
|
||||||
|
If you don't know what Access Control Lists are, say N
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@
|
||||||
* Boston, MA 021110-1307, USA.
|
* Boston, MA 021110-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/version.h>
|
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
# include <linux/freezer.h>
|
#include <linux/freezer.h>
|
||||||
|
#include <linux/ftrace.h>
|
||||||
#include "async-thread.h"
|
#include "async-thread.h"
|
||||||
|
|
||||||
#define WORK_QUEUED_BIT 0
|
#define WORK_QUEUED_BIT 0
|
||||||
|
|
@ -143,6 +143,7 @@ static int worker_loop(void *arg)
|
||||||
struct btrfs_work *work;
|
struct btrfs_work *work;
|
||||||
do {
|
do {
|
||||||
spin_lock_irq(&worker->lock);
|
spin_lock_irq(&worker->lock);
|
||||||
|
again_locked:
|
||||||
while (!list_empty(&worker->pending)) {
|
while (!list_empty(&worker->pending)) {
|
||||||
cur = worker->pending.next;
|
cur = worker->pending.next;
|
||||||
work = list_entry(cur, struct btrfs_work, list);
|
work = list_entry(cur, struct btrfs_work, list);
|
||||||
|
|
@ -165,14 +166,50 @@ static int worker_loop(void *arg)
|
||||||
check_idle_worker(worker);
|
check_idle_worker(worker);
|
||||||
|
|
||||||
}
|
}
|
||||||
worker->working = 0;
|
|
||||||
if (freezing(current)) {
|
if (freezing(current)) {
|
||||||
|
worker->working = 0;
|
||||||
|
spin_unlock_irq(&worker->lock);
|
||||||
refrigerator();
|
refrigerator();
|
||||||
} else {
|
} else {
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
|
||||||
spin_unlock_irq(&worker->lock);
|
spin_unlock_irq(&worker->lock);
|
||||||
if (!kthread_should_stop())
|
if (!kthread_should_stop()) {
|
||||||
|
cpu_relax();
|
||||||
|
/*
|
||||||
|
* we've dropped the lock, did someone else
|
||||||
|
* jump_in?
|
||||||
|
*/
|
||||||
|
smp_mb();
|
||||||
|
if (!list_empty(&worker->pending))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this short schedule allows more work to
|
||||||
|
* come in without the queue functions
|
||||||
|
* needing to go through wake_up_process()
|
||||||
|
*
|
||||||
|
* worker->working is still 1, so nobody
|
||||||
|
* is going to try and wake us up
|
||||||
|
*/
|
||||||
|
schedule_timeout(1);
|
||||||
|
smp_mb();
|
||||||
|
if (!list_empty(&worker->pending))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* still no more work?, sleep for real */
|
||||||
|
spin_lock_irq(&worker->lock);
|
||||||
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
if (!list_empty(&worker->pending))
|
||||||
|
goto again_locked;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this makes sure we get a wakeup when someone
|
||||||
|
* adds something new to the queue
|
||||||
|
*/
|
||||||
|
worker->working = 0;
|
||||||
|
spin_unlock_irq(&worker->lock);
|
||||||
|
|
||||||
schedule();
|
schedule();
|
||||||
|
}
|
||||||
__set_current_state(TASK_RUNNING);
|
__set_current_state(TASK_RUNNING);
|
||||||
}
|
}
|
||||||
} while (!kthread_should_stop());
|
} while (!kthread_should_stop());
|
||||||
|
|
@ -350,13 +387,14 @@ int btrfs_requeue_work(struct btrfs_work *work)
|
||||||
{
|
{
|
||||||
struct btrfs_worker_thread *worker = work->worker;
|
struct btrfs_worker_thread *worker = work->worker;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int wake = 0;
|
||||||
|
|
||||||
if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags))
|
if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
spin_lock_irqsave(&worker->lock, flags);
|
spin_lock_irqsave(&worker->lock, flags);
|
||||||
atomic_inc(&worker->num_pending);
|
|
||||||
list_add_tail(&work->list, &worker->pending);
|
list_add_tail(&work->list, &worker->pending);
|
||||||
|
atomic_inc(&worker->num_pending);
|
||||||
|
|
||||||
/* by definition we're busy, take ourselves off the idle
|
/* by definition we're busy, take ourselves off the idle
|
||||||
* list
|
* list
|
||||||
|
|
@ -368,10 +406,16 @@ int btrfs_requeue_work(struct btrfs_work *work)
|
||||||
&worker->workers->worker_list);
|
&worker->workers->worker_list);
|
||||||
spin_unlock_irqrestore(&worker->workers->lock, flags);
|
spin_unlock_irqrestore(&worker->workers->lock, flags);
|
||||||
}
|
}
|
||||||
|
if (!worker->working) {
|
||||||
|
wake = 1;
|
||||||
|
worker->working = 1;
|
||||||
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&worker->lock, flags);
|
spin_unlock_irqrestore(&worker->lock, flags);
|
||||||
|
if (wake)
|
||||||
|
wake_up_process(worker->task);
|
||||||
out:
|
out:
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -398,9 +442,10 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&worker->lock, flags);
|
spin_lock_irqsave(&worker->lock, flags);
|
||||||
|
|
||||||
|
list_add_tail(&work->list, &worker->pending);
|
||||||
atomic_inc(&worker->num_pending);
|
atomic_inc(&worker->num_pending);
|
||||||
check_busy_worker(worker);
|
check_busy_worker(worker);
|
||||||
list_add_tail(&work->list, &worker->pending);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* avoid calling into wake_up_process if this thread has already
|
* avoid calling into wake_up_process if this thread has already
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@
|
||||||
#include <linux/swap.h>
|
#include <linux/swap.h>
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
#include <linux/bit_spinlock.h>
|
#include <linux/bit_spinlock.h>
|
||||||
#include <linux/version.h>
|
|
||||||
#include <linux/pagevec.h>
|
#include <linux/pagevec.h>
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "ctree.h"
|
#include "ctree.h"
|
||||||
|
|
|
||||||
278
fs/btrfs/ctree.c
278
fs/btrfs/ctree.c
|
|
@ -54,6 +54,31 @@ struct btrfs_path *btrfs_alloc_path(void)
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set all locked nodes in the path to blocking locks. This should
|
||||||
|
* be done before scheduling
|
||||||
|
*/
|
||||||
|
noinline void btrfs_set_path_blocking(struct btrfs_path *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
|
||||||
|
if (p->nodes[i] && p->locks[i])
|
||||||
|
btrfs_set_lock_blocking(p->nodes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* reset all the locked nodes in the patch to spinning locks.
|
||||||
|
*/
|
||||||
|
noinline void btrfs_clear_path_blocking(struct btrfs_path *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
|
||||||
|
if (p->nodes[i] && p->locks[i])
|
||||||
|
btrfs_clear_lock_blocking(p->nodes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* this also releases the path */
|
/* this also releases the path */
|
||||||
void btrfs_free_path(struct btrfs_path *p)
|
void btrfs_free_path(struct btrfs_path *p)
|
||||||
{
|
{
|
||||||
|
|
@ -272,6 +297,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
|
||||||
if (IS_ERR(cow))
|
if (IS_ERR(cow))
|
||||||
return PTR_ERR(cow);
|
return PTR_ERR(cow);
|
||||||
|
|
||||||
|
/* cow is set to blocking by btrfs_init_new_buffer */
|
||||||
|
|
||||||
copy_extent_buffer(cow, buf, 0, 0, cow->len);
|
copy_extent_buffer(cow, buf, 0, 0, cow->len);
|
||||||
btrfs_set_header_bytenr(cow, cow->start);
|
btrfs_set_header_bytenr(cow, cow->start);
|
||||||
btrfs_set_header_generation(cow, trans->transid);
|
btrfs_set_header_generation(cow, trans->transid);
|
||||||
|
|
@ -388,17 +415,20 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&root->fs_info->hash_lock);
|
|
||||||
if (btrfs_header_generation(buf) == trans->transid &&
|
if (btrfs_header_generation(buf) == trans->transid &&
|
||||||
btrfs_header_owner(buf) == root->root_key.objectid &&
|
btrfs_header_owner(buf) == root->root_key.objectid &&
|
||||||
!btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) {
|
!btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) {
|
||||||
*cow_ret = buf;
|
*cow_ret = buf;
|
||||||
spin_unlock(&root->fs_info->hash_lock);
|
|
||||||
WARN_ON(prealloc_dest);
|
WARN_ON(prealloc_dest);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
spin_unlock(&root->fs_info->hash_lock);
|
|
||||||
search_start = buf->start & ~((u64)(1024 * 1024 * 1024) - 1);
|
search_start = buf->start & ~((u64)(1024 * 1024 * 1024) - 1);
|
||||||
|
|
||||||
|
if (parent)
|
||||||
|
btrfs_set_lock_blocking(parent);
|
||||||
|
btrfs_set_lock_blocking(buf);
|
||||||
|
|
||||||
ret = __btrfs_cow_block(trans, root, buf, parent,
|
ret = __btrfs_cow_block(trans, root, buf, parent,
|
||||||
parent_slot, cow_ret, search_start, 0,
|
parent_slot, cow_ret, search_start, 0,
|
||||||
prealloc_dest);
|
prealloc_dest);
|
||||||
|
|
@ -504,6 +534,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
|
||||||
if (parent_nritems == 1)
|
if (parent_nritems == 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
btrfs_set_lock_blocking(parent);
|
||||||
|
|
||||||
for (i = start_slot; i < end_slot; i++) {
|
for (i = start_slot; i < end_slot; i++) {
|
||||||
int close = 1;
|
int close = 1;
|
||||||
|
|
||||||
|
|
@ -564,6 +596,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
|
||||||
search_start = last_block;
|
search_start = last_block;
|
||||||
|
|
||||||
btrfs_tree_lock(cur);
|
btrfs_tree_lock(cur);
|
||||||
|
btrfs_set_lock_blocking(cur);
|
||||||
err = __btrfs_cow_block(trans, root, cur, parent, i,
|
err = __btrfs_cow_block(trans, root, cur, parent, i,
|
||||||
&cur, search_start,
|
&cur, search_start,
|
||||||
min(16 * blocksize,
|
min(16 * blocksize,
|
||||||
|
|
@ -862,6 +895,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mid = path->nodes[level];
|
mid = path->nodes[level];
|
||||||
|
|
||||||
WARN_ON(!path->locks[level]);
|
WARN_ON(!path->locks[level]);
|
||||||
WARN_ON(btrfs_header_generation(mid) != trans->transid);
|
WARN_ON(btrfs_header_generation(mid) != trans->transid);
|
||||||
|
|
||||||
|
|
@ -884,6 +918,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
|
||||||
/* promote the child to a root */
|
/* promote the child to a root */
|
||||||
child = read_node_slot(root, mid, 0);
|
child = read_node_slot(root, mid, 0);
|
||||||
btrfs_tree_lock(child);
|
btrfs_tree_lock(child);
|
||||||
|
btrfs_set_lock_blocking(child);
|
||||||
BUG_ON(!child);
|
BUG_ON(!child);
|
||||||
ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0);
|
ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
@ -900,6 +935,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
|
||||||
|
|
||||||
add_root_to_dirty_list(root);
|
add_root_to_dirty_list(root);
|
||||||
btrfs_tree_unlock(child);
|
btrfs_tree_unlock(child);
|
||||||
|
|
||||||
path->locks[level] = 0;
|
path->locks[level] = 0;
|
||||||
path->nodes[level] = NULL;
|
path->nodes[level] = NULL;
|
||||||
clean_tree_block(trans, root, mid);
|
clean_tree_block(trans, root, mid);
|
||||||
|
|
@ -924,6 +960,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
|
||||||
left = read_node_slot(root, parent, pslot - 1);
|
left = read_node_slot(root, parent, pslot - 1);
|
||||||
if (left) {
|
if (left) {
|
||||||
btrfs_tree_lock(left);
|
btrfs_tree_lock(left);
|
||||||
|
btrfs_set_lock_blocking(left);
|
||||||
wret = btrfs_cow_block(trans, root, left,
|
wret = btrfs_cow_block(trans, root, left,
|
||||||
parent, pslot - 1, &left, 0);
|
parent, pslot - 1, &left, 0);
|
||||||
if (wret) {
|
if (wret) {
|
||||||
|
|
@ -934,6 +971,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
|
||||||
right = read_node_slot(root, parent, pslot + 1);
|
right = read_node_slot(root, parent, pslot + 1);
|
||||||
if (right) {
|
if (right) {
|
||||||
btrfs_tree_lock(right);
|
btrfs_tree_lock(right);
|
||||||
|
btrfs_set_lock_blocking(right);
|
||||||
wret = btrfs_cow_block(trans, root, right,
|
wret = btrfs_cow_block(trans, root, right,
|
||||||
parent, pslot + 1, &right, 0);
|
parent, pslot + 1, &right, 0);
|
||||||
if (wret) {
|
if (wret) {
|
||||||
|
|
@ -1109,6 +1147,8 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
|
||||||
u32 left_nr;
|
u32 left_nr;
|
||||||
|
|
||||||
btrfs_tree_lock(left);
|
btrfs_tree_lock(left);
|
||||||
|
btrfs_set_lock_blocking(left);
|
||||||
|
|
||||||
left_nr = btrfs_header_nritems(left);
|
left_nr = btrfs_header_nritems(left);
|
||||||
if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
|
if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
|
||||||
wret = 1;
|
wret = 1;
|
||||||
|
|
@ -1155,7 +1195,10 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
|
||||||
*/
|
*/
|
||||||
if (right) {
|
if (right) {
|
||||||
u32 right_nr;
|
u32 right_nr;
|
||||||
|
|
||||||
btrfs_tree_lock(right);
|
btrfs_tree_lock(right);
|
||||||
|
btrfs_set_lock_blocking(right);
|
||||||
|
|
||||||
right_nr = btrfs_header_nritems(right);
|
right_nr = btrfs_header_nritems(right);
|
||||||
if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
|
if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
|
||||||
wret = 1;
|
wret = 1;
|
||||||
|
|
@ -1210,8 +1253,7 @@ static noinline void reada_for_search(struct btrfs_root *root,
|
||||||
struct btrfs_disk_key disk_key;
|
struct btrfs_disk_key disk_key;
|
||||||
u32 nritems;
|
u32 nritems;
|
||||||
u64 search;
|
u64 search;
|
||||||
u64 lowest_read;
|
u64 target;
|
||||||
u64 highest_read;
|
|
||||||
u64 nread = 0;
|
u64 nread = 0;
|
||||||
int direction = path->reada;
|
int direction = path->reada;
|
||||||
struct extent_buffer *eb;
|
struct extent_buffer *eb;
|
||||||
|
|
@ -1235,8 +1277,7 @@ static noinline void reada_for_search(struct btrfs_root *root,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
highest_read = search;
|
target = search;
|
||||||
lowest_read = search;
|
|
||||||
|
|
||||||
nritems = btrfs_header_nritems(node);
|
nritems = btrfs_header_nritems(node);
|
||||||
nr = slot;
|
nr = slot;
|
||||||
|
|
@ -1256,27 +1297,80 @@ static noinline void reada_for_search(struct btrfs_root *root,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
search = btrfs_node_blockptr(node, nr);
|
search = btrfs_node_blockptr(node, nr);
|
||||||
if ((search >= lowest_read && search <= highest_read) ||
|
if ((search <= target && target - search <= 65536) ||
|
||||||
(search < lowest_read && lowest_read - search <= 16384) ||
|
(search > target && search - target <= 65536)) {
|
||||||
(search > highest_read && search - highest_read <= 16384)) {
|
|
||||||
readahead_tree_block(root, search, blocksize,
|
readahead_tree_block(root, search, blocksize,
|
||||||
btrfs_node_ptr_generation(node, nr));
|
btrfs_node_ptr_generation(node, nr));
|
||||||
nread += blocksize;
|
nread += blocksize;
|
||||||
}
|
}
|
||||||
nscan++;
|
nscan++;
|
||||||
if (path->reada < 2 && (nread > (64 * 1024) || nscan > 32))
|
if ((nread > 65536 || nscan > 32))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (nread > (256 * 1024) || nscan > 128)
|
|
||||||
break;
|
|
||||||
|
|
||||||
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
|
* when we walk down the tree, it is usually safe to unlock the higher layers
|
||||||
* in the tree. The exceptions are when our path goes through slot 0, because
|
* in the tree. The exceptions are when our path goes through slot 0, because
|
||||||
|
|
@ -1327,6 +1421,32 @@ static noinline void unlock_up(struct btrfs_path *path, int level,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This releases any locks held in the path starting at level and
|
||||||
|
* going all the way up to the root.
|
||||||
|
*
|
||||||
|
* btrfs_search_slot will keep the lock held on higher nodes in a few
|
||||||
|
* corner cases, such as COW of the block at slot zero in the node. This
|
||||||
|
* ignores those rules, and it should only be called when there are no
|
||||||
|
* more updates to be done higher up in the tree.
|
||||||
|
*/
|
||||||
|
noinline void btrfs_unlock_up_safe(struct btrfs_path *path, int level)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (path->keep_locks || path->lowest_level)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = level; i < BTRFS_MAX_LEVEL; i++) {
|
||||||
|
if (!path->nodes[i])
|
||||||
|
continue;
|
||||||
|
if (!path->locks[i])
|
||||||
|
continue;
|
||||||
|
btrfs_tree_unlock(path->nodes[i]);
|
||||||
|
path->locks[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* look for key in the tree. path is filled in with nodes along the way
|
* look for key in the tree. path is filled in with nodes along the way
|
||||||
* if key is found, we return zero and you can find the item in the leaf
|
* if key is found, we return zero and you can find the item in the leaf
|
||||||
|
|
@ -1387,31 +1507,30 @@ again:
|
||||||
int wret;
|
int wret;
|
||||||
|
|
||||||
/* is a cow on this block not required */
|
/* is a cow on this block not required */
|
||||||
spin_lock(&root->fs_info->hash_lock);
|
|
||||||
if (btrfs_header_generation(b) == trans->transid &&
|
if (btrfs_header_generation(b) == trans->transid &&
|
||||||
btrfs_header_owner(b) == root->root_key.objectid &&
|
btrfs_header_owner(b) == root->root_key.objectid &&
|
||||||
!btrfs_header_flag(b, BTRFS_HEADER_FLAG_WRITTEN)) {
|
!btrfs_header_flag(b, BTRFS_HEADER_FLAG_WRITTEN)) {
|
||||||
spin_unlock(&root->fs_info->hash_lock);
|
|
||||||
goto cow_done;
|
goto cow_done;
|
||||||
}
|
}
|
||||||
spin_unlock(&root->fs_info->hash_lock);
|
|
||||||
|
|
||||||
/* ok, we have to cow, is our old prealloc the right
|
/* ok, we have to cow, is our old prealloc the right
|
||||||
* size?
|
* size?
|
||||||
*/
|
*/
|
||||||
if (prealloc_block.objectid &&
|
if (prealloc_block.objectid &&
|
||||||
prealloc_block.offset != b->len) {
|
prealloc_block.offset != b->len) {
|
||||||
|
btrfs_release_path(root, p);
|
||||||
btrfs_free_reserved_extent(root,
|
btrfs_free_reserved_extent(root,
|
||||||
prealloc_block.objectid,
|
prealloc_block.objectid,
|
||||||
prealloc_block.offset);
|
prealloc_block.offset);
|
||||||
prealloc_block.objectid = 0;
|
prealloc_block.objectid = 0;
|
||||||
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* for higher level blocks, try not to allocate blocks
|
* for higher level blocks, try not to allocate blocks
|
||||||
* with the block and the parent locks held.
|
* with the block and the parent locks held.
|
||||||
*/
|
*/
|
||||||
if (level > 1 && !prealloc_block.objectid &&
|
if (level > 0 && !prealloc_block.objectid &&
|
||||||
btrfs_path_lock_waiting(p, level)) {
|
btrfs_path_lock_waiting(p, level)) {
|
||||||
u32 size = b->len;
|
u32 size = b->len;
|
||||||
u64 hint = b->start;
|
u64 hint = b->start;
|
||||||
|
|
@ -1425,6 +1544,8 @@ again:
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btrfs_set_path_blocking(p);
|
||||||
|
|
||||||
wret = btrfs_cow_block(trans, root, b,
|
wret = btrfs_cow_block(trans, root, b,
|
||||||
p->nodes[level + 1],
|
p->nodes[level + 1],
|
||||||
p->slots[level + 1],
|
p->slots[level + 1],
|
||||||
|
|
@ -1446,6 +1567,22 @@ cow_done:
|
||||||
if (!p->skip_locking)
|
if (!p->skip_locking)
|
||||||
p->locks[level] = 1;
|
p->locks[level] = 1;
|
||||||
|
|
||||||
|
btrfs_clear_path_blocking(p);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we have a lock on b and as long as we aren't changing
|
||||||
|
* the tree, there is no way to for the items in b to change.
|
||||||
|
* It is safe to drop the lock on our parent before we
|
||||||
|
* go through the expensive btree search on b.
|
||||||
|
*
|
||||||
|
* If cow is true, then we might be changing slot zero,
|
||||||
|
* which may require changing the parent. So, we can't
|
||||||
|
* drop the lock until after we know which slot we're
|
||||||
|
* operating on.
|
||||||
|
*/
|
||||||
|
if (!cow)
|
||||||
|
btrfs_unlock_up_safe(p, level + 1);
|
||||||
|
|
||||||
ret = check_block(root, p, level);
|
ret = check_block(root, p, level);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
@ -1453,6 +1590,7 @@ cow_done:
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bin_search(b, key, level, &slot);
|
ret = bin_search(b, key, level, &slot);
|
||||||
|
|
||||||
if (level != 0) {
|
if (level != 0) {
|
||||||
if (ret && slot > 0)
|
if (ret && slot > 0)
|
||||||
slot -= 1;
|
slot -= 1;
|
||||||
|
|
@ -1460,7 +1598,16 @@ cow_done:
|
||||||
if ((p->search_for_split || ins_len > 0) &&
|
if ((p->search_for_split || ins_len > 0) &&
|
||||||
btrfs_header_nritems(b) >=
|
btrfs_header_nritems(b) >=
|
||||||
BTRFS_NODEPTRS_PER_BLOCK(root) - 3) {
|
BTRFS_NODEPTRS_PER_BLOCK(root) - 3) {
|
||||||
int sret = split_node(trans, root, p, level);
|
int sret;
|
||||||
|
|
||||||
|
sret = reada_for_balance(root, p, level);
|
||||||
|
if (sret)
|
||||||
|
goto again;
|
||||||
|
|
||||||
|
btrfs_set_path_blocking(p);
|
||||||
|
sret = split_node(trans, root, p, level);
|
||||||
|
btrfs_clear_path_blocking(p);
|
||||||
|
|
||||||
BUG_ON(sret > 0);
|
BUG_ON(sret > 0);
|
||||||
if (sret) {
|
if (sret) {
|
||||||
ret = sret;
|
ret = sret;
|
||||||
|
|
@ -1468,9 +1615,19 @@ cow_done:
|
||||||
}
|
}
|
||||||
b = p->nodes[level];
|
b = p->nodes[level];
|
||||||
slot = p->slots[level];
|
slot = p->slots[level];
|
||||||
} else if (ins_len < 0) {
|
} else if (ins_len < 0 &&
|
||||||
int sret = balance_level(trans, root, p,
|
btrfs_header_nritems(b) <
|
||||||
level);
|
BTRFS_NODEPTRS_PER_BLOCK(root) / 4) {
|
||||||
|
int sret;
|
||||||
|
|
||||||
|
sret = reada_for_balance(root, p, level);
|
||||||
|
if (sret)
|
||||||
|
goto again;
|
||||||
|
|
||||||
|
btrfs_set_path_blocking(p);
|
||||||
|
sret = balance_level(trans, root, p, level);
|
||||||
|
btrfs_clear_path_blocking(p);
|
||||||
|
|
||||||
if (sret) {
|
if (sret) {
|
||||||
ret = sret;
|
ret = sret;
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1504,7 +1661,7 @@ cow_done:
|
||||||
* of the btree by dropping locks before
|
* of the btree by dropping locks before
|
||||||
* we read.
|
* we read.
|
||||||
*/
|
*/
|
||||||
if (level > 1) {
|
if (level > 0) {
|
||||||
btrfs_release_path(NULL, p);
|
btrfs_release_path(NULL, p);
|
||||||
if (tmp)
|
if (tmp)
|
||||||
free_extent_buffer(tmp);
|
free_extent_buffer(tmp);
|
||||||
|
|
@ -1519,6 +1676,7 @@ cow_done:
|
||||||
free_extent_buffer(tmp);
|
free_extent_buffer(tmp);
|
||||||
goto again;
|
goto again;
|
||||||
} else {
|
} else {
|
||||||
|
btrfs_set_path_blocking(p);
|
||||||
if (tmp)
|
if (tmp)
|
||||||
free_extent_buffer(tmp);
|
free_extent_buffer(tmp);
|
||||||
if (should_reada)
|
if (should_reada)
|
||||||
|
|
@ -1528,14 +1686,29 @@ cow_done:
|
||||||
b = read_node_slot(root, b, slot);
|
b = read_node_slot(root, b, slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!p->skip_locking)
|
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_tree_lock(b);
|
||||||
|
btrfs_clear_path_blocking(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
p->slots[level] = slot;
|
p->slots[level] = slot;
|
||||||
if (ins_len > 0 &&
|
if (ins_len > 0 &&
|
||||||
btrfs_leaf_free_space(root, b) < ins_len) {
|
btrfs_leaf_free_space(root, b) < ins_len) {
|
||||||
int sret = split_leaf(trans, root, key,
|
int sret;
|
||||||
|
|
||||||
|
btrfs_set_path_blocking(p);
|
||||||
|
sret = split_leaf(trans, root, key,
|
||||||
p, ins_len, ret == 0);
|
p, ins_len, ret == 0);
|
||||||
|
btrfs_clear_path_blocking(p);
|
||||||
|
|
||||||
BUG_ON(sret > 0);
|
BUG_ON(sret > 0);
|
||||||
if (sret) {
|
if (sret) {
|
||||||
ret = sret;
|
ret = sret;
|
||||||
|
|
@ -1549,12 +1722,16 @@ cow_done:
|
||||||
}
|
}
|
||||||
ret = 1;
|
ret = 1;
|
||||||
done:
|
done:
|
||||||
|
/*
|
||||||
|
* we don't really know what they plan on doing with the path
|
||||||
|
* from here on, so for now just mark it as blocking
|
||||||
|
*/
|
||||||
|
btrfs_set_path_blocking(p);
|
||||||
if (prealloc_block.objectid) {
|
if (prealloc_block.objectid) {
|
||||||
btrfs_free_reserved_extent(root,
|
btrfs_free_reserved_extent(root,
|
||||||
prealloc_block.objectid,
|
prealloc_block.objectid,
|
||||||
prealloc_block.offset);
|
prealloc_block.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1578,6 +1755,8 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans,
|
||||||
ret = btrfs_cow_block(trans, root, eb, NULL, 0, &eb, 0);
|
ret = btrfs_cow_block(trans, root, eb, NULL, 0, &eb, 0);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
||||||
|
btrfs_set_lock_blocking(eb);
|
||||||
|
|
||||||
parent = eb;
|
parent = eb;
|
||||||
while (1) {
|
while (1) {
|
||||||
level = btrfs_header_level(parent);
|
level = btrfs_header_level(parent);
|
||||||
|
|
@ -1602,6 +1781,7 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans,
|
||||||
eb = read_tree_block(root, bytenr, blocksize,
|
eb = read_tree_block(root, bytenr, blocksize,
|
||||||
generation);
|
generation);
|
||||||
btrfs_tree_lock(eb);
|
btrfs_tree_lock(eb);
|
||||||
|
btrfs_set_lock_blocking(eb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1626,6 +1806,7 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans,
|
||||||
eb = read_tree_block(root, bytenr, blocksize,
|
eb = read_tree_block(root, bytenr, blocksize,
|
||||||
generation);
|
generation);
|
||||||
btrfs_tree_lock(eb);
|
btrfs_tree_lock(eb);
|
||||||
|
btrfs_set_lock_blocking(eb);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = btrfs_cow_block(trans, root, eb, parent, slot,
|
ret = btrfs_cow_block(trans, root, eb, parent, slot,
|
||||||
|
|
@ -2172,6 +2353,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
|
||||||
right = read_node_slot(root, upper, slot + 1);
|
right = read_node_slot(root, upper, slot + 1);
|
||||||
btrfs_tree_lock(right);
|
btrfs_tree_lock(right);
|
||||||
|
btrfs_set_lock_blocking(right);
|
||||||
|
|
||||||
free_space = btrfs_leaf_free_space(root, right);
|
free_space = btrfs_leaf_free_space(root, right);
|
||||||
if (free_space < data_size)
|
if (free_space < data_size)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
@ -2367,6 +2550,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
|
||||||
left = read_node_slot(root, path->nodes[1], slot - 1);
|
left = read_node_slot(root, path->nodes[1], slot - 1);
|
||||||
btrfs_tree_lock(left);
|
btrfs_tree_lock(left);
|
||||||
|
btrfs_set_lock_blocking(left);
|
||||||
|
|
||||||
free_space = btrfs_leaf_free_space(root, left);
|
free_space = btrfs_leaf_free_space(root, left);
|
||||||
if (free_space < data_size) {
|
if (free_space < data_size) {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
|
@ -2825,6 +3010,12 @@ int btrfs_split_item(struct btrfs_trans_handle *trans,
|
||||||
path->keep_locks = 0;
|
path->keep_locks = 0;
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make sure any changes to the path from split_leaf leave it
|
||||||
|
* in a blocking state
|
||||||
|
*/
|
||||||
|
btrfs_set_path_blocking(path);
|
||||||
|
|
||||||
leaf = path->nodes[0];
|
leaf = path->nodes[0];
|
||||||
BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item));
|
BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item));
|
||||||
|
|
||||||
|
|
@ -3354,6 +3545,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
btrfs_unlock_up_safe(path, 1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3441,15 +3633,22 @@ noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u64 root_gen = btrfs_header_generation(path->nodes[1]);
|
u64 root_gen = btrfs_header_generation(path->nodes[1]);
|
||||||
|
u64 parent_start = path->nodes[1]->start;
|
||||||
|
u64 parent_owner = btrfs_header_owner(path->nodes[1]);
|
||||||
|
|
||||||
ret = del_ptr(trans, root, path, 1, path->slots[1]);
|
ret = del_ptr(trans, root, path, 1, path->slots[1]);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* btrfs_free_extent is expensive, we want to make sure we
|
||||||
|
* aren't holding any locks when we call it
|
||||||
|
*/
|
||||||
|
btrfs_unlock_up_safe(path, 0);
|
||||||
|
|
||||||
ret = btrfs_free_extent(trans, root, bytenr,
|
ret = btrfs_free_extent(trans, root, bytenr,
|
||||||
btrfs_level_size(root, 0),
|
btrfs_level_size(root, 0),
|
||||||
path->nodes[1]->start,
|
parent_start, parent_owner,
|
||||||
btrfs_header_owner(path->nodes[1]),
|
|
||||||
root_gen, 0, 1);
|
root_gen, 0, 1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -3721,12 +3920,14 @@ find_next_key:
|
||||||
*/
|
*/
|
||||||
if (slot >= nritems) {
|
if (slot >= nritems) {
|
||||||
path->slots[level] = slot;
|
path->slots[level] = slot;
|
||||||
|
btrfs_set_path_blocking(path);
|
||||||
sret = btrfs_find_next_key(root, path, min_key, level,
|
sret = btrfs_find_next_key(root, path, min_key, level,
|
||||||
cache_only, min_trans);
|
cache_only, min_trans);
|
||||||
if (sret == 0) {
|
if (sret == 0) {
|
||||||
btrfs_release_path(root, path);
|
btrfs_release_path(root, path);
|
||||||
goto again;
|
goto again;
|
||||||
} else {
|
} else {
|
||||||
|
btrfs_clear_path_blocking(path);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3738,16 +3939,20 @@ find_next_key:
|
||||||
unlock_up(path, level, 1);
|
unlock_up(path, level, 1);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
btrfs_set_path_blocking(path);
|
||||||
cur = read_node_slot(root, cur, slot);
|
cur = read_node_slot(root, cur, slot);
|
||||||
|
|
||||||
btrfs_tree_lock(cur);
|
btrfs_tree_lock(cur);
|
||||||
|
|
||||||
path->locks[level - 1] = 1;
|
path->locks[level - 1] = 1;
|
||||||
path->nodes[level - 1] = cur;
|
path->nodes[level - 1] = cur;
|
||||||
unlock_up(path, level, 1);
|
unlock_up(path, level, 1);
|
||||||
|
btrfs_clear_path_blocking(path);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
memcpy(min_key, &found_key, sizeof(found_key));
|
memcpy(min_key, &found_key, sizeof(found_key));
|
||||||
|
btrfs_set_path_blocking(path);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3843,6 +4048,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
btrfs_set_path_blocking(path);
|
||||||
nritems = btrfs_header_nritems(path->nodes[0]);
|
nritems = btrfs_header_nritems(path->nodes[0]);
|
||||||
/*
|
/*
|
||||||
* by releasing the path above we dropped all our locks. A balance
|
* by releasing the path above we dropped all our locks. A balance
|
||||||
|
|
@ -3873,6 +4079,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
|
||||||
free_extent_buffer(next);
|
free_extent_buffer(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* the path was set to blocking above */
|
||||||
if (level == 1 && (path->locks[1] || path->skip_locking) &&
|
if (level == 1 && (path->locks[1] || path->skip_locking) &&
|
||||||
path->reada)
|
path->reada)
|
||||||
reada_for_search(root, path, level, slot, 0);
|
reada_for_search(root, path, level, slot, 0);
|
||||||
|
|
@ -3881,6 +4088,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
|
||||||
if (!path->skip_locking) {
|
if (!path->skip_locking) {
|
||||||
WARN_ON(!btrfs_tree_locked(c));
|
WARN_ON(!btrfs_tree_locked(c));
|
||||||
btrfs_tree_lock(next);
|
btrfs_tree_lock(next);
|
||||||
|
btrfs_set_lock_blocking(next);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -3897,12 +4105,15 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
|
||||||
path->locks[level] = 1;
|
path->locks[level] = 1;
|
||||||
if (!level)
|
if (!level)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
btrfs_set_path_blocking(path);
|
||||||
if (level == 1 && path->locks[1] && path->reada)
|
if (level == 1 && path->locks[1] && path->reada)
|
||||||
reada_for_search(root, path, level, slot, 0);
|
reada_for_search(root, path, level, slot, 0);
|
||||||
next = read_node_slot(root, next, 0);
|
next = read_node_slot(root, next, 0);
|
||||||
if (!path->skip_locking) {
|
if (!path->skip_locking) {
|
||||||
WARN_ON(!btrfs_tree_locked(path->nodes[level]));
|
WARN_ON(!btrfs_tree_locked(path->nodes[level]));
|
||||||
btrfs_tree_lock(next);
|
btrfs_tree_lock(next);
|
||||||
|
btrfs_set_lock_blocking(next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
|
|
@ -3927,6 +4138,7 @@ int btrfs_previous_item(struct btrfs_root *root,
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (path->slots[0] == 0) {
|
if (path->slots[0] == 0) {
|
||||||
|
btrfs_set_path_blocking(path);
|
||||||
ret = btrfs_prev_leaf(root, path);
|
ret = btrfs_prev_leaf(root, path);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -454,17 +454,11 @@ struct btrfs_timespec {
|
||||||
__le32 nsec;
|
__le32 nsec;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
typedef enum {
|
enum btrfs_compression_type {
|
||||||
BTRFS_COMPRESS_NONE = 0,
|
BTRFS_COMPRESS_NONE = 0,
|
||||||
BTRFS_COMPRESS_ZLIB = 1,
|
BTRFS_COMPRESS_ZLIB = 1,
|
||||||
BTRFS_COMPRESS_LAST = 2,
|
BTRFS_COMPRESS_LAST = 2,
|
||||||
} btrfs_compression_type;
|
};
|
||||||
|
|
||||||
/* we don't understand any encryption methods right now */
|
|
||||||
typedef enum {
|
|
||||||
BTRFS_ENCRYPTION_NONE = 0,
|
|
||||||
BTRFS_ENCRYPTION_LAST = 1,
|
|
||||||
} btrfs_encryption_type;
|
|
||||||
|
|
||||||
struct btrfs_inode_item {
|
struct btrfs_inode_item {
|
||||||
/* nfs style generation number */
|
/* nfs style generation number */
|
||||||
|
|
@ -701,9 +695,7 @@ struct btrfs_fs_info {
|
||||||
struct btrfs_transaction *running_transaction;
|
struct btrfs_transaction *running_transaction;
|
||||||
wait_queue_head_t transaction_throttle;
|
wait_queue_head_t transaction_throttle;
|
||||||
wait_queue_head_t transaction_wait;
|
wait_queue_head_t transaction_wait;
|
||||||
|
|
||||||
wait_queue_head_t async_submit_wait;
|
wait_queue_head_t async_submit_wait;
|
||||||
wait_queue_head_t tree_log_wait;
|
|
||||||
|
|
||||||
struct btrfs_super_block super_copy;
|
struct btrfs_super_block super_copy;
|
||||||
struct btrfs_super_block super_for_commit;
|
struct btrfs_super_block super_for_commit;
|
||||||
|
|
@ -711,7 +703,6 @@ struct btrfs_fs_info {
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
struct inode *btree_inode;
|
struct inode *btree_inode;
|
||||||
struct backing_dev_info bdi;
|
struct backing_dev_info bdi;
|
||||||
spinlock_t hash_lock;
|
|
||||||
struct mutex trans_mutex;
|
struct mutex trans_mutex;
|
||||||
struct mutex tree_log_mutex;
|
struct mutex tree_log_mutex;
|
||||||
struct mutex transaction_kthread_mutex;
|
struct mutex transaction_kthread_mutex;
|
||||||
|
|
@ -730,10 +721,6 @@ struct btrfs_fs_info {
|
||||||
atomic_t async_submit_draining;
|
atomic_t async_submit_draining;
|
||||||
atomic_t nr_async_bios;
|
atomic_t nr_async_bios;
|
||||||
atomic_t async_delalloc_pages;
|
atomic_t async_delalloc_pages;
|
||||||
atomic_t tree_log_writers;
|
|
||||||
atomic_t tree_log_commit;
|
|
||||||
unsigned long tree_log_batch;
|
|
||||||
u64 tree_log_transid;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* this is used by the balancing code to wait for all the pending
|
* this is used by the balancing code to wait for all the pending
|
||||||
|
|
@ -833,7 +820,14 @@ struct btrfs_root {
|
||||||
struct kobject root_kobj;
|
struct kobject root_kobj;
|
||||||
struct completion kobj_unregister;
|
struct completion kobj_unregister;
|
||||||
struct mutex objectid_mutex;
|
struct mutex objectid_mutex;
|
||||||
|
|
||||||
struct mutex log_mutex;
|
struct mutex log_mutex;
|
||||||
|
wait_queue_head_t log_writer_wait;
|
||||||
|
wait_queue_head_t log_commit_wait[2];
|
||||||
|
atomic_t log_writers;
|
||||||
|
atomic_t log_commit[2];
|
||||||
|
unsigned long log_transid;
|
||||||
|
unsigned long log_batch;
|
||||||
|
|
||||||
u64 objectid;
|
u64 objectid;
|
||||||
u64 last_trans;
|
u64 last_trans;
|
||||||
|
|
@ -1841,6 +1835,10 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
|
||||||
struct btrfs_path *btrfs_alloc_path(void);
|
struct btrfs_path *btrfs_alloc_path(void);
|
||||||
void btrfs_free_path(struct btrfs_path *p);
|
void btrfs_free_path(struct btrfs_path *p);
|
||||||
void btrfs_init_path(struct btrfs_path *p);
|
void btrfs_init_path(struct btrfs_path *p);
|
||||||
|
void btrfs_set_path_blocking(struct btrfs_path *p);
|
||||||
|
void btrfs_clear_path_blocking(struct btrfs_path *p);
|
||||||
|
void btrfs_unlock_up_safe(struct btrfs_path *p, int level);
|
||||||
|
|
||||||
int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
struct btrfs_path *path, int slot, int nr);
|
struct btrfs_path *path, int slot, int nr);
|
||||||
int btrfs_del_leaf(struct btrfs_trans_handle *trans,
|
int btrfs_del_leaf(struct btrfs_trans_handle *trans,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
* Boston, MA 021110-1307, USA.
|
* Boston, MA 021110-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/version.h>
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <linux/scatterlist.h>
|
#include <linux/scatterlist.h>
|
||||||
|
|
@ -800,7 +799,7 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
|
||||||
ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
|
ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
buf->flags |= EXTENT_UPTODATE;
|
set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags);
|
||||||
else
|
else
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
return buf;
|
return buf;
|
||||||
|
|
@ -814,6 +813,10 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
if (btrfs_header_generation(buf) ==
|
if (btrfs_header_generation(buf) ==
|
||||||
root->fs_info->running_transaction->transid) {
|
root->fs_info->running_transaction->transid) {
|
||||||
WARN_ON(!btrfs_tree_locked(buf));
|
WARN_ON(!btrfs_tree_locked(buf));
|
||||||
|
|
||||||
|
/* ugh, clear_extent_buffer_dirty can be expensive */
|
||||||
|
btrfs_set_lock_blocking(buf);
|
||||||
|
|
||||||
clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree,
|
clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree,
|
||||||
buf);
|
buf);
|
||||||
}
|
}
|
||||||
|
|
@ -850,6 +853,14 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
|
||||||
spin_lock_init(&root->list_lock);
|
spin_lock_init(&root->list_lock);
|
||||||
mutex_init(&root->objectid_mutex);
|
mutex_init(&root->objectid_mutex);
|
||||||
mutex_init(&root->log_mutex);
|
mutex_init(&root->log_mutex);
|
||||||
|
init_waitqueue_head(&root->log_writer_wait);
|
||||||
|
init_waitqueue_head(&root->log_commit_wait[0]);
|
||||||
|
init_waitqueue_head(&root->log_commit_wait[1]);
|
||||||
|
atomic_set(&root->log_commit[0], 0);
|
||||||
|
atomic_set(&root->log_commit[1], 0);
|
||||||
|
atomic_set(&root->log_writers, 0);
|
||||||
|
root->log_batch = 0;
|
||||||
|
root->log_transid = 0;
|
||||||
extent_io_tree_init(&root->dirty_log_pages,
|
extent_io_tree_init(&root->dirty_log_pages,
|
||||||
fs_info->btree_inode->i_mapping, GFP_NOFS);
|
fs_info->btree_inode->i_mapping, GFP_NOFS);
|
||||||
|
|
||||||
|
|
@ -934,15 +945,16 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
|
static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_fs_info *fs_info)
|
struct btrfs_fs_info *fs_info)
|
||||||
{
|
{
|
||||||
struct btrfs_root *root;
|
struct btrfs_root *root;
|
||||||
struct btrfs_root *tree_root = fs_info->tree_root;
|
struct btrfs_root *tree_root = fs_info->tree_root;
|
||||||
|
struct extent_buffer *leaf;
|
||||||
|
|
||||||
root = kzalloc(sizeof(*root), GFP_NOFS);
|
root = kzalloc(sizeof(*root), GFP_NOFS);
|
||||||
if (!root)
|
if (!root)
|
||||||
return -ENOMEM;
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
__setup_root(tree_root->nodesize, tree_root->leafsize,
|
__setup_root(tree_root->nodesize, tree_root->leafsize,
|
||||||
tree_root->sectorsize, tree_root->stripesize,
|
tree_root->sectorsize, tree_root->stripesize,
|
||||||
|
|
@ -951,12 +963,23 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
|
||||||
root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID;
|
root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID;
|
||||||
root->root_key.type = BTRFS_ROOT_ITEM_KEY;
|
root->root_key.type = BTRFS_ROOT_ITEM_KEY;
|
||||||
root->root_key.offset = BTRFS_TREE_LOG_OBJECTID;
|
root->root_key.offset = BTRFS_TREE_LOG_OBJECTID;
|
||||||
|
/*
|
||||||
|
* log trees do not get reference counted because they go away
|
||||||
|
* before a real commit is actually done. They do store pointers
|
||||||
|
* to file data extents, and those reference counts still get
|
||||||
|
* updated (along with back refs to the log tree).
|
||||||
|
*/
|
||||||
root->ref_cows = 0;
|
root->ref_cows = 0;
|
||||||
|
|
||||||
root->node = btrfs_alloc_free_block(trans, root, root->leafsize,
|
leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
|
||||||
0, BTRFS_TREE_LOG_OBJECTID,
|
0, BTRFS_TREE_LOG_OBJECTID,
|
||||||
trans->transid, 0, 0, 0);
|
trans->transid, 0, 0, 0);
|
||||||
|
if (IS_ERR(leaf)) {
|
||||||
|
kfree(root);
|
||||||
|
return ERR_CAST(leaf);
|
||||||
|
}
|
||||||
|
|
||||||
|
root->node = leaf;
|
||||||
btrfs_set_header_nritems(root->node, 0);
|
btrfs_set_header_nritems(root->node, 0);
|
||||||
btrfs_set_header_level(root->node, 0);
|
btrfs_set_header_level(root->node, 0);
|
||||||
btrfs_set_header_bytenr(root->node, root->node->start);
|
btrfs_set_header_bytenr(root->node, root->node->start);
|
||||||
|
|
@ -968,7 +991,48 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
|
||||||
BTRFS_FSID_SIZE);
|
BTRFS_FSID_SIZE);
|
||||||
btrfs_mark_buffer_dirty(root->node);
|
btrfs_mark_buffer_dirty(root->node);
|
||||||
btrfs_tree_unlock(root->node);
|
btrfs_tree_unlock(root->node);
|
||||||
fs_info->log_root_tree = root;
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
|
||||||
|
struct btrfs_fs_info *fs_info)
|
||||||
|
{
|
||||||
|
struct btrfs_root *log_root;
|
||||||
|
|
||||||
|
log_root = alloc_log_tree(trans, fs_info);
|
||||||
|
if (IS_ERR(log_root))
|
||||||
|
return PTR_ERR(log_root);
|
||||||
|
WARN_ON(fs_info->log_root_tree);
|
||||||
|
fs_info->log_root_tree = log_root;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
|
||||||
|
struct btrfs_root *root)
|
||||||
|
{
|
||||||
|
struct btrfs_root *log_root;
|
||||||
|
struct btrfs_inode_item *inode_item;
|
||||||
|
|
||||||
|
log_root = alloc_log_tree(trans, root->fs_info);
|
||||||
|
if (IS_ERR(log_root))
|
||||||
|
return PTR_ERR(log_root);
|
||||||
|
|
||||||
|
log_root->last_trans = trans->transid;
|
||||||
|
log_root->root_key.offset = root->root_key.objectid;
|
||||||
|
|
||||||
|
inode_item = &log_root->root_item.inode;
|
||||||
|
inode_item->generation = cpu_to_le64(1);
|
||||||
|
inode_item->size = cpu_to_le64(3);
|
||||||
|
inode_item->nlink = cpu_to_le32(1);
|
||||||
|
inode_item->nbytes = cpu_to_le64(root->leafsize);
|
||||||
|
inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
|
||||||
|
|
||||||
|
btrfs_set_root_bytenr(&log_root->root_item, log_root->node->start);
|
||||||
|
btrfs_set_root_generation(&log_root->root_item, trans->transid);
|
||||||
|
|
||||||
|
WARN_ON(root->log_root);
|
||||||
|
root->log_root = log_root;
|
||||||
|
root->log_transid = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1136,7 +1200,6 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
|
||||||
{
|
{
|
||||||
struct btrfs_fs_info *info = (struct btrfs_fs_info *)congested_data;
|
struct btrfs_fs_info *info = (struct btrfs_fs_info *)congested_data;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct list_head *cur;
|
|
||||||
struct btrfs_device *device;
|
struct btrfs_device *device;
|
||||||
struct backing_dev_info *bdi;
|
struct backing_dev_info *bdi;
|
||||||
#if 0
|
#if 0
|
||||||
|
|
@ -1144,8 +1207,7 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
|
||||||
btrfs_congested_async(info, 0))
|
btrfs_congested_async(info, 0))
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
list_for_each(cur, &info->fs_devices->devices) {
|
list_for_each_entry(device, &info->fs_devices->devices, dev_list) {
|
||||||
device = list_entry(cur, struct btrfs_device, dev_list);
|
|
||||||
if (!device->bdev)
|
if (!device->bdev)
|
||||||
continue;
|
continue;
|
||||||
bdi = blk_get_backing_dev_info(device->bdev);
|
bdi = blk_get_backing_dev_info(device->bdev);
|
||||||
|
|
@ -1163,13 +1225,11 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits)
|
||||||
*/
|
*/
|
||||||
static void __unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
|
static void __unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
|
||||||
{
|
{
|
||||||
struct list_head *cur;
|
|
||||||
struct btrfs_device *device;
|
struct btrfs_device *device;
|
||||||
struct btrfs_fs_info *info;
|
struct btrfs_fs_info *info;
|
||||||
|
|
||||||
info = (struct btrfs_fs_info *)bdi->unplug_io_data;
|
info = (struct btrfs_fs_info *)bdi->unplug_io_data;
|
||||||
list_for_each(cur, &info->fs_devices->devices) {
|
list_for_each_entry(device, &info->fs_devices->devices, dev_list) {
|
||||||
device = list_entry(cur, struct btrfs_device, dev_list);
|
|
||||||
if (!device->bdev)
|
if (!device->bdev)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -1447,7 +1507,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
||||||
INIT_LIST_HEAD(&fs_info->dead_roots);
|
INIT_LIST_HEAD(&fs_info->dead_roots);
|
||||||
INIT_LIST_HEAD(&fs_info->hashers);
|
INIT_LIST_HEAD(&fs_info->hashers);
|
||||||
INIT_LIST_HEAD(&fs_info->delalloc_inodes);
|
INIT_LIST_HEAD(&fs_info->delalloc_inodes);
|
||||||
spin_lock_init(&fs_info->hash_lock);
|
|
||||||
spin_lock_init(&fs_info->delalloc_lock);
|
spin_lock_init(&fs_info->delalloc_lock);
|
||||||
spin_lock_init(&fs_info->new_trans_lock);
|
spin_lock_init(&fs_info->new_trans_lock);
|
||||||
spin_lock_init(&fs_info->ref_cache_lock);
|
spin_lock_init(&fs_info->ref_cache_lock);
|
||||||
|
|
@ -1535,10 +1594,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
||||||
init_waitqueue_head(&fs_info->transaction_throttle);
|
init_waitqueue_head(&fs_info->transaction_throttle);
|
||||||
init_waitqueue_head(&fs_info->transaction_wait);
|
init_waitqueue_head(&fs_info->transaction_wait);
|
||||||
init_waitqueue_head(&fs_info->async_submit_wait);
|
init_waitqueue_head(&fs_info->async_submit_wait);
|
||||||
init_waitqueue_head(&fs_info->tree_log_wait);
|
|
||||||
atomic_set(&fs_info->tree_log_commit, 0);
|
|
||||||
atomic_set(&fs_info->tree_log_writers, 0);
|
|
||||||
fs_info->tree_log_transid = 0;
|
|
||||||
|
|
||||||
__setup_root(4096, 4096, 4096, 4096, tree_root,
|
__setup_root(4096, 4096, 4096, 4096, tree_root,
|
||||||
fs_info, BTRFS_ROOT_TREE_OBJECTID);
|
fs_info, BTRFS_ROOT_TREE_OBJECTID);
|
||||||
|
|
@ -1627,6 +1682,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
||||||
* low idle thresh
|
* low idle thresh
|
||||||
*/
|
*/
|
||||||
fs_info->endio_workers.idle_thresh = 4;
|
fs_info->endio_workers.idle_thresh = 4;
|
||||||
|
fs_info->endio_meta_workers.idle_thresh = 4;
|
||||||
|
|
||||||
fs_info->endio_write_workers.idle_thresh = 64;
|
fs_info->endio_write_workers.idle_thresh = 64;
|
||||||
fs_info->endio_meta_write_workers.idle_thresh = 64;
|
fs_info->endio_meta_write_workers.idle_thresh = 64;
|
||||||
|
|
||||||
|
|
@ -1740,13 +1797,13 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
||||||
fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
|
fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
|
||||||
fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
|
fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
|
||||||
"btrfs-cleaner");
|
"btrfs-cleaner");
|
||||||
if (!fs_info->cleaner_kthread)
|
if (IS_ERR(fs_info->cleaner_kthread))
|
||||||
goto fail_csum_root;
|
goto fail_csum_root;
|
||||||
|
|
||||||
fs_info->transaction_kthread = kthread_run(transaction_kthread,
|
fs_info->transaction_kthread = kthread_run(transaction_kthread,
|
||||||
tree_root,
|
tree_root,
|
||||||
"btrfs-transaction");
|
"btrfs-transaction");
|
||||||
if (!fs_info->transaction_kthread)
|
if (IS_ERR(fs_info->transaction_kthread))
|
||||||
goto fail_cleaner;
|
goto fail_cleaner;
|
||||||
|
|
||||||
if (btrfs_super_log_root(disk_super) != 0) {
|
if (btrfs_super_log_root(disk_super) != 0) {
|
||||||
|
|
@ -1828,13 +1885,14 @@ fail_sb_buffer:
|
||||||
fail_iput:
|
fail_iput:
|
||||||
invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
|
invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
|
||||||
iput(fs_info->btree_inode);
|
iput(fs_info->btree_inode);
|
||||||
fail:
|
|
||||||
btrfs_close_devices(fs_info->fs_devices);
|
btrfs_close_devices(fs_info->fs_devices);
|
||||||
btrfs_mapping_tree_free(&fs_info->mapping_tree);
|
btrfs_mapping_tree_free(&fs_info->mapping_tree);
|
||||||
|
bdi_destroy(&fs_info->bdi);
|
||||||
|
|
||||||
|
fail:
|
||||||
kfree(extent_root);
|
kfree(extent_root);
|
||||||
kfree(tree_root);
|
kfree(tree_root);
|
||||||
bdi_destroy(&fs_info->bdi);
|
|
||||||
kfree(fs_info);
|
kfree(fs_info);
|
||||||
kfree(chunk_root);
|
kfree(chunk_root);
|
||||||
kfree(dev_root);
|
kfree(dev_root);
|
||||||
|
|
@ -1995,7 +2053,6 @@ static int write_dev_supers(struct btrfs_device *device,
|
||||||
|
|
||||||
int write_all_supers(struct btrfs_root *root, int max_mirrors)
|
int write_all_supers(struct btrfs_root *root, int max_mirrors)
|
||||||
{
|
{
|
||||||
struct list_head *cur;
|
|
||||||
struct list_head *head = &root->fs_info->fs_devices->devices;
|
struct list_head *head = &root->fs_info->fs_devices->devices;
|
||||||
struct btrfs_device *dev;
|
struct btrfs_device *dev;
|
||||||
struct btrfs_super_block *sb;
|
struct btrfs_super_block *sb;
|
||||||
|
|
@ -2011,8 +2068,7 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors)
|
||||||
|
|
||||||
sb = &root->fs_info->super_for_commit;
|
sb = &root->fs_info->super_for_commit;
|
||||||
dev_item = &sb->dev_item;
|
dev_item = &sb->dev_item;
|
||||||
list_for_each(cur, head) {
|
list_for_each_entry(dev, head, dev_list) {
|
||||||
dev = list_entry(cur, struct btrfs_device, dev_list);
|
|
||||||
if (!dev->bdev) {
|
if (!dev->bdev) {
|
||||||
total_errors++;
|
total_errors++;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -2045,8 +2101,7 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors)
|
||||||
}
|
}
|
||||||
|
|
||||||
total_errors = 0;
|
total_errors = 0;
|
||||||
list_for_each(cur, head) {
|
list_for_each_entry(dev, head, dev_list) {
|
||||||
dev = list_entry(cur, struct btrfs_device, dev_list);
|
|
||||||
if (!dev->bdev)
|
if (!dev->bdev)
|
||||||
continue;
|
continue;
|
||||||
if (!dev->in_fs_metadata || !dev->writeable)
|
if (!dev->in_fs_metadata || !dev->writeable)
|
||||||
|
|
@ -2260,6 +2315,8 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
|
||||||
u64 transid = btrfs_header_generation(buf);
|
u64 transid = btrfs_header_generation(buf);
|
||||||
struct inode *btree_inode = root->fs_info->btree_inode;
|
struct inode *btree_inode = root->fs_info->btree_inode;
|
||||||
|
|
||||||
|
btrfs_set_lock_blocking(buf);
|
||||||
|
|
||||||
WARN_ON(!btrfs_tree_locked(buf));
|
WARN_ON(!btrfs_tree_locked(buf));
|
||||||
if (transid != root->fs_info->generation) {
|
if (transid != root->fs_info->generation) {
|
||||||
printk(KERN_CRIT "btrfs transid mismatch buffer %llu, "
|
printk(KERN_CRIT "btrfs transid mismatch buffer %llu, "
|
||||||
|
|
@ -2302,14 +2359,13 @@ int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid)
|
||||||
int ret;
|
int ret;
|
||||||
ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
|
ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
buf->flags |= EXTENT_UPTODATE;
|
set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btree_lock_page_hook(struct page *page)
|
int btree_lock_page_hook(struct page *page)
|
||||||
{
|
{
|
||||||
struct inode *inode = page->mapping->host;
|
struct inode *inode = page->mapping->host;
|
||||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
|
||||||
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
|
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
|
||||||
struct extent_buffer *eb;
|
struct extent_buffer *eb;
|
||||||
unsigned long len;
|
unsigned long len;
|
||||||
|
|
@ -2324,9 +2380,7 @@ int btree_lock_page_hook(struct page *page)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
btrfs_tree_lock(eb);
|
btrfs_tree_lock(eb);
|
||||||
spin_lock(&root->fs_info->hash_lock);
|
|
||||||
btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
|
btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
|
||||||
spin_unlock(&root->fs_info->hash_lock);
|
|
||||||
btrfs_tree_unlock(eb);
|
btrfs_tree_unlock(eb);
|
||||||
free_extent_buffer(eb);
|
free_extent_buffer(eb);
|
||||||
out:
|
out:
|
||||||
|
|
|
||||||
|
|
@ -98,5 +98,7 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_fs_info *fs_info);
|
struct btrfs_fs_info *fs_info);
|
||||||
int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
|
int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_fs_info *fs_info);
|
struct btrfs_fs_info *fs_info);
|
||||||
|
int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
|
||||||
|
struct btrfs_root *root);
|
||||||
int btree_lock_page_hook(struct page *page);
|
int btree_lock_page_hook(struct page *page);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <linux/version.h>
|
#include <linux/sort.h>
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "crc32c.h"
|
#include "crc32c.h"
|
||||||
|
|
@ -30,7 +30,6 @@
|
||||||
#include "volumes.h"
|
#include "volumes.h"
|
||||||
#include "locking.h"
|
#include "locking.h"
|
||||||
#include "ref-cache.h"
|
#include "ref-cache.h"
|
||||||
#include "compat.h"
|
|
||||||
|
|
||||||
#define PENDING_EXTENT_INSERT 0
|
#define PENDING_EXTENT_INSERT 0
|
||||||
#define PENDING_EXTENT_DELETE 1
|
#define PENDING_EXTENT_DELETE 1
|
||||||
|
|
@ -326,10 +325,8 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
|
||||||
u64 flags)
|
u64 flags)
|
||||||
{
|
{
|
||||||
struct list_head *head = &info->space_info;
|
struct list_head *head = &info->space_info;
|
||||||
struct list_head *cur;
|
|
||||||
struct btrfs_space_info *found;
|
struct btrfs_space_info *found;
|
||||||
list_for_each(cur, head) {
|
list_for_each_entry(found, head, list) {
|
||||||
found = list_entry(cur, struct btrfs_space_info, list);
|
|
||||||
if (found->flags == flags)
|
if (found->flags == flags)
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
@ -1525,15 +1522,55 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
/* when a block goes through cow, we update the reference counts of
|
||||||
struct extent_buffer *orig_buf, struct extent_buffer *buf,
|
* everything that block points to. The internal pointers of the block
|
||||||
u32 *nr_extents)
|
* can be in just about any order, and it is likely to have clusters of
|
||||||
|
* things that are close together and clusters of things that are not.
|
||||||
|
*
|
||||||
|
* To help reduce the seeks that come with updating all of these reference
|
||||||
|
* counts, sort them by byte number before actual updates are done.
|
||||||
|
*
|
||||||
|
* struct refsort is used to match byte number to slot in the btree block.
|
||||||
|
* we sort based on the byte number and then use the slot to actually
|
||||||
|
* find the item.
|
||||||
|
*
|
||||||
|
* struct refsort is smaller than strcut btrfs_item and smaller than
|
||||||
|
* struct btrfs_key_ptr. Since we're currently limited to the page size
|
||||||
|
* for a btree block, there's no way for a kmalloc of refsorts for a
|
||||||
|
* single node to be bigger than a page.
|
||||||
|
*/
|
||||||
|
struct refsort {
|
||||||
|
u64 bytenr;
|
||||||
|
u32 slot;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* for passing into sort()
|
||||||
|
*/
|
||||||
|
static int refsort_cmp(const void *a_void, const void *b_void)
|
||||||
|
{
|
||||||
|
const struct refsort *a = a_void;
|
||||||
|
const struct refsort *b = b_void;
|
||||||
|
|
||||||
|
if (a->bytenr < b->bytenr)
|
||||||
|
return -1;
|
||||||
|
if (a->bytenr > b->bytenr)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
noinline int btrfs_inc_ref(struct btrfs_trans_handle *trans,
|
||||||
|
struct btrfs_root *root,
|
||||||
|
struct extent_buffer *orig_buf,
|
||||||
|
struct extent_buffer *buf, u32 *nr_extents)
|
||||||
{
|
{
|
||||||
u64 bytenr;
|
u64 bytenr;
|
||||||
u64 ref_root;
|
u64 ref_root;
|
||||||
u64 orig_root;
|
u64 orig_root;
|
||||||
u64 ref_generation;
|
u64 ref_generation;
|
||||||
u64 orig_generation;
|
u64 orig_generation;
|
||||||
|
struct refsort *sorted;
|
||||||
u32 nritems;
|
u32 nritems;
|
||||||
u32 nr_file_extents = 0;
|
u32 nr_file_extents = 0;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
|
|
@ -1542,6 +1579,8 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
int level;
|
int level;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int faili = 0;
|
int faili = 0;
|
||||||
|
int refi = 0;
|
||||||
|
int slot;
|
||||||
int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *,
|
int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *,
|
||||||
u64, u64, u64, u64, u64, u64, u64, u64);
|
u64, u64, u64, u64, u64, u64, u64, u64);
|
||||||
|
|
||||||
|
|
@ -1553,6 +1592,9 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
nritems = btrfs_header_nritems(buf);
|
nritems = btrfs_header_nritems(buf);
|
||||||
level = btrfs_header_level(buf);
|
level = btrfs_header_level(buf);
|
||||||
|
|
||||||
|
sorted = kmalloc(sizeof(struct refsort) * nritems, GFP_NOFS);
|
||||||
|
BUG_ON(!sorted);
|
||||||
|
|
||||||
if (root->ref_cows) {
|
if (root->ref_cows) {
|
||||||
process_func = __btrfs_inc_extent_ref;
|
process_func = __btrfs_inc_extent_ref;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1565,6 +1607,11 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
process_func = __btrfs_update_extent_ref;
|
process_func = __btrfs_update_extent_ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we make two passes through the items. In the first pass we
|
||||||
|
* only record the byte number and slot. Then we sort based on
|
||||||
|
* byte number and do the actual work based on the sorted results
|
||||||
|
*/
|
||||||
for (i = 0; i < nritems; i++) {
|
for (i = 0; i < nritems; i++) {
|
||||||
cond_resched();
|
cond_resched();
|
||||||
if (level == 0) {
|
if (level == 0) {
|
||||||
|
|
@ -1581,6 +1628,32 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
nr_file_extents++;
|
nr_file_extents++;
|
||||||
|
sorted[refi].bytenr = bytenr;
|
||||||
|
sorted[refi].slot = i;
|
||||||
|
refi++;
|
||||||
|
} else {
|
||||||
|
bytenr = btrfs_node_blockptr(buf, i);
|
||||||
|
sorted[refi].bytenr = bytenr;
|
||||||
|
sorted[refi].slot = i;
|
||||||
|
refi++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* if refi == 0, we didn't actually put anything into the sorted
|
||||||
|
* array and we're done
|
||||||
|
*/
|
||||||
|
if (refi == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
sort(sorted, refi, sizeof(struct refsort), refsort_cmp, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < refi; i++) {
|
||||||
|
cond_resched();
|
||||||
|
slot = sorted[i].slot;
|
||||||
|
bytenr = sorted[i].bytenr;
|
||||||
|
|
||||||
|
if (level == 0) {
|
||||||
|
btrfs_item_key_to_cpu(buf, &key, slot);
|
||||||
|
|
||||||
ret = process_func(trans, root, bytenr,
|
ret = process_func(trans, root, bytenr,
|
||||||
orig_buf->start, buf->start,
|
orig_buf->start, buf->start,
|
||||||
|
|
@ -1589,25 +1662,25 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
key.objectid);
|
key.objectid);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
faili = i;
|
faili = slot;
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bytenr = btrfs_node_blockptr(buf, i);
|
|
||||||
ret = process_func(trans, root, bytenr,
|
ret = process_func(trans, root, bytenr,
|
||||||
orig_buf->start, buf->start,
|
orig_buf->start, buf->start,
|
||||||
orig_root, ref_root,
|
orig_root, ref_root,
|
||||||
orig_generation, ref_generation,
|
orig_generation, ref_generation,
|
||||||
level - 1);
|
level - 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
faili = i;
|
faili = slot;
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
kfree(sorted);
|
||||||
if (nr_extents) {
|
if (nr_extents) {
|
||||||
if (level == 0)
|
if (level == 0)
|
||||||
*nr_extents = nr_file_extents;
|
*nr_extents = nr_file_extents;
|
||||||
|
|
@ -1616,6 +1689,7 @@ out:
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
|
kfree(sorted);
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -2159,7 +2233,8 @@ again:
|
||||||
ret = find_first_extent_bit(&info->extent_ins, search, &start,
|
ret = find_first_extent_bit(&info->extent_ins, search, &start,
|
||||||
&end, EXTENT_WRITEBACK);
|
&end, EXTENT_WRITEBACK);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (skipped && all && !num_inserts) {
|
if (skipped && all && !num_inserts &&
|
||||||
|
list_empty(&update_list)) {
|
||||||
skipped = 0;
|
skipped = 0;
|
||||||
search = 0;
|
search = 0;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -2547,6 +2622,7 @@ again:
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (all && skipped && !nr) {
|
if (all && skipped && !nr) {
|
||||||
search = 0;
|
search = 0;
|
||||||
|
skipped = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mutex_unlock(&info->extent_ins_mutex);
|
mutex_unlock(&info->extent_ins_mutex);
|
||||||
|
|
@ -2700,13 +2776,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||||
/* if metadata always pin */
|
/* if metadata always pin */
|
||||||
if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID) {
|
if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID) {
|
||||||
if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
|
if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
|
||||||
struct btrfs_block_group_cache *cache;
|
mutex_lock(&root->fs_info->pinned_mutex);
|
||||||
|
btrfs_update_pinned_extents(root, bytenr, num_bytes, 1);
|
||||||
/* btrfs_free_reserved_extent */
|
mutex_unlock(&root->fs_info->pinned_mutex);
|
||||||
cache = btrfs_lookup_block_group(root->fs_info, bytenr);
|
|
||||||
BUG_ON(!cache);
|
|
||||||
btrfs_add_free_space(cache, bytenr, num_bytes);
|
|
||||||
put_block_group(cache);
|
|
||||||
update_reserved_extents(root, bytenr, num_bytes, 0);
|
update_reserved_extents(root, bytenr, num_bytes, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -3014,7 +3086,6 @@ loop_check:
|
||||||
static void dump_space_info(struct btrfs_space_info *info, u64 bytes)
|
static void dump_space_info(struct btrfs_space_info *info, u64 bytes)
|
||||||
{
|
{
|
||||||
struct btrfs_block_group_cache *cache;
|
struct btrfs_block_group_cache *cache;
|
||||||
struct list_head *l;
|
|
||||||
|
|
||||||
printk(KERN_INFO "space_info has %llu free, is %sfull\n",
|
printk(KERN_INFO "space_info has %llu free, is %sfull\n",
|
||||||
(unsigned long long)(info->total_bytes - info->bytes_used -
|
(unsigned long long)(info->total_bytes - info->bytes_used -
|
||||||
|
|
@ -3022,8 +3093,7 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes)
|
||||||
(info->full) ? "" : "not ");
|
(info->full) ? "" : "not ");
|
||||||
|
|
||||||
down_read(&info->groups_sem);
|
down_read(&info->groups_sem);
|
||||||
list_for_each(l, &info->block_groups) {
|
list_for_each_entry(cache, &info->block_groups, list) {
|
||||||
cache = list_entry(l, struct btrfs_block_group_cache, list);
|
|
||||||
spin_lock(&cache->lock);
|
spin_lock(&cache->lock);
|
||||||
printk(KERN_INFO "block group %llu has %llu bytes, %llu used "
|
printk(KERN_INFO "block group %llu has %llu bytes, %llu used "
|
||||||
"%llu pinned %llu reserved\n",
|
"%llu pinned %llu reserved\n",
|
||||||
|
|
@ -3342,7 +3412,10 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
|
||||||
btrfs_set_header_generation(buf, trans->transid);
|
btrfs_set_header_generation(buf, trans->transid);
|
||||||
btrfs_tree_lock(buf);
|
btrfs_tree_lock(buf);
|
||||||
clean_tree_block(trans, root, buf);
|
clean_tree_block(trans, root, buf);
|
||||||
|
|
||||||
|
btrfs_set_lock_blocking(buf);
|
||||||
btrfs_set_buffer_uptodate(buf);
|
btrfs_set_buffer_uptodate(buf);
|
||||||
|
|
||||||
if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
|
if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
|
||||||
set_extent_dirty(&root->dirty_log_pages, buf->start,
|
set_extent_dirty(&root->dirty_log_pages, buf->start,
|
||||||
buf->start + buf->len - 1, GFP_NOFS);
|
buf->start + buf->len - 1, GFP_NOFS);
|
||||||
|
|
@ -3351,6 +3424,7 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
|
||||||
buf->start + buf->len - 1, GFP_NOFS);
|
buf->start + buf->len - 1, GFP_NOFS);
|
||||||
}
|
}
|
||||||
trans->blocks_used++;
|
trans->blocks_used++;
|
||||||
|
/* this returns a buffer locked for blocking */
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3388,36 +3462,73 @@ int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
|
||||||
{
|
{
|
||||||
u64 leaf_owner;
|
u64 leaf_owner;
|
||||||
u64 leaf_generation;
|
u64 leaf_generation;
|
||||||
|
struct refsort *sorted;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
struct btrfs_file_extent_item *fi;
|
struct btrfs_file_extent_item *fi;
|
||||||
int i;
|
int i;
|
||||||
int nritems;
|
int nritems;
|
||||||
int ret;
|
int ret;
|
||||||
|
int refi = 0;
|
||||||
|
int slot;
|
||||||
|
|
||||||
BUG_ON(!btrfs_is_leaf(leaf));
|
BUG_ON(!btrfs_is_leaf(leaf));
|
||||||
nritems = btrfs_header_nritems(leaf);
|
nritems = btrfs_header_nritems(leaf);
|
||||||
leaf_owner = btrfs_header_owner(leaf);
|
leaf_owner = btrfs_header_owner(leaf);
|
||||||
leaf_generation = btrfs_header_generation(leaf);
|
leaf_generation = btrfs_header_generation(leaf);
|
||||||
|
|
||||||
|
sorted = kmalloc(sizeof(*sorted) * nritems, GFP_NOFS);
|
||||||
|
/* we do this loop twice. The first time we build a list
|
||||||
|
* of the extents we have a reference on, then we sort the list
|
||||||
|
* by bytenr. The second time around we actually do the
|
||||||
|
* extent freeing.
|
||||||
|
*/
|
||||||
for (i = 0; i < nritems; i++) {
|
for (i = 0; i < nritems; i++) {
|
||||||
u64 disk_bytenr;
|
u64 disk_bytenr;
|
||||||
cond_resched();
|
cond_resched();
|
||||||
|
|
||||||
btrfs_item_key_to_cpu(leaf, &key, i);
|
btrfs_item_key_to_cpu(leaf, &key, i);
|
||||||
|
|
||||||
|
/* only extents have references, skip everything else */
|
||||||
if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
|
if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
fi = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item);
|
fi = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item);
|
||||||
|
|
||||||
|
/* inline extents live in the btree, they don't have refs */
|
||||||
if (btrfs_file_extent_type(leaf, fi) ==
|
if (btrfs_file_extent_type(leaf, fi) ==
|
||||||
BTRFS_FILE_EXTENT_INLINE)
|
BTRFS_FILE_EXTENT_INLINE)
|
||||||
continue;
|
continue;
|
||||||
/*
|
|
||||||
* FIXME make sure to insert a trans record that
|
|
||||||
* repeats the snapshot del on crash
|
|
||||||
*/
|
|
||||||
disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
|
disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
|
||||||
|
|
||||||
|
/* holes don't have refs */
|
||||||
if (disk_bytenr == 0)
|
if (disk_bytenr == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
sorted[refi].bytenr = disk_bytenr;
|
||||||
|
sorted[refi].slot = i;
|
||||||
|
refi++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refi == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
sort(sorted, refi, sizeof(struct refsort), refsort_cmp, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < refi; i++) {
|
||||||
|
u64 disk_bytenr;
|
||||||
|
|
||||||
|
disk_bytenr = sorted[i].bytenr;
|
||||||
|
slot = sorted[i].slot;
|
||||||
|
|
||||||
|
cond_resched();
|
||||||
|
|
||||||
|
btrfs_item_key_to_cpu(leaf, &key, slot);
|
||||||
|
if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
|
||||||
|
|
||||||
ret = __btrfs_free_extent(trans, root, disk_bytenr,
|
ret = __btrfs_free_extent(trans, root, disk_bytenr,
|
||||||
btrfs_file_extent_disk_num_bytes(leaf, fi),
|
btrfs_file_extent_disk_num_bytes(leaf, fi),
|
||||||
leaf->start, leaf_owner, leaf_generation,
|
leaf->start, leaf_owner, leaf_generation,
|
||||||
|
|
@ -3428,6 +3539,8 @@ int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
|
||||||
wake_up(&root->fs_info->transaction_throttle);
|
wake_up(&root->fs_info->transaction_throttle);
|
||||||
cond_resched();
|
cond_resched();
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
|
kfree(sorted);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3437,9 +3550,25 @@ static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans,
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
struct btrfs_extent_info *info = ref->extents;
|
struct btrfs_extent_info *info;
|
||||||
|
struct refsort *sorted;
|
||||||
|
|
||||||
|
if (ref->nritems == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sorted = kmalloc(sizeof(*sorted) * ref->nritems, GFP_NOFS);
|
||||||
for (i = 0; i < ref->nritems; i++) {
|
for (i = 0; i < ref->nritems; i++) {
|
||||||
|
sorted[i].bytenr = ref->extents[i].bytenr;
|
||||||
|
sorted[i].slot = i;
|
||||||
|
}
|
||||||
|
sort(sorted, ref->nritems, sizeof(struct refsort), refsort_cmp, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the items in the ref were sorted when the ref was inserted
|
||||||
|
* into the ref cache, so this is already in order
|
||||||
|
*/
|
||||||
|
for (i = 0; i < ref->nritems; i++) {
|
||||||
|
info = ref->extents + sorted[i].slot;
|
||||||
ret = __btrfs_free_extent(trans, root, info->bytenr,
|
ret = __btrfs_free_extent(trans, root, info->bytenr,
|
||||||
info->num_bytes, ref->bytenr,
|
info->num_bytes, ref->bytenr,
|
||||||
ref->owner, ref->generation,
|
ref->owner, ref->generation,
|
||||||
|
|
@ -3453,6 +3582,7 @@ static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans,
|
||||||
info++;
|
info++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kfree(sorted);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3496,6 +3626,152 @@ static int drop_snap_lookup_refcount(struct btrfs_root *root, u64 start,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this is used while deleting old snapshots, and it drops the refs
|
||||||
|
* on a whole subtree starting from a level 1 node.
|
||||||
|
*
|
||||||
|
* The idea is to sort all the leaf pointers, and then drop the
|
||||||
|
* ref on all the leaves in order. Most of the time the leaves
|
||||||
|
* will have ref cache entries, so no leaf IOs will be required to
|
||||||
|
* find the extents they have references on.
|
||||||
|
*
|
||||||
|
* For each leaf, any references it has are also dropped in order
|
||||||
|
*
|
||||||
|
* This ends up dropping the references in something close to optimal
|
||||||
|
* order for reading and modifying the extent allocation tree.
|
||||||
|
*/
|
||||||
|
static noinline int drop_level_one_refs(struct btrfs_trans_handle *trans,
|
||||||
|
struct btrfs_root *root,
|
||||||
|
struct btrfs_path *path)
|
||||||
|
{
|
||||||
|
u64 bytenr;
|
||||||
|
u64 root_owner;
|
||||||
|
u64 root_gen;
|
||||||
|
struct extent_buffer *eb = path->nodes[1];
|
||||||
|
struct extent_buffer *leaf;
|
||||||
|
struct btrfs_leaf_ref *ref;
|
||||||
|
struct refsort *sorted = NULL;
|
||||||
|
int nritems = btrfs_header_nritems(eb);
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
int refi = 0;
|
||||||
|
int slot = path->slots[1];
|
||||||
|
u32 blocksize = btrfs_level_size(root, 0);
|
||||||
|
u32 refs;
|
||||||
|
|
||||||
|
if (nritems == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
root_owner = btrfs_header_owner(eb);
|
||||||
|
root_gen = btrfs_header_generation(eb);
|
||||||
|
sorted = kmalloc(sizeof(*sorted) * nritems, GFP_NOFS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* step one, sort all the leaf pointers so we don't scribble
|
||||||
|
* randomly into the extent allocation tree
|
||||||
|
*/
|
||||||
|
for (i = slot; i < nritems; i++) {
|
||||||
|
sorted[refi].bytenr = btrfs_node_blockptr(eb, i);
|
||||||
|
sorted[refi].slot = i;
|
||||||
|
refi++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nritems won't be zero, but if we're picking up drop_snapshot
|
||||||
|
* after a crash, slot might be > 0, so double check things
|
||||||
|
* just in case.
|
||||||
|
*/
|
||||||
|
if (refi == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
sort(sorted, refi, sizeof(struct refsort), refsort_cmp, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the first loop frees everything the leaves point to
|
||||||
|
*/
|
||||||
|
for (i = 0; i < refi; i++) {
|
||||||
|
u64 ptr_gen;
|
||||||
|
|
||||||
|
bytenr = sorted[i].bytenr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check the reference count on this leaf. If it is > 1
|
||||||
|
* we just decrement it below and don't update any
|
||||||
|
* of the refs the leaf points to.
|
||||||
|
*/
|
||||||
|
ret = drop_snap_lookup_refcount(root, bytenr, blocksize, &refs);
|
||||||
|
BUG_ON(ret);
|
||||||
|
if (refs != 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ptr_gen = btrfs_node_ptr_generation(eb, sorted[i].slot);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the leaf only had one reference, which means the
|
||||||
|
* only thing pointing to this leaf is the snapshot
|
||||||
|
* we're deleting. It isn't possible for the reference
|
||||||
|
* count to increase again later
|
||||||
|
*
|
||||||
|
* The reference cache is checked for the leaf,
|
||||||
|
* and if found we'll be able to drop any refs held by
|
||||||
|
* the leaf without needing to read it in.
|
||||||
|
*/
|
||||||
|
ref = btrfs_lookup_leaf_ref(root, bytenr);
|
||||||
|
if (ref && ref->generation != ptr_gen) {
|
||||||
|
btrfs_free_leaf_ref(root, ref);
|
||||||
|
ref = NULL;
|
||||||
|
}
|
||||||
|
if (ref) {
|
||||||
|
ret = cache_drop_leaf_ref(trans, root, ref);
|
||||||
|
BUG_ON(ret);
|
||||||
|
btrfs_remove_leaf_ref(root, ref);
|
||||||
|
btrfs_free_leaf_ref(root, ref);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* the leaf wasn't in the reference cache, so
|
||||||
|
* we have to read it.
|
||||||
|
*/
|
||||||
|
leaf = read_tree_block(root, bytenr, blocksize,
|
||||||
|
ptr_gen);
|
||||||
|
ret = btrfs_drop_leaf_ref(trans, root, leaf);
|
||||||
|
BUG_ON(ret);
|
||||||
|
free_extent_buffer(leaf);
|
||||||
|
}
|
||||||
|
atomic_inc(&root->fs_info->throttle_gen);
|
||||||
|
wake_up(&root->fs_info->transaction_throttle);
|
||||||
|
cond_resched();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* run through the loop again to free the refs on the leaves.
|
||||||
|
* This is faster than doing it in the loop above because
|
||||||
|
* the leaves are likely to be clustered together. We end up
|
||||||
|
* working in nice chunks on the extent allocation tree.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < refi; i++) {
|
||||||
|
bytenr = sorted[i].bytenr;
|
||||||
|
ret = __btrfs_free_extent(trans, root, bytenr,
|
||||||
|
blocksize, eb->start,
|
||||||
|
root_owner, root_gen, 0, 1);
|
||||||
|
BUG_ON(ret);
|
||||||
|
|
||||||
|
atomic_inc(&root->fs_info->throttle_gen);
|
||||||
|
wake_up(&root->fs_info->transaction_throttle);
|
||||||
|
cond_resched();
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
kfree(sorted);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* update the path to show we've processed the entire level 1
|
||||||
|
* node. This will get saved into the root's drop_snapshot_progress
|
||||||
|
* field so these drops are not repeated again if this transaction
|
||||||
|
* commits.
|
||||||
|
*/
|
||||||
|
path->slots[1] = nritems;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* helper function for drop_snapshot, this walks down the tree dropping ref
|
* helper function for drop_snapshot, this walks down the tree dropping ref
|
||||||
* counts as it goes.
|
* counts as it goes.
|
||||||
|
|
@ -3511,7 +3787,6 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
|
||||||
struct extent_buffer *next;
|
struct extent_buffer *next;
|
||||||
struct extent_buffer *cur;
|
struct extent_buffer *cur;
|
||||||
struct extent_buffer *parent;
|
struct extent_buffer *parent;
|
||||||
struct btrfs_leaf_ref *ref;
|
|
||||||
u32 blocksize;
|
u32 blocksize;
|
||||||
int ret;
|
int ret;
|
||||||
u32 refs;
|
u32 refs;
|
||||||
|
|
@ -3538,17 +3813,46 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
|
||||||
if (path->slots[*level] >=
|
if (path->slots[*level] >=
|
||||||
btrfs_header_nritems(cur))
|
btrfs_header_nritems(cur))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* the new code goes down to level 1 and does all the
|
||||||
|
* leaves pointed to that node in bulk. So, this check
|
||||||
|
* for level 0 will always be false.
|
||||||
|
*
|
||||||
|
* But, the disk format allows the drop_snapshot_progress
|
||||||
|
* field in the root to leave things in a state where
|
||||||
|
* a leaf will need cleaning up here. If someone crashes
|
||||||
|
* with the old code and then boots with the new code,
|
||||||
|
* we might find a leaf here.
|
||||||
|
*/
|
||||||
if (*level == 0) {
|
if (*level == 0) {
|
||||||
ret = btrfs_drop_leaf_ref(trans, root, cur);
|
ret = btrfs_drop_leaf_ref(trans, root, cur);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* once we get to level one, process the whole node
|
||||||
|
* at once, including everything below it.
|
||||||
|
*/
|
||||||
|
if (*level == 1) {
|
||||||
|
ret = drop_level_one_refs(trans, root, path);
|
||||||
|
BUG_ON(ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
bytenr = btrfs_node_blockptr(cur, path->slots[*level]);
|
bytenr = btrfs_node_blockptr(cur, path->slots[*level]);
|
||||||
ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]);
|
ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]);
|
||||||
blocksize = btrfs_level_size(root, *level - 1);
|
blocksize = btrfs_level_size(root, *level - 1);
|
||||||
|
|
||||||
ret = drop_snap_lookup_refcount(root, bytenr, blocksize, &refs);
|
ret = drop_snap_lookup_refcount(root, bytenr, blocksize, &refs);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if there is more than one reference, we don't need
|
||||||
|
* to read that node to drop any references it has. We
|
||||||
|
* just drop the ref we hold on that node and move on to the
|
||||||
|
* next slot in this level.
|
||||||
|
*/
|
||||||
if (refs != 1) {
|
if (refs != 1) {
|
||||||
parent = path->nodes[*level];
|
parent = path->nodes[*level];
|
||||||
root_owner = btrfs_header_owner(parent);
|
root_owner = btrfs_header_owner(parent);
|
||||||
|
|
@ -3567,46 +3871,12 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* at this point, we have a single ref, and since the
|
|
||||||
* only place referencing this extent is a dead root
|
|
||||||
* the reference count should never go higher.
|
|
||||||
* So, we don't need to check it again
|
|
||||||
*/
|
|
||||||
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
|
* we need to keep freeing things in the next level down.
|
||||||
* the ref should never go all the way down to 1
|
* read the block and loop around to process it
|
||||||
* at this point
|
|
||||||
*/
|
*/
|
||||||
ret = lookup_extent_ref(NULL, root, bytenr, blocksize,
|
next = read_tree_block(root, bytenr, blocksize, ptr_gen);
|
||||||
&refs);
|
|
||||||
BUG_ON(ret);
|
|
||||||
WARN_ON(refs != 1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
WARN_ON(*level <= 0);
|
WARN_ON(*level <= 0);
|
||||||
if (path->nodes[*level-1])
|
if (path->nodes[*level-1])
|
||||||
free_extent_buffer(path->nodes[*level-1]);
|
free_extent_buffer(path->nodes[*level-1]);
|
||||||
|
|
@ -3631,11 +3901,16 @@ out:
|
||||||
root_owner = btrfs_header_owner(parent);
|
root_owner = btrfs_header_owner(parent);
|
||||||
root_gen = btrfs_header_generation(parent);
|
root_gen = btrfs_header_generation(parent);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleanup and free the reference on the last node
|
||||||
|
* we processed
|
||||||
|
*/
|
||||||
ret = __btrfs_free_extent(trans, root, bytenr, blocksize,
|
ret = __btrfs_free_extent(trans, root, bytenr, blocksize,
|
||||||
parent->start, root_owner, root_gen,
|
parent->start, root_owner, root_gen,
|
||||||
*level, 1);
|
*level, 1);
|
||||||
free_extent_buffer(path->nodes[*level]);
|
free_extent_buffer(path->nodes[*level]);
|
||||||
path->nodes[*level] = NULL;
|
path->nodes[*level] = NULL;
|
||||||
|
|
||||||
*level += 1;
|
*level += 1;
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
||||||
|
|
@ -3687,6 +3962,7 @@ static noinline int walk_down_subtree(struct btrfs_trans_handle *trans,
|
||||||
|
|
||||||
next = read_tree_block(root, bytenr, blocksize, ptr_gen);
|
next = read_tree_block(root, bytenr, blocksize, ptr_gen);
|
||||||
btrfs_tree_lock(next);
|
btrfs_tree_lock(next);
|
||||||
|
btrfs_set_lock_blocking(next);
|
||||||
|
|
||||||
ret = btrfs_lookup_extent_ref(trans, root, bytenr, blocksize,
|
ret = btrfs_lookup_extent_ref(trans, root, bytenr, blocksize,
|
||||||
&refs);
|
&refs);
|
||||||
|
|
@ -3754,6 +4030,13 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
|
||||||
if (slot < btrfs_header_nritems(path->nodes[i]) - 1) {
|
if (slot < btrfs_header_nritems(path->nodes[i]) - 1) {
|
||||||
struct extent_buffer *node;
|
struct extent_buffer *node;
|
||||||
struct btrfs_disk_key disk_key;
|
struct btrfs_disk_key disk_key;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* there is more work to do in this level.
|
||||||
|
* Update the drop_progress marker to reflect
|
||||||
|
* the work we've done so far, and then bump
|
||||||
|
* the slot number
|
||||||
|
*/
|
||||||
node = path->nodes[i];
|
node = path->nodes[i];
|
||||||
path->slots[i]++;
|
path->slots[i]++;
|
||||||
*level = i;
|
*level = i;
|
||||||
|
|
@ -3765,6 +4048,11 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
struct extent_buffer *parent;
|
struct extent_buffer *parent;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this whole node is done, free our reference
|
||||||
|
* on it and go up one level
|
||||||
|
*/
|
||||||
if (path->nodes[*level] == root->node)
|
if (path->nodes[*level] == root->node)
|
||||||
parent = path->nodes[*level];
|
parent = path->nodes[*level];
|
||||||
else
|
else
|
||||||
|
|
@ -4444,7 +4732,7 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans,
|
||||||
u64 lock_end = 0;
|
u64 lock_end = 0;
|
||||||
u64 num_bytes;
|
u64 num_bytes;
|
||||||
u64 ext_offset;
|
u64 ext_offset;
|
||||||
u64 first_pos;
|
u64 search_end = (u64)-1;
|
||||||
u32 nritems;
|
u32 nritems;
|
||||||
int nr_scaned = 0;
|
int nr_scaned = 0;
|
||||||
int extent_locked = 0;
|
int extent_locked = 0;
|
||||||
|
|
@ -4452,7 +4740,6 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memcpy(&key, leaf_key, sizeof(key));
|
memcpy(&key, leaf_key, sizeof(key));
|
||||||
first_pos = INT_LIMIT(loff_t) - extent_key->offset;
|
|
||||||
if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS) {
|
if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS) {
|
||||||
if (key.objectid < ref_path->owner_objectid ||
|
if (key.objectid < ref_path->owner_objectid ||
|
||||||
(key.objectid == ref_path->owner_objectid &&
|
(key.objectid == ref_path->owner_objectid &&
|
||||||
|
|
@ -4501,7 +4788,7 @@ next:
|
||||||
if ((key.objectid > ref_path->owner_objectid) ||
|
if ((key.objectid > ref_path->owner_objectid) ||
|
||||||
(key.objectid == ref_path->owner_objectid &&
|
(key.objectid == ref_path->owner_objectid &&
|
||||||
key.type > BTRFS_EXTENT_DATA_KEY) ||
|
key.type > BTRFS_EXTENT_DATA_KEY) ||
|
||||||
(key.offset >= first_pos + extent_key->offset))
|
key.offset >= search_end)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4534,8 +4821,10 @@ next:
|
||||||
num_bytes = btrfs_file_extent_num_bytes(leaf, fi);
|
num_bytes = btrfs_file_extent_num_bytes(leaf, fi);
|
||||||
ext_offset = btrfs_file_extent_offset(leaf, fi);
|
ext_offset = btrfs_file_extent_offset(leaf, fi);
|
||||||
|
|
||||||
if (first_pos > key.offset - ext_offset)
|
if (search_end == (u64)-1) {
|
||||||
first_pos = key.offset - ext_offset;
|
search_end = key.offset - ext_offset +
|
||||||
|
btrfs_file_extent_ram_bytes(leaf, fi);
|
||||||
|
}
|
||||||
|
|
||||||
if (!extent_locked) {
|
if (!extent_locked) {
|
||||||
lock_start = key.offset;
|
lock_start = key.offset;
|
||||||
|
|
@ -4724,7 +5013,7 @@ next:
|
||||||
}
|
}
|
||||||
skip:
|
skip:
|
||||||
if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS &&
|
if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS &&
|
||||||
key.offset >= first_pos + extent_key->offset)
|
key.offset >= search_end)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cond_resched();
|
cond_resched();
|
||||||
|
|
@ -4778,6 +5067,7 @@ int btrfs_reloc_tree_cache_ref(struct btrfs_trans_handle *trans,
|
||||||
ref->bytenr = buf->start;
|
ref->bytenr = buf->start;
|
||||||
ref->owner = btrfs_header_owner(buf);
|
ref->owner = btrfs_header_owner(buf);
|
||||||
ref->generation = btrfs_header_generation(buf);
|
ref->generation = btrfs_header_generation(buf);
|
||||||
|
|
||||||
ret = btrfs_add_leaf_ref(root, ref, 0);
|
ret = btrfs_add_leaf_ref(root, ref, 0);
|
||||||
WARN_ON(ret);
|
WARN_ON(ret);
|
||||||
btrfs_free_leaf_ref(root, ref);
|
btrfs_free_leaf_ref(root, ref);
|
||||||
|
|
@ -5957,9 +6247,11 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
|
||||||
path = btrfs_alloc_path();
|
path = btrfs_alloc_path();
|
||||||
BUG_ON(!path);
|
BUG_ON(!path);
|
||||||
|
|
||||||
btrfs_remove_free_space_cache(block_group);
|
spin_lock(&root->fs_info->block_group_cache_lock);
|
||||||
rb_erase(&block_group->cache_node,
|
rb_erase(&block_group->cache_node,
|
||||||
&root->fs_info->block_group_cache_tree);
|
&root->fs_info->block_group_cache_tree);
|
||||||
|
spin_unlock(&root->fs_info->block_group_cache_lock);
|
||||||
|
btrfs_remove_free_space_cache(block_group);
|
||||||
down_write(&block_group->space_info->groups_sem);
|
down_write(&block_group->space_info->groups_sem);
|
||||||
list_del(&block_group->list);
|
list_del(&block_group->list);
|
||||||
up_write(&block_group->space_info->groups_sem);
|
up_write(&block_group->space_info->groups_sem);
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <linux/swap.h>
|
#include <linux/swap.h>
|
||||||
#include <linux/version.h>
|
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
#include <linux/pagevec.h>
|
#include <linux/pagevec.h>
|
||||||
#include "extent_io.h"
|
#include "extent_io.h"
|
||||||
|
|
@ -31,7 +30,7 @@ static LIST_HEAD(buffers);
|
||||||
static LIST_HEAD(states);
|
static LIST_HEAD(states);
|
||||||
|
|
||||||
#define LEAK_DEBUG 0
|
#define LEAK_DEBUG 0
|
||||||
#ifdef LEAK_DEBUG
|
#if LEAK_DEBUG
|
||||||
static DEFINE_SPINLOCK(leak_lock);
|
static DEFINE_SPINLOCK(leak_lock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -120,7 +119,7 @@ void extent_io_tree_init(struct extent_io_tree *tree,
|
||||||
static struct extent_state *alloc_extent_state(gfp_t mask)
|
static struct extent_state *alloc_extent_state(gfp_t mask)
|
||||||
{
|
{
|
||||||
struct extent_state *state;
|
struct extent_state *state;
|
||||||
#ifdef LEAK_DEBUG
|
#if LEAK_DEBUG
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -130,7 +129,7 @@ static struct extent_state *alloc_extent_state(gfp_t mask)
|
||||||
state->state = 0;
|
state->state = 0;
|
||||||
state->private = 0;
|
state->private = 0;
|
||||||
state->tree = NULL;
|
state->tree = NULL;
|
||||||
#ifdef LEAK_DEBUG
|
#if LEAK_DEBUG
|
||||||
spin_lock_irqsave(&leak_lock, flags);
|
spin_lock_irqsave(&leak_lock, flags);
|
||||||
list_add(&state->leak_list, &states);
|
list_add(&state->leak_list, &states);
|
||||||
spin_unlock_irqrestore(&leak_lock, flags);
|
spin_unlock_irqrestore(&leak_lock, flags);
|
||||||
|
|
@ -145,11 +144,11 @@ static void free_extent_state(struct extent_state *state)
|
||||||
if (!state)
|
if (!state)
|
||||||
return;
|
return;
|
||||||
if (atomic_dec_and_test(&state->refs)) {
|
if (atomic_dec_and_test(&state->refs)) {
|
||||||
#ifdef LEAK_DEBUG
|
#if LEAK_DEBUG
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
#endif
|
#endif
|
||||||
WARN_ON(state->tree);
|
WARN_ON(state->tree);
|
||||||
#ifdef LEAK_DEBUG
|
#if LEAK_DEBUG
|
||||||
spin_lock_irqsave(&leak_lock, flags);
|
spin_lock_irqsave(&leak_lock, flags);
|
||||||
list_del(&state->leak_list);
|
list_del(&state->leak_list);
|
||||||
spin_unlock_irqrestore(&leak_lock, flags);
|
spin_unlock_irqrestore(&leak_lock, flags);
|
||||||
|
|
@ -2378,11 +2377,6 @@ static int extent_write_cache_pages(struct extent_io_tree *tree,
|
||||||
int scanned = 0;
|
int scanned = 0;
|
||||||
int range_whole = 0;
|
int range_whole = 0;
|
||||||
|
|
||||||
if (wbc->nonblocking && bdi_write_congested(bdi)) {
|
|
||||||
wbc->encountered_congestion = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pagevec_init(&pvec, 0);
|
pagevec_init(&pvec, 0);
|
||||||
if (wbc->range_cyclic) {
|
if (wbc->range_cyclic) {
|
||||||
index = mapping->writeback_index; /* Start from prev offset */
|
index = mapping->writeback_index; /* Start from prev offset */
|
||||||
|
|
@ -2855,6 +2849,98 @@ out:
|
||||||
return sector;
|
return sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||||
|
__u64 start, __u64 len, get_extent_t *get_extent)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u64 off = start;
|
||||||
|
u64 max = start + len;
|
||||||
|
u32 flags = 0;
|
||||||
|
u64 disko = 0;
|
||||||
|
struct extent_map *em = NULL;
|
||||||
|
int end = 0;
|
||||||
|
u64 em_start = 0, em_len = 0;
|
||||||
|
unsigned long emflags;
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
lock_extent(&BTRFS_I(inode)->io_tree, start, start + len,
|
||||||
|
GFP_NOFS);
|
||||||
|
em = get_extent(inode, NULL, 0, off, max - off, 0);
|
||||||
|
if (!em)
|
||||||
|
goto out;
|
||||||
|
if (IS_ERR(em)) {
|
||||||
|
ret = PTR_ERR(em);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
while (!end) {
|
||||||
|
off = em->start + em->len;
|
||||||
|
if (off >= max)
|
||||||
|
end = 1;
|
||||||
|
|
||||||
|
em_start = em->start;
|
||||||
|
em_len = em->len;
|
||||||
|
|
||||||
|
disko = 0;
|
||||||
|
flags = 0;
|
||||||
|
|
||||||
|
switch (em->block_start) {
|
||||||
|
case EXTENT_MAP_LAST_BYTE:
|
||||||
|
end = 1;
|
||||||
|
flags |= FIEMAP_EXTENT_LAST;
|
||||||
|
break;
|
||||||
|
case EXTENT_MAP_HOLE:
|
||||||
|
flags |= FIEMAP_EXTENT_UNWRITTEN;
|
||||||
|
break;
|
||||||
|
case EXTENT_MAP_INLINE:
|
||||||
|
flags |= (FIEMAP_EXTENT_DATA_INLINE |
|
||||||
|
FIEMAP_EXTENT_NOT_ALIGNED);
|
||||||
|
break;
|
||||||
|
case EXTENT_MAP_DELALLOC:
|
||||||
|
flags |= (FIEMAP_EXTENT_DELALLOC |
|
||||||
|
FIEMAP_EXTENT_UNKNOWN);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
disko = em->block_start;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags))
|
||||||
|
flags |= FIEMAP_EXTENT_ENCODED;
|
||||||
|
|
||||||
|
emflags = em->flags;
|
||||||
|
free_extent_map(em);
|
||||||
|
em = NULL;
|
||||||
|
|
||||||
|
if (!end) {
|
||||||
|
em = get_extent(inode, NULL, 0, off, max - off, 0);
|
||||||
|
if (!em)
|
||||||
|
goto out;
|
||||||
|
if (IS_ERR(em)) {
|
||||||
|
ret = PTR_ERR(em);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
emflags = em->flags;
|
||||||
|
}
|
||||||
|
if (test_bit(EXTENT_FLAG_VACANCY, &emflags)) {
|
||||||
|
flags |= FIEMAP_EXTENT_LAST;
|
||||||
|
end = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fiemap_fill_next_extent(fieinfo, em_start, disko,
|
||||||
|
em_len, flags);
|
||||||
|
if (ret)
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
out_free:
|
||||||
|
free_extent_map(em);
|
||||||
|
out:
|
||||||
|
unlock_extent(&BTRFS_I(inode)->io_tree, start, start + len,
|
||||||
|
GFP_NOFS);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct page *extent_buffer_page(struct extent_buffer *eb,
|
static inline struct page *extent_buffer_page(struct extent_buffer *eb,
|
||||||
unsigned long i)
|
unsigned long i)
|
||||||
{
|
{
|
||||||
|
|
@ -2892,15 +2978,17 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
|
||||||
gfp_t mask)
|
gfp_t mask)
|
||||||
{
|
{
|
||||||
struct extent_buffer *eb = NULL;
|
struct extent_buffer *eb = NULL;
|
||||||
#ifdef LEAK_DEBUG
|
#if LEAK_DEBUG
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
eb = kmem_cache_zalloc(extent_buffer_cache, mask);
|
eb = kmem_cache_zalloc(extent_buffer_cache, mask);
|
||||||
eb->start = start;
|
eb->start = start;
|
||||||
eb->len = len;
|
eb->len = len;
|
||||||
mutex_init(&eb->mutex);
|
spin_lock_init(&eb->lock);
|
||||||
#ifdef LEAK_DEBUG
|
init_waitqueue_head(&eb->lock_wq);
|
||||||
|
|
||||||
|
#if LEAK_DEBUG
|
||||||
spin_lock_irqsave(&leak_lock, flags);
|
spin_lock_irqsave(&leak_lock, flags);
|
||||||
list_add(&eb->leak_list, &buffers);
|
list_add(&eb->leak_list, &buffers);
|
||||||
spin_unlock_irqrestore(&leak_lock, flags);
|
spin_unlock_irqrestore(&leak_lock, flags);
|
||||||
|
|
@ -2912,7 +3000,7 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
|
||||||
|
|
||||||
static void __free_extent_buffer(struct extent_buffer *eb)
|
static void __free_extent_buffer(struct extent_buffer *eb)
|
||||||
{
|
{
|
||||||
#ifdef LEAK_DEBUG
|
#if LEAK_DEBUG
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
spin_lock_irqsave(&leak_lock, flags);
|
spin_lock_irqsave(&leak_lock, flags);
|
||||||
list_del(&eb->leak_list);
|
list_del(&eb->leak_list);
|
||||||
|
|
@ -2980,8 +3068,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,
|
||||||
unlock_page(p);
|
unlock_page(p);
|
||||||
}
|
}
|
||||||
if (uptodate)
|
if (uptodate)
|
||||||
eb->flags |= EXTENT_UPTODATE;
|
set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
|
||||||
eb->flags |= EXTENT_BUFFER_FILLED;
|
|
||||||
|
|
||||||
spin_lock(&tree->buffer_lock);
|
spin_lock(&tree->buffer_lock);
|
||||||
exists = buffer_tree_insert(tree, start, &eb->rb_node);
|
exists = buffer_tree_insert(tree, start, &eb->rb_node);
|
||||||
|
|
@ -3135,7 +3222,7 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
|
||||||
unsigned long num_pages;
|
unsigned long num_pages;
|
||||||
|
|
||||||
num_pages = num_extent_pages(eb->start, eb->len);
|
num_pages = num_extent_pages(eb->start, eb->len);
|
||||||
eb->flags &= ~EXTENT_UPTODATE;
|
clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
|
||||||
|
|
||||||
clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
|
clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
|
||||||
GFP_NOFS);
|
GFP_NOFS);
|
||||||
|
|
@ -3206,7 +3293,7 @@ int extent_buffer_uptodate(struct extent_io_tree *tree,
|
||||||
struct page *page;
|
struct page *page;
|
||||||
int pg_uptodate = 1;
|
int pg_uptodate = 1;
|
||||||
|
|
||||||
if (eb->flags & EXTENT_UPTODATE)
|
if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1,
|
ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1,
|
||||||
|
|
@ -3242,7 +3329,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
|
||||||
struct bio *bio = NULL;
|
struct bio *bio = NULL;
|
||||||
unsigned long bio_flags = 0;
|
unsigned long bio_flags = 0;
|
||||||
|
|
||||||
if (eb->flags & EXTENT_UPTODATE)
|
if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (test_range_bit(tree, eb->start, eb->start + eb->len - 1,
|
if (test_range_bit(tree, eb->start, eb->start + eb->len - 1,
|
||||||
|
|
@ -3273,7 +3360,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
|
||||||
}
|
}
|
||||||
if (all_uptodate) {
|
if (all_uptodate) {
|
||||||
if (start_i == 0)
|
if (start_i == 0)
|
||||||
eb->flags |= EXTENT_UPTODATE;
|
set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
|
||||||
goto unlock_exit;
|
goto unlock_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3309,7 +3396,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
eb->flags |= EXTENT_UPTODATE;
|
set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
unlock_exit:
|
unlock_exit:
|
||||||
|
|
@ -3406,7 +3493,6 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start,
|
||||||
unmap_extent_buffer(eb, eb->map_token, km);
|
unmap_extent_buffer(eb, eb->map_token, km);
|
||||||
eb->map_token = NULL;
|
eb->map_token = NULL;
|
||||||
save = 1;
|
save = 1;
|
||||||
WARN_ON(!mutex_is_locked(&eb->mutex));
|
|
||||||
}
|
}
|
||||||
err = map_private_extent_buffer(eb, start, min_len, token, map,
|
err = map_private_extent_buffer(eb, start, min_len, token, map,
|
||||||
map_start, map_len, km);
|
map_start, map_len, km);
|
||||||
|
|
|
||||||
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