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/kernel/sysfs.c | |
| 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/kernel/sysfs.c')
| -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 | ||
