[PATCH] cpufreq: Fix RCU reboot regression on x86 PIC machines

2019-10-03 Thread Ville Syrjala
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"

2018-09-10 Thread Ville Syrjala
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"

2018-09-10 Thread Ville Syrjala
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

2018-07-12 Thread Ville Syrjala
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

2018-07-12 Thread Ville Syrjala
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

2018-07-09 Thread Ville Syrjala
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

2018-07-09 Thread Ville Syrjala
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"

2018-05-17 Thread Ville Syrjala
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"

2018-05-17 Thread Ville Syrjala
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+

2018-05-07 Thread Ville Syrjala
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+

2018-05-07 Thread Ville Syrjala
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"

2018-01-22 Thread Ville Syrjala
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"

2018-01-22 Thread Ville Syrjala
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()"

2017-11-28 Thread Ville Syrjala
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()"

2017-11-28 Thread Ville Syrjala
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()

2017-09-12 Thread Ville Syrjala
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()

2017-09-12 Thread Ville Syrjala
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

2017-05-07 Thread ville . syrjala
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

2017-05-07 Thread ville . syrjala
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()"

2017-04-20 Thread ville . syrjala
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()"

2017-04-20 Thread ville . syrjala
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

2016-10-27 Thread ville . syrjala
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

2016-10-27 Thread ville . syrjala
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

2016-10-21 Thread ville . syrjala
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

2016-10-21 Thread ville . syrjala
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

2016-10-19 Thread ville . syrjala
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

2016-10-19 Thread ville . syrjala
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

2016-08-12 Thread ville . syrjala
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

2016-08-12 Thread ville . syrjala
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

2016-08-08 Thread ville . syrjala
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

2016-08-08 Thread ville . syrjala
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

2016-06-23 Thread ville . syrjala
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

2016-06-23 Thread ville . syrjala
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

2016-05-19 Thread ville . syrjala
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

2016-05-19 Thread ville . syrjala
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

2015-11-04 Thread ville . syrjala
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

2015-11-04 Thread ville . syrjala
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

2015-11-02 Thread ville . syrjala
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

2015-11-02 Thread ville . syrjala
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

2015-10-25 Thread ville . syrjala
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

2015-10-25 Thread ville . syrjala
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()

2014-09-02 Thread ville . syrjala
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()

2014-09-02 Thread ville . syrjala
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()

2014-09-01 Thread ville . syrjala
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()

2014-09-01 Thread ville . syrjala
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()

2014-09-01 Thread ville . syrjala
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()

2014-09-01 Thread ville . syrjala
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

2014-04-13 Thread ville . syrjala
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

2014-04-13 Thread ville . syrjala
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()

2014-02-10 Thread ville . syrjala
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()

2014-02-10 Thread ville . syrjala
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

2014-02-05 Thread ville . syrjala
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

2014-02-05 Thread ville . syrjala
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

2014-02-05 Thread ville . syrjala
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

2014-02-05 Thread ville . syrjala
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

2014-02-05 Thread ville . syrjala
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

2014-02-05 Thread ville . syrjala
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

2014-02-05 Thread ville . syrjala
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

2014-02-05 Thread ville . syrjala
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

2014-01-07 Thread ville . syrjala
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

2014-01-07 Thread ville . syrjala
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

2014-01-07 Thread ville . syrjala
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

2014-01-07 Thread ville . syrjala
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

2013-12-03 Thread ville . syrjala
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

2013-12-03 Thread ville . syrjala
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

2013-12-03 Thread ville . syrjala
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

2013-12-03 Thread ville . syrjala
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

2013-12-03 Thread ville . syrjala
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

2013-12-03 Thread ville . syrjala
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()

2013-12-02 Thread ville . syrjala
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()

2013-12-02 Thread ville . syrjala
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

2013-10-04 Thread ville . syrjala
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

2013-10-04 Thread ville . syrjala
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

2013-09-17 Thread ville . syrjala
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

2013-09-17 Thread ville . syrjala
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%

2013-03-02 Thread Ville Syrjala
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%

2013-03-02 Thread Ville Syrjala
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

2012-12-12 Thread ville . syrjala
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

2012-12-12 Thread ville . syrjala
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)

2007-12-29 Thread Ville Syrjala
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)

2007-12-29 Thread Ville Syrjala
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)

2007-12-21 Thread Ville Syrjala
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)

2007-12-21 Thread Ville Syrjala
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

2007-12-20 Thread Ville Syrjala
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

2007-12-20 Thread Ville Syrjala
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