[PATCH] cpufreq: Fix RCU reboot regression on x86 PIC machines
From: Ville Syrjälä Since 4.20-rc1 my PIC machines no longer reboot/shutdown. I bisected this down to commit 45975c7d21a1 ("rcu: Define RCU-sched API in terms of RCU for Tree RCU PREEMPT builds"). I traced the hang into -> cpufreq_suspend() -> cpufreq_stop_governor() -> cpufreq_dbs_governor_stop() -> gov_clear_update_util() -> synchronize_sched() -> synchronize_rcu() Only PREEMPT=y is affected for obvious reasons. The problem is limited to PIC machines since they mask off interrupts in i8259A_shutdown() (syscore_ops.shutdown() registered from device_initcall()). I reported this long ago but no better fix has surfaced, hence sending out my initial workaround which I've been carrying around ever since. I just move cpufreq_core_init() to late_initcall() so the syscore_ops get registered in the oppsite order and thus the .shutdown() hooks get executed in the opposite order as well. Not 100% convinced this is safe (especially moving the cpufreq_global_kobject creation to late_initcall()) but I've not had any problems with it at least. Here's the resulting change in initcall_debug: + PM: Calling cpufreq_suspend+0x0/0x100 PM: Calling mce_syscore_shutdown+0x0/0x10 PM: Calling i8259A_shutdown+0x0/0x10 - PM: Calling cpufreq_suspend+0x0/0x100 + reboot: Restarting system + reboot: machine restart Cc: sta...@vger.kernel.org Cc: Paul E. McKenney Cc: Andi Kleen Cc: "Rafael J. Wysocki" Cc: Viresh Kumar Cc: linux...@vger.kernel.org Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: "H. Peter Anvin" Fixes: 45975c7d21a1 ("rcu: Define RCU-sched API in terms of RCU for Tree RCU PREEMPT builds") Signed-off-by: Ville Syrjälä --- drivers/cpufreq/cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index c52d6fa32aac..6a8fb9b08e33 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -2761,4 +2761,4 @@ static int __init cpufreq_core_init(void) return 0; } module_param(off, int, 0444); -core_initcall(cpufreq_core_init); +late_initcall(cpufreq_core_init); -- 2.21.0
[PATCH] Revert "x86/tsc: Consolidate init code"
From: Ville Syrjälä This reverts commit 608008a45798fe9e2aee04f99b5270ea57c1376f. It breaks wifi on my pentium 3 Fujitsu-Siemens Lifebook S6010 laptop. Scanning for APs doesn't seem to work most of the time, and, even when it manages to find some APs it never manages to authenticate successfully. dmesg is just littered with: "wlan0: send auth to ... (try 1/3) wlan0: send auth to ... (try 2/3) wlan0: send auth to ... (try 3/3) wlan0: authentication with ... timed out" Presumably also USB is broken on account of the following noise in dmesg: "usb usb2-port2: Cannot enable. Maybe the USB cable is bad?". Cc: Dou Liyang Cc: Thomas Gleixner Cc: Pavel Tatashin Cc: Cc: Peter Zijlstra Cc: "H. Peter Anvin" Signed-off-by: Ville Syrjälä --- arch/x86/kernel/tsc.c | 22 ++ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 6490f618e096..203edfabe813 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -182,7 +182,7 @@ static void __init cyc2ns_init_boot_cpu(void) } /* - * Secondary CPUs do not run through tsc_init(), so set up + * Secondary CPUs do not run through cyc2ns_init(), so set up * all the scale factors for all CPUs, assuming the same * speed as the bootup CPU. (cpufreq notifiers will fix this * up if their speed diverges) @@ -1389,7 +1389,7 @@ static bool __init determine_cpu_tsc_frequencies(bool early) } /* -* Trust non-zero tsc_khz as authoritative, +* Trust non-zero tsc_khz as authorative, * and use it to sanity check cpu_khz, * which will be off if system timer is off. */ @@ -1421,14 +1421,6 @@ static unsigned long __init get_loops_per_jiffy(void) return lpj; } -static void __init tsc_enable_sched_clock(void) -{ - /* Sanitize TSC ADJUST before cyc2ns gets initialized */ - tsc_store_and_check_tsc_adjust(true); - cyc2ns_init_boot_cpu(); - static_branch_enable(&__use_tsc); -} - void __init tsc_early_init(void) { if (!boot_cpu_has(X86_FEATURE_TSC)) @@ -1437,7 +1429,10 @@ void __init tsc_early_init(void) return; loops_per_jiffy = get_loops_per_jiffy(); - tsc_enable_sched_clock(); + /* Sanitize TSC ADJUST before cyc2ns gets initialized */ + tsc_store_and_check_tsc_adjust(true); + cyc2ns_init_boot_cpu(); + static_branch_enable(&__use_tsc); } void __init tsc_init(void) @@ -1461,10 +1456,13 @@ void __init tsc_init(void) setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER); return; } - tsc_enable_sched_clock(); + /* Sanitize TSC ADJUST before cyc2ns gets initialized */ + tsc_store_and_check_tsc_adjust(true); + cyc2ns_init_boot_cpu(); } cyc2ns_init_secondary_cpus(); + static_branch_enable(&__use_tsc); if (!no_sched_irq_time) enable_sched_clock_irqtime(); -- 2.16.4
[PATCH] Revert "x86/tsc: Consolidate init code"
From: Ville Syrjälä This reverts commit 608008a45798fe9e2aee04f99b5270ea57c1376f. It breaks wifi on my pentium 3 Fujitsu-Siemens Lifebook S6010 laptop. Scanning for APs doesn't seem to work most of the time, and, even when it manages to find some APs it never manages to authenticate successfully. dmesg is just littered with: "wlan0: send auth to ... (try 1/3) wlan0: send auth to ... (try 2/3) wlan0: send auth to ... (try 3/3) wlan0: authentication with ... timed out" Presumably also USB is broken on account of the following noise in dmesg: "usb usb2-port2: Cannot enable. Maybe the USB cable is bad?". Cc: Dou Liyang Cc: Thomas Gleixner Cc: Pavel Tatashin Cc: Cc: Peter Zijlstra Cc: "H. Peter Anvin" Signed-off-by: Ville Syrjälä --- arch/x86/kernel/tsc.c | 22 ++ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 6490f618e096..203edfabe813 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -182,7 +182,7 @@ static void __init cyc2ns_init_boot_cpu(void) } /* - * Secondary CPUs do not run through tsc_init(), so set up + * Secondary CPUs do not run through cyc2ns_init(), so set up * all the scale factors for all CPUs, assuming the same * speed as the bootup CPU. (cpufreq notifiers will fix this * up if their speed diverges) @@ -1389,7 +1389,7 @@ static bool __init determine_cpu_tsc_frequencies(bool early) } /* -* Trust non-zero tsc_khz as authoritative, +* Trust non-zero tsc_khz as authorative, * and use it to sanity check cpu_khz, * which will be off if system timer is off. */ @@ -1421,14 +1421,6 @@ static unsigned long __init get_loops_per_jiffy(void) return lpj; } -static void __init tsc_enable_sched_clock(void) -{ - /* Sanitize TSC ADJUST before cyc2ns gets initialized */ - tsc_store_and_check_tsc_adjust(true); - cyc2ns_init_boot_cpu(); - static_branch_enable(&__use_tsc); -} - void __init tsc_early_init(void) { if (!boot_cpu_has(X86_FEATURE_TSC)) @@ -1437,7 +1429,10 @@ void __init tsc_early_init(void) return; loops_per_jiffy = get_loops_per_jiffy(); - tsc_enable_sched_clock(); + /* Sanitize TSC ADJUST before cyc2ns gets initialized */ + tsc_store_and_check_tsc_adjust(true); + cyc2ns_init_boot_cpu(); + static_branch_enable(&__use_tsc); } void __init tsc_init(void) @@ -1461,10 +1456,13 @@ void __init tsc_init(void) setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER); return; } - tsc_enable_sched_clock(); + /* Sanitize TSC ADJUST before cyc2ns gets initialized */ + tsc_store_and_check_tsc_adjust(true); + cyc2ns_init_boot_cpu(); } cyc2ns_init_secondary_cpus(); + static_branch_enable(&__use_tsc); if (!no_sched_irq_time) enable_sched_clock_irqtime(); -- 2.16.4
[RFC][PATCH] kconfig: Add "m or y" and "y or m" answers for oldconfig
From: Ville Syrjälä Make it possible to answer "m or y" or "y or m" to oldconfig so that scripted kernel builds can easily enable new features not present in the existing .config. The particular use case I have in mind is continuous integration where you probably want to test build any new features. Currently you would have to either blindly try both 'y' and 'm' answers or parse the output to know which one will be accepted. Cc: Masahiro Yamada Cc: linux-kbu...@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- scripts/kconfig/conf.c | 26 ++ 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 671ff5364497..8038f9a6b9f4 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -201,15 +201,33 @@ static int conf_sym(struct menu *menu) continue; case 'm': case 'M': - newval = mod; - if (!line[1]) + if (!strcmp(line, "m or y") || + !strcmp(line, "M or Y")) { + if (sym_tristate_within_range(sym, mod)) + newval = mod; + else + newval = yes; break; + } else { + newval = mod; + if (!line[1]) + break; + } continue; case 'y': case 'Y': - newval = yes; - if (!line[1] || !strcmp([1], "es")) + if (!strcmp(line, "y or m") || + !strcmp(line, "Y or M")) { + if (sym_tristate_within_range(sym, yes)) + newval = yes; + else + newval = mod; break; + } else { + newval = yes; + if (!line[1] || !strcmp([1], "es")) + break; + } continue; case 0: newval = oldval; -- 2.16.4
[RFC][PATCH] kconfig: Add "m or y" and "y or m" answers for oldconfig
From: Ville Syrjälä Make it possible to answer "m or y" or "y or m" to oldconfig so that scripted kernel builds can easily enable new features not present in the existing .config. The particular use case I have in mind is continuous integration where you probably want to test build any new features. Currently you would have to either blindly try both 'y' and 'm' answers or parse the output to know which one will be accepted. Cc: Masahiro Yamada Cc: linux-kbu...@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- scripts/kconfig/conf.c | 26 ++ 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 671ff5364497..8038f9a6b9f4 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -201,15 +201,33 @@ static int conf_sym(struct menu *menu) continue; case 'm': case 'M': - newval = mod; - if (!line[1]) + if (!strcmp(line, "m or y") || + !strcmp(line, "M or Y")) { + if (sym_tristate_within_range(sym, mod)) + newval = mod; + else + newval = yes; break; + } else { + newval = mod; + if (!line[1]) + break; + } continue; case 'y': case 'Y': - newval = yes; - if (!line[1] || !strcmp([1], "es")) + if (!strcmp(line, "y or m") || + !strcmp(line, "Y or M")) { + if (sym_tristate_within_range(sym, yes)) + newval = yes; + else + newval = mod; break; + } else { + newval = yes; + if (!line[1] || !strcmp([1], "es")) + break; + } continue; case 0: newval = oldval; -- 2.16.4
[PATCH] x86/apm: Don't access __preempt_count with zeroed fs
From: Ville Syrjälä APM_DO_POP_SEGS does not restore fs/gs which were zeroed by APM_DO_ZERO_SEGS. Trying to access __preempt_count with zeroed fs doesn't really work. Move the ibrs stuff outside the APM_DO_SAVE_SEGS/APM_DO_RESTORE_SEGS invocations so that fs is actually restored before we call preempt_enable(). Fixes the following sort of oopses: [0.313581] general protection fault: [#1] PREEMPT SMP [0.313803] Modules linked in: [0.314040] CPU: 0 PID: 268 Comm: kapmd Not tainted 4.16.0-rc1-triton-bisect-00090-gdd84441a7971 #19 [0.316161] EIP: __apm_bios_call_simple+0xc8/0x170 [0.316161] EFLAGS: 00210016 CPU: 0 [0.316161] EAX: 0102 EBX: ECX: 0102 EDX: [0.316161] ESI: 530e EDI: dea95f64 EBP: dea95f18 ESP: dea95ef0 [0.316161] DS: 007b ES: 007b FS: GS: SS: 0068 [0.316161] CR0: 80050033 CR2: CR3: 015d3000 CR4: 06d0 [0.316161] Call Trace: [0.316161] ? cpumask_weight.constprop.15+0x20/0x20 [0.316161] on_cpu0+0x44/0x70 [0.316161] apm+0x54e/0x720 [0.316161] ? __switch_to_asm+0x26/0x40 [0.316161] ? __schedule+0x17d/0x590 [0.316161] kthread+0xc0/0xf0 [0.316161] ? proc_apm_show+0x150/0x150 [0.316161] ? kthread_create_worker_on_cpu+0x20/0x20 [0.316161] ret_from_fork+0x2e/0x38 [0.316161] Code: da 8e c2 8e e2 8e ea 57 55 2e ff 1d e0 bb 5d b1 0f 92 c3 5d 5f 07 1f 89 47 0c 90 8d b4 26 00 00 00 00 90 8d b4 26 00 00 00 00 90 <64> ff 0d 84 16 5c b1 74 7f 8b 45 dc 8e e0 8b 45 d8 8e e8 8b 45 [0.316161] EIP: __apm_bios_call_simple+0xc8/0x170 SS:ESP: 0068:dea95ef0 [0.316161] ---[ end trace 656253db2deaa12c ]--- Cc: sta...@vger.kernel.org Cc: David Woodhouse Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Fixes: dd84441a7971 ("x86/speculation: Use IBRS if available before calling into firmware") Signed-off-by: Ville Syrjälä --- arch/x86/include/asm/apm.h | 6 -- arch/x86/kernel/apm_32.c | 5 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/apm.h b/arch/x86/include/asm/apm.h index c356098b6fb9..4d4015ddcf26 100644 --- a/arch/x86/include/asm/apm.h +++ b/arch/x86/include/asm/apm.h @@ -7,8 +7,6 @@ #ifndef _ASM_X86_MACH_DEFAULT_APM_H #define _ASM_X86_MACH_DEFAULT_APM_H -#include - #ifdef APM_ZERO_SEGS # define APM_DO_ZERO_SEGS \ "pushl %%ds\n\t" \ @@ -34,7 +32,6 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in, * N.B. We do NOT need a cld after the BIOS call * because we always save and restore the flags. */ - firmware_restrict_branch_speculation_start(); __asm__ __volatile__(APM_DO_ZERO_SEGS "pushl %%edi\n\t" "pushl %%ebp\n\t" @@ -47,7 +44,6 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in, "=S" (*esi) : "a" (func), "b" (ebx_in), "c" (ecx_in) : "memory", "cc"); - firmware_restrict_branch_speculation_end(); } static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in, @@ -60,7 +56,6 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in, * N.B. We do NOT need a cld after the BIOS call * because we always save and restore the flags. */ - firmware_restrict_branch_speculation_start(); __asm__ __volatile__(APM_DO_ZERO_SEGS "pushl %%edi\n\t" "pushl %%ebp\n\t" @@ -73,7 +68,6 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in, "=S" (si) : "a" (func), "b" (ebx_in), "c" (ecx_in) : "memory", "cc"); - firmware_restrict_branch_speculation_end(); return error; } diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 5d0de79fdab0..ec00d1ff5098 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -240,6 +240,7 @@ #include #include #include +#include #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT) extern int (*console_blank_hook)(int); @@ -614,11 +615,13 @@ static long __apm_bios_call(void *_call) gdt[0x40 / 8] = bad_bios_desc; apm_irq_save(flags); + firmware_restrict_branch_speculation_start(); APM_DO_SAVE_SEGS; apm_bios_call_asm(call->func, call->ebx, call->ecx, >eax, >ebx, >ecx, >edx, >esi); APM_DO_RESTORE_SEGS; + firmware_restrict_branch_speculation_end(); apm_irq_restore(flags); gdt[0x40 / 8] = save_desc_40; put_cpu(); @@ -690,10 +693,12 @@ static long __apm_bios_call_simple(void *_call) gdt[0x40 / 8] = bad_bios_desc; apm_irq_save(flags); + firmware_restrict_branch_speculation_start(); APM_DO_SAVE_SEGS; error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx,
[PATCH] x86/apm: Don't access __preempt_count with zeroed fs
From: Ville Syrjälä APM_DO_POP_SEGS does not restore fs/gs which were zeroed by APM_DO_ZERO_SEGS. Trying to access __preempt_count with zeroed fs doesn't really work. Move the ibrs stuff outside the APM_DO_SAVE_SEGS/APM_DO_RESTORE_SEGS invocations so that fs is actually restored before we call preempt_enable(). Fixes the following sort of oopses: [0.313581] general protection fault: [#1] PREEMPT SMP [0.313803] Modules linked in: [0.314040] CPU: 0 PID: 268 Comm: kapmd Not tainted 4.16.0-rc1-triton-bisect-00090-gdd84441a7971 #19 [0.316161] EIP: __apm_bios_call_simple+0xc8/0x170 [0.316161] EFLAGS: 00210016 CPU: 0 [0.316161] EAX: 0102 EBX: ECX: 0102 EDX: [0.316161] ESI: 530e EDI: dea95f64 EBP: dea95f18 ESP: dea95ef0 [0.316161] DS: 007b ES: 007b FS: GS: SS: 0068 [0.316161] CR0: 80050033 CR2: CR3: 015d3000 CR4: 06d0 [0.316161] Call Trace: [0.316161] ? cpumask_weight.constprop.15+0x20/0x20 [0.316161] on_cpu0+0x44/0x70 [0.316161] apm+0x54e/0x720 [0.316161] ? __switch_to_asm+0x26/0x40 [0.316161] ? __schedule+0x17d/0x590 [0.316161] kthread+0xc0/0xf0 [0.316161] ? proc_apm_show+0x150/0x150 [0.316161] ? kthread_create_worker_on_cpu+0x20/0x20 [0.316161] ret_from_fork+0x2e/0x38 [0.316161] Code: da 8e c2 8e e2 8e ea 57 55 2e ff 1d e0 bb 5d b1 0f 92 c3 5d 5f 07 1f 89 47 0c 90 8d b4 26 00 00 00 00 90 8d b4 26 00 00 00 00 90 <64> ff 0d 84 16 5c b1 74 7f 8b 45 dc 8e e0 8b 45 d8 8e e8 8b 45 [0.316161] EIP: __apm_bios_call_simple+0xc8/0x170 SS:ESP: 0068:dea95ef0 [0.316161] ---[ end trace 656253db2deaa12c ]--- Cc: sta...@vger.kernel.org Cc: David Woodhouse Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Fixes: dd84441a7971 ("x86/speculation: Use IBRS if available before calling into firmware") Signed-off-by: Ville Syrjälä --- arch/x86/include/asm/apm.h | 6 -- arch/x86/kernel/apm_32.c | 5 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/apm.h b/arch/x86/include/asm/apm.h index c356098b6fb9..4d4015ddcf26 100644 --- a/arch/x86/include/asm/apm.h +++ b/arch/x86/include/asm/apm.h @@ -7,8 +7,6 @@ #ifndef _ASM_X86_MACH_DEFAULT_APM_H #define _ASM_X86_MACH_DEFAULT_APM_H -#include - #ifdef APM_ZERO_SEGS # define APM_DO_ZERO_SEGS \ "pushl %%ds\n\t" \ @@ -34,7 +32,6 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in, * N.B. We do NOT need a cld after the BIOS call * because we always save and restore the flags. */ - firmware_restrict_branch_speculation_start(); __asm__ __volatile__(APM_DO_ZERO_SEGS "pushl %%edi\n\t" "pushl %%ebp\n\t" @@ -47,7 +44,6 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in, "=S" (*esi) : "a" (func), "b" (ebx_in), "c" (ecx_in) : "memory", "cc"); - firmware_restrict_branch_speculation_end(); } static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in, @@ -60,7 +56,6 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in, * N.B. We do NOT need a cld after the BIOS call * because we always save and restore the flags. */ - firmware_restrict_branch_speculation_start(); __asm__ __volatile__(APM_DO_ZERO_SEGS "pushl %%edi\n\t" "pushl %%ebp\n\t" @@ -73,7 +68,6 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in, "=S" (si) : "a" (func), "b" (ebx_in), "c" (ecx_in) : "memory", "cc"); - firmware_restrict_branch_speculation_end(); return error; } diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 5d0de79fdab0..ec00d1ff5098 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -240,6 +240,7 @@ #include #include #include +#include #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT) extern int (*console_blank_hook)(int); @@ -614,11 +615,13 @@ static long __apm_bios_call(void *_call) gdt[0x40 / 8] = bad_bios_desc; apm_irq_save(flags); + firmware_restrict_branch_speculation_start(); APM_DO_SAVE_SEGS; apm_bios_call_asm(call->func, call->ebx, call->ecx, >eax, >ebx, >ecx, >edx, >esi); APM_DO_RESTORE_SEGS; + firmware_restrict_branch_speculation_end(); apm_irq_restore(flags); gdt[0x40 / 8] = save_desc_40; put_cpu(); @@ -690,10 +693,12 @@ static long __apm_bios_call_simple(void *_call) gdt[0x40 / 8] = bad_bios_desc; apm_irq_save(flags); + firmware_restrict_branch_speculation_start(); APM_DO_SAVE_SEGS; error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx,
[PATCH] Revert "mm/cma: manage the memory of the CMA area by using the ZONE_MOVABLE"
From: Ville SyrjäläThis reverts commit bad8c6c0b1144694ecb0bc5629ede9b8b578b86e. Make x86 with HIGHMEM=y and CMA=y boot again. Cc: Joonsoo Kim Cc: Aneesh Kumar K.V Cc: Tony Lindgren Cc: Vlastimil Babka Cc: Johannes Weiner Cc: Laura Abbott Cc: Marek Szyprowski Cc: Mel Gorman Cc: Michal Hocko Cc: Michal Nazarewicz Cc: Minchan Kim Cc: Rik van Riel Cc: Russell King Cc: Will Deacon Cc: Andrew Morton Cc: Linus Torvalds Cc: linux...@kvack.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- include/linux/memory_hotplug.h | 3 ++ include/linux/mm.h | 1 - mm/cma.c | 83 ++ mm/internal.h | 3 -- mm/page_alloc.c| 55 +++- 5 files changed, 19 insertions(+), 126 deletions(-) diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index e0e49b5b1ee1..2b0265265c28 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h @@ -216,6 +216,9 @@ void put_online_mems(void); void mem_hotplug_begin(void); void mem_hotplug_done(void); +extern void set_zone_contiguous(struct zone *zone); +extern void clear_zone_contiguous(struct zone *zone); + #else /* ! CONFIG_MEMORY_HOTPLUG */ #define pfn_to_online_page(pfn)\ ({ \ diff --git a/include/linux/mm.h b/include/linux/mm.h index 1ac1f06a4be6..f7f1369e9d99 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2109,7 +2109,6 @@ extern void setup_per_cpu_pageset(void); extern void zone_pcp_update(struct zone *zone); extern void zone_pcp_reset(struct zone *zone); -extern void setup_zone_pageset(struct zone *zone); /* page_alloc.c */ extern int min_free_kbytes; diff --git a/mm/cma.c b/mm/cma.c index aa40e6c7b042..5809bbe360d7 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -39,7 +39,6 @@ #include #include "cma.h" -#include "internal.h" struct cma cma_areas[MAX_CMA_AREAS]; unsigned cma_area_count; @@ -110,25 +109,23 @@ static int __init cma_activate_area(struct cma *cma) if (!cma->bitmap) return -ENOMEM; + WARN_ON_ONCE(!pfn_valid(pfn)); + zone = page_zone(pfn_to_page(pfn)); + do { unsigned j; base_pfn = pfn; - if (!pfn_valid(base_pfn)) - goto err; - - zone = page_zone(pfn_to_page(base_pfn)); for (j = pageblock_nr_pages; j; --j, pfn++) { - if (!pfn_valid(pfn)) - goto err; - + WARN_ON_ONCE(!pfn_valid(pfn)); /* -* In init_cma_reserved_pageblock(), present_pages -* is adjusted with assumption that all pages in -* the pageblock come from a single zone. +* alloc_contig_range requires the pfn range +* specified to be in the same zone. Make this +* simple by forcing the entire CMA resv range +* to be in the same zone. */ if (page_zone(pfn_to_page(pfn)) != zone) - goto err; + goto not_in_zone; } init_cma_reserved_pageblock(pfn_to_page(base_pfn)); } while (--i); @@ -142,7 +139,7 @@ static int __init cma_activate_area(struct cma *cma) return 0; -err: +not_in_zone: pr_err("CMA area %s could not be activated\n", cma->name); kfree(cma->bitmap); cma->count = 0; @@ -152,41 +149,6 @@ static int __init cma_activate_area(struct cma *cma) static int __init cma_init_reserved_areas(void) { int i; - struct zone *zone; - pg_data_t *pgdat; - - if (!cma_area_count) - return 0; - - for_each_online_pgdat(pgdat) { - unsigned long start_pfn = UINT_MAX, end_pfn = 0; - - zone = >node_zones[ZONE_MOVABLE]; - - /* -* In this case, we cannot adjust the zone range -* since it is now maximum node span and we don't -* know original zone range. -*/ - if (populated_zone(zone)) - continue; - - for (i = 0; i < cma_area_count; i++) { - if (pfn_to_nid(cma_areas[i].base_pfn) != -
[PATCH] Revert "mm/cma: manage the memory of the CMA area by using the ZONE_MOVABLE"
From: Ville Syrjälä This reverts commit bad8c6c0b1144694ecb0bc5629ede9b8b578b86e. Make x86 with HIGHMEM=y and CMA=y boot again. Cc: Joonsoo Kim Cc: Aneesh Kumar K.V Cc: Tony Lindgren Cc: Vlastimil Babka Cc: Johannes Weiner Cc: Laura Abbott Cc: Marek Szyprowski Cc: Mel Gorman Cc: Michal Hocko Cc: Michal Nazarewicz Cc: Minchan Kim Cc: Rik van Riel Cc: Russell King Cc: Will Deacon Cc: Andrew Morton Cc: Linus Torvalds Cc: linux...@kvack.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- include/linux/memory_hotplug.h | 3 ++ include/linux/mm.h | 1 - mm/cma.c | 83 ++ mm/internal.h | 3 -- mm/page_alloc.c| 55 +++- 5 files changed, 19 insertions(+), 126 deletions(-) diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index e0e49b5b1ee1..2b0265265c28 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h @@ -216,6 +216,9 @@ void put_online_mems(void); void mem_hotplug_begin(void); void mem_hotplug_done(void); +extern void set_zone_contiguous(struct zone *zone); +extern void clear_zone_contiguous(struct zone *zone); + #else /* ! CONFIG_MEMORY_HOTPLUG */ #define pfn_to_online_page(pfn)\ ({ \ diff --git a/include/linux/mm.h b/include/linux/mm.h index 1ac1f06a4be6..f7f1369e9d99 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2109,7 +2109,6 @@ extern void setup_per_cpu_pageset(void); extern void zone_pcp_update(struct zone *zone); extern void zone_pcp_reset(struct zone *zone); -extern void setup_zone_pageset(struct zone *zone); /* page_alloc.c */ extern int min_free_kbytes; diff --git a/mm/cma.c b/mm/cma.c index aa40e6c7b042..5809bbe360d7 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -39,7 +39,6 @@ #include #include "cma.h" -#include "internal.h" struct cma cma_areas[MAX_CMA_AREAS]; unsigned cma_area_count; @@ -110,25 +109,23 @@ static int __init cma_activate_area(struct cma *cma) if (!cma->bitmap) return -ENOMEM; + WARN_ON_ONCE(!pfn_valid(pfn)); + zone = page_zone(pfn_to_page(pfn)); + do { unsigned j; base_pfn = pfn; - if (!pfn_valid(base_pfn)) - goto err; - - zone = page_zone(pfn_to_page(base_pfn)); for (j = pageblock_nr_pages; j; --j, pfn++) { - if (!pfn_valid(pfn)) - goto err; - + WARN_ON_ONCE(!pfn_valid(pfn)); /* -* In init_cma_reserved_pageblock(), present_pages -* is adjusted with assumption that all pages in -* the pageblock come from a single zone. +* alloc_contig_range requires the pfn range +* specified to be in the same zone. Make this +* simple by forcing the entire CMA resv range +* to be in the same zone. */ if (page_zone(pfn_to_page(pfn)) != zone) - goto err; + goto not_in_zone; } init_cma_reserved_pageblock(pfn_to_page(base_pfn)); } while (--i); @@ -142,7 +139,7 @@ static int __init cma_activate_area(struct cma *cma) return 0; -err: +not_in_zone: pr_err("CMA area %s could not be activated\n", cma->name); kfree(cma->bitmap); cma->count = 0; @@ -152,41 +149,6 @@ static int __init cma_activate_area(struct cma *cma) static int __init cma_init_reserved_areas(void) { int i; - struct zone *zone; - pg_data_t *pgdat; - - if (!cma_area_count) - return 0; - - for_each_online_pgdat(pgdat) { - unsigned long start_pfn = UINT_MAX, end_pfn = 0; - - zone = >node_zones[ZONE_MOVABLE]; - - /* -* In this case, we cannot adjust the zone range -* since it is now maximum node span and we don't -* know original zone range. -*/ - if (populated_zone(zone)) - continue; - - for (i = 0; i < cma_area_count; i++) { - if (pfn_to_nid(cma_areas[i].base_pfn) != - pgdat->node_id) - continue; - - start_pfn = min(start_pfn, cma_areas[i].base_pfn); - end_pfn = max(end_pfn, cma_areas[i].base_pfn + - cma_areas[i].count); - } - - if (!end_pfn) - continue; - - zone->zone_start_pfn = start_pfn; -
[PATCH bluez] hid2hci: Fix udev rules for linux-4.14+
From: Ville SyrjäläSince commit 1455cf8dbfd0 ("driver core: emit uevents when device is bound to a driver") the kernel started emitting "bound" and "unbound" uevents which confuse the hid2hci udev rules. The symptoms on an affected machine (Dell E5400 in my case) include bluetooth devices not appearing and udev hogging the cpu as it's busy processing a constant stream of these "bound"+"unbound" uevents. Change the udev rules only kick in for an "add" event. This seems to cure my machine at least. Cc: Dmitry Torokhov Cc: Greg Kroah-Hartman Cc: Marcel Holtmann Cc: Kay Sievers Cc: systemd-de...@lists.freedesktop.org Cc: linux-kernel@vger.kernel.org Cc: linux-blueto...@vger.kernel.org Signed-off-by: Ville Syrjälä --- tools/hid2hci.rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/hid2hci.rules b/tools/hid2hci.rules index db6bb03d2ef3..daa381d77387 100644 --- a/tools/hid2hci.rules +++ b/tools/hid2hci.rules @@ -1,6 +1,6 @@ # do not edit this file, it will be overwritten on update -ACTION=="remove", GOTO="hid2hci_end" +ACTION!="add", GOTO="hid2hci_end" SUBSYSTEM!="usb*", GOTO="hid2hci_end" # Variety of Dell Bluetooth devices - match on a mouse device that is -- 2.16.1
[PATCH bluez] hid2hci: Fix udev rules for linux-4.14+
From: Ville Syrjälä Since commit 1455cf8dbfd0 ("driver core: emit uevents when device is bound to a driver") the kernel started emitting "bound" and "unbound" uevents which confuse the hid2hci udev rules. The symptoms on an affected machine (Dell E5400 in my case) include bluetooth devices not appearing and udev hogging the cpu as it's busy processing a constant stream of these "bound"+"unbound" uevents. Change the udev rules only kick in for an "add" event. This seems to cure my machine at least. Cc: Dmitry Torokhov Cc: Greg Kroah-Hartman Cc: Marcel Holtmann Cc: Kay Sievers Cc: systemd-de...@lists.freedesktop.org Cc: linux-kernel@vger.kernel.org Cc: linux-blueto...@vger.kernel.org Signed-off-by: Ville Syrjälä --- tools/hid2hci.rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/hid2hci.rules b/tools/hid2hci.rules index db6bb03d2ef3..daa381d77387 100644 --- a/tools/hid2hci.rules +++ b/tools/hid2hci.rules @@ -1,6 +1,6 @@ # do not edit this file, it will be overwritten on update -ACTION=="remove", GOTO="hid2hci_end" +ACTION!="add", GOTO="hid2hci_end" SUBSYSTEM!="usb*", GOTO="hid2hci_end" # Variety of Dell Bluetooth devices - match on a mouse device that is -- 2.16.1
[PATCH] Revert "cpuidle: Make drivers initialize polling state"
From: Ville SyrjäläThis reverts commit 1b39e3f813b4685c7a30ae964d5529a1b0e3a286. Makes my P3 machine oops somewhere in cpuidle. I suspect CONFIG_ACPI=n may have something to do with this. Cc: Rafael J. Wysocki Cc: Sudeep Holla Cc: Daniel Lezcano Signed-off-by: Ville Syrjälä --- drivers/acpi/processor_idle.c | 9 + drivers/cpuidle/driver.c | 2 ++ drivers/cpuidle/poll_state.c | 3 +-- drivers/idle/intel_idle.c | 1 - include/linux/cpuidle.h | 4 ++-- 5 files changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d50a7b6ccddd..cb1c7634e2ca 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -842,7 +842,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, static int acpi_processor_setup_cstates(struct acpi_processor *pr) { - int i, count; + int i, count = ACPI_IDLE_STATE_START; struct acpi_processor_cx *cx; struct cpuidle_state *state; struct cpuidle_driver *drv = _idle_driver; @@ -850,13 +850,6 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr) if (max_cstate == 0) max_cstate = 1; - if (IS_ENABLED(CONFIG_ARCH_HAS_CPU_RELAX)) { - cpuidle_poll_state_init(drv); - count = 1; - } else { - count = 0; - } - for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { cx = >power.states[i]; diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index dc32f34e68d9..6f694c86f3fa 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -216,6 +216,8 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv) on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer, (void *)1, 1); + poll_idle_init(drv); + return 0; } diff --git a/drivers/cpuidle/poll_state.c b/drivers/cpuidle/poll_state.c index 7416b16287de..0db4f7273952 100644 --- a/drivers/cpuidle/poll_state.c +++ b/drivers/cpuidle/poll_state.c @@ -21,7 +21,7 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev, return index; } -void cpuidle_poll_state_init(struct cpuidle_driver *drv) +void poll_idle_init(struct cpuidle_driver *drv) { struct cpuidle_state *state = >states[0]; @@ -34,4 +34,3 @@ void cpuidle_poll_state_init(struct cpuidle_driver *drv) state->disabled = false; state->flags = CPUIDLE_FLAG_POLLING; } -EXPORT_SYMBOL_GPL(cpuidle_poll_state_init); diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index b2ccce5fb071..6d8a4b87e4d5 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -1342,7 +1342,6 @@ static void __init intel_idle_cpuidle_driver_init(void) intel_idle_state_table_update(); - cpuidle_poll_state_init(drv); drv->state_count = 1; for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 8f7788d23b57..bc9f2603fe10 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -226,9 +226,9 @@ static inline void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, #endif #ifdef CONFIG_ARCH_HAS_CPU_RELAX -void cpuidle_poll_state_init(struct cpuidle_driver *drv); +void poll_idle_init(struct cpuidle_driver *drv); #else -static inline void cpuidle_poll_state_init(struct cpuidle_driver *drv) {} +static void poll_idle_init(struct cpuidle_driver *drv) {} #endif /** -- 2.13.6
[PATCH] Revert "cpuidle: Make drivers initialize polling state"
From: Ville Syrjälä This reverts commit 1b39e3f813b4685c7a30ae964d5529a1b0e3a286. Makes my P3 machine oops somewhere in cpuidle. I suspect CONFIG_ACPI=n may have something to do with this. Cc: Rafael J. Wysocki Cc: Sudeep Holla Cc: Daniel Lezcano Signed-off-by: Ville Syrjälä --- drivers/acpi/processor_idle.c | 9 + drivers/cpuidle/driver.c | 2 ++ drivers/cpuidle/poll_state.c | 3 +-- drivers/idle/intel_idle.c | 1 - include/linux/cpuidle.h | 4 ++-- 5 files changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d50a7b6ccddd..cb1c7634e2ca 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -842,7 +842,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, static int acpi_processor_setup_cstates(struct acpi_processor *pr) { - int i, count; + int i, count = ACPI_IDLE_STATE_START; struct acpi_processor_cx *cx; struct cpuidle_state *state; struct cpuidle_driver *drv = _idle_driver; @@ -850,13 +850,6 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr) if (max_cstate == 0) max_cstate = 1; - if (IS_ENABLED(CONFIG_ARCH_HAS_CPU_RELAX)) { - cpuidle_poll_state_init(drv); - count = 1; - } else { - count = 0; - } - for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { cx = >power.states[i]; diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index dc32f34e68d9..6f694c86f3fa 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -216,6 +216,8 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv) on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer, (void *)1, 1); + poll_idle_init(drv); + return 0; } diff --git a/drivers/cpuidle/poll_state.c b/drivers/cpuidle/poll_state.c index 7416b16287de..0db4f7273952 100644 --- a/drivers/cpuidle/poll_state.c +++ b/drivers/cpuidle/poll_state.c @@ -21,7 +21,7 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev, return index; } -void cpuidle_poll_state_init(struct cpuidle_driver *drv) +void poll_idle_init(struct cpuidle_driver *drv) { struct cpuidle_state *state = >states[0]; @@ -34,4 +34,3 @@ void cpuidle_poll_state_init(struct cpuidle_driver *drv) state->disabled = false; state->flags = CPUIDLE_FLAG_POLLING; } -EXPORT_SYMBOL_GPL(cpuidle_poll_state_init); diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index b2ccce5fb071..6d8a4b87e4d5 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -1342,7 +1342,6 @@ static void __init intel_idle_cpuidle_driver_init(void) intel_idle_state_table_update(); - cpuidle_poll_state_init(drv); drv->state_count = 1; for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 8f7788d23b57..bc9f2603fe10 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -226,9 +226,9 @@ static inline void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, #endif #ifdef CONFIG_ARCH_HAS_CPU_RELAX -void cpuidle_poll_state_init(struct cpuidle_driver *drv); +void poll_idle_init(struct cpuidle_driver *drv); #else -static inline void cpuidle_poll_state_init(struct cpuidle_driver *drv) {} +static void poll_idle_init(struct cpuidle_driver *drv) {} #endif /** -- 2.13.6
[PATCH] Revert "x86/apic: Remove init_bsp_APIC()"
From: Ville SyrjäläThis reverts commit b371ae0d4a194b178817b0edfb6a7395c7aec37a. Causes my P3 UP machine to hang at boot with "lapic". Cc: Dou Liyang Cc: Thomas Gleixner Cc: ying...@kernel.org Cc: b...@redhat.com Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Ville Syrjälä --- arch/x86/include/asm/apic.h | 1 + arch/x86/kernel/apic/apic.c | 49 + arch/x86/kernel/irqinit.c | 3 +++ 3 files changed, 53 insertions(+) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index a9e57f08bfa6..98722773391d 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -136,6 +136,7 @@ extern void disconnect_bsp_APIC(int virt_wire_setup); extern void disable_local_APIC(void); extern void lapic_shutdown(void); extern void sync_Arb_IDs(void); +extern void init_bsp_APIC(void); extern void apic_intr_mode_init(void); extern void setup_local_APIC(void); extern void init_apic_mappings(void); diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 6e272f3ea984..cec9aaea7f9d 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1286,6 +1286,55 @@ static int __init apic_intr_mode_select(void) return APIC_SYMMETRIC_IO; } +/* + * An initial setup of the virtual wire mode. + */ +void __init init_bsp_APIC(void) +{ + unsigned int value; + + /* +* Don't do the setup now if we have a SMP BIOS as the +* through-I/O-APIC virtual wire mode might be active. +*/ + if (smp_found_config || !boot_cpu_has(X86_FEATURE_APIC)) + return; + + /* +* Do not trust the local APIC being empty at bootup. +*/ + clear_local_APIC(); + + /* +* Enable APIC. +*/ + value = apic_read(APIC_SPIV); + value &= ~APIC_VECTOR_MASK; + value |= APIC_SPIV_APIC_ENABLED; + +#ifdef CONFIG_X86_32 + /* This bit is reserved on P4/Xeon and should be cleared */ + if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && + (boot_cpu_data.x86 == 15)) + value &= ~APIC_SPIV_FOCUS_DISABLED; + else +#endif + value |= APIC_SPIV_FOCUS_DISABLED; + value |= SPURIOUS_APIC_VECTOR; + apic_write(APIC_SPIV, value); + + /* +* Set up the virtual wire mode. +*/ + apic_write(APIC_LVT0, APIC_DM_EXTINT); + value = APIC_DM_NMI; + if (!lapic_is_integrated()) /* 82489DX */ + value |= APIC_LVT_LEVEL_TRIGGER; + if (apic_extnmi == APIC_EXTNMI_NONE) + value |= APIC_LVT_MASKED; + apic_write(APIC_LVT1, value); +} + /* Init the interrupt delivery mode for the BSP */ void __init apic_intr_mode_init(void) { diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 8da3e909e967..a539410c4ea9 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c @@ -61,6 +61,9 @@ void __init init_ISA_irqs(void) struct irq_chip *chip = legacy_pic->chip; int i; +#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC) + init_bsp_APIC(); +#endif legacy_pic->init(0); for (i = 0; i < nr_legacy_irqs(); i++) -- 2.13.6
[PATCH] Revert "x86/apic: Remove init_bsp_APIC()"
From: Ville Syrjälä This reverts commit b371ae0d4a194b178817b0edfb6a7395c7aec37a. Causes my P3 UP machine to hang at boot with "lapic". Cc: Dou Liyang Cc: Thomas Gleixner Cc: ying...@kernel.org Cc: b...@redhat.com Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Ville Syrjälä --- arch/x86/include/asm/apic.h | 1 + arch/x86/kernel/apic/apic.c | 49 + arch/x86/kernel/irqinit.c | 3 +++ 3 files changed, 53 insertions(+) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index a9e57f08bfa6..98722773391d 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -136,6 +136,7 @@ extern void disconnect_bsp_APIC(int virt_wire_setup); extern void disable_local_APIC(void); extern void lapic_shutdown(void); extern void sync_Arb_IDs(void); +extern void init_bsp_APIC(void); extern void apic_intr_mode_init(void); extern void setup_local_APIC(void); extern void init_apic_mappings(void); diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 6e272f3ea984..cec9aaea7f9d 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1286,6 +1286,55 @@ static int __init apic_intr_mode_select(void) return APIC_SYMMETRIC_IO; } +/* + * An initial setup of the virtual wire mode. + */ +void __init init_bsp_APIC(void) +{ + unsigned int value; + + /* +* Don't do the setup now if we have a SMP BIOS as the +* through-I/O-APIC virtual wire mode might be active. +*/ + if (smp_found_config || !boot_cpu_has(X86_FEATURE_APIC)) + return; + + /* +* Do not trust the local APIC being empty at bootup. +*/ + clear_local_APIC(); + + /* +* Enable APIC. +*/ + value = apic_read(APIC_SPIV); + value &= ~APIC_VECTOR_MASK; + value |= APIC_SPIV_APIC_ENABLED; + +#ifdef CONFIG_X86_32 + /* This bit is reserved on P4/Xeon and should be cleared */ + if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && + (boot_cpu_data.x86 == 15)) + value &= ~APIC_SPIV_FOCUS_DISABLED; + else +#endif + value |= APIC_SPIV_FOCUS_DISABLED; + value |= SPURIOUS_APIC_VECTOR; + apic_write(APIC_SPIV, value); + + /* +* Set up the virtual wire mode. +*/ + apic_write(APIC_LVT0, APIC_DM_EXTINT); + value = APIC_DM_NMI; + if (!lapic_is_integrated()) /* 82489DX */ + value |= APIC_LVT_LEVEL_TRIGGER; + if (apic_extnmi == APIC_EXTNMI_NONE) + value |= APIC_LVT_MASKED; + apic_write(APIC_LVT1, value); +} + /* Init the interrupt delivery mode for the BSP */ void __init apic_intr_mode_init(void) { diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 8da3e909e967..a539410c4ea9 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c @@ -61,6 +61,9 @@ void __init init_ISA_irqs(void) struct irq_chip *chip = legacy_pic->chip; int i; +#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC) + init_bsp_APIC(); +#endif legacy_pic->init(0); for (i = 0; i < nr_legacy_irqs(); i++) -- 2.13.6
[PATCH] x86: Don't cast away the __user in __get_user_asm_u64()
From: Ville SyrjäläDon't cast away the __user in __get_user_asm_u64() on x86-32. Avoids sparse getting upset. Cc: Benjamin LaHaise Cc: Linus Torvalds Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Ville Syrjälä --- arch/x86/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 30269dafec47..1a7d930c33d9 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -332,7 +332,7 @@ do { \ _ASM_EXTABLE(1b, 4b) \ _ASM_EXTABLE(2b, 4b) \ : "=r" (retval), "="(x) \ -: "m" (__m(__ptr)), "m" __m(((u32 *)(__ptr)) + 1), \ +: "m" (__m(__ptr)), "m" __m(((u32 __user *)(__ptr)) + 1), \ "i" (errret), "0" (retval)); \ }) -- 2.13.5
[PATCH] x86: Don't cast away the __user in __get_user_asm_u64()
From: Ville Syrjälä Don't cast away the __user in __get_user_asm_u64() on x86-32. Avoids sparse getting upset. Cc: Benjamin LaHaise Cc: Linus Torvalds Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Ville Syrjälä --- arch/x86/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 30269dafec47..1a7d930c33d9 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -332,7 +332,7 @@ do { \ _ASM_EXTABLE(1b, 4b) \ _ASM_EXTABLE(2b, 4b) \ : "=r" (retval), "="(x) \ -: "m" (__m(__ptr)), "m" __m(((u32 *)(__ptr)) + 1), \ +: "m" (__m(__ptr)), "m" __m(((u32 __user *)(__ptr)) + 1), \ "i" (errret), "0" (retval)); \ }) -- 2.13.5
[PATCH] drm/i915: Make vblank evade warnings optional
From: Ville SyrjäläAdd a new Kconfig option to enable/disable the extra warnings from the vblank evade code. For now we'll keep the warning about an actually missed vblank always enabled as that can have an actual user visible impact. But if we miss the deadline othrwise there's no real need to bother the user with that. We'll want these warnings enabled during development however so that we can catch regressions. Based on the reports it looks like this is still very easy to hit on SKL, so we have more work ahead of us to optimize the crtiical section further. Cc: Daniel Vetter Cc: Jani Nikula Cc: Dave Airlie Cc: Jens Axboe Cc: Linus Torvalds Cc: Maarten Lankhorst Reported-by: Jens Axboe Reported-by: Linus Torvalds Fixes: e1edbd44e23b ("drm/i915: Complain if we take too long under vblank evasion.") Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/Kconfig.debug | 13 + drivers/gpu/drm/i915/intel_sprite.c | 7 +-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index e091809a9a9e..49db32fa6524 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -87,3 +87,16 @@ config DRM_I915_LOW_LEVEL_TRACEPOINTS and also analyze the request dependency resolving timeline. If in doubt, say "N". + +config DRM_I915_DEBUG_VBLANK_EVADE + bool "Enable extra debug warnings for vblank evasion" + depends on DRM_I915 + default n + help + Choose this option to turn on extra debug warnings for the + vblank evade mechanism. This gives a warning every time the + the deadline allotted for the vblank evade critical section + is exceeded, even if there isn't an actual risk of missing + the vblank. + + If in doubt, say "N". diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index f7d431427115..8c87c717c7cd 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -198,12 +198,15 @@ void intel_pipe_update_end(struct intel_crtc *crtc, struct intel_flip_work *work ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), crtc->debug.min_vbl, crtc->debug.max_vbl, crtc->debug.scanline_start, scanline_end); - } else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) > - VBLANK_EVASION_TIME_US) + } +#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE + else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) > +VBLANK_EVASION_TIME_US) DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n", pipe_name(pipe), ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), VBLANK_EVASION_TIME_US); +#endif } static void -- 2.10.2
[PATCH] drm/i915: Make vblank evade warnings optional
From: Ville Syrjälä Add a new Kconfig option to enable/disable the extra warnings from the vblank evade code. For now we'll keep the warning about an actually missed vblank always enabled as that can have an actual user visible impact. But if we miss the deadline othrwise there's no real need to bother the user with that. We'll want these warnings enabled during development however so that we can catch regressions. Based on the reports it looks like this is still very easy to hit on SKL, so we have more work ahead of us to optimize the crtiical section further. Cc: Daniel Vetter Cc: Jani Nikula Cc: Dave Airlie Cc: Jens Axboe Cc: Linus Torvalds Cc: Maarten Lankhorst Reported-by: Jens Axboe Reported-by: Linus Torvalds Fixes: e1edbd44e23b ("drm/i915: Complain if we take too long under vblank evasion.") Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/Kconfig.debug | 13 + drivers/gpu/drm/i915/intel_sprite.c | 7 +-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index e091809a9a9e..49db32fa6524 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -87,3 +87,16 @@ config DRM_I915_LOW_LEVEL_TRACEPOINTS and also analyze the request dependency resolving timeline. If in doubt, say "N". + +config DRM_I915_DEBUG_VBLANK_EVADE + bool "Enable extra debug warnings for vblank evasion" + depends on DRM_I915 + default n + help + Choose this option to turn on extra debug warnings for the + vblank evade mechanism. This gives a warning every time the + the deadline allotted for the vblank evade critical section + is exceeded, even if there isn't an actual risk of missing + the vblank. + + If in doubt, say "N". diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index f7d431427115..8c87c717c7cd 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -198,12 +198,15 @@ void intel_pipe_update_end(struct intel_crtc *crtc, struct intel_flip_work *work ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), crtc->debug.min_vbl, crtc->debug.max_vbl, crtc->debug.scanline_start, scanline_end); - } else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) > - VBLANK_EVASION_TIME_US) + } +#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE + else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) > +VBLANK_EVASION_TIME_US) DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n", pipe_name(pipe), ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), VBLANK_EVASION_TIME_US); +#endif } static void -- 2.10.2
[PATCH] Revert "cpuidle: Replace ktime_get() with local_clock()"
From: Ville SyrjäläThis reverts commit e93e59ce5b85e6c2b444f09fd1f707274ec066dc. The TSC stops in deeper C states, so using local_clock() in cpuidle to track the C state residency seems like a bad idea. With local_clock() powertop is reporting mostly 0% residency for C states here. Presumably the core is still spending most of its time in some deep C-state since the totals typically add up to only 5% or so, so perhaps the governor isn't getting totally confused by these bogus numbers. But let's go back to using ktime_get() as that at least works correctly across the board. Note that the code has changed somewhat since the regression happened, so this isn't a 1:1 revert of the offending commit. Cc: sta...@vger.kernel.org Cc: Daniel Lezcano Cc: Peter Zijlstra (Intel) Cc: Rafael J. Wysocki Signed-off-by: Ville Syrjälä --- drivers/cpuidle/cpuidle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 548b90be7685..24a52805527f 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -213,13 +213,13 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, sched_idle_set_state(target_state); trace_cpu_idle_rcuidle(index, dev->cpu); - time_start = ns_to_ktime(local_clock()); + time_start = ktime_get(); stop_critical_timings(); entered_state = target_state->enter(dev, drv, index); start_critical_timings(); - time_end = ns_to_ktime(local_clock()); + time_end = ktime_get(); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); /* The cpu is no longer idle or about to enter idle. */ -- 2.10.2
[PATCH] Revert "cpuidle: Replace ktime_get() with local_clock()"
From: Ville Syrjälä This reverts commit e93e59ce5b85e6c2b444f09fd1f707274ec066dc. The TSC stops in deeper C states, so using local_clock() in cpuidle to track the C state residency seems like a bad idea. With local_clock() powertop is reporting mostly 0% residency for C states here. Presumably the core is still spending most of its time in some deep C-state since the totals typically add up to only 5% or so, so perhaps the governor isn't getting totally confused by these bogus numbers. But let's go back to using ktime_get() as that at least works correctly across the board. Note that the code has changed somewhat since the regression happened, so this isn't a 1:1 revert of the offending commit. Cc: sta...@vger.kernel.org Cc: Daniel Lezcano Cc: Peter Zijlstra (Intel) Cc: Rafael J. Wysocki Signed-off-by: Ville Syrjälä --- drivers/cpuidle/cpuidle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 548b90be7685..24a52805527f 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -213,13 +213,13 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, sched_idle_set_state(target_state); trace_cpu_idle_rcuidle(index, dev->cpu); - time_start = ns_to_ktime(local_clock()); + time_start = ktime_get(); stop_critical_timings(); entered_state = target_state->enter(dev, drv, index); start_critical_timings(); - time_end = ns_to_ktime(local_clock()); + time_end = ktime_get(); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); /* The cpu is no longer idle or about to enter idle. */ -- 2.10.2
[PATCH] intel_idle: Don't use on Lenovo Ideapad S10-3t
From: Ville SyrjäläLenovo Ideapad S10-3t hangs coming out of S3 with intel_idle. The two workaround that seem to help are "intel_idle.max_cstate=0" or "nohz=off highres=off". At a first glance quirk_tigerpoint_bm_sts() seemed promising, but even when moved to early_resume it didn't do anything. I have no idea what's wrong here, so let's just disable intel_idle for these machines using a DMI match. I sent this patch originally about one year ago, at which time I was asked to file a bug, which I did [1], which was mostly a waste of time since no one actually did anything to fix the problem. In the meantime even acpi-idle got broken and then fixed again [2], so at least there's still a working alternative. As intel_idle has never worked on this machine, and it looks like no one has any real intention to fix it, I'm going to suggest *again* that we simply disable intel_idle on this machine and get on with life. [1] https://bugzilla.kernel.org/show_bug.cgi?id=107151 [2] https://lkml.org/lkml/2016/5/11/238 Cc: feng.t...@intel.com Cc: Steven Rostedt Cc: Sebastian Andrzej Siewior Cc: Thomas Gleixner Cc: Rik van Riel Cc: "Srivatsa S. Bhat" Cc: Peter Zijlstra Cc: Arjan van de Ven Cc: Rusty Russell Cc: Oleg Nesterov Cc: Tejun Heo Cc: Andrew Morton Cc: Paul McKenney Cc: Linus Torvalds Cc: Paul Turner Cc: "Zhang, Rui" Cc: Len Brown Cc: Rafael J. Wysocki Cc: linux...@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-a...@vger.kernel.org Signed-off-by: Ville Syrjälä --- drivers/idle/intel_idle.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 4466a2f969d7..db81b27f6250 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -1089,6 +1090,25 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { {} }; +static int intel_idle_disable_callback(const struct dmi_system_id *id) +{ + pr_debug(PREFIX "problematic system (%s), disabling\n", id->ident); + return 1; +} + +static const struct dmi_system_id intel_idle_disable_dmi[] = { + { + /* Lenovo Ideapad S10-3t, hangs coming out of S3 */ + .callback = intel_idle_disable_callback, + .ident = "Lenovo Ideapad S10-3t", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Ideapad S10-3t"), + }, + }, + {} +}; + /* * intel_idle_probe() */ @@ -1121,6 +1141,9 @@ static int __init intel_idle_probe(void) !mwait_substates) return -ENODEV; + if (dmi_check_system(intel_idle_disable_dmi)) + return -ENODEV; + pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates); icpu = (const struct idle_cpu *)id->driver_data; -- 2.7.4
[PATCH] intel_idle: Don't use on Lenovo Ideapad S10-3t
From: Ville Syrjälä Lenovo Ideapad S10-3t hangs coming out of S3 with intel_idle. The two workaround that seem to help are "intel_idle.max_cstate=0" or "nohz=off highres=off". At a first glance quirk_tigerpoint_bm_sts() seemed promising, but even when moved to early_resume it didn't do anything. I have no idea what's wrong here, so let's just disable intel_idle for these machines using a DMI match. I sent this patch originally about one year ago, at which time I was asked to file a bug, which I did [1], which was mostly a waste of time since no one actually did anything to fix the problem. In the meantime even acpi-idle got broken and then fixed again [2], so at least there's still a working alternative. As intel_idle has never worked on this machine, and it looks like no one has any real intention to fix it, I'm going to suggest *again* that we simply disable intel_idle on this machine and get on with life. [1] https://bugzilla.kernel.org/show_bug.cgi?id=107151 [2] https://lkml.org/lkml/2016/5/11/238 Cc: feng.t...@intel.com Cc: Steven Rostedt Cc: Sebastian Andrzej Siewior Cc: Thomas Gleixner Cc: Rik van Riel Cc: "Srivatsa S. Bhat" Cc: Peter Zijlstra Cc: Arjan van de Ven Cc: Rusty Russell Cc: Oleg Nesterov Cc: Tejun Heo Cc: Andrew Morton Cc: Paul McKenney Cc: Linus Torvalds Cc: Paul Turner Cc: "Zhang, Rui" Cc: Len Brown Cc: Rafael J. Wysocki Cc: linux...@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-a...@vger.kernel.org Signed-off-by: Ville Syrjälä --- drivers/idle/intel_idle.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 4466a2f969d7..db81b27f6250 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -1089,6 +1090,25 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { {} }; +static int intel_idle_disable_callback(const struct dmi_system_id *id) +{ + pr_debug(PREFIX "problematic system (%s), disabling\n", id->ident); + return 1; +} + +static const struct dmi_system_id intel_idle_disable_dmi[] = { + { + /* Lenovo Ideapad S10-3t, hangs coming out of S3 */ + .callback = intel_idle_disable_callback, + .ident = "Lenovo Ideapad S10-3t", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Ideapad S10-3t"), + }, + }, + {} +}; + /* * intel_idle_probe() */ @@ -1121,6 +1141,9 @@ static int __init intel_idle_probe(void) !mwait_substates) return -ENODEV; + if (dmi_check_system(intel_idle_disable_dmi)) + return -ENODEV; + pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates); icpu = (const struct idle_cpu *)id->driver_data; -- 2.7.4
[PATCH] arch/x86: Don't try to poke disabled/non-existent APIC
From: Ville SyrjäläApparently trying to poke a disabled or non-existent APIC leads to a box that doesn't even boot. Let's not do that. No real clue if this is the right fix, but at least my P3 machine boots again. Cc: sta...@vger.kernel.org Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: Prarit Bhargava Cc: Peter Zijlstra Cc: Len Brown Cc: Borislav Petkov Cc: Andi Kleen Cc: Jiri Olsa Cc: Juergen Gross Cc: dyo...@redhat.com Cc: Eric Biederman Cc: ke...@lists.infradead.org Cc: Thomas Gleixner Fixes: 2a51fe083eba ("arch/x86: Handle non enumerated CPU after physical hotplug") Signed-off-by: Ville Syrjälä --- arch/x86/kernel/smpboot.c | 16 +--- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 951f093a96fe..42f5eb7b4f6c 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1409,15 +1409,17 @@ __init void prefill_possible_map(void) /* No boot processor was found in mptable or ACPI MADT */ if (!num_processors) { - int apicid = boot_cpu_physical_apicid; - int cpu = hard_smp_processor_id(); + if (boot_cpu_has(X86_FEATURE_APIC)) { + int apicid = boot_cpu_physical_apicid; + int cpu = hard_smp_processor_id(); - pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu); + pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu); - /* Make sure boot cpu is enumerated */ - if (apic->cpu_present_to_apicid(0) == BAD_APICID && - apic->apic_id_valid(apicid)) - generic_processor_info(apicid, boot_cpu_apic_version); + /* Make sure boot cpu is enumerated */ + if (apic->cpu_present_to_apicid(0) == BAD_APICID && + apic->apic_id_valid(apicid)) + generic_processor_info(apicid, boot_cpu_apic_version); + } if (!num_processors) num_processors = 1; -- 2.7.4
[PATCH] arch/x86: Don't try to poke disabled/non-existent APIC
From: Ville Syrjälä Apparently trying to poke a disabled or non-existent APIC leads to a box that doesn't even boot. Let's not do that. No real clue if this is the right fix, but at least my P3 machine boots again. Cc: sta...@vger.kernel.org Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: Prarit Bhargava Cc: Peter Zijlstra Cc: Len Brown Cc: Borislav Petkov Cc: Andi Kleen Cc: Jiri Olsa Cc: Juergen Gross Cc: dyo...@redhat.com Cc: Eric Biederman Cc: ke...@lists.infradead.org Cc: Thomas Gleixner Fixes: 2a51fe083eba ("arch/x86: Handle non enumerated CPU after physical hotplug") Signed-off-by: Ville Syrjälä --- arch/x86/kernel/smpboot.c | 16 +--- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 951f093a96fe..42f5eb7b4f6c 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1409,15 +1409,17 @@ __init void prefill_possible_map(void) /* No boot processor was found in mptable or ACPI MADT */ if (!num_processors) { - int apicid = boot_cpu_physical_apicid; - int cpu = hard_smp_processor_id(); + if (boot_cpu_has(X86_FEATURE_APIC)) { + int apicid = boot_cpu_physical_apicid; + int cpu = hard_smp_processor_id(); - pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu); + pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu); - /* Make sure boot cpu is enumerated */ - if (apic->cpu_present_to_apicid(0) == BAD_APICID && - apic->apic_id_valid(apicid)) - generic_processor_info(apicid, boot_cpu_apic_version); + /* Make sure boot cpu is enumerated */ + if (apic->cpu_present_to_apicid(0) == BAD_APICID && + apic->apic_id_valid(apicid)) + generic_processor_info(apicid, boot_cpu_apic_version); + } if (!num_processors) num_processors = 1; -- 2.7.4
[PATCH] rtc: cmos: Don't enable interrupts in the middle of the interrupt handler
From: Ville SyrjäläUsing spin_lock_irq()/spin_unlock_irq() from within the interrupt handler is a no-no. Let's save/restore the flags to avoid turning on interrupts prematurely. We hit this in a bunch of our CI systems, but for whatever reason I wasn't able to reproduce on my own machine, so this fix is just based on the backtrace. [ 202.634918] WARNING: CPU: 0 PID: 0 at kernel/locking/lockdep.c:2729 trace_hardirqs_on_caller+0x113/0x1b0 [ 202.634919] DEBUG_LOCKS_WARN_ON(current->hardirq_context) [ 202.634929] Modules linked in: snd_hda_intel i915 x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel lpc_ich snd_hda_codec_realtek snd_hda_codec_generic snd_hda_codec_hdmi snd_hda_codec snd_hwdep i2c_designware_platform i2c_designware_core snd_hda_core mei_me mei snd_pcm r8169 mii sdhci_acpi sdhci mmc_core i2c_hid [last unloaded: i915] [ 202.634930] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G U 4.9.0-rc1-CI-CI_DRM_1734+ #1 [ 202.634931] Hardware name: GIGABYTE M4HM87P-00/M4HM87P-00, BIOS F6 12/10/2014 [ 202.634933] 88011ea03d68 8142dce5 88011ea03db8 [ 202.634934] 88011ea03da8 8107e496 0aa90002 81e249a0 [ 202.634935] 81815637 82e7c280 0004 [ 202.634936] Call Trace: [ 202.634939] [ 202.634939] [] dump_stack+0x67/0x92 [ 202.634941] [] __warn+0xc6/0xe0 [ 202.634944] [] ? _raw_spin_unlock_irq+0x27/0x50 [ 202.634945] [] warn_slowpath_fmt+0x4a/0x50 [ 202.634946] [] trace_hardirqs_on_caller+0x113/0x1b0 [ 202.634948] [] trace_hardirqs_on+0xd/0x10 [ 202.634949] [] _raw_spin_unlock_irq+0x27/0x50 [ 202.634951] [] rtc_handler+0x32/0xa0 [ 202.634954] [] acpi_ev_fixed_event_detect+0xd4/0xfb [ 202.634956] [] acpi_ev_sci_xrupt_handler+0xf/0x2d [ 202.634957] [] acpi_irq+0x11/0x2c [ 202.634960] [] __handle_irq_event_percpu+0x58/0x370 [ 202.634961] [] handle_irq_event_percpu+0x1e/0x50 [ 202.634962] [] handle_irq_event+0x34/0x60 [ 202.634963] [] handle_fasteoi_irq+0xa6/0x170 [ 202.634966] [] handle_irq+0x15/0x20 [ 202.634967] [] do_IRQ+0x68/0x130 [ 202.634968] [] common_interrupt+0x89/0x89 [ 202.634970] [ 202.634970] [] ? mwait_idle+0x93/0x210 [ 202.634971] [] ? mwait_idle+0x8a/0x210 [ 202.634972] [] arch_cpu_idle+0xa/0x10 [ 202.634973] [] default_idle_call+0x1e/0x30 [ 202.634974] [] cpu_startup_entry+0x17c/0x1f0 [ 202.634976] [] rest_init+0x127/0x130 [ 202.634978] [] start_kernel+0x3f6/0x403 [ 202.634980] [] x86_64_start_reservations+0x2a/0x2c [ 202.634981] [] x86_64_start_kernel+0x173/0x186 [ 202.634982] ---[ end trace 293c99618fa08d34 ]--- Cc: Gabriele Mazzotta Cc: Alexandre Belloni Fixes: 983bf1256edb ("rtc: cmos: Clear ACPI-driven alarms upon resume") Signed-off-by: Ville Syrjälä --- drivers/rtc/rtc-cmos.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index dd3d59806ffa..19cd49ad92dc 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -996,8 +996,9 @@ static u32 rtc_handler(void *context) struct cmos_rtc *cmos = dev_get_drvdata(dev); unsigned char rtc_control = 0; unsigned char rtc_intr; + unsigned long flags; - spin_lock_irq(_lock); + spin_lock_irqsave(_lock, flags); if (cmos_rtc.suspend_ctrl) rtc_control = CMOS_READ(RTC_CONTROL); if (rtc_control & RTC_AIE) { @@ -1006,7 +1007,7 @@ static u32 rtc_handler(void *context) rtc_intr = CMOS_READ(RTC_INTR_FLAGS); rtc_update_irq(cmos->rtc, 1, rtc_intr); } - spin_unlock_irq(_lock); + spin_unlock_irqrestore(_lock, flags); pm_wakeup_event(dev, 0); acpi_clear_event(ACPI_EVENT_RTC); -- 2.7.4
[PATCH] rtc: cmos: Don't enable interrupts in the middle of the interrupt handler
From: Ville Syrjälä Using spin_lock_irq()/spin_unlock_irq() from within the interrupt handler is a no-no. Let's save/restore the flags to avoid turning on interrupts prematurely. We hit this in a bunch of our CI systems, but for whatever reason I wasn't able to reproduce on my own machine, so this fix is just based on the backtrace. [ 202.634918] WARNING: CPU: 0 PID: 0 at kernel/locking/lockdep.c:2729 trace_hardirqs_on_caller+0x113/0x1b0 [ 202.634919] DEBUG_LOCKS_WARN_ON(current->hardirq_context) [ 202.634929] Modules linked in: snd_hda_intel i915 x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel lpc_ich snd_hda_codec_realtek snd_hda_codec_generic snd_hda_codec_hdmi snd_hda_codec snd_hwdep i2c_designware_platform i2c_designware_core snd_hda_core mei_me mei snd_pcm r8169 mii sdhci_acpi sdhci mmc_core i2c_hid [last unloaded: i915] [ 202.634930] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G U 4.9.0-rc1-CI-CI_DRM_1734+ #1 [ 202.634931] Hardware name: GIGABYTE M4HM87P-00/M4HM87P-00, BIOS F6 12/10/2014 [ 202.634933] 88011ea03d68 8142dce5 88011ea03db8 [ 202.634934] 88011ea03da8 8107e496 0aa90002 81e249a0 [ 202.634935] 81815637 82e7c280 0004 [ 202.634936] Call Trace: [ 202.634939] [ 202.634939] [] dump_stack+0x67/0x92 [ 202.634941] [] __warn+0xc6/0xe0 [ 202.634944] [] ? _raw_spin_unlock_irq+0x27/0x50 [ 202.634945] [] warn_slowpath_fmt+0x4a/0x50 [ 202.634946] [] trace_hardirqs_on_caller+0x113/0x1b0 [ 202.634948] [] trace_hardirqs_on+0xd/0x10 [ 202.634949] [] _raw_spin_unlock_irq+0x27/0x50 [ 202.634951] [] rtc_handler+0x32/0xa0 [ 202.634954] [] acpi_ev_fixed_event_detect+0xd4/0xfb [ 202.634956] [] acpi_ev_sci_xrupt_handler+0xf/0x2d [ 202.634957] [] acpi_irq+0x11/0x2c [ 202.634960] [] __handle_irq_event_percpu+0x58/0x370 [ 202.634961] [] handle_irq_event_percpu+0x1e/0x50 [ 202.634962] [] handle_irq_event+0x34/0x60 [ 202.634963] [] handle_fasteoi_irq+0xa6/0x170 [ 202.634966] [] handle_irq+0x15/0x20 [ 202.634967] [] do_IRQ+0x68/0x130 [ 202.634968] [] common_interrupt+0x89/0x89 [ 202.634970] [ 202.634970] [] ? mwait_idle+0x93/0x210 [ 202.634971] [] ? mwait_idle+0x8a/0x210 [ 202.634972] [] arch_cpu_idle+0xa/0x10 [ 202.634973] [] default_idle_call+0x1e/0x30 [ 202.634974] [] cpu_startup_entry+0x17c/0x1f0 [ 202.634976] [] rest_init+0x127/0x130 [ 202.634978] [] start_kernel+0x3f6/0x403 [ 202.634980] [] x86_64_start_reservations+0x2a/0x2c [ 202.634981] [] x86_64_start_kernel+0x173/0x186 [ 202.634982] ---[ end trace 293c99618fa08d34 ]--- Cc: Gabriele Mazzotta Cc: Alexandre Belloni Fixes: 983bf1256edb ("rtc: cmos: Clear ACPI-driven alarms upon resume") Signed-off-by: Ville Syrjälä --- drivers/rtc/rtc-cmos.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index dd3d59806ffa..19cd49ad92dc 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -996,8 +996,9 @@ static u32 rtc_handler(void *context) struct cmos_rtc *cmos = dev_get_drvdata(dev); unsigned char rtc_control = 0; unsigned char rtc_intr; + unsigned long flags; - spin_lock_irq(_lock); + spin_lock_irqsave(_lock, flags); if (cmos_rtc.suspend_ctrl) rtc_control = CMOS_READ(RTC_CONTROL); if (rtc_control & RTC_AIE) { @@ -1006,7 +1007,7 @@ static u32 rtc_handler(void *context) rtc_intr = CMOS_READ(RTC_INTR_FLAGS); rtc_update_irq(cmos->rtc, 1, rtc_intr); } - spin_unlock_irq(_lock); + spin_unlock_irqrestore(_lock, flags); pm_wakeup_event(dev, 0); acpi_clear_event(ACPI_EVENT_RTC); -- 2.7.4
[PATCH] timer: Make msleep(0) a nop
From: Ville SyrjäläThanks to the msecs_to_jiffies()+1 msleep(0) may actually sleep for up to one jiffy. Presumably the caller should be satisfied if we "sleep" for 0 jiffies instead of 0-1 jiffies, so let's just turn msleep(0) into a nop. This can simplify some callers as they don't have to check for the 0 msecs case themselves anymore. Or if they're not checking for 0, they might avoid a needless sleep occasionally. A slight concern might be that someone is calling msleep(0) and depending on some delay being there. But that can clearly blow up even without this change, so I'm not overly worried about it. Cc: Thomas Gleixner Cc: John Stultz Signed-off-by: Ville Syrjälä --- kernel/time/timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 555670a5143c..1f9ccfccb68f 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -1870,7 +1870,7 @@ void __init init_timers(void) */ void msleep(unsigned int msecs) { - unsigned long timeout = msecs_to_jiffies(msecs) + 1; + unsigned long timeout = msecs ? msecs_to_jiffies(msecs) + 1 : 0; while (timeout) timeout = schedule_timeout_uninterruptible(timeout); @@ -1884,7 +1884,7 @@ EXPORT_SYMBOL(msleep); */ unsigned long msleep_interruptible(unsigned int msecs) { - unsigned long timeout = msecs_to_jiffies(msecs) + 1; + unsigned long timeout = msecs ? msecs_to_jiffies(msecs) + 1 : 0; while (timeout && !signal_pending(current)) timeout = schedule_timeout_interruptible(timeout); -- 2.7.4
[PATCH] timer: Make msleep(0) a nop
From: Ville Syrjälä Thanks to the msecs_to_jiffies()+1 msleep(0) may actually sleep for up to one jiffy. Presumably the caller should be satisfied if we "sleep" for 0 jiffies instead of 0-1 jiffies, so let's just turn msleep(0) into a nop. This can simplify some callers as they don't have to check for the 0 msecs case themselves anymore. Or if they're not checking for 0, they might avoid a needless sleep occasionally. A slight concern might be that someone is calling msleep(0) and depending on some delay being there. But that can clearly blow up even without this change, so I'm not overly worried about it. Cc: Thomas Gleixner Cc: John Stultz Signed-off-by: Ville Syrjälä --- kernel/time/timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 555670a5143c..1f9ccfccb68f 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -1870,7 +1870,7 @@ void __init init_timers(void) */ void msleep(unsigned int msecs) { - unsigned long timeout = msecs_to_jiffies(msecs) + 1; + unsigned long timeout = msecs ? msecs_to_jiffies(msecs) + 1 : 0; while (timeout) timeout = schedule_timeout_uninterruptible(timeout); @@ -1884,7 +1884,7 @@ EXPORT_SYMBOL(msleep); */ unsigned long msleep_interruptible(unsigned int msecs) { - unsigned long timeout = msecs_to_jiffies(msecs) + 1; + unsigned long timeout = msecs ? msecs_to_jiffies(msecs) + 1 : 0; while (timeout && !signal_pending(current)) timeout = schedule_timeout_interruptible(timeout); -- 2.7.4
[PATCH] x86/hweight: Don't clobber %rdi
From: Ville SyrjäläThe caller expects %rdi to remain intact, push+pop it make that happen. Fixes the following kind of explosions on my core2duo machine when trying to reboot or shut down: general protection fault: [#1] PREEMPT SMP Modules linked in: i915 i2c_algo_bit drm_kms_helper cfbfillrect syscopyarea cfbimgblt sysfillrect sysimgblt fb_sys_fops cfbcopyarea drm netconsole configfs binfmt_misc iTCO_wdt psmouse pcspkr snd_hda_codec_idt e100 coretemp hwmon snd_hda_codec_generic i2c_i801 mii i2c_smbus lpc_ich mfd_core snd_hda_intel uhci_hcd snd_hda_codec snd_hwdep snd_hda_core ehci_pci 8250 ehci_hcd snd_pcm 8250_base usbcore evdev serial_core usb_common parport_pc parport snd_timer snd soundcore CPU: 0 PID: 3070 Comm: reboot Not tainted 4.8.0-rc1-perf-dirty #69 Hardware name: /D946GZIS, BIOS TS94610J.86A.0087.2007.1107.1049 11/07/2007 task: 88012a0b4080 task.stack: 88012385 RIP: 0010:[] [] x86_perf_event_update+0x52/0xc0 RSP: 0018:880123853b60 EFLAGS: 00010087 RAX: 0001 RBX: 88012fc0a3c0 RCX: 001e RDX: RSI: 4000 RDI: 88012b014800 RBP: 880123853b88 R08: R09: R10: ea0004a012c0 R11: ea0004acedc0 R12: 8001 R13: 88012b0149c0 R14: 88012b014800 R15: 0018 FS: 7f8b155cd700() GS:88012fc0() knlGS: CS: 0010 DS: ES: CR0: 80050033 CR2: 7f8b155f5000 CR3: 00012a2d7000 CR4: 06f0 Stack: 88012fc0a3c0 88012b014800 0004 0001 88012fc1b750 880123853bb0 81003d59 88012b014800 88012fc0a3c0 88012b014800 880123853bd8 81003e13 Call Trace: [] x86_pmu_stop+0x59/0xd0 [] x86_pmu_del+0x43/0x140 [] event_sched_out.isra.105+0xbd/0x260 [] __perf_remove_from_context+0x2d/0xb0 [] __perf_event_exit_context+0x4d/0x70 [] generic_exec_single+0xb6/0x140 [] ? __perf_remove_from_context+0xb0/0xb0 [] ? __perf_remove_from_context+0xb0/0xb0 [] smp_call_function_single+0xdf/0x140 [] perf_event_exit_cpu_context+0x87/0xc0 [] perf_reboot+0x13/0x40 [] notifier_call_chain+0x4a/0x70 [] __blocking_notifier_call_chain+0x47/0x60 [] blocking_notifier_call_chain+0x16/0x20 [] kernel_restart_prepare+0x1d/0x40 [] kernel_restart+0x12/0x60 [] SYSC_reboot+0xf6/0x1b0 [] ? mntput_no_expire+0x2c/0x1b0 [] ? mntput+0x24/0x40 [] ? __fput+0x16c/0x1e0 [] ? fput+0xe/0x10 [] ? task_work_run+0x83/0xa0 [] ? exit_to_usermode_loop+0x53/0xc0 [] ? trace_hardirqs_on_thunk+0x1a/0x1c [] SyS_reboot+0xe/0x10 [] entry_SYSCALL_64_fastpath+0x18/0xa3 Code: 7c 4c 8d af c0 01 00 00 49 89 fe eb 10 48 09 c2 4c 89 e0 49 0f b1 55 00 4c 39 e0 74 35 4d 8b a6 c0 01 00 00 41 8b 8e 60 01 00 00 <0f> 33 8b 35 6e 02 8c 00 48 c1 e2 20 85 f6 7e d2 48 89 d3 89 cf RIP [] x86_perf_event_update+0x52/0xc0 RSP ---[ end trace 7ec95181faf211be ]--- note: reboot[3070] exited with preempt_count 2 Cc: Borislav Petkov Cc: H. Peter Anvin Cc: Andy Lutomirski Cc: Brian Gerst Cc: Denys Vlasenko Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Ingo Molnar Fixes: f5967101e9de ("x86/hweight: Get rid of the special calling convention") Signed-off-by: Ville Syrjälä --- arch/x86/lib/hweight.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/lib/hweight.S b/arch/x86/lib/hweight.S index 02de3d74d2c5..8a602a1e404a 100644 --- a/arch/x86/lib/hweight.S +++ b/arch/x86/lib/hweight.S @@ -35,6 +35,7 @@ ENDPROC(__sw_hweight32) ENTRY(__sw_hweight64) #ifdef CONFIG_X86_64 + pushq %rdi pushq %rdx movq%rdi, %rdx # w -> t @@ -60,6 +61,7 @@ ENTRY(__sw_hweight64) shrq$56, %rax # w = w_tmp >> 56 popq%rdx + popq%rdi ret #else /* CONFIG_X86_32 */ /* We're getting an u64 arg in (%eax,%edx): unsigned long hweight64(__u64 w) */ -- 2.7.4
[PATCH] x86/hweight: Don't clobber %rdi
From: Ville Syrjälä The caller expects %rdi to remain intact, push+pop it make that happen. Fixes the following kind of explosions on my core2duo machine when trying to reboot or shut down: general protection fault: [#1] PREEMPT SMP Modules linked in: i915 i2c_algo_bit drm_kms_helper cfbfillrect syscopyarea cfbimgblt sysfillrect sysimgblt fb_sys_fops cfbcopyarea drm netconsole configfs binfmt_misc iTCO_wdt psmouse pcspkr snd_hda_codec_idt e100 coretemp hwmon snd_hda_codec_generic i2c_i801 mii i2c_smbus lpc_ich mfd_core snd_hda_intel uhci_hcd snd_hda_codec snd_hwdep snd_hda_core ehci_pci 8250 ehci_hcd snd_pcm 8250_base usbcore evdev serial_core usb_common parport_pc parport snd_timer snd soundcore CPU: 0 PID: 3070 Comm: reboot Not tainted 4.8.0-rc1-perf-dirty #69 Hardware name: /D946GZIS, BIOS TS94610J.86A.0087.2007.1107.1049 11/07/2007 task: 88012a0b4080 task.stack: 88012385 RIP: 0010:[] [] x86_perf_event_update+0x52/0xc0 RSP: 0018:880123853b60 EFLAGS: 00010087 RAX: 0001 RBX: 88012fc0a3c0 RCX: 001e RDX: RSI: 4000 RDI: 88012b014800 RBP: 880123853b88 R08: R09: R10: ea0004a012c0 R11: ea0004acedc0 R12: 8001 R13: 88012b0149c0 R14: 88012b014800 R15: 0018 FS: 7f8b155cd700() GS:88012fc0() knlGS: CS: 0010 DS: ES: CR0: 80050033 CR2: 7f8b155f5000 CR3: 00012a2d7000 CR4: 06f0 Stack: 88012fc0a3c0 88012b014800 0004 0001 88012fc1b750 880123853bb0 81003d59 88012b014800 88012fc0a3c0 88012b014800 880123853bd8 81003e13 Call Trace: [] x86_pmu_stop+0x59/0xd0 [] x86_pmu_del+0x43/0x140 [] event_sched_out.isra.105+0xbd/0x260 [] __perf_remove_from_context+0x2d/0xb0 [] __perf_event_exit_context+0x4d/0x70 [] generic_exec_single+0xb6/0x140 [] ? __perf_remove_from_context+0xb0/0xb0 [] ? __perf_remove_from_context+0xb0/0xb0 [] smp_call_function_single+0xdf/0x140 [] perf_event_exit_cpu_context+0x87/0xc0 [] perf_reboot+0x13/0x40 [] notifier_call_chain+0x4a/0x70 [] __blocking_notifier_call_chain+0x47/0x60 [] blocking_notifier_call_chain+0x16/0x20 [] kernel_restart_prepare+0x1d/0x40 [] kernel_restart+0x12/0x60 [] SYSC_reboot+0xf6/0x1b0 [] ? mntput_no_expire+0x2c/0x1b0 [] ? mntput+0x24/0x40 [] ? __fput+0x16c/0x1e0 [] ? fput+0xe/0x10 [] ? task_work_run+0x83/0xa0 [] ? exit_to_usermode_loop+0x53/0xc0 [] ? trace_hardirqs_on_thunk+0x1a/0x1c [] SyS_reboot+0xe/0x10 [] entry_SYSCALL_64_fastpath+0x18/0xa3 Code: 7c 4c 8d af c0 01 00 00 49 89 fe eb 10 48 09 c2 4c 89 e0 49 0f b1 55 00 4c 39 e0 74 35 4d 8b a6 c0 01 00 00 41 8b 8e 60 01 00 00 <0f> 33 8b 35 6e 02 8c 00 48 c1 e2 20 85 f6 7e d2 48 89 d3 89 cf RIP [] x86_perf_event_update+0x52/0xc0 RSP ---[ end trace 7ec95181faf211be ]--- note: reboot[3070] exited with preempt_count 2 Cc: Borislav Petkov Cc: H. Peter Anvin Cc: Andy Lutomirski Cc: Brian Gerst Cc: Denys Vlasenko Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Ingo Molnar Fixes: f5967101e9de ("x86/hweight: Get rid of the special calling convention") Signed-off-by: Ville Syrjälä --- arch/x86/lib/hweight.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/lib/hweight.S b/arch/x86/lib/hweight.S index 02de3d74d2c5..8a602a1e404a 100644 --- a/arch/x86/lib/hweight.S +++ b/arch/x86/lib/hweight.S @@ -35,6 +35,7 @@ ENDPROC(__sw_hweight32) ENTRY(__sw_hweight64) #ifdef CONFIG_X86_64 + pushq %rdi pushq %rdx movq%rdi, %rdx # w -> t @@ -60,6 +61,7 @@ ENTRY(__sw_hweight64) shrq$56, %rax # w = w_tmp >> 56 popq%rdx + popq%rdi ret #else /* CONFIG_X86_32 */ /* We're getting an u64 arg in (%eax,%edx): unsigned long hweight64(__u64 w) */ -- 2.7.4
[PATCH] x86/perf/intel/rapl: Fix module name collision with powercap intel-rapl
From: Ville SyrjäläSince commit 4b6e2571bf00 ("x86/perf/intel/rapl: Make the Intel RAPL PMU driver modular") the rapl perf module calls itself intel-rapl. That name was already in use by the rapl powercap driver, which now fails to load if the perf module is loaded. Fix the problem by renaming the perf module to intel-rapl-perf, so that both modules can coexist. Cc: Kan Liang Cc: Thomas Gleixner Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Vince Weaver Fixes: 4b6e2571bf00 ("x86/perf/intel/rapl: Make the Intel RAPL PMU driver modular") Signed-off-by: Ville Syrjälä --- arch/x86/events/intel/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/events/intel/Makefile b/arch/x86/events/intel/Makefile index 3660b2cf245a..06c2baa51814 100644 --- a/arch/x86/events/intel/Makefile +++ b/arch/x86/events/intel/Makefile @@ -1,8 +1,8 @@ obj-$(CONFIG_CPU_SUP_INTEL)+= core.o bts.o cqm.o obj-$(CONFIG_CPU_SUP_INTEL)+= ds.o knc.o obj-$(CONFIG_CPU_SUP_INTEL)+= lbr.o p4.o p6.o pt.o -obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL) += intel-rapl.o -intel-rapl-objs:= rapl.o +obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL) += intel-rapl-perf.o +intel-rapl-perf-objs := rapl.o obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel-uncore.o intel-uncore-objs := uncore.o uncore_nhmex.o uncore_snb.o uncore_snbep.o obj-$(CONFIG_PERF_EVENTS_INTEL_CSTATE) += intel-cstate.o -- 2.7.4
[PATCH] x86/perf/intel/rapl: Fix module name collision with powercap intel-rapl
From: Ville Syrjälä Since commit 4b6e2571bf00 ("x86/perf/intel/rapl: Make the Intel RAPL PMU driver modular") the rapl perf module calls itself intel-rapl. That name was already in use by the rapl powercap driver, which now fails to load if the perf module is loaded. Fix the problem by renaming the perf module to intel-rapl-perf, so that both modules can coexist. Cc: Kan Liang Cc: Thomas Gleixner Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Vince Weaver Fixes: 4b6e2571bf00 ("x86/perf/intel/rapl: Make the Intel RAPL PMU driver modular") Signed-off-by: Ville Syrjälä --- arch/x86/events/intel/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/events/intel/Makefile b/arch/x86/events/intel/Makefile index 3660b2cf245a..06c2baa51814 100644 --- a/arch/x86/events/intel/Makefile +++ b/arch/x86/events/intel/Makefile @@ -1,8 +1,8 @@ obj-$(CONFIG_CPU_SUP_INTEL)+= core.o bts.o cqm.o obj-$(CONFIG_CPU_SUP_INTEL)+= ds.o knc.o obj-$(CONFIG_CPU_SUP_INTEL)+= lbr.o p4.o p6.o pt.o -obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL) += intel-rapl.o -intel-rapl-objs:= rapl.o +obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL) += intel-rapl-perf.o +intel-rapl-perf-objs := rapl.o obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel-uncore.o intel-uncore-objs := uncore.o uncore_nhmex.o uncore_snb.o uncore_snbep.o obj-$(CONFIG_PERF_EVENTS_INTEL_CSTATE) += intel-cstate.o -- 2.7.4
[PATCH] dma-debug: Avoid spinlock recursion when disabling dma-debug
From: Ville SyrjäläWith netconsole (at least) the pr_err("... disabling\n") call can recurse back into the dma-debug code, where it'll try to grab free_entries_lock again. Avoid the problem by doing the printk after dropping the lock. Cc: sta...@vger.kernel.org Cc: Andrew Morton Signed-off-by: Ville Syrjälä --- lib/dma-debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 4a1515f4b452..51a76af25c66 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -657,9 +657,9 @@ static struct dma_debug_entry *dma_entry_alloc(void) spin_lock_irqsave(_entries_lock, flags); if (list_empty(_entries)) { - pr_err("DMA-API: debugging out of memory - disabling\n"); global_disable = true; spin_unlock_irqrestore(_entries_lock, flags); + pr_err("DMA-API: debugging out of memory - disabling\n"); return NULL; } -- 2.7.4
[PATCH] dma-debug: Avoid spinlock recursion when disabling dma-debug
From: Ville Syrjälä With netconsole (at least) the pr_err("... disabling\n") call can recurse back into the dma-debug code, where it'll try to grab free_entries_lock again. Avoid the problem by doing the printk after dropping the lock. Cc: sta...@vger.kernel.org Cc: Andrew Morton Signed-off-by: Ville Syrjälä --- lib/dma-debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 4a1515f4b452..51a76af25c66 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -657,9 +657,9 @@ static struct dma_debug_entry *dma_entry_alloc(void) spin_lock_irqsave(_entries_lock, flags); if (list_empty(_entries)) { - pr_err("DMA-API: debugging out of memory - disabling\n"); global_disable = true; spin_unlock_irqrestore(_entries_lock, flags); + pr_err("DMA-API: debugging out of memory - disabling\n"); return NULL; } -- 2.7.4
[PATCH 01/29] pci: Decouple quirks.c from i915_reg.h
From: Ville Syrjälä i915 register defines are going to become type safe, so going forward the register defines can't be used as straight numbers. Since quirks.c needs just a few extra register defines from i915_reg.h, decouple the two by defining the required registers locally in quirks.c. This was already done for a few other igpu related registers. Cc: Bjorn Helgaas Cc: linux-...@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- drivers/pci/quirks.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index b03373f..78a70fb 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3404,7 +3404,9 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) return 0; } -#include "../gpu/drm/i915/i915_reg.h" +#define SOUTH_CHICKEN2 0xc2004 +#define PCH_PP_STATUS 0xc7200 +#define PCH_PP_CONTROL 0xc7204 #define MSG_CTL0x45010 #define NSDE_PWR_STATE 0xd0100 #define IGD_OPERATION_TIMEOUT 1 /* set timeout 10 seconds */ -- 2.4.10 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 01/29] pci: Decouple quirks.c from i915_reg.h
From: Ville Syrjäläi915 register defines are going to become type safe, so going forward the register defines can't be used as straight numbers. Since quirks.c needs just a few extra register defines from i915_reg.h, decouple the two by defining the required registers locally in quirks.c. This was already done for a few other igpu related registers. Cc: Bjorn Helgaas Cc: linux-...@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- drivers/pci/quirks.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index b03373f..78a70fb 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3404,7 +3404,9 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) return 0; } -#include "../gpu/drm/i915/i915_reg.h" +#define SOUTH_CHICKEN2 0xc2004 +#define PCH_PP_STATUS 0xc7200 +#define PCH_PP_CONTROL 0xc7204 #define MSG_CTL0x45010 #define NSDE_PWR_STATE 0xd0100 #define IGD_OPERATION_TIMEOUT 1 /* set timeout 10 seconds */ -- 2.4.10 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] intel_idle: Don't use on Lenovo Ideapad S10-3t
From: Ville Syrjälä Lenovo Ideapad S10-3t hangs coming out of S3 with intel_idle. The two workaround that seem to help are "intel_idle.max_cstate=0" or "nohz=off highres=off". At a first glance quirk_tigerpoint_bm_sts() seemed promising, but even when moved to early_resume it didn't do anything. I have no idea what's wrong here, so let's just disable intel_idle for these machines using a DMI match. Cc: Len Brown Cc: Rafael J. Wysocki Cc: linux...@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- If anyone has any better ideas, I can try out some patches. drivers/idle/intel_idle.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index cd4510a..c4a6888 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -925,6 +926,25 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { }; MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); +static int intel_idle_disable_callback(const struct dmi_system_id *id) +{ + pr_debug(PREFIX "problematic system (%s), disabling\n", id->ident); + return 1; +} + +static const struct dmi_system_id intel_idle_disable_dmi[] = { + { + /* Lenovo Ideapad S10-3t, hangs coming out of S3 */ + .callback = intel_idle_disable_callback, + .ident = "Lenovo Ideapad S10-3t", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Ideapad S10-3t"), + }, + }, + {} +}; + /* * intel_idle_probe() */ @@ -957,6 +977,9 @@ static int __init intel_idle_probe(void) !mwait_substates) return -ENODEV; + if (dmi_check_system(intel_idle_disable_dmi)) + return -ENODEV; + pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates); icpu = (const struct idle_cpu *)id->driver_data; -- 2.4.10 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] intel_idle: Don't use on Lenovo Ideapad S10-3t
From: Ville SyrjäläLenovo Ideapad S10-3t hangs coming out of S3 with intel_idle. The two workaround that seem to help are "intel_idle.max_cstate=0" or "nohz=off highres=off". At a first glance quirk_tigerpoint_bm_sts() seemed promising, but even when moved to early_resume it didn't do anything. I have no idea what's wrong here, so let's just disable intel_idle for these machines using a DMI match. Cc: Len Brown Cc: Rafael J. Wysocki Cc: linux...@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- If anyone has any better ideas, I can try out some patches. drivers/idle/intel_idle.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index cd4510a..c4a6888 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -925,6 +926,25 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { }; MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); +static int intel_idle_disable_callback(const struct dmi_system_id *id) +{ + pr_debug(PREFIX "problematic system (%s), disabling\n", id->ident); + return 1; +} + +static const struct dmi_system_id intel_idle_disable_dmi[] = { + { + /* Lenovo Ideapad S10-3t, hangs coming out of S3 */ + .callback = intel_idle_disable_callback, + .ident = "Lenovo Ideapad S10-3t", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Ideapad S10-3t"), + }, + }, + {} +}; + /* * intel_idle_probe() */ @@ -957,6 +977,9 @@ static int __init intel_idle_probe(void) !mwait_substates) return -ENODEV; + if (dmi_check_system(intel_idle_disable_dmi)) + return -ENODEV; + pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates); icpu = (const struct idle_cpu *)id->driver_data; -- 2.4.10 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] x86: dma-mapping: Fix arch_dma_alloc_attrs() oops with NULL dev
From: Ville Syrjälä Commit 6894258eda2f ("dma-mapping: consolidate dma_{alloc,free}_{attrs,coherent}") broke drivers that pass NULL as the device for dma_alloc. Fix things by moving the ISA DMA fallback dev assignment earlier. A quick search suggest that Meelis Roos has hit this with sb16, and I caught it with smsc-ircc2. Here's the oops I got: BUG: unable to handle kernel NULL pointer dereference at 01c0 IP: [] arch_dma_alloc_attrs+0xd/0x80 *pde = Oops: [#1] PREEMPT Modules linked in: smsc_ircc2(+) irda crc_ccitt sch_fq_codel binfmt_misc joydev mousedev ipw2100 libipw snd_intel8x0 lib80211 snd_ac97_codec cfg80211 iTCO_wdt ac97_bus evdev psmouse firewire_ohci snd_pcm input_leds firewire_core crc_itu_t intel_agp 8139too mii led_class snd_timer snd intel_gtt soundcore lpc_ich mfd_core i2c_i801 i2c_core agpgart rng_core rfkill CPU: 0 PID: 2135 Comm: modprobe Not tainted 4.2.0-dma-oops+ #41 Hardware name: FUJITSU SIEMENS LIFEBOOK S6010/FJNB159, BIOS Version 1.07 10/28/2002 task: f39ba7c0 ti: f39d4000 task.ti: f39d4000 EIP: 0060:[] EFLAGS: 00010246 CPU: 0 EIP is at arch_dma_alloc_attrs+0xd/0x80 EAX: f39d5d7c EBX: ECX: 80d0 EDX: f39d5d78 ESI: f39ce800 EDI: c16325a0 EBP: f39d5d30 ESP: f39d5d2c DS: 007b ES: 007b FS: GS: 0033 SS: 0068 CR0: 8005003b CR2: 01c0 CR3: 339a8000 CR4: 06d0 Stack: 0400 f39d5dbc f88ca8bb f39d5d88 0002 0400 02e8 0003 0003 0003 c1e8e600 0404 0407 0003 0003 f39ceda0 f39cee34 02e8 80d0 c108c0b4 Call Trace: [] smsc_ircc_open+0x5eb/0x8f0 [smsc_ircc2] [] ? vprintk_default+0x34/0x40 [] ? printk+0x16/0x18 [] ? smsc_superio_flat+0xcd/0x103 [smsc_ircc2] [] smsc_superio_flat+0xed/0x103 [smsc_ircc2] [] smsc_ircc_init+0x43f/0x8c8 [smsc_ircc2] [] ? trace_hardirqs_on+0xb/0x10 [] ? do_one_initcall+0x73/0x1b0 [] ? smsc_superio_paged+0xac/0xac [smsc_ircc2] [] do_one_initcall+0x7e/0x1b0 [] ? smsc_superio_paged+0xac/0xac [smsc_ircc2] [] ? rcu_read_lock_sched_held+0x62/0x90 [] ? kmem_cache_alloc_trace+0xe5/0x2b0 [] ? __vunmap+0xb5/0x100 [] ? do_init_module+0x21/0x1b5 [] do_init_module+0x4f/0x1b5 [] load_module+0x1c19/0x2040 [] SyS_finit_module+0x61/0x80 [] sysenter_do_call+0x12/0x12 Code: 3b 4d e4 77 e7 42 83 c0 14 39 fa 75 be 90 83 c4 10 31 c0 5b 5e 5f 5d c3 66 90 66 90 66 90 55 89 e5 53 3e 8d 74 26 00 8b 18 8b 0a <8b> 9b c0 01 00 00 85 db 75 29 f6 c1 01 75 2c 83 e1 f8 89 0a 8b EIP: [] arch_dma_alloc_attrs+0xd/0x80 SS:ESP 0068:f39d5d2c CR2: 01c0 ---[ end trace fbf24ded74a1e64a ]--- Cc: Christoph Hellwig Cc: Ingo Molnar Cc: Thomas Gleixner Cc: "H. Peter Anvin" Cc: linux-kernel@vger.kernel.org Cc: Meelis Roos References: http://permalink.gmane.org/gmane.linux.kernel/2048042 Fixes: 6894258eda2f ("dma-mapping: consolidate dma_{alloc,free}_{attrs,coherent}") Signed-off-by: Ville Syrjälä --- arch/x86/kernel/pci-dma.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 1b55de1..cd99433 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -131,11 +131,12 @@ void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr, bool arch_dma_alloc_attrs(struct device **dev, gfp_t *gfp) { + if (!*dev) + *dev = _dma_fallback_dev; + *gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); *gfp = dma_alloc_coherent_gfp_flags(*dev, *gfp); - if (!*dev) - *dev = _dma_fallback_dev; if (!is_device_dma_capable(*dev)) return false; return true; -- 2.4.10 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] x86: dma-mapping: Fix arch_dma_alloc_attrs() oops with NULL dev
From: Ville SyrjäläCommit 6894258eda2f ("dma-mapping: consolidate dma_{alloc,free}_{attrs,coherent}") broke drivers that pass NULL as the device for dma_alloc. Fix things by moving the ISA DMA fallback dev assignment earlier. A quick search suggest that Meelis Roos has hit this with sb16, and I caught it with smsc-ircc2. Here's the oops I got: BUG: unable to handle kernel NULL pointer dereference at 01c0 IP: [] arch_dma_alloc_attrs+0xd/0x80 *pde = Oops: [#1] PREEMPT Modules linked in: smsc_ircc2(+) irda crc_ccitt sch_fq_codel binfmt_misc joydev mousedev ipw2100 libipw snd_intel8x0 lib80211 snd_ac97_codec cfg80211 iTCO_wdt ac97_bus evdev psmouse firewire_ohci snd_pcm input_leds firewire_core crc_itu_t intel_agp 8139too mii led_class snd_timer snd intel_gtt soundcore lpc_ich mfd_core i2c_i801 i2c_core agpgart rng_core rfkill CPU: 0 PID: 2135 Comm: modprobe Not tainted 4.2.0-dma-oops+ #41 Hardware name: FUJITSU SIEMENS LIFEBOOK S6010/FJNB159, BIOS Version 1.07 10/28/2002 task: f39ba7c0 ti: f39d4000 task.ti: f39d4000 EIP: 0060:[] EFLAGS: 00010246 CPU: 0 EIP is at arch_dma_alloc_attrs+0xd/0x80 EAX: f39d5d7c EBX: ECX: 80d0 EDX: f39d5d78 ESI: f39ce800 EDI: c16325a0 EBP: f39d5d30 ESP: f39d5d2c DS: 007b ES: 007b FS: GS: 0033 SS: 0068 CR0: 8005003b CR2: 01c0 CR3: 339a8000 CR4: 06d0 Stack: 0400 f39d5dbc f88ca8bb f39d5d88 0002 0400 02e8 0003 0003 0003 c1e8e600 0404 0407 0003 0003 f39ceda0 f39cee34 02e8 80d0 c108c0b4 Call Trace: [] smsc_ircc_open+0x5eb/0x8f0 [smsc_ircc2] [] ? vprintk_default+0x34/0x40 [] ? printk+0x16/0x18 [] ? smsc_superio_flat+0xcd/0x103 [smsc_ircc2] [] smsc_superio_flat+0xed/0x103 [smsc_ircc2] [] smsc_ircc_init+0x43f/0x8c8 [smsc_ircc2] [] ? trace_hardirqs_on+0xb/0x10 [] ? do_one_initcall+0x73/0x1b0 [] ? smsc_superio_paged+0xac/0xac [smsc_ircc2] [] do_one_initcall+0x7e/0x1b0 [] ? smsc_superio_paged+0xac/0xac [smsc_ircc2] [] ? rcu_read_lock_sched_held+0x62/0x90 [] ? kmem_cache_alloc_trace+0xe5/0x2b0 [] ? __vunmap+0xb5/0x100 [] ? do_init_module+0x21/0x1b5 [] do_init_module+0x4f/0x1b5 [] load_module+0x1c19/0x2040 [] SyS_finit_module+0x61/0x80 [] sysenter_do_call+0x12/0x12 Code: 3b 4d e4 77 e7 42 83 c0 14 39 fa 75 be 90 83 c4 10 31 c0 5b 5e 5f 5d c3 66 90 66 90 66 90 55 89 e5 53 3e 8d 74 26 00 8b 18 8b 0a <8b> 9b c0 01 00 00 85 db 75 29 f6 c1 01 75 2c 83 e1 f8 89 0a 8b EIP: [] arch_dma_alloc_attrs+0xd/0x80 SS:ESP 0068:f39d5d2c CR2: 01c0 ---[ end trace fbf24ded74a1e64a ]--- Cc: Christoph Hellwig Cc: Ingo Molnar Cc: Thomas Gleixner Cc: "H. Peter Anvin" Cc: linux-kernel@vger.kernel.org Cc: Meelis Roos References: http://permalink.gmane.org/gmane.linux.kernel/2048042 Fixes: 6894258eda2f ("dma-mapping: consolidate dma_{alloc,free}_{attrs,coherent}") Signed-off-by: Ville Syrjälä --- arch/x86/kernel/pci-dma.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 1b55de1..cd99433 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -131,11 +131,12 @@ void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr, bool arch_dma_alloc_attrs(struct device **dev, gfp_t *gfp) { + if (!*dev) + *dev = _dma_fallback_dev; + *gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); *gfp = dma_alloc_coherent_gfp_flags(*dev, *gfp); - if (!*dev) - *dev = _dma_fallback_dev; if (!is_device_dma_capable(*dev)) return false; return true; -- 2.4.10 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3] drm/i915: Fix lock dropping in intel_tv_detect()
From: Ville Syrjälä When intel_tv_detect() fails to do load detection it would forget to drop the locks and clean up the acquire context. Fix it up. This is a regression from: commit 208bf9fdcd3575aa4a5d48b3e0295f7cdaf6fc44 Author: Ville Syrjälä Date: Mon Aug 11 13:15:35 2014 +0300 drm/i915: Fix locking for intel_enable_pipe_a() v2: Make the code more readable (Chris) v3: Drop WARN_ON(type < 0) (Chris) Cc: sta...@vger.kernel.org Cc: Tibor Billes Reported-by: Tibor Billes Tested-by: Tibor Billes Reviewed-by: Chris Wilson Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_tv.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 32186a6..c69d3ce 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1311,6 +1311,7 @@ intel_tv_detect(struct drm_connector *connector, bool force) { struct drm_display_mode mode; struct intel_tv *intel_tv = intel_attached_tv(connector); + enum drm_connector_status status; int type; DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n", @@ -1328,16 +1329,19 @@ intel_tv_detect(struct drm_connector *connector, bool force) if (intel_get_load_detect_pipe(connector, , , )) { type = intel_tv_detect_type(intel_tv, connector); intel_release_load_detect_pipe(connector, ); + status = type < 0 ? + connector_status_disconnected : + connector_status_connected; } else - return connector_status_unknown; + status = connector_status_unknown; drm_modeset_drop_locks(); drm_modeset_acquire_fini(); } else return connector->status; - if (type < 0) - return connector_status_disconnected; + if (status != connector_status_connected) + return status; intel_tv->type = type; intel_tv_find_better_format(connector); -- 1.8.5.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3] drm/i915: Fix lock dropping in intel_tv_detect()
From: Ville Syrjälä ville.syrj...@linux.intel.com When intel_tv_detect() fails to do load detection it would forget to drop the locks and clean up the acquire context. Fix it up. This is a regression from: commit 208bf9fdcd3575aa4a5d48b3e0295f7cdaf6fc44 Author: Ville Syrjälä ville.syrj...@linux.intel.com Date: Mon Aug 11 13:15:35 2014 +0300 drm/i915: Fix locking for intel_enable_pipe_a() v2: Make the code more readable (Chris) v3: Drop WARN_ON(type 0) (Chris) Cc: sta...@vger.kernel.org Cc: Tibor Billes tbil...@gmx.com Reported-by: Tibor Billes tbil...@gmx.com Tested-by: Tibor Billes tbil...@gmx.com Reviewed-by: Chris Wilson ch...@chris-wilson.co.uk Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- drivers/gpu/drm/i915/intel_tv.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 32186a6..c69d3ce 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1311,6 +1311,7 @@ intel_tv_detect(struct drm_connector *connector, bool force) { struct drm_display_mode mode; struct intel_tv *intel_tv = intel_attached_tv(connector); + enum drm_connector_status status; int type; DRM_DEBUG_KMS([CONNECTOR:%d:%s] force=%d\n, @@ -1328,16 +1329,19 @@ intel_tv_detect(struct drm_connector *connector, bool force) if (intel_get_load_detect_pipe(connector, mode, tmp, ctx)) { type = intel_tv_detect_type(intel_tv, connector); intel_release_load_detect_pipe(connector, tmp); + status = type 0 ? + connector_status_disconnected : + connector_status_connected; } else - return connector_status_unknown; + status = connector_status_unknown; drm_modeset_drop_locks(ctx); drm_modeset_acquire_fini(ctx); } else return connector-status; - if (type 0) - return connector_status_disconnected; + if (status != connector_status_connected) + return status; intel_tv-type = type; intel_tv_find_better_format(connector); -- 1.8.5.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] drm/i915: Fix lock dropping in intel_tv_detect()
From: Ville Syrjälä When intel_tv_detect() fails to do load detection it would forget to drop the locks and clean up the acquire context. Fix it up. This is a regression from: commit 208bf9fdcd3575aa4a5d48b3e0295f7cdaf6fc44 Author: Ville Syrjälä Date: Mon Aug 11 13:15:35 2014 +0300 drm/i915: Fix locking for intel_enable_pipe_a() v2: Make the code more readable (Chris) Cc: Tibor Billes Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_tv.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 32186a6..c6b00f20 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1311,6 +1311,7 @@ intel_tv_detect(struct drm_connector *connector, bool force) { struct drm_display_mode mode; struct intel_tv *intel_tv = intel_attached_tv(connector); + enum drm_connector_status status; int type; DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n", @@ -1328,15 +1329,21 @@ intel_tv_detect(struct drm_connector *connector, bool force) if (intel_get_load_detect_pipe(connector, , , )) { type = intel_tv_detect_type(intel_tv, connector); intel_release_load_detect_pipe(connector, ); + status = type < 0 ? + connector_status_disconnected : + connector_status_connected; } else - return connector_status_unknown; + status = connector_status_unknown; drm_modeset_drop_locks(); drm_modeset_acquire_fini(); } else return connector->status; - if (type < 0) + if (status != connector_status_connected) + return status; + + if (WARN_ON(type < 0)) return connector_status_disconnected; intel_tv->type = type; -- 1.8.5.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] drm/i915: Fix lock dropping in intel_tv_detect()
From: Ville Syrjälä When intel_tv_detect() fails to do load detection it would forget to drop the locks and clean up the acquire context. Fix it up. This is a regression from: commit 208bf9fdcd3575aa4a5d48b3e0295f7cdaf6fc44 Author: Ville Syrjälä Date: Mon Aug 11 13:15:35 2014 +0300 drm/i915: Fix locking for intel_enable_pipe_a() Cc: Tibor Billes Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_tv.c | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 32186a6..abbf0ea 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1311,7 +1311,8 @@ intel_tv_detect(struct drm_connector *connector, bool force) { struct drm_display_mode mode; struct intel_tv *intel_tv = intel_attached_tv(connector); - int type; + enum drm_connector_status status = connector->status; + int type = -1; DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n", connector->base.id, connector->name, @@ -1328,21 +1329,23 @@ intel_tv_detect(struct drm_connector *connector, bool force) if (intel_get_load_detect_pipe(connector, , , )) { type = intel_tv_detect_type(intel_tv, connector); intel_release_load_detect_pipe(connector, ); + status = type < 0 ? + connector_status_disconnected : + connector_status_connected; } else - return connector_status_unknown; + status = connector_status_unknown; drm_modeset_drop_locks(); drm_modeset_acquire_fini(); - } else - return connector->status; + } if (type < 0) - return connector_status_disconnected; + return status; intel_tv->type = type; intel_tv_find_better_format(connector); - return connector_status_connected; + return status; } static const struct input_res { -- 1.8.5.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] drm/i915: Fix lock dropping in intel_tv_detect()
From: Ville Syrjälä ville.syrj...@linux.intel.com When intel_tv_detect() fails to do load detection it would forget to drop the locks and clean up the acquire context. Fix it up. This is a regression from: commit 208bf9fdcd3575aa4a5d48b3e0295f7cdaf6fc44 Author: Ville Syrjälä ville.syrj...@linux.intel.com Date: Mon Aug 11 13:15:35 2014 +0300 drm/i915: Fix locking for intel_enable_pipe_a() Cc: Tibor Billes tbil...@gmx.com Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- drivers/gpu/drm/i915/intel_tv.c | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 32186a6..abbf0ea 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1311,7 +1311,8 @@ intel_tv_detect(struct drm_connector *connector, bool force) { struct drm_display_mode mode; struct intel_tv *intel_tv = intel_attached_tv(connector); - int type; + enum drm_connector_status status = connector-status; + int type = -1; DRM_DEBUG_KMS([CONNECTOR:%d:%s] force=%d\n, connector-base.id, connector-name, @@ -1328,21 +1329,23 @@ intel_tv_detect(struct drm_connector *connector, bool force) if (intel_get_load_detect_pipe(connector, mode, tmp, ctx)) { type = intel_tv_detect_type(intel_tv, connector); intel_release_load_detect_pipe(connector, tmp); + status = type 0 ? + connector_status_disconnected : + connector_status_connected; } else - return connector_status_unknown; + status = connector_status_unknown; drm_modeset_drop_locks(ctx); drm_modeset_acquire_fini(ctx); - } else - return connector-status; + } if (type 0) - return connector_status_disconnected; + return status; intel_tv-type = type; intel_tv_find_better_format(connector); - return connector_status_connected; + return status; } static const struct input_res { -- 1.8.5.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] drm/i915: Fix lock dropping in intel_tv_detect()
From: Ville Syrjälä ville.syrj...@linux.intel.com When intel_tv_detect() fails to do load detection it would forget to drop the locks and clean up the acquire context. Fix it up. This is a regression from: commit 208bf9fdcd3575aa4a5d48b3e0295f7cdaf6fc44 Author: Ville Syrjälä ville.syrj...@linux.intel.com Date: Mon Aug 11 13:15:35 2014 +0300 drm/i915: Fix locking for intel_enable_pipe_a() v2: Make the code more readable (Chris) Cc: Tibor Billes tbil...@gmx.com Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- drivers/gpu/drm/i915/intel_tv.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 32186a6..c6b00f20 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1311,6 +1311,7 @@ intel_tv_detect(struct drm_connector *connector, bool force) { struct drm_display_mode mode; struct intel_tv *intel_tv = intel_attached_tv(connector); + enum drm_connector_status status; int type; DRM_DEBUG_KMS([CONNECTOR:%d:%s] force=%d\n, @@ -1328,15 +1329,21 @@ intel_tv_detect(struct drm_connector *connector, bool force) if (intel_get_load_detect_pipe(connector, mode, tmp, ctx)) { type = intel_tv_detect_type(intel_tv, connector); intel_release_load_detect_pipe(connector, tmp); + status = type 0 ? + connector_status_disconnected : + connector_status_connected; } else - return connector_status_unknown; + status = connector_status_unknown; drm_modeset_drop_locks(ctx); drm_modeset_acquire_fini(ctx); } else return connector-status; - if (type 0) + if (status != connector_status_connected) + return status; + + if (WARN_ON(type 0)) return connector_status_disconnected; intel_tv-type = type; -- 1.8.5.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] x86/gpu: Fix sign extension issue in Intel graphics stolen memory quirks
From: Ville Syrjälä Have the KB(),MB(),GB() macros produce unsigned longs to avoid uninteded sign extension issues with the gen2 memory size detection. What happens is first the uint8_t returned by read_pci_config_byte() gets promoted to an int which gets multiplied by another int from the MB() macro, and finally the result gets sign extended to size_t. Although this shouldn't be a problem in practice as all affected gen2 platforms are 32bit AFAIK, so size_t will be 32 bits. Cc: H. Peter Anvin Cc: Bjorn Helgaas Cc: Ingo Molnar Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- arch/x86/kernel/early-quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index b0cc380..6e2537c 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -240,7 +240,7 @@ static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_s return base; } -#define KB(x) ((x) * 1024) +#define KB(x) ((x) * 1024UL) #define MB(x) (KB (KB (x))) #define GB(x) (MB (KB (x))) -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] x86/gpu: Fix sign extension issue in Intel graphics stolen memory quirks
From: Ville Syrjälä ville.syrj...@linux.intel.com Have the KB(),MB(),GB() macros produce unsigned longs to avoid uninteded sign extension issues with the gen2 memory size detection. What happens is first the uint8_t returned by read_pci_config_byte() gets promoted to an int which gets multiplied by another int from the MB() macro, and finally the result gets sign extended to size_t. Although this shouldn't be a problem in practice as all affected gen2 platforms are 32bit AFAIK, so size_t will be 32 bits. Cc: H. Peter Anvin h...@zytor.com Cc: Bjorn Helgaas bhelg...@google.com Cc: Ingo Molnar mi...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- arch/x86/kernel/early-quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index b0cc380..6e2537c 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -240,7 +240,7 @@ static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_s return base; } -#define KB(x) ((x) * 1024) +#define KB(x) ((x) * 1024UL) #define MB(x) (KB (KB (x))) #define GB(x) (MB (KB (x))) -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 02/11] drm: Add support_bits parameter to drm_property_create_bitmask()
From: Ville Syrjälä Make drm_property_create_bitmask() a bit more generic by allowing the caller to specify which bits are in fact supported. This allows multiple callers to use the same enum list, but still create different versions of the same property with different list of supported bits. v2: Populate values[] array as non-sparse Make supported_bits 64bit Fix up omapdrm call site (Rob) Cc: Tomi Valkeinen Cc: Rob Clark Cc: Sagar Kamble Cc: dri-de...@lists.freedesktop.org Signed-off-by: Ville Syrjälä --- This should also make my original "drm: Add drm_mode_create_rotation_property()" patch do the right thing. So patch 03/11 of the series needs to be replaced with the original. drivers/gpu/drm/drm_crtc.c | 18 ++ drivers/gpu/drm/omapdrm/omap_plane.c | 5 - include/drm/drm_crtc.h | 3 ++- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3b7d32d..6e099069 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2906,10 +2906,12 @@ EXPORT_SYMBOL(drm_property_create_enum); struct drm_property *drm_property_create_bitmask(struct drm_device *dev, int flags, const char *name, const struct drm_prop_enum_list *props, -int num_values) +int num_props, +uint64_t supported_bits) { struct drm_property *property; - int i, ret; + int i, ret, index = 0; + int num_values = hweight64(supported_bits); flags |= DRM_MODE_PROP_BITMASK; @@ -2917,8 +2919,16 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev, if (!property) return NULL; - for (i = 0; i < num_values; i++) { - ret = drm_property_add_enum(property, i, + for (i = 0; i < num_props; i++) { + if (!(supported_bits & (1ULL << props[i].type))) + continue; + + if (WARN_ON(index >= num_values)) { + drm_property_destroy(dev, property); + return NULL; + } + + ret = drm_property_add_enum(property, index++, props[i].type, props[i].name); if (ret) { diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 046d5e6..0d97650 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -309,7 +309,10 @@ void omap_plane_install_properties(struct drm_plane *plane, { DRM_REFLECT_Y, "reflect-y" }, }; prop = drm_property_create_bitmask(dev, 0, "rotation", - props, ARRAY_SIZE(props)); + props, ARRAY_SIZE(props), + BIT(DRM_ROTATE_0) | BIT(DRM_ROTATE_90) | + BIT(DRM_ROTATE_180) | BIT(DRM_ROTATE_270) | + BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y)); if (prop == NULL) return; priv->rotation_prop = prop; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index d5c46c1..4e6d2aa 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1070,7 +1070,8 @@ extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int struct drm_property *drm_property_create_bitmask(struct drm_device *dev, int flags, const char *name, const struct drm_prop_enum_list *props, -int num_values); +int num_props, +uint64_t supported_bits); struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, const char *name, uint64_t min, uint64_t max); -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 02/11] drm: Add support_bits parameter to drm_property_create_bitmask()
From: Ville Syrjälä ville.syrjala at linux.intel.com Make drm_property_create_bitmask() a bit more generic by allowing the caller to specify which bits are in fact supported. This allows multiple callers to use the same enum list, but still create different versions of the same property with different list of supported bits. v2: Populate values[] array as non-sparse Make supported_bits 64bit Fix up omapdrm call site (Rob) Cc: Tomi Valkeinen tomi.valkei...@ti.com Cc: Rob Clark robdcl...@gmail.com Cc: Sagar Kamble sagar.a.kam...@intel.com Cc: dri-de...@lists.freedesktop.org Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- This should also make my original drm: Add drm_mode_create_rotation_property() patch do the right thing. So patch 03/11 of the series needs to be replaced with the original. drivers/gpu/drm/drm_crtc.c | 18 ++ drivers/gpu/drm/omapdrm/omap_plane.c | 5 - include/drm/drm_crtc.h | 3 ++- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3b7d32d..6e099069 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2906,10 +2906,12 @@ EXPORT_SYMBOL(drm_property_create_enum); struct drm_property *drm_property_create_bitmask(struct drm_device *dev, int flags, const char *name, const struct drm_prop_enum_list *props, -int num_values) +int num_props, +uint64_t supported_bits) { struct drm_property *property; - int i, ret; + int i, ret, index = 0; + int num_values = hweight64(supported_bits); flags |= DRM_MODE_PROP_BITMASK; @@ -2917,8 +2919,16 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev, if (!property) return NULL; - for (i = 0; i num_values; i++) { - ret = drm_property_add_enum(property, i, + for (i = 0; i num_props; i++) { + if (!(supported_bits (1ULL props[i].type))) + continue; + + if (WARN_ON(index = num_values)) { + drm_property_destroy(dev, property); + return NULL; + } + + ret = drm_property_add_enum(property, index++, props[i].type, props[i].name); if (ret) { diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 046d5e6..0d97650 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -309,7 +309,10 @@ void omap_plane_install_properties(struct drm_plane *plane, { DRM_REFLECT_Y, reflect-y }, }; prop = drm_property_create_bitmask(dev, 0, rotation, - props, ARRAY_SIZE(props)); + props, ARRAY_SIZE(props), + BIT(DRM_ROTATE_0) | BIT(DRM_ROTATE_90) | + BIT(DRM_ROTATE_180) | BIT(DRM_ROTATE_270) | + BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y)); if (prop == NULL) return; priv-rotation_prop = prop; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index d5c46c1..4e6d2aa 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1070,7 +1070,8 @@ extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int struct drm_property *drm_property_create_bitmask(struct drm_device *dev, int flags, const char *name, const struct drm_prop_enum_list *props, -int num_values); +int num_props, +uint64_t supported_bits); struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, const char *name, uint64_t min, uint64_t max); -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/3] x86: Add vfunc for Intel graphics stolen memory base address
From: Ville Syrjälä For gen2 devices we're going to need another way to determine the stolen memory base address. Make that into a vfunc as well. Also drop the bogus inline keyword from gen8_stolen_size(). Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- arch/x86/kernel/early-quirks.c | 77 ++ 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index bc4a088..fddd4d0 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -228,7 +228,7 @@ static void __init intel_remapping_check(int num, int slot, int func) * * And yes, so far on current devices the base addr is always under 4G. */ -static u32 __init intel_stolen_base(int num, int slot, int func) +static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_size) { u32 base; @@ -313,7 +313,7 @@ static size_t __init gen6_stolen_size(int num, int slot, int func) return gmch_ctrl << 25; /* 32 MB units */ } -static inline size_t gen8_stolen_size(int num, int slot, int func) +static size_t gen8_stolen_size(int num, int slot, int func) { u16 gmch_ctrl; @@ -323,31 +323,50 @@ static inline size_t gen8_stolen_size(int num, int slot, int func) return gmch_ctrl << 25; /* 32 MB units */ } -typedef size_t (*stolen_size_fn)(int num, int slot, int func); + +struct intel_stolen_funcs { + size_t (*size)(int num, int slot, int func); + u32 (*base)(int num, int slot, int func, size_t size); +}; + +static const struct intel_stolen_funcs gen3_stolen_funcs = { + .base = intel_stolen_base, + .size = gen3_stolen_size, +}; + +static const struct intel_stolen_funcs gen6_stolen_funcs = { + .base = intel_stolen_base, + .size = gen6_stolen_size, +}; + +static const struct intel_stolen_funcs gen8_stolen_funcs = { + .base = intel_stolen_base, + .size = gen8_stolen_size, +}; static struct pci_device_id intel_stolen_ids[] __initdata = { - INTEL_I915G_IDS(gen3_stolen_size), - INTEL_I915GM_IDS(gen3_stolen_size), - INTEL_I945G_IDS(gen3_stolen_size), - INTEL_I945GM_IDS(gen3_stolen_size), - INTEL_VLV_M_IDS(gen6_stolen_size), - INTEL_VLV_D_IDS(gen6_stolen_size), - INTEL_PINEVIEW_IDS(gen3_stolen_size), - INTEL_I965G_IDS(gen3_stolen_size), - INTEL_G33_IDS(gen3_stolen_size), - INTEL_I965GM_IDS(gen3_stolen_size), - INTEL_GM45_IDS(gen3_stolen_size), - INTEL_G45_IDS(gen3_stolen_size), - INTEL_IRONLAKE_D_IDS(gen3_stolen_size), - INTEL_IRONLAKE_M_IDS(gen3_stolen_size), - INTEL_SNB_D_IDS(gen6_stolen_size), - INTEL_SNB_M_IDS(gen6_stolen_size), - INTEL_IVB_M_IDS(gen6_stolen_size), - INTEL_IVB_D_IDS(gen6_stolen_size), - INTEL_HSW_D_IDS(gen6_stolen_size), - INTEL_HSW_M_IDS(gen6_stolen_size), - INTEL_BDW_M_IDS(gen8_stolen_size), - INTEL_BDW_D_IDS(gen8_stolen_size) + INTEL_I915G_IDS(_stolen_funcs), + INTEL_I915GM_IDS(_stolen_funcs), + INTEL_I945G_IDS(_stolen_funcs), + INTEL_I945GM_IDS(_stolen_funcs), + INTEL_VLV_M_IDS(_stolen_funcs), + INTEL_VLV_D_IDS(_stolen_funcs), + INTEL_PINEVIEW_IDS(_stolen_funcs), + INTEL_I965G_IDS(_stolen_funcs), + INTEL_G33_IDS(_stolen_funcs), + INTEL_I965GM_IDS(_stolen_funcs), + INTEL_GM45_IDS(_stolen_funcs), + INTEL_G45_IDS(_stolen_funcs), + INTEL_IRONLAKE_D_IDS(_stolen_funcs), + INTEL_IRONLAKE_M_IDS(_stolen_funcs), + INTEL_SNB_D_IDS(_stolen_funcs), + INTEL_SNB_M_IDS(_stolen_funcs), + INTEL_IVB_M_IDS(_stolen_funcs), + INTEL_IVB_D_IDS(_stolen_funcs), + INTEL_HSW_D_IDS(_stolen_funcs), + INTEL_HSW_M_IDS(_stolen_funcs), + INTEL_BDW_M_IDS(_stolen_funcs), + INTEL_BDW_D_IDS(_stolen_funcs) }; static void __init intel_graphics_stolen(int num, int slot, int func) @@ -364,10 +383,10 @@ static void __init intel_graphics_stolen(int num, int slot, int func) for (i = 0; i < ARRAY_SIZE(intel_stolen_ids); i++) { if (intel_stolen_ids[i].device == device) { - stolen_size_fn stolen_size = - (stolen_size_fn)intel_stolen_ids[i].driver_data; - size = stolen_size(num, slot, func); - start = intel_stolen_base(num, slot, func); + const struct intel_stolen_funcs *stolen_funcs = + (const struct intel_stolen_funcs *)intel_stolen_ids[i].driver_data; + size = stolen_funcs->size(num, slot, func); + start = stolen_funcs->base(num, slot, func, size); if (size && start) { /* Mark this space as reserved */
[PATCH v3 2/3] x86: Add Intel graphics stolen memory quirk for gen2 platforms
From: Ville Syrjälä There isn't an explicit stolen memory base register on gen2. Some old comment in the i915 code suggests we should get it via max_low_pfn_mapped, but that's clearly a bad idea on my MGM. The e820 map in said machine looks like this: [0.00] BIOS-e820: [mem 0x-0x0009f7ff] usable [0.00] BIOS-e820: [mem 0x0009f800-0x0009] reserved [0.00] BIOS-e820: [mem 0x000ce000-0x000c] reserved [0.00] BIOS-e820: [mem 0x000dc000-0x000f] reserved [0.00] BIOS-e820: [mem 0x0010-0x1f6e] usable [0.00] BIOS-e820: [mem 0x1f6f-0x1f6f7fff] ACPI data [0.00] BIOS-e820: [mem 0x1f6f8000-0x1f6f] ACPI NVS [0.00] BIOS-e820: [mem 0x1f70-0x1fff] reserved [0.00] BIOS-e820: [mem 0xfec1-0xfec1] reserved [0.00] BIOS-e820: [mem 0xffb0-0xffbf] reserved [0.00] BIOS-e820: [mem 0xfff0-0x] reserved That makes max_low_pfn_mapped = 1f6f, so assuming our stolen memory would start there would place it on top of some ACPI memory regions. So not a good idea as already stated. The 9MB region after the ACPI regions at 0x1f70 however looks promising given that the macine reports the stolen memory size to be 8MB. Looking at the PGTBL_CTL register, the GTT entries are at offset 0x1fee0, and given that the GTT entries occupy 128KB, it looks like the stolen memory could start at 0x1f70 and the GTT entries would occupy the last 128KB of the stolen memory. After some more digging through chipset documentation, I've determined the BIOS first allocates space for something called TSEG (something to do with SMM) from the top of memory, and then it allocates the graphics stolen memory below that. Accordind to the chipset documentation TSEG has a fixed size of 1MB on 855. So that explains the top 1MB in the e820 region. And it also confirms that the GTT entries are in fact at the end of the the stolen memory region. Derive the stolen memory base address on gen2 the same as the BIOS does (TOM-TSEG_SIZE-stolen_size). There are a few differences between the registers on various gen2 chipsets, so a few different codepaths are required. 865G is again bit more special since it seems to support enough memory to hit 4GB address space issues. This means the PCI allocations will also affect the location of the stolen memory. Fortunately there appears to be the TOUD register which may give us the correct answer directly. But the chipset docs are a bit unclear, so I'm not 100% sure that the graphics stolen memory is always the last thing the BIOS steals. Someone would need to verify it on a real system. I tested this on the my 830 and 855 machines, and so far everything looks peachy. v2: Rewrite to use the TOM-TSEG_SIZE-stolen_size and TOUD methods v3: Fix TSEG size for 830 Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- arch/x86/kernel/early-quirks.c | 132 + include/drm/i915_drm.h | 20 +++ 2 files changed, 152 insertions(+) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index fddd4d0..5218dd2 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -247,6 +247,114 @@ static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_s #define MB(x) (KB (KB (x))) #define GB(x) (MB (KB (x))) +static size_t __init i830_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I830_ESMRAMC); + + if (!(tmp & TSEG_ENABLE)) + return 0; + + if (tmp & I830_TSEG_SIZE_1M) + return MB(1); + else + return KB(512); +} + +static size_t __init i845_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I845_ESMRAMC); + + if (!(tmp & TSEG_ENABLE)) + return 0; + + switch (tmp & I845_TSEG_SIZE_MASK) { + case I845_TSEG_SIZE_512K: + return KB(512); + case I845_TSEG_SIZE_1M: + return MB(1); + default: + WARN_ON(1); + return 0; + } +} + +static size_t __init i85x_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC); + + if (!(tmp & TSEG_ENABLE)) + return 0; + + return MB(1); +} + +static size_t __init i830_mem_size(void) +{ + return read_pci_config_byte(0, 0, 0, I830_DRB3) * MB(32); +} + +static size_t __init i85x_mem_size(void) +{ + return read_pci_config_byte(0, 0, 1, I85X_DRB3) * MB(32); +} + +/* + * On 830/845/85x the stolen memory base isn't available in any + * register. We need to calculate it as TOM-TSEG_SIZE-stolen_size. + */ +static u32 __init
[PATCH 0/3] x86: Intel gen2 graphics stolen memory quirks
From: Ville Syrjälä Ingo asked me to post the x86 bits as a standalone series. So here it is. So the series adds the Intel gen2 graphics stolen memory reservation quirks to arch/x86. These are not unlike the quirks we have for later gens, except it's a bit more work to dig out the correct range to reserve on gen2. This has been tested on 830, 845 and 855 chipsets. 865 still eludes me unfortunately. Ville Syrjälä (3): x86: Add vfunc for Intel graphics stolen memory base address x86: Add Intel graphics stolen memory quirk for gen2 platforms x86: Print the Intel graphcis stolen memory range arch/x86/kernel/early-quirks.c | 211 +++-- include/drm/i915_drm.h | 20 2 files changed, 202 insertions(+), 29 deletions(-) -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/3] x86: Print the Intel graphics stolen memory range
From: Ville Syrjälä Print an informative message when reserving the graphics stolen memory region in the early quirk. Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- arch/x86/kernel/early-quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 5218dd2..52f36e6 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -520,6 +520,8 @@ static void __init intel_graphics_stolen(int num, int slot, int func) size = stolen_funcs->size(num, slot, func); start = stolen_funcs->base(num, slot, func, size); if (size && start) { + printk(KERN_INFO "Reserving Intel graphics stolen memory at 0x%x-0x%x\n", + start, start + (u32)size - 1); /* Mark this space as reserved */ e820_add_region(start, size, E820_RESERVED); sanitize_e820_map(e820.map, -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/3] x86: Print the Intel graphics stolen memory range
From: Ville Syrjälä ville.syrj...@linux.intel.com Print an informative message when reserving the graphics stolen memory region in the early quirk. Cc: Thomas Gleixner t...@linutronix.de Cc: Ingo Molnar mi...@redhat.com Cc: H. Peter Anvin h...@zytor.com Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- arch/x86/kernel/early-quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 5218dd2..52f36e6 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -520,6 +520,8 @@ static void __init intel_graphics_stolen(int num, int slot, int func) size = stolen_funcs-size(num, slot, func); start = stolen_funcs-base(num, slot, func, size); if (size start) { + printk(KERN_INFO Reserving Intel graphics stolen memory at 0x%x-0x%x\n, + start, start + (u32)size - 1); /* Mark this space as reserved */ e820_add_region(start, size, E820_RESERVED); sanitize_e820_map(e820.map, -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/3] x86: Intel gen2 graphics stolen memory quirks
From: Ville Syrjälä ville.syrj...@linux.intel.com Ingo asked me to post the x86 bits as a standalone series. So here it is. So the series adds the Intel gen2 graphics stolen memory reservation quirks to arch/x86. These are not unlike the quirks we have for later gens, except it's a bit more work to dig out the correct range to reserve on gen2. This has been tested on 830, 845 and 855 chipsets. 865 still eludes me unfortunately. Ville Syrjälä (3): x86: Add vfunc for Intel graphics stolen memory base address x86: Add Intel graphics stolen memory quirk for gen2 platforms x86: Print the Intel graphcis stolen memory range arch/x86/kernel/early-quirks.c | 211 +++-- include/drm/i915_drm.h | 20 2 files changed, 202 insertions(+), 29 deletions(-) -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 2/3] x86: Add Intel graphics stolen memory quirk for gen2 platforms
From: Ville Syrjälä ville.syrj...@linux.intel.com There isn't an explicit stolen memory base register on gen2. Some old comment in the i915 code suggests we should get it via max_low_pfn_mapped, but that's clearly a bad idea on my MGM. The e820 map in said machine looks like this: [0.00] BIOS-e820: [mem 0x-0x0009f7ff] usable [0.00] BIOS-e820: [mem 0x0009f800-0x0009] reserved [0.00] BIOS-e820: [mem 0x000ce000-0x000c] reserved [0.00] BIOS-e820: [mem 0x000dc000-0x000f] reserved [0.00] BIOS-e820: [mem 0x0010-0x1f6e] usable [0.00] BIOS-e820: [mem 0x1f6f-0x1f6f7fff] ACPI data [0.00] BIOS-e820: [mem 0x1f6f8000-0x1f6f] ACPI NVS [0.00] BIOS-e820: [mem 0x1f70-0x1fff] reserved [0.00] BIOS-e820: [mem 0xfec1-0xfec1] reserved [0.00] BIOS-e820: [mem 0xffb0-0xffbf] reserved [0.00] BIOS-e820: [mem 0xfff0-0x] reserved That makes max_low_pfn_mapped = 1f6f, so assuming our stolen memory would start there would place it on top of some ACPI memory regions. So not a good idea as already stated. The 9MB region after the ACPI regions at 0x1f70 however looks promising given that the macine reports the stolen memory size to be 8MB. Looking at the PGTBL_CTL register, the GTT entries are at offset 0x1fee0, and given that the GTT entries occupy 128KB, it looks like the stolen memory could start at 0x1f70 and the GTT entries would occupy the last 128KB of the stolen memory. After some more digging through chipset documentation, I've determined the BIOS first allocates space for something called TSEG (something to do with SMM) from the top of memory, and then it allocates the graphics stolen memory below that. Accordind to the chipset documentation TSEG has a fixed size of 1MB on 855. So that explains the top 1MB in the e820 region. And it also confirms that the GTT entries are in fact at the end of the the stolen memory region. Derive the stolen memory base address on gen2 the same as the BIOS does (TOM-TSEG_SIZE-stolen_size). There are a few differences between the registers on various gen2 chipsets, so a few different codepaths are required. 865G is again bit more special since it seems to support enough memory to hit 4GB address space issues. This means the PCI allocations will also affect the location of the stolen memory. Fortunately there appears to be the TOUD register which may give us the correct answer directly. But the chipset docs are a bit unclear, so I'm not 100% sure that the graphics stolen memory is always the last thing the BIOS steals. Someone would need to verify it on a real system. I tested this on the my 830 and 855 machines, and so far everything looks peachy. v2: Rewrite to use the TOM-TSEG_SIZE-stolen_size and TOUD methods v3: Fix TSEG size for 830 Cc: Thomas Gleixner t...@linutronix.de Cc: Ingo Molnar mi...@redhat.com Cc: H. Peter Anvin h...@zytor.com Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- arch/x86/kernel/early-quirks.c | 132 + include/drm/i915_drm.h | 20 +++ 2 files changed, 152 insertions(+) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index fddd4d0..5218dd2 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -247,6 +247,114 @@ static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_s #define MB(x) (KB (KB (x))) #define GB(x) (MB (KB (x))) +static size_t __init i830_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I830_ESMRAMC); + + if (!(tmp TSEG_ENABLE)) + return 0; + + if (tmp I830_TSEG_SIZE_1M) + return MB(1); + else + return KB(512); +} + +static size_t __init i845_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I845_ESMRAMC); + + if (!(tmp TSEG_ENABLE)) + return 0; + + switch (tmp I845_TSEG_SIZE_MASK) { + case I845_TSEG_SIZE_512K: + return KB(512); + case I845_TSEG_SIZE_1M: + return MB(1); + default: + WARN_ON(1); + return 0; + } +} + +static size_t __init i85x_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC); + + if (!(tmp TSEG_ENABLE)) + return 0; + + return MB(1); +} + +static size_t __init i830_mem_size(void) +{ + return read_pci_config_byte(0, 0, 0, I830_DRB3) * MB(32); +} + +static size_t __init i85x_mem_size(void) +{ + return read_pci_config_byte(0, 0, 1, I85X_DRB3) * MB(32); +} + +/* + * On 830/845/85x the stolen memory base isn't available in
[PATCH 1/3] x86: Add vfunc for Intel graphics stolen memory base address
From: Ville Syrjälä ville.syrj...@linux.intel.com For gen2 devices we're going to need another way to determine the stolen memory base address. Make that into a vfunc as well. Also drop the bogus inline keyword from gen8_stolen_size(). Cc: Thomas Gleixner t...@linutronix.de Cc: Ingo Molnar mi...@redhat.com Cc: H. Peter Anvin h...@zytor.com Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- arch/x86/kernel/early-quirks.c | 77 ++ 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index bc4a088..fddd4d0 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -228,7 +228,7 @@ static void __init intel_remapping_check(int num, int slot, int func) * * And yes, so far on current devices the base addr is always under 4G. */ -static u32 __init intel_stolen_base(int num, int slot, int func) +static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_size) { u32 base; @@ -313,7 +313,7 @@ static size_t __init gen6_stolen_size(int num, int slot, int func) return gmch_ctrl 25; /* 32 MB units */ } -static inline size_t gen8_stolen_size(int num, int slot, int func) +static size_t gen8_stolen_size(int num, int slot, int func) { u16 gmch_ctrl; @@ -323,31 +323,50 @@ static inline size_t gen8_stolen_size(int num, int slot, int func) return gmch_ctrl 25; /* 32 MB units */ } -typedef size_t (*stolen_size_fn)(int num, int slot, int func); + +struct intel_stolen_funcs { + size_t (*size)(int num, int slot, int func); + u32 (*base)(int num, int slot, int func, size_t size); +}; + +static const struct intel_stolen_funcs gen3_stolen_funcs = { + .base = intel_stolen_base, + .size = gen3_stolen_size, +}; + +static const struct intel_stolen_funcs gen6_stolen_funcs = { + .base = intel_stolen_base, + .size = gen6_stolen_size, +}; + +static const struct intel_stolen_funcs gen8_stolen_funcs = { + .base = intel_stolen_base, + .size = gen8_stolen_size, +}; static struct pci_device_id intel_stolen_ids[] __initdata = { - INTEL_I915G_IDS(gen3_stolen_size), - INTEL_I915GM_IDS(gen3_stolen_size), - INTEL_I945G_IDS(gen3_stolen_size), - INTEL_I945GM_IDS(gen3_stolen_size), - INTEL_VLV_M_IDS(gen6_stolen_size), - INTEL_VLV_D_IDS(gen6_stolen_size), - INTEL_PINEVIEW_IDS(gen3_stolen_size), - INTEL_I965G_IDS(gen3_stolen_size), - INTEL_G33_IDS(gen3_stolen_size), - INTEL_I965GM_IDS(gen3_stolen_size), - INTEL_GM45_IDS(gen3_stolen_size), - INTEL_G45_IDS(gen3_stolen_size), - INTEL_IRONLAKE_D_IDS(gen3_stolen_size), - INTEL_IRONLAKE_M_IDS(gen3_stolen_size), - INTEL_SNB_D_IDS(gen6_stolen_size), - INTEL_SNB_M_IDS(gen6_stolen_size), - INTEL_IVB_M_IDS(gen6_stolen_size), - INTEL_IVB_D_IDS(gen6_stolen_size), - INTEL_HSW_D_IDS(gen6_stolen_size), - INTEL_HSW_M_IDS(gen6_stolen_size), - INTEL_BDW_M_IDS(gen8_stolen_size), - INTEL_BDW_D_IDS(gen8_stolen_size) + INTEL_I915G_IDS(gen3_stolen_funcs), + INTEL_I915GM_IDS(gen3_stolen_funcs), + INTEL_I945G_IDS(gen3_stolen_funcs), + INTEL_I945GM_IDS(gen3_stolen_funcs), + INTEL_VLV_M_IDS(gen6_stolen_funcs), + INTEL_VLV_D_IDS(gen6_stolen_funcs), + INTEL_PINEVIEW_IDS(gen3_stolen_funcs), + INTEL_I965G_IDS(gen3_stolen_funcs), + INTEL_G33_IDS(gen3_stolen_funcs), + INTEL_I965GM_IDS(gen3_stolen_funcs), + INTEL_GM45_IDS(gen3_stolen_funcs), + INTEL_G45_IDS(gen3_stolen_funcs), + INTEL_IRONLAKE_D_IDS(gen3_stolen_funcs), + INTEL_IRONLAKE_M_IDS(gen3_stolen_funcs), + INTEL_SNB_D_IDS(gen6_stolen_funcs), + INTEL_SNB_M_IDS(gen6_stolen_funcs), + INTEL_IVB_M_IDS(gen6_stolen_funcs), + INTEL_IVB_D_IDS(gen6_stolen_funcs), + INTEL_HSW_D_IDS(gen6_stolen_funcs), + INTEL_HSW_M_IDS(gen6_stolen_funcs), + INTEL_BDW_M_IDS(gen8_stolen_funcs), + INTEL_BDW_D_IDS(gen8_stolen_funcs) }; static void __init intel_graphics_stolen(int num, int slot, int func) @@ -364,10 +383,10 @@ static void __init intel_graphics_stolen(int num, int slot, int func) for (i = 0; i ARRAY_SIZE(intel_stolen_ids); i++) { if (intel_stolen_ids[i].device == device) { - stolen_size_fn stolen_size = - (stolen_size_fn)intel_stolen_ids[i].driver_data; - size = stolen_size(num, slot, func); - start = intel_stolen_base(num, slot, func); + const struct intel_stolen_funcs *stolen_funcs = + (const struct intel_stolen_funcs *)intel_stolen_ids[i].driver_data; + size = stolen_funcs-size(num, slot, func); +
[PATCH] x86: Drop casts from __copy_{from,to}_user_inatomic
From: Ville Syrjälä The casts in __copy_{from,to}_user_inatomic lead to sparse warnings. Drop the casts to get rid of the warnings. Example: CHECK drivers/gpu/drm/i915/i915_gem.c arch/x86/include/asm/uaccess_64.h:213:40: warning: incorrect type in argument 1 (different address spaces) arch/x86/include/asm/uaccess_64.h:213:40:expected void [noderef] *dst arch/x86/include/asm/uaccess_64.h:213:40:got void * The warnings got introduced by this commit: commit ff47ab4ff3cddfa7bc1b25b990e24abe2ae474ff Author: Andi Kleen Date: Fri Aug 16 14:17:19 2013 -0700 x86: Add 1/2/4/8 byte optimization to 64bit __copy_{from,to}_user_inatomic Cc: Andi Kleen Cc: H. Peter Anvin Signed-off-by: Ville Syrjälä --- arch/x86/include/asm/uaccess_64.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index 190413d..12a26b9 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -204,13 +204,13 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size) static __must_check __always_inline int __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size) { - return __copy_from_user_nocheck(dst, (__force const void *)src, size); + return __copy_from_user_nocheck(dst, src, size); } static __must_check __always_inline int __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size) { - return __copy_to_user_nocheck((__force void *)dst, src, size); + return __copy_to_user_nocheck(dst, src, size); } extern long __copy_user_nocache(void *dst, const void __user *src, -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 2/6] x86: Add Intel graphics stolen memory quirk for gen2 platforms
From: Ville Syrjälä There isn't an explicit stolen memory base register on gen2. Some old comment in the i915 code suggests we should get it via max_low_pfn_mapped, but that's clearly a bad idea on my MGM. The e820 map in said machine looks like this: [0.00] BIOS-e820: [mem 0x-0x0009f7ff] usable [0.00] BIOS-e820: [mem 0x0009f800-0x0009] reserved [0.00] BIOS-e820: [mem 0x000ce000-0x000c] reserved [0.00] BIOS-e820: [mem 0x000dc000-0x000f] reserved [0.00] BIOS-e820: [mem 0x0010-0x1f6e] usable [0.00] BIOS-e820: [mem 0x1f6f-0x1f6f7fff] ACPI data [0.00] BIOS-e820: [mem 0x1f6f8000-0x1f6f] ACPI NVS [0.00] BIOS-e820: [mem 0x1f70-0x1fff] reserved [0.00] BIOS-e820: [mem 0xfec1-0xfec1] reserved [0.00] BIOS-e820: [mem 0xffb0-0xffbf] reserved [0.00] BIOS-e820: [mem 0xfff0-0x] reserved That makes max_low_pfn_mapped = 1f6f, so assuming our stolen memory would start there would place it on top of some ACPI memory regions. So not a good idea as already stated. The 9MB region after the ACPI regions at 0x1f70 however looks promising given that the macine reports the stolen memory size to be 8MB. Looking at the PGTBL_CTL register, the GTT entries are at offset 0x1fee0, and given that the GTT entries occupy 128KB, it looks like the stolen memory could start at 0x1f70 and the GTT entries would occupy the last 128KB of the stolen memory. After some more digging through chipset documentation, I've determined the BIOS first allocates space for something called TSEG (something to do with SMM) from the top of memory, and then it allocates the graphics stolen memory below that. Accordind to the chipset documentation TSEG has a fixed size of 1MB on 855. So that explains the top 1MB in the e820 region. And it also confirms that the GTT entries are in fact at the end of the the stolen memory region. Derive the stolen memory base address on gen2 the same as the BIOS does (TOM-TSEG_SIZE-stolen_size). There are a few differences between the registers on various gen2 chipsets, so a few different codepaths are required. 865G is again bit more special since it seems to support enough memory to hit 4GB address space issues. This means the PCI allocations will also affect the location of the stolen memory. Fortunately there appears to be the TOUD register which may give us the correct answer directly. But the chipset docs are a bit unclear, so I'm not 100% sure that the graphics stolen memory is always the last thing the BIOS steals. Someone would need to verify it on a real system. I tested this on the my 830 and 855 machines, and so far everything looks peachy. v2: Rewrite to use the TOM-TSEG_SIZE-stolen_size and TOUD methods v3: Fix TSEG size for 830 Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- arch/x86/kernel/early-quirks.c | 132 + include/drm/i915_drm.h | 20 +++ 2 files changed, 152 insertions(+) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index fddd4d0..5218dd2 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -247,6 +247,114 @@ static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_s #define MB(x) (KB (KB (x))) #define GB(x) (MB (KB (x))) +static size_t __init i830_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I830_ESMRAMC); + + if (!(tmp & TSEG_ENABLE)) + return 0; + + if (tmp & I830_TSEG_SIZE_1M) + return MB(1); + else + return KB(512); +} + +static size_t __init i845_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I845_ESMRAMC); + + if (!(tmp & TSEG_ENABLE)) + return 0; + + switch (tmp & I845_TSEG_SIZE_MASK) { + case I845_TSEG_SIZE_512K: + return KB(512); + case I845_TSEG_SIZE_1M: + return MB(1); + default: + WARN_ON(1); + return 0; + } +} + +static size_t __init i85x_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC); + + if (!(tmp & TSEG_ENABLE)) + return 0; + + return MB(1); +} + +static size_t __init i830_mem_size(void) +{ + return read_pci_config_byte(0, 0, 0, I830_DRB3) * MB(32); +} + +static size_t __init i85x_mem_size(void) +{ + return read_pci_config_byte(0, 0, 1, I85X_DRB3) * MB(32); +} + +/* + * On 830/845/85x the stolen memory base isn't available in any + * register. We need to calculate it as TOM-TSEG_SIZE-stolen_size. + */ +static u32 __init
[PATCH v3 2/6] x86: Add Intel graphics stolen memory quirk for gen2 platforms
From: Ville Syrjälä ville.syrj...@linux.intel.com There isn't an explicit stolen memory base register on gen2. Some old comment in the i915 code suggests we should get it via max_low_pfn_mapped, but that's clearly a bad idea on my MGM. The e820 map in said machine looks like this: [0.00] BIOS-e820: [mem 0x-0x0009f7ff] usable [0.00] BIOS-e820: [mem 0x0009f800-0x0009] reserved [0.00] BIOS-e820: [mem 0x000ce000-0x000c] reserved [0.00] BIOS-e820: [mem 0x000dc000-0x000f] reserved [0.00] BIOS-e820: [mem 0x0010-0x1f6e] usable [0.00] BIOS-e820: [mem 0x1f6f-0x1f6f7fff] ACPI data [0.00] BIOS-e820: [mem 0x1f6f8000-0x1f6f] ACPI NVS [0.00] BIOS-e820: [mem 0x1f70-0x1fff] reserved [0.00] BIOS-e820: [mem 0xfec1-0xfec1] reserved [0.00] BIOS-e820: [mem 0xffb0-0xffbf] reserved [0.00] BIOS-e820: [mem 0xfff0-0x] reserved That makes max_low_pfn_mapped = 1f6f, so assuming our stolen memory would start there would place it on top of some ACPI memory regions. So not a good idea as already stated. The 9MB region after the ACPI regions at 0x1f70 however looks promising given that the macine reports the stolen memory size to be 8MB. Looking at the PGTBL_CTL register, the GTT entries are at offset 0x1fee0, and given that the GTT entries occupy 128KB, it looks like the stolen memory could start at 0x1f70 and the GTT entries would occupy the last 128KB of the stolen memory. After some more digging through chipset documentation, I've determined the BIOS first allocates space for something called TSEG (something to do with SMM) from the top of memory, and then it allocates the graphics stolen memory below that. Accordind to the chipset documentation TSEG has a fixed size of 1MB on 855. So that explains the top 1MB in the e820 region. And it also confirms that the GTT entries are in fact at the end of the the stolen memory region. Derive the stolen memory base address on gen2 the same as the BIOS does (TOM-TSEG_SIZE-stolen_size). There are a few differences between the registers on various gen2 chipsets, so a few different codepaths are required. 865G is again bit more special since it seems to support enough memory to hit 4GB address space issues. This means the PCI allocations will also affect the location of the stolen memory. Fortunately there appears to be the TOUD register which may give us the correct answer directly. But the chipset docs are a bit unclear, so I'm not 100% sure that the graphics stolen memory is always the last thing the BIOS steals. Someone would need to verify it on a real system. I tested this on the my 830 and 855 machines, and so far everything looks peachy. v2: Rewrite to use the TOM-TSEG_SIZE-stolen_size and TOUD methods v3: Fix TSEG size for 830 Cc: Thomas Gleixner t...@linutronix.de Cc: Ingo Molnar mi...@redhat.com Cc: H. Peter Anvin h...@zytor.com Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- arch/x86/kernel/early-quirks.c | 132 + include/drm/i915_drm.h | 20 +++ 2 files changed, 152 insertions(+) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index fddd4d0..5218dd2 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -247,6 +247,114 @@ static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_s #define MB(x) (KB (KB (x))) #define GB(x) (MB (KB (x))) +static size_t __init i830_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I830_ESMRAMC); + + if (!(tmp TSEG_ENABLE)) + return 0; + + if (tmp I830_TSEG_SIZE_1M) + return MB(1); + else + return KB(512); +} + +static size_t __init i845_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I845_ESMRAMC); + + if (!(tmp TSEG_ENABLE)) + return 0; + + switch (tmp I845_TSEG_SIZE_MASK) { + case I845_TSEG_SIZE_512K: + return KB(512); + case I845_TSEG_SIZE_1M: + return MB(1); + default: + WARN_ON(1); + return 0; + } +} + +static size_t __init i85x_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC); + + if (!(tmp TSEG_ENABLE)) + return 0; + + return MB(1); +} + +static size_t __init i830_mem_size(void) +{ + return read_pci_config_byte(0, 0, 0, I830_DRB3) * MB(32); +} + +static size_t __init i85x_mem_size(void) +{ + return read_pci_config_byte(0, 0, 1, I85X_DRB3) * MB(32); +} + +/* + * On 830/845/85x the stolen memory base isn't available in
[PATCH] x86: Drop casts from __copy_{from,to}_user_inatomic
From: Ville Syrjälä ville.syrj...@linux.intel.com The casts in __copy_{from,to}_user_inatomic lead to sparse warnings. Drop the casts to get rid of the warnings. Example: CHECK drivers/gpu/drm/i915/i915_gem.c arch/x86/include/asm/uaccess_64.h:213:40: warning: incorrect type in argument 1 (different address spaces) arch/x86/include/asm/uaccess_64.h:213:40:expected void [noderef] asn:1*dst arch/x86/include/asm/uaccess_64.h:213:40:got void *noident The warnings got introduced by this commit: commit ff47ab4ff3cddfa7bc1b25b990e24abe2ae474ff Author: Andi Kleen a...@linux.intel.com Date: Fri Aug 16 14:17:19 2013 -0700 x86: Add 1/2/4/8 byte optimization to 64bit __copy_{from,to}_user_inatomic Cc: Andi Kleen a...@linux.intel.com Cc: H. Peter Anvin h...@linux.intel.com Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- arch/x86/include/asm/uaccess_64.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index 190413d..12a26b9 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -204,13 +204,13 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size) static __must_check __always_inline int __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size) { - return __copy_from_user_nocheck(dst, (__force const void *)src, size); + return __copy_from_user_nocheck(dst, src, size); } static __must_check __always_inline int __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size) { - return __copy_to_user_nocheck((__force void *)dst, src, size); + return __copy_to_user_nocheck(dst, src, size); } extern long __copy_user_nocache(void *dst, const void __user *src, -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 2/6] x86: Add Intel graphics stolen memory quirk for gen2 platforms
From: Ville Syrjälä There isn't an explicit stolen memory base register on gen2. Some old comment in the i915 code suggests we should get it via max_low_pfn_mapped, but that's clearly a bad idea on my MGM. The e820 map in said machine looks like this: [0.00] BIOS-e820: [mem 0x-0x0009f7ff] usable [0.00] BIOS-e820: [mem 0x0009f800-0x0009] reserved [0.00] BIOS-e820: [mem 0x000ce000-0x000c] reserved [0.00] BIOS-e820: [mem 0x000dc000-0x000f] reserved [0.00] BIOS-e820: [mem 0x0010-0x1f6e] usable [0.00] BIOS-e820: [mem 0x1f6f-0x1f6f7fff] ACPI data [0.00] BIOS-e820: [mem 0x1f6f8000-0x1f6f] ACPI NVS [0.00] BIOS-e820: [mem 0x1f70-0x1fff] reserved [0.00] BIOS-e820: [mem 0xfec1-0xfec1] reserved [0.00] BIOS-e820: [mem 0xffb0-0xffbf] reserved [0.00] BIOS-e820: [mem 0xfff0-0x] reserved That makes max_low_pfn_mapped = 1f6f, so assuming our stolen memory would start there would place it on top of some ACPI memory regions. So not a good idea as already stated. The 9MB region after the ACPI regions at 0x1f70 however looks promising given that the macine reports the stolen memory size to be 8MB. Looking at the PGTBL_CTL register, the GTT entries are at offset 0x1fee0, and given that the GTT entries occupy 128KB, it looks like the stolen memory could start at 0x1f70 and the GTT entries would occupy the last 128KB of the stolen memory. After some more digging through chipset documentation, I've determined the BIOS first allocates space for something called TSEG (something to do with SMM) from the top of memory, and then it allocates the graphics stolen memory below that. Accordind to the chipset documentation TSEG has a fixed size of 1MB on 855. So that explains the top 1MB in the e820 region. And it also confirms that the GTT entries are in fact at the end of the the stolen memory region. Derive the stolen memory base address on gen2 the same as the BIOS does (TOM-TSEG_SIZE-stolen_size). There are a few differences between the registers on various gen2 chipsets, so a few different codepaths are required. 865G is again bit more special since it seems to support enough memory to hit 4GB address space issues. This means the PCI allocations will also affect the location of the stolen memory. Fortunately there appears to be the TOUD register which may give us the correct answer directly. But the chipset docs are a bit unclear, so I'm not 100% sure that the graphics stolen memory is always the last thing the BIOS steals. Someone would need to verify it on a real system. I tested this on the my 855 machine, and so far everything looks peachy. v2: Rewrite to use the TOM-TSEG_SIZE-stolen_size and TOUD methods Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- arch/x86/kernel/early-quirks.c | 139 + include/drm/i915_drm.h | 18 ++ 2 files changed, 157 insertions(+) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index fddd4d0..66357bf 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -247,6 +247,121 @@ static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_s #define MB(x) (KB (KB (x))) #define GB(x) (MB (KB (x))) +/* FIXME is this actually correct for 830? */ +static size_t __init i830_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I830_ESMRAMC); + + if (!(tmp & TSEG_ENABLE)) + return 0; + + switch (tmp & TSEG_SIZE_MASK) { + case TSEG_SIZE_512K: + return KB(512); + case TSEG_SIZE_1M: + return MB(1); + default: + WARN_ON(1); + return 0; + } +} + +static size_t __init i845_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I845_ESMRAMC); + + if (!(tmp & TSEG_ENABLE)) + return 0; + + switch (tmp & TSEG_SIZE_MASK) { + case TSEG_SIZE_512K: + return KB(512); + case TSEG_SIZE_1M: + return MB(1); + default: + WARN_ON(1); + return 0; + } +} + +static size_t __init i85x_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC); + + if (!(tmp & TSEG_ENABLE)) + return 0; + + return MB(1); +} + +/* FIXME is this actually correct for 830? */ +static size_t __init i830_mem_size(void) +{ + return read_pci_config_byte(0, 0, 0, I830_DRB3) * MB(32); +} + +static size_t __init i85x_mem_size(void) +{ + return read_pci_config_byte(0, 0, 1, I85X_DRB3) * MB(32);
[PATCH 1/6] x86: Add vfunc for Intel graphics stolen memory base address
From: Ville Syrjälä For gen2 devices we're going to need another way to determine the stolen memory base address. Make that into a vfunc as well. Also drop the bogus inline keyword from gen8_stolen_size(). Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- arch/x86/kernel/early-quirks.c | 77 ++ 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index bc4a088..fddd4d0 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -228,7 +228,7 @@ static void __init intel_remapping_check(int num, int slot, int func) * * And yes, so far on current devices the base addr is always under 4G. */ -static u32 __init intel_stolen_base(int num, int slot, int func) +static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_size) { u32 base; @@ -313,7 +313,7 @@ static size_t __init gen6_stolen_size(int num, int slot, int func) return gmch_ctrl << 25; /* 32 MB units */ } -static inline size_t gen8_stolen_size(int num, int slot, int func) +static size_t gen8_stolen_size(int num, int slot, int func) { u16 gmch_ctrl; @@ -323,31 +323,50 @@ static inline size_t gen8_stolen_size(int num, int slot, int func) return gmch_ctrl << 25; /* 32 MB units */ } -typedef size_t (*stolen_size_fn)(int num, int slot, int func); + +struct intel_stolen_funcs { + size_t (*size)(int num, int slot, int func); + u32 (*base)(int num, int slot, int func, size_t size); +}; + +static const struct intel_stolen_funcs gen3_stolen_funcs = { + .base = intel_stolen_base, + .size = gen3_stolen_size, +}; + +static const struct intel_stolen_funcs gen6_stolen_funcs = { + .base = intel_stolen_base, + .size = gen6_stolen_size, +}; + +static const struct intel_stolen_funcs gen8_stolen_funcs = { + .base = intel_stolen_base, + .size = gen8_stolen_size, +}; static struct pci_device_id intel_stolen_ids[] __initdata = { - INTEL_I915G_IDS(gen3_stolen_size), - INTEL_I915GM_IDS(gen3_stolen_size), - INTEL_I945G_IDS(gen3_stolen_size), - INTEL_I945GM_IDS(gen3_stolen_size), - INTEL_VLV_M_IDS(gen6_stolen_size), - INTEL_VLV_D_IDS(gen6_stolen_size), - INTEL_PINEVIEW_IDS(gen3_stolen_size), - INTEL_I965G_IDS(gen3_stolen_size), - INTEL_G33_IDS(gen3_stolen_size), - INTEL_I965GM_IDS(gen3_stolen_size), - INTEL_GM45_IDS(gen3_stolen_size), - INTEL_G45_IDS(gen3_stolen_size), - INTEL_IRONLAKE_D_IDS(gen3_stolen_size), - INTEL_IRONLAKE_M_IDS(gen3_stolen_size), - INTEL_SNB_D_IDS(gen6_stolen_size), - INTEL_SNB_M_IDS(gen6_stolen_size), - INTEL_IVB_M_IDS(gen6_stolen_size), - INTEL_IVB_D_IDS(gen6_stolen_size), - INTEL_HSW_D_IDS(gen6_stolen_size), - INTEL_HSW_M_IDS(gen6_stolen_size), - INTEL_BDW_M_IDS(gen8_stolen_size), - INTEL_BDW_D_IDS(gen8_stolen_size) + INTEL_I915G_IDS(_stolen_funcs), + INTEL_I915GM_IDS(_stolen_funcs), + INTEL_I945G_IDS(_stolen_funcs), + INTEL_I945GM_IDS(_stolen_funcs), + INTEL_VLV_M_IDS(_stolen_funcs), + INTEL_VLV_D_IDS(_stolen_funcs), + INTEL_PINEVIEW_IDS(_stolen_funcs), + INTEL_I965G_IDS(_stolen_funcs), + INTEL_G33_IDS(_stolen_funcs), + INTEL_I965GM_IDS(_stolen_funcs), + INTEL_GM45_IDS(_stolen_funcs), + INTEL_G45_IDS(_stolen_funcs), + INTEL_IRONLAKE_D_IDS(_stolen_funcs), + INTEL_IRONLAKE_M_IDS(_stolen_funcs), + INTEL_SNB_D_IDS(_stolen_funcs), + INTEL_SNB_M_IDS(_stolen_funcs), + INTEL_IVB_M_IDS(_stolen_funcs), + INTEL_IVB_D_IDS(_stolen_funcs), + INTEL_HSW_D_IDS(_stolen_funcs), + INTEL_HSW_M_IDS(_stolen_funcs), + INTEL_BDW_M_IDS(_stolen_funcs), + INTEL_BDW_D_IDS(_stolen_funcs) }; static void __init intel_graphics_stolen(int num, int slot, int func) @@ -364,10 +383,10 @@ static void __init intel_graphics_stolen(int num, int slot, int func) for (i = 0; i < ARRAY_SIZE(intel_stolen_ids); i++) { if (intel_stolen_ids[i].device == device) { - stolen_size_fn stolen_size = - (stolen_size_fn)intel_stolen_ids[i].driver_data; - size = stolen_size(num, slot, func); - start = intel_stolen_base(num, slot, func); + const struct intel_stolen_funcs *stolen_funcs = + (const struct intel_stolen_funcs *)intel_stolen_ids[i].driver_data; + size = stolen_funcs->size(num, slot, func); + start = stolen_funcs->base(num, slot, func, size); if (size && start) { /* Mark this space as reserved */
[PATCH 3/6] x86: Print the Intel graphcis stolen memory range
From: Ville Syrjälä Print an informative message when reserving the graphics stolen memory region in the early quirk. Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä --- arch/x86/kernel/early-quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 66357bf..d15e087 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -527,6 +527,8 @@ static void __init intel_graphics_stolen(int num, int slot, int func) size = stolen_funcs->size(num, slot, func); start = stolen_funcs->base(num, slot, func, size); if (size && start) { + printk(KERN_INFO "Reserving Intel graphics stolen memory at 0x%x-0x%x\n", + start, start + (u32)size - 1); /* Mark this space as reserved */ e820_add_region(start, size, E820_RESERVED); sanitize_e820_map(e820.map, -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/6] x86: Print the Intel graphcis stolen memory range
From: Ville Syrjälä ville.syrj...@linux.intel.com Print an informative message when reserving the graphics stolen memory region in the early quirk. Cc: Thomas Gleixner t...@linutronix.de Cc: Ingo Molnar mi...@redhat.com Cc: H. Peter Anvin h...@zytor.com Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- arch/x86/kernel/early-quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 66357bf..d15e087 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -527,6 +527,8 @@ static void __init intel_graphics_stolen(int num, int slot, int func) size = stolen_funcs-size(num, slot, func); start = stolen_funcs-base(num, slot, func, size); if (size start) { + printk(KERN_INFO Reserving Intel graphics stolen memory at 0x%x-0x%x\n, + start, start + (u32)size - 1); /* Mark this space as reserved */ e820_add_region(start, size, E820_RESERVED); sanitize_e820_map(e820.map, -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/6] x86: Add vfunc for Intel graphics stolen memory base address
From: Ville Syrjälä ville.syrj...@linux.intel.com For gen2 devices we're going to need another way to determine the stolen memory base address. Make that into a vfunc as well. Also drop the bogus inline keyword from gen8_stolen_size(). Cc: Thomas Gleixner t...@linutronix.de Cc: Ingo Molnar mi...@redhat.com Cc: H. Peter Anvin h...@zytor.com Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- arch/x86/kernel/early-quirks.c | 77 ++ 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index bc4a088..fddd4d0 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -228,7 +228,7 @@ static void __init intel_remapping_check(int num, int slot, int func) * * And yes, so far on current devices the base addr is always under 4G. */ -static u32 __init intel_stolen_base(int num, int slot, int func) +static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_size) { u32 base; @@ -313,7 +313,7 @@ static size_t __init gen6_stolen_size(int num, int slot, int func) return gmch_ctrl 25; /* 32 MB units */ } -static inline size_t gen8_stolen_size(int num, int slot, int func) +static size_t gen8_stolen_size(int num, int slot, int func) { u16 gmch_ctrl; @@ -323,31 +323,50 @@ static inline size_t gen8_stolen_size(int num, int slot, int func) return gmch_ctrl 25; /* 32 MB units */ } -typedef size_t (*stolen_size_fn)(int num, int slot, int func); + +struct intel_stolen_funcs { + size_t (*size)(int num, int slot, int func); + u32 (*base)(int num, int slot, int func, size_t size); +}; + +static const struct intel_stolen_funcs gen3_stolen_funcs = { + .base = intel_stolen_base, + .size = gen3_stolen_size, +}; + +static const struct intel_stolen_funcs gen6_stolen_funcs = { + .base = intel_stolen_base, + .size = gen6_stolen_size, +}; + +static const struct intel_stolen_funcs gen8_stolen_funcs = { + .base = intel_stolen_base, + .size = gen8_stolen_size, +}; static struct pci_device_id intel_stolen_ids[] __initdata = { - INTEL_I915G_IDS(gen3_stolen_size), - INTEL_I915GM_IDS(gen3_stolen_size), - INTEL_I945G_IDS(gen3_stolen_size), - INTEL_I945GM_IDS(gen3_stolen_size), - INTEL_VLV_M_IDS(gen6_stolen_size), - INTEL_VLV_D_IDS(gen6_stolen_size), - INTEL_PINEVIEW_IDS(gen3_stolen_size), - INTEL_I965G_IDS(gen3_stolen_size), - INTEL_G33_IDS(gen3_stolen_size), - INTEL_I965GM_IDS(gen3_stolen_size), - INTEL_GM45_IDS(gen3_stolen_size), - INTEL_G45_IDS(gen3_stolen_size), - INTEL_IRONLAKE_D_IDS(gen3_stolen_size), - INTEL_IRONLAKE_M_IDS(gen3_stolen_size), - INTEL_SNB_D_IDS(gen6_stolen_size), - INTEL_SNB_M_IDS(gen6_stolen_size), - INTEL_IVB_M_IDS(gen6_stolen_size), - INTEL_IVB_D_IDS(gen6_stolen_size), - INTEL_HSW_D_IDS(gen6_stolen_size), - INTEL_HSW_M_IDS(gen6_stolen_size), - INTEL_BDW_M_IDS(gen8_stolen_size), - INTEL_BDW_D_IDS(gen8_stolen_size) + INTEL_I915G_IDS(gen3_stolen_funcs), + INTEL_I915GM_IDS(gen3_stolen_funcs), + INTEL_I945G_IDS(gen3_stolen_funcs), + INTEL_I945GM_IDS(gen3_stolen_funcs), + INTEL_VLV_M_IDS(gen6_stolen_funcs), + INTEL_VLV_D_IDS(gen6_stolen_funcs), + INTEL_PINEVIEW_IDS(gen3_stolen_funcs), + INTEL_I965G_IDS(gen3_stolen_funcs), + INTEL_G33_IDS(gen3_stolen_funcs), + INTEL_I965GM_IDS(gen3_stolen_funcs), + INTEL_GM45_IDS(gen3_stolen_funcs), + INTEL_G45_IDS(gen3_stolen_funcs), + INTEL_IRONLAKE_D_IDS(gen3_stolen_funcs), + INTEL_IRONLAKE_M_IDS(gen3_stolen_funcs), + INTEL_SNB_D_IDS(gen6_stolen_funcs), + INTEL_SNB_M_IDS(gen6_stolen_funcs), + INTEL_IVB_M_IDS(gen6_stolen_funcs), + INTEL_IVB_D_IDS(gen6_stolen_funcs), + INTEL_HSW_D_IDS(gen6_stolen_funcs), + INTEL_HSW_M_IDS(gen6_stolen_funcs), + INTEL_BDW_M_IDS(gen8_stolen_funcs), + INTEL_BDW_D_IDS(gen8_stolen_funcs) }; static void __init intel_graphics_stolen(int num, int slot, int func) @@ -364,10 +383,10 @@ static void __init intel_graphics_stolen(int num, int slot, int func) for (i = 0; i ARRAY_SIZE(intel_stolen_ids); i++) { if (intel_stolen_ids[i].device == device) { - stolen_size_fn stolen_size = - (stolen_size_fn)intel_stolen_ids[i].driver_data; - size = stolen_size(num, slot, func); - start = intel_stolen_base(num, slot, func); + const struct intel_stolen_funcs *stolen_funcs = + (const struct intel_stolen_funcs *)intel_stolen_ids[i].driver_data; + size = stolen_funcs-size(num, slot, func); +
[PATCH v2 2/6] x86: Add Intel graphics stolen memory quirk for gen2 platforms
From: Ville Syrjälä ville.syrj...@linux.intel.com There isn't an explicit stolen memory base register on gen2. Some old comment in the i915 code suggests we should get it via max_low_pfn_mapped, but that's clearly a bad idea on my MGM. The e820 map in said machine looks like this: [0.00] BIOS-e820: [mem 0x-0x0009f7ff] usable [0.00] BIOS-e820: [mem 0x0009f800-0x0009] reserved [0.00] BIOS-e820: [mem 0x000ce000-0x000c] reserved [0.00] BIOS-e820: [mem 0x000dc000-0x000f] reserved [0.00] BIOS-e820: [mem 0x0010-0x1f6e] usable [0.00] BIOS-e820: [mem 0x1f6f-0x1f6f7fff] ACPI data [0.00] BIOS-e820: [mem 0x1f6f8000-0x1f6f] ACPI NVS [0.00] BIOS-e820: [mem 0x1f70-0x1fff] reserved [0.00] BIOS-e820: [mem 0xfec1-0xfec1] reserved [0.00] BIOS-e820: [mem 0xffb0-0xffbf] reserved [0.00] BIOS-e820: [mem 0xfff0-0x] reserved That makes max_low_pfn_mapped = 1f6f, so assuming our stolen memory would start there would place it on top of some ACPI memory regions. So not a good idea as already stated. The 9MB region after the ACPI regions at 0x1f70 however looks promising given that the macine reports the stolen memory size to be 8MB. Looking at the PGTBL_CTL register, the GTT entries are at offset 0x1fee0, and given that the GTT entries occupy 128KB, it looks like the stolen memory could start at 0x1f70 and the GTT entries would occupy the last 128KB of the stolen memory. After some more digging through chipset documentation, I've determined the BIOS first allocates space for something called TSEG (something to do with SMM) from the top of memory, and then it allocates the graphics stolen memory below that. Accordind to the chipset documentation TSEG has a fixed size of 1MB on 855. So that explains the top 1MB in the e820 region. And it also confirms that the GTT entries are in fact at the end of the the stolen memory region. Derive the stolen memory base address on gen2 the same as the BIOS does (TOM-TSEG_SIZE-stolen_size). There are a few differences between the registers on various gen2 chipsets, so a few different codepaths are required. 865G is again bit more special since it seems to support enough memory to hit 4GB address space issues. This means the PCI allocations will also affect the location of the stolen memory. Fortunately there appears to be the TOUD register which may give us the correct answer directly. But the chipset docs are a bit unclear, so I'm not 100% sure that the graphics stolen memory is always the last thing the BIOS steals. Someone would need to verify it on a real system. I tested this on the my 855 machine, and so far everything looks peachy. v2: Rewrite to use the TOM-TSEG_SIZE-stolen_size and TOUD methods Cc: Thomas Gleixner t...@linutronix.de Cc: Ingo Molnar mi...@redhat.com Cc: H. Peter Anvin h...@zytor.com Cc: x...@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- arch/x86/kernel/early-quirks.c | 139 + include/drm/i915_drm.h | 18 ++ 2 files changed, 157 insertions(+) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index fddd4d0..66357bf 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -247,6 +247,121 @@ static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_s #define MB(x) (KB (KB (x))) #define GB(x) (MB (KB (x))) +/* FIXME is this actually correct for 830? */ +static size_t __init i830_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I830_ESMRAMC); + + if (!(tmp TSEG_ENABLE)) + return 0; + + switch (tmp TSEG_SIZE_MASK) { + case TSEG_SIZE_512K: + return KB(512); + case TSEG_SIZE_1M: + return MB(1); + default: + WARN_ON(1); + return 0; + } +} + +static size_t __init i845_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I845_ESMRAMC); + + if (!(tmp TSEG_ENABLE)) + return 0; + + switch (tmp TSEG_SIZE_MASK) { + case TSEG_SIZE_512K: + return KB(512); + case TSEG_SIZE_1M: + return MB(1); + default: + WARN_ON(1); + return 0; + } +} + +static size_t __init i85x_tseg_size(void) +{ + u8 tmp = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC); + + if (!(tmp TSEG_ENABLE)) + return 0; + + return MB(1); +} + +/* FIXME is this actually correct for 830? */ +static size_t __init i830_mem_size(void) +{ + return read_pci_config_byte(0, 0, 0, I830_DRB3) * MB(32); +} + +static
[PATCH] drm/i915: Take modeset locks around intel_modeset_setup_hw_state()
From: Ville Syrjälä Some lower level things get angry if we don't have modeset locks during intel_modeset_setup_hw_state(). Actually the resume and lid_notify codepaths alreday hold the locks, but the init codepath doesn't, so fix that. Signed-off-by: Ville Syrjälä --- Totally untested, but looks correct to me. drivers/gpu/drm/i915/intel_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 080f6fd..114db51 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11046,7 +11046,9 @@ void intel_modeset_gem_init(struct drm_device *dev) intel_setup_overlay(dev); + drm_modeset_lock_all(dev); intel_modeset_setup_hw_state(dev, false); + drm_modeset_unlock_all(dev); } void intel_modeset_cleanup(struct drm_device *dev) -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] drm/i915: Take modeset locks around intel_modeset_setup_hw_state()
From: Ville Syrjälä ville.syrj...@linux.intel.com Some lower level things get angry if we don't have modeset locks during intel_modeset_setup_hw_state(). Actually the resume and lid_notify codepaths alreday hold the locks, but the init codepath doesn't, so fix that. Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- Totally untested, but looks correct to me. drivers/gpu/drm/i915/intel_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 080f6fd..114db51 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11046,7 +11046,9 @@ void intel_modeset_gem_init(struct drm_device *dev) intel_setup_overlay(dev); + drm_modeset_lock_all(dev); intel_modeset_setup_hw_state(dev, false); + drm_modeset_unlock_all(dev); } void intel_modeset_cleanup(struct drm_device *dev) -- 1.8.3.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] x86: Add reboot quirk for Dell Latitude E5410
From: Ville Syrjälä Dell Latitude E5410 needs reboot=pci to actually reboot. Signed-off-by: Ville Syrjälä --- arch/x86/kernel/reboot.c | 8 1 file changed, 8 insertions(+) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index e643e74..7e920bf 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -326,6 +326,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6320"), }, }, + { /* Handle problems with rebooting on the Latitude E5410. */ + .callback = set_pci_reboot, + .ident = "Dell Latitude E5410", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5410"), + }, + }, { /* Handle problems with rebooting on the Latitude E5420. */ .callback = set_pci_reboot, .ident = "Dell Latitude E5420", -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] x86: Add reboot quirk for Dell Latitude E5410
From: Ville Syrjälä ville.syrj...@linux.intel.com Dell Latitude E5410 needs reboot=pci to actually reboot. Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- arch/x86/kernel/reboot.c | 8 1 file changed, 8 insertions(+) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index e643e74..7e920bf 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -326,6 +326,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, Latitude E6320), }, }, + { /* Handle problems with rebooting on the Latitude E5410. */ + .callback = set_pci_reboot, + .ident = Dell Latitude E5410, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, Dell Inc.), + DMI_MATCH(DMI_PRODUCT_NAME, Latitude E5410), + }, + }, { /* Handle problems with rebooting on the Latitude E5420. */ .callback = set_pci_reboot, .ident = Dell Latitude E5420, -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[RFC][PATCH] drm/i915: Fix VGA handling using stop_machine() or mmio
From: Ville Syrjälä We have several problems with out VGA handling: - We try to use the GMCH control VGA disable bit even though it may be locked - If we manage to disable VGA throuh GMCH control, we're no longer able to correctly disable the VGA plane - Taking part in the VGA arbitration is too expensive for X [1] So let's treat the GMCH control VGA disable bit as read-only and leave it for the BIOS to set, as it was intended. To disable VGA we will use the VGA misc register, and to disable VGA IO we will disable IO space completely via the PCI command register. But we still need VGA register access during resume (and possibly during lid event on insane BIOSen) to disable the VGA plane. Also we need to re-disable VGA memory decode via the VGA misc register on resume. Luckily up to gen4, VGA registers can be accessed through MMIO. Unfortunately from gen5 onwards only the legacy VGA IO port range works. So on gen5+ we still need IO space to be enabled during those few special moments when we need to access VGA registers. We still want to opt out of VGA arbitration on gen5+, so we have keep IO space disabled most of the time. And when we do need to poke at VGA registers, we enable IO space briefly while no one is looking. To guarantee that no one is looking we will use stop_machine(). [1] http://lists.x.org/archives/xorg-devel/2013-September/037763.html Cc: Alex Williamson Cc: Chris Wilson Cc: Dave Airlie Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/i915_dma.c | 37 +- drivers/gpu/drm/i915/i915_suspend.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 247 +-- drivers/gpu/drm/i915/intel_drv.h | 1 - 4 files changed, 215 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index be5120f7..0fd86c2 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1225,19 +1225,6 @@ intel_teardown_mchbar(struct drm_device *dev) release_resource(_priv->mch_res); } -/* true = enable decode, false = disable decoder */ -static unsigned int i915_vga_set_decode(void *cookie, bool state) -{ - struct drm_device *dev = cookie; - - intel_modeset_vga_set_state(dev, state); - if (state) - return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | - VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; - else - return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; -} - static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) { struct drm_device *dev = pci_get_drvdata(pdev); @@ -1283,25 +1270,11 @@ static int i915_load_modeset_init(struct drm_device *dev) if (ret) DRM_INFO("failed to find VBIOS tables\n"); - /* If we have > 1 VGA cards, then we need to arbitrate access -* to the common VGA resources. -* -* If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA), -* then we do not take part in VGA arbitration and the -* vga_client_register() fails with -ENODEV. -*/ - if (!HAS_PCH_SPLIT(dev)) { - ret = vga_client_register(dev->pdev, dev, NULL, - i915_vga_set_decode); - if (ret && ret != -ENODEV) - goto out; - } - intel_register_dsm_handler(); ret = vga_switcheroo_register_client(dev->pdev, _switcheroo_ops, false); if (ret) - goto cleanup_vga_client; + goto out; /* Initialise stolen first so that we may reserve preallocated * objects for the BIOS to KMS transition. @@ -1352,10 +1325,13 @@ static int i915_load_modeset_init(struct drm_device *dev) intel_fbdev_initial_config(dev); /* +* Disable VGA IO and memory, and +* tell the arbiter to ignore us. +* * Must do this after fbcon init so that * vgacon_save_screen() works during the handover. */ - i915_disable_vga_mem(dev); + intel_modeset_vga_set_state(dev, false); /* Only enable hotplug handling once the fbdev is fully set up. */ dev_priv->enable_hotplug_processing = true; @@ -1377,8 +1353,6 @@ cleanup_gem_stolen: i915_gem_cleanup_stolen(dev); cleanup_vga_switcheroo: vga_switcheroo_unregister_client(dev->pdev); -cleanup_vga_client: - vga_client_register(dev->pdev, NULL, NULL, NULL); out: return ret; } @@ -1749,7 +1723,6 @@ int i915_driver_unload(struct drm_device *dev) } vga_switcheroo_unregister_client(dev->pdev); - vga_client_register(dev->pdev, NULL, NULL, NULL); } /* Free error state after interrupts are fully disabled. */ diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 70db618..c5e8958 100644 ---
[RFC][PATCH] drm/i915: Fix VGA handling using stop_machine() or mmio
From: Ville Syrjälä ville.syrj...@linux.intel.com We have several problems with out VGA handling: - We try to use the GMCH control VGA disable bit even though it may be locked - If we manage to disable VGA throuh GMCH control, we're no longer able to correctly disable the VGA plane - Taking part in the VGA arbitration is too expensive for X [1] So let's treat the GMCH control VGA disable bit as read-only and leave it for the BIOS to set, as it was intended. To disable VGA we will use the VGA misc register, and to disable VGA IO we will disable IO space completely via the PCI command register. But we still need VGA register access during resume (and possibly during lid event on insane BIOSen) to disable the VGA plane. Also we need to re-disable VGA memory decode via the VGA misc register on resume. Luckily up to gen4, VGA registers can be accessed through MMIO. Unfortunately from gen5 onwards only the legacy VGA IO port range works. So on gen5+ we still need IO space to be enabled during those few special moments when we need to access VGA registers. We still want to opt out of VGA arbitration on gen5+, so we have keep IO space disabled most of the time. And when we do need to poke at VGA registers, we enable IO space briefly while no one is looking. To guarantee that no one is looking we will use stop_machine(). [1] http://lists.x.org/archives/xorg-devel/2013-September/037763.html Cc: Alex Williamson alex.william...@redhat.com Cc: Chris Wilson ch...@chris-wilson.co.uk Cc: Dave Airlie airl...@redhat.com Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- drivers/gpu/drm/i915/i915_dma.c | 37 +- drivers/gpu/drm/i915/i915_suspend.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 247 +-- drivers/gpu/drm/i915/intel_drv.h | 1 - 4 files changed, 215 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index be5120f7..0fd86c2 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1225,19 +1225,6 @@ intel_teardown_mchbar(struct drm_device *dev) release_resource(dev_priv-mch_res); } -/* true = enable decode, false = disable decoder */ -static unsigned int i915_vga_set_decode(void *cookie, bool state) -{ - struct drm_device *dev = cookie; - - intel_modeset_vga_set_state(dev, state); - if (state) - return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | - VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; - else - return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; -} - static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) { struct drm_device *dev = pci_get_drvdata(pdev); @@ -1283,25 +1270,11 @@ static int i915_load_modeset_init(struct drm_device *dev) if (ret) DRM_INFO(failed to find VBIOS tables\n); - /* If we have 1 VGA cards, then we need to arbitrate access -* to the common VGA resources. -* -* If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA), -* then we do not take part in VGA arbitration and the -* vga_client_register() fails with -ENODEV. -*/ - if (!HAS_PCH_SPLIT(dev)) { - ret = vga_client_register(dev-pdev, dev, NULL, - i915_vga_set_decode); - if (ret ret != -ENODEV) - goto out; - } - intel_register_dsm_handler(); ret = vga_switcheroo_register_client(dev-pdev, i915_switcheroo_ops, false); if (ret) - goto cleanup_vga_client; + goto out; /* Initialise stolen first so that we may reserve preallocated * objects for the BIOS to KMS transition. @@ -1352,10 +1325,13 @@ static int i915_load_modeset_init(struct drm_device *dev) intel_fbdev_initial_config(dev); /* +* Disable VGA IO and memory, and +* tell the arbiter to ignore us. +* * Must do this after fbcon init so that * vgacon_save_screen() works during the handover. */ - i915_disable_vga_mem(dev); + intel_modeset_vga_set_state(dev, false); /* Only enable hotplug handling once the fbdev is fully set up. */ dev_priv-enable_hotplug_processing = true; @@ -1377,8 +1353,6 @@ cleanup_gem_stolen: i915_gem_cleanup_stolen(dev); cleanup_vga_switcheroo: vga_switcheroo_unregister_client(dev-pdev); -cleanup_vga_client: - vga_client_register(dev-pdev, NULL, NULL, NULL); out: return ret; } @@ -1749,7 +1723,6 @@ int i915_driver_unload(struct drm_device *dev) } vga_switcheroo_unregister_client(dev-pdev); - vga_client_register(dev-pdev, NULL, NULL, NULL); } /* Free error state after interrupts are fully disabled. */ diff --git
Re: regression in linux 3.7 - fan speed at 100% after suspend/resume at 100%
Roberto Oppedisano gmail.com> writes: > > Hello, > with recent kernels after a suspend/resume cycle on my laptop (HP > 6730b) the fans stays at full speed. I too have been hit by this regression w/ a HP Compaq NC6000 laptop. >From what I can tell 3.7.x gets confused about trip points after resume. Based on the information in sysfs, it seems to always think that the CPU temp > 65C, when in fact it's usually 40C or so. Loading the CPU enough to rise the temperature past the trip point where the kernel thinks we're at seems to re-synchronize the kernel's reality with the firmware's reality. On a few occasions however the fan did stop, but the trip points were still confused the same way. So what happened is that the fan didn't come back to life until I hit the next higher trip point at 80C. Under normal conditions I've never reached the 80C trip point on this laptop. I also tried this tree: git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git next $ git describe v3.8-rc2-72-gf5b6d45 Sadly I must report that it's even worse than 3.7. Even without any suspend/resume cycles, the system gets confused. When I heat up the CPU the fan comes on correctly and speeds up as the temperature rises. Unfortunately when the temperature drops the fan doesn't slow down at all. So once I hit a high trip point the fan stays at that speed forever. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: regression in linux 3.7 - fan speed at 100% after suspend/resume at 100%
Roberto Oppedisano roberto.oppedisano at gmail.com writes: Hello, with recent kernels after a suspend/resume cycle on my laptop (HP 6730b) the fans stays at full speed. I too have been hit by this regression w/ a HP Compaq NC6000 laptop. From what I can tell 3.7.x gets confused about trip points after resume. Based on the information in sysfs, it seems to always think that the CPU temp 65C, when in fact it's usually 40C or so. Loading the CPU enough to rise the temperature past the trip point where the kernel thinks we're at seems to re-synchronize the kernel's reality with the firmware's reality. On a few occasions however the fan did stop, but the trip points were still confused the same way. So what happened is that the fan didn't come back to life until I hit the next higher trip point at 80C. Under normal conditions I've never reached the 80C trip point on this laptop. I also tried this tree: git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git next $ git describe v3.8-rc2-72-gf5b6d45 Sadly I must report that it's even worse than 3.7. Even without any suspend/resume cycles, the system gets confused. When I heat up the CPU the fan comes on correctly and speeds up as the temperature rises. Unfortunately when the temperature drops the fan doesn't slow down at all. So once I hit a high trip point the fan stays at that speed forever. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] x86: Add support for 64bit get_user() on x86-32
From: Ville Syrjälä Implement __get_user_8() for x86-32. It will return the 64bit result in edx:eax register pair, and ecx is used to pass in the address and return the error value. For consistency, change the register assignment for all other __get_user_x() variants, so that address is passed in ecx/rcx, the error value is returned in ecx/rcx, and eax/rax contains the actual value. This is a partial refresh of a patch [1] by Jamie Lokier from 2004. Only the minimal changes to implement 64bit get_user() were picked from the original patch. [1] http://article.gmane.org/gmane.linux.kernel/198823 Cc: Jamie Lokier Signed-off-by: Ville Syrjälä --- arch/x86/include/asm/uaccess.h | 17 ++-- arch/x86/kernel/i386_ksyms_32.c |1 + arch/x86/lib/getuser.S | 82 ++ 3 files changed, 69 insertions(+), 31 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 7ccf8d1..3f4387e 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -127,7 +127,7 @@ extern int __get_user_bad(void); #define __get_user_x(size, ret, x, ptr) \ asm volatile("call __get_user_" #size \ -: "=a" (ret), "=d" (x) \ +: "=c" (ret), "=a" (x) \ : "0" (ptr)) \ /* Careful: we have to cast the result to the type of the pointer @@ -151,8 +151,11 @@ extern int __get_user_bad(void); * On error, the variable @x is set to zero. */ #ifdef CONFIG_X86_32 -#define __get_user_8(__ret_gu, __val_gu, ptr) \ - __get_user_x(X, __ret_gu, __val_gu, ptr) +#define __get_user_8(ret, x, ptr)\ + asm volatile("call __get_user_8" \ +: "=c" (ret), "=A" (x) \ +: "0" (ptr)) \ + #else #define __get_user_8(__ret_gu, __val_gu, ptr) \ __get_user_x(8, __ret_gu, __val_gu, ptr) @@ -162,6 +165,7 @@ extern int __get_user_bad(void); ({ \ int __ret_gu; \ unsigned long __val_gu; \ + unsigned long long __val_gu8; \ __chk_user_ptr(ptr);\ might_fault(); \ switch (sizeof(*(ptr))) { \ @@ -175,13 +179,16 @@ extern int __get_user_bad(void); __get_user_x(4, __ret_gu, __val_gu, ptr); \ break; \ case 8: \ - __get_user_8(__ret_gu, __val_gu, ptr); \ + __get_user_8(__ret_gu, __val_gu8, ptr); \ break; \ default:\ __get_user_x(X, __ret_gu, __val_gu, ptr); \ break; \ } \ - (x) = (__typeof__(*(ptr)))__val_gu; \ + if (sizeof(*(ptr)) == 8)\ + (x) = (__typeof__(*(ptr)))__val_gu8;\ + else\ + (x) = (__typeof__(*(ptr)))__val_gu; \ __ret_gu; \ }) diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c index 9c3bd4a..0fa6912 100644 --- a/arch/x86/kernel/i386_ksyms_32.c +++ b/arch/x86/kernel/i386_ksyms_32.c @@ -26,6 +26,7 @@ EXPORT_SYMBOL(csum_partial_copy_generic); EXPORT_SYMBOL(__get_user_1); EXPORT_SYMBOL(__get_user_2); EXPORT_SYMBOL(__get_user_4); +EXPORT_SYMBOL(__get_user_8); EXPORT_SYMBOL(__put_user_1); EXPORT_SYMBOL(__put_user_2); diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S index 156b9c8..38afef0 100644 --- a/arch/x86/lib/getuser.S +++ b/arch/x86/lib/getuser.S @@ -14,12 +14,11 @@ /* * __get_user_X * - * Inputs: %[r|e]ax contains the address. - * The register is modified, but all changes are undone - * before returning because the C code doesn't know about it. + * Inputs: %[r|e]cx contains the address. * - * Outputs:%[r|e]ax is error code (0 or -EFAULT) - * %[r|e]dx contains zero-extended value + * Outputs:%[r|e]cx is error code (0 or -EFAULT) + * %[r|e]ax contains zero-extended value + *
[PATCH] x86: Add support for 64bit get_user() on x86-32
From: Ville Syrjälä ville.syrj...@linux.intel.com Implement __get_user_8() for x86-32. It will return the 64bit result in edx:eax register pair, and ecx is used to pass in the address and return the error value. For consistency, change the register assignment for all other __get_user_x() variants, so that address is passed in ecx/rcx, the error value is returned in ecx/rcx, and eax/rax contains the actual value. This is a partial refresh of a patch [1] by Jamie Lokier from 2004. Only the minimal changes to implement 64bit get_user() were picked from the original patch. [1] http://article.gmane.org/gmane.linux.kernel/198823 Cc: Jamie Lokier ja...@shareable.org Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com --- arch/x86/include/asm/uaccess.h | 17 ++-- arch/x86/kernel/i386_ksyms_32.c |1 + arch/x86/lib/getuser.S | 82 ++ 3 files changed, 69 insertions(+), 31 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 7ccf8d1..3f4387e 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -127,7 +127,7 @@ extern int __get_user_bad(void); #define __get_user_x(size, ret, x, ptr) \ asm volatile(call __get_user_ #size \ -: =a (ret), =d (x) \ +: =c (ret), =a (x) \ : 0 (ptr)) \ /* Careful: we have to cast the result to the type of the pointer @@ -151,8 +151,11 @@ extern int __get_user_bad(void); * On error, the variable @x is set to zero. */ #ifdef CONFIG_X86_32 -#define __get_user_8(__ret_gu, __val_gu, ptr) \ - __get_user_x(X, __ret_gu, __val_gu, ptr) +#define __get_user_8(ret, x, ptr)\ + asm volatile(call __get_user_8 \ +: =c (ret), =A (x) \ +: 0 (ptr)) \ + #else #define __get_user_8(__ret_gu, __val_gu, ptr) \ __get_user_x(8, __ret_gu, __val_gu, ptr) @@ -162,6 +165,7 @@ extern int __get_user_bad(void); ({ \ int __ret_gu; \ unsigned long __val_gu; \ + unsigned long long __val_gu8; \ __chk_user_ptr(ptr);\ might_fault(); \ switch (sizeof(*(ptr))) { \ @@ -175,13 +179,16 @@ extern int __get_user_bad(void); __get_user_x(4, __ret_gu, __val_gu, ptr); \ break; \ case 8: \ - __get_user_8(__ret_gu, __val_gu, ptr); \ + __get_user_8(__ret_gu, __val_gu8, ptr); \ break; \ default:\ __get_user_x(X, __ret_gu, __val_gu, ptr); \ break; \ } \ - (x) = (__typeof__(*(ptr)))__val_gu; \ + if (sizeof(*(ptr)) == 8)\ + (x) = (__typeof__(*(ptr)))__val_gu8;\ + else\ + (x) = (__typeof__(*(ptr)))__val_gu; \ __ret_gu; \ }) diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c index 9c3bd4a..0fa6912 100644 --- a/arch/x86/kernel/i386_ksyms_32.c +++ b/arch/x86/kernel/i386_ksyms_32.c @@ -26,6 +26,7 @@ EXPORT_SYMBOL(csum_partial_copy_generic); EXPORT_SYMBOL(__get_user_1); EXPORT_SYMBOL(__get_user_2); EXPORT_SYMBOL(__get_user_4); +EXPORT_SYMBOL(__get_user_8); EXPORT_SYMBOL(__put_user_1); EXPORT_SYMBOL(__put_user_2); diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S index 156b9c8..38afef0 100644 --- a/arch/x86/lib/getuser.S +++ b/arch/x86/lib/getuser.S @@ -14,12 +14,11 @@ /* * __get_user_X * - * Inputs: %[r|e]ax contains the address. - * The register is modified, but all changes are undone - * before returning because the C code doesn't know about it. + * Inputs: %[r|e]cx contains the address. * - * Outputs:%[r|e]ax is error code (0 or -EFAULT) - * %[r|e]dx contains zero-extended value + * Outputs:%[r|e]cx is error code (0 or -EFAULT) + *
[PATCH] w1-gpio: Add GPIO w1 bus master driver (v3)
Add a GPIO 1-wire bus master driver. The driver used the GPIO API to control the wire and the GPIO pin can be specified using platform data similar to i2c-gpio. The driver was tested with AT91SAM9260 + DS2401. Signed-off-by: Ville Syrjala <[EMAIL PROTECTED]> --- Changes from version 2 to version 3: * Use platform_driver_probe() instead of platform_driver_register(). * Remove useless address operators from function pointer assignments. Documentation/w1/masters/00-INDEX |2 + Documentation/w1/masters/w1-gpio | 33 ++ drivers/w1/masters/Kconfig| 10 +++ drivers/w1/masters/Makefile |1 + drivers/w1/masters/w1-gpio.c | 124 + include/linux/w1-gpio.h | 23 +++ 6 files changed, 193 insertions(+), 0 deletions(-) create mode 100644 Documentation/w1/masters/w1-gpio create mode 100644 drivers/w1/masters/w1-gpio.c create mode 100644 include/linux/w1-gpio.h diff --git a/Documentation/w1/masters/00-INDEX b/Documentation/w1/masters/00-INDEX index 752613c..7b0ceaa 100644 --- a/Documentation/w1/masters/00-INDEX +++ b/Documentation/w1/masters/00-INDEX @@ -4,3 +4,5 @@ ds2482 - The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses. ds2490 - The Maxim/Dallas Semiconductor DS2490 builds USB <-> W1 bridges. +w1-gpio + - GPIO 1-wire bus master driver. diff --git a/Documentation/w1/masters/w1-gpio b/Documentation/w1/masters/w1-gpio new file mode 100644 index 000..af5d3b4 --- /dev/null +++ b/Documentation/w1/masters/w1-gpio @@ -0,0 +1,33 @@ +Kernel driver w1-gpio += + +Author: Ville Syrjala <[EMAIL PROTECTED]> + + +Description +--- + +GPIO 1-wire bus master driver. The driver uses the GPIO API to control the +wire and the GPIO pin can be specified using platform data. + + +Example (mach-at91) +--- + +#include + +static struct w1_gpio_platform_data foo_w1_gpio_pdata = { + .pin= AT91_PIN_PB20, + .is_open_drain = 1, +}; + +static struct platform_device foo_w1_device = { + .name = "w1-gpio", + .id = -1, + .dev.platform_data = _w1_gpio_pdata, +}; + +... + at91_set_GPIO_periph(foo_w1_gpio_pdata.pin, 1); + at91_set_multi_drive(foo_w1_gpio_pdata.pin, 1); + platform_device_register(_w1_device); diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 8236d44..c449309 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -42,5 +42,15 @@ config W1_MASTER_DS1WM in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like hx4700. +config W1_MASTER_GPIO + tristate "GPIO 1-wire busmaster" + depends on GENERIC_GPIO + help + Say Y here if you want to communicate with your 1-wire devices using + GPIO pins. This driver uses the GPIO API to control the wire. + + This support is also available as a module. If so, the module + will be called w1-gpio.ko. + endmenu diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 11551b3..1420b5b 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o +obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c new file mode 100644 index 000..9e1138a --- /dev/null +++ b/drivers/w1/masters/w1-gpio.c @@ -0,0 +1,124 @@ +/* + * w1-gpio - GPIO w1 bus master driver + * + * Copyright (C) 2007 Ville Syrjala <[EMAIL PROTECTED]> + * + * 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. + */ + +#include +#include +#include +#include + +#include "../w1.h" +#include "../w1_int.h" + +#include + +static void w1_gpio_write_bit_dir(void *data, u8 bit) +{ + struct w1_gpio_platform_data *pdata = data; + + if (bit) + gpio_direction_input(pdata->pin); + else + gpio_direction_output(pdata->pin, 0); +} + +static void w1_gpio_write_bit_val(void *data, u8 bit) +{ + struct w1_gpio_platform_data *pdata = data; + + gpio_set_value(pdata->pin, bit); +} + +static u8 w1_gpio_read_bit(void *data) +{ + struct w1_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata->pin); +} + +static int __init w1_gpio_probe(struct platform_device *pdev) +{ + struct w1_bus_master *master; + struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; + int err; + + if (!pdata) + return -ENXIO; + +
[PATCH] w1-gpio: Add GPIO w1 bus master driver (v3)
Add a GPIO 1-wire bus master driver. The driver used the GPIO API to control the wire and the GPIO pin can be specified using platform data similar to i2c-gpio. The driver was tested with AT91SAM9260 + DS2401. Signed-off-by: Ville Syrjala [EMAIL PROTECTED] --- Changes from version 2 to version 3: * Use platform_driver_probe() instead of platform_driver_register(). * Remove useless address operators from function pointer assignments. Documentation/w1/masters/00-INDEX |2 + Documentation/w1/masters/w1-gpio | 33 ++ drivers/w1/masters/Kconfig| 10 +++ drivers/w1/masters/Makefile |1 + drivers/w1/masters/w1-gpio.c | 124 + include/linux/w1-gpio.h | 23 +++ 6 files changed, 193 insertions(+), 0 deletions(-) create mode 100644 Documentation/w1/masters/w1-gpio create mode 100644 drivers/w1/masters/w1-gpio.c create mode 100644 include/linux/w1-gpio.h diff --git a/Documentation/w1/masters/00-INDEX b/Documentation/w1/masters/00-INDEX index 752613c..7b0ceaa 100644 --- a/Documentation/w1/masters/00-INDEX +++ b/Documentation/w1/masters/00-INDEX @@ -4,3 +4,5 @@ ds2482 - The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses. ds2490 - The Maxim/Dallas Semiconductor DS2490 builds USB - W1 bridges. +w1-gpio + - GPIO 1-wire bus master driver. diff --git a/Documentation/w1/masters/w1-gpio b/Documentation/w1/masters/w1-gpio new file mode 100644 index 000..af5d3b4 --- /dev/null +++ b/Documentation/w1/masters/w1-gpio @@ -0,0 +1,33 @@ +Kernel driver w1-gpio += + +Author: Ville Syrjala [EMAIL PROTECTED] + + +Description +--- + +GPIO 1-wire bus master driver. The driver uses the GPIO API to control the +wire and the GPIO pin can be specified using platform data. + + +Example (mach-at91) +--- + +#include linux/w1-gpio.h + +static struct w1_gpio_platform_data foo_w1_gpio_pdata = { + .pin= AT91_PIN_PB20, + .is_open_drain = 1, +}; + +static struct platform_device foo_w1_device = { + .name = w1-gpio, + .id = -1, + .dev.platform_data = foo_w1_gpio_pdata, +}; + +... + at91_set_GPIO_periph(foo_w1_gpio_pdata.pin, 1); + at91_set_multi_drive(foo_w1_gpio_pdata.pin, 1); + platform_device_register(foo_w1_device); diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 8236d44..c449309 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -42,5 +42,15 @@ config W1_MASTER_DS1WM in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like hx4700. +config W1_MASTER_GPIO + tristate GPIO 1-wire busmaster + depends on GENERIC_GPIO + help + Say Y here if you want to communicate with your 1-wire devices using + GPIO pins. This driver uses the GPIO API to control the wire. + + This support is also available as a module. If so, the module + will be called w1-gpio.ko. + endmenu diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 11551b3..1420b5b 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o +obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c new file mode 100644 index 000..9e1138a --- /dev/null +++ b/drivers/w1/masters/w1-gpio.c @@ -0,0 +1,124 @@ +/* + * w1-gpio - GPIO w1 bus master driver + * + * Copyright (C) 2007 Ville Syrjala [EMAIL PROTECTED] + * + * 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. + */ + +#include linux/init.h +#include linux/module.h +#include linux/platform_device.h +#include linux/w1-gpio.h + +#include ../w1.h +#include ../w1_int.h + +#include asm/gpio.h + +static void w1_gpio_write_bit_dir(void *data, u8 bit) +{ + struct w1_gpio_platform_data *pdata = data; + + if (bit) + gpio_direction_input(pdata-pin); + else + gpio_direction_output(pdata-pin, 0); +} + +static void w1_gpio_write_bit_val(void *data, u8 bit) +{ + struct w1_gpio_platform_data *pdata = data; + + gpio_set_value(pdata-pin, bit); +} + +static u8 w1_gpio_read_bit(void *data) +{ + struct w1_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata-pin); +} + +static int __init w1_gpio_probe(struct platform_device *pdev) +{ + struct w1_bus_master *master; + struct w1_gpio_platform_data *pdata = pdev-dev.platform_data; + int err; + + if (!pdata) + return -ENXIO; + + master
[PATCH] w1-gpio: Add GPIO w1 bus master driver (v2)
Add a GPIO 1-wire bus master driver. The driver used the GPIO API to control the wire and the GPIO pin can be specified using platform data similar to i2c-gpio. The driver was tested with AT91SAM9260 + DS2401. Signed-off-by: Ville Syrjala <[EMAIL PROTECTED]> --- Version 2 of the patch changes the sizeof to use the type as requested. I also had a better look at i2c-gpio and noticed that I should probably call gpio_request()/gpio_free(). Those functions are no-ops on mach-at91 but perhaps some other platforms require them. Also I removed the open-drain requirement like i2c-gpio does by toggling the pin direction. Documentation/w1/masters/00-INDEX |2 + Documentation/w1/masters/w1-gpio | 33 ++ drivers/w1/masters/Kconfig| 10 +++ drivers/w1/masters/Makefile |1 + drivers/w1/masters/w1-gpio.c | 125 + include/linux/w1-gpio.h | 23 +++ 6 files changed, 194 insertions(+), 0 deletions(-) create mode 100644 Documentation/w1/masters/w1-gpio create mode 100644 drivers/w1/masters/w1-gpio.c create mode 100644 include/linux/w1-gpio.h diff --git a/Documentation/w1/masters/00-INDEX b/Documentation/w1/masters/00-INDEX index 752613c..7b0ceaa 100644 --- a/Documentation/w1/masters/00-INDEX +++ b/Documentation/w1/masters/00-INDEX @@ -4,3 +4,5 @@ ds2482 - The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses. ds2490 - The Maxim/Dallas Semiconductor DS2490 builds USB <-> W1 bridges. +w1-gpio + - GPIO 1-wire bus master driver. diff --git a/Documentation/w1/masters/w1-gpio b/Documentation/w1/masters/w1-gpio new file mode 100644 index 000..af5d3b4 --- /dev/null +++ b/Documentation/w1/masters/w1-gpio @@ -0,0 +1,33 @@ +Kernel driver w1-gpio += + +Author: Ville Syrjala <[EMAIL PROTECTED]> + + +Description +--- + +GPIO 1-wire bus master driver. The driver uses the GPIO API to control the +wire and the GPIO pin can be specified using platform data. + + +Example (mach-at91) +--- + +#include + +static struct w1_gpio_platform_data foo_w1_gpio_pdata = { + .pin= AT91_PIN_PB20, + .is_open_drain = 1, +}; + +static struct platform_device foo_w1_device = { + .name = "w1-gpio", + .id = -1, + .dev.platform_data = _w1_gpio_pdata, +}; + +... + at91_set_GPIO_periph(foo_w1_gpio_pdata.pin, 1); + at91_set_multi_drive(foo_w1_gpio_pdata.pin, 1); + platform_device_register(_w1_device); diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 8236d44..c449309 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -42,5 +42,15 @@ config W1_MASTER_DS1WM in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like hx4700. +config W1_MASTER_GPIO + tristate "GPIO 1-wire busmaster" + depends on GENERIC_GPIO + help + Say Y here if you want to communicate with your 1-wire devices using + GPIO pins. This driver uses the GPIO API to control the wire. + + This support is also available as a module. If so, the module + will be called w1-gpio.ko. + endmenu diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 11551b3..1420b5b 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o +obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c new file mode 100644 index 000..354ee6f --- /dev/null +++ b/drivers/w1/masters/w1-gpio.c @@ -0,0 +1,125 @@ +/* + * w1-gpio - GPIO w1 bus master driver + * + * Copyright (C) 2007 Ville Syrjala <[EMAIL PROTECTED]> + * + * 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. + */ + +#include +#include +#include +#include + +#include "../w1.h" +#include "../w1_int.h" + +#include + +static void w1_gpio_write_bit_dir(void *data, u8 bit) +{ + struct w1_gpio_platform_data *pdata = data; + + if (bit) + gpio_direction_input(pdata->pin); + else + gpio_direction_output(pdata->pin, 0); +} + +static void w1_gpio_write_bit_val(void *data, u8 bit) +{ + struct w1_gpio_platform_data *pdata = data; + + gpio_set_value(pdata->pin, bit); +} + +static u8 w1_gpio_read_bit(void *data) +{ + struct w1_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata->pin); +} + +static int __init w1_gpio_probe(struct platform_device *pdev) +{ + stru
[PATCH] w1-gpio: Add GPIO w1 bus master driver (v2)
Add a GPIO 1-wire bus master driver. The driver used the GPIO API to control the wire and the GPIO pin can be specified using platform data similar to i2c-gpio. The driver was tested with AT91SAM9260 + DS2401. Signed-off-by: Ville Syrjala [EMAIL PROTECTED] --- Version 2 of the patch changes the sizeof to use the type as requested. I also had a better look at i2c-gpio and noticed that I should probably call gpio_request()/gpio_free(). Those functions are no-ops on mach-at91 but perhaps some other platforms require them. Also I removed the open-drain requirement like i2c-gpio does by toggling the pin direction. Documentation/w1/masters/00-INDEX |2 + Documentation/w1/masters/w1-gpio | 33 ++ drivers/w1/masters/Kconfig| 10 +++ drivers/w1/masters/Makefile |1 + drivers/w1/masters/w1-gpio.c | 125 + include/linux/w1-gpio.h | 23 +++ 6 files changed, 194 insertions(+), 0 deletions(-) create mode 100644 Documentation/w1/masters/w1-gpio create mode 100644 drivers/w1/masters/w1-gpio.c create mode 100644 include/linux/w1-gpio.h diff --git a/Documentation/w1/masters/00-INDEX b/Documentation/w1/masters/00-INDEX index 752613c..7b0ceaa 100644 --- a/Documentation/w1/masters/00-INDEX +++ b/Documentation/w1/masters/00-INDEX @@ -4,3 +4,5 @@ ds2482 - The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses. ds2490 - The Maxim/Dallas Semiconductor DS2490 builds USB - W1 bridges. +w1-gpio + - GPIO 1-wire bus master driver. diff --git a/Documentation/w1/masters/w1-gpio b/Documentation/w1/masters/w1-gpio new file mode 100644 index 000..af5d3b4 --- /dev/null +++ b/Documentation/w1/masters/w1-gpio @@ -0,0 +1,33 @@ +Kernel driver w1-gpio += + +Author: Ville Syrjala [EMAIL PROTECTED] + + +Description +--- + +GPIO 1-wire bus master driver. The driver uses the GPIO API to control the +wire and the GPIO pin can be specified using platform data. + + +Example (mach-at91) +--- + +#include linux/w1-gpio.h + +static struct w1_gpio_platform_data foo_w1_gpio_pdata = { + .pin= AT91_PIN_PB20, + .is_open_drain = 1, +}; + +static struct platform_device foo_w1_device = { + .name = w1-gpio, + .id = -1, + .dev.platform_data = foo_w1_gpio_pdata, +}; + +... + at91_set_GPIO_periph(foo_w1_gpio_pdata.pin, 1); + at91_set_multi_drive(foo_w1_gpio_pdata.pin, 1); + platform_device_register(foo_w1_device); diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 8236d44..c449309 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -42,5 +42,15 @@ config W1_MASTER_DS1WM in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like hx4700. +config W1_MASTER_GPIO + tristate GPIO 1-wire busmaster + depends on GENERIC_GPIO + help + Say Y here if you want to communicate with your 1-wire devices using + GPIO pins. This driver uses the GPIO API to control the wire. + + This support is also available as a module. If so, the module + will be called w1-gpio.ko. + endmenu diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 11551b3..1420b5b 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o +obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c new file mode 100644 index 000..354ee6f --- /dev/null +++ b/drivers/w1/masters/w1-gpio.c @@ -0,0 +1,125 @@ +/* + * w1-gpio - GPIO w1 bus master driver + * + * Copyright (C) 2007 Ville Syrjala [EMAIL PROTECTED] + * + * 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. + */ + +#include linux/init.h +#include linux/module.h +#include linux/platform_device.h +#include linux/w1-gpio.h + +#include ../w1.h +#include ../w1_int.h + +#include asm/gpio.h + +static void w1_gpio_write_bit_dir(void *data, u8 bit) +{ + struct w1_gpio_platform_data *pdata = data; + + if (bit) + gpio_direction_input(pdata-pin); + else + gpio_direction_output(pdata-pin, 0); +} + +static void w1_gpio_write_bit_val(void *data, u8 bit) +{ + struct w1_gpio_platform_data *pdata = data; + + gpio_set_value(pdata-pin, bit); +} + +static u8 w1_gpio_read_bit(void *data) +{ + struct w1_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata-pin); +} + +static int __init w1_gpio_probe(struct platform_device *pdev) +{ + struct
[PATCH] w1-gpio: Add GPIO w1 bus master driver
Add a GPIO 1-wire bus master driver. The driver used the GPIO API to control the wire and the GPIO pin can be specified using platform data similar to i2c-gpio. The driver was tested with AT91SAM9260 + DS2401. Signed-off-by: Ville Syrjala <[EMAIL PROTECTED]> --- Documentation/w1/masters/00-INDEX |2 + Documentation/w1/masters/w1-gpio | 33 drivers/w1/masters/Kconfig| 10 drivers/w1/masters/Makefile |1 + drivers/w1/masters/w1-gpio.c | 100 + include/linux/w1-gpio.h | 21 6 files changed, 167 insertions(+), 0 deletions(-) create mode 100644 Documentation/w1/masters/w1-gpio create mode 100644 drivers/w1/masters/w1-gpio.c create mode 100644 include/linux/w1-gpio.h diff --git a/Documentation/w1/masters/00-INDEX b/Documentation/w1/masters/00-INDEX index 752613c..7b0ceaa 100644 --- a/Documentation/w1/masters/00-INDEX +++ b/Documentation/w1/masters/00-INDEX @@ -4,3 +4,5 @@ ds2482 - The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses. ds2490 - The Maxim/Dallas Semiconductor DS2490 builds USB <-> W1 bridges. +w1-gpio + - GPIO 1-wire bus master driver. diff --git a/Documentation/w1/masters/w1-gpio b/Documentation/w1/masters/w1-gpio new file mode 100644 index 000..c927139 --- /dev/null +++ b/Documentation/w1/masters/w1-gpio @@ -0,0 +1,33 @@ +Kernel driver w1-gpio += + +Author: Ville Syrjala <[EMAIL PROTECTED]> + + +Description +--- + +GPIO 1-wire bus master driver. The driver uses the GPIO API to control the +wire and the GPIO pin can be specified using platform data. The GPIO pin +must be configured as open-drain. + + +Example (mach-at91) +--- + +#include + +static struct w1_gpio_platform_data foo_w1_gpio_pdata = { + .pin = AT91_PIN_PB20, +}; + +static struct platform_device foo_w1_device = { + .name = "w1-gpio", + .id = -1, + .dev.platform_data = _w1_gpio_pdata, +}; + +... + at91_set_GPIO_periph(foo_w1_gpio_pdata.pin, 1); + at91_set_multi_drive(foo_w1_gpio_pdata.pin, 1); + platform_device_register(_w1_device); diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 8236d44..c449309 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -42,5 +42,15 @@ config W1_MASTER_DS1WM in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like hx4700. +config W1_MASTER_GPIO + tristate "GPIO 1-wire busmaster" + depends on GENERIC_GPIO + help + Say Y here if you want to communicate with your 1-wire devices using + GPIO pins. This driver uses the GPIO API to control the wire. + + This support is also available as a module. If so, the module + will be called w1-gpio.ko. + endmenu diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 11551b3..1420b5b 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o +obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c new file mode 100644 index 000..c5327df --- /dev/null +++ b/drivers/w1/masters/w1-gpio.c @@ -0,0 +1,100 @@ +/* + * w1-gpio - GPIO w1 bus master driver + * + * Copyright (C) 2007 Ville Syrjala <[EMAIL PROTECTED]> + * + * 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. + */ + +#include +#include +#include +#include + +#include "../w1.h" +#include "../w1_int.h" + +#include + +static void w1_gpio_write_bit(void *data, u8 bit) +{ + struct w1_gpio_platform_data *pdata = data; + + gpio_set_value(pdata->pin, bit); +} + +static u8 w1_gpio_read_bit(void *data) +{ + struct w1_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata->pin); +} + +static int __init w1_gpio_probe(struct platform_device *pdev) +{ + struct w1_bus_master *master; + struct w1_gpio_platform_data *pdata; + int err; + + pdata = pdev->dev.platform_data; + if (!pdata) + return -ENXIO; + + master = kzalloc(sizeof *master, GFP_KERNEL); + if (!master) + return -ENOMEM; + + gpio_direction_output(pdata->pin, 1); + + master->data = pdata; + master->read_bit = _gpio_read_bit; + master->write_bit = _gpio_write_bit; + + err = w1_add_master_device(master); + if (err) { + kfree(master); + return err; +
[PATCH] w1-gpio: Add GPIO w1 bus master driver
Add a GPIO 1-wire bus master driver. The driver used the GPIO API to control the wire and the GPIO pin can be specified using platform data similar to i2c-gpio. The driver was tested with AT91SAM9260 + DS2401. Signed-off-by: Ville Syrjala [EMAIL PROTECTED] --- Documentation/w1/masters/00-INDEX |2 + Documentation/w1/masters/w1-gpio | 33 drivers/w1/masters/Kconfig| 10 drivers/w1/masters/Makefile |1 + drivers/w1/masters/w1-gpio.c | 100 + include/linux/w1-gpio.h | 21 6 files changed, 167 insertions(+), 0 deletions(-) create mode 100644 Documentation/w1/masters/w1-gpio create mode 100644 drivers/w1/masters/w1-gpio.c create mode 100644 include/linux/w1-gpio.h diff --git a/Documentation/w1/masters/00-INDEX b/Documentation/w1/masters/00-INDEX index 752613c..7b0ceaa 100644 --- a/Documentation/w1/masters/00-INDEX +++ b/Documentation/w1/masters/00-INDEX @@ -4,3 +4,5 @@ ds2482 - The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses. ds2490 - The Maxim/Dallas Semiconductor DS2490 builds USB - W1 bridges. +w1-gpio + - GPIO 1-wire bus master driver. diff --git a/Documentation/w1/masters/w1-gpio b/Documentation/w1/masters/w1-gpio new file mode 100644 index 000..c927139 --- /dev/null +++ b/Documentation/w1/masters/w1-gpio @@ -0,0 +1,33 @@ +Kernel driver w1-gpio += + +Author: Ville Syrjala [EMAIL PROTECTED] + + +Description +--- + +GPIO 1-wire bus master driver. The driver uses the GPIO API to control the +wire and the GPIO pin can be specified using platform data. The GPIO pin +must be configured as open-drain. + + +Example (mach-at91) +--- + +#include linux/w1-gpio.h + +static struct w1_gpio_platform_data foo_w1_gpio_pdata = { + .pin = AT91_PIN_PB20, +}; + +static struct platform_device foo_w1_device = { + .name = w1-gpio, + .id = -1, + .dev.platform_data = foo_w1_gpio_pdata, +}; + +... + at91_set_GPIO_periph(foo_w1_gpio_pdata.pin, 1); + at91_set_multi_drive(foo_w1_gpio_pdata.pin, 1); + platform_device_register(foo_w1_device); diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 8236d44..c449309 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -42,5 +42,15 @@ config W1_MASTER_DS1WM in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like hx4700. +config W1_MASTER_GPIO + tristate GPIO 1-wire busmaster + depends on GENERIC_GPIO + help + Say Y here if you want to communicate with your 1-wire devices using + GPIO pins. This driver uses the GPIO API to control the wire. + + This support is also available as a module. If so, the module + will be called w1-gpio.ko. + endmenu diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 11551b3..1420b5b 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o +obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c new file mode 100644 index 000..c5327df --- /dev/null +++ b/drivers/w1/masters/w1-gpio.c @@ -0,0 +1,100 @@ +/* + * w1-gpio - GPIO w1 bus master driver + * + * Copyright (C) 2007 Ville Syrjala [EMAIL PROTECTED] + * + * 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. + */ + +#include linux/init.h +#include linux/module.h +#include linux/platform_device.h +#include linux/w1-gpio.h + +#include ../w1.h +#include ../w1_int.h + +#include asm/gpio.h + +static void w1_gpio_write_bit(void *data, u8 bit) +{ + struct w1_gpio_platform_data *pdata = data; + + gpio_set_value(pdata-pin, bit); +} + +static u8 w1_gpio_read_bit(void *data) +{ + struct w1_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata-pin); +} + +static int __init w1_gpio_probe(struct platform_device *pdev) +{ + struct w1_bus_master *master; + struct w1_gpio_platform_data *pdata; + int err; + + pdata = pdev-dev.platform_data; + if (!pdata) + return -ENXIO; + + master = kzalloc(sizeof *master, GFP_KERNEL); + if (!master) + return -ENOMEM; + + gpio_direction_output(pdata-pin, 1); + + master-data = pdata; + master-read_bit = w1_gpio_read_bit; + master-write_bit = w1_gpio_write_bit; + + err = w1_add_master_device(master); + if (err) { + kfree(master); + return err