summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-devices-firmware_node17
-rw-r--r--Makefile2
-rw-r--r--arch/arm/mach-orion5x/common.c7
-rw-r--r--arch/arm/mm/dma-mapping.c2
-rw-r--r--arch/um/include/asm/processor-generic.h9
-rw-r--r--arch/um/include/shared/common-offsets.h10
-rw-r--r--arch/um/include/shared/user.h11
-rw-r--r--arch/um/kernel/exec.c25
-rw-r--r--arch/um/kernel/process.c8
-rw-r--r--arch/um/kernel/signal.c6
-rw-r--r--arch/um/kernel/syscall.c24
-rw-r--r--arch/um/scripts/Makefile.rules2
-rw-r--r--arch/x86/um/Kconfig1
-rw-r--r--arch/x86/um/shared/sysdep/kernel-offsets.h3
-rw-r--r--arch/x86/um/shared/sysdep/syscalls.h2
-rw-r--r--arch/x86/um/signal.c6
-rw-r--r--arch/x86/um/sys_call_table_32.c2
-rw-r--r--arch/x86/um/syscalls_32.c27
-rw-r--r--arch/x86/um/syscalls_64.c23
-rw-r--r--drivers/acpi/acpica/Makefile1
-rw-r--r--drivers/acpi/acpica/achware.h3
-rw-r--r--drivers/acpi/acpica/aclocal.h23
-rw-r--r--drivers/acpi/acpica/acmacros.h29
-rw-r--r--drivers/acpi/acpica/dswload.c14
-rw-r--r--drivers/acpi/acpica/dswload2.c14
-rw-r--r--drivers/acpi/acpica/evgpe.c24
-rw-r--r--drivers/acpi/acpica/evxfgpe.c3
-rw-r--r--drivers/acpi/acpica/hwgpe.c15
-rw-r--r--drivers/acpi/acpica/hwxfsleep.c1
-rw-r--r--drivers/acpi/acpica/nsdump.c2
-rw-r--r--drivers/acpi/acpica/tbinstal.c20
-rw-r--r--drivers/acpi/acpica/tbxface.c41
-rw-r--r--drivers/acpi/acpica/utosi.c1
-rw-r--r--drivers/acpi/acpica/utxface.c354
-rw-r--r--drivers/acpi/acpica/utxfinit.c317
-rw-r--r--drivers/acpi/bus.c8
-rw-r--r--drivers/acpi/button.c13
-rw-r--r--drivers/acpi/fan.c22
-rw-r--r--drivers/acpi/glue.c135
-rw-r--r--drivers/acpi/hed.c20
-rw-r--r--drivers/acpi/proc.c57
-rw-r--r--drivers/acpi/sbshc.c18
-rw-r--r--drivers/acpi/scan.c56
-rw-r--r--drivers/acpi/tables.c18
-rw-r--r--drivers/acpi/utils.c11
-rw-r--r--drivers/block/nvme.c153
-rw-r--r--drivers/edac/i3200_edac.c2
-rw-r--r--drivers/edac/i5000_edac.c4
-rw-r--r--drivers/edac/sb_edac.c7
-rw-r--r--drivers/gpio/gpio-lpc32xx.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fb.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fifo.c3
-rw-r--r--drivers/gpu/drm/nouveau/nve0_fifo.c3
-rw-r--r--drivers/gpu/drm/udl/udl_connector.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fence.c2
-rw-r--r--drivers/i2c/busses/i2c-scmi.c14
-rw-r--r--drivers/input/misc/atlas_btns.c17
-rw-r--r--drivers/iommu/amd_iommu.c6
-rw-r--r--drivers/md/dm-mpath.c11
-rw-r--r--drivers/md/dm-table.c61
-rw-r--r--drivers/md/dm-thin.c135
-rw-r--r--drivers/md/dm-verity.c8
-rw-r--r--drivers/md/dm.c71
-rw-r--r--drivers/md/dm.h1
-rw-r--r--drivers/md/raid10.c8
-rw-r--r--drivers/md/raid5.c1
-rw-r--r--drivers/mtd/mtdchar.c48
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c2
-rw-r--r--drivers/net/ethernet/octeon/octeon_mgmt.c4
-rw-r--r--drivers/net/ethernet/pasemi/pasemi_mac.c4
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c4
-rw-r--r--drivers/net/phy/smsc.c28
-rw-r--r--drivers/net/team/team.c12
-rw-r--r--drivers/net/usb/smsc75xx.c1
-rw-r--r--drivers/platform/x86/hp_accel.c25
-rw-r--r--drivers/platform/x86/ideapad-laptop.c14
-rw-r--r--drivers/platform/x86/topstar-laptop.c22
-rw-r--r--drivers/platform/x86/toshiba_bluetooth.c22
-rw-r--r--drivers/platform/x86/xo15-ebook.c14
-rw-r--r--drivers/pnp/pnpacpi/core.c7
-rw-r--r--drivers/usb/core/devices.c2
-rw-r--r--drivers/usb/core/hcd.c6
-rw-r--r--drivers/usb/core/usb-acpi.c5
-rw-r--r--drivers/usb/host/ohci-at91.c3
-rw-r--r--fs/dcache.c8
-rw-r--r--fs/lockd/svclock.c3
-rw-r--r--fs/namespace.c10
-rw-r--r--include/acpi/acbuffer.h235
-rw-r--r--include/acpi/acnames.h3
-rw-r--r--include/acpi/acpi_bus.h60
-rw-r--r--include/acpi/acpixf.h7
-rw-r--r--include/acpi/actbl.h60
-rw-r--r--include/acpi/actbl1.h16
-rw-r--r--include/acpi/actbl2.h123
-rw-r--r--include/acpi/actbl3.h13
-rw-r--r--include/acpi/actypes.h7
-rw-r--r--include/linux/iommu.h42
-rw-r--r--include/linux/nvme.h2
-rw-r--r--mm/huge_memory.c1
-rw-r--r--net/ipv4/inetpeer.c5
-rw-r--r--net/l2tp/l2tp_netlink.c12
-rw-r--r--net/netfilter/xt_limit.c8
-rw-r--r--sound/soc/codecs/wm2000.c2
-rw-r--r--sound/usb/endpoint.c8
-rw-r--r--tools/power/acpi/Makefile18
-rw-r--r--tools/power/acpi/acpidump.859
-rw-r--r--tools/power/acpi/acpidump.c560
-rw-r--r--tools/power/x86/turbostat/turbostat.855
-rw-r--r--tools/power/x86/turbostat/turbostat.c214
110 files changed, 2635 insertions, 1048 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-firmware_node b/Documentation/ABI/testing/sysfs-devices-firmware_node
new file mode 100644
index 000000000000..46badc9ea284
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-firmware_node
@@ -0,0 +1,17 @@
+What: /sys/devices/.../firmware_node/
+Date: September 2012
+Contact: <>
+Description:
+ The /sys/devices/.../firmware_node directory contains attributes
+ allowing the user space to check and modify some firmware
+ related properties of given device.
+
+What: /sys/devices/.../firmware_node/description
+Date: September 2012
+Contact: Lance Ortiz <lance.ortiz@hp.com>
+Description:
+ The /sys/devices/.../firmware/description attribute contains a string
+ that describes the device as provided by the _STR method in the ACPI
+ namespace. This attribute is read-only. If the device does not have
+ an _STR method associated with it in the ACPI namespace, this
+ attribute is not present.
diff --git a/Makefile b/Makefile
index a3c11d589681..bb9fff26f078 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 3
PATCHLEVEL = 6
SUBLEVEL = 0
-EXTRAVERSION = -rc7
+EXTRAVERSION =
NAME = Terrified Chipmunk
# *DOCUMENTATION*
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 410291c67666..a6cd14ab1e4e 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -204,6 +204,13 @@ void __init orion5x_wdt_init(void)
void __init orion5x_init_early(void)
{
orion_time_set_base(TIMER_VIRT_BASE);
+
+ /*
+ * Some Orion5x devices allocate their coherent buffers from atomic
+ * context. Increase size of atomic coherent pool to make sure such
+ * the allocations won't fail.
+ */
+ init_dma_coherent_pool_size(SZ_1M);
}
int orion5x_tclk;
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index e59c4ab71bcb..13f555d62491 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -346,6 +346,8 @@ static int __init atomic_pool_init(void)
(unsigned)pool->size / 1024);
return 0;
}
+
+ kfree(pages);
no_pages:
kfree(bitmap);
no_bitmap:
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h
index 69f1c57a8d0d..33a6a2423bd2 100644
--- a/arch/um/include/asm/processor-generic.h
+++ b/arch/um/include/asm/processor-generic.h
@@ -20,14 +20,6 @@ struct mm_struct;
struct thread_struct {
struct task_struct *saved_task;
- /*
- * This flag is set to 1 before calling do_fork (and analyzed in
- * copy_thread) to mark that we are begin called from userspace (fork /
- * vfork / clone), and reset to 0 after. It is left to 0 when called
- * from kernelspace (i.e. kernel_thread() or fork_idle(),
- * as of 2.6.11).
- */
- int forking;
struct pt_regs regs;
int singlestep_syscall;
void *fault_addr;
@@ -58,7 +50,6 @@ struct thread_struct {
#define INIT_THREAD \
{ \
- .forking = 0, \
.regs = EMPTY_REGS, \
.fault_addr = NULL, \
.prev_sched = NULL, \
diff --git a/arch/um/include/shared/common-offsets.h b/arch/um/include/shared/common-offsets.h
index 40db8f71deae..2df313b6a586 100644
--- a/arch/um/include/shared/common-offsets.h
+++ b/arch/um/include/shared/common-offsets.h
@@ -7,16 +7,6 @@ DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK);
DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT);
DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
-DEFINE_STR(UM_KERN_EMERG, KERN_EMERG);
-DEFINE_STR(UM_KERN_ALERT, KERN_ALERT);
-DEFINE_STR(UM_KERN_CRIT, KERN_CRIT);
-DEFINE_STR(UM_KERN_ERR, KERN_ERR);
-DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
-DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
-DEFINE_STR(UM_KERN_INFO, KERN_INFO);
-DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
-DEFINE_STR(UM_KERN_CONT, KERN_CONT);
-
DEFINE(UM_ELF_CLASS, ELF_CLASS);
DEFINE(UM_ELFCLASS32, ELFCLASS32);
DEFINE(UM_ELFCLASS64, ELFCLASS64);
diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h
index 4fa82c055aab..cef068563336 100644
--- a/arch/um/include/shared/user.h
+++ b/arch/um/include/shared/user.h
@@ -26,6 +26,17 @@
extern void panic(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
+/* Requires preincluding include/linux/kern_levels.h */
+#define UM_KERN_EMERG KERN_EMERG
+#define UM_KERN_ALERT KERN_ALERT
+#define UM_KERN_CRIT KERN_CRIT
+#define UM_KERN_ERR KERN_ERR
+#define UM_KERN_WARNING KERN_WARNING
+#define UM_KERN_NOTICE KERN_NOTICE
+#define UM_KERN_INFO KERN_INFO
+#define UM_KERN_DEBUG KERN_DEBUG
+#define UM_KERN_CONT KERN_CONT
+
#ifdef UML_CONFIG_PRINTK
extern int printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 6cade9366364..8c82786da823 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -39,34 +39,21 @@ void flush_thread(void)
void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
{
+ get_safe_registers(regs->regs.gp, regs->regs.fp);
PT_REGS_IP(regs) = eip;
PT_REGS_SP(regs) = esp;
-}
-EXPORT_SYMBOL(start_thread);
-
-static long execve1(const char *file,
- const char __user *const __user *argv,
- const char __user *const __user *env)
-{
- long error;
-
- error = do_execve(file, argv, env, &current->thread.regs);
- if (error == 0) {
- task_lock(current);
- current->ptrace &= ~PT_DTRACE;
+ current->ptrace &= ~PT_DTRACE;
#ifdef SUBARCH_EXECVE1
- SUBARCH_EXECVE1(&current->thread.regs.regs);
+ SUBARCH_EXECVE1(regs->regs);
#endif
- task_unlock(current);
- }
- return error;
}
+EXPORT_SYMBOL(start_thread);
long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env)
{
long err;
- err = execve1(file, argv, env);
+ err = do_execve(file, argv, env, &current->thread.regs);
if (!err)
UML_LONGJMP(current->thread.exec_buf, 1);
return err;
@@ -81,7 +68,7 @@ long sys_execve(const char __user *file, const char __user *const __user *argv,
filename = getname(file);
error = PTR_ERR(filename);
if (IS_ERR(filename)) goto out;
- error = execve1(filename, argv, env);
+ error = do_execve(filename, argv, env, &current->thread.regs);
putname(filename);
out:
return error;
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 57fc7028714a..c5f5afa50745 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -181,11 +181,12 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
struct pt_regs *regs)
{
void (*handler)(void);
+ int kthread = current->flags & PF_KTHREAD;
int ret = 0;
p->thread = (struct thread_struct) INIT_THREAD;
- if (current->thread.forking) {
+ if (!kthread) {
memcpy(&p->thread.regs.regs, &regs->regs,
sizeof(p->thread.regs.regs));
PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0);
@@ -195,8 +196,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
handler = fork_handler;
arch_copy_thread(&current->thread.arch, &p->thread.arch);
- }
- else {
+ } else {
get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp);
p->thread.request.u.thread = current->thread.request.u.thread;
handler = new_thread_handler;
@@ -204,7 +204,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
new_thread(task_stack_page(p), &p->thread.switch_buf, handler);
- if (current->thread.forking) {
+ if (!kthread) {
clear_flushed_tls(p);
/*
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index 7362d58efc29..cc9c2350e417 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -22,9 +22,13 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
struct k_sigaction *ka, siginfo_t *info)
{
sigset_t *oldset = sigmask_to_save();
+ int singlestep = 0;
unsigned long sp;
int err;
+ if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
+ singlestep = 1;
+
/* Did we come from a system call? */
if (PT_REGS_SYSCALL_NR(regs) >= 0) {
/* If so, check system call restarting.. */
@@ -61,7 +65,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
if (err)
force_sigsegv(signr, current);
else
- signal_delivered(signr, info, ka, regs, 0);
+ signal_delivered(signr, info, ka, regs, singlestep);
}
static int kern_do_signal(struct pt_regs *regs)
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index f958cb876ee3..a4c6d8eee74c 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -17,25 +17,25 @@
long sys_fork(void)
{
- long ret;
-
- current->thread.forking = 1;
- ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
+ return do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
&current->thread.regs, 0, NULL, NULL);
- current->thread.forking = 0;
- return ret;
}
long sys_vfork(void)
{
- long ret;
-
- current->thread.forking = 1;
- ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
UPT_SP(&current->thread.regs.regs),
&current->thread.regs, 0, NULL, NULL);
- current->thread.forking = 0;
- return ret;
+}
+
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+ void __user *parent_tid, void __user *child_tid)
+{
+ if (!newsp)
+ newsp = UPT_SP(&current->thread.regs.regs);
+
+ return do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+ child_tid);
}
long old_mmap(unsigned long addr, unsigned long len,
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index d50270d26b42..15889df9b466 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS))
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS:.o=.%): \
- c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include user.h $(CFLAGS_$(basetarget).o)
+ c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include $(srctree)/include/linux/kern_levels.h -include user.h $(CFLAGS_$(basetarget).o)
# These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of
# using it directly.
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index 9926e11a772d..aeaff8bef2f1 100644
--- a/arch/x86/um/Kconfig
+++ b/arch/x86/um/Kconfig
@@ -21,6 +21,7 @@ config 64BIT
config X86_32
def_bool !64BIT
select HAVE_AOUT
+ select ARCH_WANT_IPC_PARSE_VERSION
config X86_64
def_bool 64BIT
diff --git a/arch/x86/um/shared/sysdep/kernel-offsets.h b/arch/x86/um/shared/sysdep/kernel-offsets.h
index 5868526b5eef..46a9df99f3c5 100644
--- a/arch/x86/um/shared/sysdep/kernel-offsets.h
+++ b/arch/x86/um/shared/sysdep/kernel-offsets.h
@@ -7,9 +7,6 @@
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-#define STR(x) #x
-#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
-
#define BLANK() asm volatile("\n->" : : )
#define OFFSET(sym, str, mem) \
diff --git a/arch/x86/um/shared/sysdep/syscalls.h b/arch/x86/um/shared/sysdep/syscalls.h
index bd9a89b67e41..ca255a805ed9 100644
--- a/arch/x86/um/shared/sysdep/syscalls.h
+++ b/arch/x86/um/shared/sysdep/syscalls.h
@@ -1,3 +1,5 @@
+extern long sys_clone(unsigned long clone_flags, unsigned long newsp,
+ void __user *parent_tid, void __user *child_tid);
#ifdef __i386__
#include "syscalls_32.h"
#else
diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c
index a508cea13503..ba7363ecf896 100644
--- a/arch/x86/um/signal.c
+++ b/arch/x86/um/signal.c
@@ -416,9 +416,6 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
PT_REGS_AX(regs) = (unsigned long) sig;
PT_REGS_DX(regs) = (unsigned long) 0;
PT_REGS_CX(regs) = (unsigned long) 0;
-
- if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
- ptrace_notify(SIGTRAP);
return 0;
}
@@ -466,9 +463,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
PT_REGS_AX(regs) = (unsigned long) sig;
PT_REGS_DX(regs) = (unsigned long) &frame->info;
PT_REGS_CX(regs) = (unsigned long) &frame->uc;
-
- if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
- ptrace_notify(SIGTRAP);
return 0;
}
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c
index 68d1dc91b37b..b5408cecac6c 100644
--- a/arch/x86/um/sys_call_table_32.c
+++ b/arch/x86/um/sys_call_table_32.c
@@ -28,7 +28,7 @@
#define ptregs_execve sys_execve
#define ptregs_iopl sys_iopl
#define ptregs_vm86old sys_vm86old
-#define ptregs_clone sys_clone
+#define ptregs_clone i386_clone
#define ptregs_vm86 sys_vm86
#define ptregs_sigaltstack sys_sigaltstack
#define ptregs_vfork sys_vfork
diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c
index b853e8600b9d..db444c7218fe 100644
--- a/arch/x86/um/syscalls_32.c
+++ b/arch/x86/um/syscalls_32.c
@@ -3,37 +3,24 @@
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/shm.h"
-#include "linux/ipc.h"
-#include "linux/syscalls.h"
-#include "asm/mman.h"
-#include "asm/uaccess.h"
-#include "asm/unistd.h"
+#include <linux/syscalls.h>
+#include <sysdep/syscalls.h>
/*
* The prototype on i386 is:
*
- * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
+ * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls
*
* and the "newtls" arg. on i386 is read by copy_thread directly from the
* register saved on the stack.
*/
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
- int __user *parent_tid, void *newtls, int __user *child_tid)
+long i386_clone(unsigned long clone_flags, unsigned long newsp,
+ int __user *parent_tid, void *newtls, int __user *child_tid)
{
- long ret;
-
- if (!newsp)
- newsp = UPT_SP(&current->thread.regs.regs);
-
- current->thread.forking = 1;
- ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
- child_tid);
- current->thread.forking = 0;
- return ret;
+ return sys_clone(clone_flags, newsp, parent_tid, child_tid);
}
+
long sys_sigaction(int sig, const struct old_sigaction __user *act,
struct old_sigaction __user *oact)
{
diff --git a/arch/x86/um/syscalls_64.c b/arch/x86/um/syscalls_64.c
index f3d82bb6e15a..adb08eb5c22a 100644
--- a/arch/x86/um/syscalls_64.c
+++ b/arch/x86/um/syscalls_64.c
@@ -5,12 +5,9 @@
* Licensed under the GPL
*/
-#include "linux/linkage.h"
-#include "linux/personality.h"
-#include "linux/utsname.h"
-#include "asm/prctl.h" /* XXX This should get the constants from libc */
-#include "asm/uaccess.h"
-#include "os.h"
+#include <linux/sched.h>
+#include <asm/prctl.h> /* XXX This should get the constants from libc */
+#include <os.h>
long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
{
@@ -79,20 +76,6 @@ long sys_arch_prctl(int code, unsigned long addr)
return arch_prctl(current, code, (unsigned long __user *) addr);
}
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
- void __user *parent_tid, void __user *child_tid)
-{
- long ret;
-
- if (!newsp)
- newsp = UPT_SP(&current->thread.regs.regs);
- current->thread.forking = 1;
- ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
- child_tid);
- current->thread.forking = 0;
- return ret;
-}
-
void arch_switch_to(struct task_struct *to)
{
if ((to->thread.arch.fs == 0) || (to->mm == NULL))
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index 0a1b3435f920..7f1d40797e80 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -158,5 +158,6 @@ acpi-y += \
utresrc.o \
utstate.o \
utxface.o \
+ utxfinit.o \
utxferror.o \
utxfmutex.o
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h
index 5de4ec72766d..d902d31abc6c 100644
--- a/drivers/acpi/acpica/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -110,8 +110,7 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width);
/*
* hwgpe - GPE support
*/
-u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
- struct acpi_gpe_register_info *gpe_register_info);
+u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info);
acpi_status
acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action);
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index cc80fe10e8ea..c816ee675094 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -707,15 +707,18 @@ union acpi_parse_value {
u8 disasm_opcode; /* Subtype used for disassembly */\
char aml_op_name[16]) /* Op name (debug only) */
-#define ACPI_DASM_BUFFER 0x00
-#define ACPI_DASM_RESOURCE 0x01
-#define ACPI_DASM_STRING 0x02
-#define ACPI_DASM_UNICODE 0x03
-#define ACPI_DASM_EISAID 0x04
-#define ACPI_DASM_MATCHOP 0x05
-#define ACPI_DASM_LNOT_PREFIX 0x06
-#define ACPI_DASM_LNOT_SUFFIX 0x07
-#define ACPI_DASM_IGNORE 0x08
+/* Flags for disasm_flags field above */
+
+#define ACPI_DASM_BUFFER 0x00 /* Buffer is a simple data buffer */
+#define ACPI_DASM_RESOURCE 0x01 /* Buffer is a Resource Descriptor */
+#define ACPI_DASM_STRING 0x02 /* Buffer is a ASCII string */
+#define ACPI_DASM_UNICODE 0x03 /* Buffer is a Unicode string */
+#define ACPI_DASM_PLD_METHOD 0x04 /* Buffer is a _PLD method bit-packed buffer */
+#define ACPI_DASM_EISAID 0x05 /* Integer is an EISAID */
+#define ACPI_DASM_MATCHOP 0x06 /* Parent opcode is a Match() operator */
+#define ACPI_DASM_LNOT_PREFIX 0x07 /* Start of a Lnot_equal (etc.) pair of opcodes */
+#define ACPI_DASM_LNOT_SUFFIX 0x08 /* End of a Lnot_equal (etc.) pair of opcodes */
+#define ACPI_DASM_IGNORE 0x09 /* Not used at this time */
/*
* Generic operation (for example: If, While, Store)
@@ -932,6 +935,7 @@ struct acpi_bit_register_info {
#define ACPI_OSI_WIN_VISTA_SP1 0x09
#define ACPI_OSI_WIN_VISTA_SP2 0x0A
#define ACPI_OSI_WIN_7 0x0B
+#define ACPI_OSI_WIN_8 0x0C
#define ACPI_ALWAYS_ILLEGAL 0x00
@@ -1024,6 +1028,7 @@ struct acpi_port_info {
****************************************************************************/
struct acpi_db_method_info {
+ acpi_handle method;
acpi_handle main_thread_gate;
acpi_handle thread_complete_gate;
acpi_thread_id *threads;
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h
index 832b6198652e..a7f68c47f517 100644
--- a/drivers/acpi/acpica/acmacros.h
+++ b/drivers/acpi/acpica/acmacros.h
@@ -277,10 +277,33 @@
/* Bitfields within ACPI registers */
-#define ACPI_REGISTER_PREPARE_BITS(val, pos, mask) ((val << pos) & mask)
-#define ACPI_REGISTER_INSERT_VALUE(reg, pos, mask, val) reg = (reg & (~(mask))) | ACPI_REGISTER_PREPARE_BITS(val, pos, mask)
+#define ACPI_REGISTER_PREPARE_BITS(val, pos, mask) \
+ ((val << pos) & mask)
-#define ACPI_INSERT_BITS(target, mask, source) target = ((target & (~(mask))) | (source & mask))
+#define ACPI_REGISTER_INSERT_VALUE(reg, pos, mask, val) \
+ reg = (reg & (~(mask))) | ACPI_REGISTER_PREPARE_BITS(val, pos, mask)
+
+#define ACPI_INSERT_BITS(target, mask, source) \
+ target = ((target & (~(mask))) | (source & mask))
+
+/* Generic bitfield macros and masks */
+
+#define ACPI_GET_BITS(source_ptr, position, mask) \
+ ((*source_ptr >> position) & mask)
+
+#define ACPI_SET_BITS(target_ptr, position, mask, value) \
+ (*target_ptr |= ((value & mask) << position))
+
+#define ACPI_1BIT_MASK 0x00000001
+#define ACPI_2BIT_MASK 0x00000003
+#define ACPI_3BIT_MASK 0x00000007
+#define ACPI_4BIT_MASK 0x0000000F
+#define ACPI_5BIT_MASK 0x0000001F
+#define ACPI_6BIT_MASK 0x0000003F
+#define ACPI_7BIT_MASK 0x0000007F
+#define ACPI_8BIT_MASK 0x000000FF
+#define ACPI_16BIT_MASK 0x0000FFFF
+#define ACPI_24BIT_MASK 0x00FFFFFF
/*
* An object of type struct acpi_namespace_node can appear in some contexts
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c
index 552aa3a50c84..557510084c7a 100644
--- a/drivers/acpi/acpica/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -230,6 +230,20 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
walk_state->scope_info->common.value = ACPI_TYPE_ANY;
break;
+ case ACPI_TYPE_METHOD:
+
+ /*
+ * Allow scope change to root during execution of module-level
+ * code. Root is typed METHOD during this time.
+ */
+ if ((node == acpi_gbl_root_node) &&
+ (walk_state->
+ parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
+ break;
+ }
+
+ /*lint -fallthrough */
+
default:
/* All other types are an error */
diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c
index ae7147724763..89c0114210c0 100644
--- a/drivers/acpi/acpica/dswload2.c
+++ b/drivers/acpi/acpica/dswload2.c
@@ -230,6 +230,20 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
walk_state->scope_info->common.value = ACPI_TYPE_ANY;
break;
+ case ACPI_TYPE_METHOD:
+
+ /*
+ * Allow scope change to root during execution of module-level
+ * code. Root is typed METHOD during this time.
+ */
+ if ((node == acpi_gbl_root_node) &&
+ (walk_state->
+ parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
+ break;
+ }
+
+ /*lint -fallthrough */
+
default:
/* All other types are an error */
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index afbd5cb391f6..ef0193d74b5d 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -80,8 +80,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
return_ACPI_STATUS(AE_NOT_EXIST);
}
- register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
- gpe_register_info);
+ register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
/* Clear the run bit up front */
@@ -379,6 +378,18 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
*/
if (!(gpe_register_info->enable_for_run |
gpe_register_info->enable_for_wake)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
+ "Ignore disabled registers for GPE%02X-GPE%02X: "
+ "RunEnable=%02X, WakeEnable=%02X\n",
+ gpe_register_info->
+ base_gpe_number,
+ gpe_register_info->
+ base_gpe_number +
+ (ACPI_GPE_REGISTER_WIDTH - 1),
+ gpe_register_info->
+ enable_for_run,
+ gpe_register_info->
+ enable_for_wake));
continue;
}
@@ -401,9 +412,14 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
}
ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
- "Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n",
+ "Read registers for GPE%02X-GPE%02X: Status=%02X, Enable=%02X, "
+ "RunEnable=%02X, WakeEnable=%02X\n",
gpe_register_info->base_gpe_number,
- status_reg, enable_reg));
+ gpe_register_info->base_gpe_number +
+ (ACPI_GPE_REGISTER_WIDTH - 1),
+ status_reg, enable_reg,
+ gpe_register_info->enable_for_run,
+ gpe_register_info->enable_for_wake));
/* Check if there is anything active at all in this register */
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index 6affbdb4b88c..87c5f2332260 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -357,8 +357,7 @@ acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 ac
goto unlock_and_exit;
}
- register_bit =
- acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
+ register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
/* Perform the action */
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index 25bd28c4ae8d..db4076580e2b 100644
--- a/drivers/acpi/acpica/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -60,7 +60,6 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
* FUNCTION: acpi_hw_get_gpe_register_bit
*
* PARAMETERS: gpe_event_info - Info block for the GPE
- * gpe_register_info - Info block for the GPE register
*
* RETURN: Register mask with a one in the GPE bit position
*
@@ -69,11 +68,10 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
*
******************************************************************************/
-u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
- struct acpi_gpe_register_info *gpe_register_info)
+u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info)
{
return (u32)1 << (gpe_event_info->gpe_number -
- gpe_register_info->base_gpe_number);
+ gpe_event_info->register_info->base_gpe_number);
}
/******************************************************************************
@@ -115,8 +113,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
/* Set or clear just the bit that corresponds to this GPE */
- register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
- gpe_register_info);
+ register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
switch (action) {
case ACPI_GPE_CONDITIONAL_ENABLE:
@@ -178,8 +175,7 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
- register_bit =
- acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
+ register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
status = acpi_hw_write(register_bit,
&gpe_register_info->status_address);
@@ -222,8 +218,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
/* Get the register bitmask for this GPE */
- register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
- gpe_register_info);
+ register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
/* GPE currently enabled? (enabled for runtime?) */
diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c
index 1f165a750ae2..0ff1ecea5c3a 100644
--- a/drivers/acpi/acpica/hwxfsleep.c
+++ b/drivers/acpi/acpica/hwxfsleep.c
@@ -381,7 +381,6 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)
* FUNCTION: acpi_leave_sleep_state_prep
*
* PARAMETERS: sleep_state - Which sleep state we are exiting
- * flags - ACPI_EXECUTE_BFS to run optional method
*
* RETURN: Status
*
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index 7ee4e6aeb0a2..2526aaf945ee 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -264,7 +264,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
switch (type) {
case ACPI_TYPE_PROCESSOR:
- acpi_os_printf("ID %X Len %.4X Addr %p\n",
+ acpi_os_printf("ID %02X Len %02X Addr %p\n",
obj_desc->processor.proc_id,
obj_desc->processor.length,
ACPI_CAST_PTR(void,
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
index 74f97d74db1c..70f9d787c82c 100644
--- a/drivers/acpi/acpica/tbinstal.c
+++ b/drivers/acpi/acpica/tbinstal.c
@@ -350,6 +350,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
acpi_status acpi_tb_resize_root_table_list(void)
{
struct acpi_table_desc *tables;
+ u32 table_count;
ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
@@ -363,8 +364,13 @@ acpi_status acpi_tb_resize_root_table_list(void)
/* Increase the Table Array size */
- tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list.
- max_table_count +
+ if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
+ table_count = acpi_gbl_root_table_list.max_table_count;
+ } else {
+ table_count = acpi_gbl_root_table_list.current_table_count;
+ }
+
+ tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count +
ACPI_ROOT_TABLE_SIZE_INCREMENT) *
sizeof(struct acpi_table_desc));
if (!tables) {
@@ -377,8 +383,8 @@ acpi_status acpi_tb_resize_root_table_list(void)
if (acpi_gbl_root_table_list.tables) {
ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
- (acpi_size) acpi_gbl_root_table_list.
- max_table_count * sizeof(struct acpi_table_desc));
+ (acpi_size) table_count *
+ sizeof(struct acpi_table_desc));
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
ACPI_FREE(acpi_gbl_root_table_list.tables);
@@ -386,9 +392,9 @@ acpi_status acpi_tb_resize_root_table_list(void)
}
acpi_gbl_root_table_list.tables = tables;
- acpi_gbl_root_table_list.max_table_count +=
- ACPI_ROOT_TABLE_SIZE_INCREMENT;
- acpi_gbl_root_table_list.flags |= (u8)ACPI_ROOT_ORIGIN_ALLOCATED;
+ acpi_gbl_root_table_list.max_table_count =
+ table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
+ acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c
index 29e51bc01383..21101262e47a 100644
--- a/drivers/acpi/acpica/tbxface.c
+++ b/drivers/acpi/acpica/tbxface.c
@@ -159,14 +159,12 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
* DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the
* root list from the previously provided scratch area. Should
* be called once dynamic memory allocation is available in the
- * kernel
+ * kernel.
*
******************************************************************************/
acpi_status acpi_reallocate_root_table(void)
{
- struct acpi_table_desc *tables;
- acpi_size new_size;
- acpi_size current_size;
+ acpi_status status;
ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
@@ -178,39 +176,10 @@ acpi_status acpi_reallocate_root_table(void)
return_ACPI_STATUS(AE_SUPPORT);
}
- /*
- * Get the current size of the root table and add the default
- * increment to create the new table size.
- */
- current_size = (acpi_size)
- acpi_gbl_root_table_list.current_table_count *
- sizeof(struct acpi_table_desc);
-
- new_size = current_size +
- (ACPI_ROOT_TABLE_SIZE_INCREMENT * sizeof(struct acpi_table_desc));
-
- /* Create new array and copy the old array */
-
- tables = ACPI_ALLOCATE_ZEROED(new_size);
- if (!tables) {
- return_ACPI_STATUS(AE_NO_MEMORY);
- }
+ acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE;
- ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, current_size);
-
- /*
- * Update the root table descriptor. The new size will be the current
- * number of tables plus the increment, independent of the reserved
- * size of the original table list.
- */
- acpi_gbl_root_table_list.tables = tables;
- acpi_gbl_root_table_list.max_table_count =
- acpi_gbl_root_table_list.current_table_count +
- ACPI_ROOT_TABLE_SIZE_INCREMENT;
- acpi_gbl_root_table_list.flags =
- ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE;
-
- return_ACPI_STATUS(AE_OK);
+ status = acpi_tb_resize_root_table_list();
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c
index 34ef0bd7e4b4..676285d6116d 100644
--- a/drivers/acpi/acpica/utosi.c
+++ b/drivers/acpi/acpica/utosi.c
@@ -73,6 +73,7 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = {
{"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */
{"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */
{"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */
+ {"Windows 2012", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8 and Server 2012 - Added 08/2012 */
/* Feature Group Strings */
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index 534179f1177b..b09632b4f5b3 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -1,6 +1,6 @@
/******************************************************************************
*
- * Module Name: utxface - External interfaces for "global" ACPI functions
+ * Module Name: utxface - External interfaces, miscellaneous utility functions
*
*****************************************************************************/
@@ -53,271 +53,6 @@
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utxface")
-#ifndef ACPI_ASL_COMPILER
-/*******************************************************************************
- *
- * FUNCTION: acpi_initialize_subsystem
- *
- * PARAMETERS: None
- *
- * RETURN: Status
- *
- * DESCRIPTION: Initializes all global variables. This is the first function
- * called, so any early initialization belongs here.
- *
- ******************************************************************************/
-acpi_status __init acpi_initialize_subsystem(void)
-{
- acpi_status status;
-
- ACPI_FUNCTION_TRACE(acpi_initialize_subsystem);
-
- acpi_gbl_startup_flags = ACPI_SUBSYSTEM_INITIALIZE;
- ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace());
-
- /* Initialize the OS-Dependent layer */
-
- status = acpi_os_initialize();
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization"));
- return_ACPI_STATUS(status);
- }
-
- /* Initialize all globals used by the subsystem */
-
- status = acpi_ut_init_globals();
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "During initialization of globals"));
- return_ACPI_STATUS(status);
- }
-
- /* Create the default mutex objects */
-
- status = acpi_ut_mutex_initialize();
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "During Global Mutex creation"));
- return_ACPI_STATUS(status);
- }
-
- /*
- * Initialize the namespace manager and
- * the root of the namespace tree
- */
- status = acpi_ns_root_initialize();
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "During Namespace initialization"));
- return_ACPI_STATUS(status);
- }
-
- /* Initialize the global OSI interfaces list with the static names */
-
- status = acpi_ut_initialize_interfaces();
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "During OSI interfaces initialization"));
- return_ACPI_STATUS(status);
- }
-
- /* If configured, initialize the AML debugger */
-
- ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
- return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_enable_subsystem
- *
- * PARAMETERS: flags - Init/enable Options
- *
- * RETURN: Status
- *
- * DESCRIPTION: Completes the subsystem initialization including hardware.
- * Puts system into ACPI mode if it isn't already.
- *
- ******************************************************************************/
-acpi_status acpi_enable_subsystem(u32 flags)
-{
- acpi_status status = AE_OK;
-
- ACPI_FUNCTION_TRACE(acpi_enable_subsystem);
-
-#if (!ACPI_REDUCED_HARDWARE)
-
- /* Enable ACPI mode */
-
- if (!(flags & ACPI_NO_ACPI_ENABLE)) {
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "[Init] Going into ACPI mode\n"));
-
- acpi_gbl_original_mode = acpi_hw_get_mode();
-
- status = acpi_enable();
- if (ACPI_FAILURE(status)) {
- ACPI_WARNING((AE_INFO, "AcpiEnable failed"));
- return_ACPI_STATUS(status);
- }
- }
-
- /*
- * Obtain a permanent mapping for the FACS. This is required for the
- * Global Lock and the Firmware Waking Vector
- */
- status = acpi_tb_initialize_facs();
- if (ACPI_FAILURE(status)) {
- ACPI_WARNING((AE_INFO, "Could not map the FACS table"));
- return_ACPI_STATUS(status);
- }
-#endif /* !ACPI_REDUCED_HARDWARE */
-
- /*
- * Install the default op_region handlers. These are installed unless
- * other handlers have already been installed via the
- * install_address_space_handler interface.
- */
- if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "[Init] Installing default address space handlers\n"));
-
- status = acpi_ev_install_region_handlers();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
-#if (!ACPI_REDUCED_HARDWARE)
- /*
- * Initialize ACPI Event handling (Fixed and General Purpose)
- *
- * Note1: We must have the hardware and events initialized before we can
- * execute any control methods safely. Any control method can require
- * ACPI hardware support, so the hardware must be fully initialized before
- * any method execution!
- *
- * Note2: Fixed events are initialized and enabled here. GPEs are
- * initialized, but cannot be enabled until after the hardware is
- * completely initialized (SCI and global_lock activated)
- */
- if (!(flags & ACPI_NO_EVENT_INIT)) {
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "[Init] Initializing ACPI events\n"));
-
- status = acpi_ev_initialize_events();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
-
- /*
- * Install the SCI handler and Global Lock handler. This completes the
- * hardware initialization.
- */
- if (!(flags & ACPI_NO_HANDLER_INIT)) {
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "[Init] Installing SCI/GL handlers\n"));
-
- status = acpi_ev_install_xrupt_handlers();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
-#endif /* !ACPI_REDUCED_HARDWARE */
-
- return_ACPI_STATUS(status);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_enable_subsystem)
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_initialize_objects
- *
- * PARAMETERS: flags - Init/enable Options
- *
- * RETURN: Status
- *
- * DESCRIPTION: Completes namespace initialization by initializing device
- * objects and executing AML code for Regions, buffers, etc.
- *
- ******************************************************************************/
-acpi_status acpi_initialize_objects(u32 flags)
-{
- acpi_status status = AE_OK;
-
- ACPI_FUNCTION_TRACE(acpi_initialize_objects);
-
- /*
- * Run all _REG methods
- *
- * Note: Any objects accessed by the _REG methods will be automatically
- * initialized, even if they contain executable AML (see the call to
- * acpi_ns_initialize_objects below).
- */
- if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "[Init] Executing _REG OpRegion methods\n"));
-
- status = acpi_ev_initialize_op_regions();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
-
- /*
- * Execute any module-level code that was detected during the table load
- * phase. Although illegal since ACPI 2.0, there are many machines that
- * contain this type of code. Each block of detected executable AML code
- * outside of any control method is wrapped with a temporary control
- * method object and placed on a global list. The methods on this list
- * are executed below.
- */
- acpi_ns_exec_module_code_list();
-
- /*
- * Initialize the objects that remain uninitialized. This runs the
- * executable AML that may be part of the declaration of these objects:
- * operation_regions, buffer_fields, Buffers, and Packages.
- */
- if (!(flags & ACPI_NO_OBJECT_INIT)) {
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "[Init] Completing Initialization of ACPI Objects\n"));
-
- status = acpi_ns_initialize_objects();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
-
- /*
- * Initialize all device objects in the namespace. This runs the device
- * _STA and _INI methods.
- */
- if (!(flags & ACPI_NO_DEVICE_INIT)) {
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "[Init] Initializing ACPI Devices\n"));
-
- status = acpi_ns_initialize_devices();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
-
- /*
- * Empty the caches (delete the cached objects) on the assumption that
- * the table load filled them up more than they will be at runtime --
- * thus wasting non-paged memory.
- */
- status = acpi_purge_cached_objects();
-
- acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK;
- return_ACPI_STATUS(status);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_initialize_objects)
-
-#endif
/*******************************************************************************
*
* FUNCTION: acpi_terminate
@@ -683,3 +418,90 @@ acpi_check_address_range(acpi_adr_space_type space_id,
ACPI_EXPORT_SYMBOL(acpi_check_address_range)
#endif /* !ACPI_ASL_COMPILER */
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_decode_pld_buffer
+ *
+ * PARAMETERS: in_buffer - Buffer returned by _PLD method
+ * length - Length of the in_buffer
+ * return_buffer - Where the decode buffer is returned
+ *
+ * RETURN: Status and the decoded _PLD buffer. User must deallocate
+ * the buffer via ACPI_FREE.
+ *
+ * DESCRIPTION: Decode the bit-packed buffer returned by the _PLD method into
+ * a local struct that is much more useful to an ACPI driver.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_decode_pld_buffer(u8 *in_buffer,
+ acpi_size length, struct acpi_pld_info ** return_buffer)
+{
+ struct acpi_pld_info *pld_info;
+ u32 *buffer = ACPI_CAST_PTR(u32, in_buffer);
+ u32 dword;
+
+ /* Parameter validation */
+
+ if (!in_buffer || !return_buffer || (length < 16)) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ pld_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pld_info));
+ if (!pld_info) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* First 32-bit DWord */
+
+ ACPI_MOVE_32_TO_32(&dword, &buffer[0]);
+ pld_info->revision = ACPI_PLD_GET_REVISION(&dword);
+ pld_info->ignore_color = ACPI_PLD_GET_IGNORE_COLOR(&dword);
+ pld_info->color = ACPI_PLD_GET_COLOR(&dword);
+
+ /* Second 32-bit DWord */
+
+ ACPI_MOVE_32_TO_32(&dword, &buffer[1]);
+ pld_info->width = ACPI_PLD_GET_WIDTH(&dword);
+ pld_info->height = ACPI_PLD_GET_HEIGHT(&dword);
+
+ /* Third 32-bit DWord */
+
+ ACPI_MOVE_32_TO_32(&dword, &buffer[2]);
+ pld_info->user_visible = ACPI_PLD_GET_USER_VISIBLE(&dword);
+ pld_info->dock = ACPI_PLD_GET_DOCK(&dword);
+ pld_info->lid = ACPI_PLD_GET_LID(&dword);
+ pld_info->panel = ACPI_PLD_GET_PANEL(&dword);
+ pld_info->vertical_position = ACPI_PLD_GET_VERTICAL(&dword);
+ pld_info->horizontal_position = ACPI_PLD_GET_HORIZONTAL(&dword);
+ pld_info->shape = ACPI_PLD_GET_SHAPE(&dword);
+ pld_info->group_orientation = ACPI_PLD_GET_ORIENTATION(&dword);
+ pld_info->group_token = ACPI_PLD_GET_TOKEN(&dword);
+ pld_info->group_position = ACPI_PLD_GET_POSITION(&dword);
+ pld_info->bay = ACPI_PLD_GET_BAY(&dword);
+
+ /* Fourth 32-bit DWord */
+
+ ACPI_MOVE_32_TO_32(&dword, &buffer[3]);
+ pld_info->ejectable = ACPI_PLD_GET_EJECTABLE(&dword);
+ pld_info->ospm_eject_required = ACPI_PLD_GET_OSPM_EJECT(&dword);
+ pld_info->cabinet_number = ACPI_PLD_GET_CABINET(&dword);
+ pld_info->card_cage_number = ACPI_PLD_GET_CARD_CAGE(&dword);
+ pld_info->reference = ACPI_PLD_GET_REFERENCE(&dword);
+ pld_info->rotation = ACPI_PLD_GET_ROTATION(&dword);
+ pld_info->order = ACPI_PLD_GET_ORDER(&dword);
+
+ if (length >= ACPI_PLD_BUFFER_SIZE) {
+
+ /* Fifth 32-bit DWord (Revision 2 of _PLD) */
+
+ ACPI_MOVE_32_TO_32(&dword, &buffer[4]);
+ pld_info->vertical_offset = ACPI_PLD_GET_VERT_OFFSET(&dword);
+ pld_info->horizontal_offset = ACPI_PLD_GET_HORIZ_OFFSET(&dword);
+ }
+
+ *return_buffer = pld_info;
+ return (AE_OK);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_decode_pld_buffer)
diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c
new file mode 100644
index 000000000000..14f523627a5e
--- /dev/null
+++ b/drivers/acpi/acpica/utxfinit.c
@@ -0,0 +1,317 @@
+/******************************************************************************
+ *
+ * Module Name: utxfinit - External interfaces for ACPICA initialization
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <linux/export.h>
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acevents.h"
+#include "acnamesp.h"
+#include "acdebug.h"
+#include "actables.h"
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("utxfinit")
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_initialize_subsystem
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Initializes all global variables. This is the first function
+ * called, so any early initialization belongs here.
+ *
+ ******************************************************************************/
+acpi_status acpi_initialize_subsystem(void)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(acpi_initialize_subsystem);
+
+ acpi_gbl_startup_flags = ACPI_SUBSYSTEM_INITIALIZE;
+ ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace());
+
+ /* Initialize the OS-Dependent layer */
+
+ status = acpi_os_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization"));
+ return_ACPI_STATUS(status);
+ }
+
+ /* Initialize all globals used by the subsystem */
+
+ status = acpi_ut_init_globals();
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During initialization of globals"));
+ return_ACPI_STATUS(status);
+ }
+
+ /* Create the default mutex objects */
+
+ status = acpi_ut_mutex_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During Global Mutex creation"));
+ return_ACPI_STATUS(status);
+ }
+
+ /*
+ * Initialize the namespace manager and
+ * the root of the namespace tree
+ */
+ status = acpi_ns_root_initialize();
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During Namespace initialization"));
+ return_ACPI_STATUS(status);
+ }
+
+ /* Initialize the global OSI interfaces list with the static names */
+
+ status = acpi_ut_initialize_interfaces();
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During OSI interfaces initialization"));
+ return_ACPI_STATUS(status);
+ }
+
+ /* If configured, initialize the AML debugger */
+
+ ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
+ return_ACPI_STATUS(status);
+}
+ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem)
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_enable_subsystem
+ *
+ * PARAMETERS: flags - Init/enable Options
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Completes the subsystem initialization including hardware.
+ * Puts system into ACPI mode if it isn't already.
+ *
+ ******************************************************************************/
+acpi_status acpi_enable_subsystem(u32 flags)
+{
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE(acpi_enable_subsystem);
+
+#if (!ACPI_REDUCED_HARDWARE)
+
+ /* Enable ACPI mode */
+
+ if (!(flags & ACPI_NO_ACPI_ENABLE)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Going into ACPI mode\n"));
+
+ acpi_gbl_original_mode = acpi_hw_get_mode();
+
+ status = acpi_enable();
+ if (ACPI_FAILURE(status)) {
+ ACPI_WARNING((AE_INFO, "AcpiEnable failed"));
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ /*
+ * Obtain a permanent mapping for the FACS. This is required for the
+ * Global Lock and the Firmware Waking Vector
+ */
+ status = acpi_tb_initialize_facs();
+ if (ACPI_FAILURE(status)) {
+ ACPI_WARNING((AE_INFO, "Could not map the FACS table"));
+ return_ACPI_STATUS(status);
+ }
+#endif /* !ACPI_REDUCED_HARDWARE */
+
+ /*
+ * Install the default op_region handlers. These are installed unless
+ * other handlers have already been installed via the
+ * install_address_space_handler interface.
+ */
+ if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Installing default address space handlers\n"));
+
+ status = acpi_ev_install_region_handlers();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+ }
+#if (!ACPI_REDUCED_HARDWARE)
+ /*
+ * Initialize ACPI Event handling (Fixed and General Purpose)
+ *
+ * Note1: We must have the hardware and events initialized before we can
+ * execute any control methods safely. Any control method can require
+ * ACPI hardware support, so the hardware must be fully initialized before
+ * any method execution!
+ *
+ * Note2: Fixed events are initialized and enabled here. GPEs are
+ * initialized, but cannot be enabled until after the hardware is
+ * completely initialized (SCI and global_lock activated) and the various
+ * initialization control methods are run (_REG, _STA, _INI) on the
+ * entire namespace.
+ */
+ if (!(flags & ACPI_NO_EVENT_INIT)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Initializing ACPI events\n"));
+
+ status = acpi_ev_initialize_events();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ /*
+ * Install the SCI handler and Global Lock handler. This completes the
+ * hardware initialization.
+ */
+ if (!(flags & ACPI_NO_HANDLER_INIT)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Installing SCI/GL handlers\n"));
+
+ status = acpi_ev_install_xrupt_handlers();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+ }
+#endif /* !ACPI_REDUCED_HARDWARE */
+
+ return_ACPI_STATUS(status);
+}
+ACPI_EXPORT_SYMBOL(acpi_enable_subsystem)
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_initialize_objects
+ *
+ * PARAMETERS: flags - Init/enable Options
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Completes namespace initialization by initializing device
+ * objects and executing AML code for Regions, buffers, etc.
+ *
+ ******************************************************************************/
+acpi_status acpi_initialize_objects(u32 flags)
+{
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE(acpi_initialize_objects);
+
+ /*
+ * Run all _REG methods
+ *
+ * Note: Any objects accessed by the _REG methods will be automatically
+ * initialized, even if they contain executable AML (see the call to
+ * acpi_ns_initialize_objects below).
+ */
+ if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Executing _REG OpRegion methods\n"));
+
+ status = acpi_ev_initialize_op_regions();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ /*
+ * Execute any module-level code that was detected during the table load
+ * phase. Although illegal since ACPI 2.0, there are many machines that
+ * contain this type of code. Each block of detected executable AML code
+ * outside of any control method is wrapped with a temporary control
+ * method object and placed on a global list. The methods on this list
+ * are executed below.
+ */
+ acpi_ns_exec_module_code_list();
+
+ /*
+ * Initialize the objects that remain uninitialized. This runs the
+ * executable AML that may be part of the declaration of these objects:
+ * operation_regions, buffer_fields, Buffers, and Packages.
+ */
+ if (!(flags & ACPI_NO_OBJECT_INIT)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Completing Initialization of ACPI Objects\n"));
+
+ status = acpi_ns_initialize_objects();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ /*
+ * Initialize all device objects in the namespace. This runs the device
+ * _STA and _INI methods.
+ */
+ if (!(flags & ACPI_NO_DEVICE_INIT)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[Init] Initializing ACPI Devices\n"));
+
+ status = acpi_ns_initialize_devices();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ /*
+ * Empty the caches (delete the cached objects) on the assumption that
+ * the table load filled them up more than they will be at runtime --
+ * thus wasting non-paged memory.
+ */
+ status = acpi_purge_cached_objects();
+
+ acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK;
+ return_ACPI_STATUS(status);
+}
+ACPI_EXPORT_SYMBOL(acpi_initialize_objects)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index e0596954290b..d59175efc428 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -994,8 +994,6 @@ static int __init acpi_bus_init(void)
status = acpi_ec_ecdt_probe();
/* Ignore result. Not having an ECDT is not fatal. */
- acpi_bus_osc_support();
-
status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n");
@@ -1003,6 +1001,12 @@ static int __init acpi_bus_init(void)
}
/*
+ * _OSC method may exist in module level code,
+ * so it must be run after ACPI_FULL_INITIALIZATION
+ */
+ acpi_bus_osc_support();
+
+ /*
* _PDC control method may load dynamic SSDT tables,
* and we need to install the table handler before that.
*/
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 314a3b84bbc7..f0d936b65e37 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -450,15 +450,4 @@ static int acpi_button_remove(struct acpi_device *device, int type)
return 0;
}
-static int __init acpi_button_init(void)
-{
- return acpi_bus_register_driver(&acpi_button_driver);
-}
-
-static void __exit acpi_button_exit(void)
-{
- acpi_bus_unregister_driver(&acpi_button_driver);
-}
-
-module_init(acpi_button_init);
-module_exit(acpi_button_exit);
+module_acpi_driver(acpi_button_driver);
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index bc36a476f1ab..3bd6a54702d6 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -212,24 +212,4 @@ static int acpi_fan_resume(struct device *dev)
}
#endif
-static int __init acpi_fan_init(void)
-{
- int result = 0;
-
- result = acpi_bus_register_driver(&acpi_fan_driver);
- if (result < 0)
- return -ENODEV;
-
- return 0;
-}
-
-static void __exit acpi_fan_exit(void)
-{
-
- acpi_bus_unregister_driver(&acpi_fan_driver);
-
- return;
-}
-
-module_init(acpi_fan_init);
-module_exit(acpi_fan_exit);
+module_acpi_driver(acpi_fan_driver);
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 243ee85e4d2e..d1a2d74033e9 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -25,6 +25,8 @@
static LIST_HEAD(bus_type_list);
static DECLARE_RWSEM(bus_type_sem);
+#define PHYSICAL_NODE_STRING "physical_node"
+
int register_acpi_bus_type(struct acpi_bus_type *type)
{
if (acpi_disabled)
@@ -124,84 +126,119 @@ acpi_handle acpi_get_child(acpi_handle parent, u64 address)
EXPORT_SYMBOL(acpi_get_child);
-/* Link ACPI devices with physical devices */
-static void acpi_glue_data_handler(acpi_handle handle,
- void *context)
-{
- /* we provide an empty handler */
-}
-
-/* Note: a success call will increase reference count by one */
-struct device *acpi_get_physical_device(acpi_handle handle)
-{
- acpi_status status;
- struct device *dev;
-
- status = acpi_get_data(handle, acpi_glue_data_handler, (void **)&dev);
- if (ACPI_SUCCESS(status))
- return get_device(dev);
- return NULL;
-}
-
-EXPORT_SYMBOL(acpi_get_physical_device);
-
static int acpi_bind_one(struct device *dev, acpi_handle handle)
{
struct acpi_device *acpi_dev;
acpi_status status;
+ struct acpi_device_physical_node *physical_node;
+ char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
+ int retval = -EINVAL;
if (dev->archdata.acpi_handle) {
dev_warn(dev, "Drivers changed 'acpi_handle'\n");
return -EINVAL;
}
+
get_device(dev);
- status = acpi_attach_data(handle, acpi_glue_data_handler, dev);
- if (ACPI_FAILURE(status)) {
- put_device(dev);
- return -EINVAL;
+ status = acpi_bus_get_device(handle, &acpi_dev);
+ if (ACPI_FAILURE(status))
+ goto err;
+
+ physical_node = kzalloc(sizeof(struct acpi_device_physical_node),
+ GFP_KERNEL);
+ if (!physical_node) {
+ retval = -ENOMEM;
+ goto err;
}
- dev->archdata.acpi_handle = handle;
- status = acpi_bus_get_device(handle, &acpi_dev);
- if (!ACPI_FAILURE(status)) {
- int ret;
-
- ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
- "firmware_node");
- ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
- "physical_node");
- if (acpi_dev->wakeup.flags.valid)
- device_set_wakeup_capable(dev, true);
+ mutex_lock(&acpi_dev->physical_node_lock);
+ /* allocate physical node id according to physical_node_id_bitmap */
+ physical_node->node_id =
+ find_first_zero_bit(acpi_dev->physical_node_id_bitmap,
+ ACPI_MAX_PHYSICAL_NODE);
+ if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
+ retval = -ENOSPC;
+ mutex_unlock(&acpi_dev->physical_node_lock);
+ goto err;
}
+ set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap);
+ physical_node->dev = dev;
+ list_add_tail(&physical_node->node, &acpi_dev->physical_node_list);
+ acpi_dev->physical_node_count++;
+ mutex_unlock(&acpi_dev->physical_node_lock);
+
+ dev->archdata.acpi_handle = handle;
+
+ if (!physical_node->node_id)
+ strcpy(physical_node_name, PHYSICAL_NODE_STRING);
+ else
+ sprintf(physical_node_name,
+ "physical_node%d", physical_node->node_id);
+ retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
+ physical_node_name);
+ retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
+ "firmware_node");
+
+ if (acpi_dev->wakeup.flags.valid)
+ device_set_wakeup_capable(dev, true);
+
return 0;
+
+ err:
+ put_device(dev);
+ return retval;
}
static int acpi_unbind_one(struct device *dev)
{
+ struct acpi_device_physical_node *entry;
+ struct acpi_device *acpi_dev;
+ acpi_status status;
+ struct list_head *node, *next;
+
if (!dev->archdata.acpi_handle)
return 0;
- if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
- struct acpi_device *acpi_dev;
- /* acpi_get_physical_device increase refcnt by one */
- put_device(dev);
+ status = acpi_bus_get_device(dev->archdata.acpi_handle,
+ &acpi_dev);
+ if (ACPI_FAILURE(status))
+ goto err;
- if (!acpi_bus_get_device(dev->archdata.acpi_handle,
- &acpi_dev)) {
- sysfs_remove_link(&dev->kobj, "firmware_node");
- sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node");
- }
+ mutex_lock(&acpi_dev->physical_node_lock);
+ list_for_each_safe(node, next, &acpi_dev->physical_node_list) {
+ char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
+
+ entry = list_entry(node, struct acpi_device_physical_node,
+ node);
+ if (entry->dev != dev)
+ continue;
+
+ list_del(node);
+ clear_bit(entry->node_id, acpi_dev->physical_node_id_bitmap);
- acpi_detach_data(dev->archdata.acpi_handle,
- acpi_glue_data_handler);
+ acpi_dev->physical_node_count--;
+
+ if (!entry->node_id)
+ strcpy(physical_node_name, PHYSICAL_NODE_STRING);
+ else
+ sprintf(physical_node_name,
+ "physical_node%d", entry->node_id);
+
+ sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name);
+ sysfs_remove_link(&dev->kobj, "firmware_node");
dev->archdata.acpi_handle = NULL;
/* acpi_bind_one increase refcnt by one */
put_device(dev);
- } else {
- dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
+ kfree(entry);
}
+ mutex_unlock(&acpi_dev->physical_node_lock);
+
return 0;
+
+err:
+ dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
+ return -EINVAL;
}
static int acpi_platform_notify(struct device *dev)
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
index d0c1967f7597..20a0f2c3ca3b 100644
--- a/drivers/acpi/hed.c
+++ b/drivers/acpi/hed.c
@@ -86,25 +86,7 @@ static struct acpi_driver acpi_hed_driver = {
.notify = acpi_hed_notify,
},
};
-
-static int __init acpi_hed_init(void)
-{
- if (acpi_disabled)
- return -ENODEV;
-
- if (acpi_bus_register_driver(&acpi_hed_driver) < 0)
- return -ENODEV;
-
- return 0;
-}
-
-static void __exit acpi_hed_exit(void)
-{
- acpi_bus_unregister_driver(&acpi_hed_driver);
-}
-
-module_init(acpi_hed_init);
-module_exit(acpi_hed_exit);
+module_acpi_driver(acpi_hed_driver);
ACPI_MODULE_NAME("hed");
MODULE_AUTHOR("Huang Ying");
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c
index 251c7b6273a9..27adb090bb30 100644
--- a/drivers/acpi/proc.c
+++ b/drivers/acpi/proc.c
@@ -302,26 +302,41 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
struct acpi_device *dev =
container_of(node, struct acpi_device, wakeup_list);
- struct device *ldev;
+ struct acpi_device_physical_node *entry;
if (!dev->wakeup.flags.valid)
continue;
- ldev = acpi_get_physical_device(dev->handle);
- seq_printf(seq, "%s\t S%d\t%c%-8s ",
+ seq_printf(seq, "%s\t S%d\t",
dev->pnp.bus_id,
- (u32) dev->wakeup.sleep_state,
- dev->wakeup.flags.run_wake ? '*' : ' ',
- (device_may_wakeup(&dev->dev)
- || (ldev && device_may_wakeup(ldev))) ?
- "enabled" : "disabled");
- if (ldev)
- seq_printf(seq, "%s:%s",
- ldev->bus ? ldev->bus->name : "no-bus",
- dev_name(ldev));
- seq_printf(seq, "\n");
- put_device(ldev);
-
+ (u32) dev->wakeup.sleep_state);
+
+ if (!dev->physical_node_count)
+ seq_printf(seq, "%c%-8s\n",
+ dev->wakeup.flags.run_wake ?
+ '*' : ' ', "disabled");
+ else {
+ struct device *ldev;
+ list_for_each_entry(entry, &dev->physical_node_list,
+ node) {
+ ldev = get_device(entry->dev);
+ if (!ldev)
+ continue;
+
+ if (&entry->node !=
+ dev->physical_node_list.next)
+ seq_printf(seq, "\t\t");
+
+ seq_printf(seq, "%c%-8s %s:%s\n",
+ dev->wakeup.flags.run_wake ? '*' : ' ',
+ (device_may_wakeup(&dev->dev) ||
+ (ldev && device_may_wakeup(ldev))) ?
+ "enabled" : "disabled",
+ ldev->bus ? ldev->bus->name :
+ "no-bus", dev_name(ldev));
+ put_device(ldev);
+ }
+ }
}
mutex_unlock(&acpi_device_lock);
return 0;
@@ -329,12 +344,14 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
static void physical_device_enable_wakeup(struct acpi_device *adev)
{
- struct device *dev = acpi_get_physical_device(adev->handle);
+ struct acpi_device_physical_node *entry;
- if (dev && device_can_wakeup(dev)) {
- bool enable = !device_may_wakeup(dev);
- device_set_wakeup_enable(dev, enable);
- }
+ list_for_each_entry(entry,
+ &adev->physical_node_list, node)
+ if (entry->dev && device_can_wakeup(entry->dev)) {
+ bool enable = !device_may_wakeup(entry->dev);
+ device_set_wakeup_enable(entry->dev, enable);
+ }
}
static ssize_t
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index f8d2a472795c..cf6129a8af7c 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -310,23 +310,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device, int type)
return 0;
}
-static int __init acpi_smb_hc_init(void)
-{
- int result;
-
- result = acpi_bus_register_driver(&acpi_smb_hc_driver);
- if (result < 0)
- return -ENODEV;
- return 0;
-}
-
-static void __exit acpi_smb_hc_exit(void)
-{
- acpi_bus_unregister_driver(&acpi_smb_hc_driver);
-}
-
-module_init(acpi_smb_hc_init);
-module_exit(acpi_smb_hc_exit);
+module_acpi_driver(acpi_smb_hc_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexey Starikovskiy");
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index d1ecca2b641a..1fcb8678665c 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -10,6 +10,7 @@
#include <linux/signal.h>
#include <linux/kthread.h>
#include <linux/dmi.h>
+#include <linux/nls.h>
#include <acpi/acpi_drivers.h>
@@ -232,8 +233,35 @@ end:
}
static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
+/* sysfs file that shows description text from the ACPI _STR method */
+static ssize_t description_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf) {
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ int result;
+
+ if (acpi_dev->pnp.str_obj == NULL)
+ return 0;
+
+ /*
+ * The _STR object contains a Unicode identifier for a device.
+ * We need to convert to utf-8 so it can be displayed.
+ */
+ result = utf16s_to_utf8s(
+ (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
+ acpi_dev->pnp.str_obj->buffer.length,
+ UTF16_LITTLE_ENDIAN, buf,
+ PAGE_SIZE);
+
+ buf[result++] = '\n';
+
+ return result;
+}
+static DEVICE_ATTR(description, 0444, description_show, NULL);
+
static int acpi_device_setup_files(struct acpi_device *dev)
{
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
acpi_handle temp;
int result = 0;
@@ -257,6 +285,21 @@ static int acpi_device_setup_files(struct acpi_device *dev)
goto end;
}
+ /*
+ * If device has _STR, 'description' file is created
+ */
+ status = acpi_get_handle(dev->handle, "_STR", &temp);
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_evaluate_object(dev->handle, "_STR",
+ NULL, &buffer);
+ if (ACPI_FAILURE(status))
+ buffer.pointer = NULL;
+ dev->pnp.str_obj = buffer.pointer;
+ result = device_create_file(&dev->dev, &dev_attr_description);
+ if (result)
+ goto end;
+ }
+
/*
* If device has _EJ0, 'eject' file is created that is used to trigger
* hot-removal function from userland.
@@ -274,8 +317,15 @@ static void acpi_device_remove_files(struct acpi_device *dev)
acpi_handle temp;
/*
- * If device has _EJ0, 'eject' file is created that is used to trigger
- * hot-removal function from userland.
+ * If device has _STR, remove 'description' file
+ */
+ status = acpi_get_handle(dev->handle, "_STR", &temp);
+ if (ACPI_SUCCESS(status)) {
+ kfree(dev->pnp.str_obj);
+ device_remove_file(&dev->dev, &dev_attr_description);
+ }
+ /*
+ * If device has _EJ0, remove 'eject' file.
*/
status = acpi_get_handle(dev->handle, "_EJ0", &temp);
if (ACPI_SUCCESS(status))
@@ -481,6 +531,8 @@ static int acpi_device_register(struct acpi_device *device)
INIT_LIST_HEAD(&device->children);
INIT_LIST_HEAD(&device->node);
INIT_LIST_HEAD(&device->wakeup_list);
+ INIT_LIST_HEAD(&device->physical_node_list);
+ mutex_init(&device->physical_node_lock);
new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
if (!new_bus_id) {
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index f336bca7c450..2572d9715bda 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -240,10 +240,17 @@ acpi_table_parse_entries(char *id,
table_end) {
if (entry->type == entry_id
&& (!max_entries || count++ < max_entries))
- if (handler(entry, table_end)) {
- early_acpi_os_unmap_memory((char *)table_header, tbl_size);
- return -EINVAL;
- }
+ if (handler(entry, table_end))
+ goto err;
+
+ /*
+ * If entry->length is 0, break from this loop to avoid
+ * infinite loop.
+ */
+ if (entry->length == 0) {
+ pr_err(PREFIX "[%4.4s:0x%02x] Invalid zero length\n", id, entry_id);
+ goto err;
+ }
entry = (struct acpi_subtable_header *)
((unsigned long)entry + entry->length);
@@ -255,6 +262,9 @@ acpi_table_parse_entries(char *id,
early_acpi_os_unmap_memory((char *)table_header, tbl_size);
return count;
+err:
+ early_acpi_os_unmap_memory((char *)table_header, tbl_size);
+ return -EINVAL;
}
int __init
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 3e87c9c538aa..462f7e300363 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -384,7 +384,7 @@ acpi_evaluate_reference(acpi_handle handle,
EXPORT_SYMBOL(acpi_evaluate_reference);
acpi_status
-acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld *pld)
+acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld)
{
acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -400,13 +400,16 @@ acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld *pld)
if (!output || output->type != ACPI_TYPE_PACKAGE
|| !output->package.count
|| output->package.elements[0].type != ACPI_TYPE_BUFFER
- || output->package.elements[0].buffer.length > sizeof(*pld)) {
+ || output->package.elements[0].buffer.length < ACPI_PLD_REV1_BUFFER_SIZE) {
status = AE_TYPE;
goto out;
}
- memcpy(pld, output->package.elements[0].buffer.pointer,
- output->package.elements[0].buffer.length);
+ status = acpi_decode_pld_buffer(
+ output->package.elements[0].buffer.pointer,
+ output->package.elements[0].buffer.length,
+ pld);
+
out:
kfree(buffer.pointer);
return status;
diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c
index 38a2d0631882..ad16c68c8645 100644
--- a/drivers/block/nvme.c
+++ b/drivers/block/nvme.c
@@ -79,6 +79,7 @@ struct nvme_dev {
char serial[20];
char model[40];
char firmware_rev[8];
+ u32 max_hw_sectors;
};
/*
@@ -835,15 +836,15 @@ static int nvme_identify(struct nvme_dev *dev, unsigned nsid, unsigned cns,
}
static int nvme_get_features(struct nvme_dev *dev, unsigned fid,
- unsigned dword11, dma_addr_t dma_addr)
+ unsigned nsid, dma_addr_t dma_addr)
{
struct nvme_command c;
memset(&c, 0, sizeof(c));
c.features.opcode = nvme_admin_get_features;
+ c.features.nsid = cpu_to_le32(nsid);
c.features.prp1 = cpu_to_le64(dma_addr);
c.features.fid = cpu_to_le32(fid);
- c.features.dword11 = cpu_to_le32(dword11);
return nvme_submit_admin_cmd(dev, &c, NULL);
}
@@ -862,11 +863,51 @@ static int nvme_set_features(struct nvme_dev *dev, unsigned fid,
return nvme_submit_admin_cmd(dev, &c, result);
}
+/**
+ * nvme_cancel_ios - Cancel outstanding I/Os
+ * @queue: The queue to cancel I/Os on
+ * @timeout: True to only cancel I/Os which have timed out
+ */
+static void nvme_cancel_ios(struct nvme_queue *nvmeq, bool timeout)
+{
+ int depth = nvmeq->q_depth - 1;
+ struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
+ unsigned long now = jiffies;
+ int cmdid;
+
+ for_each_set_bit(cmdid, nvmeq->cmdid_data, depth) {
+ void *ctx;
+ nvme_completion_fn fn;
+ static struct nvme_completion cqe = {
+ .status = cpu_to_le16(NVME_SC_ABORT_REQ) << 1,
+ };
+
+ if (timeout && !time_after(now, info[cmdid].timeout))
+ continue;
+ dev_warn(nvmeq->q_dmadev, "Cancelling I/O %d\n", cmdid);
+ ctx = cancel_cmdid(nvmeq, cmdid, &fn);
+ fn(nvmeq->dev, ctx, &cqe);
+ }
+}
+
+static void nvme_free_queue_mem(struct nvme_queue *nvmeq)
+{
+ dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth),
+ (void *)nvmeq->cqes, nvmeq->cq_dma_addr);
+ dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth),
+ nvmeq->sq_cmds, nvmeq->sq_dma_addr);
+ kfree(nvmeq);
+}
+
static void nvme_free_queue(struct nvme_dev *dev, int qid)
{
struct nvme_queue *nvmeq = dev->queues[qid];
int vector = dev->entry[nvmeq->cq_vector].vector;
+ spin_lock_irq(&nvmeq->q_lock);
+ nvme_cancel_ios(nvmeq, false);
+ spin_unlock_irq(&nvmeq->q_lock);
+
irq_set_affinity_hint(vector, NULL);
free_irq(vector, nvmeq);
@@ -876,18 +917,15 @@ static void nvme_free_queue(struct nvme_dev *dev, int qid)
adapter_delete_cq(dev, qid);
}
- dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth),
- (void *)nvmeq->cqes, nvmeq->cq_dma_addr);
- dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth),
- nvmeq->sq_cmds, nvmeq->sq_dma_addr);
- kfree(nvmeq);
+ nvme_free_queue_mem(nvmeq);
}
static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
int depth, int vector)
{
struct device *dmadev = &dev->pci_dev->dev;
- unsigned extra = (depth / 8) + (depth * sizeof(struct nvme_cmd_info));
+ unsigned extra = DIV_ROUND_UP(depth, 8) + (depth *
+ sizeof(struct nvme_cmd_info));
struct nvme_queue *nvmeq = kzalloc(sizeof(*nvmeq) + extra, GFP_KERNEL);
if (!nvmeq)
return NULL;
@@ -975,7 +1013,7 @@ static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev,
static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)
{
- int result;
+ int result = 0;
u32 aqa;
u64 cap;
unsigned long timeout;
@@ -1005,17 +1043,22 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)
timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
dev->db_stride = NVME_CAP_STRIDE(cap);
- while (!(readl(&dev->bar->csts) & NVME_CSTS_RDY)) {
+ while (!result && !(readl(&dev->bar->csts) & NVME_CSTS_RDY)) {
msleep(100);
if (fatal_signal_pending(current))
- return -EINTR;
+ result = -EINTR;
if (time_after(jiffies, timeout)) {
dev_err(&dev->pci_dev->dev,
"Device not ready; aborting initialisation\n");
- return -ENODEV;
+ result = -ENODEV;
}
}
+ if (result) {
+ nvme_free_queue_mem(nvmeq);
+ return result;
+ }
+
result = queue_request_irq(dev, nvmeq, "nvme admin");
dev->queues[0] = nvmeq;
return result;
@@ -1037,6 +1080,8 @@ static struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write,
offset = offset_in_page(addr);
count = DIV_ROUND_UP(offset + length, PAGE_SIZE);
pages = kcalloc(count, sizeof(*pages), GFP_KERNEL);
+ if (!pages)
+ return ERR_PTR(-ENOMEM);
err = get_user_pages_fast(addr, count, 1, pages);
if (err < count) {
@@ -1146,14 +1191,13 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
return status;
}
-static int nvme_user_admin_cmd(struct nvme_ns *ns,
+static int nvme_user_admin_cmd(struct nvme_dev *dev,
struct nvme_admin_cmd __user *ucmd)
{
- struct nvme_dev *dev = ns->dev;
struct nvme_admin_cmd cmd;
struct nvme_command c;
int status, length;
- struct nvme_iod *iod;
+ struct nvme_iod *uninitialized_var(iod);
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -1204,7 +1248,7 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
case NVME_IOCTL_ID:
return ns->ns_id;
case NVME_IOCTL_ADMIN_CMD:
- return nvme_user_admin_cmd(ns, (void __user *)arg);
+ return nvme_user_admin_cmd(ns->dev, (void __user *)arg);
case NVME_IOCTL_SUBMIT_IO:
return nvme_submit_io(ns, (void __user *)arg);
default:
@@ -1218,26 +1262,6 @@ static const struct block_device_operations nvme_fops = {
.compat_ioctl = nvme_ioctl,
};
-static void nvme_timeout_ios(struct nvme_queue *nvmeq)
-{
- int depth = nvmeq->q_depth - 1;
- struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
- unsigned long now = jiffies;
- int cmdid;
-
- for_each_set_bit(cmdid, nvmeq->cmdid_data, depth) {
- void *ctx;
- nvme_completion_fn fn;
- static struct nvme_completion cqe = { .status = cpu_to_le16(NVME_SC_ABORT_REQ) << 1, };
-
- if (!time_after(now, info[cmdid].timeout))
- continue;
- dev_warn(nvmeq->q_dmadev, "Timing out I/O %d\n", cmdid);
- ctx = cancel_cmdid(nvmeq, cmdid, &fn);
- fn(nvmeq->dev, ctx, &cqe);
- }
-}
-
static void nvme_resubmit_bios(struct nvme_queue *nvmeq)
{
while (bio_list_peek(&nvmeq->sq_cong)) {
@@ -1269,7 +1293,7 @@ static int nvme_kthread(void *data)
spin_lock_irq(&nvmeq->q_lock);
if (nvme_process_cq(nvmeq))
printk("process_cq did something\n");
- nvme_timeout_ios(nvmeq);
+ nvme_cancel_ios(nvmeq, true);
nvme_resubmit_bios(nvmeq);
spin_unlock_irq(&nvmeq->q_lock);
}
@@ -1339,6 +1363,9 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int nsid,
ns->disk = disk;
lbaf = id->flbas & 0xf;
ns->lba_shift = id->lbaf[lbaf].ds;
+ blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift);
+ if (dev->max_hw_sectors)
+ blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors);
disk->major = nvme_major;
disk->minors = NVME_MINORS;
@@ -1383,7 +1410,7 @@ static int set_queue_count(struct nvme_dev *dev, int count)
static int __devinit nvme_setup_io_queues(struct nvme_dev *dev)
{
- int result, cpu, i, nr_io_queues, db_bar_size;
+ int result, cpu, i, nr_io_queues, db_bar_size, q_depth;
nr_io_queues = num_online_cpus();
result = set_queue_count(dev, nr_io_queues);
@@ -1429,9 +1456,10 @@ static int __devinit nvme_setup_io_queues(struct nvme_dev *dev)
cpu = cpumask_next(cpu, cpu_online_mask);
}
+ q_depth = min_t(int, NVME_CAP_MQES(readq(&dev->bar->cap)) + 1,
+ NVME_Q_DEPTH);
for (i = 0; i < nr_io_queues; i++) {
- dev->queues[i + 1] = nvme_create_queue(dev, i + 1,
- NVME_Q_DEPTH, i);
+ dev->queues[i + 1] = nvme_create_queue(dev, i + 1, q_depth, i);
if (IS_ERR(dev->queues[i + 1]))
return PTR_ERR(dev->queues[i + 1]);
dev->queue_count++;
@@ -1480,6 +1508,10 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev)
memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn));
memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn));
memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
+ if (ctrl->mdts) {
+ int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
+ dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9);
+ }
id_ns = mem;
for (i = 1; i <= nn; i++) {
@@ -1523,8 +1555,6 @@ static int nvme_dev_remove(struct nvme_dev *dev)
list_del(&dev->node);
spin_unlock(&dev_list_lock);
- /* TODO: wait all I/O finished or cancel them */
-
list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
list_del(&ns->list);
del_gendisk(ns->disk);
@@ -1560,15 +1590,33 @@ static void nvme_release_prp_pools(struct nvme_dev *dev)
dma_pool_destroy(dev->prp_small_pool);
}
-/* XXX: Use an ida or something to let remove / add work correctly */
-static void nvme_set_instance(struct nvme_dev *dev)
+static DEFINE_IDA(nvme_instance_ida);
+
+static int nvme_set_instance(struct nvme_dev *dev)
{
- static int instance;
- dev->instance = instance++;
+ int instance, error;
+
+ do {
+ if (!ida_pre_get(&nvme_instance_ida, GFP_KERNEL))
+ return -ENODEV;
+
+ spin_lock(&dev_list_lock);
+ error = ida_get_new(&nvme_instance_ida, &instance);
+ spin_unlock(&dev_list_lock);
+ } while (error == -EAGAIN);
+
+ if (error)
+ return -ENODEV;
+
+ dev->instance = instance;
+ return 0;
}
static void nvme_release_instance(struct nvme_dev *dev)
{
+ spin_lock(&dev_list_lock);
+ ida_remove(&nvme_instance_ida, dev->instance);
+ spin_unlock(&dev_list_lock);
}
static int __devinit nvme_probe(struct pci_dev *pdev,
@@ -1601,7 +1649,10 @@ static int __devinit nvme_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, dev);
dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
- nvme_set_instance(dev);
+ result = nvme_set_instance(dev);
+ if (result)
+ goto disable;
+
dev->entry[0].vector = pdev->irq;
result = nvme_setup_prp_pools(dev);
@@ -1704,15 +1755,17 @@ static struct pci_driver nvme_driver = {
static int __init nvme_init(void)
{
- int result = -EBUSY;
+ int result;
nvme_thread = kthread_run(nvme_kthread, NULL, "nvme");
if (IS_ERR(nvme_thread))
return PTR_ERR(nvme_thread);
- nvme_major = register_blkdev(nvme_major, "nvme");
- if (nvme_major <= 0)
+ result = register_blkdev(nvme_major, "nvme");
+ if (result < 0)
goto kill_kthread;
+ else if (result > 0)
+ nvme_major = result;
result = pci_register_driver(&nvme_driver);
if (result)
diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c
index 47180a08edad..b6653a6fc5d5 100644
--- a/drivers/edac/i3200_edac.c
+++ b/drivers/edac/i3200_edac.c
@@ -391,7 +391,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
for (j = 0; j < nr_channels; j++) {
struct dimm_info *dimm = csrow->channels[j]->dimm;
- dimm->nr_pages = nr_pages / nr_channels;
+ dimm->nr_pages = nr_pages;
dimm->grain = nr_pages << PAGE_SHIFT;
dimm->mtype = MEM_DDR2;
dimm->dtype = DEV_UNKNOWN;
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
index 39c63757c2a1..6a49dd00b81b 100644
--- a/drivers/edac/i5000_edac.c
+++ b/drivers/edac/i5000_edac.c
@@ -1012,6 +1012,10 @@ static void handle_channel(struct i5000_pvt *pvt, int slot, int channel,
/* add the number of COLUMN bits */
addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
+ /* Dual-rank memories have twice the size */
+ if (dinfo->dual_rank)
+ addrBits++;
+
addrBits += 6; /* add 64 bits per DIMM */
addrBits -= 20; /* divide by 2^^20 */
addrBits -= 3; /* 8 bits per bytes */
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index f3b1f9fafa4b..5715b7c2c517 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -513,7 +513,8 @@ static int get_dimm_config(struct mem_ctl_info *mci)
{
struct sbridge_pvt *pvt = mci->pvt_info;
struct dimm_info *dimm;
- int i, j, banks, ranks, rows, cols, size, npages;
+ unsigned i, j, banks, ranks, rows, cols, npages;
+ u64 size;
u32 reg;
enum edac_type mode;
enum mem_type mtype;
@@ -585,10 +586,10 @@ static int get_dimm_config(struct mem_ctl_info *mci)
cols = numcol(mtr);
/* DDR3 has 8 I/O banks */
- size = (rows * cols * banks * ranks) >> (20 - 3);
+ size = ((u64)rows * cols * banks * ranks) >> (20 - 3);
npages = MiB_TO_PAGES(size);
- edac_dbg(0, "mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
+ edac_dbg(0, "mc#%d: channel %d, dimm %d, %Ld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
pvt->sbridge_dev->mc, i, j,
size, npages,
banks, ranks, rows, cols);
diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index 8a420f13905e..ed94b4ea72e9 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -308,6 +308,7 @@ static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
{
struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+ __set_gpio_level_p012(group, pin, value);
__set_gpio_dir_p012(group, pin, 0);
return 0;
@@ -318,6 +319,7 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
{
struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+ __set_gpio_level_p3(group, pin, value);
__set_gpio_dir_p3(group, pin, 0);
return 0;
@@ -326,6 +328,9 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
int value)
{
+ struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+ __set_gpo_level_p3(group, pin, value);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index ff23d88880e5..3ca240b4413d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -179,7 +179,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
return 0;
} else
if (init->class == 0x906e) {
- NV_ERROR(dev, "906e not supported yet\n");
+ NV_DEBUG(dev, "906e not supported yet\n");
return -EINVAL;
}
diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c
index f704e942372e..f376c39310df 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fb.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fb.c
@@ -124,6 +124,7 @@ nvc0_fb_init(struct drm_device *dev)
priv = dev_priv->engine.fb.priv;
nv_wr32(dev, 0x100c10, priv->r100c10 >> 8);
+ nv_mask(dev, 0x17e820, 0x00100000, 0x00000000); /* NV_PLTCG_INTR_EN */
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c
index 7d85553d518c..cd39eb99f5b1 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fifo.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c
@@ -373,7 +373,8 @@ nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)
static void
nvc0_fifo_isr(struct drm_device *dev)
{
- u32 stat = nv_rd32(dev, 0x002100);
+ u32 mask = nv_rd32(dev, 0x002140);
+ u32 stat = nv_rd32(dev, 0x002100) & mask;
if (stat & 0x00000100) {
NV_INFO(dev, "PFIFO: unknown status 0x00000100\n");
diff --git a/drivers/gpu/drm/nouveau/nve0_fifo.c b/drivers/gpu/drm/nouveau/nve0_fifo.c
index e98d144e6eb9..281bece751b6 100644
--- a/drivers/gpu/drm/nouveau/nve0_fifo.c
+++ b/drivers/gpu/drm/nouveau/nve0_fifo.c
@@ -345,7 +345,8 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)
static void
nve0_fifo_isr(struct drm_device *dev)
{
- u32 stat = nv_rd32(dev, 0x002100);
+ u32 mask = nv_rd32(dev, 0x002140);
+ u32 stat = nv_rd32(dev, 0x002100) & mask;
if (stat & 0x00000100) {
NV_INFO(dev, "PFIFO: unknown status 0x00000100\n");
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index ba055e9ca007..8d9dc44f1f94 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -69,6 +69,13 @@ static int udl_get_modes(struct drm_connector *connector)
static int udl_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
+ struct udl_device *udl = connector->dev->dev_private;
+ if (!udl->sku_pixel_limit)
+ return 0;
+
+ if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit)
+ return MODE_VIRTUAL_Y;
+
return 0;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
index f2fb8f15e2f1..7e0743358dff 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -1018,7 +1018,7 @@ int vmw_event_fence_action_create(struct drm_file *file_priv,
}
- event = kzalloc(sizeof(event->event), GFP_KERNEL);
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
if (unlikely(event == NULL)) {
DRM_ERROR("Failed to allocate an event.\n");
ret = -ENOMEM;
diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c
index 388cbdc96db7..6aafa3d88ff0 100644
--- a/drivers/i2c/busses/i2c-scmi.c
+++ b/drivers/i2c/busses/i2c-scmi.c
@@ -426,19 +426,7 @@ static struct acpi_driver acpi_smbus_cmi_driver = {
.remove = acpi_smbus_cmi_remove,
},
};
-
-static int __init acpi_smbus_cmi_init(void)
-{
- return acpi_bus_register_driver(&acpi_smbus_cmi_driver);
-}
-
-static void __exit acpi_smbus_cmi_exit(void)
-{
- acpi_bus_unregister_driver(&acpi_smbus_cmi_driver);
-}
-
-module_init(acpi_smbus_cmi_init);
-module_exit(acpi_smbus_cmi_exit);
+module_acpi_driver(acpi_smbus_cmi_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Crane Cai <crane.cai@amd.com>");
diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c
index 601f7372f9c4..26f13131639a 100644
--- a/drivers/input/misc/atlas_btns.c
+++ b/drivers/input/misc/atlas_btns.c
@@ -151,22 +151,7 @@ static struct acpi_driver atlas_acpi_driver = {
.remove = atlas_acpi_button_remove,
},
};
-
-static int __init atlas_acpi_init(void)
-{
- if (acpi_disabled)
- return -ENODEV;
-
- return acpi_bus_register_driver(&atlas_acpi_driver);
-}
-
-static void __exit atlas_acpi_exit(void)
-{
- acpi_bus_unregister_driver(&atlas_acpi_driver);
-}
-
-module_init(atlas_acpi_init);
-module_exit(atlas_acpi_exit);
+module_acpi_driver(atlas_acpi_driver);
MODULE_AUTHOR("Jaya Kumar");
MODULE_LICENSE("GPL");
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index b64502dfa9f4..e89daf1b21b4 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -266,7 +266,7 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
static int iommu_init_device(struct device *dev)
{
- struct pci_dev *dma_pdev, *pdev = to_pci_dev(dev);
+ struct pci_dev *dma_pdev = NULL, *pdev = to_pci_dev(dev);
struct iommu_dev_data *dev_data;
struct iommu_group *group;
u16 alias;
@@ -293,7 +293,9 @@ static int iommu_init_device(struct device *dev)
dev_data->alias_data = alias_data;
dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff);
- } else
+ }
+
+ if (dma_pdev == NULL)
dma_pdev = pci_dev_get(pdev);
/* Account for quirked devices */
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index d8abb90a6c2f..034233eefc82 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1555,6 +1555,7 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
unsigned long arg)
{
struct multipath *m = ti->private;
+ struct pgpath *pgpath;
struct block_device *bdev;
fmode_t mode;
unsigned long flags;
@@ -1570,12 +1571,14 @@ again:
if (!m->current_pgpath)
__choose_pgpath(m, 0);
- if (m->current_pgpath) {
- bdev = m->current_pgpath->path.dev->bdev;
- mode = m->current_pgpath->path.dev->mode;
+ pgpath = m->current_pgpath;
+
+ if (pgpath) {
+ bdev = pgpath->path.dev->bdev;
+ mode = pgpath->path.dev->mode;
}
- if (m->queue_io)
+ if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
r = -EAGAIN;
else if (!bdev)
r = -EIO;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index f90069029aae..100368eb7991 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1212,6 +1212,41 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector)
return &t->targets[(KEYS_PER_NODE * n) + k];
}
+static int count_device(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+{
+ unsigned *num_devices = data;
+
+ (*num_devices)++;
+
+ return 0;
+}
+
+/*
+ * Check whether a table has no data devices attached using each
+ * target's iterate_devices method.
+ * Returns false if the result is unknown because a target doesn't
+ * support iterate_devices.
+ */
+bool dm_table_has_no_data_devices(struct dm_table *table)
+{
+ struct dm_target *uninitialized_var(ti);
+ unsigned i = 0, num_devices = 0;
+
+ while (i < dm_table_get_num_targets(table)) {
+ ti = dm_table_get_target(table, i++);
+
+ if (!ti->type->iterate_devices)
+ return false;
+
+ ti->type->iterate_devices(ti, count_device, &num_devices);
+ if (num_devices)
+ return false;
+ }
+
+ return true;
+}
+
/*
* Establish the new table's queue_limits and validate them.
*/
@@ -1354,17 +1389,25 @@ static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev,
return q && blk_queue_nonrot(q);
}
-static bool dm_table_is_nonrot(struct dm_table *t)
+static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+{
+ struct request_queue *q = bdev_get_queue(dev->bdev);
+
+ return q && !blk_queue_add_random(q);
+}
+
+static bool dm_table_all_devices_attribute(struct dm_table *t,
+ iterate_devices_callout_fn func)
{
struct dm_target *ti;
unsigned i = 0;
- /* Ensure that all underlying device are non-rotational. */
while (i < dm_table_get_num_targets(t)) {
ti = dm_table_get_target(t, i++);
if (!ti->type->iterate_devices ||
- !ti->type->iterate_devices(ti, device_is_nonrot, NULL))
+ !ti->type->iterate_devices(ti, func, NULL))
return 0;
}
@@ -1396,7 +1439,8 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
if (!dm_table_discard_zeroes_data(t))
q->limits.discard_zeroes_data = 0;
- if (dm_table_is_nonrot(t))
+ /* Ensure that all underlying devices are non-rotational. */
+ if (dm_table_all_devices_attribute(t, device_is_nonrot))
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
else
queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q);
@@ -1404,6 +1448,15 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
dm_table_set_integrity(t);
/*
+ * Determine whether or not this queue's I/O timings contribute
+ * to the entropy pool, Only request-based targets use this.
+ * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not
+ * have it set.
+ */
+ if (blk_queue_add_random(q) && dm_table_all_devices_attribute(t, device_is_not_random))
+ queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, q);
+
+ /*
* QUEUE_FLAG_STACKABLE must be set after all queue settings are
* visible to other CPUs because, once the flag is set, incoming bios
* are processed by request-based dm, which refers to the queue
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index af1fc3b2c2ad..c29410af1e22 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -509,9 +509,9 @@ enum pool_mode {
struct pool_features {
enum pool_mode mode;
- unsigned zero_new_blocks:1;
- unsigned discard_enabled:1;
- unsigned discard_passdown:1;
+ bool zero_new_blocks:1;
+ bool discard_enabled:1;
+ bool discard_passdown:1;
};
struct thin_c;
@@ -580,7 +580,8 @@ struct pool_c {
struct dm_target_callbacks callbacks;
dm_block_t low_water_blocks;
- struct pool_features pf;
+ struct pool_features requested_pf; /* Features requested during table load */
+ struct pool_features adjusted_pf; /* Features used after adjusting for constituent devices */
};
/*
@@ -1839,6 +1840,47 @@ static void __requeue_bios(struct pool *pool)
/*----------------------------------------------------------------
* Binding of control targets to a pool object
*--------------------------------------------------------------*/
+static bool data_dev_supports_discard(struct pool_c *pt)
+{
+ struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+
+ return q && blk_queue_discard(q);
+}
+
+/*
+ * If discard_passdown was enabled verify that the data device
+ * supports discards. Disable discard_passdown if not.
+ */
+static void disable_passdown_if_not_supported(struct pool_c *pt)
+{
+ struct pool *pool = pt->pool;
+ struct block_device *data_bdev = pt->data_dev->bdev;
+ struct queue_limits *data_limits = &bdev_get_queue(data_bdev)->limits;
+ sector_t block_size = pool->sectors_per_block << SECTOR_SHIFT;
+ const char *reason = NULL;
+ char buf[BDEVNAME_SIZE];
+
+ if (!pt->adjusted_pf.discard_passdown)
+ return;
+
+ if (!data_dev_supports_discard(pt))
+ reason = "discard unsupported";
+
+ else if (data_limits->max_discard_sectors < pool->sectors_per_block)
+ reason = "max discard sectors smaller than a block";
+
+ else if (data_limits->discard_granularity > block_size)
+ reason = "discard granularity larger than a block";
+
+ else if (block_size & (data_limits->discard_granularity - 1))
+ reason = "discard granularity not a factor of block size";
+
+ if (reason) {
+ DMWARN("Data device (%s) %s: Disabling discard passdown.", bdevname(data_bdev, buf), reason);
+ pt->adjusted_pf.discard_passdown = false;
+ }
+}
+
static int bind_control_target(struct pool *pool, struct dm_target *ti)
{
struct pool_c *pt = ti->private;
@@ -1847,31 +1889,16 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
* We want to make sure that degraded pools are never upgraded.
*/
enum pool_mode old_mode = pool->pf.mode;
- enum pool_mode new_mode = pt->pf.mode;
+ enum pool_mode new_mode = pt->adjusted_pf.mode;
if (old_mode > new_mode)
new_mode = old_mode;
pool->ti = ti;
pool->low_water_blocks = pt->low_water_blocks;
- pool->pf = pt->pf;
- set_pool_mode(pool, new_mode);
+ pool->pf = pt->adjusted_pf;
- /*
- * If discard_passdown was enabled verify that the data device
- * supports discards. Disable discard_passdown if not; otherwise
- * -EOPNOTSUPP will be returned.
- */
- /* FIXME: pull this out into a sep fn. */
- if (pt->pf.discard_passdown) {
- struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
- if (!q || !blk_queue_discard(q)) {
- char buf[BDEVNAME_SIZE];
- DMWARN("Discard unsupported by data device (%s): Disabling discard passdown.",
- bdevname(pt->data_dev->bdev, buf));
- pool->pf.discard_passdown = 0;
- }
- }
+ set_pool_mode(pool, new_mode);
return 0;
}
@@ -1889,9 +1916,9 @@ static void unbind_control_target(struct pool *pool, struct dm_target *ti)
static void pool_features_init(struct pool_features *pf)
{
pf->mode = PM_WRITE;
- pf->zero_new_blocks = 1;
- pf->discard_enabled = 1;
- pf->discard_passdown = 1;
+ pf->zero_new_blocks = true;
+ pf->discard_enabled = true;
+ pf->discard_passdown = true;
}
static void __pool_destroy(struct pool *pool)
@@ -2119,13 +2146,13 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
argc--;
if (!strcasecmp(arg_name, "skip_block_zeroing"))
- pf->zero_new_blocks = 0;
+ pf->zero_new_blocks = false;
else if (!strcasecmp(arg_name, "ignore_discard"))
- pf->discard_enabled = 0;
+ pf->discard_enabled = false;
else if (!strcasecmp(arg_name, "no_discard_passdown"))
- pf->discard_passdown = 0;
+ pf->discard_passdown = false;
else if (!strcasecmp(arg_name, "read_only"))
pf->mode = PM_READ_ONLY;
@@ -2259,8 +2286,9 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
pt->metadata_dev = metadata_dev;
pt->data_dev = data_dev;
pt->low_water_blocks = low_water_blocks;
- pt->pf = pf;
+ pt->adjusted_pf = pt->requested_pf = pf;
ti->num_flush_requests = 1;
+
/*
* Only need to enable discards if the pool should pass
* them down to the data device. The thin device's discard
@@ -2268,12 +2296,14 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
*/
if (pf.discard_enabled && pf.discard_passdown) {
ti->num_discard_requests = 1;
+
/*
* Setting 'discards_supported' circumvents the normal
* stacking of discard limits (this keeps the pool and
* thin devices' discard limits consistent).
*/
ti->discards_supported = true;
+ ti->discard_zeroes_data_unsupported = true;
}
ti->private = pt;
@@ -2703,7 +2733,7 @@ static int pool_status(struct dm_target *ti, status_type_t type,
format_dev_t(buf2, pt->data_dev->bdev->bd_dev),
(unsigned long)pool->sectors_per_block,
(unsigned long long)pt->low_water_blocks);
- emit_flags(&pt->pf, result, sz, maxlen);
+ emit_flags(&pt->requested_pf, result, sz, maxlen);
break;
}
@@ -2732,20 +2762,21 @@ static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
}
-static void set_discard_limits(struct pool *pool, struct queue_limits *limits)
+static void set_discard_limits(struct pool_c *pt, struct queue_limits *limits)
{
- /*
- * FIXME: these limits may be incompatible with the pool's data device
- */
+ struct pool *pool = pt->pool;
+ struct queue_limits *data_limits;
+
limits->max_discard_sectors = pool->sectors_per_block;
/*
- * This is just a hint, and not enforced. We have to cope with
- * bios that cover a block partially. A discard that spans a block
- * boundary is not sent to this target.
+ * discard_granularity is just a hint, and not enforced.
*/
- limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
- limits->discard_zeroes_data = pool->pf.zero_new_blocks;
+ if (pt->adjusted_pf.discard_passdown) {
+ data_limits = &bdev_get_queue(pt->data_dev->bdev)->limits;
+ limits->discard_granularity = data_limits->discard_granularity;
+ } else
+ limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
}
static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
@@ -2755,15 +2786,25 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
blk_limits_io_min(limits, 0);
blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
- if (pool->pf.discard_enabled)
- set_discard_limits(pool, limits);
+
+ /*
+ * pt->adjusted_pf is a staging area for the actual features to use.
+ * They get transferred to the live pool in bind_control_target()
+ * called from pool_preresume().
+ */
+ if (!pt->adjusted_pf.discard_enabled)
+ return;
+
+ disable_passdown_if_not_supported(pt);
+
+ set_discard_limits(pt, limits);
}
static struct target_type pool_target = {
.name = "thin-pool",
.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
DM_TARGET_IMMUTABLE,
- .version = {1, 3, 0},
+ .version = {1, 4, 0},
.module = THIS_MODULE,
.ctr = pool_ctr,
.dtr = pool_dtr,
@@ -3042,19 +3083,19 @@ static int thin_iterate_devices(struct dm_target *ti,
return 0;
}
+/*
+ * A thin device always inherits its queue limits from its pool.
+ */
static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
{
struct thin_c *tc = ti->private;
- struct pool *pool = tc->pool;
- blk_limits_io_min(limits, 0);
- blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
- set_discard_limits(pool, limits);
+ *limits = bdev_get_queue(tc->pool_dev->bdev)->limits;
}
static struct target_type thin_target = {
.name = "thin",
- .version = {1, 3, 0},
+ .version = {1, 4, 0},
.module = THIS_MODULE,
.ctr = thin_ctr,
.dtr = thin_dtr,
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
index 254d19268ad2..892ae2766aa6 100644
--- a/drivers/md/dm-verity.c
+++ b/drivers/md/dm-verity.c
@@ -718,8 +718,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
v->hash_dev_block_bits = ffs(num) - 1;
if (sscanf(argv[5], "%llu%c", &num_ll, &dummy) != 1 ||
- num_ll << (v->data_dev_block_bits - SECTOR_SHIFT) !=
- (sector_t)num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) {
+ (sector_t)(num_ll << (v->data_dev_block_bits - SECTOR_SHIFT))
+ >> (v->data_dev_block_bits - SECTOR_SHIFT) != num_ll) {
ti->error = "Invalid data blocks";
r = -EINVAL;
goto bad;
@@ -733,8 +733,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
}
if (sscanf(argv[6], "%llu%c", &num_ll, &dummy) != 1 ||
- num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT) !=
- (sector_t)num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT)) {
+ (sector_t)(num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT))
+ >> (v->hash_dev_block_bits - SECTOR_SHIFT) != num_ll) {
ti->error = "Invalid hash start";
r = -EINVAL;
goto bad;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 4e09b6ff5b49..67ffa391edcf 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -865,10 +865,14 @@ static void dm_done(struct request *clone, int error, bool mapped)
{
int r = error;
struct dm_rq_target_io *tio = clone->end_io_data;
- dm_request_endio_fn rq_end_io = tio->ti->type->rq_end_io;
+ dm_request_endio_fn rq_end_io = NULL;
- if (mapped && rq_end_io)
- r = rq_end_io(tio->ti, clone, error, &tio->info);
+ if (tio->ti) {
+ rq_end_io = tio->ti->type->rq_end_io;
+
+ if (mapped && rq_end_io)
+ r = rq_end_io(tio->ti, clone, error, &tio->info);
+ }
if (r <= 0)
/* The target wants to complete the I/O */
@@ -1588,15 +1592,6 @@ static int map_request(struct dm_target *ti, struct request *clone,
int r, requeued = 0;
struct dm_rq_target_io *tio = clone->end_io_data;
- /*
- * Hold the md reference here for the in-flight I/O.
- * We can't rely on the reference count by device opener,
- * because the device may be closed during the request completion
- * when all bios are completed.
- * See the comment in rq_completed() too.
- */
- dm_get(md);
-
tio->ti = ti;
r = ti->type->map_rq(ti, clone, &tio->info);
switch (r) {
@@ -1628,6 +1623,26 @@ static int map_request(struct dm_target *ti, struct request *clone,
return requeued;
}
+static struct request *dm_start_request(struct mapped_device *md, struct request *orig)
+{
+ struct request *clone;
+
+ blk_start_request(orig);
+ clone = orig->special;
+ atomic_inc(&md->pending[rq_data_dir(clone)]);
+
+ /*
+ * Hold the md reference here for the in-flight I/O.
+ * We can't rely on the reference count by device opener,
+ * because the device may be closed during the request completion
+ * when all bios are completed.
+ * See the comment in rq_completed() too.
+ */
+ dm_get(md);
+
+ return clone;
+}
+
/*
* q->request_fn for request-based dm.
* Called with the queue lock held.
@@ -1657,14 +1672,21 @@ static void dm_request_fn(struct request_queue *q)
pos = blk_rq_pos(rq);
ti = dm_table_find_target(map, pos);
- BUG_ON(!dm_target_is_valid(ti));
+ if (!dm_target_is_valid(ti)) {
+ /*
+ * Must perform setup, that dm_done() requires,
+ * before calling dm_kill_unmapped_request
+ */
+ DMERR_LIMIT("request attempted access beyond the end of device");
+ clone = dm_start_request(md, rq);
+ dm_kill_unmapped_request(clone, -EIO);
+ continue;
+ }
if (ti->type->busy && ti->type->busy(ti))
goto delay_and_out;
- blk_start_request(rq);
- clone = rq->special;
- atomic_inc(&md->pending[rq_data_dir(clone)]);
+ clone = dm_start_request(md, rq);
spin_unlock(q->queue_lock);
if (map_request(ti, clone, md))
@@ -1684,8 +1706,6 @@ delay_and_out:
blk_delay_queue(q, HZ / 10);
out:
dm_table_put(map);
-
- return;
}
int dm_underlying_device_busy(struct request_queue *q)
@@ -2409,7 +2429,7 @@ static void dm_queue_flush(struct mapped_device *md)
*/
struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
{
- struct dm_table *map = ERR_PTR(-EINVAL);
+ struct dm_table *live_map, *map = ERR_PTR(-EINVAL);
struct queue_limits limits;
int r;
@@ -2419,6 +2439,19 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
if (!dm_suspended_md(md))
goto out;
+ /*
+ * If the new table has no data devices, retain the existing limits.
+ * This helps multipath with queue_if_no_path if all paths disappear,
+ * then new I/O is queued based on these limits, and then some paths
+ * reappear.
+ */
+ if (dm_table_has_no_data_devices(table)) {
+ live_map = dm_get_live_table(md);
+ if (live_map)
+ limits = md->queue->limits;
+ dm_table_put(live_map);
+ }
+
r = dm_calculate_queue_limits(table, &limits);
if (r) {
map = ERR_PTR(r);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 52eef493d266..6a99fefaa743 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -54,6 +54,7 @@ void dm_table_event_callback(struct dm_table *t,
void (*fn)(void *), void *context);
struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index);
struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector);
+bool dm_table_has_no_data_devices(struct dm_table *table);
int dm_calculate_queue_limits(struct dm_table *table,
struct queue_limits *limits);
void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 1c2eb38f3c51..0138a727c1f3 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1512,14 +1512,16 @@ static int _enough(struct r10conf *conf, struct geom *geo, int ignore)
do {
int n = conf->copies;
int cnt = 0;
+ int this = first;
while (n--) {
- if (conf->mirrors[first].rdev &&
- first != ignore)
+ if (conf->mirrors[this].rdev &&
+ this != ignore)
cnt++;
- first = (first+1) % geo->raid_disks;
+ this = (this+1) % geo->raid_disks;
}
if (cnt == 0)
return 0;
+ first = (first + geo->near_copies) % geo->raid_disks;
} while (first != 0);
return 1;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 7031b865b3a0..0689173fd9f5 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1591,6 +1591,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
#ifdef CONFIG_MULTICORE_RAID456
init_waitqueue_head(&nsh->ops.wait_for_ops);
#endif
+ spin_lock_init(&nsh->stripe_lock);
list_add(&nsh->lru, &newstripes);
}
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index f2f482bec573..a6e74514e662 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1123,6 +1123,33 @@ static unsigned long mtdchar_get_unmapped_area(struct file *file,
}
#endif
+static inline unsigned long get_vm_size(struct vm_area_struct *vma)
+{
+ return vma->vm_end - vma->vm_start;
+}
+
+static inline resource_size_t get_vm_offset(struct vm_area_struct *vma)
+{
+ return (resource_size_t) vma->vm_pgoff << PAGE_SHIFT;
+}
+
+/*
+ * Set a new vm offset.
+ *
+ * Verify that the incoming offset really works as a page offset,
+ * and that the offset and size fit in a resource_size_t.
+ */
+static inline int set_vm_offset(struct vm_area_struct *vma, resource_size_t off)
+{
+ pgoff_t pgoff = off >> PAGE_SHIFT;
+ if (off != (resource_size_t) pgoff << PAGE_SHIFT)
+ return -EINVAL;
+ if (off + get_vm_size(vma) - 1 < off)
+ return -EINVAL;
+ vma->vm_pgoff = pgoff;
+ return 0;
+}
+
/*
* set up a mapping for shared memory segments
*/
@@ -1132,20 +1159,29 @@ static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma)
struct mtd_file_info *mfi = file->private_data;
struct mtd_info *mtd = mfi->mtd;
struct map_info *map = mtd->priv;
- unsigned long start;
- unsigned long off;
- u32 len;
+ resource_size_t start, off;
+ unsigned long len, vma_len;
if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) {
- off = vma->vm_pgoff << PAGE_SHIFT;
+ off = get_vm_offset(vma);
start = map->phys;
len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size);
start &= PAGE_MASK;
- if ((vma->vm_end - vma->vm_start + off) > len)
+ vma_len = get_vm_size(vma);
+
+ /* Overflow in off+len? */
+ if (vma_len + off < off)
+ return -EINVAL;
+ /* Does it fit in the mapping? */
+ if (vma_len + off > len)
return -EINVAL;
off += start;
- vma->vm_pgoff = off >> PAGE_SHIFT;
+ /* Did that overflow? */
+ if (off < start)
+ return -EINVAL;
+ if (set_vm_offset(vma, off) < 0)
+ return -EINVAL;
vma->vm_flags |= VM_IO | VM_RESERVED;
#ifdef pgprot_noncached
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 79cebd8525ce..e48312f2305d 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -8564,7 +8564,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
error:
- iounmap(bp->regview);
+ pci_iounmap(pdev, bp->regview);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index c42bbb16cdae..a688a2ddcfd6 100644
--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -722,10 +722,8 @@ static int octeon_mgmt_init_phy(struct net_device *netdev)
octeon_mgmt_adjust_link, 0,
PHY_INTERFACE_MODE_MII);
- if (IS_ERR(p->phydev)) {
- p->phydev = NULL;
+ if (!p->phydev)
return -1;
- }
phy_start_aneg(p->phydev);
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index e559dfa06d6a..6fa74d530e44 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -1101,9 +1101,9 @@ static int pasemi_mac_phy_init(struct net_device *dev)
phydev = of_phy_connect(dev, phy_dn, &pasemi_adjust_link, 0,
PHY_INTERFACE_MODE_SGMII);
- if (IS_ERR(phydev)) {
+ if (!phydev) {
printk(KERN_ERR "%s: Could not attach to phy\n", dev->name);
- return PTR_ERR(phydev);
+ return -ENODEV;
}
mac->phydev = phydev;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index b8ead696141e..2a179d087207 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -15,7 +15,7 @@ qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
do {
/* give atleast 1ms for firmware to respond */
- msleep(1);
+ mdelay(1);
if (++timeout > QLCNIC_OS_CRB_RETRY_COUNT)
return QLCNIC_CDRP_RSP_TIMEOUT;
@@ -601,7 +601,7 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
qlcnic_fw_cmd_destroy_tx_ctx(adapter);
/* Allow dma queues to drain after context reset */
- msleep(20);
+ mdelay(20);
}
}
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 6d6192316b30..88e3991464e7 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -56,6 +56,32 @@ static int smsc_phy_config_init(struct phy_device *phydev)
return smsc_phy_ack_interrupt (phydev);
}
+static int lan87xx_config_init(struct phy_device *phydev)
+{
+ /*
+ * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
+ * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
+ * to a bug on the chip.
+ *
+ * When the system is powered on with the network cable being
+ * disconnected all the way until after ifconfig ethX up is
+ * issued for the LAN port with this PHY, connecting the cable
+ * afterwards does not cause LINK change detection, while the
+ * expected behavior is the Link UP being detected.
+ */
+ int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+ if (rc < 0)
+ return rc;
+
+ rc &= ~MII_LAN83C185_EDPWRDOWN;
+
+ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
+ if (rc < 0)
+ return rc;
+
+ return smsc_phy_ack_interrupt(phydev);
+}
+
static int lan911x_config_init(struct phy_device *phydev)
{
return smsc_phy_ack_interrupt(phydev);
@@ -162,7 +188,7 @@ static struct phy_driver smsc_phy_driver[] = {
/* basic functions */
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
- .config_init = smsc_phy_config_init,
+ .config_init = lan87xx_config_init,
/* IRQ related */
.ack_interrupt = smsc_phy_ack_interrupt,
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 3ffe8a6e3c8b..f8cd61f449a4 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1653,8 +1653,8 @@ static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
&team_nl_family, 0, TEAM_CMD_NOOP);
- if (IS_ERR(hdr)) {
- err = PTR_ERR(hdr);
+ if (!hdr) {
+ err = -EMSGSIZE;
goto err_msg_put;
}
@@ -1848,8 +1848,8 @@ start_again:
hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags | NLM_F_MULTI,
TEAM_CMD_OPTIONS_GET);
- if (IS_ERR(hdr))
- return PTR_ERR(hdr);
+ if (!hdr)
+ return -EMSGSIZE;
if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex))
goto nla_put_failure;
@@ -2068,8 +2068,8 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb,
hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags,
TEAM_CMD_PORT_LIST_GET);
- if (IS_ERR(hdr))
- return PTR_ERR(hdr);
+ if (!hdr)
+ return -EMSGSIZE;
if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex))
goto nla_put_failure;
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index f5ab6e613ec8..376143e8a1aa 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1253,6 +1253,7 @@ static struct usb_driver smsc75xx_driver = {
.probe = usbnet_probe,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .reset_resume = usbnet_resume,
.disconnect = usbnet_disconnect,
.disable_hub_initiated_lpm = 1,
};
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
index 6b9af989632b..18d74f29dcb2 100644
--- a/drivers/platform/x86/hp_accel.c
+++ b/drivers/platform/x86/hp_accel.c
@@ -382,31 +382,8 @@ static struct acpi_driver lis3lv02d_driver = {
},
.drv.pm = HP_ACCEL_PM,
};
-
-static int __init lis3lv02d_init_module(void)
-{
- int ret;
-
- if (acpi_disabled)
- return -ENODEV;
-
- ret = acpi_bus_register_driver(&lis3lv02d_driver);
- if (ret < 0)
- return ret;
-
- pr_info("driver loaded\n");
-
- return 0;
-}
-
-static void __exit lis3lv02d_exit_module(void)
-{
- acpi_bus_unregister_driver(&lis3lv02d_driver);
-}
+module_acpi_driver(lis3lv02d_driver);
MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED.");
MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
MODULE_LICENSE("GPL");
-
-module_init(lis3lv02d_init_module);
-module_exit(lis3lv02d_exit_module);
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index dae7abe1d711..5ff4f2e314d2 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -917,20 +917,8 @@ static struct acpi_driver ideapad_acpi_driver = {
.drv.pm = &ideapad_pm,
.owner = THIS_MODULE,
};
-
-static int __init ideapad_acpi_module_init(void)
-{
- return acpi_bus_register_driver(&ideapad_acpi_driver);
-}
-
-static void __exit ideapad_acpi_module_exit(void)
-{
- acpi_bus_unregister_driver(&ideapad_acpi_driver);
-}
+module_acpi_driver(ideapad_acpi_driver);
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("IdeaPad ACPI Extras");
MODULE_LICENSE("GPL");
-
-module_init(ideapad_acpi_module_init);
-module_exit(ideapad_acpi_module_exit);
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index d528daa0e81c..d727bfee89a6 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -186,27 +186,7 @@ static struct acpi_driver acpi_topstar_driver = {
.notify = acpi_topstar_notify,
},
};
-
-static int __init topstar_laptop_init(void)
-{
- int ret;
-
- ret = acpi_bus_register_driver(&acpi_topstar_driver);
- if (ret < 0)
- return ret;
-
- pr_info("ACPI extras driver loaded\n");
-
- return 0;
-}
-
-static void __exit topstar_laptop_exit(void)
-{
- acpi_bus_unregister_driver(&acpi_topstar_driver);
-}
-
-module_init(topstar_laptop_init);
-module_exit(topstar_laptop_exit);
+module_acpi_driver(acpi_topstar_driver);
MODULE_AUTHOR("Herton Ronaldo Krzesinski");
MODULE_DESCRIPTION("Topstar Laptop ACPI Extras driver");
diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c
index 5e5d6317d690..e95be0b74859 100644
--- a/drivers/platform/x86/toshiba_bluetooth.c
+++ b/drivers/platform/x86/toshiba_bluetooth.c
@@ -122,30 +122,10 @@ static int toshiba_bt_rfkill_add(struct acpi_device *device)
return result;
}
-static int __init toshiba_bt_rfkill_init(void)
-{
- int result;
-
- result = acpi_bus_register_driver(&toshiba_bt_rfkill_driver);
- if (result < 0) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Error registering driver\n"));
- return result;
- }
-
- return 0;
-}
-
static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type)
{
/* clean up */
return 0;
}
-static void __exit toshiba_bt_rfkill_exit(void)
-{
- acpi_bus_unregister_driver(&toshiba_bt_rfkill_driver);
-}
-
-module_init(toshiba_bt_rfkill_init);
-module_exit(toshiba_bt_rfkill_exit);
+module_acpi_driver(toshiba_bt_rfkill_driver);
diff --git a/drivers/platform/x86/xo15-ebook.c b/drivers/platform/x86/xo15-ebook.c
index 38ba39d7ca7d..16d340c3b852 100644
--- a/drivers/platform/x86/xo15-ebook.c
+++ b/drivers/platform/x86/xo15-ebook.c
@@ -170,16 +170,4 @@ static struct acpi_driver xo15_ebook_driver = {
},
.drv.pm = &ebook_switch_pm,
};
-
-static int __init xo15_ebook_init(void)
-{
- return acpi_bus_register_driver(&xo15_ebook_driver);
-}
-
-static void __exit xo15_ebook_exit(void)
-{
- acpi_bus_unregister_driver(&xo15_ebook_driver);
-}
-
-module_init(xo15_ebook_init);
-module_exit(xo15_ebook_exit);
+module_acpi_driver(xo15_ebook_driver);
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 507a8e2b9a4c..26b5d4b18dd7 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -321,14 +321,9 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp)
{
struct acpi_device *acpi = to_acpi_device(dev);
struct pnp_dev *pnp = _pnp;
- struct device *physical_device;
-
- physical_device = acpi_get_physical_device(acpi->handle);
- if (physical_device)
- put_device(physical_device);
/* true means it matched */
- return !physical_device
+ return !acpi->physical_node_count
&& compare_pnp_id(pnp->id, acpi_device_hid(acpi));
}
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index d95696584762..3440812b4a84 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -624,7 +624,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf,
/* print devices for all busses */
list_for_each_entry(bus, &usb_bus_list, bus_list) {
/* recurse through all children of the root hub */
- if (!bus->root_hub)
+ if (!bus_to_hcd(bus)->rh_registered)
continue;
usb_lock_device(bus->root_hub);
ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos,
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index bc84106ac057..75ba2091f9b4 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1011,10 +1011,7 @@ static int register_root_hub(struct usb_hcd *hcd)
if (retval) {
dev_err (parent_dev, "can't register root hub for %s, %d\n",
dev_name(&usb_dev->dev), retval);
- }
- mutex_unlock(&usb_bus_list_lock);
-
- if (retval == 0) {
+ } else {
spin_lock_irq (&hcd_root_hub_lock);
hcd->rh_registered = 1;
spin_unlock_irq (&hcd_root_hub_lock);
@@ -1023,6 +1020,7 @@ static int register_root_hub(struct usb_hcd *hcd)
if (HCD_DEAD(hcd))
usb_hc_died (hcd); /* This time clean up */
}
+ mutex_unlock(&usb_bus_list_lock);
return retval;
}
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c
index 8947b203d5a4..ce45f5535236 100644
--- a/drivers/usb/core/usb-acpi.c
+++ b/drivers/usb/core/usb-acpi.c
@@ -52,18 +52,19 @@ out:
static int usb_acpi_check_pld(struct usb_device *udev, acpi_handle handle)
{
acpi_status status;
- struct acpi_pld pld;
+ struct acpi_pld_info *pld;
status = acpi_get_physical_device_location(handle, &pld);
if (ACPI_FAILURE(status))
return -ENODEV;
- if (pld.user_visible)
+ if (pld->user_visible)
udev->removable = USB_DEVICE_REMOVABLE;
else
udev->removable = USB_DEVICE_FIXED;
+ ACPI_FREE(pld);
return 0;
}
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index aaa8d2bce217..0bf72f943b00 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -467,7 +467,8 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
/* From the GPIO notifying the over-current situation, find
* out the corresponding port */
at91_for_each_port(port) {
- if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) {
+ if (gpio_is_valid(pdata->overcurrent_pin[port]) &&
+ gpio_to_irq(pdata->overcurrent_pin[port]) == irq) {
gpio = pdata->overcurrent_pin[port];
break;
}
diff --git a/fs/dcache.c b/fs/dcache.c
index 16521a9f2038..693f95bf1cae 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1134,6 +1134,8 @@ positive:
return 1;
rename_retry:
+ if (locked)
+ goto again;
locked = 1;
write_seqlock(&rename_lock);
goto again;
@@ -1141,7 +1143,7 @@ rename_retry:
EXPORT_SYMBOL(have_submounts);
/*
- * Search the dentry child list for the specified parent,
+ * Search the dentry child list of the specified parent,
* and move any unused dentries to the end of the unused
* list for prune_dcache(). We descend to the next level
* whenever the d_subdirs list is non-empty and continue
@@ -1236,6 +1238,8 @@ out:
rename_retry:
if (found)
return found;
+ if (locked)
+ goto again;
locked = 1;
write_seqlock(&rename_lock);
goto again;
@@ -3035,6 +3039,8 @@ resume:
return;
rename_retry:
+ if (locked)
+ goto again;
locked = 1;
write_seqlock(&rename_lock);
goto again;
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index fb1a2bedbe97..8d80c990dffd 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -289,7 +289,6 @@ static void nlmsvc_free_block(struct kref *kref)
dprintk("lockd: freeing block %p...\n", block);
/* Remove block from file's list of blocks */
- mutex_lock(&file->f_mutex);
list_del_init(&block->b_flist);
mutex_unlock(&file->f_mutex);
@@ -303,7 +302,7 @@ static void nlmsvc_free_block(struct kref *kref)
static void nlmsvc_release_block(struct nlm_block *block)
{
if (block != NULL)
- kref_put(&block->b_count, nlmsvc_free_block);
+ kref_put_mutex(&block->b_count, nlmsvc_free_block, &block->b_file->f_mutex);
}
/*
diff --git a/fs/namespace.c b/fs/namespace.c
index 4d31f73e2561..7bdf7907413f 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1886,8 +1886,14 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
return err;
err = -EINVAL;
- if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(real_mount(path->mnt)))
- goto unlock;
+ if (unlikely(!check_mnt(real_mount(path->mnt)))) {
+ /* that's acceptable only for automounts done in private ns */
+ if (!(mnt_flags & MNT_SHRINKABLE))
+ goto unlock;
+ /* ... and for those we'd better have mountpoint still alive */
+ if (!real_mount(path->mnt)->mnt_ns)
+ goto unlock;
+ }
/* Refuse the same filesystem on the same mount point */
err = -EBUSY;
diff --git a/include/acpi/acbuffer.h b/include/acpi/acbuffer.h
new file mode 100644
index 000000000000..a1e45cdd729a
--- /dev/null
+++ b/include/acpi/acbuffer.h
@@ -0,0 +1,235 @@
+/******************************************************************************
+ *
+ * Name: acbuffer.h - Support for buffers returned by ACPI predefined names
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef __ACBUFFER_H__
+#define __ACBUFFER_H__
+
+/*
+ * Contains buffer structures for these predefined names:
+ * _FDE, _GRT, _GTM, _PLD, _SRT
+ */
+
+/*
+ * Note: C bitfields are not used for this reason:
+ *
+ * "Bitfields are great and easy to read, but unfortunately the C language
+ * does not specify the layout of bitfields in memory, which means they are
+ * essentially useless for dealing with packed data in on-disk formats or
+ * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me,
+ * this decision was a design error in C. Ritchie could have picked an order
+ * and stuck with it." Norman Ramsey.
+ * See http://stackoverflow.com/a/1053662/41661
+ */
+
+/* _FDE return value */
+
+struct acpi_fde_info {
+ u32 floppy0;
+ u32 floppy1;
+ u32 floppy2;
+ u32 floppy3;
+ u32 tape;
+};
+
+/*
+ * _GRT return value
+ * _SRT input value
+ */
+struct acpi_grt_info {
+ u16 year;
+ u8 month;
+ u8 day;
+ u8 hour;
+ u8 minute;
+ u8 second;
+ u8 valid;
+ u16 milliseconds;
+ u16 timezone;
+ u8 daylight;
+ u8 reserved[3];
+};
+
+/* _GTM return value */
+
+struct acpi_gtm_info {
+ u32 pio_speed0;
+ u32 dma_speed0;
+ u32 pio_speed1;
+ u32 dma_speed1;
+ u32 flags;
+};
+
+/*
+ * Formatted _PLD return value. The minimum size is a package containing
+ * one buffer.
+ * Revision 1: Buffer is 16 bytes (128 bits)
+ * Revision 2: Buffer is 20 bytes (160 bits)
+ *
+ * Note: This structure is returned from the acpi_decode_pld_buffer
+ * interface.
+ */
+struct acpi_pld_info {
+ u8 revision;
+ u8 ignore_color;
+ u32 color;
+ u16 width;
+ u16 height;
+ u8 user_visible;
+ u8 dock;
+ u8 lid;
+ u8 panel;
+ u8 vertical_position;
+ u8 horizontal_position;
+ u8 shape;
+ u8 group_orientation;
+ u8 group_token;
+ u8 group_position;
+ u8 bay;
+ u8 ejectable;
+ u8 ospm_eject_required;
+ u8 cabinet_number;
+ u8 card_cage_number;
+ u8 reference;
+ u8 rotation;
+ u8 order;
+ u8 reserved;
+ u16 vertical_offset;
+ u16 horizontal_offset;
+};
+
+/*
+ * Macros to:
+ * 1) Convert a _PLD buffer to internal struct acpi_pld_info format - ACPI_PLD_GET*
+ * (Used by acpi_decode_pld_buffer)
+ * 2) Construct a _PLD buffer - ACPI_PLD_SET*
+ * (Intended for BIOS use only)
+ */
+#define ACPI_PLD_REV1_BUFFER_SIZE 16 /* For Revision 1 of the buffer (From ACPI spec) */
+#define ACPI_PLD_BUFFER_SIZE 20 /* For Revision 2 of the buffer (From ACPI spec) */
+
+/* First 32-bit dword, bits 0:32 */
+
+#define ACPI_PLD_GET_REVISION(dword) ACPI_GET_BITS (dword, 0, ACPI_7BIT_MASK)
+#define ACPI_PLD_SET_REVISION(dword,value) ACPI_SET_BITS (dword, 0, ACPI_7BIT_MASK, value) /* Offset 0, Len 7 */
+
+#define ACPI_PLD_GET_IGNORE_COLOR(dword) ACPI_GET_BITS (dword, 7, ACPI_1BIT_MASK)
+#define ACPI_PLD_SET_IGNORE_COLOR(dword,value) ACPI_SET_BITS (dword, 7, ACPI_1BIT_MASK, value) /* Offset 7, Len 1 */
+
+#define ACPI_PLD_GET_COLOR(dword) ACPI_GET_BITS (dword, 8, ACPI_24BIT_MASK)
+#define ACPI_PLD_SET_COLOR(dword,value) ACPI_SET_BITS (dword, 8, ACPI_24BIT_MASK, value) /* Offset 8, Len 24 */
+
+/* Second 32-bit dword, bits 33:63 */
+
+#define ACPI_PLD_GET_WIDTH(dword) ACPI_GET_BITS (dword, 0, ACPI_16BIT_MASK)
+#define ACPI_PLD_SET_WIDTH(dword,value) ACPI_SET_BITS (dword, 0, ACPI_16BIT_MASK, value) /* Offset 32+0=32, Len 16 */
+
+#define ACPI_PLD_GET_HEIGHT(dword) ACPI_GET_BITS (dword, 16, ACPI_16BIT_MASK)
+#define ACPI_PLD_SET_HEIGHT(dword,value) ACPI_SET_BITS (dword, 16, ACPI_16BIT_MASK, value) /* Offset 32+16=48, Len 16 */
+
+/* Third 32-bit dword, bits 64:95 */
+
+#define ACPI_PLD_GET_USER_VISIBLE(dword) ACPI_GET_BITS (dword, 0, ACPI_1BIT_MASK)
+#define ACPI_PLD_SET_USER_VISIBLE(dword,value) ACPI_SET_BITS (dword, 0, ACPI_1BIT_MASK, value) /* Offset 64+0=64, Len 1 */
+
+#define ACPI_PLD_GET_DOCK(dword) ACPI_GET_BITS (dword, 1, ACPI_1BIT_MASK)
+#define ACPI_PLD_SET_DOCK(dword,value) ACPI_SET_BITS (dword, 1, ACPI_1BIT_MASK, value) /* Offset 64+1=65, Len 1 */
+
+#define ACPI_PLD_GET_LID(dword) ACPI_GET_BITS (dword, 2, ACPI_1BIT_MASK)
+#define ACPI_PLD_SET_LID(dword,value) ACPI_SET_BITS (dword, 2, ACPI_1BIT_MASK, value) /* Offset 64+2=66, Len 1 */
+
+#define ACPI_PLD_GET_PANEL(dword) ACPI_GET_BITS (dword, 3, ACPI_3BIT_MASK)
+#define ACPI_PLD_SET_PANEL(dword,value) ACPI_SET_BITS (dword, 3, ACPI_3BIT_MASK, value) /* Offset 64+3=67, Len 3 */
+
+#define ACPI_PLD_GET_VERTICAL(dword) ACPI_GET_BITS (dword, 6, ACPI_2BIT_MASK)
+#define ACPI_PLD_SET_VERTICAL(dword,value) ACPI_SET_BITS (dword, 6, ACPI_2BIT_MASK, value) /* Offset 64+6=70, Len 2 */
+
+#define ACPI_PLD_GET_HORIZONTAL(dword) ACPI_GET_BITS (dword, 8, ACPI_2BIT_MASK)
+#define ACPI_PLD_SET_HORIZONTAL(dword,value) ACPI_SET_BITS (dword, 8, ACPI_2BIT_MASK, value) /* Offset 64+8=72, Len 2 */
+
+#define ACPI_PLD_GET_SHAPE(dword) ACPI_GET_BITS (dword, 10, ACPI_4BIT_MASK)
+#define ACPI_PLD_SET_SHAPE(dword,value) ACPI_SET_BITS (dword, 10, ACPI_4BIT_MASK, value) /* Offset 64+10=74, Len 4 */
+
+#define ACPI_PLD_GET_ORIENTATION(dword) ACPI_GET_BITS (dword, 14, ACPI_1BIT_MASK)
+#define ACPI_PLD_SET_ORIENTATION(dword,value) ACPI_SET_BITS (dword, 14, ACPI_1BIT_MASK, value) /* Offset 64+14=78, Len 1 */
+
+#define ACPI_PLD_GET_TOKEN(dword) ACPI_GET_BITS (dword, 15, ACPI_8BIT_MASK)
+#define ACPI_PLD_SET_TOKEN(dword,value) ACPI_SET_BITS (dword, 15, ACPI_8BIT_MASK, value) /* Offset 64+15=79, Len 8 */
+
+#define ACPI_PLD_GET_POSITION(dword) ACPI_GET_BITS (dword, 23, ACPI_8BIT_MASK)
+#define ACPI_PLD_SET_POSITION(dword,value) ACPI_SET_BITS (dword, 23, ACPI_8BIT_MASK, value) /* Offset 64+23=87, Len 8 */
+
+#define ACPI_PLD_GET_BAY(dword) ACPI_GET_BITS (dword, 31, ACPI_1BIT_MASK)
+#define ACPI_PLD_SET_BAY(dword,value) ACPI_SET_BITS (dword, 31, ACPI_1BIT_MASK, value) /* Offset 64+31=95, Len 1 */
+
+/* Fourth 32-bit dword, bits 96:127 */
+
+#define ACPI_PLD_GET_EJECTABLE(dword) ACPI_GET_BITS (dword, 0, ACPI_1BIT_MASK)
+#define ACPI_PLD_SET_EJECTABLE(dword,value) ACPI_SET_BITS (dword, 0, ACPI_1BIT_MASK, value) /* Offset 96+0=96, Len 1 */
+
+#define ACPI_PLD_GET_OSPM_EJECT(dword) ACPI_GET_BITS (dword, 1, ACPI_1BIT_MASK)
+#define ACPI_PLD_SET_OSPM_EJECT(dword,value) ACPI_SET_BITS (dword, 1, ACPI_1BIT_MASK, value) /* Offset 96+1=97, Len 1 */
+
+#define ACPI_PLD_GET_CABINET(dword) ACPI_GET_BITS (dword, 2, ACPI_8BIT_MASK)
+#define ACPI_PLD_SET_CABINET(dword,value) ACPI_SET_BITS (dword, 2, ACPI_8BIT_MASK, value) /* Offset 96+2=98, Len 8 */
+
+#define ACPI_PLD_GET_CARD_CAGE(dword) ACPI_GET_BITS (dword, 10, ACPI_8BIT_MASK)
+#define ACPI_PLD_SET_CARD_CAGE(dword,value) ACPI_SET_BITS (dword, 10, ACPI_8BIT_MASK, value) /* Offset 96+10=106, Len 8 */
+
+#define ACPI_PLD_GET_REFERENCE(dword) ACPI_GET_BITS (dword, 18, ACPI_1BIT_MASK)
+#define ACPI_PLD_SET_REFERENCE(dword,value) ACPI_SET_BITS (dword, 18, ACPI_1BIT_MASK, value) /* Offset 96+18=114, Len 1 */
+
+#define ACPI_PLD_GET_ROTATION(dword) ACPI_GET_BITS (dword, 19, ACPI_4BIT_MASK)
+#define ACPI_PLD_SET_ROTATION(dword,value) ACPI_SET_BITS (dword, 19, ACPI_4BIT_MASK, value) /* Offset 96+19=115, Len 4 */
+
+#define ACPI_PLD_GET_ORDER(dword) ACPI_GET_BITS (dword, 23, ACPI_5BIT_MASK)
+#define ACPI_PLD_SET_ORDER(dword,value) ACPI_SET_BITS (dword, 23, ACPI_5BIT_MASK, value) /* Offset 96+23=119, Len 5 */
+
+/* Fifth 32-bit dword, bits 128:159 (Revision 2 of _PLD only) */
+
+#define ACPI_PLD_GET_VERT_OFFSET(dword) ACPI_GET_BITS (dword, 0, ACPI_16BIT_MASK)
+#define ACPI_PLD_SET_VERT_OFFSET(dword,value) ACPI_SET_BITS (dword, 0, ACPI_16BIT_MASK, value) /* Offset 128+0=128, Len 16 */
+
+#define ACPI_PLD_GET_HORIZ_OFFSET(dword) ACPI_GET_BITS (dword, 16, ACPI_16BIT_MASK)
+#define ACPI_PLD_SET_HORIZ_OFFSET(dword,value) ACPI_SET_BITS (dword, 16, ACPI_16BIT_MASK, value) /* Offset 128+16=144, Len 16 */
+
+#endif /* ACBUFFER_H */
diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h
index d988ac54f41e..745dd24e3cb5 100644
--- a/include/acpi/acnames.h
+++ b/include/acpi/acnames.h
@@ -63,11 +63,10 @@
#define METHOD_NAME__PRW "_PRW"
#define METHOD_NAME__SRS "_SRS"
#define METHOD_NAME__CBA "_CBA"
+#define METHOD_NAME__PLD "_PLD"
/* Method names - these methods must appear at the namespace root */
-#define METHOD_PATHNAME__BFS "\\_BFS"
-#define METHOD_PATHNAME__GTS "\\_GTS"
#define METHOD_PATHNAME__PTS "\\_PTS"
#define METHOD_PATHNAME__SST "\\_SI._SST"
#define METHOD_PATHNAME__WAK "\\_WAK"
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index bde976ee068d..0daa0fbd8654 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -54,37 +54,8 @@ acpi_status
acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event,
u32 status_code, struct acpi_buffer *status_buf);
-struct acpi_pld {
- unsigned int revision:7; /* 0 */
- unsigned int ignore_colour:1; /* 7 */
- unsigned int colour:24; /* 8 */
- unsigned int width:16; /* 32 */
- unsigned int height:16; /* 48 */
- unsigned int user_visible:1; /* 64 */
- unsigned int dock:1; /* 65 */
- unsigned int lid:1; /* 66 */
- unsigned int panel:3; /* 67 */
- unsigned int vertical_pos:2; /* 70 */
- unsigned int horizontal_pos:2; /* 72 */
- unsigned int shape:4; /* 74 */
- unsigned int group_orientation:1; /* 78 */
- unsigned int group_token:8; /* 79 */
- unsigned int group_position:8; /* 87 */
- unsigned int bay:1; /* 95 */
- unsigned int ejectable:1; /* 96 */
- unsigned int ospm_eject_required:1; /* 97 */
- unsigned int cabinet_number:8; /* 98 */
- unsigned int card_cage_number:8; /* 106 */
- unsigned int reference:1; /* 114 */
- unsigned int rotation:4; /* 115 */
- unsigned int order:5; /* 119 */
- unsigned int reserved:4; /* 124 */
- unsigned int vertical_offset:16; /* 128 */
- unsigned int horizontal_offset:16; /* 144 */
-} __attribute__((__packed__));
-
acpi_status
-acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld *pld);
+acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld);
#ifdef CONFIG_ACPI
#include <linux/proc_fs.h>
@@ -208,6 +179,7 @@ struct acpi_device_pnp {
struct list_head ids; /* _HID and _CIDs */
acpi_device_name device_name; /* Driver-determined */
acpi_device_class device_class; /* " */
+ union acpi_object *str_obj; /* unicode string for _STR method */
};
#define acpi_device_bid(d) ((d)->pnp.bus_id)
@@ -282,8 +254,16 @@ struct acpi_device_wakeup {
int prepare_count;
};
-/* Device */
+struct acpi_device_physical_node {
+ u8 node_id;
+ struct list_head node;
+ struct device *dev;
+};
+
+/* set maximum of physical nodes to 32 for expansibility */
+#define ACPI_MAX_PHYSICAL_NODE 32
+/* Device */
struct acpi_device {
int device_type;
acpi_handle handle; /* no handle for fixed hardware */
@@ -304,6 +284,10 @@ struct acpi_device {
struct device dev;
struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */
enum acpi_bus_removal_type removal_type; /* indicate for different removal type */
+ u8 physical_node_count;
+ struct list_head physical_node_list;
+ struct mutex physical_node_lock;
+ DECLARE_BITMAP(physical_node_id_bitmap, ACPI_MAX_PHYSICAL_NODE);
};
static inline void *acpi_driver_data(struct acpi_device *d)
@@ -381,6 +365,19 @@ int acpi_match_device_ids(struct acpi_device *device,
int acpi_create_dir(struct acpi_device *);
void acpi_remove_dir(struct acpi_device *);
+
+/**
+ * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver
+ * @__acpi_driver: acpi_driver struct
+ *
+ * Helper macro for ACPI drivers which do not do anything special in module
+ * init/exit. This eliminates a lot of boilerplate. Each module may only
+ * use this macro once, and calling it replaces module_init() and module_exit()
+ */
+#define module_acpi_driver(__acpi_driver) \
+ module_driver(__acpi_driver, acpi_bus_register_driver, \
+ acpi_bus_unregister_driver)
+
/*
* Bind physical devices with ACPI devices
*/
@@ -394,7 +391,6 @@ struct acpi_bus_type {
};
int register_acpi_bus_type(struct acpi_bus_type *);
int unregister_acpi_bus_type(struct acpi_bus_type *);
-struct device *acpi_get_physical_device(acpi_handle);
struct acpi_pci_root {
struct list_head node;
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 26a92fc28a59..267bfc4b26a9 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -47,11 +47,12 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20120711
+#define ACPI_CA_VERSION 0x20120913
#include "acconfig.h"
#include "actypes.h"
#include "actbl.h"
+#include "acbuffer.h"
extern u8 acpi_gbl_permanent_mmap;
@@ -144,6 +145,10 @@ acpi_check_address_range(acpi_adr_space_type space_id,
acpi_physical_address address,
acpi_size length, u8 warn);
+acpi_status
+acpi_decode_pld_buffer(u8 *in_buffer,
+ acpi_size length, struct acpi_pld_info **return_buffer);
+
/*
* ACPI Memory management
*/
diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h
index 59a73e1b2845..4f94b1d812d5 100644
--- a/include/acpi/actbl.h
+++ b/include/acpi/actbl.h
@@ -79,9 +79,15 @@
#pragma pack(1)
/*
- * Note about bitfields: The u8 type is used for bitfields in ACPI tables.
- * This is the only type that is even remotely portable. Anything else is not
- * portable, so do not use any other bitfield types.
+ * Note: C bitfields are not used for this reason:
+ *
+ * "Bitfields are great and easy to read, but unfortunately the C language
+ * does not specify the layout of bitfields in memory, which means they are
+ * essentially useless for dealing with packed data in on-disk formats or
+ * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me,
+ * this decision was a design error in C. Ritchie could have picked an order
+ * and stuck with it." Norman Ramsey.
+ * See http://stackoverflow.com/a/1053662/41661
*/
/*******************************************************************************
@@ -94,7 +100,7 @@
struct acpi_table_header {
char signature[ACPI_NAME_SIZE]; /* ASCII table signature */
u32 length; /* Length of table in bytes, including this header */
- u8 revision; /* ACPI Specification minor version # */
+ u8 revision; /* ACPI Specification minor version number */
u8 checksum; /* To make sum of entire table == 0 */
char oem_id[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */
@@ -108,7 +114,7 @@ struct acpi_table_header {
* GAS - Generic Address Structure (ACPI 2.0+)
*
* Note: Since this structure is used in the ACPI tables, it is byte aligned.
- * If misaliged access is not supported by the hardware, accesses to the
+ * If misaligned access is not supported by the hardware, accesses to the
* 64-bit Address field must be performed with care.
*
******************************************************************************/
@@ -210,18 +216,18 @@ struct acpi_table_fadt {
u8 preferred_profile; /* Conveys preferred power management profile to OSPM. */
u16 sci_interrupt; /* System vector of SCI interrupt */
u32 smi_command; /* 32-bit Port address of SMI command port */
- u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */
- u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */
- u8 s4_bios_request; /* Value to write to SMI CMD to enter S4BIOS state */
+ u8 acpi_enable; /* Value to write to SMI_CMD to enable ACPI */
+ u8 acpi_disable; /* Value to write to SMI_CMD to disable ACPI */
+ u8 s4_bios_request; /* Value to write to SMI_CMD to enter S4BIOS state */
u8 pstate_control; /* Processor performance state control */
- u32 pm1a_event_block; /* 32-bit Port address of Power Mgt 1a Event Reg Blk */
- u32 pm1b_event_block; /* 32-bit Port address of Power Mgt 1b Event Reg Blk */
- u32 pm1a_control_block; /* 32-bit Port address of Power Mgt 1a Control Reg Blk */
- u32 pm1b_control_block; /* 32-bit Port address of Power Mgt 1b Control Reg Blk */
- u32 pm2_control_block; /* 32-bit Port address of Power Mgt 2 Control Reg Blk */
- u32 pm_timer_block; /* 32-bit Port address of Power Mgt Timer Ctrl Reg Blk */
- u32 gpe0_block; /* 32-bit Port address of General Purpose Event 0 Reg Blk */
- u32 gpe1_block; /* 32-bit Port address of General Purpose Event 1 Reg Blk */
+ u32 pm1a_event_block; /* 32-bit port address of Power Mgt 1a Event Reg Blk */
+ u32 pm1b_event_block; /* 32-bit port address of Power Mgt 1b Event Reg Blk */
+ u32 pm1a_control_block; /* 32-bit port address of Power Mgt 1a Control Reg Blk */
+ u32 pm1b_control_block; /* 32-bit port address of Power Mgt 1b Control Reg Blk */
+ u32 pm2_control_block; /* 32-bit port address of Power Mgt 2 Control Reg Blk */
+ u32 pm_timer_block; /* 32-bit port address of Power Mgt Timer Ctrl Reg Blk */
+ u32 gpe0_block; /* 32-bit port address of General Purpose Event 0 Reg Blk */
+ u32 gpe1_block; /* 32-bit port address of General Purpose Event 1 Reg Blk */
u8 pm1_event_length; /* Byte Length of ports at pm1x_event_block */
u8 pm1_control_length; /* Byte Length of ports at pm1x_control_block */
u8 pm2_control_length; /* Byte Length of ports at pm2_control_block */
@@ -229,12 +235,12 @@ struct acpi_table_fadt {
u8 gpe0_block_length; /* Byte Length of ports at gpe0_block */
u8 gpe1_block_length; /* Byte Length of ports at gpe1_block */
u8 gpe1_base; /* Offset in GPE number space where GPE1 events start */
- u8 cst_control; /* Support for the _CST object and C States change notification */
+ u8 cst_control; /* Support for the _CST object and C-States change notification */
u16 c2_latency; /* Worst case HW latency to enter/exit C2 state */
u16 c3_latency; /* Worst case HW latency to enter/exit C3 state */
- u16 flush_size; /* Processor's memory cache line width, in bytes */
+ u16 flush_size; /* Processor memory cache line width, in bytes */
u16 flush_stride; /* Number of flush strides that need to be read */
- u8 duty_offset; /* Processor duty cycle index in processor's P_CNT reg */
+ u8 duty_offset; /* Processor duty cycle index in processor P_CNT reg */
u8 duty_width; /* Processor duty cycle value bit width in P_CNT register */
u8 day_alarm; /* Index to day-of-month alarm in RTC CMOS RAM */
u8 month_alarm; /* Index to month-of-year alarm in RTC CMOS RAM */
@@ -255,11 +261,11 @@ struct acpi_table_fadt {
struct acpi_generic_address xpm_timer_block; /* 64-bit Extended Power Mgt Timer Ctrl Reg Blk address */
struct acpi_generic_address xgpe0_block; /* 64-bit Extended General Purpose Event 0 Reg Blk address */
struct acpi_generic_address xgpe1_block; /* 64-bit Extended General Purpose Event 1 Reg Blk address */
- struct acpi_generic_address sleep_control; /* 64-bit Sleep Control register */
- struct acpi_generic_address sleep_status; /* 64-bit Sleep Status register */
+ struct acpi_generic_address sleep_control; /* 64-bit Sleep Control register (ACPI 5.0) */
+ struct acpi_generic_address sleep_status; /* 64-bit Sleep Status register (ACPI 5.0) */
};
-/* Masks for FADT Boot Architecture Flags (boot_flags) */
+/* Masks for FADT Boot Architecture Flags (boot_flags) [Vx]=Introduced in this FADT revision */
#define ACPI_FADT_LEGACY_DEVICES (1) /* 00: [V2] System has LPC or ISA bus devices */
#define ACPI_FADT_8042 (1<<1) /* 01: [V3] System has an 8042 controller on port 60/64 */
@@ -272,13 +278,13 @@ struct acpi_table_fadt {
/* Masks for FADT flags */
-#define ACPI_FADT_WBINVD (1) /* 00: [V1] The wbinvd instruction works properly */
-#define ACPI_FADT_WBINVD_FLUSH (1<<1) /* 01: [V1] wbinvd flushes but does not invalidate caches */
+#define ACPI_FADT_WBINVD (1) /* 00: [V1] The WBINVD instruction works properly */
+#define ACPI_FADT_WBINVD_FLUSH (1<<1) /* 01: [V1] WBINVD flushes but does not invalidate caches */
#define ACPI_FADT_C1_SUPPORTED (1<<2) /* 02: [V1] All processors support C1 state */
#define ACPI_FADT_C2_MP_SUPPORTED (1<<3) /* 03: [V1] C2 state works on MP system */
#define ACPI_FADT_POWER_BUTTON (1<<4) /* 04: [V1] Power button is handled as a control method device */
#define ACPI_FADT_SLEEP_BUTTON (1<<5) /* 05: [V1] Sleep button is handled as a control method device */
-#define ACPI_FADT_FIXED_RTC (1<<6) /* 06: [V1] RTC wakeup status not in fixed register space */
+#define ACPI_FADT_FIXED_RTC (1<<6) /* 06: [V1] RTC wakeup status is not in fixed register space */
#define ACPI_FADT_S4_RTC_WAKE (1<<7) /* 07: [V1] RTC alarm can wake system from S4 */
#define ACPI_FADT_32BIT_TIMER (1<<8) /* 08: [V1] ACPI timer width is 32-bit (0=24-bit) */
#define ACPI_FADT_DOCKING_SUPPORTED (1<<9) /* 09: [V1] Docking supported */
@@ -297,7 +303,7 @@ struct acpi_table_fadt {
/* Values for preferred_profile (Preferred Power Management Profiles) */
-enum acpi_prefered_pm_profiles {
+enum acpi_preferred_pm_profiles {
PM_UNSPECIFIED = 0,
PM_DESKTOP = 1,
PM_MOBILE = 2,
@@ -335,7 +341,7 @@ union acpi_name_union {
struct acpi_table_desc {
acpi_physical_address address;
struct acpi_table_header *pointer;
- u32 length; /* Length fixed at 32 bits */
+ u32 length; /* Length fixed at 32 bits (fixed in table header) */
union acpi_name_union signature;
acpi_owner_id owner_id;
u8 flags;
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index 300d14e7c5d5..280fc45b59dd 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -79,9 +79,15 @@
#pragma pack(1)
/*
- * Note about bitfields: The u8 type is used for bitfields in ACPI tables.
- * This is the only type that is even remotely portable. Anything else is not
- * portable, so do not use any other bitfield types.
+ * Note: C bitfields are not used for this reason:
+ *
+ * "Bitfields are great and easy to read, but unfortunately the C language
+ * does not specify the layout of bitfields in memory, which means they are
+ * essentially useless for dealing with packed data in on-disk formats or
+ * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me,
+ * this decision was a design error in C. Ritchie could have picked an order
+ * and stuck with it." Norman Ramsey.
+ * See http://stackoverflow.com/a/1053662/41661
*/
/*******************************************************************************
@@ -489,7 +495,9 @@ enum acpi_hest_notify_types {
ACPI_HEST_NOTIFY_LOCAL = 2,
ACPI_HEST_NOTIFY_SCI = 3,
ACPI_HEST_NOTIFY_NMI = 4,
- ACPI_HEST_NOTIFY_RESERVED = 5 /* 5 and greater are reserved */
+ ACPI_HEST_NOTIFY_CMCI = 5, /* ACPI 5.0 */
+ ACPI_HEST_NOTIFY_MCE = 6, /* ACPI 5.0 */
+ ACPI_HEST_NOTIFY_RESERVED = 7 /* 7 and greater are reserved */
};
/* Values for config_write_enable bitfield above */
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index d9ceb3d31629..1b2b356486d1 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -63,6 +63,8 @@
*/
#define ACPI_SIG_ASF "ASF!" /* Alert Standard Format table */
#define ACPI_SIG_BOOT "BOOT" /* Simple Boot Flag Table */
+#define ACPI_SIG_CSRT "CSRT" /* Core System Resource Table */
+#define ACPI_SIG_DBG2 "DBG2" /* Debug Port table type 2 */
#define ACPI_SIG_DBGP "DBGP" /* Debug Port table */
#define ACPI_SIG_DMAR "DMAR" /* DMA Remapping table */
#define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */
@@ -96,9 +98,15 @@
#pragma pack(1)
/*
- * Note about bitfields: The u8 type is used for bitfields in ACPI tables.
- * This is the only type that is even remotely portable. Anything else is not
- * portable, so do not use any other bitfield types.
+ * Note: C bitfields are not used for this reason:
+ *
+ * "Bitfields are great and easy to read, but unfortunately the C language
+ * does not specify the layout of bitfields in memory, which means they are
+ * essentially useless for dealing with packed data in on-disk formats or
+ * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me,
+ * this decision was a design error in C. Ritchie could have picked an order
+ * and stuck with it." Norman Ramsey.
+ * See http://stackoverflow.com/a/1053662/41661
*/
/*******************************************************************************
@@ -232,6 +240,115 @@ struct acpi_table_boot {
/*******************************************************************************
*
+ * CSRT - Core System Resource Table
+ * Version 0
+ *
+ * Conforms to the "Core System Resource Table (CSRT)", November 14, 2011
+ *
+ ******************************************************************************/
+
+struct acpi_table_csrt {
+ struct acpi_table_header header; /* Common ACPI table header */
+};
+
+/* Resource Group subtable */
+
+struct acpi_csrt_group {
+ u32 length;
+ u32 vendor_id;
+ u32 subvendor_id;
+ u16 device_id;
+ u16 subdevice_id;
+ u16 revision;
+ u16 reserved;
+ u32 info_length;
+
+ /* Shared data (length = info_length) immediately follows */
+};
+
+/* Resource Descriptor subtable */
+
+struct acpi_csrt_descriptor {
+ u32 length;
+ u16 type;
+ u16 subtype;
+ u32 uid;
+
+ /* Resource-specific information immediately follows */
+};
+
+/* Resource Types */
+
+#define ACPI_CSRT_TYPE_INTERRUPT 0x0001
+#define ACPI_CSRT_TYPE_TIMER 0x0002
+#define ACPI_CSRT_TYPE_DMA 0x0003
+
+/* Resource Subtypes */
+
+#define ACPI_CSRT_XRUPT_LINE 0x0000
+#define ACPI_CSRT_XRUPT_CONTROLLER 0x0001
+#define ACPI_CSRT_TIMER 0x0000
+#define ACPI_CSRT_DMA_CHANNEL 0x0000
+#define ACPI_CSRT_DMA_CONTROLLER 0x0001
+
+/*******************************************************************************
+ *
+ * DBG2 - Debug Port Table 2
+ * Version 0 (Both main table and subtables)
+ *
+ * Conforms to "Microsoft Debug Port Table 2 (DBG2)", May 22 2012.
+ *
+ ******************************************************************************/
+
+struct acpi_table_dbg2 {
+ struct acpi_table_header header; /* Common ACPI table header */
+ u32 info_offset;
+ u32 info_count;
+};
+
+/* Debug Device Information Subtable */
+
+struct acpi_dbg2_device {
+ u8 revision;
+ u16 length;
+ u8 register_count; /* Number of base_address registers */
+ u16 namepath_length;
+ u16 namepath_offset;
+ u16 oem_data_length;
+ u16 oem_data_offset;
+ u16 port_type;
+ u16 port_subtype;
+ u16 reserved;
+ u16 base_address_offset;
+ u16 address_size_offset;
+ /*
+ * Data that follows:
+ * base_address (required) - Each in 12-byte Generic Address Structure format.
+ * address_size (required) - Array of u32 sizes corresponding to each base_address register.
+ * Namepath (required) - Null terminated string. Single dot if not supported.
+ * oem_data (optional) - Length is oem_data_length.
+ */
+};
+
+/* Types for port_type field above */
+
+#define ACPI_DBG2_SERIAL_PORT 0x8000
+#define ACPI_DBG2_1394_PORT 0x8001
+#define ACPI_DBG2_USB_PORT 0x8002
+#define ACPI_DBG2_NET_PORT 0x8003
+
+/* Subtypes for port_subtype field above */
+
+#define ACPI_DBG2_16550_COMPATIBLE 0x0000
+#define ACPI_DBG2_16550_SUBSET 0x0001
+
+#define ACPI_DBG2_1394_STANDARD 0x0000
+
+#define ACPI_DBG2_USB_XHCI 0x0000
+#define ACPI_DBG2_USB_EHCI 0x0001
+
+/*******************************************************************************
+ *
* DBGP - Debug Port table
* Version 1
*
diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h
index f65a0ed869eb..8c61b5fe42a4 100644
--- a/include/acpi/actbl3.h
+++ b/include/acpi/actbl3.h
@@ -75,7 +75,6 @@
/* Reserved table signatures */
#define ACPI_SIG_CSRT "CSRT" /* Core System Resources Table */
-#define ACPI_SIG_DBG2 "DBG2" /* Debug Port table 2 */
#define ACPI_SIG_MATR "MATR" /* Memory Address Translation Table */
#define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */
#define ACPI_SIG_WPBT "WPBT" /* Windows Platform Binary Table */
@@ -87,9 +86,15 @@
#pragma pack(1)
/*
- * Note about bitfields: The u8 type is used for bitfields in ACPI tables.
- * This is the only type that is even remotely portable. Anything else is not
- * portable, so do not use any other bitfield types.
+ * Note: C bitfields are not used for this reason:
+ *
+ * "Bitfields are great and easy to read, but unfortunately the C language
+ * does not specify the layout of bitfields in memory, which means they are
+ * essentially useless for dealing with packed data in on-disk formats or
+ * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me,
+ * this decision was a design error in C. Ritchie could have picked an order
+ * and stuck with it." Norman Ramsey.
+ * See http://stackoverflow.com/a/1053662/41661
*/
/*******************************************************************************
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 3d00bd5bd7e3..a85bae968262 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -519,13 +519,6 @@ typedef u64 acpi_integer;
#define ACPI_SLEEP_TYPE_INVALID 0xFF
/*
- * Sleep/Wake flags
- */
-#define ACPI_NO_OPTIONAL_METHODS 0x00 /* Do not execute any optional methods */
-#define ACPI_EXECUTE_GTS 0x01 /* For enter sleep interface */
-#define ACPI_EXECUTE_BFS 0x02 /* For leave sleep prep interface */
-
-/*
* Standard notify values
*/
#define ACPI_NOTIFY_BUS_CHECK (u8) 0x00
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 7e83370e6fd2..f3b99e1c1042 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -256,72 +256,78 @@ static inline void iommu_set_fault_handler(struct iommu_domain *domain,
{
}
-int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group)
+static inline int iommu_attach_group(struct iommu_domain *domain,
+ struct iommu_group *group)
{
return -ENODEV;
}
-void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group)
+static inline void iommu_detach_group(struct iommu_domain *domain,
+ struct iommu_group *group)
{
}
-struct iommu_group *iommu_group_alloc(void)
+static inline struct iommu_group *iommu_group_alloc(void)
{
return ERR_PTR(-ENODEV);
}
-void *iommu_group_get_iommudata(struct iommu_group *group)
+static inline void *iommu_group_get_iommudata(struct iommu_group *group)
{
return NULL;
}
-void iommu_group_set_iommudata(struct iommu_group *group, void *iommu_data,
- void (*release)(void *iommu_data))
+static inline void iommu_group_set_iommudata(struct iommu_group *group,
+ void *iommu_data,
+ void (*release)(void *iommu_data))
{
}
-int iommu_group_set_name(struct iommu_group *group, const char *name)
+static inline int iommu_group_set_name(struct iommu_group *group,
+ const char *name)
{
return -ENODEV;
}
-int iommu_group_add_device(struct iommu_group *group, struct device *dev)
+static inline int iommu_group_add_device(struct iommu_group *group,
+ struct device *dev)
{
return -ENODEV;
}
-void iommu_group_remove_device(struct device *dev)
+static inline void iommu_group_remove_device(struct device *dev)
{
}
-int iommu_group_for_each_dev(struct iommu_group *group, void *data,
- int (*fn)(struct device *, void *))
+static inline int iommu_group_for_each_dev(struct iommu_group *group,
+ void *data,
+ int (*fn)(struct device *, void *))
{
return -ENODEV;
}
-struct iommu_group *iommu_group_get(struct device *dev)
+static inline struct iommu_group *iommu_group_get(struct device *dev)
{
return NULL;
}
-void iommu_group_put(struct iommu_group *group)
+static inline void iommu_group_put(struct iommu_group *group)
{
}
-int iommu_group_register_notifier(struct iommu_group *group,
- struct notifier_block *nb)
+static inline int iommu_group_register_notifier(struct iommu_group *group,
+ struct notifier_block *nb)
{
return -ENODEV;
}
-int iommu_group_unregister_notifier(struct iommu_group *group,
- struct notifier_block *nb)
+static inline int iommu_group_unregister_notifier(struct iommu_group *group,
+ struct notifier_block *nb)
{
return 0;
}
-int iommu_group_id(struct iommu_group *group)
+static inline int iommu_group_id(struct iommu_group *group)
{
return -ENODEV;
}
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 9490a00529f4..c25cccaa555a 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -35,8 +35,10 @@ struct nvme_bar {
__u64 acq; /* Admin CQ Base Address */
};
+#define NVME_CAP_MQES(cap) ((cap) & 0xffff)
#define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff)
#define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf)
+#define NVME_CAP_MPSMIN(cap) (((cap) >> 48) & 0xf)
enum {
NVME_CC_ENABLE = 1 << 0,
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 57c4b9309015..141dbb695097 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1811,7 +1811,6 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page,
src_page = pte_page(pteval);
copy_user_highpage(page, src_page, address, vma);
VM_BUG_ON(page_mapcount(src_page) != 1);
- VM_BUG_ON(page_count(src_page) != 2);
release_pte_page(src_page);
/*
* ptl mostly unnecessary, but preempt has to
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index e1e0a4e8fd34..c7527f6b9ad9 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -510,7 +510,10 @@ relookup:
secure_ipv6_id(daddr->addr.a6));
p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
p->rate_tokens = 0;
- p->rate_last = 0;
+ /* 60*HZ is arbitrary, but chosen enough high so that the first
+ * calculation of tokens is at its maximum.
+ */
+ p->rate_last = jiffies - 60*HZ;
INIT_LIST_HEAD(&p->gc_list);
/* Link the node. */
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index d71cd9229a47..6f936358d664 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -80,8 +80,8 @@ static int l2tp_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
&l2tp_nl_family, 0, L2TP_CMD_NOOP);
- if (IS_ERR(hdr)) {
- ret = PTR_ERR(hdr);
+ if (!hdr) {
+ ret = -EMSGSIZE;
goto err_out;
}
@@ -250,8 +250,8 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags,
hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags,
L2TP_CMD_TUNNEL_GET);
- if (IS_ERR(hdr))
- return PTR_ERR(hdr);
+ if (!hdr)
+ return -EMSGSIZE;
if (nla_put_u8(skb, L2TP_ATTR_PROTO_VERSION, tunnel->version) ||
nla_put_u32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id) ||
@@ -617,8 +617,8 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 pid, u32 seq, int flags
sk = tunnel->sock;
hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags, L2TP_CMD_SESSION_GET);
- if (IS_ERR(hdr))
- return PTR_ERR(hdr);
+ if (!hdr)
+ return -EMSGSIZE;
if (nla_put_u32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id) ||
nla_put_u32(skb, L2TP_ATTR_SESSION_ID, session->session_id) ||
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 5c22ce8ab309..a4c1e4528cac 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -117,11 +117,11 @@ static int limit_mt_check(const struct xt_mtchk_param *par)
/* For SMP, we only want to use one set of state. */
r->master = priv;
+ /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
+ 128. */
+ priv->prev = jiffies;
+ priv->credit = user2credits(r->avg * r->burst); /* Credits full. */
if (r->cost == 0) {
- /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
- 128. */
- priv->prev = jiffies;
- priv->credit = user2credits(r->avg * r->burst); /* Credits full. */
r->credit_cap = priv->credit; /* Credits full. */
r->cost = user2credits(r->avg);
}
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 3fd5b29dc933..a3acb7a85f6a 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -702,7 +702,7 @@ static bool wm2000_readable_reg(struct device *dev, unsigned int reg)
}
static const struct regmap_config wm2000_regmap = {
- .reg_bits = 8,
+ .reg_bits = 16,
.val_bits = 8,
.max_register = WM2000_REG_IF_CTL,
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index d6e2bb49c59c..060dccb9ec75 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -197,7 +197,13 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep,
/* no data provider, so send silence */
unsigned int offs = 0;
for (i = 0; i < ctx->packets; ++i) {
- int counts = ctx->packet_size[i];
+ int counts;
+
+ if (ctx->packet_size[i])
+ counts = ctx->packet_size[i];
+ else
+ counts = snd_usb_endpoint_next_packet_size(ep);
+
urb->iso_frame_desc[i].offset = offs * ep->stride;
urb->iso_frame_desc[i].length = counts * ep->stride;
offs += counts;
diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile
new file mode 100644
index 000000000000..6b9cf7a987c7
--- /dev/null
+++ b/tools/power/acpi/Makefile
@@ -0,0 +1,18 @@
+PROG= acpidump
+SRCS= acpidump.c
+KERNEL_INCLUDE := ../../../include
+CFLAGS += -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Os -s -D_LINUX -DDEFINE_ALTERNATE_TYPES -I$(KERNEL_INCLUDE)
+
+all: acpidump
+$(PROG) : $(SRCS)
+ $(CC) $(CFLAGS) $(SRCS) -o $(PROG)
+
+CLEANFILES= $(PROG)
+
+clean :
+ rm -f $(CLEANFILES) $(patsubst %.c,%.o, $(SRCS)) *~
+
+install :
+ install acpidump /usr/bin/acpidump
+ install acpidump.8 /usr/share/man/man8
+
diff --git a/tools/power/acpi/acpidump.8 b/tools/power/acpi/acpidump.8
new file mode 100644
index 000000000000..adfa99166e5e
--- /dev/null
+++ b/tools/power/acpi/acpidump.8
@@ -0,0 +1,59 @@
+.TH ACPIDUMP 8
+.SH NAME
+acpidump \- Dump system's ACPI tables to an ASCII file.
+.SH SYNOPSIS
+.ft B
+.B acpidump > acpidump.out
+.SH DESCRIPTION
+\fBacpidump \fP dumps the systems ACPI tables to an ASCII file
+appropriate for attaching to a bug report.
+
+Subsequently, they can be processed by utilities in the ACPICA package.
+.SS Options
+no options worth worrying about.
+.PP
+.SH EXAMPLE
+
+.nf
+# acpidump > acpidump.out
+
+$ acpixtract -a acpidump.out
+ Acpi table [DSDT] - 15974 bytes written to DSDT.dat
+ Acpi table [FACS] - 64 bytes written to FACS.dat
+ Acpi table [FACP] - 116 bytes written to FACP.dat
+ Acpi table [APIC] - 120 bytes written to APIC.dat
+ Acpi table [MCFG] - 60 bytes written to MCFG.dat
+ Acpi table [SSDT] - 444 bytes written to SSDT1.dat
+ Acpi table [SSDT] - 439 bytes written to SSDT2.dat
+ Acpi table [SSDT] - 439 bytes written to SSDT3.dat
+ Acpi table [SSDT] - 439 bytes written to SSDT4.dat
+ Acpi table [SSDT] - 439 bytes written to SSDT5.dat
+ Acpi table [RSDT] - 76 bytes written to RSDT.dat
+ Acpi table [RSDP] - 20 bytes written to RSDP.dat
+
+$ iasl -d *.dat
+...
+.fi
+creates *.dsl, a human readable form which can be edited
+and compiled using iasl.
+
+
+.SH NOTES
+
+.B "acpidump "
+must be run as root.
+
+.SH REFERENCES
+ACPICA: https://acpica.org/
+
+.SH FILES
+.ta
+.nf
+/dev/mem
+/sys/firmware/acpi/tables/dynamic/*
+.fi
+
+.PP
+.SH AUTHOR
+.nf
+Written by Len Brown <len.brown@intel.com>
diff --git a/tools/power/acpi/acpidump.c b/tools/power/acpi/acpidump.c
new file mode 100644
index 000000000000..07779871421c
--- /dev/null
+++ b/tools/power/acpi/acpidump.c
@@ -0,0 +1,560 @@
+/*
+ * (c) Alexey Starikovskiy, Intel, 2005-2006.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifdef DEFINE_ALTERNATE_TYPES
+/* hack to enable building old application with new headers -lenb */
+#define acpi_fadt_descriptor acpi_table_fadt
+#define acpi_rsdp_descriptor acpi_table_rsdp
+#define DSDT_SIG ACPI_SIG_DSDT
+#define FACS_SIG ACPI_SIG_FACS
+#define FADT_SIG ACPI_SIG_FADT
+#define xfirmware_ctrl Xfacs
+#define firmware_ctrl facs
+
+typedef int s32;
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+typedef long long s64;
+#endif
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <acpi/acconfig.h>
+#include <acpi/platform/acenv.h>
+#include <acpi/actypes.h>
+#include <acpi/actbl.h>
+
+static inline u8 checksum(u8 * buffer, u32 length)
+{
+ u8 sum = 0, *i = buffer;
+ buffer += length;
+ for (; i < buffer; sum += *(i++));
+ return sum;
+}
+
+static unsigned long psz, addr, length;
+static int print, connect, skip;
+static u8 select_sig[4];
+
+static unsigned long read_efi_systab( void )
+{
+ char buffer[80];
+ unsigned long addr;
+ FILE *f = fopen("/sys/firmware/efi/systab", "r");
+ if (f) {
+ while (fgets(buffer, 80, f)) {
+ if (sscanf(buffer, "ACPI20=0x%lx", &addr) == 1)
+ return addr;
+ }
+ fclose(f);
+ }
+ return 0;
+}
+
+static u8 *acpi_map_memory(unsigned long where, unsigned length)
+{
+ unsigned long offset;
+ u8 *there;
+ int fd = open("/dev/mem", O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "acpi_os_map_memory: cannot open /dev/mem\n");
+ exit(1);
+ }
+ offset = where % psz;
+ there = mmap(NULL, length + offset, PROT_READ, MAP_PRIVATE,
+ fd, where - offset);
+ close(fd);
+ if (there == MAP_FAILED) return 0;
+ return (there + offset);
+}
+
+static void acpi_unmap_memory(u8 * there, unsigned length)
+{
+ unsigned long offset = (unsigned long)there % psz;
+ munmap(there - offset, length + offset);
+}
+
+static struct acpi_table_header *acpi_map_table(unsigned long where, char *sig)
+{
+ unsigned size;
+ struct acpi_table_header *tbl = (struct acpi_table_header *)
+ acpi_map_memory(where, sizeof(struct acpi_table_header));
+ if (!tbl || (sig && memcmp(sig, tbl->signature, 4))) return 0;
+ size = tbl->length;
+ acpi_unmap_memory((u8 *) tbl, sizeof(struct acpi_table_header));
+ return (struct acpi_table_header *)acpi_map_memory(where, size);
+}
+
+static void acpi_unmap_table(struct acpi_table_header *tbl)
+{
+ acpi_unmap_memory((u8 *)tbl, tbl->length);
+}
+
+static struct acpi_rsdp_descriptor *acpi_scan_for_rsdp(u8 *begin, u32 length)
+{
+ struct acpi_rsdp_descriptor *rsdp;
+ u8 *i, *end = begin + length;
+ /* Search from given start address for the requested length */
+ for (i = begin; i < end; i += ACPI_RSDP_SCAN_STEP) {
+ /* The signature and checksum must both be correct */
+ if (memcmp((char *)i, "RSD PTR ", 8)) continue;
+ rsdp = (struct acpi_rsdp_descriptor *)i;
+ /* Signature matches, check the appropriate checksum */
+ if (!checksum((u8 *) rsdp, (rsdp->revision < 2) ?
+ ACPI_RSDP_CHECKSUM_LENGTH :
+ ACPI_RSDP_XCHECKSUM_LENGTH))
+ /* Checksum valid, we have found a valid RSDP */
+ return rsdp;
+ }
+ /* Searched entire block, no RSDP was found */
+ return 0;
+}
+
+/*
+ * Output data
+ */
+static void acpi_show_data(int fd, u8 * data, int size)
+{
+ char buffer[256];
+ int len;
+ int i, remain = size;
+ while (remain > 0) {
+ len = snprintf(buffer, 256, " %04x:", size - remain);
+ for (i = 0; i < 16 && i < remain; i++) {
+ len +=
+ snprintf(&buffer[len], 256 - len, " %02x", data[i]);
+ }
+ for (; i < 16; i++) {
+ len += snprintf(&buffer[len], 256 - len, " ");
+ }
+ len += snprintf(&buffer[len], 256 - len, " ");
+ for (i = 0; i < 16 && i < remain; i++) {
+ buffer[len++] = (isprint(data[i])) ? data[i] : '.';
+ }
+ buffer[len++] = '\n';
+ write(fd, buffer, len);
+ data += 16;
+ remain -= 16;
+ }
+}
+
+/*
+ * Output ACPI table
+ */
+static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr)
+{
+ char buff[80];
+ int len = snprintf(buff, 80, "%.4s @ %p\n", table->signature, (void *)addr);
+ write(fd, buff, len);
+ acpi_show_data(fd, (u8 *) table, table->length);
+ buff[0] = '\n';
+ write(fd, buff, 1);
+}
+
+static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr)
+{
+ static int select_done = 0;
+ if (!select_sig[0]) {
+ if (print) {
+ acpi_show_table(fd, tbl, addr);
+ } else {
+ write(fd, tbl, tbl->length);
+ }
+ } else if (!select_done && !memcmp(select_sig, tbl->signature, 4)) {
+ if (skip > 0) {
+ --skip;
+ return;
+ }
+ if (print) {
+ acpi_show_table(fd, tbl, addr);
+ } else {
+ write(fd, tbl, tbl->length);
+ }
+ select_done = 1;
+ }
+}
+
+static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) {
+ struct acpi_fadt_descriptor x;
+ unsigned long addr;
+ size_t len = sizeof(struct acpi_fadt_descriptor);
+ if (len > tbl->length) len = tbl->length;
+ memcpy(&x, tbl, len);
+ x.header.length = len;
+ if (checksum((u8 *)tbl, len)) {
+ fprintf(stderr, "Wrong checksum for FADT!\n");
+ }
+ if (x.header.length >= 148 && x.Xdsdt) {
+ addr = (unsigned long)x.Xdsdt;
+ if (connect) {
+ x.Xdsdt = lseek(fd, 0, SEEK_CUR);
+ }
+ } else if (x.header.length >= 44 && x.dsdt) {
+ addr = (unsigned long)x.dsdt;
+ if (connect) {
+ x.dsdt = lseek(fd, 0, SEEK_CUR);
+ }
+ } else {
+ fprintf(stderr, "No DSDT in FADT!\n");
+ goto no_dsdt;
+ }
+ tbl = acpi_map_table(addr, DSDT_SIG);
+ if (!tbl) goto no_dsdt;
+ if (checksum((u8 *)tbl, tbl->length))
+ fprintf(stderr, "Wrong checksum for DSDT!\n");
+ write_table(fd, tbl, addr);
+ acpi_unmap_table(tbl);
+no_dsdt:
+ if (x.header.length >= 140 && x.xfirmware_ctrl) {
+ addr = (unsigned long)x.xfirmware_ctrl;
+ if (connect) {
+ x.xfirmware_ctrl = lseek(fd, 0, SEEK_CUR);
+ }
+ } else if (x.header.length >= 40 && x.firmware_ctrl) {
+ addr = (unsigned long)x.firmware_ctrl;
+ if (connect) {
+ x.firmware_ctrl = lseek(fd, 0, SEEK_CUR);
+ }
+ } else {
+ fprintf(stderr, "No FACS in FADT!\n");
+ goto no_facs;
+ }
+ tbl = acpi_map_table(addr, FACS_SIG);
+ if (!tbl) goto no_facs;
+ /* do not checksum FACS */
+ write_table(fd, tbl, addr);
+ acpi_unmap_table(tbl);
+no_facs:
+ write_table(fd, (struct acpi_table_header *)&x, xaddr);
+}
+
+static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp)
+{
+ struct acpi_table_header *sdt, *tbl = 0;
+ int xsdt = 1, i, num;
+ char *offset;
+ unsigned long addr;
+ if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
+ tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT");
+ }
+ if (!tbl && rsdp->rsdt_physical_address) {
+ xsdt = 0;
+ tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT");
+ }
+ if (!tbl) return 0;
+ sdt = malloc(tbl->length);
+ memcpy(sdt, tbl, tbl->length);
+ acpi_unmap_table(tbl);
+ if (checksum((u8 *)sdt, sdt->length))
+ fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT");
+ num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32));
+ offset = (char *)sdt + sizeof(struct acpi_table_header);
+ for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) {
+ addr = (xsdt) ? (unsigned long)(*(u64 *)offset):
+ (unsigned long)(*(u32 *)offset);
+ if (!addr) continue;
+ tbl = acpi_map_table(addr, 0);
+ if (!tbl) continue;
+ if (!memcmp(tbl->signature, FADT_SIG, 4)) {
+ acpi_dump_FADT(fd, tbl, addr);
+ } else {
+ if (checksum((u8 *)tbl, tbl->length))
+ fprintf(stderr, "Wrong checksum for generic table!\n");
+ write_table(fd, tbl, addr);
+ }
+ acpi_unmap_table(tbl);
+ if (connect) {
+ if (xsdt)
+ (*(u64*)offset) = lseek(fd, 0, SEEK_CUR);
+ else
+ (*(u32*)offset) = lseek(fd, 0, SEEK_CUR);
+ }
+ }
+ if (xsdt) {
+ addr = (unsigned long)rsdp->xsdt_physical_address;
+ if (connect) {
+ rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR);
+ }
+ } else {
+ addr = (unsigned long)rsdp->rsdt_physical_address;
+ if (connect) {
+ rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR);
+ }
+ }
+ write_table(fd, sdt, addr);
+ free (sdt);
+ return 1;
+}
+
+#define DYNAMIC_SSDT "/sys/firmware/acpi/tables/dynamic"
+
+static void acpi_dump_dynamic_SSDT(int fd)
+{
+ struct stat file_stat;
+ char filename[256], *ptr;
+ DIR *tabledir;
+ struct dirent *entry;
+ FILE *fp;
+ int count, readcount, length;
+ struct acpi_table_header table_header, *ptable;
+
+ if (stat(DYNAMIC_SSDT, &file_stat) == -1) {
+ /* The directory doesn't exist */
+ return;
+ }
+ tabledir = opendir(DYNAMIC_SSDT);
+ if(!tabledir){
+ /*can't open the directory */
+ return;
+ }
+
+ while ((entry = readdir(tabledir)) != 0){
+ /* skip the file of . /.. */
+ if (entry->d_name[0] == '.')
+ continue;
+
+ sprintf(filename, "%s/%s", DYNAMIC_SSDT, entry->d_name);
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "Can't open the file of %s\n",
+ filename);
+ continue;
+ }
+ /* Read the Table header to parse the table length */
+ count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp);
+ if (count < sizeof(table_header)) {
+ /* the length is lessn than ACPI table header. skip it */
+ fclose(fp);
+ continue;
+ }
+ length = table_header.length;
+ ptr = malloc(table_header.length);
+ fseek(fp, 0, SEEK_SET);
+ readcount = 0;
+ while(!feof(fp) && readcount < length) {
+ count = fread(ptr + readcount, 1, 256, fp);
+ readcount += count;
+ }
+ fclose(fp);
+ ptable = (struct acpi_table_header *) ptr;
+ if (checksum((u8 *) ptable, ptable->length))
+ fprintf(stderr, "Wrong checksum "
+ "for dynamic SSDT table!\n");
+ write_table(fd, ptable, 0);
+ free(ptr);
+ }
+ closedir(tabledir);
+ return;
+}
+
+static void usage(const char *progname)
+{
+ puts("Usage:");
+ printf("%s [--addr 0x1234][--table DSDT][--output filename]"
+ "[--binary][--length 0x456][--help]\n", progname);
+ puts("\t--addr 0x1234 or -a 0x1234 -- look for tables at this physical address");
+ puts("\t--table DSDT or -t DSDT -- only dump table with DSDT signature");
+ puts("\t--output filename or -o filename -- redirect output from stdin to filename");
+ puts("\t--binary or -b -- dump data in binary form rather than in hex-dump format");
+ puts("\t--length 0x456 or -l 0x456 -- works only with --addr, dump physical memory"
+ "\n\t\tregion without trying to understand it's contents");
+ puts("\t--skip 2 or -s 2 -- skip 2 tables of the given name and output only 3rd one");
+ puts("\t--help or -h -- this help message");
+ exit(0);
+}
+
+static struct option long_options[] = {
+ {"addr", 1, 0, 0},
+ {"table", 1, 0, 0},
+ {"output", 1, 0, 0},
+ {"binary", 0, 0, 0},
+ {"length", 1, 0, 0},
+ {"skip", 1, 0, 0},
+ {"help", 0, 0, 0},
+ {0, 0, 0, 0}
+};
+int main(int argc, char **argv)
+{
+ int option_index, c, fd;
+ u8 *raw;
+ struct acpi_rsdp_descriptor rsdpx, *x = 0;
+ char *filename = 0;
+ char buff[80];
+ memset(select_sig, 0, 4);
+ print = 1;
+ connect = 0;
+ addr = length = 0;
+ skip = 0;
+ while (1) {
+ option_index = 0;
+ c = getopt_long(argc, argv, "a:t:o:bl:s:h",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 0:
+ switch (option_index) {
+ case 0:
+ addr = strtoul(optarg, (char **)NULL, 16);
+ break;
+ case 1:
+ memcpy(select_sig, optarg, 4);
+ break;
+ case 2:
+ filename = optarg;
+ break;
+ case 3:
+ print = 0;
+ break;
+ case 4:
+ length = strtoul(optarg, (char **)NULL, 16);
+ break;
+ case 5:
+ skip = strtoul(optarg, (char **)NULL, 10);
+ break;
+ case 6:
+ usage(argv[0]);
+ exit(0);
+ }
+ break;
+ case 'a':
+ addr = strtoul(optarg, (char **)NULL, 16);
+ break;
+ case 't':
+ memcpy(select_sig, optarg, 4);
+ break;
+ case 'o':
+ filename = optarg;
+ break;
+ case 'b':
+ print = 0;
+ break;
+ case 'l':
+ length = strtoul(optarg, (char **)NULL, 16);
+ break;
+ case 's':
+ skip = strtoul(optarg, (char **)NULL, 10);
+ break;
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ default:
+ printf("Unknown option!\n");
+ usage(argv[0]);
+ exit(0);
+ }
+ }
+
+ fd = STDOUT_FILENO;
+ if (filename) {
+ fd = creat(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (fd < 0)
+ return fd;
+ }
+
+ if (!select_sig[0] && !print) {
+ connect = 1;
+ }
+
+ psz = sysconf(_SC_PAGESIZE);
+ if (length && addr) {
+ /* We know length and address, it means we just want a memory dump */
+ if (!(raw = acpi_map_memory(addr, length)))
+ goto not_found;
+ write(fd, raw, length);
+ acpi_unmap_memory(raw, length);
+ close(fd);
+ return 0;
+ }
+
+ length = sizeof(struct acpi_rsdp_descriptor);
+ if (!addr) {
+ addr = read_efi_systab();
+ if (!addr) {
+ addr = ACPI_HI_RSDP_WINDOW_BASE;
+ length = ACPI_HI_RSDP_WINDOW_SIZE;
+ }
+ }
+
+ if (!(raw = acpi_map_memory(addr, length)) ||
+ !(x = acpi_scan_for_rsdp(raw, length)))
+ goto not_found;
+
+ /* Find RSDP and print all found tables */
+ memcpy(&rsdpx, x, sizeof(struct acpi_rsdp_descriptor));
+ acpi_unmap_memory(raw, length);
+ if (connect) {
+ lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET);
+ }
+ if (!acpi_dump_SDT(fd, &rsdpx))
+ goto not_found;
+ if (connect) {
+ lseek(fd, 0, SEEK_SET);
+ write(fd, x, (rsdpx.revision < 2) ?
+ ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH);
+ } else if (!select_sig[0] || !memcmp("RSD PTR ", select_sig, 4)) {
+ addr += (long)x - (long)raw;
+ length = snprintf(buff, 80, "RSD PTR @ %p\n", (void *)addr);
+ write(fd, buff, length);
+ acpi_show_data(fd, (u8 *) & rsdpx, (rsdpx.revision < 2) ?
+ ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH);
+ buff[0] = '\n';
+ write(fd, buff, 1);
+ }
+ acpi_dump_dynamic_SSDT(fd);
+ close(fd);
+ return 0;
+not_found:
+ close(fd);
+ fprintf(stderr, "ACPI tables were not found. If you know location "
+ "of RSD PTR table (from dmesg, etc), "
+ "supply it with either --addr or -a option\n");
+ return 1;
+}
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index 74e44507dfe9..e4d0690cccf9 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -4,15 +4,11 @@ turbostat \- Report processor frequency and idle statistics
.SH SYNOPSIS
.ft B
.B turbostat
-.RB [ "\-s" ]
-.RB [ "\-v" ]
-.RB [ "\-M MSR#" ]
+.RB [ Options ]
.RB command
.br
.B turbostat
-.RB [ "\-s" ]
-.RB [ "\-v" ]
-.RB [ "\-M MSR#" ]
+.RB [ Options ]
.RB [ "\-i interval_sec" ]
.SH DESCRIPTION
\fBturbostat \fP reports processor topology, frequency
@@ -27,16 +23,23 @@ supports an "invariant" TSC, plus the APERF and MPERF MSRs.
on processors that additionally support C-state residency counters.
.SS Options
-The \fB-s\fP option limits output to a 1-line system summary for each interval.
+The \fB-p\fP option limits output to the 1st thread in 1st core of each package.
.PP
-The \fB-c\fP option limits output to the 1st thread in each core.
+The \fB-P\fP option limits output to the 1st thread in each Package.
.PP
-The \fB-p\fP option limits output to the 1st thread in each package.
+The \fB-S\fP option limits output to a 1-line System Summary for each interval.
.PP
The \fB-v\fP option increases verbosity.
.PP
-The \fB-M MSR#\fP option dumps the specified MSR,
-in addition to the usual frequency and idle statistics.
+The \fB-s\fP option prints the SMI counter, equivalent to "-c 0x34"
+.PP
+The \fB-c MSR#\fP option includes the delta of the specified 32-bit MSR counter.
+.PP
+The \fB-C MSR#\fP option includes the delta of the specified 64-bit MSR counter.
+.PP
+The \fB-m MSR#\fP option includes the the specified 32-bit MSR value.
+.PP
+The \fB-M MSR#\fP option includes the the specified 64-bit MSR value.
.PP
The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds.
The default is 5 seconds.
@@ -150,6 +153,29 @@ Note that turbostat reports average GHz of 3.63, while
the arithmetic average of the GHz column above is lower.
This is a weighted average, where the weight is %c0. ie. it is the total number of
un-halted cycles elapsed per time divided by the number of CPUs.
+.SH SMI COUNTING EXAMPLE
+On Intel Nehalem and newer processors, MSR 0x34 is a System Management Mode Interrupt (SMI) counter.
+Using the -m option, you can display how many SMIs have fired since reset, or if there
+are SMIs during the measurement interval, you can display the delta using the -d option.
+.nf
+[root@x980 ~]# turbostat -m 0x34
+cor CPU %c0 GHz TSC MSR 0x034 %c1 %c3 %c6 %pc3 %pc6
+ 1.41 1.82 3.38 0x00000000 8.92 37.82 51.85 17.37 0.55
+ 0 0 3.73 2.03 3.38 0x00000055 1.72 48.25 46.31 17.38 0.55
+ 0 6 0.14 1.63 3.38 0x00000056 5.30
+ 1 2 2.51 1.80 3.38 0x00000056 15.65 29.33 52.52
+ 1 8 0.10 1.65 3.38 0x00000056 18.05
+ 2 4 1.16 1.68 3.38 0x00000056 5.87 24.47 68.50
+ 2 10 0.10 1.63 3.38 0x00000056 6.93
+ 8 1 3.84 1.91 3.38 0x00000056 1.36 50.65 44.16
+ 8 7 0.08 1.64 3.38 0x00000056 5.12
+ 9 3 1.82 1.73 3.38 0x00000056 7.59 24.21 66.38
+ 9 9 0.09 1.68 3.38 0x00000056 9.32
+ 10 5 1.66 1.65 3.38 0x00000056 15.10 50.00 33.23
+ 10 11 1.72 1.65 3.38 0x00000056 15.05
+^C
+[root@x980 ~]#
+.fi
.SH NOTES
.B "turbostat "
@@ -165,6 +191,13 @@ may work poorly on Linux-2.6.20 through 2.6.29,
as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF
in those kernels.
+If the TSC column does not make sense, then
+the other numbers will also make no sense.
+Turbostat is lightweight, and its data collection is not atomic.
+These issues are usually caused by an extremely short measurement
+interval (much less than 1 second), or system activity that prevents
+turbostat from being able to run on all CPUS to quickly collect data.
+
The APERF, MPERF MSRs are defined to count non-halted cycles.
Although it is not guaranteed by the architecture, turbostat assumes
that they count at TSC rate, which is true on all processors tested to date.
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 861d77190206..2655ae9a3ad8 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -35,9 +35,9 @@
#include <ctype.h>
#include <sched.h>
-#define MSR_TSC 0x10
#define MSR_NEHALEM_PLATFORM_INFO 0xCE
#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD
+#define MSR_IVT_TURBO_RATIO_LIMIT 0x1AE
#define MSR_APERF 0xE8
#define MSR_MPERF 0xE7
#define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */
@@ -62,7 +62,11 @@ unsigned int genuine_intel;
unsigned int has_invariant_tsc;
unsigned int do_nehalem_platform_info;
unsigned int do_nehalem_turbo_ratio_limit;
-unsigned int extra_msr_offset;
+unsigned int do_ivt_turbo_ratio_limit;
+unsigned int extra_msr_offset32;
+unsigned int extra_msr_offset64;
+unsigned int extra_delta_offset32;
+unsigned int extra_delta_offset64;
double bclk;
unsigned int show_pkg;
unsigned int show_core;
@@ -83,7 +87,10 @@ struct thread_data {
unsigned long long aperf;
unsigned long long mperf;
unsigned long long c1; /* derived */
- unsigned long long extra_msr;
+ unsigned long long extra_msr64;
+ unsigned long long extra_delta64;
+ unsigned long long extra_msr32;
+ unsigned long long extra_delta32;
unsigned int cpu_id;
unsigned int flags;
#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
@@ -222,6 +229,14 @@ void print_header(void)
if (has_aperf)
outp += sprintf(outp, " GHz");
outp += sprintf(outp, " TSC");
+ if (extra_delta_offset32)
+ outp += sprintf(outp, " count 0x%03X", extra_delta_offset32);
+ if (extra_delta_offset64)
+ outp += sprintf(outp, " COUNT 0x%03X", extra_delta_offset64);
+ if (extra_msr_offset32)
+ outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32);
+ if (extra_msr_offset64)
+ outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64);
if (do_nhm_cstates)
outp += sprintf(outp, " %%c1");
if (do_nhm_cstates)
@@ -238,8 +253,6 @@ void print_header(void)
outp += sprintf(outp, " %%pc6");
if (do_snb_cstates)
outp += sprintf(outp, " %%pc7");
- if (extra_msr_offset)
- outp += sprintf(outp, " MSR 0x%x ", extra_msr_offset);
outp += sprintf(outp, "\n");
}
@@ -255,8 +268,14 @@ int dump_counters(struct thread_data *t, struct core_data *c,
fprintf(stderr, "aperf: %016llX\n", t->aperf);
fprintf(stderr, "mperf: %016llX\n", t->mperf);
fprintf(stderr, "c1: %016llX\n", t->c1);
+ fprintf(stderr, "msr0x%x: %08llX\n",
+ extra_delta_offset32, t->extra_delta32);
fprintf(stderr, "msr0x%x: %016llX\n",
- extra_msr_offset, t->extra_msr);
+ extra_delta_offset64, t->extra_delta64);
+ fprintf(stderr, "msr0x%x: %08llX\n",
+ extra_msr_offset32, t->extra_msr32);
+ fprintf(stderr, "msr0x%x: %016llX\n",
+ extra_msr_offset64, t->extra_msr64);
}
if (c) {
@@ -360,6 +379,21 @@ int format_counters(struct thread_data *t, struct core_data *c,
/* TSC */
outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float);
+ /* delta */
+ if (extra_delta_offset32)
+ outp += sprintf(outp, " %11llu", t->extra_delta32);
+
+ /* DELTA */
+ if (extra_delta_offset64)
+ outp += sprintf(outp, " %11llu", t->extra_delta64);
+ /* msr */
+ if (extra_msr_offset32)
+ outp += sprintf(outp, " 0x%08llx", t->extra_msr32);
+
+ /* MSR */
+ if (extra_msr_offset64)
+ outp += sprintf(outp, " 0x%016llx", t->extra_msr64);
+
if (do_nhm_cstates) {
if (!skip_c1)
outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc);
@@ -391,8 +425,6 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (do_snb_cstates)
outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc);
done:
- if (extra_msr_offset)
- outp += sprintf(outp, " 0x%016llx", t->extra_msr);
outp += sprintf(outp, "\n");
return 0;
@@ -502,10 +534,16 @@ delta_thread(struct thread_data *new, struct thread_data *old,
old->mperf = 1; /* divide by 0 protection */
}
+ old->extra_delta32 = new->extra_delta32 - old->extra_delta32;
+ old->extra_delta32 &= 0xFFFFFFFF;
+
+ old->extra_delta64 = new->extra_delta64 - old->extra_delta64;
+
/*
- * for "extra msr", just copy the latest w/o subtracting
+ * Extra MSR is just a snapshot, simply copy latest w/o subtracting
*/
- old->extra_msr = new->extra_msr;
+ old->extra_msr32 = new->extra_msr32;
+ old->extra_msr64 = new->extra_msr64;
}
int delta_cpu(struct thread_data *t, struct core_data *c,
@@ -533,6 +571,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
t->mperf = 0;
t->c1 = 0;
+ t->extra_delta32 = 0;
+ t->extra_delta64 = 0;
+
/* tells format_counters to dump all fields from this set */
t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE;
@@ -553,6 +594,9 @@ int sum_counters(struct thread_data *t, struct core_data *c,
average.threads.mperf += t->mperf;
average.threads.c1 += t->c1;
+ average.threads.extra_delta32 += t->extra_delta32;
+ average.threads.extra_delta64 += t->extra_delta64;
+
/* sum per-core values only for 1st thread in core */
if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
return 0;
@@ -588,6 +632,11 @@ void compute_average(struct thread_data *t, struct core_data *c,
average.threads.mperf /= topo.num_cpus;
average.threads.c1 /= topo.num_cpus;
+ average.threads.extra_delta32 /= topo.num_cpus;
+ average.threads.extra_delta32 &= 0xFFFFFFFF;
+
+ average.threads.extra_delta64 /= topo.num_cpus;
+
average.cores.c3 /= topo.num_cores;
average.cores.c6 /= topo.num_cores;
average.cores.c7 /= topo.num_cores;
@@ -629,8 +678,24 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return -4;
}
- if (extra_msr_offset)
- if (get_msr(cpu, extra_msr_offset, &t->extra_msr))
+ if (extra_delta_offset32) {
+ if (get_msr(cpu, extra_delta_offset32, &t->extra_delta32))
+ return -5;
+ t->extra_delta32 &= 0xFFFFFFFF;
+ }
+
+ if (extra_delta_offset64)
+ if (get_msr(cpu, extra_delta_offset64, &t->extra_delta64))
+ return -5;
+
+ if (extra_msr_offset32) {
+ if (get_msr(cpu, extra_msr_offset32, &t->extra_msr32))
+ return -5;
+ t->extra_msr32 &= 0xFFFFFFFF;
+ }
+
+ if (extra_msr_offset64)
+ if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64))
return -5;
/* collect core counters only for 1st thread in core */
@@ -677,6 +742,9 @@ void print_verbose_header(void)
get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr);
+ if (verbose > 1)
+ fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr);
+
ratio = (msr >> 40) & 0xFF;
fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n",
ratio, bclk, ratio * bclk);
@@ -685,14 +753,84 @@ void print_verbose_header(void)
fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n",
ratio, bclk, ratio * bclk);
+ if (!do_ivt_turbo_ratio_limit)
+ goto print_nhm_turbo_ratio_limits;
+
+ get_msr(0, MSR_IVT_TURBO_RATIO_LIMIT, &msr);
+
if (verbose > 1)
- fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr);
+ fprintf(stderr, "MSR_IVT_TURBO_RATIO_LIMIT: 0x%llx\n", msr);
+
+ ratio = (msr >> 56) & 0xFF;
+ if (ratio)
+ fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 16 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 48) & 0xFF;
+ if (ratio)
+ fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 15 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 40) & 0xFF;
+ if (ratio)
+ fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 14 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 32) & 0xFF;
+ if (ratio)
+ fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 13 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 24) & 0xFF;
+ if (ratio)
+ fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 12 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 16) & 0xFF;
+ if (ratio)
+ fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 11 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 8) & 0xFF;
+ if (ratio)
+ fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 10 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 0) & 0xFF;
+ if (ratio)
+ fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 9 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+print_nhm_turbo_ratio_limits:
if (!do_nehalem_turbo_ratio_limit)
return;
get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr);
+ if (verbose > 1)
+ fprintf(stderr, "MSR_NEHALEM_TURBO_RATIO_LIMIT: 0x%llx\n", msr);
+
+ ratio = (msr >> 56) & 0xFF;
+ if (ratio)
+ fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 8 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 48) & 0xFF;
+ if (ratio)
+ fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 7 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 40) & 0xFF;
+ if (ratio)
+ fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 6 active cores\n",
+ ratio, bclk, ratio * bclk);
+
+ ratio = (msr >> 32) & 0xFF;
+ if (ratio)
+ fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 5 active cores\n",
+ ratio, bclk, ratio * bclk);
+
ratio = (msr >> 24) & 0xFF;
if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n",
@@ -712,7 +850,6 @@ void print_verbose_header(void)
if (ratio)
fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
ratio, bclk, ratio * bclk);
-
}
void free_all_buffers(void)
@@ -1038,7 +1175,7 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
case 0x2A: /* SNB */
case 0x2D: /* SNB Xeon */
case 0x3A: /* IVB */
- case 0x3D: /* IVB Xeon */
+ case 0x3E: /* IVB Xeon */
return 1;
case 0x2E: /* Nehalem-EX Xeon - Beckton */
case 0x2F: /* Westmere-EX Xeon - Eagleton */
@@ -1046,6 +1183,22 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
return 0;
}
}
+int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
+{
+ if (!genuine_intel)
+ return 0;
+
+ if (family != 6)
+ return 0;
+
+ switch (model) {
+ case 0x3E: /* IVB Xeon */
+ return 1;
+ default:
+ return 0;
+ }
+}
+
int is_snb(unsigned int family, unsigned int model)
{
@@ -1056,7 +1209,7 @@ int is_snb(unsigned int family, unsigned int model)
case 0x2A:
case 0x2D:
case 0x3A: /* IVB */
- case 0x3D: /* IVB Xeon */
+ case 0x3E: /* IVB Xeon */
return 1;
}
return 0;
@@ -1145,12 +1298,13 @@ void check_cpuid()
bclk = discover_bclk(family, model);
do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model);
+ do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model);
}
void usage()
{
- fprintf(stderr, "%s: [-v] [-M MSR#] [-i interval_sec | command ...]\n",
+ fprintf(stderr, "%s: [-v][-p|-P|-S][-c MSR# | -s]][-C MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n",
progname);
exit(1);
}
@@ -1440,15 +1594,15 @@ void cmdline(int argc, char **argv)
progname = argv[0];
- while ((opt = getopt(argc, argv, "+cpsvi:M:")) != -1) {
+ while ((opt = getopt(argc, argv, "+pPSvisc:sC:m:M:")) != -1) {
switch (opt) {
- case 'c':
+ case 'p':
show_core_only++;
break;
- case 'p':
+ case 'P':
show_pkg_only++;
break;
- case 's':
+ case 'S':
summary_only++;
break;
case 'v':
@@ -1457,10 +1611,20 @@ void cmdline(int argc, char **argv)
case 'i':
interval_sec = atoi(optarg);
break;
+ case 'c':
+ sscanf(optarg, "%x", &extra_delta_offset32);
+ break;
+ case 's':
+ extra_delta_offset32 = 0x34; /* SMI counter */
+ break;
+ case 'C':
+ sscanf(optarg, "%x", &extra_delta_offset64);
+ break;
+ case 'm':
+ sscanf(optarg, "%x", &extra_msr_offset32);
+ break;
case 'M':
- sscanf(optarg, "%x", &extra_msr_offset);
- if (verbose > 1)
- fprintf(stderr, "MSR 0x%X\n", extra_msr_offset);
+ sscanf(optarg, "%x", &extra_msr_offset64);
break;
default:
usage();
@@ -1473,7 +1637,7 @@ int main(int argc, char **argv)
cmdline(argc, argv);
if (verbose > 1)
- fprintf(stderr, "turbostat v2.0 May 16, 2012"
+ fprintf(stderr, "turbostat v2.1 October 6, 2012"
" - Len Brown <lenb@kernel.org>\n");
turbostat_init();