diff options
36 files changed, 806 insertions, 581 deletions
diff --git a/Documentation/cgroups/cpuacct.txt b/Documentation/cgroups/cpuacct.txt index 9ad85df..9d73cc0 100644 --- a/Documentation/cgroups/cpuacct.txt +++ b/Documentation/cgroups/cpuacct.txt @@ -23,7 +23,7 @@ New accounting groups can be created under the parent group /sys/fs/cgroup. # cd /sys/fs/cgroup # mkdir g1 -# echo $$ > g1 +# echo $$ > g1/tasks The above steps create a new group g1 and move the current shell process (bash) into it. CPU time consumed by this bash and its children diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt index 5b0d78e..5c51ed4 100644 --- a/Documentation/cgroups/cpusets.txt +++ b/Documentation/cgroups/cpusets.txt @@ -180,7 +180,7 @@ files describing that cpuset: - cpuset.sched_load_balance flag: if set, load balance within CPUs on that cpuset - cpuset.sched_relax_domain_level: the searching range when migrating tasks -In addition, the root cpuset only has the following file: +In addition, only the root cpuset has the following file: - cpuset.memory_pressure_enabled flag: compute memory_pressure? New cpusets are created using the mkdir system call or shell diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 5e7cb39..1c7fb0a 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -17,23 +17,21 @@ before actually making adjustments. Currently, these files might (depending on your configuration) show up in /proc/sys/kernel: -- acpi_video_flags + - acct +- acpi_video_flags +- auto_msgmni - bootloader_type [ X86 only ] - bootloader_version [ X86 only ] - callhome [ S390 only ] -- auto_msgmni - core_pattern - core_pipe_limit - core_uses_pid - ctrl-alt-del -- dentry-state - dmesg_restrict - domainname - hostname - hotplug -- java-appletviewer [ binfmt_java, obsolete ] -- java-interpreter [ binfmt_java, obsolete ] - kptr_restrict - kstack_depth_to_print [ X86 only ] - l2cr [ PPC only ] @@ -48,10 +46,14 @@ show up in /proc/sys/kernel: - overflowgid - overflowuid - panic +- panic_on_oops +- panic_on_unrecovered_nmi - pid_max - powersave-nap [ PPC only ] -- panic_on_unrecovered_nmi - printk +- printk_delay +- printk_ratelimit +- printk_ratelimit_burst - randomize_va_space - real-root-dev ==> Documentation/initrd.txt - reboot-cmd [ SPARC only ] @@ -62,6 +64,7 @@ show up in /proc/sys/kernel: - shmall - shmmax [ sysv ipc ] - shmmni +- softlockup_thresh - stop-a [ SPARC only ] - sysrq ==> Documentation/sysrq.txt - tainted @@ -71,15 +74,6 @@ show up in /proc/sys/kernel: ============================================================== -acpi_video_flags: - -flags - -See Doc*/kernel/power/video.txt, it allows mode of video boot to be -set during run time. - -============================================================== - acct: highwater lowwater frequency @@ -97,6 +91,25 @@ valid for 30 seconds. ============================================================== +acpi_video_flags: + +flags + +See Doc*/kernel/power/video.txt, it allows mode of video boot to be +set during run time. + +============================================================== + +auto_msgmni: + +Enables/Disables automatic recomputing of msgmni upon memory add/remove +or upon ipc namespace creation/removal (see the msgmni description +above). Echoing "1" into this file enables msgmni automatic recomputing. +Echoing "0" turns it off. auto_msgmni default value is 1. + + +============================================================== + bootloader_type: x86 bootloader identification @@ -172,22 +185,24 @@ core_pattern is used to specify a core dumpfile pattern name. core_pipe_limit: -This sysctl is only applicable when core_pattern is configured to pipe core -files to a user space helper (when the first character of core_pattern is a '|', -see above). When collecting cores via a pipe to an application, it is -occasionally useful for the collecting application to gather data about the -crashing process from its /proc/pid directory. In order to do this safely, the -kernel must wait for the collecting process to exit, so as not to remove the -crashing processes proc files prematurely. This in turn creates the possibility -that a misbehaving userspace collecting process can block the reaping of a -crashed process simply by never exiting. This sysctl defends against that. It -defines how many concurrent crashing processes may be piped to user space -applications in parallel. If this value is exceeded, then those crashing -processes above that value are noted via the kernel log and their cores are -skipped. 0 is a special value, indicating that unlimited processes may be -captured in parallel, but that no waiting will take place (i.e. the collecting -process is not guaranteed access to /proc/<crashing pid>/). This value defaults -to 0. +This sysctl is only applicable when core_pattern is configured to pipe +core files to a user space helper (when the first character of +core_pattern is a '|', see above). When collecting cores via a pipe +to an application, it is occasionally useful for the collecting +application to gather data about the crashing process from its +/proc/pid directory. In order to do this safely, the kernel must wait +for the collecting process to exit, so as not to remove the crashing +processes proc files prematurely. This in turn creates the +possibility that a misbehaving userspace collecting process can block +the reaping of a crashed process simply by never exiting. This sysctl +defends against that. It defines how many concurrent crashing +processes may be piped to user space applications in parallel. If +this value is exceeded, then those crashing processes above that value +are noted via the kernel log and their cores are skipped. 0 is a +special value, indicating that unlimited processes may be captured in +parallel, but that no waiting will take place (i.e. the collecting +process is not guaranteed access to /proc/<crashing pid>/). This +value defaults to 0. ============================================================== @@ -218,14 +233,14 @@ to decide what to do with it. dmesg_restrict: -This toggle indicates whether unprivileged users are prevented from using -dmesg(8) to view messages from the kernel's log buffer. When -dmesg_restrict is set to (0) there are no restrictions. When +This toggle indicates whether unprivileged users are prevented +from using dmesg(8) to view messages from the kernel's log buffer. +When dmesg_restrict is set to (0) there are no restrictions. When dmesg_restrict is set set to (1), users must have CAP_SYSLOG to use dmesg(8). -The kernel config option CONFIG_SECURITY_DMESG_RESTRICT sets the default -value of dmesg_restrict. +The kernel config option CONFIG_SECURITY_DMESG_RESTRICT sets the +default value of dmesg_restrict. ============================================================== @@ -256,13 +271,6 @@ Default value is "/sbin/hotplug". ============================================================== -l2cr: (PPC only) - -This flag controls the L2 cache of G3 processor boards. If -0, the cache is disabled. Enabled if nonzero. - -============================================================== - kptr_restrict: This toggle indicates whether restrictions are placed on @@ -283,6 +291,13 @@ kernel stack. ============================================================== +l2cr: (PPC only) + +This flag controls the L2 cache of G3 processor boards. If +0, the cache is disabled. Enabled if nonzero. + +============================================================== + modules_disabled: A toggle value indicating if modules are allowed to be loaded @@ -293,6 +308,21 @@ to false. ============================================================== +nmi_watchdog: + +Enables/Disables the NMI watchdog on x86 systems. When the value is +non-zero the NMI watchdog is enabled and will continuously test all +online cpus to determine whether or not they are still functioning +properly. Currently, passing "nmi_watchdog=" parameter at boot time is +required for this function to work. + +If LAPIC NMI watchdog method is in use (nmi_watchdog=2 kernel +parameter), the NMI watchdog shares registers with oprofile. By +disabling the NMI watchdog, oprofile may have more registers to +utilize. + +============================================================== + osrelease, ostype & version: # cat osrelease @@ -312,10 +342,10 @@ The only way to tune these values is to rebuild the kernel :-) overflowgid & overflowuid: -if your architecture did not always support 32-bit UIDs (i.e. arm, i386, -m68k, sh, and sparc32), a fixed UID and GID will be returned to -applications that use the old 16-bit UID/GID system calls, if the actual -UID or GID would exceed 65535. +if your architecture did not always support 32-bit UIDs (i.e. arm, +i386, m68k, sh, and sparc32), a fixed UID and GID will be returned to +applications that use the old 16-bit UID/GID system calls, if the +actual UID or GID would exceed 65535. These sysctls allow you to change the value of the fixed UID and GID. The default is 65534. @@ -324,9 +354,22 @@ The default is 65534. panic: -The value in this file represents the number of seconds the -kernel waits before rebooting on a panic. When you use the -software watchdog, the recommended setting is 60. +The value in this file represents the number of seconds the kernel +waits before rebooting on a panic. When you use the software watchdog, +the recommended setting is 60. + +============================================================== + +panic_on_unrecovered_nmi: + +The default Linux behaviour on an NMI of either memory or unknown is +to continue operation. For many environments such as scientific +computing it is preferable that the box is taken out and the error +dealt with than an uncorrected parity/ECC error get propagated. + +A small number of systems do generate NMI's for bizarre random reasons +such as power management so the default is off. That sysctl works like +the existing panic controls already in that directory. ============================================================== @@ -376,6 +419,14 @@ the different loglevels. ============================================================== +printk_delay: + +Delay each printk message in printk_delay milliseconds + +Value from 0 - 10000 is allowed. + +============================================================== + printk_ratelimit: Some warning messages are rate limited. printk_ratelimit specifies @@ -395,15 +446,7 @@ send before ratelimiting kicks in. ============================================================== -printk_delay: - -Delay each printk message in printk_delay milliseconds - -Value from 0 - 10000 is allowed. - -============================================================== - -randomize-va-space: +randomize_va_space: This option can be used to select the type of process address space randomization that is used in the system, for architectures @@ -466,11 +509,11 @@ are doing anyway :) ============================================================== -shmmax: +shmmax: This value can be used to query and set the run time limit on the maximum shared memory segment size that can be created. -Shared memory segments up to 1Gb are now supported in the +Shared memory segments up to 1Gb are now supported in the kernel. This value defaults to SHMMAX. ============================================================== @@ -484,7 +527,7 @@ tunable to zero will disable the softlockup detection altogether. ============================================================== -tainted: +tainted: Non-zero if the kernel has been tainted. Numeric values, which can be ORed together: @@ -509,49 +552,11 @@ can be ORed together: ============================================================== -auto_msgmni: - -Enables/Disables automatic recomputing of msgmni upon memory add/remove or -upon ipc namespace creation/removal (see the msgmni description above). -Echoing "1" into this file enables msgmni automatic recomputing. -Echoing "0" turns it off. -auto_msgmni default value is 1. - -============================================================== - -nmi_watchdog: - -Enables/Disables the NMI watchdog on x86 systems. When the value is non-zero -the NMI watchdog is enabled and will continuously test all online cpus to -determine whether or not they are still functioning properly. Currently, -passing "nmi_watchdog=" parameter at boot time is required for this function -to work. - -If LAPIC NMI watchdog method is in use (nmi_watchdog=2 kernel parameter), the -NMI watchdog shares registers with oprofile. By disabling the NMI watchdog, -oprofile may have more registers to utilize. - -============================================================== - unknown_nmi_panic: -The value in this file affects behavior of handling NMI. When the value is -non-zero, unknown NMI is trapped and then panic occurs. At that time, kernel -debugging information is displayed on console. - -NMI switch that most IA32 servers have fires unknown NMI up, for example. -If a system hangs up, try pressing the NMI switch. - -============================================================== - -panic_on_unrecovered_nmi: - -The default Linux behaviour on an NMI of either memory or unknown is to continue -operation. For many environments such as scientific computing it is preferable -that the box is taken out and the error dealt with than an uncorrected -parity/ECC error get propogated. - -A small number of systems do generate NMI's for bizarre random reasons such as -power management so the default is off. That sysctl works like the existing -panic controls already in that directory. +The value in this file affects behavior of handling NMI. When the +value is non-zero, unknown NMI is trapped and then panic occurs. At +that time, kernel debugging information is displayed on console. +NMI switch that most IA32 servers have fires unknown NMI up, for +example. If a system hangs up, try pressing the NMI switch. diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig index fa4d1e5..9806e55 100644 --- a/arch/ia64/kvm/Kconfig +++ b/arch/ia64/kvm/Kconfig @@ -49,6 +49,5 @@ config KVM_INTEL extensions. source drivers/vhost/Kconfig -source drivers/virtio/Kconfig endif # VIRTUALIZATION diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 6cb60ad..177cdaf 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2493,20 +2493,4 @@ source "security/Kconfig" source "crypto/Kconfig" -menuconfig VIRTUALIZATION - bool "Virtualization" - default n - ---help--- - Say Y here to get to see options for using your Linux host to run other - operating systems inside virtual machines (guests). - This option alone does not add any kernel code. - - If you say N, all options in this submenu will be skipped and disabled. - -if VIRTUALIZATION - -source drivers/virtio/Kconfig - -endif # VIRTUALIZATION - source "lib/Kconfig" diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index b7baff7..105b691 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig @@ -99,6 +99,5 @@ config KVM_E500 If unsure, say N. source drivers/vhost/Kconfig -source drivers/virtio/Kconfig endif # VIRTUALIZATION diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index f66a1bd..a216341 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig @@ -37,6 +37,5 @@ config KVM # OK, it's a little counter-intuitive to do this, but it puts it neatly under # the virtualization menu. source drivers/vhost/Kconfig -source drivers/virtio/Kconfig endif # VIRTUALIZATION diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index bbdeb48b..748ff19 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -897,20 +897,4 @@ source "security/Kconfig" source "crypto/Kconfig" -menuconfig VIRTUALIZATION - bool "Virtualization" - default n - ---help--- - Say Y here to get to see options for using your Linux host to run other - operating systems inside virtual machines (guests). - This option alone does not add any kernel code. - - If you say N, all options in this submenu will be skipped and disabled. - -if VIRTUALIZATION - -source drivers/virtio/Kconfig - -endif # VIRTUALIZATION - source "lib/Kconfig" diff --git a/arch/tile/kvm/Kconfig b/arch/tile/kvm/Kconfig index b88f9c0..669fcdb 100644 --- a/arch/tile/kvm/Kconfig +++ b/arch/tile/kvm/Kconfig @@ -33,6 +33,5 @@ config KVM If unsure, say N. source drivers/vhost/Kconfig -source drivers/virtio/Kconfig endif # VIRTUALIZATION diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 15587ed..87b659d 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile @@ -8,7 +8,8 @@ obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ obj-$(CONFIG_BINFMT_ELF) += elfcore.o -subarch-obj-y = lib/rwsem.o lib/string_32.o +subarch-obj-y = lib/string_32.o +subarch-obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += lib/rwsem.o subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o subarch-obj-$(CONFIG_MODULES) += kernel/module.o diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5f60ea1..b212754 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -390,12 +390,21 @@ config X86_INTEL_CE This option compiles in support for the CE4100 SOC for settop boxes and media devices. +config X86_INTEL_MID + bool "Intel MID platform support" + depends on X86_32 + depends on X86_EXTENDED_PLATFORM + ---help--- + Select to build a kernel capable of supporting Intel MID platform + systems which do not have the PCI legacy interfaces (Moorestown, + Medfield). If you are building for a PC class system say N here. + +if X86_INTEL_MID + config X86_MRST bool "Moorestown MID platform" depends on PCI depends on PCI_GOANY - depends on X86_32 - depends on X86_EXTENDED_PLATFORM depends on X86_IO_APIC select APB_TIMER select I2C @@ -410,6 +419,8 @@ config X86_MRST nor standard legacy replacement devices/features. e.g. Moorestown does not contain i8259, i8254, HPET, legacy BIOS, most of the io ports. +endif + config X86_RDC321X bool "RDC R-321x SoC" depends on X86_32 @@ -623,6 +634,7 @@ config HPET_EMULATE_RTC config APB_TIMER def_bool y if MRST prompt "Langwell APB Timer Support" if X86_MRST + select DW_APB_TIMER help APB timer is the replacement for 8254, HPET on X86 MID platforms. The APBT provides a stable time base on SMP diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 6a7cfdf..e3ca7e0 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -312,6 +312,9 @@ config X86_CMPXCHG config CMPXCHG_LOCAL def_bool X86_64 || (X86_32 && !M386) +config CMPXCHG_DOUBLE + def_bool y + config X86_L1_CACHE_SHIFT int default "7" if MPENTIUM4 || MPSC diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index f7cb086..95365a8 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -9,12 +9,6 @@ # Changed by many, many contributors over the years. # -# ROOT_DEV specifies the default root-device when making the image. -# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case -# the default of FLOPPY is used by 'build'. - -ROOT_DEV := CURRENT - # If you want to preset the SVGA mode, uncomment the next line and # set SVGA_MODE to whatever number you want. # Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode. @@ -75,8 +69,7 @@ GCOV_PROFILE := n $(obj)/bzImage: asflags-y := $(SVGA_MODE) quiet_cmd_image = BUILD $@ -cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin \ - $(ROOT_DEV) > $@ +cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin > $@ $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE $(call if_changed,image) diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index ee3a4ea..fdc60a0 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c @@ -130,7 +130,7 @@ static void die(const char * str, ...) static void usage(void) { - die("Usage: build setup system [rootdev] [> image]"); + die("Usage: build setup system [> image]"); } int main(int argc, char ** argv) @@ -138,39 +138,14 @@ int main(int argc, char ** argv) unsigned int i, sz, setup_sectors; int c; u32 sys_size; - u8 major_root, minor_root; struct stat sb; FILE *file; int fd; void *kernel; u32 crc = 0xffffffffUL; - if ((argc < 3) || (argc > 4)) + if (argc != 3) usage(); - if (argc > 3) { - if (!strcmp(argv[3], "CURRENT")) { - if (stat("/", &sb)) { - perror("/"); - die("Couldn't stat /"); - } - major_root = major(sb.st_dev); - minor_root = minor(sb.st_dev); - } else if (strcmp(argv[3], "FLOPPY")) { - if (stat(argv[3], &sb)) { - perror(argv[3]); - die("Couldn't stat root device."); - } - major_root = major(sb.st_rdev); - minor_root = minor(sb.st_rdev); - } else { - major_root = 0; - minor_root = 0; - } - } else { - major_root = DEFAULT_MAJOR_ROOT; - minor_root = DEFAULT_MINOR_ROOT; - } - fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); /* Copy the setup code */ file = fopen(argv[1], "r"); @@ -193,8 +168,8 @@ int main(int argc, char ** argv) memset(buf+c, 0, i-c); /* Set the default root device */ - buf[508] = minor_root; - buf[509] = major_root; + buf[508] = DEFAULT_MINOR_ROOT; + buf[509] = DEFAULT_MAJOR_ROOT; fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i); diff --git a/arch/x86/include/asm/apb_timer.h b/arch/x86/include/asm/apb_timer.h index 082cf81..0acbac2 100644 --- a/arch/x86/include/asm/apb_timer.h +++ b/arch/x86/include/asm/apb_timer.h @@ -18,24 +18,6 @@ #ifdef CONFIG_APB_TIMER -/* Langwell DW APB timer registers */ -#define APBTMR_N_LOAD_COUNT 0x00 -#define APBTMR_N_CURRENT_VALUE 0x04 -#define APBTMR_N_CONTROL 0x08 -#define APBTMR_N_EOI 0x0c -#define APBTMR_N_INT_STATUS 0x10 - -#define APBTMRS_INT_STATUS 0xa0 -#define APBTMRS_EOI 0xa4 -#define APBTMRS_RAW_INT_STATUS 0xa8 -#define APBTMRS_COMP_VERSION 0xac -#define APBTMRS_REG_SIZE 0x14 - -/* register bits */ -#define APBTMR_CONTROL_ENABLE (1<<0) -#define APBTMR_CONTROL_MODE_PERIODIC (1<<1) /*1: periodic 0:free running */ -#define APBTMR_CONTROL_INT (1<<2) - /* default memory mapped register base */ #define LNW_SCU_ADDR 0xFF100000 #define LNW_EXT_TIMER_OFFSET 0x1B800 @@ -43,8 +25,8 @@ #define LNW_EXT_TIMER_PGOFFSET 0x800 /* APBT clock speed range from PCLK to fabric base, 25-100MHz */ -#define APBT_MAX_FREQ 50 -#define APBT_MIN_FREQ 1 +#define APBT_MAX_FREQ 50000000 +#define APBT_MIN_FREQ 1000000 #define APBT_MMAP_SIZE 1024 #define APBT_DEV_USED 1 diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h index 284a6e8..3deb725 100644 --- a/arch/x86/include/asm/cmpxchg_32.h +++ b/arch/x86/include/asm/cmpxchg_32.h @@ -280,4 +280,52 @@ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old, #endif +#define cmpxchg8b(ptr, o1, o2, n1, n2) \ +({ \ + char __ret; \ + __typeof__(o2) __dummy; \ + __typeof__(*(ptr)) __old1 = (o1); \ + __typeof__(o2) __old2 = (o2); \ + __typeof__(*(ptr)) __new1 = (n1); \ + __typeof__(o2) __new2 = (n2); \ + asm volatile(LOCK_PREFIX "cmpxchg8b %2; setz %1" \ + : "=d"(__dummy), "=a" (__ret), "+m" (*ptr)\ + : "a" (__old1), "d"(__old2), \ + "b" (__new1), "c" (__new2) \ + : "memory"); \ + __ret; }) + + +#define cmpxchg8b_local(ptr, o1, o2, n1, n2) \ +({ \ + char __ret; \ + __typeof__(o2) __dummy; \ + __typeof__(*(ptr)) __old1 = (o1); \ + __typeof__(o2) __old2 = (o2); \ + __typeof__(*(ptr)) __new1 = (n1); \ + __typeof__(o2) __new2 = (n2); \ + asm volatile("cmpxchg8b %2; setz %1" \ + : "=d"(__dummy), "=a"(__ret), "+m" (*ptr)\ + : "a" (__old), "d"(__old2), \ + "b" (__new1), "c" (__new2), \ + : "memory"); \ + __ret; }) + + +#define cmpxchg_double(ptr, o1, o2, n1, n2) \ +({ \ + BUILD_BUG_ON(sizeof(*(ptr)) != 4); \ + VM_BUG_ON((unsigned long)(ptr) % 8); \ + cmpxchg8b((ptr), (o1), (o2), (n1), (n2)); \ +}) + +#define cmpxchg_double_local(ptr, o1, o2, n1, n2) \ +({ \ + BUILD_BUG_ON(sizeof(*(ptr)) != 4); \ + VM_BUG_ON((unsigned long)(ptr) % 8); \ + cmpxchg16b_local((ptr), (o1), (o2), (n1), (n2)); \ +}) + +#define system_has_cmpxchg_double() cpu_has_cx8 + #endif /* _ASM_X86_CMPXCHG_32_H */ diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h index 423ae58..7cf5c0a 100644 --- a/arch/x86/include/asm/cmpxchg_64.h +++ b/arch/x86/include/asm/cmpxchg_64.h @@ -151,4 +151,49 @@ extern void __cmpxchg_wrong_size(void); cmpxchg_local((ptr), (o), (n)); \ }) +#define cmpxchg16b(ptr, o1, o2, n1, n2) \ +({ \ + char __ret; \ + __typeof__(o2) __junk; \ + __typeof__(*(ptr)) __old1 = (o1); \ + __typeof__(o2) __old2 = (o2); \ + __typeof__(*(ptr)) __new1 = (n1); \ + __typeof__(o2) __new2 = (n2); \ + asm volatile(LOCK_PREFIX "cmpxchg16b %2;setz %1" \ + : "=d"(__junk), "=a"(__ret), "+m" (*ptr) \ + : "b"(__new1), "c"(__new2), \ + "a"(__old1), "d"(__old2)); \ + __ret; }) + + +#define cmpxchg16b_local(ptr, o1, o2, n1, n2) \ +({ \ + char __ret; \ + __typeof__(o2) __junk; \ + __typeof__(*(ptr)) __old1 = (o1); \ + __typeof__(o2) __old2 = (o2); \ + __typeof__(*(ptr)) __new1 = (n1); \ + __typeof__(o2) __new2 = (n2); \ + asm volatile("cmpxchg16b %2;setz %1" \ + : "=d"(__junk), "=a"(__ret), "+m" (*ptr) \ + : "b"(__new1), "c"(__new2), \ + "a"(__old1), "d"(__old2)); \ + __ret; }) + +#define cmpxchg_double(ptr, o1, o2, n1, n2) \ +({ \ + BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ + VM_BUG_ON((unsigned long)(ptr) % 16); \ + cmpxchg16b((ptr), (o1), (o2), (n1), (n2)); \ +}) + +#define cmpxchg_double_local(ptr, o1, o2, n1, n2) \ +({ \ + BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ + VM_BUG_ON((unsigned long)(ptr) % 16); \ + cmpxchg16b_local((ptr), (o1), (o2), (n1), (n2)); \ +}) + +#define system_has_cmpxchg_double() cpu_has_cx16 + #endif /* _ASM_X86_CMPXCHG_64_H */ diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 9929b35..4258aac 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -288,6 +288,8 @@ extern const char * const x86_power_flags[32]; #define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) #define cpu_has_pclmulqdq boot_cpu_has(X86_FEATURE_PCLMULQDQ) #define cpu_has_perfctr_core boot_cpu_has(X86_FEATURE_PERFCTR_CORE) +#define cpu_has_cx8 boot_cpu_has(X86_FEATURE_CX8) +#define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16) #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) # define cpu_has_invlpg 1 diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c index 2b6630d..afdc3f75 100644 --- a/arch/x86/kernel/apb_timer.c +++ b/arch/x86/kernel/apb_timer.c @@ -27,15 +27,12 @@ * timer, but by default APB timer has higher rating than local APIC timers. */ -#include <linux/clocksource.h> -#include <linux/clockchips.h> #include <linux/delay.h> +#include <linux/dw_apb_timer.h> #include <linux/errno.h> #include <linux/init.h> -#include <linux/sysdev.h> #include <linux/slab.h> #include <linux/pm.h> -#include <linux/pci.h> #include <linux/sfi.h> #include <linux/interrupt.h> #include <linux/cpu.h> @@ -46,75 +43,46 @@ #include <asm/mrst.h> #include <asm/time.h> -#define APBT_MASK CLOCKSOURCE_MASK(32) -#define APBT_SHIFT 22 #define APBT_CLOCKEVENT_RATING 110 #define APBT_CLOCKSOURCE_RATING 250 -#define APBT_MIN_DELTA_USEC 200 -#define EVT_TO_APBT_DEV(evt) container_of(evt, struct apbt_dev, evt) #define APBT_CLOCKEVENT0_NUM (0) -#define APBT_CLOCKEVENT1_NUM (1) #define APBT_CLOCKSOURCE_NUM (2) -static unsigned long apbt_address; +static phys_addr_t apbt_address; static int apb_timer_block_enabled; static void __iomem *apbt_virt_address; -static int phy_cs_timer_id; /* * Common DW APB timer info */ -static uint64_t apbt_freq; - -static void apbt_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt); -static int apbt_next_event(unsigned long delta, - struct clock_event_device *evt); -static cycle_t apbt_read_clocksource(struct clocksource *cs); -static void apbt_restart_clocksource(struct clocksource *cs); +static unsigned long apbt_freq; struct apbt_dev { - struct clock_event_device evt; - unsigned int num; - int cpu; - unsigned int irq; - unsigned int tick; - unsigned int count; - unsigned int flags; - char name[10]; + struct dw_apb_clock_event_device *timer; + unsigned int num; + int cpu; + unsigned int irq; + char name[10]; }; -static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev); +static struct dw_apb_clocksource *clocksource_apbt; -#ifdef CONFIG_SMP -static unsigned int apbt_num_timers_used; -static struct apbt_dev *apbt_devs; -#endif - -static inline unsigned long apbt_readl_reg(unsigned long a) +static inline void __iomem *adev_virt_addr(struct apbt_dev *adev) { - return readl(apbt_virt_address + a); + return apbt_virt_address + adev->num * APBTMRS_REG_SIZE; } -static inline void apbt_writel_reg(unsigned long d, unsigned long a) -{ - writel(d, apbt_virt_address + a); -} - -static inline unsigned long apbt_readl(int n, unsigned long a) -{ - return readl(apbt_virt_address + a + n * APBTMRS_REG_SIZE); -} +static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev); -static inline void apbt_writel(int n, unsigned long d, unsigned long a) -{ - writel(d, apbt_virt_address + a + n * APBTMRS_REG_SIZE); -} +#ifdef CONFIG_SMP +static unsigned int apbt_num_timers_used; +#endif static inline void apbt_set_mapping(void) { struct sfi_timer_table_entry *mtmr; + int phy_cs_timer_id = 0; if (apbt_virt_address) { pr_debug("APBT base already mapped\n"); @@ -126,21 +94,18 @@ static inline void apbt_set_mapping(void) APBT_CLOCKEVENT0_NUM); return; } - apbt_address = (unsigned long)mtmr->phys_addr; + apbt_address = (phys_addr_t)mtmr->phys_addr; if (!apbt_address) { printk(KERN_WARNING "No timer base from SFI, use default\n"); apbt_address = APBT_DEFAULT_BASE; } apbt_virt_address = ioremap_nocache(apbt_address, APBT_MMAP_SIZE); - if (apbt_virt_address) { - pr_debug("Mapped APBT physical addr %p at virtual addr %p\n",\ - (void *)apbt_address, (void *)apbt_virt_address); - } else { - pr_debug("Failed mapping APBT phy address at %p\n",\ - (void *)apbt_address); + if (!apbt_virt_address) { + pr_debug("Failed mapping APBT phy address at %lu\n",\ + (unsigned long)apbt_address); goto panic_noapbt; } - apbt_freq = mtmr->freq_hz / USEC_PER_SEC; + apbt_freq = mtmr->freq_hz; sfi_free_mtmr(mtmr); /* Now figure out the physical timer id for clocksource device */ @@ -149,9 +114,14 @@ static inline void apbt_set_mapping(void) goto panic_noapbt; /* Now figure out the physical timer id */ - phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff) - / APBTMRS_REG_SIZE; - pr_debug("Use timer %d for clocksource\n", phy_cs_timer_id); + pr_debug("Use timer %d for clocksource\n", + (int)(mtmr->phys_addr & 0xff) / APBTMRS_REG_SIZE); + phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff) / + APBTMRS_REG_SIZE; + + clocksource_apbt = dw_apb_clocksource_init(APBT_CLOCKSOURCE_RATING, + "apbt0", apbt_virt_address + phy_cs_timer_id * + APBTMRS_REG_SIZE, apbt_freq); return; panic_noapbt: @@ -173,82 +143,6 @@ static inline int is_apbt_capable(void) return apbt_virt_address ? 1 : 0; } -static struct clocksource clocksource_apbt = { - .name = "apbt", - .rating = APBT_CLOCKSOURCE_RATING, - .read = apbt_read_clocksource, - .mask = APBT_MASK, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, - .resume = apbt_restart_clocksource, -}; - -/* boot APB clock event device */ -static struct clock_event_device apbt_clockevent = { - .name = "apbt0", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = apbt_set_mode, - .set_next_event = apbt_next_event, - .shift = APBT_SHIFT, - .irq = 0, - .rating = APBT_CLOCKEVENT_RATING, -}; - -/* - * start count down from 0xffff_ffff. this is done by toggling the enable bit - * then load initial load count to ~0. - */ -static void apbt_start_counter(int n) -{ - unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); - - ctrl &= ~APBTMR_CONTROL_ENABLE; - apbt_writel(n, ctrl, APBTMR_N_CONTROL); - apbt_writel(n, ~0, APBTMR_N_LOAD_COUNT); - /* enable, mask interrupt */ - ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; - ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT); - apbt_writel(n, ctrl, APBTMR_N_CONTROL); - /* read it once to get cached counter value initialized */ - apbt_read_clocksource(&clocksource_apbt); -} - -static irqreturn_t apbt_interrupt_handler(int irq, void *data) -{ - struct apbt_dev *dev = (struct apbt_dev *)data; - struct clock_event_device *aevt = &dev->evt; - - if (!aevt->event_handler) { - printk(KERN_INFO "Spurious APBT timer interrupt on %d\n", - dev->num); - return IRQ_NONE; - } - aevt->event_handler(aevt); - return IRQ_HANDLED; -} - -static void apbt_restart_clocksource(struct clocksource *cs) -{ - apbt_start_counter(phy_cs_timer_id); -} - -static void apbt_enable_int(int n) -{ - unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); - /* clear pending intr */ - apbt_readl(n, APBTMR_N_EOI); - ctrl &= ~APBTMR_CONTROL_INT; - apbt_writel(n, ctrl, APBTMR_N_CONTROL); -} - -static void apbt_disable_int(int n) -{ - unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); - - ctrl |= APBTMR_CONTROL_INT; - apbt_writel(n, ctrl, APBTMR_N_CONTROL); -} - - static int __init apbt_clockevent_register(void) { struct sfi_timer_table_entry *mtmr; @@ -261,45 +155,21 @@ static int __init apbt_clockevent_register(void) return -ENODEV; } - /* - * We need to calculate the scaled math multiplication factor for - * nanosecond to apbt tick conversion. - * mult = (nsec/cycle)*2^APBT_SHIFT - */ - apbt_clockevent.mult = div_sc((unsigned long) mtmr->freq_hz - , NSEC_PER_SEC, APBT_SHIFT); - - /* Calculate the min / max delta */ - apbt_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, - &apbt_clockevent); - apbt_clockevent.min_delta_ns = clockevent_delta2ns( - APBT_MIN_DELTA_USEC*apbt_freq, - &apbt_clockevent); - /* - * Start apbt with the boot cpu mask and make it - * global if not used for per cpu timer. - */ - apbt_clockevent.cpumask = cpumask_of(smp_processor_id()); adev->num = smp_processor_id(); - memcpy(&adev->evt, &apbt_clockevent, sizeof(struct clock_event_device)); + adev->timer = dw_apb_clockevent_init(smp_processor_id(), "apbt0", + mrst_timer_options == MRST_TIMER_LAPIC_APBT ? + APBT_CLOCKEVENT_RATING - 100 : APBT_CLOCKEVENT_RATING, + adev_virt_addr(adev), 0, apbt_freq); + /* Firmware does EOI handling for us. */ + adev->timer->eoi = NULL; if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) { - adev->evt.rating = APBT_CLOCKEVENT_RATING - 100; - global_clock_event = &adev->evt; + global_clock_event = &adev->timer->ced; printk(KERN_DEBUG "%s clockevent registered as global\n", global_clock_event->name); } - if (request_irq(apbt_clockevent.irq, apbt_interrupt_handler, - IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, - apbt_clockevent.name, adev)) { - printk(KERN_ERR "Failed request IRQ for APBT%d\n", - apbt_clockevent.irq); - } - - clockevents_register_device(&adev->evt); - /* Start APBT 0 interrupts */ - apbt_enable_int(APBT_CLOCKEVENT0_NUM); + dw_apb_clockevent_register(adev->timer); sfi_free_mtmr(mtmr); return 0; @@ -317,52 +187,34 @@ static void apbt_setup_irq(struct apbt_dev *adev) irq_set_affinity(adev->irq, cpumask_of(adev->cpu)); /* APB timer irqs are set up as mp_irqs, timer is edge type */ __irq_set_handler(adev->irq, handle_edge_irq, 0, "edge"); - - if (system_state == SYSTEM_BOOTING) { - if (request_irq(adev->irq, apbt_interrupt_handler, - IRQF_TIMER | IRQF_DISABLED | - IRQF_NOBALANCING, - adev->name, adev)) { - printk(KERN_ERR "Failed request IRQ for APBT%d\n", - adev->num); - } - } else - enable_irq(adev->irq); } /* Should be called with per cpu */ void apbt_setup_secondary_clock(void) { struct apbt_dev *adev; - struct clock_event_device *aevt; int cpu; /* Don't register boot CPU clockevent */ cpu = smp_processor_id(); if (!cpu) return; - /* - * We need to calculate the scaled math multiplication factor for - * nanosecond to apbt tick conversion. - * mult = (nsec/cycle)*2^APBT_SHIFT - */ - printk(KERN_INFO "Init per CPU clockevent %d\n", cpu); - adev = &per_cpu(cpu_apbt_dev, cpu); - aevt = &adev->evt; - memcpy(aevt, &apbt_clockevent, sizeof(*aevt)); - aevt->cpumask = cpumask_of(cpu); - aevt->name = adev->name; - aevt->mode = CLOCK_EVT_MODE_UNUSED; + adev = &__get_cpu_var(cpu_apbt_dev); + if (!adev->timer) { + adev->timer = dw_apb_clockevent_init(cpu, adev->name, + APBT_CLOCKEVENT_RATING, adev_virt_addr(adev), + adev->irq, apbt_freq); + adev->timer->eoi = NULL; + } else { + dw_apb_clockevent_resume(adev->timer); + } - printk(KERN_INFO "Registering CPU %d clockevent device %s, mask %08x\n", - cpu, aevt->name, *(u32 *)aevt->cpumask); + printk(KERN_INFO "Registering CPU %d clockevent device %s, cpu %08x\n", + cpu, adev->name, adev->cpu); apbt_setup_irq(adev); - - clockevents_register_device(aevt); - - apbt_enable_int(cpu); + dw_apb_clockevent_register(adev->timer); return; } @@ -385,13 +237,12 @@ static int apbt_cpuhp_notify(struct notifier_block *n, switch (action & 0xf) { case CPU_DEAD: - disable_irq(adev->irq); - apbt_disable_int(cpu); + dw_apb_clockevent_pause(adev->timer); if (system_state == SYSTEM_RUNNING) { pr_debug("skipping APBT CPU %lu offline\n", cpu); } else if (adev) { pr_debug("APBT clockevent for cpu %lu offline\n", cpu); - free_irq(adev->irq, adev); + dw_apb_clockevent_stop(adev->timer); } break; default: @@ -416,116 +267,16 @@ void apbt_setup_secondary_clock(void) {} #endif /* CONFIG_SMP */ -static void apbt_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - unsigned long ctrl; - uint64_t delta; - int timer_num; - struct apbt_dev *adev = EVT_TO_APBT_DEV(evt); - - BUG_ON(!apbt_virt_address); - - timer_num = adev->num; - pr_debug("%s CPU %d timer %d mode=%d\n", - __func__, first_cpu(*evt->cpumask), timer_num, mode); - - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * apbt_clockevent.mult; - delta >>= apbt_clockevent.shift; - ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL); - ctrl |= APBTMR_CONTROL_MODE_PERIODIC; - apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); - /* - * DW APB p. 46, have to disable timer before load counter, - * may cause sync problem. - */ - ctrl &= ~APBTMR_CONTROL_ENABLE; - apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); - udelay(1); - pr_debug("Setting clock period %d for HZ %d\n", (int)delta, HZ); - apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT); - ctrl |= APBTMR_CONTROL_ENABLE; - apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); - break; - /* APB timer does not have one-shot mode, use free running mode */ - case CLOCK_EVT_MODE_ONESHOT: - ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL); - /* - * set free running mode, this mode will let timer reload max - * timeout which will give time (3min on 25MHz clock) to rearm - * the next event, therefore emulate the one-shot mode. - */ - ctrl &= ~APBTMR_CONTROL_ENABLE; - ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; - - apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); - /* write again to set free running mode */ - apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); - - /* - * DW APB p. 46, load counter with all 1s before starting free - * running mode. - */ - apbt_writel(timer_num, ~0, APBTMR_N_LOAD_COUNT); - ctrl &= ~APBTMR_CONTROL_INT; - ctrl |= APBTMR_CONTROL_ENABLE; - apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); - break; - - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - apbt_disable_int(timer_num); - ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL); - ctrl &= ~APBTMR_CONTROL_ENABLE; - apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); - break; - - case CLOCK_EVT_MODE_RESUME: - apbt_enable_int(timer_num); - break; - } -} - -static int apbt_next_event(unsigned long delta, - struct clock_event_device *evt) -{ - unsigned long ctrl; - int timer_num; - - struct apbt_dev *adev = EVT_TO_APBT_DEV(evt); - - timer_num = adev->num; - /* Disable timer */ - ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL); - ctrl &= ~APBTMR_CONTROL_ENABLE; - apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); - /* write new count */ - apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT); - ctrl |= APBTMR_CONTROL_ENABLE; - apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); - return 0; -} - -static cycle_t apbt_read_clocksource(struct clocksource *cs) -{ - unsigned long current_count; - - current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE); - return (cycle_t)~current_count; -} - static int apbt_clocksource_register(void) { u64 start, now; cycle_t t1; /* Start the counter, use timer 2 as source, timer 0/1 for event */ - apbt_start_counter(phy_cs_timer_id); + dw_apb_clocksource_start(clocksource_apbt); /* Verify whether apbt counter works */ - t1 = apbt_read_clocksource(&clocksource_apbt); + t1 = dw_apb_clocksource_read(clocksource_apbt); rdtscll(start); /* @@ -540,10 +291,10 @@ static int apbt_clocksource_register(void) } while ((now - start) < 200000UL); /* APBT is the only always on clocksource, it has to work! */ - if (t1 == apbt_read_clocksource(&clocksource_apbt)) + if (t1 == dw_apb_clocksource_read(clocksource_apbt)) panic("APBT counter not counting. APBT disabled\n"); - clocksource_register_khz(&clocksource_apbt, (u32)apbt_freq*1000); + dw_apb_clocksource_register(clocksource_apbt); return 0; } @@ -567,10 +318,7 @@ void __init apbt_time_init(void) if (apb_timer_block_enabled) return; apbt_set_mapping(); - if (apbt_virt_address) { - pr_debug("Found APBT version 0x%lx\n",\ - apbt_readl_reg(APBTMRS_COMP_VERSION)); - } else + if (!apbt_virt_address) goto out_noapbt; /* * Read the frequency and check for a sane value, for ESL model @@ -578,7 +326,7 @@ void __init apbt_time_init(void) */ if (apbt_freq < APBT_MIN_FREQ || apbt_freq > APBT_MAX_FREQ) { - pr_debug("APBT has invalid freq 0x%llx\n", apbt_freq); + pr_debug("APBT has invalid freq 0x%lx\n", apbt_freq); goto out_noapbt; } if (apbt_clocksource_register()) { @@ -604,30 +352,20 @@ void __init apbt_time_init(void) } else { percpu_timer = 0; apbt_num_timers_used = 1; - adev = &per_cpu(cpu_apbt_dev, 0); - adev->flags &= ~APBT_DEV_USED; } pr_debug("%s: %d APB timers used\n", __func__, apbt_num_timers_used); /* here we set up per CPU timer data structure */ - apbt_devs = kzalloc(sizeof(struct apbt_dev) * apbt_num_timers_used, - GFP_KERNEL); - if (!apbt_devs) { - printk(KERN_ERR "Failed to allocate APB timer devices\n"); - return; - } for (i = 0; i < apbt_num_timers_used; i++) { adev = &per_cpu(cpu_apbt_dev, i); adev->num = i; adev->cpu = i; p_mtmr = sfi_get_mtmr(i); - if (p_mtmr) { - adev->tick = p_mtmr->freq_hz; + if (p_mtmr) adev->irq = p_mtmr->irq; - } else + else printk(KERN_ERR "Failed to get timer for cpu %d\n", i); - adev->count = 0; - sprintf(adev->name, "apbt%d", i); + snprintf(adev->name, sizeof(adev->name) - 1, "apbt%d", i); } #endif @@ -639,17 +377,8 @@ out_noapbt: panic("failed to enable APB timer\n"); } -static inline void apbt_disable(int n) -{ - if (is_apbt_capable()) { - unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); - ctrl &= ~APBTMR_CONTROL_ENABLE; - apbt_writel(n, ctrl, APBTMR_N_CONTROL); - } -} - /* called before apb_timer_enable, use early map */ -unsigned long apbt_quick_calibrate() +unsigned long apbt_quick_calibrate(void) { int i, scale; u64 old, new; @@ -658,31 +387,31 @@ unsigned long apbt_quick_calibrate() u32 loop, shift; apbt_set_mapping(); - apbt_start_counter(phy_cs_timer_id); + dw_apb_clocksource_start(clocksource_apbt); /* check if the timer can count down, otherwise return */ - old = apbt_read_clocksource(&clocksource_apbt); + old = dw_apb_clocksource_read(clocksource_apbt); i = 10000; while (--i) { - if (old != apbt_read_clocksource(&clocksource_apbt)) + if (old != dw_apb_clocksource_read(clocksource_apbt)) break; } if (!i) goto failed; /* count 16 ms */ - loop = (apbt_freq * 1000) << 4; + loop = (apbt_freq / 1000) << 4; /* restart the timer to ensure it won't get to 0 in the calibration */ - apbt_start_counter(phy_cs_timer_id); + dw_apb_clocksource_start(clocksource_apbt); - old = apbt_read_clocksource(&clocksource_apbt); + old = dw_apb_clocksource_read(clocksource_apbt); old += loop; t1 = __native_read_tsc(); do { - new = apbt_read_clocksource(&clocksource_apbt); + new = dw_apb_clocksource_read(clocksource_apbt); } while (new < old); t2 = __native_read_tsc(); @@ -694,7 +423,7 @@ unsigned long apbt_quick_calibrate() return 0; } scale = (int)div_u64((t2 - t1), loop >> shift); - khz = (scale * apbt_freq * 1000) >> shift; + khz = (scale * (apbt_freq / 1000)) >> shift; printk(KERN_INFO "TSC freq calculated by APB timer is %lu khz\n", khz); return khz; failed: diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 9498b84..b24be38 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1944,10 +1944,28 @@ void disconnect_bsp_APIC(int virt_wire_setup) void __cpuinit generic_processor_info(int apicid, int version) { - int cpu; + int cpu, max = nr_cpu_ids; + bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid, + phys_cpu_present_map); + + /* + * If boot cpu has not been detected yet, then only allow upto + * nr_cpu_ids - 1 processors and keep one slot free for boot cpu + */ + if (!boot_cpu_detected && num_processors >= nr_cpu_ids - 1 && + apicid != boot_cpu_physical_apicid) { + int thiscpu = max + disabled_cpus - 1; + + pr_warning( + "ACPI: NR_CPUS/possible_cpus limit of %i almost" + " reached. Keeping one slot for boot cpu." + " Processor %d/0x%x ignored.\n", max, thiscpu, apicid); + + disabled_cpus++; + return; + } if (num_processors >= nr_cpu_ids) { - int max = nr_cpu_ids; int thiscpu = max + disabled_cpus; pr_warning( diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 525514c..46674fb 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -62,6 +62,8 @@ static void __init check_fpu(void) return; } + kernel_fpu_begin(); + /* * trap_init() enabled FXSR and company _before_ testing for FP * problems here. @@ -80,6 +82,8 @@ static void __init check_fpu(void) : "=m" (*&fdiv_bug) : "m" (*&x), "m" (*&y)); + kernel_fpu_end(); + boot_cpu_data.fdiv_bug = fdiv_bug; if (boot_cpu_data.fdiv_bug) printk(KERN_WARNING "Hmm, FPU with FDIV bug.\n"); diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index 8095f86..755f64f 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c @@ -32,11 +32,11 @@ */ static const __initconst struct hypervisor_x86 * const hypervisors[] = { - &x86_hyper_vmware, - &x86_hyper_ms_hyperv, #ifdef CONFIG_XEN_PVHVM &x86_hyper_xen_hvm, #endif + &x86_hyper_vmware, + &x86_hyper_ms_hyperv, }; const struct hypervisor_x86 *x86_hyper; diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 8bbe8c5..b78643d 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -10,7 +10,7 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) { - u8 config, rev; + u8 config; u16 word; /* BIOS may enable hardware IRQ balancing for @@ -18,8 +18,7 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) * based platforms. * Disable SW irqbalance/affinity on those platforms. */ - pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev); - if (rev > 0x9) + if (dev->revision > 0x9) return; /* enable access to config space*/ diff --git a/arch/x86/kernel/relocate_kernel_32.S b/arch/x86/kernel/relocate_kernel_32.S index 4123553..36818f8 100644 --- a/arch/x86/kernel/relocate_kernel_32.S +++ b/arch/x86/kernel/relocate_kernel_32.S @@ -97,6 +97,8 @@ relocate_kernel: ret identity_mapped: + /* set return address to 0 if not preserving context */ + pushl $0 /* store the start address on the stack */ pushl %edx diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S index 4de8f5b..7a6f3b3 100644 --- a/arch/x86/kernel/relocate_kernel_64.S +++ b/arch/x86/kernel/relocate_kernel_64.S @@ -100,6 +100,8 @@ relocate_kernel: ret identity_mapped: + /* set return address to 0 if not preserving context */ + pushq $0 /* store the start address on the stack */ pushq %rdx diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 56c633a..db48336 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -5,7 +5,6 @@ #include <linux/timer.h> #include <linux/acpi_pmtmr.h> #include <linux/cpufreq.h> -#include <linux/dmi.h> #include <linux/delay.h> #include <linux/clocksource.h> #include <linux/percpu.h> @@ -800,27 +799,6 @@ void mark_tsc_unstable(char *reason) EXPORT_SYMBOL_GPL(mark_tsc_unstable); -static int __init dmi_mark_tsc_unstable(const struct dmi_system_id *d) -{ - printk(KERN_NOTICE "%s detected: marking TSC unstable.\n", - d->ident); - tsc_unstable = 1; - return 0; -} - -/* List of systems that have known TSC problems */ -static struct dmi_system_id __initdata bad_tsc_dmi_table[] = { - { - .callback = dmi_mark_tsc_unstable, - .ident = "IBM Thinkpad 380XD", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), - DMI_MATCH(DMI_BOARD_NAME, "2635FA0"), - }, - }, - {} -}; - static void __init check_system_tsc_reliable(void) { #ifdef CONFIG_MGEODE_LX @@ -1010,8 +988,6 @@ void __init tsc_init(void) lpj_fine = lpj; use_tsc_delay(); - /* Check and install the TSC clocksource */ - dmi_check_system(bad_tsc_dmi_table); if (unsynchronized_tsc()) mark_tsc_unstable("TSCs unsynchronized"); diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 50f6364..65cf823 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -76,6 +76,5 @@ config KVM_MMU_AUDIT # the virtualization menu. source drivers/vhost/Kconfig source drivers/lguest/Kconfig -source drivers/virtio/Kconfig endif # VIRTUALIZATION diff --git a/drivers/Kconfig b/drivers/Kconfig index 52e306d..9e7a4f5 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -112,6 +112,8 @@ source "drivers/uio/Kconfig" source "drivers/vlynq/Kconfig" +source "drivers/virtio/Kconfig" + source "drivers/xen/Kconfig" source "drivers/staging/Kconfig" diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index d8d3e02..34e9c4f 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -12,3 +12,6 @@ config CLKBLD_I8253 config CLKSRC_MMIO bool + +config DW_APB_TIMER + bool diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 7922a0c..85ad1646 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o obj-$(CONFIG_CLKBLD_I8253) += i8253.o obj-$(CONFIG_CLKSRC_MMIO) += mmio.o +obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c new file mode 100644 index 0000000..580f870 --- /dev/null +++ b/drivers/clocksource/dw_apb_timer.c @@ -0,0 +1,401 @@ +/* + * (C) Copyright 2009 Intel Corporation + * Author: Jacob Pan (jacob.jun.pan@intel.com) + * + * Shared with ARM platforms, Jamie Iles, Picochip 2011 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Support for the Synopsys DesignWare APB Timers. + */ +#include <linux/dw_apb_timer.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <linux/slab.h> + +#define APBT_MIN_PERIOD 4 +#define APBT_MIN_DELTA_USEC 200 + +#define APBTMR_N_LOAD_COUNT 0x00 +#define APBTMR_N_CURRENT_VALUE 0x04 +#define APBTMR_N_CONTROL 0x08 +#define APBTMR_N_EOI 0x0c +#define APBTMR_N_INT_STATUS 0x10 + +#define APBTMRS_INT_STATUS 0xa0 +#define APBTMRS_EOI 0xa4 +#define APBTMRS_RAW_INT_STATUS 0xa8 +#define APBTMRS_COMP_VERSION 0xac + +#define APBTMR_CONTROL_ENABLE (1 << 0) +/* 1: periodic, 0:free running. */ +#define APBTMR_CONTROL_MODE_PERIODIC (1 << 1) +#define APBTMR_CONTROL_INT (1 << 2) + +static inline struct dw_apb_clock_event_device * +ced_to_dw_apb_ced(struct clock_event_device *evt) +{ + return container_of(evt, struct dw_apb_clock_event_device, ced); +} + +static inline struct dw_apb_clocksource * +clocksource_to_dw_apb_clocksource(struct clocksource *cs) +{ + return container_of(cs, struct dw_apb_clocksource, cs); +} + +static unsigned long apbt_readl(struct dw_apb_timer *timer, unsigned long offs) +{ + return readl(timer->base + offs); +} + +static void apbt_writel(struct dw_apb_timer *timer, unsigned long val, + unsigned long offs) +{ + writel(val, timer->base + offs); +} + +static void apbt_disable_int(struct dw_apb_timer *timer) +{ + unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL); + + ctrl |= APBTMR_CONTROL_INT; + apbt_writel(timer, ctrl, APBTMR_N_CONTROL); +} + +/** + * dw_apb_clockevent_pause() - stop the clock_event_device from running + * + * @dw_ced: The APB clock to stop generating events. + */ +void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced) +{ + disable_irq(dw_ced->timer.irq); + apbt_disable_int(&dw_ced->timer); +} + +static void apbt_eoi(struct dw_apb_timer *timer) +{ + apbt_readl(timer, APBTMR_N_EOI); +} + +static irqreturn_t dw_apb_clockevent_irq(int irq, void *data) +{ + struct clock_event_device *evt = data; + struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); + + if (!evt->event_handler) { + pr_info("Spurious APBT timer interrupt %d", irq); + return IRQ_NONE; + } + + if (dw_ced->eoi) + dw_ced->eoi(&dw_ced->timer); + + evt->event_handler(evt); + return IRQ_HANDLED; +} + +static void apbt_enable_int(struct dw_apb_timer *timer) +{ + unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL); + /* clear pending intr */ + apbt_readl(timer, APBTMR_N_EOI); + ctrl &= ~APBTMR_CONTROL_INT; + apbt_writel(timer, ctrl, APBTMR_N_CONTROL); +} + +static void apbt_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + unsigned long ctrl; + unsigned long period; + struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); + + pr_debug("%s CPU %d mode=%d\n", __func__, first_cpu(*evt->cpumask), + mode); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + period = DIV_ROUND_UP(dw_ced->timer.freq, HZ); + ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); + ctrl |= APBTMR_CONTROL_MODE_PERIODIC; + apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); + /* + * DW APB p. 46, have to disable timer before load counter, + * may cause sync problem. + */ + ctrl &= ~APBTMR_CONTROL_ENABLE; + apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); + udelay(1); + pr_debug("Setting clock period %lu for HZ %d\n", period, HZ); + apbt_writel(&dw_ced->timer, period, APBTMR_N_LOAD_COUNT); + ctrl |= APBTMR_CONTROL_ENABLE; + apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); + break; + + case CLOCK_EVT_MODE_ONESHOT: + ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); + /* + * set free running mode, this mode will let timer reload max + * timeout which will give time (3min on 25MHz clock) to rearm + * the next event, therefore emulate the one-shot mode. + */ + ctrl &= ~APBTMR_CONTROL_ENABLE; + ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; + + apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); + /* write again to set free running mode */ + apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); + + /* + * DW APB p. 46, load counter with all 1s before starting free + * running mode. + */ + apbt_writel(&dw_ced->timer, ~0, APBTMR_N_LOAD_COUNT); + ctrl &= ~APBTMR_CONTROL_INT; + ctrl |= APBTMR_CONTROL_ENABLE; + apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); + break; + + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); + ctrl &= ~APBTMR_CONTROL_ENABLE; + apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); + break; + + case CLOCK_EVT_MODE_RESUME: + apbt_enable_int(&dw_ced->timer); + break; + } +} + +static int apbt_next_event(unsigned long delta, + struct clock_event_device *evt) +{ + unsigned long ctrl; + struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); + + /* Disable timer */ + ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); + ctrl &= ~APBTMR_CONTROL_ENABLE; + apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); + /* write new count */ + apbt_writel(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT); + ctrl |= APBTMR_CONTROL_ENABLE; + apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); + + return 0; +} + +/** + * dw_apb_clockevent_init() - use an APB timer as a clock_event_device + * + * @cpu: The CPU the events will be targeted at. + * @name: The name used for the timer and the IRQ for it. + * @rating: The rating to give the timer. + * @base: I/O base for the timer registers. + * @irq: The interrupt number to use for the timer. + * @freq: The frequency that the timer counts at. + * + * This creates a clock_event_device for using with the generic clock layer + * but does not start and register it. This should be done with + * dw_apb_clockevent_register() as the next step. If this is the first time + * it has been called for a timer then the IRQ will be requested, if not it + * just be enabled to allow CPU hotplug to avoid repeatedly requesting and + * releasing the IRQ. + */ +struct dw_apb_clock_event_device * +dw_apb_clockevent_init(int cpu, const char *name, unsigned rating, + void __iomem *base, int irq, unsigned long freq) +{ + struct dw_apb_clock_event_device *dw_ced = + kzalloc(sizeof(*dw_ced), GFP_KERNEL); + int err; + + if (!dw_ced) + return NULL; + + dw_ced->timer.base = base; + dw_ced->timer.irq = irq; + dw_ced->timer.freq = freq; + + clockevents_calc_mult_shift(&dw_ced->ced, freq, APBT_MIN_PERIOD); + dw_ced->ced.max_delta_ns = clockevent_delta2ns(0x7fffffff, + &dw_ced->ced); + dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced); + dw_ced->ced.cpumask = cpumask_of(cpu); + dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; + dw_ced->ced.set_mode = apbt_set_mode; + dw_ced->ced.set_next_event = apbt_next_event; + dw_ced->ced.irq = dw_ced->timer.irq; + dw_ced->ced.rating = rating; + dw_ced->ced.name = name; + + dw_ced->irqaction.name = dw_ced->ced.name; + dw_ced->irqaction.handler = dw_apb_clockevent_irq; + dw_ced->irqaction.dev_id = &dw_ced->ced; + dw_ced->irqaction.irq = irq; + dw_ced->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | + IRQF_NOBALANCING | + IRQF_DISABLED; + + dw_ced->eoi = apbt_eoi; + err = setup_irq(irq, &dw_ced->irqaction); + if (err) { + pr_err("failed to request timer irq\n"); + kfree(dw_ced); + dw_ced = NULL; + } + + return dw_ced; +} + +/** + * dw_apb_clockevent_resume() - resume a clock that has been paused. + * + * @dw_ced: The APB clock to resume. + */ +void dw_apb_clockevent_resume(struct dw_apb_clock_event_device *dw_ced) +{ + enable_irq(dw_ced->timer.irq); +} + +/** + * dw_apb_clockevent_stop() - stop the clock_event_device and release the IRQ. + * + * @dw_ced: The APB clock to stop generating the events. + */ +void dw_apb_clockevent_stop(struct dw_apb_clock_event_device *dw_ced) +{ + free_irq(dw_ced->timer.irq, &dw_ced->ced); +} + +/** + * dw_apb_clockevent_register() - register the clock with the generic layer + * + * @dw_ced: The APB clock to register as a clock_event_device. + */ +void dw_apb_clockevent_register(struct dw_apb_clock_event_device *dw_ced) +{ + apbt_writel(&dw_ced->timer, 0, APBTMR_N_CONTROL); + clockevents_register_device(&dw_ced->ced); + apbt_enable_int(&dw_ced->timer); +} + +/** + * dw_apb_clocksource_start() - start the clocksource counting. + * + * @dw_cs: The clocksource to start. + * + * This is used to start the clocksource before registration and can be used + * to enable calibration of timers. + */ +void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs) +{ + /* + * start count down from 0xffff_ffff. this is done by toggling the + * enable bit then load initial load count to ~0. + */ + unsigned long ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL); + + ctrl &= ~APBTMR_CONTROL_ENABLE; + apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL); + apbt_writel(&dw_cs->timer, ~0, APBTMR_N_LOAD_COUNT); + /* enable, mask interrupt */ + ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; + ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT); + apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL); + /* read it once to get cached counter value initialized */ + dw_apb_clocksource_read(dw_cs); +} + +static cycle_t __apbt_read_clocksource(struct clocksource *cs) +{ + unsigned long current_count; + struct dw_apb_clocksource *dw_cs = + clocksource_to_dw_apb_clocksource(cs); + + current_count = apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE); + + return (cycle_t)~current_count; +} + +static void apbt_restart_clocksource(struct clocksource *cs) +{ + struct dw_apb_clocksource *dw_cs = + clocksource_to_dw_apb_clocksource(cs); + + dw_apb_clocksource_start(dw_cs); +} + +/** + * dw_apb_clocksource_init() - use an APB timer as a clocksource. + * + * @rating: The rating to give the clocksource. + * @name: The name for the clocksource. + * @base: The I/O base for the timer registers. + * @freq: The frequency that the timer counts at. + * + * This creates a clocksource using an APB timer but does not yet register it + * with the clocksource system. This should be done with + * dw_apb_clocksource_register() as the next step. + */ +struct dw_apb_clocksource * +dw_apb_clocksource_init(unsigned rating, char *name, void __iomem *base, + unsigned long freq) +{ + struct dw_apb_clocksource *dw_cs = kzalloc(sizeof(*dw_cs), GFP_KERNEL); + + if (!dw_cs) + return NULL; + + dw_cs->timer.base = base; + dw_cs->timer.freq = freq; + dw_cs->cs.name = name; + dw_cs->cs.rating = rating; + dw_cs->cs.read = __apbt_read_clocksource; + dw_cs->cs.mask = CLOCKSOURCE_MASK(32); + dw_cs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; + dw_cs->cs.resume = apbt_restart_clocksource; + + return dw_cs; +} + +/** + * dw_apb_clocksource_register() - register the APB clocksource. + * + * @dw_cs: The clocksource to register. + */ +void dw_apb_clocksource_register(struct dw_apb_clocksource *dw_cs) +{ + clocksource_register_hz(&dw_cs->cs, dw_cs->timer.freq); +} + +/** + * dw_apb_clocksource_read() - read the current value of a clocksource. + * + * @dw_cs: The clocksource to read. + */ +cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs) +{ + return (cycle_t)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE); +} + +/** + * dw_apb_clocksource_unregister() - unregister and free a clocksource. + * + * @dw_cs: The clocksource to unregister/free. + */ +void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs) +{ + clocksource_unregister(&dw_cs->cs); + + kfree(dw_cs); +} diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index 3dd6294..57e493b 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -7,6 +7,8 @@ config VIRTIO_RING tristate depends on VIRTIO +menu "Virtio drivers" + config VIRTIO_PCI tristate "PCI driver for virtio devices (EXPERIMENTAL)" depends on PCI && EXPERIMENTAL @@ -33,3 +35,4 @@ config VIRTIO_BALLOON If unsure, say M. +endmenu diff --git a/include/linux/dw_apb_timer.h b/include/linux/dw_apb_timer.h new file mode 100644 index 0000000..49638ea --- /dev/null +++ b/include/linux/dw_apb_timer.h @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2009 Intel Corporation + * Author: Jacob Pan (jacob.jun.pan@intel.com) + * + * Shared with ARM platforms, Jamie Iles, Picochip 2011 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Support for the Synopsys DesignWare APB Timers. + */ +#ifndef __DW_APB_TIMER_H__ +#define __DW_APB_TIMER_H__ + +#include <linux/clockchips.h> +#include <linux/clocksource.h> +#include <linux/interrupt.h> + +#define APBTMRS_REG_SIZE 0x14 + +struct dw_apb_timer { + void __iomem *base; + unsigned long freq; + int irq; +}; + +struct dw_apb_clock_event_device { + struct clock_event_device ced; + struct dw_apb_timer timer; + struct irqaction irqaction; + void (*eoi)(struct dw_apb_timer *); +}; + +struct dw_apb_clocksource { + struct dw_apb_timer timer; + struct clocksource cs; +}; + +void dw_apb_clockevent_register(struct dw_apb_clock_event_device *dw_ced); +void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced); +void dw_apb_clockevent_resume(struct dw_apb_clock_event_device *dw_ced); +void dw_apb_clockevent_stop(struct dw_apb_clock_event_device *dw_ced); + +struct dw_apb_clock_event_device * +dw_apb_clockevent_init(int cpu, const char *name, unsigned rating, + void __iomem *base, int irq, unsigned long freq); +struct dw_apb_clocksource * +dw_apb_clocksource_init(unsigned rating, char *name, void __iomem *base, + unsigned long freq); +void dw_apb_clocksource_register(struct dw_apb_clocksource *dw_cs); +void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs); +cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs); +void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs); + +#endif /* __DW_APB_TIMER_H__ */ diff --git a/include/linux/irq.h b/include/linux/irq.h index baa397e..5f69504 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -96,11 +96,6 @@ enum { #define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING) -static inline __deprecated bool CHECK_IRQ_PER_CPU(unsigned int status) -{ - return status & IRQ_PER_CPU; -} - /* * Return value for chip->irq_set_affinity() * diff --git a/init/Kconfig b/init/Kconfig index 27b8a7a..e20aa31 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -917,6 +917,8 @@ config ANON_INODES menuconfig EXPERT bool "Configure standard kernel features (expert users)" + # Unhide debug options, to make the on-by-default options visible + select DEBUG_KERNEL help This option allows certain base kernel options and settings to be disabled or tweaked. This is for specialized diff --git a/tools/perf/Makefile b/tools/perf/Makefile index d0861bb..56d62d3 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -52,7 +52,10 @@ ifeq ($(ARCH),i386) endif ifeq ($(ARCH),x86_64) ARCH := x86 - IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) + IS_X86_64 := 0 + ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) + IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) + endif ifeq (${IS_X86_64}, 1) RAW_ARCH := x86_64 ARCH_CFLAGS := -DARCH_X86_64 |