diff options
| -rw-r--r-- | arch/ia64/sn/kernel/setup.c | 6 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/sn2/sn2_smp.c | 21 | ||||
| -rw-r--r-- | include/asm-ia64/machvec.h | 13 | ||||
| -rw-r--r-- | include/asm-ia64/machvec_sn2.h | 4 | ||||
| -rw-r--r-- | include/asm-ia64/processor.h | 3 | ||||
| -rw-r--r-- | include/asm-ia64/system.h | 7 | ||||
| -rw-r--r-- | include/asm-ia64/thread_info.h | 1 | 
7 files changed, 51 insertions, 4 deletions
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 5b84836c2171..8b6d5c844708 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> | 
| @@ -498,6 +498,7 @@ void __init sn_setup(char **cmdline_p) | |||
| 498 | * for sn. | 498 | * for sn. | 
| 499 | */ | 499 | */ | 
| 500 | pm_power_off = ia64_sn_power_down; | 500 | pm_power_off = ia64_sn_power_down; | 
| 501 | current->thread.flags |= IA64_THREAD_MIGRATION; | ||
| 501 | } | 502 | } | 
| 502 | 503 | ||
| 503 | /** | 504 | /** | 
| @@ -660,7 +661,8 @@ void __init sn_cpu_init(void) | |||
| 660 | SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3}; | 661 | SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3}; | 
| 661 | u64 *pio; | 662 | u64 *pio; | 
| 662 | pio = is_shub1() ? pio1 : pio2; | 663 | pio = is_shub1() ? pio1 : pio2; | 
| 663 | pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]); | 664 | pda->pio_write_status_addr = | 
| 665 | (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid, pio[slice]); | ||
| 664 | pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0; | 666 | pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0; | 
| 665 | } | 667 | } | 
| 666 | 668 | ||
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index b2e1e746b47f..d9d306c79f2d 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c  | |||
| @@ -93,6 +93,27 @@ static inline unsigned long wait_piowc(void) | |||
| 93 | return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0; | 93 | return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0; | 
| 94 | } | 94 | } | 
| 95 | 95 | ||
| 96 | /** | ||
| 97 | * sn_migrate - SN-specific task migration actions | ||
| 98 | * @task: Task being migrated to new CPU | ||
| 99 | * | ||
| 100 | * SN2 PIO writes from separate CPUs are not guaranteed to arrive in order. | ||
| 101 | * Context switching user threads which have memory-mapped MMIO may cause | ||
| 102 | * PIOs to issue from seperate CPUs, thus the PIO writes must be drained | ||
| 103 | * from the previous CPU's Shub before execution resumes on the new CPU. | ||
| 104 | */ | ||
| 105 | void sn_migrate(struct task_struct *task) | ||
| 106 | { | ||
| 107 | pda_t *last_pda = pdacpu(task_thread_info(task)->last_cpu); | ||
| 108 | volatile unsigned long *adr = last_pda->pio_write_status_addr; | ||
| 109 | unsigned long val = last_pda->pio_write_status_val; | ||
| 110 | |||
| 111 | /* Drain PIO writes from old CPU's Shub */ | ||
| 112 | while (unlikely((*adr & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) | ||
| 113 | != val)) | ||
| 114 | cpu_relax(); | ||
| 115 | } | ||
| 116 | |||
| 96 | void sn_tlb_migrate_finish(struct mm_struct *mm) | 117 | void sn_tlb_migrate_finish(struct mm_struct *mm) | 
| 97 | { | 118 | { | 
| 98 | /* flush_tlb_mm is inefficient if more than 1 users of mm */ | 119 | /* flush_tlb_mm is inefficient if more than 1 users of mm */ | 
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h index ca5ea994d688..c3e4ed8a3e17 100644 --- a/include/asm-ia64/machvec.h +++ b/include/asm-ia64/machvec.h  | |||
| @@ -20,6 +20,7 @@ struct scatterlist; | |||
| 20 | struct page; | 20 | struct page; | 
| 21 | struct mm_struct; | 21 | struct mm_struct; | 
| 22 | struct pci_bus; | 22 | struct pci_bus; | 
| 23 | struct task_struct; | ||
| 23 | 24 | ||
| 24 | typedef void ia64_mv_setup_t (char **); | 25 | typedef void ia64_mv_setup_t (char **); | 
| 25 | typedef void ia64_mv_cpu_init_t (void); | 26 | typedef void ia64_mv_cpu_init_t (void); | 
| @@ -34,6 +35,7 @@ typedef int ia64_mv_pci_legacy_read_t (struct pci_bus *, u16 port, u32 *val, | |||
| 34 | u8 size); | 35 | u8 size); | 
| 35 | typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val, | 36 | typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val, | 
| 36 | u8 size); | 37 | u8 size); | 
| 38 | typedef void ia64_mv_migrate_t(struct task_struct * task); | ||
| 37 | 39 | ||
| 38 | /* DMA-mapping interface: */ | 40 | /* DMA-mapping interface: */ | 
| 39 | typedef void ia64_mv_dma_init (void); | 41 | typedef void ia64_mv_dma_init (void); | 
| @@ -85,6 +87,11 @@ machvec_noop_mm (struct mm_struct *mm) | |||
| 85 | { | 87 | { | 
| 86 | } | 88 | } | 
| 87 | 89 | ||
| 90 | static inline void | ||
| 91 | machvec_noop_task (struct task_struct *task) | ||
| 92 | { | ||
| 93 | } | ||
| 94 | |||
| 88 | extern void machvec_setup (char **); | 95 | extern void machvec_setup (char **); | 
| 89 | extern void machvec_timer_interrupt (int, void *, struct pt_regs *); | 96 | extern void machvec_timer_interrupt (int, void *, struct pt_regs *); | 
| 90 | extern void machvec_dma_sync_single (struct device *, dma_addr_t, size_t, int); | 97 | extern void machvec_dma_sync_single (struct device *, dma_addr_t, size_t, int); | 
| @@ -146,6 +153,7 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); | |||
| 146 | # define platform_readw_relaxed ia64_mv.readw_relaxed | 153 | # define platform_readw_relaxed ia64_mv.readw_relaxed | 
| 147 | # define platform_readl_relaxed ia64_mv.readl_relaxed | 154 | # define platform_readl_relaxed ia64_mv.readl_relaxed | 
| 148 | # define platform_readq_relaxed ia64_mv.readq_relaxed | 155 | # define platform_readq_relaxed ia64_mv.readq_relaxed | 
| 156 | # define platform_migrate ia64_mv.migrate | ||
| 149 | # endif | 157 | # endif | 
| 150 | 158 | ||
| 151 | /* __attribute__((__aligned__(16))) is required to make size of the | 159 | /* __attribute__((__aligned__(16))) is required to make size of the | 
| @@ -194,6 +202,7 @@ struct ia64_machine_vector { | |||
| 194 | ia64_mv_readw_relaxed_t *readw_relaxed; | 202 | ia64_mv_readw_relaxed_t *readw_relaxed; | 
| 195 | ia64_mv_readl_relaxed_t *readl_relaxed; | 203 | ia64_mv_readl_relaxed_t *readl_relaxed; | 
| 196 | ia64_mv_readq_relaxed_t *readq_relaxed; | 204 | ia64_mv_readq_relaxed_t *readq_relaxed; | 
| 205 | ia64_mv_migrate_t *migrate; | ||
| 197 | } __attribute__((__aligned__(16))); /* align attrib? see above comment */ | 206 | } __attribute__((__aligned__(16))); /* align attrib? see above comment */ | 
| 198 | 207 | ||
| 199 | #define MACHVEC_INIT(name) \ | 208 | #define MACHVEC_INIT(name) \ | 
| @@ -238,6 +247,7 @@ struct ia64_machine_vector { | |||
| 238 | platform_readw_relaxed, \ | 247 | platform_readw_relaxed, \ | 
| 239 | platform_readl_relaxed, \ | 248 | platform_readl_relaxed, \ | 
| 240 | platform_readq_relaxed, \ | 249 | platform_readq_relaxed, \ | 
| 250 | platform_migrate, \ | ||
| 241 | } | 251 | } | 
| 242 | 252 | ||
| 243 | extern struct ia64_machine_vector ia64_mv; | 253 | extern struct ia64_machine_vector ia64_mv; | 
| @@ -386,5 +396,8 @@ extern ia64_mv_dma_supported swiotlb_dma_supported; | |||
| 386 | #ifndef platform_readq_relaxed | 396 | #ifndef platform_readq_relaxed | 
| 387 | # define platform_readq_relaxed __ia64_readq_relaxed | 397 | # define platform_readq_relaxed __ia64_readq_relaxed | 
| 388 | #endif | 398 | #endif | 
| 399 | #ifndef platform_migrate | ||
| 400 | # define platform_migrate machvec_noop_task | ||
| 401 | #endif | ||
| 389 | 402 | ||
| 390 | #endif /* _ASM_IA64_MACHVEC_H */ | 403 | #endif /* _ASM_IA64_MACHVEC_H */ | 
diff --git a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h index 03d00faf03b5..da1d43755afe 100644 --- a/include/asm-ia64/machvec_sn2.h +++ b/include/asm-ia64/machvec_sn2.h  | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* | 
| 2 | * Copyright (c) 2002-2003, 2006 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2002-2003,2006 Silicon Graphics, Inc. All Rights Reserved. | 
| 3 | * | 3 | * | 
| 4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it | 
| 5 | * under the terms of version 2 of the GNU General Public License | 5 | * under the terms of version 2 of the GNU General Public License | 
| @@ -66,6 +66,7 @@ extern ia64_mv_dma_sync_single_for_device sn_dma_sync_single_for_device; | |||
| 66 | extern ia64_mv_dma_sync_sg_for_device sn_dma_sync_sg_for_device; | 66 | extern ia64_mv_dma_sync_sg_for_device sn_dma_sync_sg_for_device; | 
| 67 | extern ia64_mv_dma_mapping_error sn_dma_mapping_error; | 67 | extern ia64_mv_dma_mapping_error sn_dma_mapping_error; | 
| 68 | extern ia64_mv_dma_supported sn_dma_supported; | 68 | extern ia64_mv_dma_supported sn_dma_supported; | 
| 69 | extern ia64_mv_migrate_t sn_migrate; | ||
| 69 | 70 | ||
| 70 | /* | 71 | /* | 
| 71 | * This stuff has dual use! | 72 | * This stuff has dual use! | 
| @@ -115,6 +116,7 @@ extern ia64_mv_dma_supported sn_dma_supported; | |||
| 115 | #define platform_dma_sync_sg_for_device sn_dma_sync_sg_for_device | 116 | #define platform_dma_sync_sg_for_device sn_dma_sync_sg_for_device | 
| 116 | #define platform_dma_mapping_error sn_dma_mapping_error | 117 | #define platform_dma_mapping_error sn_dma_mapping_error | 
| 117 | #define platform_dma_supported sn_dma_supported | 118 | #define platform_dma_supported sn_dma_supported | 
| 119 | #define platform_migrate sn_migrate | ||
| 118 | 120 | ||
| 119 | #include <asm/sn/io.h> | 121 | #include <asm/sn/io.h> | 
| 120 | 122 | ||
diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h index 23c8e1be1911..128fefd8056f 100644 --- a/include/asm-ia64/processor.h +++ b/include/asm-ia64/processor.h  | |||
| @@ -50,7 +50,8 @@ | |||
| 50 | #define IA64_THREAD_PM_VALID (__IA64_UL(1) << 2) /* performance registers valid? */ | 50 | #define IA64_THREAD_PM_VALID (__IA64_UL(1) << 2) /* performance registers valid? */ | 
| 51 | #define IA64_THREAD_UAC_NOPRINT (__IA64_UL(1) << 3) /* don't log unaligned accesses */ | 51 | #define IA64_THREAD_UAC_NOPRINT (__IA64_UL(1) << 3) /* don't log unaligned accesses */ | 
| 52 | #define IA64_THREAD_UAC_SIGBUS (__IA64_UL(1) << 4) /* generate SIGBUS on unaligned acc. */ | 52 | #define IA64_THREAD_UAC_SIGBUS (__IA64_UL(1) << 4) /* generate SIGBUS on unaligned acc. */ | 
| 53 | /* bit 5 is currently unused */ | 53 | #define IA64_THREAD_MIGRATION (__IA64_UL(1) << 5) /* require migration | 
| 54 | sync at ctx sw */ | ||
| 54 | #define IA64_THREAD_FPEMU_NOPRINT (__IA64_UL(1) << 6) /* don't log any fpswa faults */ | 55 | #define IA64_THREAD_FPEMU_NOPRINT (__IA64_UL(1) << 6) /* don't log any fpswa faults */ | 
| 55 | #define IA64_THREAD_FPEMU_SIGFPE (__IA64_UL(1) << 7) /* send a SIGFPE for fpswa faults */ | 56 | #define IA64_THREAD_FPEMU_SIGFPE (__IA64_UL(1) << 7) /* send a SIGFPE for fpswa faults */ | 
| 56 | 57 | ||
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h index 062538715623..cd4233d66f15 100644 --- a/include/asm-ia64/system.h +++ b/include/asm-ia64/system.h  | |||
| @@ -244,6 +244,13 @@ extern void ia64_load_extra (struct task_struct *task); | |||
| 244 | __ia64_save_fpu((prev)->thread.fph); \ | 244 | __ia64_save_fpu((prev)->thread.fph); \ | 
| 245 | } \ | 245 | } \ | 
| 246 | __switch_to(prev, next, last); \ | 246 | __switch_to(prev, next, last); \ | 
| 247 | /* "next" in old context is "current" in new context */ \ | ||
| 248 | if (unlikely((current->thread.flags & IA64_THREAD_MIGRATION) && \ | ||
| 249 | (task_cpu(current) != \ | ||
| 250 | task_thread_info(current)->last_cpu))) { \ | ||
| 251 | platform_migrate(current); \ | ||
| 252 | task_thread_info(current)->last_cpu = task_cpu(current); \ | ||
| 253 | } \ | ||
| 247 | } while (0) | 254 | } while (0) | 
| 248 | #else | 255 | #else | 
| 249 | # define switch_to(prev,next,last) __switch_to(prev, next, last) | 256 | # define switch_to(prev,next,last) __switch_to(prev, next, last) | 
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h index a6ee27343a4a..56394a2c7055 100644 --- a/include/asm-ia64/thread_info.h +++ b/include/asm-ia64/thread_info.h  | |||
| @@ -26,6 +26,7 @@ struct thread_info { | |||
| 26 | struct exec_domain *exec_domain;/* execution domain */ | 26 | struct exec_domain *exec_domain;/* execution domain */ | 
| 27 | __u32 flags; /* thread_info flags (see TIF_*) */ | 27 | __u32 flags; /* thread_info flags (see TIF_*) */ | 
| 28 | __u32 cpu; /* current CPU */ | 28 | __u32 cpu; /* current CPU */ | 
| 29 | __u32 last_cpu; /* Last CPU thread ran on */ | ||
| 29 | mm_segment_t addr_limit; /* user-level address space limit */ | 30 | mm_segment_t addr_limit; /* user-level address space limit */ | 
| 30 | int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */ | 31 | int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */ | 
| 31 | struct restart_block restart_block; | 32 | struct restart_block restart_block; | 
