aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn
diff options
context:
space:
mode:
authorBrent Casavant <bcasavan@sgi.com>2006-01-26 18:55:52 -0500
committerTony Luck <tony.luck@intel.com>2006-01-26 18:55:52 -0500
commite08e6c521355cd33e647b2f739885bc3050eead6 (patch)
tree251dd80647bd3a0140f5f31c35c125094c035f9c /arch/ia64/sn
parent3ee68c4af3fd7228c1be63254b9f884614f9ebb2 (diff)
[IA64] hooks to wait for mmio writes to drain when migrating processes
On SN2, MMIO writes which are issued from separate processors are not guaranteed to arrive in any particular order at the IO hardware. When performing such writes from the kernel this is not a problem, as a kernel thread will not migrate to another CPU during execution, and mmiowb() calls can guarantee write ordering when control of the IO resource is allowed to move between threads. However, when MMIO writes can be performed from user space (e.g. DRM) there are no such guarantees and mechanisms, as the process may context-switch at any time, and may migrate to a different CPU as part of the switch. For such programs/hardware to operate correctly, it is required that the MMIO writes from the old CPU be accepted by the IO hardware before subsequent writes from the new CPU can be issued. The following patch implements this behavior on SN2 by waiting for a Shub register to indicate that these writes have been accepted. This is placed in the context switch-in path, and only performs the wait when the newly scheduled task changes CPUs. Signed-off-by: Prarit Bhargava <prarit@sgi.com> Signed-off-by: Brent Casavant <bcasavan@sgi.com>
Diffstat (limited to 'arch/ia64/sn')
-rw-r--r--arch/ia64/sn/kernel/setup.c6
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c23
2 files changed, 26 insertions, 3 deletions
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index e510dce9971f..f1c1338b10b4 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All rights reserved. 6 * Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All rights reserved.
7 */ 7 */
8 8
9#include <linux/config.h> 9#include <linux/config.h>
@@ -496,6 +496,7 @@ void __init sn_setup(char **cmdline_p)
496 * for sn. 496 * for sn.
497 */ 497 */
498 pm_power_off = ia64_sn_power_down; 498 pm_power_off = ia64_sn_power_down;
499 current->thread.flags |= IA64_THREAD_MIGRATION;
499} 500}
500 501
501/** 502/**
@@ -654,7 +655,8 @@ void __init sn_cpu_init(void)
654 SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3}; 655 SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3};
655 u64 *pio; 656 u64 *pio;
656 pio = is_shub1() ? pio1 : pio2; 657 pio = is_shub1() ? pio1 : pio2;
657 pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]); 658 pda->pio_write_status_addr =
659 (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid, pio[slice]);
658 pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0; 660 pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0;
659 } 661 }
660 662
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index 471bbaa65d1b..1b33fd5e4e3a 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -5,7 +5,7 @@
5 * License. See the file "COPYING" in the main directory of this archive 5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details. 6 * for more details.
7 * 7 *
8 * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. 8 * Copyright (C) 2000-2006 Silicon Graphics, Inc. All rights reserved.
9 */ 9 */
10 10
11#include <linux/init.h> 11#include <linux/init.h>
@@ -169,6 +169,27 @@ static inline unsigned long wait_piowc(void)
169 return ws; 169 return ws;
170} 170}
171 171
172/**
173 * sn_migrate - SN-specific task migration actions
174 * @task: Task being migrated to new CPU
175 *
176 * SN2 PIO writes from separate CPUs are not guaranteed to arrive in order.
177 * Context switching user threads which have memory-mapped MMIO may cause
178 * PIOs to issue from seperate CPUs, thus the PIO writes must be drained
179 * from the previous CPU's Shub before execution resumes on the new CPU.
180 */
181void sn_migrate(struct task_struct *task)
182{
183 pda_t *last_pda = pdacpu(task_thread_info(task)->last_cpu);
184 volatile unsigned long *adr = last_pda->pio_write_status_addr;
185 unsigned long val = last_pda->pio_write_status_val;
186
187 /* Drain PIO writes from old CPU's Shub */
188 while (unlikely((*adr & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK)
189 != val))
190 cpu_relax();
191}
192
172void sn_tlb_migrate_finish(struct mm_struct *mm) 193void sn_tlb_migrate_finish(struct mm_struct *mm)
173{ 194{
174 if (mm == current->mm) 195 if (mm == current->mm)