diff options
author | Anton Blanchard <anton@samba.org> | 2012-09-03 12:47:56 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-09-05 02:05:20 -0400 |
commit | 1b6ca2a6fe56e7697d57348646e07df08f43b1bb (patch) | |
tree | e6002bbd58816dfe10b639e2843c804b5dad18c3 /arch/powerpc | |
parent | 375f561a4131a0f501c8845a2a20f2ca1abc8f7a (diff) |
powerpc: Update DSCR on all CPUs when writing sysfs dscr_default
Writing to dscr_default in sysfs doesn't actually change the DSCR -
we rely on a context switch on each CPU to do the work. There is no
guarantee we will get a context switch in a reasonable amount of time
so fire off an IPI to force an immediate change.
This issue was found with the following test case:
http://ozlabs.org/~anton/junkcode/dscr_explicit_test.c
Signed-off-by: Anton Blanchard <anton@samba.org>
Cc: <stable@kernel.org> # 3.0+
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kernel/sysfs.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 3529446c2abd..d4cbbd1fa75f 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -194,6 +194,12 @@ static ssize_t show_dscr_default(struct device *dev, | |||
194 | return sprintf(buf, "%lx\n", dscr_default); | 194 | return sprintf(buf, "%lx\n", dscr_default); |
195 | } | 195 | } |
196 | 196 | ||
197 | static void update_dscr(void *dummy) | ||
198 | { | ||
199 | if (!current->thread.dscr_inherit) | ||
200 | mtspr(SPRN_DSCR, dscr_default); | ||
201 | } | ||
202 | |||
197 | static ssize_t __used store_dscr_default(struct device *dev, | 203 | static ssize_t __used store_dscr_default(struct device *dev, |
198 | struct device_attribute *attr, const char *buf, | 204 | struct device_attribute *attr, const char *buf, |
199 | size_t count) | 205 | size_t count) |
@@ -206,6 +212,8 @@ static ssize_t __used store_dscr_default(struct device *dev, | |||
206 | return -EINVAL; | 212 | return -EINVAL; |
207 | dscr_default = val; | 213 | dscr_default = val; |
208 | 214 | ||
215 | on_each_cpu(update_dscr, NULL, 1); | ||
216 | |||
209 | return count; | 217 | return count; |
210 | } | 218 | } |
211 | 219 | ||