diff options
author | Robin Holt <holt@sgi.com> | 2009-12-15 19:47:56 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:20:14 -0500 |
commit | c2c9f115741453715d6b4da1cd2de65af8c7ad86 (patch) | |
tree | 8e20a0641c622b07b3c7380f81a5552e20e1c8d1 | |
parent | 289750d1f1fd4a715baa2a2c6dd0cec2b8317fd7 (diff) |
x86: uv: update XPC to handle updated BIOS interface
The UV BIOS has moved the location of some of their pointers to the
"partition reserved page" from memory into a uv hub MMR. The GRU does not
support bcopy operations from MMR space so we need to special case the MMR
addresses using VLOAD operations.
Additionally, the BIOS call for registering a message queue watchlist has
removed the 'blade' value and eliminated the structure that was being
passed in. This is also reflected in this patch.
Signed-off-by: Robin Holt <holt@sgi.com>
Cc: Jack Steiner <steiner@sgi.com>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/x86/include/asm/uv/bios.h | 11 | ||||
-rw-r--r-- | arch/x86/kernel/bios_uv.c | 8 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xp_uv.c | 23 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc_partition.c | 13 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc_uv.c | 27 |
5 files changed, 50 insertions, 32 deletions
diff --git a/arch/x86/include/asm/uv/bios.h b/arch/x86/include/asm/uv/bios.h index 7ed17ff502b9..2751f3075d8b 100644 --- a/arch/x86/include/asm/uv/bios.h +++ b/arch/x86/include/asm/uv/bios.h | |||
@@ -76,15 +76,6 @@ union partition_info_u { | |||
76 | }; | 76 | }; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | union uv_watchlist_u { | ||
80 | u64 val; | ||
81 | struct { | ||
82 | u64 blade : 16, | ||
83 | size : 32, | ||
84 | filler : 16; | ||
85 | }; | ||
86 | }; | ||
87 | |||
88 | enum uv_memprotect { | 79 | enum uv_memprotect { |
89 | UV_MEMPROT_RESTRICT_ACCESS, | 80 | UV_MEMPROT_RESTRICT_ACCESS, |
90 | UV_MEMPROT_ALLOW_AMO, | 81 | UV_MEMPROT_ALLOW_AMO, |
@@ -100,7 +91,7 @@ extern s64 uv_bios_call_reentrant(enum uv_bios_cmd, u64, u64, u64, u64, u64); | |||
100 | 91 | ||
101 | extern s64 uv_bios_get_sn_info(int, int *, long *, long *, long *); | 92 | extern s64 uv_bios_get_sn_info(int, int *, long *, long *, long *); |
102 | extern s64 uv_bios_freq_base(u64, u64 *); | 93 | extern s64 uv_bios_freq_base(u64, u64 *); |
103 | extern int uv_bios_mq_watchlist_alloc(int, unsigned long, unsigned int, | 94 | extern int uv_bios_mq_watchlist_alloc(unsigned long, unsigned int, |
104 | unsigned long *); | 95 | unsigned long *); |
105 | extern int uv_bios_mq_watchlist_free(int, int); | 96 | extern int uv_bios_mq_watchlist_free(int, int); |
106 | extern s64 uv_bios_change_memprotect(u64, u64, enum uv_memprotect); | 97 | extern s64 uv_bios_change_memprotect(u64, u64, enum uv_memprotect); |
diff --git a/arch/x86/kernel/bios_uv.c b/arch/x86/kernel/bios_uv.c index 63a88e1f987d..b0206a211b09 100644 --- a/arch/x86/kernel/bios_uv.c +++ b/arch/x86/kernel/bios_uv.c | |||
@@ -101,21 +101,17 @@ s64 uv_bios_get_sn_info(int fc, int *uvtype, long *partid, long *coher, | |||
101 | } | 101 | } |
102 | 102 | ||
103 | int | 103 | int |
104 | uv_bios_mq_watchlist_alloc(int blade, unsigned long addr, unsigned int mq_size, | 104 | uv_bios_mq_watchlist_alloc(unsigned long addr, unsigned int mq_size, |
105 | unsigned long *intr_mmr_offset) | 105 | unsigned long *intr_mmr_offset) |
106 | { | 106 | { |
107 | union uv_watchlist_u size_blade; | ||
108 | u64 watchlist; | 107 | u64 watchlist; |
109 | s64 ret; | 108 | s64 ret; |
110 | 109 | ||
111 | size_blade.size = mq_size; | ||
112 | size_blade.blade = blade; | ||
113 | |||
114 | /* | 110 | /* |
115 | * bios returns watchlist number or negative error number. | 111 | * bios returns watchlist number or negative error number. |
116 | */ | 112 | */ |
117 | ret = (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_ALLOC, addr, | 113 | ret = (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_ALLOC, addr, |
118 | size_blade.val, (u64)intr_mmr_offset, | 114 | mq_size, (u64)intr_mmr_offset, |
119 | (u64)&watchlist, 0); | 115 | (u64)&watchlist, 0); |
120 | if (ret < BIOS_STATUS_SUCCESS) | 116 | if (ret < BIOS_STATUS_SUCCESS) |
121 | return ret; | 117 | return ret; |
diff --git a/drivers/misc/sgi-xp/xp_uv.c b/drivers/misc/sgi-xp/xp_uv.c index 1e61f8a61a30..a0d093274dc0 100644 --- a/drivers/misc/sgi-xp/xp_uv.c +++ b/drivers/misc/sgi-xp/xp_uv.c | |||
@@ -42,11 +42,34 @@ xp_socket_pa_uv(unsigned long gpa) | |||
42 | } | 42 | } |
43 | 43 | ||
44 | static enum xp_retval | 44 | static enum xp_retval |
45 | xp_remote_mmr_read(unsigned long dst_gpa, const unsigned long src_gpa, | ||
46 | size_t len) | ||
47 | { | ||
48 | int ret; | ||
49 | unsigned long *dst_va = __va(uv_gpa_to_soc_phys_ram(dst_gpa)); | ||
50 | |||
51 | BUG_ON(!uv_gpa_in_mmr_space(src_gpa)); | ||
52 | BUG_ON(len != 8); | ||
53 | |||
54 | ret = gru_read_gpa(dst_va, src_gpa); | ||
55 | if (ret == 0) | ||
56 | return xpSuccess; | ||
57 | |||
58 | dev_err(xp, "gru_read_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx " | ||
59 | "len=%ld\n", dst_gpa, src_gpa, len); | ||
60 | return xpGruCopyError; | ||
61 | } | ||
62 | |||
63 | |||
64 | static enum xp_retval | ||
45 | xp_remote_memcpy_uv(unsigned long dst_gpa, const unsigned long src_gpa, | 65 | xp_remote_memcpy_uv(unsigned long dst_gpa, const unsigned long src_gpa, |
46 | size_t len) | 66 | size_t len) |
47 | { | 67 | { |
48 | int ret; | 68 | int ret; |
49 | 69 | ||
70 | if (uv_gpa_in_mmr_space(src_gpa)) | ||
71 | return xp_remote_mmr_read(dst_gpa, src_gpa, len); | ||
72 | |||
50 | ret = gru_copy_gpa(dst_gpa, src_gpa, len); | 73 | ret = gru_copy_gpa(dst_gpa, src_gpa, len); |
51 | if (ret == 0) | 74 | if (ret == 0) |
52 | return xpSuccess; | 75 | return xpSuccess; |
diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c index 65877bc5edaa..9a6268c89fdd 100644 --- a/drivers/misc/sgi-xp/xpc_partition.c +++ b/drivers/misc/sgi-xp/xpc_partition.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/device.h> | 18 | #include <linux/device.h> |
19 | #include <linux/hardirq.h> | 19 | #include <linux/hardirq.h> |
20 | #include "xpc.h" | 20 | #include "xpc.h" |
21 | #include <asm/uv/uv_hub.h> | ||
21 | 22 | ||
22 | /* XPC is exiting flag */ | 23 | /* XPC is exiting flag */ |
23 | int xpc_exiting; | 24 | int xpc_exiting; |
@@ -92,8 +93,12 @@ xpc_get_rsvd_page_pa(int nasid) | |||
92 | break; | 93 | break; |
93 | 94 | ||
94 | /* !!! L1_CACHE_ALIGN() is only a sn2-bte_copy requirement */ | 95 | /* !!! L1_CACHE_ALIGN() is only a sn2-bte_copy requirement */ |
95 | if (L1_CACHE_ALIGN(len) > buf_len) { | 96 | if (is_shub()) |
96 | kfree(buf_base); | 97 | len = L1_CACHE_ALIGN(len); |
98 | |||
99 | if (len > buf_len) { | ||
100 | if (buf_base != NULL) | ||
101 | kfree(buf_base); | ||
97 | buf_len = L1_CACHE_ALIGN(len); | 102 | buf_len = L1_CACHE_ALIGN(len); |
98 | buf = xpc_kmalloc_cacheline_aligned(buf_len, GFP_KERNEL, | 103 | buf = xpc_kmalloc_cacheline_aligned(buf_len, GFP_KERNEL, |
99 | &buf_base); | 104 | &buf_base); |
@@ -105,7 +110,7 @@ xpc_get_rsvd_page_pa(int nasid) | |||
105 | } | 110 | } |
106 | } | 111 | } |
107 | 112 | ||
108 | ret = xp_remote_memcpy(xp_pa(buf), rp_pa, buf_len); | 113 | ret = xp_remote_memcpy(xp_pa(buf), rp_pa, len); |
109 | if (ret != xpSuccess) { | 114 | if (ret != xpSuccess) { |
110 | dev_dbg(xpc_part, "xp_remote_memcpy failed %d\n", ret); | 115 | dev_dbg(xpc_part, "xp_remote_memcpy failed %d\n", ret); |
111 | break; | 116 | break; |
@@ -143,7 +148,7 @@ xpc_setup_rsvd_page(void) | |||
143 | dev_err(xpc_part, "SAL failed to locate the reserved page\n"); | 148 | dev_err(xpc_part, "SAL failed to locate the reserved page\n"); |
144 | return -ESRCH; | 149 | return -ESRCH; |
145 | } | 150 | } |
146 | rp = (struct xpc_rsvd_page *)__va(rp_pa); | 151 | rp = (struct xpc_rsvd_page *)__va(xp_socket_pa(rp_pa)); |
147 | 152 | ||
148 | if (rp->SAL_version < 3) { | 153 | if (rp->SAL_version < 3) { |
149 | /* SAL_versions < 3 had a SAL_partid defined as a u8 */ | 154 | /* SAL_versions < 3 had a SAL_partid defined as a u8 */ |
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index b5bbe59f9c57..bbf0e2ee6fd9 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c | |||
@@ -157,22 +157,24 @@ xpc_gru_mq_watchlist_alloc_uv(struct xpc_gru_mq_uv *mq) | |||
157 | { | 157 | { |
158 | int ret; | 158 | int ret; |
159 | 159 | ||
160 | #if defined CONFIG_X86_64 | 160 | #if defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV |
161 | ret = uv_bios_mq_watchlist_alloc(mq->mmr_blade, uv_gpa(mq->address), | 161 | int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade); |
162 | mq->order, &mq->mmr_offset); | 162 | |
163 | if (ret < 0) { | 163 | ret = sn_mq_watchlist_alloc(mmr_pnode, (void *)uv_gpa(mq->address), |
164 | dev_err(xpc_part, "uv_bios_mq_watchlist_alloc() failed, " | ||
165 | "ret=%d\n", ret); | ||
166 | return ret; | ||
167 | } | ||
168 | #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV | ||
169 | ret = sn_mq_watchlist_alloc(mq->mmr_blade, (void *)uv_gpa(mq->address), | ||
170 | mq->order, &mq->mmr_offset); | 164 | mq->order, &mq->mmr_offset); |
171 | if (ret < 0) { | 165 | if (ret < 0) { |
172 | dev_err(xpc_part, "sn_mq_watchlist_alloc() failed, ret=%d\n", | 166 | dev_err(xpc_part, "sn_mq_watchlist_alloc() failed, ret=%d\n", |
173 | ret); | 167 | ret); |
174 | return -EBUSY; | 168 | return -EBUSY; |
175 | } | 169 | } |
170 | #elif defined CONFIG_X86_64 | ||
171 | ret = uv_bios_mq_watchlist_alloc(uv_gpa(mq->address), | ||
172 | mq->order, &mq->mmr_offset); | ||
173 | if (ret < 0) { | ||
174 | dev_err(xpc_part, "uv_bios_mq_watchlist_alloc() failed, " | ||
175 | "ret=%d\n", ret); | ||
176 | return ret; | ||
177 | } | ||
176 | #else | 178 | #else |
177 | #error not a supported configuration | 179 | #error not a supported configuration |
178 | #endif | 180 | #endif |
@@ -185,12 +187,13 @@ static void | |||
185 | xpc_gru_mq_watchlist_free_uv(struct xpc_gru_mq_uv *mq) | 187 | xpc_gru_mq_watchlist_free_uv(struct xpc_gru_mq_uv *mq) |
186 | { | 188 | { |
187 | int ret; | 189 | int ret; |
190 | int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade); | ||
188 | 191 | ||
189 | #if defined CONFIG_X86_64 | 192 | #if defined CONFIG_X86_64 |
190 | ret = uv_bios_mq_watchlist_free(mq->mmr_blade, mq->watchlist_num); | 193 | ret = uv_bios_mq_watchlist_free(mmr_pnode, mq->watchlist_num); |
191 | BUG_ON(ret != BIOS_STATUS_SUCCESS); | 194 | BUG_ON(ret != BIOS_STATUS_SUCCESS); |
192 | #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV | 195 | #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV |
193 | ret = sn_mq_watchlist_free(mq->mmr_blade, mq->watchlist_num); | 196 | ret = sn_mq_watchlist_free(mmr_pnode, mq->watchlist_num); |
194 | BUG_ON(ret != SALRET_OK); | 197 | BUG_ON(ret != SALRET_OK); |
195 | #else | 198 | #else |
196 | #error not a supported configuration | 199 | #error not a supported configuration |