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

This commit is contained in:
Ingo Molnar 2009-02-09 10:32:48 +01:00
commit 4ad476e11f
162 changed files with 3103 additions and 2049 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

175
drivers/rtc/rtc-dm355evm.c Normal file
View 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");

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More