diff options
Diffstat (limited to 'arch/ia64/sn')
25 files changed, 985 insertions, 1784 deletions
diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h index 71c2b271b4..8182583c76 100644 --- a/arch/ia64/sn/include/xtalk/hubdev.h +++ b/arch/ia64/sn/include/xtalk/hubdev.h | |||
@@ -26,29 +26,46 @@ | |||
26 | #define IIO_NUM_ITTES 7 | 26 | #define IIO_NUM_ITTES 7 |
27 | #define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1) | 27 | #define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1) |
28 | 28 | ||
29 | struct sn_flush_device_list { | 29 | /* This struct is shared between the PROM and the kernel. |
30 | * Changes to this struct will require corresponding changes to the kernel. | ||
31 | */ | ||
32 | struct sn_flush_device_common { | ||
30 | int sfdl_bus; | 33 | int sfdl_bus; |
31 | int sfdl_slot; | 34 | int sfdl_slot; |
32 | int sfdl_pin; | 35 | int sfdl_pin; |
33 | struct bar_list { | 36 | struct common_bar_list { |
34 | unsigned long start; | 37 | unsigned long start; |
35 | unsigned long end; | 38 | unsigned long end; |
36 | } sfdl_bar_list[6]; | 39 | } sfdl_bar_list[6]; |
37 | unsigned long sfdl_force_int_addr; | 40 | unsigned long sfdl_force_int_addr; |
38 | unsigned long sfdl_flush_value; | 41 | unsigned long sfdl_flush_value; |
39 | volatile unsigned long *sfdl_flush_addr; | 42 | volatile unsigned long *sfdl_flush_addr; |
40 | uint32_t sfdl_persistent_busnum; | 43 | u32 sfdl_persistent_busnum; |
41 | uint32_t sfdl_persistent_segment; | 44 | u32 sfdl_persistent_segment; |
42 | struct pcibus_info *sfdl_pcibus_info; | 45 | struct pcibus_info *sfdl_pcibus_info; |
46 | }; | ||
47 | |||
48 | /* This struct is kernel only and is not used by the PROM */ | ||
49 | struct sn_flush_device_kernel { | ||
43 | spinlock_t sfdl_flush_lock; | 50 | spinlock_t sfdl_flush_lock; |
51 | struct sn_flush_device_common *common; | ||
52 | }; | ||
53 | |||
54 | /* 01/16/06 This struct is the old PROM/kernel struct and needs to be included | ||
55 | * for older official PROMs to function on the new kernel base. This struct | ||
56 | * will be removed when the next official PROM release occurs. */ | ||
57 | |||
58 | struct sn_flush_device_war { | ||
59 | struct sn_flush_device_common common; | ||
60 | u32 filler; /* older PROMs expect the default size of a spinlock_t */ | ||
44 | }; | 61 | }; |
45 | 62 | ||
46 | /* | 63 | /* |
47 | * **widget_p - Used as an array[wid_num][device] of sn_flush_device_list. | 64 | * **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel. |
48 | */ | 65 | */ |
49 | struct sn_flush_nasid_entry { | 66 | struct sn_flush_nasid_entry { |
50 | struct sn_flush_device_list **widget_p; /* Used as a array of wid_num */ | 67 | struct sn_flush_device_kernel **widget_p; // Used as an array of wid_num |
51 | uint64_t iio_itte[8]; | 68 | u64 iio_itte[8]; |
52 | }; | 69 | }; |
53 | 70 | ||
54 | struct hubdev_info { | 71 | struct hubdev_info { |
@@ -62,8 +79,8 @@ struct hubdev_info { | |||
62 | 79 | ||
63 | void *hdi_nodepda; | 80 | void *hdi_nodepda; |
64 | void *hdi_node_vertex; | 81 | void *hdi_node_vertex; |
65 | uint32_t max_segment_number; | 82 | u32 max_segment_number; |
66 | uint32_t max_pcibus_number; | 83 | u32 max_pcibus_number; |
67 | }; | 84 | }; |
68 | 85 | ||
69 | extern void hubdev_init_node(nodepda_t *, cnodeid_t); | 86 | extern void hubdev_init_node(nodepda_t *, cnodeid_t); |
diff --git a/arch/ia64/sn/include/xtalk/xbow.h b/arch/ia64/sn/include/xtalk/xbow.h index ec56b3432f..90f37a4133 100644 --- a/arch/ia64/sn/include/xtalk/xbow.h +++ b/arch/ia64/sn/include/xtalk/xbow.h | |||
@@ -3,7 +3,8 @@ | |||
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) 1992-1997,2000-2004 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (C) 1992-1997,2000-2006 Silicon Graphics, Inc. All Rights |
7 | * Reserved. | ||
7 | */ | 8 | */ |
8 | #ifndef _ASM_IA64_SN_XTALK_XBOW_H | 9 | #ifndef _ASM_IA64_SN_XTALK_XBOW_H |
9 | #define _ASM_IA64_SN_XTALK_XBOW_H | 10 | #define _ASM_IA64_SN_XTALK_XBOW_H |
@@ -21,94 +22,94 @@ | |||
21 | 22 | ||
22 | /* Register set for each xbow link */ | 23 | /* Register set for each xbow link */ |
23 | typedef volatile struct xb_linkregs_s { | 24 | typedef volatile struct xb_linkregs_s { |
24 | /* | 25 | /* |
25 | * we access these through synergy unswizzled space, so the address | 26 | * we access these through synergy unswizzled space, so the address |
26 | * gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.) | 27 | * gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.) |
27 | * That's why we put the register first and filler second. | 28 | * That's why we put the register first and filler second. |
28 | */ | 29 | */ |
29 | uint32_t link_ibf; | 30 | u32 link_ibf; |
30 | uint32_t filler0; /* filler for proper alignment */ | 31 | u32 filler0; /* filler for proper alignment */ |
31 | uint32_t link_control; | 32 | u32 link_control; |
32 | uint32_t filler1; | 33 | u32 filler1; |
33 | uint32_t link_status; | 34 | u32 link_status; |
34 | uint32_t filler2; | 35 | u32 filler2; |
35 | uint32_t link_arb_upper; | 36 | u32 link_arb_upper; |
36 | uint32_t filler3; | 37 | u32 filler3; |
37 | uint32_t link_arb_lower; | 38 | u32 link_arb_lower; |
38 | uint32_t filler4; | 39 | u32 filler4; |
39 | uint32_t link_status_clr; | 40 | u32 link_status_clr; |
40 | uint32_t filler5; | 41 | u32 filler5; |
41 | uint32_t link_reset; | 42 | u32 link_reset; |
42 | uint32_t filler6; | 43 | u32 filler6; |
43 | uint32_t link_aux_status; | 44 | u32 link_aux_status; |
44 | uint32_t filler7; | 45 | u32 filler7; |
45 | } xb_linkregs_t; | 46 | } xb_linkregs_t; |
46 | 47 | ||
47 | typedef volatile struct xbow_s { | 48 | typedef volatile struct xbow_s { |
48 | /* standard widget configuration 0x000000-0x000057 */ | 49 | /* standard widget configuration 0x000000-0x000057 */ |
49 | struct widget_cfg xb_widget; /* 0x000000 */ | 50 | struct widget_cfg xb_widget; /* 0x000000 */ |
50 | 51 | ||
51 | /* helper fieldnames for accessing bridge widget */ | 52 | /* helper fieldnames for accessing bridge widget */ |
52 | 53 | ||
53 | #define xb_wid_id xb_widget.w_id | 54 | #define xb_wid_id xb_widget.w_id |
54 | #define xb_wid_stat xb_widget.w_status | 55 | #define xb_wid_stat xb_widget.w_status |
55 | #define xb_wid_err_upper xb_widget.w_err_upper_addr | 56 | #define xb_wid_err_upper xb_widget.w_err_upper_addr |
56 | #define xb_wid_err_lower xb_widget.w_err_lower_addr | 57 | #define xb_wid_err_lower xb_widget.w_err_lower_addr |
57 | #define xb_wid_control xb_widget.w_control | 58 | #define xb_wid_control xb_widget.w_control |
58 | #define xb_wid_req_timeout xb_widget.w_req_timeout | 59 | #define xb_wid_req_timeout xb_widget.w_req_timeout |
59 | #define xb_wid_int_upper xb_widget.w_intdest_upper_addr | 60 | #define xb_wid_int_upper xb_widget.w_intdest_upper_addr |
60 | #define xb_wid_int_lower xb_widget.w_intdest_lower_addr | 61 | #define xb_wid_int_lower xb_widget.w_intdest_lower_addr |
61 | #define xb_wid_err_cmdword xb_widget.w_err_cmd_word | 62 | #define xb_wid_err_cmdword xb_widget.w_err_cmd_word |
62 | #define xb_wid_llp xb_widget.w_llp_cfg | 63 | #define xb_wid_llp xb_widget.w_llp_cfg |
63 | #define xb_wid_stat_clr xb_widget.w_tflush | 64 | #define xb_wid_stat_clr xb_widget.w_tflush |
64 | 65 | ||
65 | /* | 66 | /* |
66 | * we access these through synergy unswizzled space, so the address | 67 | * we access these through synergy unswizzled space, so the address |
67 | * gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.) | 68 | * gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.) |
68 | * That's why we put the register first and filler second. | 69 | * That's why we put the register first and filler second. |
69 | */ | 70 | */ |
70 | /* xbow-specific widget configuration 0x000058-0x0000FF */ | 71 | /* xbow-specific widget configuration 0x000058-0x0000FF */ |
71 | uint32_t xb_wid_arb_reload; /* 0x00005C */ | 72 | u32 xb_wid_arb_reload; /* 0x00005C */ |
72 | uint32_t _pad_000058; | 73 | u32 _pad_000058; |
73 | uint32_t xb_perf_ctr_a; /* 0x000064 */ | 74 | u32 xb_perf_ctr_a; /* 0x000064 */ |
74 | uint32_t _pad_000060; | 75 | u32 _pad_000060; |
75 | uint32_t xb_perf_ctr_b; /* 0x00006c */ | 76 | u32 xb_perf_ctr_b; /* 0x00006c */ |
76 | uint32_t _pad_000068; | 77 | u32 _pad_000068; |
77 | uint32_t xb_nic; /* 0x000074 */ | 78 | u32 xb_nic; /* 0x000074 */ |
78 | uint32_t _pad_000070; | 79 | u32 _pad_000070; |
79 | 80 | ||
80 | /* Xbridge only */ | 81 | /* Xbridge only */ |
81 | uint32_t xb_w0_rst_fnc; /* 0x00007C */ | 82 | u32 xb_w0_rst_fnc; /* 0x00007C */ |
82 | uint32_t _pad_000078; | 83 | u32 _pad_000078; |
83 | uint32_t xb_l8_rst_fnc; /* 0x000084 */ | 84 | u32 xb_l8_rst_fnc; /* 0x000084 */ |
84 | uint32_t _pad_000080; | 85 | u32 _pad_000080; |
85 | uint32_t xb_l9_rst_fnc; /* 0x00008c */ | 86 | u32 xb_l9_rst_fnc; /* 0x00008c */ |
86 | uint32_t _pad_000088; | 87 | u32 _pad_000088; |
87 | uint32_t xb_la_rst_fnc; /* 0x000094 */ | 88 | u32 xb_la_rst_fnc; /* 0x000094 */ |
88 | uint32_t _pad_000090; | 89 | u32 _pad_000090; |
89 | uint32_t xb_lb_rst_fnc; /* 0x00009c */ | 90 | u32 xb_lb_rst_fnc; /* 0x00009c */ |
90 | uint32_t _pad_000098; | 91 | u32 _pad_000098; |
91 | uint32_t xb_lc_rst_fnc; /* 0x0000a4 */ | 92 | u32 xb_lc_rst_fnc; /* 0x0000a4 */ |
92 | uint32_t _pad_0000a0; | 93 | u32 _pad_0000a0; |
93 | uint32_t xb_ld_rst_fnc; /* 0x0000ac */ | 94 | u32 xb_ld_rst_fnc; /* 0x0000ac */ |
94 | uint32_t _pad_0000a8; | 95 | u32 _pad_0000a8; |
95 | uint32_t xb_le_rst_fnc; /* 0x0000b4 */ | 96 | u32 xb_le_rst_fnc; /* 0x0000b4 */ |
96 | uint32_t _pad_0000b0; | 97 | u32 _pad_0000b0; |
97 | uint32_t xb_lf_rst_fnc; /* 0x0000bc */ | 98 | u32 xb_lf_rst_fnc; /* 0x0000bc */ |
98 | uint32_t _pad_0000b8; | 99 | u32 _pad_0000b8; |
99 | uint32_t xb_lock; /* 0x0000c4 */ | 100 | u32 xb_lock; /* 0x0000c4 */ |
100 | uint32_t _pad_0000c0; | 101 | u32 _pad_0000c0; |
101 | uint32_t xb_lock_clr; /* 0x0000cc */ | 102 | u32 xb_lock_clr; /* 0x0000cc */ |
102 | uint32_t _pad_0000c8; | 103 | u32 _pad_0000c8; |
103 | /* end of Xbridge only */ | 104 | /* end of Xbridge only */ |
104 | uint32_t _pad_0000d0[12]; | 105 | u32 _pad_0000d0[12]; |
105 | 106 | ||
106 | /* Link Specific Registers, port 8..15 0x000100-0x000300 */ | 107 | /* Link Specific Registers, port 8..15 0x000100-0x000300 */ |
107 | xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS]; | 108 | xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS]; |
108 | #define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)] | ||
109 | |||
110 | } xbow_t; | 109 | } xbow_t; |
111 | 110 | ||
111 | #define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)] | ||
112 | |||
112 | #define XB_FLAGS_EXISTS 0x1 /* device exists */ | 113 | #define XB_FLAGS_EXISTS 0x1 /* device exists */ |
113 | #define XB_FLAGS_MASTER 0x2 | 114 | #define XB_FLAGS_MASTER 0x2 |
114 | #define XB_FLAGS_SLAVE 0x0 | 115 | #define XB_FLAGS_SLAVE 0x0 |
@@ -160,7 +161,7 @@ typedef volatile struct xbow_s { | |||
160 | /* End of Xbridge only */ | 161 | /* End of Xbridge only */ |
161 | 162 | ||
162 | /* used only in ide, but defined here within the reserved portion */ | 163 | /* used only in ide, but defined here within the reserved portion */ |
163 | /* of the widget0 address space (before 0xf4) */ | 164 | /* of the widget0 address space (before 0xf4) */ |
164 | #define XBOW_WID_UNDEF 0xe4 | 165 | #define XBOW_WID_UNDEF 0xe4 |
165 | 166 | ||
166 | /* xbow link register set base, legal value for x is 0x8..0xf */ | 167 | /* xbow link register set base, legal value for x is 0x8..0xf */ |
@@ -179,29 +180,37 @@ typedef volatile struct xbow_s { | |||
179 | 180 | ||
180 | /* link_control(x) */ | 181 | /* link_control(x) */ |
181 | #define XB_CTRL_LINKALIVE_IE 0x80000000 /* link comes alive */ | 182 | #define XB_CTRL_LINKALIVE_IE 0x80000000 /* link comes alive */ |
182 | /* reserved: 0x40000000 */ | 183 | /* reserved: 0x40000000 */ |
183 | #define XB_CTRL_PERF_CTR_MODE_MSK 0x30000000 /* perf counter mode */ | 184 | #define XB_CTRL_PERF_CTR_MODE_MSK 0x30000000 /* perf counter mode */ |
184 | #define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer level */ | 185 | #define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer |
185 | #define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8 bit mode */ | 186 | level */ |
186 | #define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP packet */ | 187 | #define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8 |
187 | #define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit mask */ | 188 | bit mode */ |
188 | #define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit shift */ | 189 | #define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP |
189 | #define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination */ | 190 | packet */ |
190 | #define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input buffer */ | 191 | #define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit |
191 | /* reserved: 0x0000fe00 */ | 192 | mask */ |
193 | #define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit | ||
194 | shift */ | ||
195 | #define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination | ||
196 | */ | ||
197 | #define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input | ||
198 | buffer */ | ||
199 | /* reserved: 0x0000fe00 */ | ||
192 | #define XB_CTRL_BNDWDTH_ALLOC_IE 0x00000100 /* bandwidth alloc */ | 200 | #define XB_CTRL_BNDWDTH_ALLOC_IE 0x00000100 /* bandwidth alloc */ |
193 | #define XB_CTRL_RCV_CNT_OFLOW_IE 0x00000080 /* rcv retry overflow */ | 201 | #define XB_CTRL_RCV_CNT_OFLOW_IE 0x00000080 /* rcv retry overflow */ |
194 | #define XB_CTRL_XMT_CNT_OFLOW_IE 0x00000040 /* xmt retry overflow */ | 202 | #define XB_CTRL_XMT_CNT_OFLOW_IE 0x00000040 /* xmt retry overflow */ |
195 | #define XB_CTRL_XMT_MAX_RTRY_IE 0x00000020 /* max transmit retry */ | 203 | #define XB_CTRL_XMT_MAX_RTRY_IE 0x00000020 /* max transmit retry */ |
196 | #define XB_CTRL_RCV_IE 0x00000010 /* receive */ | 204 | #define XB_CTRL_RCV_IE 0x00000010 /* receive */ |
197 | #define XB_CTRL_XMT_RTRY_IE 0x00000008 /* transmit retry */ | 205 | #define XB_CTRL_XMT_RTRY_IE 0x00000008 /* transmit retry */ |
198 | /* reserved: 0x00000004 */ | 206 | /* reserved: 0x00000004 */ |
199 | #define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request timeout */ | 207 | #define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request |
208 | timeout */ | ||
200 | #define XB_CTRL_SRC_TOUT_IE 0x00000001 /* source timeout */ | 209 | #define XB_CTRL_SRC_TOUT_IE 0x00000001 /* source timeout */ |
201 | 210 | ||
202 | /* link_status(x) */ | 211 | /* link_status(x) */ |
203 | #define XB_STAT_LINKALIVE XB_CTRL_LINKALIVE_IE | 212 | #define XB_STAT_LINKALIVE XB_CTRL_LINKALIVE_IE |
204 | /* reserved: 0x7ff80000 */ | 213 | /* reserved: 0x7ff80000 */ |
205 | #define XB_STAT_MULTI_ERR 0x00040000 /* multi error */ | 214 | #define XB_STAT_MULTI_ERR 0x00040000 /* multi error */ |
206 | #define XB_STAT_ILLEGAL_DST_ERR XB_CTRL_ILLEGAL_DST_IE | 215 | #define XB_STAT_ILLEGAL_DST_ERR XB_CTRL_ILLEGAL_DST_IE |
207 | #define XB_STAT_OALLOC_IBUF_ERR XB_CTRL_OALLOC_IBUF_IE | 216 | #define XB_STAT_OALLOC_IBUF_ERR XB_CTRL_OALLOC_IBUF_IE |
@@ -211,7 +220,7 @@ typedef volatile struct xbow_s { | |||
211 | #define XB_STAT_XMT_MAX_RTRY_ERR XB_CTRL_XMT_MAX_RTRY_IE | 220 | #define XB_STAT_XMT_MAX_RTRY_ERR XB_CTRL_XMT_MAX_RTRY_IE |
212 | #define XB_STAT_RCV_ERR XB_CTRL_RCV_IE | 221 | #define XB_STAT_RCV_ERR XB_CTRL_RCV_IE |
213 | #define XB_STAT_XMT_RTRY_ERR XB_CTRL_XMT_RTRY_IE | 222 | #define XB_STAT_XMT_RTRY_ERR XB_CTRL_XMT_RTRY_IE |
214 | /* reserved: 0x00000004 */ | 223 | /* reserved: 0x00000004 */ |
215 | #define XB_STAT_MAXREQ_TOUT_ERR XB_CTRL_MAXREQ_TOUT_IE | 224 | #define XB_STAT_MAXREQ_TOUT_ERR XB_CTRL_MAXREQ_TOUT_IE |
216 | #define XB_STAT_SRC_TOUT_ERR XB_CTRL_SRC_TOUT_IE | 225 | #define XB_STAT_SRC_TOUT_ERR XB_CTRL_SRC_TOUT_IE |
217 | 226 | ||
@@ -222,7 +231,7 @@ typedef volatile struct xbow_s { | |||
222 | #define XB_AUX_LINKFAIL_RST_BAD 0x00000040 | 231 | #define XB_AUX_LINKFAIL_RST_BAD 0x00000040 |
223 | #define XB_AUX_STAT_PRESENT 0x00000020 | 232 | #define XB_AUX_STAT_PRESENT 0x00000020 |
224 | #define XB_AUX_STAT_PORT_WIDTH 0x00000010 | 233 | #define XB_AUX_STAT_PORT_WIDTH 0x00000010 |
225 | /* reserved: 0x0000000f */ | 234 | /* reserved: 0x0000000f */ |
226 | 235 | ||
227 | /* | 236 | /* |
228 | * link_arb_upper/link_arb_lower(x), (reg) should be the link_arb_upper | 237 | * link_arb_upper/link_arb_lower(x), (reg) should be the link_arb_upper |
@@ -238,7 +247,8 @@ typedef volatile struct xbow_s { | |||
238 | /* XBOW_WID_STAT */ | 247 | /* XBOW_WID_STAT */ |
239 | #define XB_WID_STAT_LINK_INTR_SHFT (24) | 248 | #define XB_WID_STAT_LINK_INTR_SHFT (24) |
240 | #define XB_WID_STAT_LINK_INTR_MASK (0xFF << XB_WID_STAT_LINK_INTR_SHFT) | 249 | #define XB_WID_STAT_LINK_INTR_MASK (0xFF << XB_WID_STAT_LINK_INTR_SHFT) |
241 | #define XB_WID_STAT_LINK_INTR(x) (0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT)) | 250 | #define XB_WID_STAT_LINK_INTR(x) \ |
251 | (0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT)) | ||
242 | #define XB_WID_STAT_WIDGET0_INTR 0x00800000 | 252 | #define XB_WID_STAT_WIDGET0_INTR 0x00800000 |
243 | #define XB_WID_STAT_SRCID_MASK 0x000003c0 /* Xbridge only */ | 253 | #define XB_WID_STAT_SRCID_MASK 0x000003c0 /* Xbridge only */ |
244 | #define XB_WID_STAT_REG_ACC_ERR 0x00000020 | 254 | #define XB_WID_STAT_REG_ACC_ERR 0x00000020 |
@@ -264,7 +274,7 @@ typedef volatile struct xbow_s { | |||
264 | #define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */ | 274 | #define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */ |
265 | #define XBOW_WIDGET_MFGR_NUM 0x0 | 275 | #define XBOW_WIDGET_MFGR_NUM 0x0 |
266 | #define XXBOW_WIDGET_MFGR_NUM 0x0 | 276 | #define XXBOW_WIDGET_MFGR_NUM 0x0 |
267 | #define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */ | 277 | #define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */ |
268 | 278 | ||
269 | #define XBOW_REV_1_0 0x1 /* xbow rev 1.0 is "1" */ | 279 | #define XBOW_REV_1_0 0x1 /* xbow rev 1.0 is "1" */ |
270 | #define XBOW_REV_1_1 0x2 /* xbow rev 1.1 is "2" */ | 280 | #define XBOW_REV_1_1 0x2 /* xbow rev 1.1 is "2" */ |
@@ -279,13 +289,13 @@ typedef volatile struct xbow_s { | |||
279 | #define XBOW_WID_ARB_RELOAD_INT 0x3f /* GBR reload interval */ | 289 | #define XBOW_WID_ARB_RELOAD_INT 0x3f /* GBR reload interval */ |
280 | 290 | ||
281 | #define IS_XBRIDGE_XBOW(wid) \ | 291 | #define IS_XBRIDGE_XBOW(wid) \ |
282 | (XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \ | 292 | (XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \ |
283 | XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) | 293 | XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) |
284 | 294 | ||
285 | #define IS_PIC_XBOW(wid) \ | 295 | #define IS_PIC_XBOW(wid) \ |
286 | (XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \ | 296 | (XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \ |
287 | XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) | 297 | XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) |
288 | 298 | ||
289 | #define XBOW_WAR_ENABLED(pv, widid) ((1 << XWIDGET_REV_NUM(widid)) & pv) | 299 | #define XBOW_WAR_ENABLED(pv, widid) ((1 << XWIDGET_REV_NUM(widid)) & pv) |
290 | 300 | ||
291 | #endif /* _ASM_IA64_SN_XTALK_XBOW_H */ | 301 | #endif /* _ASM_IA64_SN_XTALK_XBOW_H */ |
diff --git a/arch/ia64/sn/include/xtalk/xwidgetdev.h b/arch/ia64/sn/include/xtalk/xwidgetdev.h index c5f4bc5cc0..2800eda0fd 100644 --- a/arch/ia64/sn/include/xtalk/xwidgetdev.h +++ b/arch/ia64/sn/include/xtalk/xwidgetdev.h | |||
@@ -25,28 +25,28 @@ | |||
25 | 25 | ||
26 | /* widget configuration registers */ | 26 | /* widget configuration registers */ |
27 | struct widget_cfg{ | 27 | struct widget_cfg{ |
28 | uint32_t w_id; /* 0x04 */ | 28 | u32 w_id; /* 0x04 */ |
29 | uint32_t w_pad_0; /* 0x00 */ | 29 | u32 w_pad_0; /* 0x00 */ |
30 | uint32_t w_status; /* 0x0c */ | 30 | u32 w_status; /* 0x0c */ |
31 | uint32_t w_pad_1; /* 0x08 */ | 31 | u32 w_pad_1; /* 0x08 */ |
32 | uint32_t w_err_upper_addr; /* 0x14 */ | 32 | u32 w_err_upper_addr; /* 0x14 */ |
33 | uint32_t w_pad_2; /* 0x10 */ | 33 | u32 w_pad_2; /* 0x10 */ |
34 | uint32_t w_err_lower_addr; /* 0x1c */ | 34 | u32 w_err_lower_addr; /* 0x1c */ |
35 | uint32_t w_pad_3; /* 0x18 */ | 35 | u32 w_pad_3; /* 0x18 */ |
36 | uint32_t w_control; /* 0x24 */ | 36 | u32 w_control; /* 0x24 */ |
37 | uint32_t w_pad_4; /* 0x20 */ | 37 | u32 w_pad_4; /* 0x20 */ |
38 | uint32_t w_req_timeout; /* 0x2c */ | 38 | u32 w_req_timeout; /* 0x2c */ |
39 | uint32_t w_pad_5; /* 0x28 */ | 39 | u32 w_pad_5; /* 0x28 */ |
40 | uint32_t w_intdest_upper_addr; /* 0x34 */ | 40 | u32 w_intdest_upper_addr; /* 0x34 */ |
41 | uint32_t w_pad_6; /* 0x30 */ | 41 | u32 w_pad_6; /* 0x30 */ |
42 | uint32_t w_intdest_lower_addr; /* 0x3c */ | 42 | u32 w_intdest_lower_addr; /* 0x3c */ |
43 | uint32_t w_pad_7; /* 0x38 */ | 43 | u32 w_pad_7; /* 0x38 */ |
44 | uint32_t w_err_cmd_word; /* 0x44 */ | 44 | u32 w_err_cmd_word; /* 0x44 */ |
45 | uint32_t w_pad_8; /* 0x40 */ | 45 | u32 w_pad_8; /* 0x40 */ |
46 | uint32_t w_llp_cfg; /* 0x4c */ | 46 | u32 w_llp_cfg; /* 0x4c */ |
47 | uint32_t w_pad_9; /* 0x48 */ | 47 | u32 w_pad_9; /* 0x48 */ |
48 | uint32_t w_tflush; /* 0x54 */ | 48 | u32 w_tflush; /* 0x54 */ |
49 | uint32_t w_pad_10; /* 0x50 */ | 49 | u32 w_pad_10; /* 0x50 */ |
50 | }; | 50 | }; |
51 | 51 | ||
52 | /* | 52 | /* |
@@ -63,7 +63,7 @@ struct xwidget_info{ | |||
63 | struct xwidget_hwid xwi_hwid; /* Widget Identification */ | 63 | struct xwidget_hwid xwi_hwid; /* Widget Identification */ |
64 | char xwi_masterxid; /* Hub's Widget Port Number */ | 64 | char xwi_masterxid; /* Hub's Widget Port Number */ |
65 | void *xwi_hubinfo; /* Hub's provider private info */ | 65 | void *xwi_hubinfo; /* Hub's provider private info */ |
66 | uint64_t *xwi_hub_provider; /* prom provider functions */ | 66 | u64 *xwi_hub_provider; /* prom provider functions */ |
67 | void *xwi_vertex; | 67 | void *xwi_vertex; |
68 | }; | 68 | }; |
69 | 69 | ||
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c index d71f4de44f..dd73c0cb75 100644 --- a/arch/ia64/sn/kernel/bte.c +++ b/arch/ia64/sn/kernel/bte.c | |||
@@ -137,6 +137,7 @@ retry_bteop: | |||
137 | bte = bte_if_on_node(nasid_to_try[nasid_index],bte_if_index); | 137 | bte = bte_if_on_node(nasid_to_try[nasid_index],bte_if_index); |
138 | 138 | ||
139 | if (bte == NULL) { | 139 | if (bte == NULL) { |
140 | nasid_index++; | ||
140 | continue; | 141 | continue; |
141 | } | 142 | } |
142 | 143 | ||
diff --git a/arch/ia64/sn/kernel/bte_error.c b/arch/ia64/sn/kernel/bte_error.c index fcbc748ae4..f1ec1370b3 100644 --- a/arch/ia64/sn/kernel/bte_error.c +++ b/arch/ia64/sn/kernel/bte_error.c | |||
@@ -33,7 +33,7 @@ void bte_error_handler(unsigned long); | |||
33 | * Wait until all BTE related CRBs are completed | 33 | * Wait until all BTE related CRBs are completed |
34 | * and then reset the interfaces. | 34 | * and then reset the interfaces. |
35 | */ | 35 | */ |
36 | void shub1_bte_error_handler(unsigned long _nodepda) | 36 | int shub1_bte_error_handler(unsigned long _nodepda) |
37 | { | 37 | { |
38 | struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; | 38 | struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; |
39 | struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer; | 39 | struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer; |
@@ -53,7 +53,7 @@ void shub1_bte_error_handler(unsigned long _nodepda) | |||
53 | (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) { | 53 | (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) { |
54 | BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda, | 54 | BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda, |
55 | smp_processor_id())); | 55 | smp_processor_id())); |
56 | return; | 56 | return 1; |
57 | } | 57 | } |
58 | 58 | ||
59 | /* Determine information about our hub */ | 59 | /* Determine information about our hub */ |
@@ -81,7 +81,7 @@ void shub1_bte_error_handler(unsigned long _nodepda) | |||
81 | mod_timer(recovery_timer, HZ * 5); | 81 | mod_timer(recovery_timer, HZ * 5); |
82 | BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda, | 82 | BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda, |
83 | smp_processor_id())); | 83 | smp_processor_id())); |
84 | return; | 84 | return 1; |
85 | } | 85 | } |
86 | if (icmr.ii_icmr_fld_s.i_crb_vld != 0) { | 86 | if (icmr.ii_icmr_fld_s.i_crb_vld != 0) { |
87 | 87 | ||
@@ -99,7 +99,7 @@ void shub1_bte_error_handler(unsigned long _nodepda) | |||
99 | BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n", | 99 | BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n", |
100 | err_nodepda, smp_processor_id(), | 100 | err_nodepda, smp_processor_id(), |
101 | i)); | 101 | i)); |
102 | return; | 102 | return 1; |
103 | } | 103 | } |
104 | } | 104 | } |
105 | } | 105 | } |
@@ -124,6 +124,42 @@ void shub1_bte_error_handler(unsigned long _nodepda) | |||
124 | REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval); | 124 | REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval); |
125 | 125 | ||
126 | del_timer(recovery_timer); | 126 | del_timer(recovery_timer); |
127 | return 0; | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * Wait until all BTE related CRBs are completed | ||
132 | * and then reset the interfaces. | ||
133 | */ | ||
134 | int shub2_bte_error_handler(unsigned long _nodepda) | ||
135 | { | ||
136 | struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; | ||
137 | struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer; | ||
138 | struct bteinfo_s *bte; | ||
139 | nasid_t nasid; | ||
140 | u64 status; | ||
141 | int i; | ||
142 | |||
143 | nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode); | ||
144 | |||
145 | /* | ||
146 | * Verify that all the BTEs are complete | ||
147 | */ | ||
148 | for (i = 0; i < BTES_PER_NODE; i++) { | ||
149 | bte = &err_nodepda->bte_if[i]; | ||
150 | status = BTE_LNSTAT_LOAD(bte); | ||
151 | if ((status & IBLS_ERROR) || !(status & IBLS_BUSY)) | ||
152 | continue; | ||
153 | mod_timer(recovery_timer, HZ * 5); | ||
154 | BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda, | ||
155 | smp_processor_id())); | ||
156 | return 1; | ||
157 | } | ||
158 | if (ia64_sn_bte_recovery(nasid)) | ||
159 | panic("bte_error_handler(): Fatal BTE Error"); | ||
160 | |||
161 | del_timer(recovery_timer); | ||
162 | return 0; | ||
127 | } | 163 | } |
128 | 164 | ||
129 | /* | 165 | /* |
@@ -135,7 +171,6 @@ void bte_error_handler(unsigned long _nodepda) | |||
135 | struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; | 171 | struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; |
136 | spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock; | 172 | spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock; |
137 | int i; | 173 | int i; |
138 | nasid_t nasid; | ||
139 | unsigned long irq_flags; | 174 | unsigned long irq_flags; |
140 | volatile u64 *notify; | 175 | volatile u64 *notify; |
141 | bte_result_t bh_error; | 176 | bte_result_t bh_error; |
@@ -160,12 +195,15 @@ void bte_error_handler(unsigned long _nodepda) | |||
160 | } | 195 | } |
161 | 196 | ||
162 | if (is_shub1()) { | 197 | if (is_shub1()) { |
163 | shub1_bte_error_handler(_nodepda); | 198 | if (shub1_bte_error_handler(_nodepda)) { |
199 | spin_unlock_irqrestore(recovery_lock, irq_flags); | ||
200 | return; | ||
201 | } | ||
164 | } else { | 202 | } else { |
165 | nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode); | 203 | if (shub2_bte_error_handler(_nodepda)) { |
166 | 204 | spin_unlock_irqrestore(recovery_lock, irq_flags); | |
167 | if (ia64_sn_bte_recovery(nasid)) | 205 | return; |
168 | panic("bte_error_handler(): Fatal BTE Error"); | 206 | } |
169 | } | 207 | } |
170 | 208 | ||
171 | for (i = 0; i < BTES_PER_NODE; i++) { | 209 | for (i = 0; i < BTES_PER_NODE; i++) { |
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c index 5c5eb01c50..56ab6bae00 100644 --- a/arch/ia64/sn/kernel/huberror.c +++ b/arch/ia64/sn/kernel/huberror.c | |||
@@ -32,13 +32,14 @@ static irqreturn_t hub_eint_handler(int irq, void *arg, struct pt_regs *ep) | |||
32 | ret_stuff.v0 = 0; | 32 | ret_stuff.v0 = 0; |
33 | hubdev_info = (struct hubdev_info *)arg; | 33 | hubdev_info = (struct hubdev_info *)arg; |
34 | nasid = hubdev_info->hdi_nasid; | 34 | nasid = hubdev_info->hdi_nasid; |
35 | SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT, | 35 | |
36 | if (is_shub1()) { | ||
37 | SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT, | ||
36 | (u64) nasid, 0, 0, 0, 0, 0, 0); | 38 | (u64) nasid, 0, 0, 0, 0, 0, 0); |
37 | 39 | ||
38 | if ((int)ret_stuff.v0) | 40 | if ((int)ret_stuff.v0) |
39 | panic("hubii_eint_handler(): Fatal TIO Error"); | 41 | panic("hubii_eint_handler(): Fatal TIO Error"); |
40 | 42 | ||
41 | if (is_shub1()) { | ||
42 | if (!(nasid & 1)) /* Not a TIO, handle CRB errors */ | 43 | if (!(nasid & 1)) /* Not a TIO, handle CRB errors */ |
43 | (void)hubiio_crb_error_handler(hubdev_info); | 44 | (void)hubiio_crb_error_handler(hubdev_info); |
44 | } else | 45 | } else |
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 05e4ea8899..00700f7e68 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.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) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. | 6 | * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/bootmem.h> | 9 | #include <linux/bootmem.h> |
@@ -76,11 +76,12 @@ static struct sn_pcibus_provider sn_pci_default_provider = { | |||
76 | }; | 76 | }; |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * Retrieve the DMA Flush List given nasid. This list is needed | 79 | * Retrieve the DMA Flush List given nasid, widget, and device. |
80 | * to implement the WAR - Flush DMA data on PIO Reads. | 80 | * This list is needed to implement the WAR - Flush DMA data on PIO Reads. |
81 | */ | 81 | */ |
82 | static inline uint64_t | 82 | static inline u64 |
83 | sal_get_widget_dmaflush_list(u64 nasid, u64 widget_num, u64 address) | 83 | sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, |
84 | u64 address) | ||
84 | { | 85 | { |
85 | 86 | ||
86 | struct ia64_sal_retval ret_stuff; | 87 | struct ia64_sal_retval ret_stuff; |
@@ -88,17 +89,17 @@ sal_get_widget_dmaflush_list(u64 nasid, u64 widget_num, u64 address) | |||
88 | ret_stuff.v0 = 0; | 89 | ret_stuff.v0 = 0; |
89 | 90 | ||
90 | SAL_CALL_NOLOCK(ret_stuff, | 91 | SAL_CALL_NOLOCK(ret_stuff, |
91 | (u64) SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST, | 92 | (u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST, |
92 | (u64) nasid, (u64) widget_num, (u64) address, 0, 0, 0, | 93 | (u64) nasid, (u64) widget_num, |
93 | 0); | 94 | (u64) device_num, (u64) address, 0, 0, 0); |
94 | return ret_stuff.v0; | 95 | return ret_stuff.status; |
95 | 96 | ||
96 | } | 97 | } |
97 | 98 | ||
98 | /* | 99 | /* |
99 | * Retrieve the hub device info structure for the given nasid. | 100 | * Retrieve the hub device info structure for the given nasid. |
100 | */ | 101 | */ |
101 | static inline uint64_t sal_get_hubdev_info(u64 handle, u64 address) | 102 | static inline u64 sal_get_hubdev_info(u64 handle, u64 address) |
102 | { | 103 | { |
103 | 104 | ||
104 | struct ia64_sal_retval ret_stuff; | 105 | struct ia64_sal_retval ret_stuff; |
@@ -114,7 +115,7 @@ static inline uint64_t sal_get_hubdev_info(u64 handle, u64 address) | |||
114 | /* | 115 | /* |
115 | * Retrieve the pci bus information given the bus number. | 116 | * Retrieve the pci bus information given the bus number. |
116 | */ | 117 | */ |
117 | static inline uint64_t sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) | 118 | static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) |
118 | { | 119 | { |
119 | 120 | ||
120 | struct ia64_sal_retval ret_stuff; | 121 | struct ia64_sal_retval ret_stuff; |
@@ -130,9 +131,9 @@ static inline uint64_t sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) | |||
130 | /* | 131 | /* |
131 | * Retrieve the pci device information given the bus and device|function number. | 132 | * Retrieve the pci device information given the bus and device|function number. |
132 | */ | 133 | */ |
133 | static inline uint64_t | 134 | static inline u64 |
134 | sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, | 135 | sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, |
135 | u64 sn_irq_info) | 136 | u64 sn_irq_info) |
136 | { | 137 | { |
137 | struct ia64_sal_retval ret_stuff; | 138 | struct ia64_sal_retval ret_stuff; |
138 | ret_stuff.status = 0; | 139 | ret_stuff.status = 0; |
@@ -140,24 +141,79 @@ sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, | |||
140 | 141 | ||
141 | SAL_CALL_NOLOCK(ret_stuff, | 142 | SAL_CALL_NOLOCK(ret_stuff, |
142 | (u64) SN_SAL_IOIF_GET_PCIDEV_INFO, | 143 | (u64) SN_SAL_IOIF_GET_PCIDEV_INFO, |
143 | (u64) segment, (u64) bus_number, (u64) devfn, | 144 | (u64) segment, (u64) bus_number, (u64) devfn, |
144 | (u64) pci_dev, | 145 | (u64) pci_dev, |
145 | sn_irq_info, 0, 0); | 146 | sn_irq_info, 0, 0); |
146 | return ret_stuff.v0; | 147 | return ret_stuff.v0; |
147 | } | 148 | } |
148 | 149 | ||
149 | /* | 150 | /* |
150 | * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for | 151 | * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified |
152 | * device. | ||
153 | */ | ||
154 | inline struct pcidev_info * | ||
155 | sn_pcidev_info_get(struct pci_dev *dev) | ||
156 | { | ||
157 | struct pcidev_info *pcidev; | ||
158 | |||
159 | list_for_each_entry(pcidev, | ||
160 | &(SN_PCI_CONTROLLER(dev)->pcidev_info), pdi_list) { | ||
161 | if (pcidev->pdi_linux_pcidev == dev) { | ||
162 | return pcidev; | ||
163 | } | ||
164 | } | ||
165 | return NULL; | ||
166 | } | ||
167 | |||
168 | /* Older PROM flush WAR | ||
169 | * | ||
170 | * 01/16/06 -- This war will be in place until a new official PROM is released. | ||
171 | * Additionally note that the struct sn_flush_device_war also has to be | ||
172 | * removed from arch/ia64/sn/include/xtalk/hubdev.h | ||
173 | */ | ||
174 | static u8 war_implemented = 0; | ||
175 | |||
176 | static void sn_device_fixup_war(u64 nasid, u64 widget, int device, | ||
177 | struct sn_flush_device_common *common) | ||
178 | { | ||
179 | struct sn_flush_device_war *war_list; | ||
180 | struct sn_flush_device_war *dev_entry; | ||
181 | struct ia64_sal_retval isrv = {0,0,0,0}; | ||
182 | |||
183 | if (!war_implemented) { | ||
184 | printk(KERN_WARNING "PROM version < 4.50 -- implementing old " | ||
185 | "PROM flush WAR\n"); | ||
186 | war_implemented = 1; | ||
187 | } | ||
188 | |||
189 | war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL); | ||
190 | if (!war_list) | ||
191 | BUG(); | ||
192 | |||
193 | SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST, | ||
194 | nasid, widget, __pa(war_list), 0, 0, 0 ,0); | ||
195 | if (isrv.status) | ||
196 | panic("sn_device_fixup_war failed: %s\n", | ||
197 | ia64_sal_strerror(isrv.status)); | ||
198 | |||
199 | dev_entry = war_list + device; | ||
200 | memcpy(common,dev_entry, sizeof(*common)); | ||
201 | |||
202 | kfree(war_list); | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for | ||
151 | * each node in the system. | 207 | * each node in the system. |
152 | */ | 208 | */ |
153 | static void sn_fixup_ionodes(void) | 209 | static void sn_fixup_ionodes(void) |
154 | { | 210 | { |
155 | 211 | struct sn_flush_device_kernel *sn_flush_device_kernel; | |
156 | struct sn_flush_device_list *sn_flush_device_list; | 212 | struct sn_flush_device_kernel *dev_entry; |
157 | struct hubdev_info *hubdev; | 213 | struct hubdev_info *hubdev; |
158 | uint64_t status; | 214 | u64 status; |
159 | uint64_t nasid; | 215 | u64 nasid; |
160 | int i, widget; | 216 | int i, widget, device; |
161 | 217 | ||
162 | /* | 218 | /* |
163 | * Get SGI Specific HUB chipset information. | 219 | * Get SGI Specific HUB chipset information. |
@@ -168,7 +224,7 @@ static void sn_fixup_ionodes(void) | |||
168 | nasid = cnodeid_to_nasid(i); | 224 | nasid = cnodeid_to_nasid(i); |
169 | hubdev->max_segment_number = 0xffffffff; | 225 | hubdev->max_segment_number = 0xffffffff; |
170 | hubdev->max_pcibus_number = 0xff; | 226 | hubdev->max_pcibus_number = 0xff; |
171 | status = sal_get_hubdev_info(nasid, (uint64_t) __pa(hubdev)); | 227 | status = sal_get_hubdev_info(nasid, (u64) __pa(hubdev)); |
172 | if (status) | 228 | if (status) |
173 | continue; | 229 | continue; |
174 | 230 | ||
@@ -195,38 +251,104 @@ static void sn_fixup_ionodes(void) | |||
195 | 251 | ||
196 | hubdev->hdi_flush_nasid_list.widget_p = | 252 | hubdev->hdi_flush_nasid_list.widget_p = |
197 | kmalloc((HUB_WIDGET_ID_MAX + 1) * | 253 | kmalloc((HUB_WIDGET_ID_MAX + 1) * |
198 | sizeof(struct sn_flush_device_list *), GFP_KERNEL); | 254 | sizeof(struct sn_flush_device_kernel *), |
199 | 255 | GFP_KERNEL); | |
200 | memset(hubdev->hdi_flush_nasid_list.widget_p, 0x0, | 256 | memset(hubdev->hdi_flush_nasid_list.widget_p, 0x0, |
201 | (HUB_WIDGET_ID_MAX + 1) * | 257 | (HUB_WIDGET_ID_MAX + 1) * |
202 | sizeof(struct sn_flush_device_list *)); | 258 | sizeof(struct sn_flush_device_kernel *)); |
203 | 259 | ||
204 | for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { | 260 | for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { |
205 | sn_flush_device_list = kmalloc(DEV_PER_WIDGET * | 261 | sn_flush_device_kernel = kmalloc(DEV_PER_WIDGET * |
206 | sizeof(struct | 262 | sizeof(struct |
207 | sn_flush_device_list), | 263 | sn_flush_device_kernel), |
208 | GFP_KERNEL); | 264 | GFP_KERNEL); |
209 | memset(sn_flush_device_list, 0x0, | 265 | if (!sn_flush_device_kernel) |
266 | BUG(); | ||
267 | memset(sn_flush_device_kernel, 0x0, | ||
210 | DEV_PER_WIDGET * | 268 | DEV_PER_WIDGET * |
211 | sizeof(struct sn_flush_device_list)); | 269 | sizeof(struct sn_flush_device_kernel)); |
212 | 270 | ||
213 | status = | 271 | dev_entry = sn_flush_device_kernel; |
214 | sal_get_widget_dmaflush_list(nasid, widget, | 272 | for (device = 0; device < DEV_PER_WIDGET; |
215 | (uint64_t) | 273 | device++,dev_entry++) { |
216 | __pa | 274 | dev_entry->common = kmalloc(sizeof(struct |
217 | (sn_flush_device_list)); | 275 | sn_flush_device_common), |
218 | if (status) { | 276 | GFP_KERNEL); |
219 | kfree(sn_flush_device_list); | 277 | if (!dev_entry->common) |
220 | continue; | 278 | BUG(); |
279 | memset(dev_entry->common, 0x0, sizeof(struct | ||
280 | sn_flush_device_common)); | ||
281 | |||
282 | status = sal_get_device_dmaflush_list(nasid, | ||
283 | widget, | ||
284 | device, | ||
285 | (u64)(dev_entry->common)); | ||
286 | if (status) { | ||
287 | if (sn_sal_rev() < 0x0450) { | ||
288 | /* shortlived WAR for older | ||
289 | * PROM images | ||
290 | */ | ||
291 | sn_device_fixup_war(nasid, | ||
292 | widget, | ||
293 | device, | ||
294 | dev_entry->common); | ||
295 | } | ||
296 | else | ||
297 | BUG(); | ||
298 | } | ||
299 | |||
300 | spin_lock_init(&dev_entry->sfdl_flush_lock); | ||
221 | } | 301 | } |
222 | 302 | ||
223 | spin_lock_init(&sn_flush_device_list->sfdl_flush_lock); | 303 | if (sn_flush_device_kernel) |
224 | hubdev->hdi_flush_nasid_list.widget_p[widget] = | 304 | hubdev->hdi_flush_nasid_list.widget_p[widget] = |
225 | sn_flush_device_list; | 305 | sn_flush_device_kernel; |
226 | } | 306 | } |
307 | } | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * sn_pci_window_fixup() - Create a pci_window for each device resource. | ||
312 | * Until ACPI support is added, we need this code | ||
313 | * to setup pci_windows for use by | ||
314 | * pcibios_bus_to_resource(), | ||
315 | * pcibios_resource_to_bus(), etc. | ||
316 | */ | ||
317 | static void | ||
318 | sn_pci_window_fixup(struct pci_dev *dev, unsigned int count, | ||
319 | s64 * pci_addrs) | ||
320 | { | ||
321 | struct pci_controller *controller = PCI_CONTROLLER(dev->bus); | ||
322 | unsigned int i; | ||
323 | unsigned int idx; | ||
324 | unsigned int new_count; | ||
325 | struct pci_window *new_window; | ||
326 | |||
327 | if (count == 0) | ||
328 | return; | ||
329 | idx = controller->windows; | ||
330 | new_count = controller->windows + count; | ||
331 | new_window = kcalloc(new_count, sizeof(struct pci_window), GFP_KERNEL); | ||
332 | if (new_window == NULL) | ||
333 | BUG(); | ||
334 | if (controller->window) { | ||
335 | memcpy(new_window, controller->window, | ||
336 | sizeof(struct pci_window) * controller->windows); | ||
337 | kfree(controller->window); | ||
338 | } | ||
227 | 339 | ||
340 | /* Setup a pci_window for each device resource. */ | ||
341 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
342 | if (pci_addrs[i] == -1) | ||
343 | continue; | ||
344 | |||
345 | new_window[idx].offset = dev->resource[i].start - pci_addrs[i]; | ||
346 | new_window[idx].resource = dev->resource[i]; | ||
347 | idx++; | ||
228 | } | 348 | } |
229 | 349 | ||
350 | controller->windows = new_count; | ||
351 | controller->window = new_window; | ||
230 | } | 352 | } |
231 | 353 | ||
232 | void sn_pci_unfixup_slot(struct pci_dev *dev) | 354 | void sn_pci_unfixup_slot(struct pci_dev *dev) |
@@ -246,21 +368,23 @@ void sn_pci_unfixup_slot(struct pci_dev *dev) | |||
246 | */ | 368 | */ |
247 | void sn_pci_fixup_slot(struct pci_dev *dev) | 369 | void sn_pci_fixup_slot(struct pci_dev *dev) |
248 | { | 370 | { |
371 | unsigned int count = 0; | ||
249 | int idx; | 372 | int idx; |
250 | int segment = pci_domain_nr(dev->bus); | 373 | int segment = pci_domain_nr(dev->bus); |
251 | int status = 0; | 374 | int status = 0; |
252 | struct pcibus_bussoft *bs; | 375 | struct pcibus_bussoft *bs; |
253 | struct pci_bus *host_pci_bus; | 376 | struct pci_bus *host_pci_bus; |
254 | struct pci_dev *host_pci_dev; | 377 | struct pci_dev *host_pci_dev; |
378 | struct pcidev_info *pcidev_info; | ||
379 | s64 pci_addrs[PCI_ROM_RESOURCE + 1]; | ||
255 | struct sn_irq_info *sn_irq_info; | 380 | struct sn_irq_info *sn_irq_info; |
256 | unsigned long size; | 381 | unsigned long size; |
257 | unsigned int bus_no, devfn; | 382 | unsigned int bus_no, devfn; |
258 | 383 | ||
259 | pci_dev_get(dev); /* for the sysdata pointer */ | 384 | pci_dev_get(dev); /* for the sysdata pointer */ |
260 | dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL); | 385 | pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL); |
261 | if (SN_PCIDEV_INFO(dev) <= 0) | 386 | if (pcidev_info <= 0) |
262 | BUG(); /* Cannot afford to run out of memory */ | 387 | BUG(); /* Cannot afford to run out of memory */ |
263 | memset(SN_PCIDEV_INFO(dev), 0, sizeof(struct pcidev_info)); | ||
264 | 388 | ||
265 | sn_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_KERNEL); | 389 | sn_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_KERNEL); |
266 | if (sn_irq_info <= 0) | 390 | if (sn_irq_info <= 0) |
@@ -270,22 +394,34 @@ void sn_pci_fixup_slot(struct pci_dev *dev) | |||
270 | /* Call to retrieve pci device information needed by kernel. */ | 394 | /* Call to retrieve pci device information needed by kernel. */ |
271 | status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, | 395 | status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, |
272 | dev->devfn, | 396 | dev->devfn, |
273 | (u64) __pa(SN_PCIDEV_INFO(dev)), | 397 | (u64) __pa(pcidev_info), |
274 | (u64) __pa(sn_irq_info)); | 398 | (u64) __pa(sn_irq_info)); |
275 | if (status) | 399 | if (status) |
276 | BUG(); /* Cannot get platform pci device information */ | 400 | BUG(); /* Cannot get platform pci device information */ |
277 | 401 | ||
402 | /* Add pcidev_info to list in sn_pci_controller struct */ | ||
403 | list_add_tail(&pcidev_info->pdi_list, | ||
404 | &(SN_PCI_CONTROLLER(dev->bus)->pcidev_info)); | ||
405 | |||
278 | /* Copy over PIO Mapped Addresses */ | 406 | /* Copy over PIO Mapped Addresses */ |
279 | for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) { | 407 | for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) { |
280 | unsigned long start, end, addr; | 408 | unsigned long start, end, addr; |
281 | 409 | ||
282 | if (!SN_PCIDEV_INFO(dev)->pdi_pio_mapped_addr[idx]) | 410 | if (!pcidev_info->pdi_pio_mapped_addr[idx]) { |
411 | pci_addrs[idx] = -1; | ||
283 | continue; | 412 | continue; |
413 | } | ||
284 | 414 | ||
285 | start = dev->resource[idx].start; | 415 | start = dev->resource[idx].start; |
286 | end = dev->resource[idx].end; | 416 | end = dev->resource[idx].end; |
287 | size = end - start; | 417 | size = end - start; |
288 | addr = SN_PCIDEV_INFO(dev)->pdi_pio_mapped_addr[idx]; | 418 | if (size == 0) { |
419 | pci_addrs[idx] = -1; | ||
420 | continue; | ||
421 | } | ||
422 | pci_addrs[idx] = start; | ||
423 | count++; | ||
424 | addr = pcidev_info->pdi_pio_mapped_addr[idx]; | ||
289 | addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET; | 425 | addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET; |
290 | dev->resource[idx].start = addr; | 426 | dev->resource[idx].start = addr; |
291 | dev->resource[idx].end = addr + size; | 427 | dev->resource[idx].end = addr + size; |
@@ -294,23 +430,27 @@ void sn_pci_fixup_slot(struct pci_dev *dev) | |||
294 | else | 430 | else |
295 | dev->resource[idx].parent = &iomem_resource; | 431 | dev->resource[idx].parent = &iomem_resource; |
296 | } | 432 | } |
433 | /* Create a pci_window in the pci_controller struct for | ||
434 | * each device resource. | ||
435 | */ | ||
436 | if (count > 0) | ||
437 | sn_pci_window_fixup(dev, count, pci_addrs); | ||
297 | 438 | ||
298 | /* | 439 | /* |
299 | * Using the PROMs values for the PCI host bus, get the Linux | 440 | * Using the PROMs values for the PCI host bus, get the Linux |
300 | * PCI host_pci_dev struct and set up host bus linkages | 441 | * PCI host_pci_dev struct and set up host bus linkages |
301 | */ | 442 | */ |
302 | 443 | ||
303 | bus_no = (SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32) & 0xff; | 444 | bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff; |
304 | devfn = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle & 0xffffffff; | 445 | devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff; |
305 | host_pci_bus = pci_find_bus(segment, bus_no); | 446 | host_pci_bus = pci_find_bus(segment, bus_no); |
306 | host_pci_dev = pci_get_slot(host_pci_bus, devfn); | 447 | host_pci_dev = pci_get_slot(host_pci_bus, devfn); |
307 | 448 | ||
308 | SN_PCIDEV_INFO(dev)->host_pci_dev = host_pci_dev; | 449 | pcidev_info->host_pci_dev = host_pci_dev; |
309 | SN_PCIDEV_INFO(dev)->pdi_host_pcidev_info = | 450 | pcidev_info->pdi_linux_pcidev = dev; |
310 | SN_PCIDEV_INFO(host_pci_dev); | 451 | pcidev_info->pdi_host_pcidev_info = SN_PCIDEV_INFO(host_pci_dev); |
311 | SN_PCIDEV_INFO(dev)->pdi_linux_pcidev = dev; | ||
312 | bs = SN_PCIBUS_BUSSOFT(dev->bus); | 452 | bs = SN_PCIBUS_BUSSOFT(dev->bus); |
313 | SN_PCIDEV_INFO(dev)->pdi_pcibus_info = bs; | 453 | pcidev_info->pdi_pcibus_info = bs; |
314 | 454 | ||
315 | if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) { | 455 | if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) { |
316 | SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type]; | 456 | SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type]; |
@@ -320,11 +460,11 @@ void sn_pci_fixup_slot(struct pci_dev *dev) | |||
320 | 460 | ||
321 | /* Only set up IRQ stuff if this device has a host bus context */ | 461 | /* Only set up IRQ stuff if this device has a host bus context */ |
322 | if (bs && sn_irq_info->irq_irq) { | 462 | if (bs && sn_irq_info->irq_irq) { |
323 | SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = sn_irq_info; | 463 | pcidev_info->pdi_sn_irq_info = sn_irq_info; |
324 | dev->irq = SN_PCIDEV_INFO(dev)->pdi_sn_irq_info->irq_irq; | 464 | dev->irq = pcidev_info->pdi_sn_irq_info->irq_irq; |
325 | sn_irq_fixup(dev, sn_irq_info); | 465 | sn_irq_fixup(dev, sn_irq_info); |
326 | } else { | 466 | } else { |
327 | SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = NULL; | 467 | pcidev_info->pdi_sn_irq_info = NULL; |
328 | kfree(sn_irq_info); | 468 | kfree(sn_irq_info); |
329 | } | 469 | } |
330 | } | 470 | } |
@@ -338,6 +478,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) | |||
338 | int status = 0; | 478 | int status = 0; |
339 | int nasid, cnode; | 479 | int nasid, cnode; |
340 | struct pci_controller *controller; | 480 | struct pci_controller *controller; |
481 | struct sn_pci_controller *sn_controller; | ||
341 | struct pcibus_bussoft *prom_bussoft_ptr; | 482 | struct pcibus_bussoft *prom_bussoft_ptr; |
342 | struct hubdev_info *hubdev_info; | 483 | struct hubdev_info *hubdev_info; |
343 | void *provider_soft = NULL; | 484 | void *provider_soft = NULL; |
@@ -349,10 +490,15 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) | |||
349 | return; /*bus # does not exist */ | 490 | return; /*bus # does not exist */ |
350 | prom_bussoft_ptr = __va(prom_bussoft_ptr); | 491 | prom_bussoft_ptr = __va(prom_bussoft_ptr); |
351 | 492 | ||
352 | controller = kzalloc(sizeof(struct pci_controller), GFP_KERNEL); | 493 | /* Allocate a sn_pci_controller, which has a pci_controller struct |
494 | * as the first member. | ||
495 | */ | ||
496 | sn_controller = kzalloc(sizeof(struct sn_pci_controller), GFP_KERNEL); | ||
497 | if (!sn_controller) | ||
498 | BUG(); | ||
499 | INIT_LIST_HEAD(&sn_controller->pcidev_info); | ||
500 | controller = &sn_controller->pci_controller; | ||
353 | controller->segment = segment; | 501 | controller->segment = segment; |
354 | if (!controller) | ||
355 | BUG(); | ||
356 | 502 | ||
357 | if (bus == NULL) { | 503 | if (bus == NULL) { |
358 | bus = pci_scan_bus(busnum, &pci_root_ops, controller); | 504 | bus = pci_scan_bus(busnum, &pci_root_ops, controller); |
@@ -390,6 +536,29 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) | |||
390 | } | 536 | } |
391 | 537 | ||
392 | /* | 538 | /* |
539 | * Setup pci_windows for legacy IO and MEM space. | ||
540 | * (Temporary until ACPI support is in place.) | ||
541 | */ | ||
542 | controller->window = kcalloc(2, sizeof(struct pci_window), GFP_KERNEL); | ||
543 | if (controller->window == NULL) | ||
544 | BUG(); | ||
545 | controller->window[0].offset = prom_bussoft_ptr->bs_legacy_io; | ||
546 | controller->window[0].resource.name = "legacy_io"; | ||
547 | controller->window[0].resource.flags = IORESOURCE_IO; | ||
548 | controller->window[0].resource.start = prom_bussoft_ptr->bs_legacy_io; | ||
549 | controller->window[0].resource.end = | ||
550 | controller->window[0].resource.start + 0xffff; | ||
551 | controller->window[0].resource.parent = &ioport_resource; | ||
552 | controller->window[1].offset = prom_bussoft_ptr->bs_legacy_mem; | ||
553 | controller->window[1].resource.name = "legacy_mem"; | ||
554 | controller->window[1].resource.flags = IORESOURCE_MEM; | ||
555 | controller->window[1].resource.start = prom_bussoft_ptr->bs_legacy_mem; | ||
556 | controller->window[1].resource.end = | ||
557 | controller->window[1].resource.start + (1024 * 1024) - 1; | ||
558 | controller->window[1].resource.parent = &iomem_resource; | ||
559 | controller->windows = 2; | ||
560 | |||
561 | /* | ||
393 | * Generic bus fixup goes here. Don't reference prom_bussoft_ptr | 562 | * Generic bus fixup goes here. Don't reference prom_bussoft_ptr |
394 | * after this point. | 563 | * after this point. |
395 | */ | 564 | */ |
@@ -421,7 +590,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) | |||
421 | 590 | ||
422 | error_return: | 591 | error_return: |
423 | 592 | ||
424 | kfree(controller); | 593 | kfree(sn_controller); |
425 | return; | 594 | return; |
426 | } | 595 | } |
427 | 596 | ||
@@ -434,7 +603,7 @@ void sn_bus_store_sysdata(struct pci_dev *dev) | |||
434 | dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__); | 603 | dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__); |
435 | return; | 604 | return; |
436 | } | 605 | } |
437 | element->sysdata = dev->sysdata; | 606 | element->sysdata = SN_PCIDEV_INFO(dev); |
438 | list_add(&element->entry, &sn_sysdata_list); | 607 | list_add(&element->entry, &sn_sysdata_list); |
439 | } | 608 | } |
440 | 609 | ||
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 01d18b7b5b..ec37084bdc 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c | |||
@@ -28,7 +28,7 @@ extern int sn_ioif_inited; | |||
28 | static struct list_head **sn_irq_lh; | 28 | static struct list_head **sn_irq_lh; |
29 | static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */ | 29 | static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */ |
30 | 30 | ||
31 | static inline uint64_t sn_intr_alloc(nasid_t local_nasid, int local_widget, | 31 | static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget, |
32 | u64 sn_irq_info, | 32 | u64 sn_irq_info, |
33 | int req_irq, nasid_t req_nasid, | 33 | int req_irq, nasid_t req_nasid, |
34 | int req_slice) | 34 | int req_slice) |
@@ -123,7 +123,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) | |||
123 | 123 | ||
124 | list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, | 124 | list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, |
125 | sn_irq_lh[irq], list) { | 125 | sn_irq_lh[irq], list) { |
126 | uint64_t bridge; | 126 | u64 bridge; |
127 | int local_widget, status; | 127 | int local_widget, status; |
128 | nasid_t local_nasid; | 128 | nasid_t local_nasid; |
129 | struct sn_irq_info *new_irq_info; | 129 | struct sn_irq_info *new_irq_info; |
@@ -134,7 +134,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) | |||
134 | break; | 134 | break; |
135 | memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); | 135 | memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); |
136 | 136 | ||
137 | bridge = (uint64_t) new_irq_info->irq_bridge; | 137 | bridge = (u64) new_irq_info->irq_bridge; |
138 | if (!bridge) { | 138 | if (!bridge) { |
139 | kfree(new_irq_info); | 139 | kfree(new_irq_info); |
140 | break; /* irq is not a device interrupt */ | 140 | break; /* irq is not a device interrupt */ |
@@ -349,10 +349,10 @@ static void force_interrupt(int irq) | |||
349 | */ | 349 | */ |
350 | static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) | 350 | static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) |
351 | { | 351 | { |
352 | uint64_t regval; | 352 | u64 regval; |
353 | int irr_reg_num; | 353 | int irr_reg_num; |
354 | int irr_bit; | 354 | int irr_bit; |
355 | uint64_t irr_reg; | 355 | u64 irr_reg; |
356 | struct pcidev_info *pcidev_info; | 356 | struct pcidev_info *pcidev_info; |
357 | struct pcibus_info *pcibus_info; | 357 | struct pcibus_info *pcibus_info; |
358 | 358 | ||
diff --git a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c index 6546db6abd..9ab684d1bb 100644 --- a/arch/ia64/sn/kernel/mca.c +++ b/arch/ia64/sn/kernel/mca.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/timer.h> | 11 | #include <linux/timer.h> |
12 | #include <linux/vmalloc.h> | 12 | #include <linux/vmalloc.h> |
13 | #include <linux/mutex.h> | ||
13 | #include <asm/mca.h> | 14 | #include <asm/mca.h> |
14 | #include <asm/sal.h> | 15 | #include <asm/sal.h> |
15 | #include <asm/sn/sn_sal.h> | 16 | #include <asm/sn/sn_sal.h> |
@@ -27,7 +28,7 @@ void sn_init_cpei_timer(void); | |||
27 | /* Printing oemdata from mca uses data that is not passed through SAL, it is | 28 | /* Printing oemdata from mca uses data that is not passed through SAL, it is |
28 | * global. Only one user at a time. | 29 | * global. Only one user at a time. |
29 | */ | 30 | */ |
30 | static DECLARE_MUTEX(sn_oemdata_mutex); | 31 | static DEFINE_MUTEX(sn_oemdata_mutex); |
31 | static u8 **sn_oemdata; | 32 | static u8 **sn_oemdata; |
32 | static u64 *sn_oemdata_size, sn_oemdata_bufsize; | 33 | static u64 *sn_oemdata_size, sn_oemdata_bufsize; |
33 | 34 | ||
@@ -89,7 +90,7 @@ static int | |||
89 | sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata, | 90 | sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata, |
90 | u64 * oemdata_size) | 91 | u64 * oemdata_size) |
91 | { | 92 | { |
92 | down(&sn_oemdata_mutex); | 93 | mutex_lock(&sn_oemdata_mutex); |
93 | sn_oemdata = oemdata; | 94 | sn_oemdata = oemdata; |
94 | sn_oemdata_size = oemdata_size; | 95 | sn_oemdata_size = oemdata_size; |
95 | sn_oemdata_bufsize = 0; | 96 | sn_oemdata_bufsize = 0; |
@@ -107,7 +108,7 @@ sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata, | |||
107 | *sn_oemdata_size = 0; | 108 | *sn_oemdata_size = 0; |
108 | ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header); | 109 | ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header); |
109 | } | 110 | } |
110 | up(&sn_oemdata_mutex); | 111 | mutex_unlock(&sn_oemdata_mutex); |
111 | return 0; | 112 | return 0; |
112 | } | 113 | } |
113 | 114 | ||
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 0fb579ef18..e510dce997 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/root_dev.h> | 30 | #include <linux/root_dev.h> |
31 | #include <linux/nodemask.h> | 31 | #include <linux/nodemask.h> |
32 | #include <linux/pm.h> | 32 | #include <linux/pm.h> |
33 | #include <linux/efi.h> | ||
33 | 34 | ||
34 | #include <asm/io.h> | 35 | #include <asm/io.h> |
35 | #include <asm/sal.h> | 36 | #include <asm/sal.h> |
@@ -242,6 +243,135 @@ static void __init sn_check_for_wars(void) | |||
242 | } | 243 | } |
243 | } | 244 | } |
244 | 245 | ||
246 | /* | ||
247 | * Scan the EFI PCDP table (if it exists) for an acceptable VGA console | ||
248 | * output device. If one exists, pick it and set sn_legacy_{io,mem} to | ||
249 | * reflect the bus offsets needed to address it. | ||
250 | * | ||
251 | * Since pcdp support in SN is not supported in the 2.4 kernel (or at least | ||
252 | * the one lbs is based on) just declare the needed structs here. | ||
253 | * | ||
254 | * Reference spec http://www.dig64.org/specifications/DIG64_PCDPv20.pdf | ||
255 | * | ||
256 | * Returns 0 if no acceptable vga is found, !0 otherwise. | ||
257 | * | ||
258 | * Note: This stuff is duped here because Altix requires the PCDP to | ||
259 | * locate a usable VGA device due to lack of proper ACPI support. Structures | ||
260 | * could be used from drivers/firmware/pcdp.h, but it was decided that moving | ||
261 | * this file to a more public location just for Altix use was undesireable. | ||
262 | */ | ||
263 | |||
264 | struct hcdp_uart_desc { | ||
265 | u8 pad[45]; | ||
266 | }; | ||
267 | |||
268 | struct pcdp { | ||
269 | u8 signature[4]; /* should be 'HCDP' */ | ||
270 | u32 length; | ||
271 | u8 rev; /* should be >=3 for pcdp, <3 for hcdp */ | ||
272 | u8 sum; | ||
273 | u8 oem_id[6]; | ||
274 | u64 oem_tableid; | ||
275 | u32 oem_rev; | ||
276 | u32 creator_id; | ||
277 | u32 creator_rev; | ||
278 | u32 num_type0; | ||
279 | struct hcdp_uart_desc uart[0]; /* num_type0 of these */ | ||
280 | /* pcdp descriptors follow */ | ||
281 | } __attribute__((packed)); | ||
282 | |||
283 | struct pcdp_device_desc { | ||
284 | u8 type; | ||
285 | u8 primary; | ||
286 | u16 length; | ||
287 | u16 index; | ||
288 | /* interconnect specific structure follows */ | ||
289 | /* device specific structure follows that */ | ||
290 | } __attribute__((packed)); | ||
291 | |||
292 | struct pcdp_interface_pci { | ||
293 | u8 type; /* 1 == pci */ | ||
294 | u8 reserved; | ||
295 | u16 length; | ||
296 | u8 segment; | ||
297 | u8 bus; | ||
298 | u8 dev; | ||
299 | u8 fun; | ||
300 | u16 devid; | ||
301 | u16 vendid; | ||
302 | u32 acpi_interrupt; | ||
303 | u64 mmio_tra; | ||
304 | u64 ioport_tra; | ||
305 | u8 flags; | ||
306 | u8 translation; | ||
307 | } __attribute__((packed)); | ||
308 | |||
309 | struct pcdp_vga_device { | ||
310 | u8 num_eas_desc; | ||
311 | /* ACPI Extended Address Space Desc follows */ | ||
312 | } __attribute__((packed)); | ||
313 | |||
314 | /* from pcdp_device_desc.primary */ | ||
315 | #define PCDP_PRIMARY_CONSOLE 0x01 | ||
316 | |||
317 | /* from pcdp_device_desc.type */ | ||
318 | #define PCDP_CONSOLE_INOUT 0x0 | ||
319 | #define PCDP_CONSOLE_DEBUG 0x1 | ||
320 | #define PCDP_CONSOLE_OUT 0x2 | ||
321 | #define PCDP_CONSOLE_IN 0x3 | ||
322 | #define PCDP_CONSOLE_TYPE_VGA 0x8 | ||
323 | |||
324 | #define PCDP_CONSOLE_VGA (PCDP_CONSOLE_TYPE_VGA | PCDP_CONSOLE_OUT) | ||
325 | |||
326 | /* from pcdp_interface_pci.type */ | ||
327 | #define PCDP_IF_PCI 1 | ||
328 | |||
329 | /* from pcdp_interface_pci.translation */ | ||
330 | #define PCDP_PCI_TRANS_IOPORT 0x02 | ||
331 | #define PCDP_PCI_TRANS_MMIO 0x01 | ||
332 | |||
333 | static void | ||
334 | sn_scan_pcdp(void) | ||
335 | { | ||
336 | u8 *bp; | ||
337 | struct pcdp *pcdp; | ||
338 | struct pcdp_device_desc device; | ||
339 | struct pcdp_interface_pci if_pci; | ||
340 | extern struct efi efi; | ||
341 | |||
342 | pcdp = efi.hcdp; | ||
343 | if (! pcdp) | ||
344 | return; /* no hcdp/pcdp table */ | ||
345 | |||
346 | if (pcdp->rev < 3) | ||
347 | return; /* only support PCDP (rev >= 3) */ | ||
348 | |||
349 | for (bp = (u8 *)&pcdp->uart[pcdp->num_type0]; | ||
350 | bp < (u8 *)pcdp + pcdp->length; | ||
351 | bp += device.length) { | ||
352 | memcpy(&device, bp, sizeof(device)); | ||
353 | if (! (device.primary & PCDP_PRIMARY_CONSOLE)) | ||
354 | continue; /* not primary console */ | ||
355 | |||
356 | if (device.type != PCDP_CONSOLE_VGA) | ||
357 | continue; /* not VGA descriptor */ | ||
358 | |||
359 | memcpy(&if_pci, bp+sizeof(device), sizeof(if_pci)); | ||
360 | if (if_pci.type != PCDP_IF_PCI) | ||
361 | continue; /* not PCI interconnect */ | ||
362 | |||
363 | if (if_pci.translation & PCDP_PCI_TRANS_IOPORT) | ||
364 | vga_console_iobase = | ||
365 | if_pci.ioport_tra | __IA64_UNCACHED_OFFSET; | ||
366 | |||
367 | if (if_pci.translation & PCDP_PCI_TRANS_MMIO) | ||
368 | vga_console_membase = | ||
369 | if_pci.mmio_tra | __IA64_UNCACHED_OFFSET; | ||
370 | |||
371 | break; /* once we find the primary, we're done */ | ||
372 | } | ||
373 | } | ||
374 | |||
245 | /** | 375 | /** |
246 | * sn_setup - SN platform setup routine | 376 | * sn_setup - SN platform setup routine |
247 | * @cmdline_p: kernel command line | 377 | * @cmdline_p: kernel command line |
@@ -263,16 +393,35 @@ void __init sn_setup(char **cmdline_p) | |||
263 | 393 | ||
264 | #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) | 394 | #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) |
265 | /* | 395 | /* |
266 | * If there was a primary vga adapter identified through the | 396 | * Handle SN vga console. |
267 | * EFI PCDP table, make it the preferred console. Otherwise | 397 | * |
268 | * zero out conswitchp. | 398 | * SN systems do not have enough ACPI table information |
399 | * being passed from prom to identify VGA adapters and the legacy | ||
400 | * addresses to access them. Until that is done, SN systems rely | ||
401 | * on the PCDP table to identify the primary VGA console if one | ||
402 | * exists. | ||
403 | * | ||
404 | * However, kernel PCDP support is optional, and even if it is built | ||
405 | * into the kernel, it will not be used if the boot cmdline contains | ||
406 | * console= directives. | ||
407 | * | ||
408 | * So, to work around this mess, we duplicate some of the PCDP code | ||
409 | * here so that the primary VGA console (as defined by PCDP) will | ||
410 | * work on SN systems even if a different console (e.g. serial) is | ||
411 | * selected on the boot line (or CONFIG_EFI_PCDP is off). | ||
269 | */ | 412 | */ |
270 | 413 | ||
414 | if (! vga_console_membase) | ||
415 | sn_scan_pcdp(); | ||
416 | |||
271 | if (vga_console_membase) { | 417 | if (vga_console_membase) { |
272 | /* usable vga ... make tty0 the preferred default console */ | 418 | /* usable vga ... make tty0 the preferred default console */ |
273 | add_preferred_console("tty", 0, NULL); | 419 | if (!strstr(*cmdline_p, "console=")) |
420 | add_preferred_console("tty", 0, NULL); | ||
274 | } else { | 421 | } else { |
275 | printk(KERN_DEBUG "SGI: Disabling VGA console\n"); | 422 | printk(KERN_DEBUG "SGI: Disabling VGA console\n"); |
423 | if (!strstr(*cmdline_p, "console=")) | ||
424 | add_preferred_console("ttySG", 0, NULL); | ||
276 | #ifdef CONFIG_DUMMY_CONSOLE | 425 | #ifdef CONFIG_DUMMY_CONSOLE |
277 | conswitchp = &dummy_con; | 426 | conswitchp = &dummy_con; |
278 | #else | 427 | #else |
diff --git a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S index 3fa95065a4..bebbcc4f8d 100644 --- a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S +++ b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S | |||
@@ -39,9 +39,13 @@ sn2_ptc_deadlock_recovery_core: | |||
39 | mov r8=r0 | 39 | mov r8=r0 |
40 | 40 | ||
41 | 1: | 41 | 1: |
42 | cmp.ne p8,p9=r0,ptc1 // Test for shub type (ptc1 non-null on shub1) | ||
43 | // p8 = 1 if shub1, p9 = 1 if shub2 | ||
44 | |||
42 | add scr2=ALIAS_OFFSET,piowc // Address of WRITE_STATUS alias register | 45 | add scr2=ALIAS_OFFSET,piowc // Address of WRITE_STATUS alias register |
43 | ;; | 46 | mov scr1=7;; // Clear DEADLOCK, WRITE_ERROR, MULTI_WRITE_ERROR |
44 | ld8.acq scr1=[scr2];; | 47 | (p8) st8.rel [scr2]=scr1;; |
48 | (p9) ld8.acq scr1=[scr2];; | ||
45 | 49 | ||
46 | 5: ld8.acq scr1=[piowc];; // Wait for PIOs to complete. | 50 | 5: ld8.acq scr1=[piowc];; // Wait for PIOs to complete. |
47 | hint @pause | 51 | hint @pause |
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 49b530c39a..471bbaa65d 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c | |||
@@ -202,7 +202,7 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, | |||
202 | unsigned long end, unsigned long nbits) | 202 | unsigned long end, unsigned long nbits) |
203 | { | 203 | { |
204 | int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0; | 204 | int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0; |
205 | int mymm = (mm == current->active_mm); | 205 | int mymm = (mm == current->active_mm && current->mm); |
206 | volatile unsigned long *ptc0, *ptc1; | 206 | volatile unsigned long *ptc0, *ptc1; |
207 | unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value; | 207 | unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value; |
208 | short nasids[MAX_NUMNODES], nix; | 208 | short nasids[MAX_NUMNODES], nix; |
@@ -492,6 +492,9 @@ static struct proc_dir_entry *proc_sn2_ptc; | |||
492 | 492 | ||
493 | static int __init sn2_ptc_init(void) | 493 | static int __init sn2_ptc_init(void) |
494 | { | 494 | { |
495 | if (!ia64_platform_is("sn2")) | ||
496 | return -ENOSYS; | ||
497 | |||
495 | if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) { | 498 | if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) { |
496 | printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME); | 499 | printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME); |
497 | return -EINVAL; | 500 | return -EINVAL; |
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 6c6fbca322..19b54fbcd7 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c | |||
@@ -743,13 +743,14 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) | |||
743 | if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) { | 743 | if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) { |
744 | memset(p, 0, a.sz); | 744 | memset(p, 0, a.sz); |
745 | for (i = 0; i < nobj; i++) { | 745 | for (i = 0; i < nobj; i++) { |
746 | int cpuobj_index = 0; | ||
746 | if (!SN_HWPERF_IS_NODE(objs + i)) | 747 | if (!SN_HWPERF_IS_NODE(objs + i)) |
747 | continue; | 748 | continue; |
748 | node = sn_hwperf_obj_to_cnode(objs + i); | 749 | node = sn_hwperf_obj_to_cnode(objs + i); |
749 | for_each_online_cpu(j) { | 750 | for_each_online_cpu(j) { |
750 | if (node != cpu_to_node(j)) | 751 | if (node != cpu_to_node(j)) |
751 | continue; | 752 | continue; |
752 | cpuobj = (struct sn_hwperf_object_info *) p + j; | 753 | cpuobj = (struct sn_hwperf_object_info *) p + cpuobj_index++; |
753 | slice = 'a' + cpuid_to_slice(j); | 754 | slice = 'a' + cpuid_to_slice(j); |
754 | cdata = cpu_data(j); | 755 | cdata = cpu_data(j); |
755 | cpuobj->id = j; | 756 | cpuobj->id = j; |
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 0d8592a745..d263d3e8fb 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
13 | #include <linux/proc_fs.h> | 13 | #include <linux/proc_fs.h> |
14 | #include <linux/capability.h> | ||
14 | #include <linux/device.h> | 15 | #include <linux/device.h> |
15 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
16 | #include <asm/system.h> | 17 | #include <asm/system.h> |
@@ -65,7 +66,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv) | |||
65 | 66 | ||
66 | } | 67 | } |
67 | 68 | ||
68 | static int tiocx_hotplug(struct device *dev, char **envp, int num_envp, | 69 | static int tiocx_uevent(struct device *dev, char **envp, int num_envp, |
69 | char *buffer, int buffer_size) | 70 | char *buffer, int buffer_size) |
70 | { | 71 | { |
71 | return -ENODEV; | 72 | return -ENODEV; |
@@ -76,12 +77,6 @@ static void tiocx_bus_release(struct device *dev) | |||
76 | kfree(to_cx_dev(dev)); | 77 | kfree(to_cx_dev(dev)); |
77 | } | 78 | } |
78 | 79 | ||
79 | struct bus_type tiocx_bus_type = { | ||
80 | .name = "tiocx", | ||
81 | .match = tiocx_match, | ||
82 | .hotplug = tiocx_hotplug, | ||
83 | }; | ||
84 | |||
85 | /** | 80 | /** |
86 | * cx_device_match - Find cx_device in the id table. | 81 | * cx_device_match - Find cx_device in the id table. |
87 | * @ids: id table from driver | 82 | * @ids: id table from driver |
@@ -148,6 +143,14 @@ static int cx_driver_remove(struct device *dev) | |||
148 | return 0; | 143 | return 0; |
149 | } | 144 | } |
150 | 145 | ||
146 | struct bus_type tiocx_bus_type = { | ||
147 | .name = "tiocx", | ||
148 | .match = tiocx_match, | ||
149 | .uevent = tiocx_uevent, | ||
150 | .probe = cx_device_probe, | ||
151 | .remove = cx_driver_remove, | ||
152 | }; | ||
153 | |||
151 | /** | 154 | /** |
152 | * cx_driver_register - Register the driver. | 155 | * cx_driver_register - Register the driver. |
153 | * @cx_driver: driver table (cx_drv struct) from driver | 156 | * @cx_driver: driver table (cx_drv struct) from driver |
@@ -161,8 +164,6 @@ int cx_driver_register(struct cx_drv *cx_driver) | |||
161 | { | 164 | { |
162 | cx_driver->driver.name = cx_driver->name; | 165 | cx_driver->driver.name = cx_driver->name; |
163 | cx_driver->driver.bus = &tiocx_bus_type; | 166 | cx_driver->driver.bus = &tiocx_bus_type; |
164 | cx_driver->driver.probe = cx_device_probe; | ||
165 | cx_driver->driver.remove = cx_driver_remove; | ||
166 | 167 | ||
167 | return driver_register(&cx_driver->driver); | 168 | return driver_register(&cx_driver->driver); |
168 | } | 169 | } |
@@ -244,7 +245,7 @@ static int cx_device_reload(struct cx_dev *cx_dev) | |||
244 | cx_dev->bt); | 245 | cx_dev->bt); |
245 | } | 246 | } |
246 | 247 | ||
247 | static inline uint64_t tiocx_intr_alloc(nasid_t nasid, int widget, | 248 | static inline u64 tiocx_intr_alloc(nasid_t nasid, int widget, |
248 | u64 sn_irq_info, | 249 | u64 sn_irq_info, |
249 | int req_irq, nasid_t req_nasid, | 250 | int req_irq, nasid_t req_nasid, |
250 | int req_slice) | 251 | int req_slice) |
@@ -301,7 +302,7 @@ struct sn_irq_info *tiocx_irq_alloc(nasid_t nasid, int widget, int irq, | |||
301 | 302 | ||
302 | void tiocx_irq_free(struct sn_irq_info *sn_irq_info) | 303 | void tiocx_irq_free(struct sn_irq_info *sn_irq_info) |
303 | { | 304 | { |
304 | uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge; | 305 | u64 bridge = (u64) sn_irq_info->irq_bridge; |
305 | nasid_t nasid = NASID_GET(bridge); | 306 | nasid_t nasid = NASID_GET(bridge); |
306 | int widget; | 307 | int widget; |
307 | 308 | ||
@@ -312,12 +313,12 @@ void tiocx_irq_free(struct sn_irq_info *sn_irq_info) | |||
312 | } | 313 | } |
313 | } | 314 | } |
314 | 315 | ||
315 | uint64_t tiocx_dma_addr(uint64_t addr) | 316 | u64 tiocx_dma_addr(u64 addr) |
316 | { | 317 | { |
317 | return PHYS_TO_TIODMA(addr); | 318 | return PHYS_TO_TIODMA(addr); |
318 | } | 319 | } |
319 | 320 | ||
320 | uint64_t tiocx_swin_base(int nasid) | 321 | u64 tiocx_swin_base(int nasid) |
321 | { | 322 | { |
322 | return TIO_SWIN_BASE(nasid, TIOCX_CORELET); | 323 | return TIO_SWIN_BASE(nasid, TIOCX_CORELET); |
323 | } | 324 | } |
@@ -334,8 +335,8 @@ EXPORT_SYMBOL(tiocx_swin_base); | |||
334 | 335 | ||
335 | static void tio_conveyor_set(nasid_t nasid, int enable_flag) | 336 | static void tio_conveyor_set(nasid_t nasid, int enable_flag) |
336 | { | 337 | { |
337 | uint64_t ice_frz; | 338 | u64 ice_frz; |
338 | uint64_t disable_cb = (1ull << 61); | 339 | u64 disable_cb = (1ull << 61); |
339 | 340 | ||
340 | if (!(nasid & 1)) | 341 | if (!(nasid & 1)) |
341 | return; | 342 | return; |
@@ -387,7 +388,7 @@ static int is_fpga_tio(int nasid, int *bt) | |||
387 | 388 | ||
388 | static int bitstream_loaded(nasid_t nasid) | 389 | static int bitstream_loaded(nasid_t nasid) |
389 | { | 390 | { |
390 | uint64_t cx_credits; | 391 | u64 cx_credits; |
391 | 392 | ||
392 | cx_credits = REMOTE_HUB_L(nasid, TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3); | 393 | cx_credits = REMOTE_HUB_L(nasid, TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3); |
393 | cx_credits &= TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK; | 394 | cx_credits &= TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK; |
@@ -403,14 +404,14 @@ static int tiocx_reload(struct cx_dev *cx_dev) | |||
403 | nasid_t nasid = cx_dev->cx_id.nasid; | 404 | nasid_t nasid = cx_dev->cx_id.nasid; |
404 | 405 | ||
405 | if (bitstream_loaded(nasid)) { | 406 | if (bitstream_loaded(nasid)) { |
406 | uint64_t cx_id; | 407 | u64 cx_id; |
407 | int rv; | 408 | int rv; |
408 | 409 | ||
409 | rv = ia64_sn_sysctl_tio_clock_reset(nasid); | 410 | rv = ia64_sn_sysctl_tio_clock_reset(nasid); |
410 | if (rv) { | 411 | if (rv) { |
411 | printk(KERN_ALERT "CX port JTAG reset failed.\n"); | 412 | printk(KERN_ALERT "CX port JTAG reset failed.\n"); |
412 | } else { | 413 | } else { |
413 | cx_id = *(volatile uint64_t *) | 414 | cx_id = *(volatile u64 *) |
414 | (TIO_SWIN_BASE(nasid, TIOCX_CORELET) + | 415 | (TIO_SWIN_BASE(nasid, TIOCX_CORELET) + |
415 | WIDGET_ID); | 416 | WIDGET_ID); |
416 | part_num = XWIDGET_PART_NUM(cx_id); | 417 | part_num = XWIDGET_PART_NUM(cx_id); |
diff --git a/arch/ia64/sn/kernel/xp_main.c b/arch/ia64/sn/kernel/xp_main.c index 3be52a34c8..b7ea46645e 100644 --- a/arch/ia64/sn/kernel/xp_main.c +++ b/arch/ia64/sn/kernel/xp_main.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/mutex.h> | ||
22 | #include <asm/sn/intr.h> | 23 | #include <asm/sn/intr.h> |
23 | #include <asm/sn/sn_sal.h> | 24 | #include <asm/sn/sn_sal.h> |
24 | #include <asm/sn/xp.h> | 25 | #include <asm/sn/xp.h> |
@@ -136,13 +137,13 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size, | |||
136 | 137 | ||
137 | registration = &xpc_registrations[ch_number]; | 138 | registration = &xpc_registrations[ch_number]; |
138 | 139 | ||
139 | if (down_interruptible(®istration->sema) != 0) { | 140 | if (mutex_lock_interruptible(®istration->mutex) != 0) { |
140 | return xpcInterrupted; | 141 | return xpcInterrupted; |
141 | } | 142 | } |
142 | 143 | ||
143 | /* if XPC_CHANNEL_REGISTERED(ch_number) */ | 144 | /* if XPC_CHANNEL_REGISTERED(ch_number) */ |
144 | if (registration->func != NULL) { | 145 | if (registration->func != NULL) { |
145 | up(®istration->sema); | 146 | mutex_unlock(®istration->mutex); |
146 | return xpcAlreadyRegistered; | 147 | return xpcAlreadyRegistered; |
147 | } | 148 | } |
148 | 149 | ||
@@ -154,7 +155,7 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size, | |||
154 | registration->key = key; | 155 | registration->key = key; |
155 | registration->func = func; | 156 | registration->func = func; |
156 | 157 | ||
157 | up(®istration->sema); | 158 | mutex_unlock(®istration->mutex); |
158 | 159 | ||
159 | xpc_interface.connect(ch_number); | 160 | xpc_interface.connect(ch_number); |
160 | 161 | ||
@@ -190,11 +191,11 @@ xpc_disconnect(int ch_number) | |||
190 | * figured XPC's users will just turn around and call xpc_disconnect() | 191 | * figured XPC's users will just turn around and call xpc_disconnect() |
191 | * again anyways, so we might as well wait, if need be. | 192 | * again anyways, so we might as well wait, if need be. |
192 | */ | 193 | */ |
193 | down(®istration->sema); | 194 | mutex_lock(®istration->mutex); |
194 | 195 | ||
195 | /* if !XPC_CHANNEL_REGISTERED(ch_number) */ | 196 | /* if !XPC_CHANNEL_REGISTERED(ch_number) */ |
196 | if (registration->func == NULL) { | 197 | if (registration->func == NULL) { |
197 | up(®istration->sema); | 198 | mutex_unlock(®istration->mutex); |
198 | return; | 199 | return; |
199 | } | 200 | } |
200 | 201 | ||
@@ -208,7 +209,7 @@ xpc_disconnect(int ch_number) | |||
208 | 209 | ||
209 | xpc_interface.disconnect(ch_number); | 210 | xpc_interface.disconnect(ch_number); |
210 | 211 | ||
211 | up(®istration->sema); | 212 | mutex_unlock(®istration->mutex); |
212 | 213 | ||
213 | return; | 214 | return; |
214 | } | 215 | } |
@@ -250,9 +251,9 @@ xp_init(void) | |||
250 | xp_nofault_PIOR_target = SH1_IPI_ACCESS; | 251 | xp_nofault_PIOR_target = SH1_IPI_ACCESS; |
251 | } | 252 | } |
252 | 253 | ||
253 | /* initialize the connection registration semaphores */ | 254 | /* initialize the connection registration mutex */ |
254 | for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) { | 255 | for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) { |
255 | sema_init(&xpc_registrations[ch_number].sema, 1); /* mutex */ | 256 | mutex_init(&xpc_registrations[ch_number].mutex); |
256 | } | 257 | } |
257 | 258 | ||
258 | return 0; | 259 | return 0; |
diff --git a/arch/ia64/sn/kernel/xpc.h b/arch/ia64/sn/kernel/xpc.h deleted file mode 100644 index 5483a9f227..0000000000 --- a/arch/ia64/sn/kernel/xpc.h +++ /dev/null | |||
@@ -1,1273 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. | ||
7 | */ | ||
8 | |||
9 | |||
10 | /* | ||
11 | * Cross Partition Communication (XPC) structures and macros. | ||
12 | */ | ||
13 | |||
14 | #ifndef _IA64_SN_KERNEL_XPC_H | ||
15 | #define _IA64_SN_KERNEL_XPC_H | ||
16 | |||
17 | |||
18 | #include <linux/config.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/sysctl.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <asm/pgtable.h> | ||
23 | #include <asm/processor.h> | ||
24 | #include <asm/sn/bte.h> | ||
25 | #include <asm/sn/clksupport.h> | ||
26 | #include <asm/sn/addrs.h> | ||
27 | #include <asm/sn/mspec.h> | ||
28 | #include <asm/sn/shub_mmr.h> | ||
29 | #include <asm/sn/xp.h> | ||
30 | |||
31 | |||
32 | /* | ||
33 | * XPC Version numbers consist of a major and minor number. XPC can always | ||
34 | * talk to versions with same major #, and never talk to versions with a | ||
35 | * different major #. | ||
36 | */ | ||
37 | #define _XPC_VERSION(_maj, _min) (((_maj) << 4) | ((_min) & 0xf)) | ||
38 | #define XPC_VERSION_MAJOR(_v) ((_v) >> 4) | ||
39 | #define XPC_VERSION_MINOR(_v) ((_v) & 0xf) | ||
40 | |||
41 | |||
42 | /* | ||
43 | * The next macros define word or bit representations for given | ||
44 | * C-brick nasid in either the SAL provided bit array representing | ||
45 | * nasids in the partition/machine or the AMO_t array used for | ||
46 | * inter-partition initiation communications. | ||
47 | * | ||
48 | * For SN2 machines, C-Bricks are alway even numbered NASIDs. As | ||
49 | * such, some space will be saved by insisting that nasid information | ||
50 | * passed from SAL always be packed for C-Bricks and the | ||
51 | * cross-partition interrupts use the same packing scheme. | ||
52 | */ | ||
53 | #define XPC_NASID_W_INDEX(_n) (((_n) / 64) / 2) | ||
54 | #define XPC_NASID_B_INDEX(_n) (((_n) / 2) & (64 - 1)) | ||
55 | #define XPC_NASID_IN_ARRAY(_n, _p) ((_p)[XPC_NASID_W_INDEX(_n)] & \ | ||
56 | (1UL << XPC_NASID_B_INDEX(_n))) | ||
57 | #define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2) | ||
58 | |||
59 | #define XPC_HB_DEFAULT_INTERVAL 5 /* incr HB every x secs */ | ||
60 | #define XPC_HB_CHECK_DEFAULT_INTERVAL 20 /* check HB every x secs */ | ||
61 | |||
62 | /* define the process name of HB checker and the CPU it is pinned to */ | ||
63 | #define XPC_HB_CHECK_THREAD_NAME "xpc_hb" | ||
64 | #define XPC_HB_CHECK_CPU 0 | ||
65 | |||
66 | /* define the process name of the discovery thread */ | ||
67 | #define XPC_DISCOVERY_THREAD_NAME "xpc_discovery" | ||
68 | |||
69 | |||
70 | /* | ||
71 | * the reserved page | ||
72 | * | ||
73 | * SAL reserves one page of memory per partition for XPC. Though a full page | ||
74 | * in length (16384 bytes), its starting address is not page aligned, but it | ||
75 | * is cacheline aligned. The reserved page consists of the following: | ||
76 | * | ||
77 | * reserved page header | ||
78 | * | ||
79 | * The first cacheline of the reserved page contains the header | ||
80 | * (struct xpc_rsvd_page). Before SAL initialization has completed, | ||
81 | * SAL has set up the following fields of the reserved page header: | ||
82 | * SAL_signature, SAL_version, partid, and nasids_size. The other | ||
83 | * fields are set up by XPC. (xpc_rsvd_page points to the local | ||
84 | * partition's reserved page.) | ||
85 | * | ||
86 | * part_nasids mask | ||
87 | * mach_nasids mask | ||
88 | * | ||
89 | * SAL also sets up two bitmaps (or masks), one that reflects the actual | ||
90 | * nasids in this partition (part_nasids), and the other that reflects | ||
91 | * the actual nasids in the entire machine (mach_nasids). We're only | ||
92 | * interested in the even numbered nasids (which contain the processors | ||
93 | * and/or memory), so we only need half as many bits to represent the | ||
94 | * nasids. The part_nasids mask is located starting at the first cacheline | ||
95 | * following the reserved page header. The mach_nasids mask follows right | ||
96 | * after the part_nasids mask. The size in bytes of each mask is reflected | ||
97 | * by the reserved page header field 'nasids_size'. (Local partition's | ||
98 | * mask pointers are xpc_part_nasids and xpc_mach_nasids.) | ||
99 | * | ||
100 | * vars | ||
101 | * vars part | ||
102 | * | ||
103 | * Immediately following the mach_nasids mask are the XPC variables | ||
104 | * required by other partitions. First are those that are generic to all | ||
105 | * partitions (vars), followed on the next available cacheline by those | ||
106 | * which are partition specific (vars part). These are setup by XPC. | ||
107 | * (Local partition's vars pointers are xpc_vars and xpc_vars_part.) | ||
108 | * | ||
109 | * Note: Until vars_pa is set, the partition XPC code has not been initialized. | ||
110 | */ | ||
111 | struct xpc_rsvd_page { | ||
112 | u64 SAL_signature; /* SAL: unique signature */ | ||
113 | u64 SAL_version; /* SAL: version */ | ||
114 | u8 partid; /* SAL: partition ID */ | ||
115 | u8 version; | ||
116 | u8 pad1[6]; /* align to next u64 in cacheline */ | ||
117 | volatile u64 vars_pa; | ||
118 | struct timespec stamp; /* time when reserved page was setup by XPC */ | ||
119 | u64 pad2[9]; /* align to last u64 in cacheline */ | ||
120 | u64 nasids_size; /* SAL: size of each nasid mask in bytes */ | ||
121 | }; | ||
122 | |||
123 | #define XPC_RP_VERSION _XPC_VERSION(1,1) /* version 1.1 of the reserved page */ | ||
124 | |||
125 | #define XPC_SUPPORTS_RP_STAMP(_version) \ | ||
126 | (_version >= _XPC_VERSION(1,1)) | ||
127 | |||
128 | /* | ||
129 | * compare stamps - the return value is: | ||
130 | * | ||
131 | * < 0, if stamp1 < stamp2 | ||
132 | * = 0, if stamp1 == stamp2 | ||
133 | * > 0, if stamp1 > stamp2 | ||
134 | */ | ||
135 | static inline int | ||
136 | xpc_compare_stamps(struct timespec *stamp1, struct timespec *stamp2) | ||
137 | { | ||
138 | int ret; | ||
139 | |||
140 | |||
141 | if ((ret = stamp1->tv_sec - stamp2->tv_sec) == 0) { | ||
142 | ret = stamp1->tv_nsec - stamp2->tv_nsec; | ||
143 | } | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | |||
148 | /* | ||
149 | * Define the structures by which XPC variables can be exported to other | ||
150 | * partitions. (There are two: struct xpc_vars and struct xpc_vars_part) | ||
151 | */ | ||
152 | |||
153 | /* | ||
154 | * The following structure describes the partition generic variables | ||
155 | * needed by other partitions in order to properly initialize. | ||
156 | * | ||
157 | * struct xpc_vars version number also applies to struct xpc_vars_part. | ||
158 | * Changes to either structure and/or related functionality should be | ||
159 | * reflected by incrementing either the major or minor version numbers | ||
160 | * of struct xpc_vars. | ||
161 | */ | ||
162 | struct xpc_vars { | ||
163 | u8 version; | ||
164 | u64 heartbeat; | ||
165 | u64 heartbeating_to_mask; | ||
166 | u64 heartbeat_offline; /* if 0, heartbeat should be changing */ | ||
167 | int act_nasid; | ||
168 | int act_phys_cpuid; | ||
169 | u64 vars_part_pa; | ||
170 | u64 amos_page_pa; /* paddr of page of AMOs from MSPEC driver */ | ||
171 | AMO_t *amos_page; /* vaddr of page of AMOs from MSPEC driver */ | ||
172 | }; | ||
173 | |||
174 | #define XPC_V_VERSION _XPC_VERSION(3,1) /* version 3.1 of the cross vars */ | ||
175 | |||
176 | #define XPC_SUPPORTS_DISENGAGE_REQUEST(_version) \ | ||
177 | (_version >= _XPC_VERSION(3,1)) | ||
178 | |||
179 | |||
180 | static inline int | ||
181 | xpc_hb_allowed(partid_t partid, struct xpc_vars *vars) | ||
182 | { | ||
183 | return ((vars->heartbeating_to_mask & (1UL << partid)) != 0); | ||
184 | } | ||
185 | |||
186 | static inline void | ||
187 | xpc_allow_hb(partid_t partid, struct xpc_vars *vars) | ||
188 | { | ||
189 | u64 old_mask, new_mask; | ||
190 | |||
191 | do { | ||
192 | old_mask = vars->heartbeating_to_mask; | ||
193 | new_mask = (old_mask | (1UL << partid)); | ||
194 | } while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) != | ||
195 | old_mask); | ||
196 | } | ||
197 | |||
198 | static inline void | ||
199 | xpc_disallow_hb(partid_t partid, struct xpc_vars *vars) | ||
200 | { | ||
201 | u64 old_mask, new_mask; | ||
202 | |||
203 | do { | ||
204 | old_mask = vars->heartbeating_to_mask; | ||
205 | new_mask = (old_mask & ~(1UL << partid)); | ||
206 | } while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) != | ||
207 | old_mask); | ||
208 | } | ||
209 | |||
210 | |||
211 | /* | ||
212 | * The AMOs page consists of a number of AMO variables which are divided into | ||
213 | * four groups, The first two groups are used to identify an IRQ's sender. | ||
214 | * These two groups consist of 64 and 128 AMO variables respectively. The last | ||
215 | * two groups, consisting of just one AMO variable each, are used to identify | ||
216 | * the remote partitions that are currently engaged (from the viewpoint of | ||
217 | * the XPC running on the remote partition). | ||
218 | */ | ||
219 | #define XPC_NOTIFY_IRQ_AMOS 0 | ||
220 | #define XPC_ACTIVATE_IRQ_AMOS (XPC_NOTIFY_IRQ_AMOS + XP_MAX_PARTITIONS) | ||
221 | #define XPC_ENGAGED_PARTITIONS_AMO (XPC_ACTIVATE_IRQ_AMOS + XP_NASID_MASK_WORDS) | ||
222 | #define XPC_DISENGAGE_REQUEST_AMO (XPC_ENGAGED_PARTITIONS_AMO + 1) | ||
223 | |||
224 | |||
225 | /* | ||
226 | * The following structure describes the per partition specific variables. | ||
227 | * | ||
228 | * An array of these structures, one per partition, will be defined. As a | ||
229 | * partition becomes active XPC will copy the array entry corresponding to | ||
230 | * itself from that partition. It is desirable that the size of this | ||
231 | * structure evenly divide into a cacheline, such that none of the entries | ||
232 | * in this array crosses a cacheline boundary. As it is now, each entry | ||
233 | * occupies half a cacheline. | ||
234 | */ | ||
235 | struct xpc_vars_part { | ||
236 | volatile u64 magic; | ||
237 | |||
238 | u64 openclose_args_pa; /* physical address of open and close args */ | ||
239 | u64 GPs_pa; /* physical address of Get/Put values */ | ||
240 | |||
241 | u64 IPI_amo_pa; /* physical address of IPI AMO_t structure */ | ||
242 | int IPI_nasid; /* nasid of where to send IPIs */ | ||
243 | int IPI_phys_cpuid; /* physical CPU ID of where to send IPIs */ | ||
244 | |||
245 | u8 nchannels; /* #of defined channels supported */ | ||
246 | |||
247 | u8 reserved[23]; /* pad to a full 64 bytes */ | ||
248 | }; | ||
249 | |||
250 | /* | ||
251 | * The vars_part MAGIC numbers play a part in the first contact protocol. | ||
252 | * | ||
253 | * MAGIC1 indicates that the per partition specific variables for a remote | ||
254 | * partition have been initialized by this partition. | ||
255 | * | ||
256 | * MAGIC2 indicates that this partition has pulled the remote partititions | ||
257 | * per partition variables that pertain to this partition. | ||
258 | */ | ||
259 | #define XPC_VP_MAGIC1 0x0053524156435058L /* 'XPCVARS\0'L (little endian) */ | ||
260 | #define XPC_VP_MAGIC2 0x0073726176435058L /* 'XPCvars\0'L (little endian) */ | ||
261 | |||
262 | |||
263 | /* the reserved page sizes and offsets */ | ||
264 | |||
265 | #define XPC_RP_HEADER_SIZE L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page)) | ||
266 | #define XPC_RP_VARS_SIZE L1_CACHE_ALIGN(sizeof(struct xpc_vars)) | ||
267 | |||
268 | #define XPC_RP_PART_NASIDS(_rp) (u64 *) ((u8 *) _rp + XPC_RP_HEADER_SIZE) | ||
269 | #define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + xp_nasid_mask_words) | ||
270 | #define XPC_RP_VARS(_rp) ((struct xpc_vars *) XPC_RP_MACH_NASIDS(_rp) + xp_nasid_mask_words) | ||
271 | #define XPC_RP_VARS_PART(_rp) (struct xpc_vars_part *) ((u8 *) XPC_RP_VARS(rp) + XPC_RP_VARS_SIZE) | ||
272 | |||
273 | |||
274 | /* | ||
275 | * Functions registered by add_timer() or called by kernel_thread() only | ||
276 | * allow for a single 64-bit argument. The following macros can be used to | ||
277 | * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from | ||
278 | * the passed argument. | ||
279 | */ | ||
280 | #define XPC_PACK_ARGS(_arg1, _arg2) \ | ||
281 | ((((u64) _arg1) & 0xffffffff) | \ | ||
282 | ((((u64) _arg2) & 0xffffffff) << 32)) | ||
283 | |||
284 | #define XPC_UNPACK_ARG1(_args) (((u64) _args) & 0xffffffff) | ||
285 | #define XPC_UNPACK_ARG2(_args) ((((u64) _args) >> 32) & 0xffffffff) | ||
286 | |||
287 | |||
288 | |||
289 | /* | ||
290 | * Define a Get/Put value pair (pointers) used with a message queue. | ||
291 | */ | ||
292 | struct xpc_gp { | ||
293 | volatile s64 get; /* Get value */ | ||
294 | volatile s64 put; /* Put value */ | ||
295 | }; | ||
296 | |||
297 | #define XPC_GP_SIZE \ | ||
298 | L1_CACHE_ALIGN(sizeof(struct xpc_gp) * XPC_NCHANNELS) | ||
299 | |||
300 | |||
301 | |||
302 | /* | ||
303 | * Define a structure that contains arguments associated with opening and | ||
304 | * closing a channel. | ||
305 | */ | ||
306 | struct xpc_openclose_args { | ||
307 | u16 reason; /* reason why channel is closing */ | ||
308 | u16 msg_size; /* sizeof each message entry */ | ||
309 | u16 remote_nentries; /* #of message entries in remote msg queue */ | ||
310 | u16 local_nentries; /* #of message entries in local msg queue */ | ||
311 | u64 local_msgqueue_pa; /* physical address of local message queue */ | ||
312 | }; | ||
313 | |||
314 | #define XPC_OPENCLOSE_ARGS_SIZE \ | ||
315 | L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * XPC_NCHANNELS) | ||
316 | |||
317 | |||
318 | |||
319 | /* struct xpc_msg flags */ | ||
320 | |||
321 | #define XPC_M_DONE 0x01 /* msg has been received/consumed */ | ||
322 | #define XPC_M_READY 0x02 /* msg is ready to be sent */ | ||
323 | #define XPC_M_INTERRUPT 0x04 /* send interrupt when msg consumed */ | ||
324 | |||
325 | |||
326 | #define XPC_MSG_ADDRESS(_payload) \ | ||
327 | ((struct xpc_msg *)((u8 *)(_payload) - XPC_MSG_PAYLOAD_OFFSET)) | ||
328 | |||
329 | |||
330 | |||
331 | /* | ||
332 | * Defines notify entry. | ||
333 | * | ||
334 | * This is used to notify a message's sender that their message was received | ||
335 | * and consumed by the intended recipient. | ||
336 | */ | ||
337 | struct xpc_notify { | ||
338 | struct semaphore sema; /* notify semaphore */ | ||
339 | volatile u8 type; /* type of notification */ | ||
340 | |||
341 | /* the following two fields are only used if type == XPC_N_CALL */ | ||
342 | xpc_notify_func func; /* user's notify function */ | ||
343 | void *key; /* pointer to user's key */ | ||
344 | }; | ||
345 | |||
346 | /* struct xpc_notify type of notification */ | ||
347 | |||
348 | #define XPC_N_CALL 0x01 /* notify function provided by user */ | ||
349 | |||
350 | |||
351 | |||
352 | /* | ||
353 | * Define the structure that manages all the stuff required by a channel. In | ||
354 | * particular, they are used to manage the messages sent across the channel. | ||
355 | * | ||
356 | * This structure is private to a partition, and is NOT shared across the | ||
357 | * partition boundary. | ||
358 | * | ||
359 | * There is an array of these structures for each remote partition. It is | ||
360 | * allocated at the time a partition becomes active. The array contains one | ||
361 | * of these structures for each potential channel connection to that partition. | ||
362 | * | ||
363 | * Each of these structures manages two message queues (circular buffers). | ||
364 | * They are allocated at the time a channel connection is made. One of | ||
365 | * these message queues (local_msgqueue) holds the locally created messages | ||
366 | * that are destined for the remote partition. The other of these message | ||
367 | * queues (remote_msgqueue) is a locally cached copy of the remote partition's | ||
368 | * own local_msgqueue. | ||
369 | * | ||
370 | * The following is a description of the Get/Put pointers used to manage these | ||
371 | * two message queues. Consider the local_msgqueue to be on one partition | ||
372 | * and the remote_msgqueue to be its cached copy on another partition. A | ||
373 | * description of what each of the lettered areas contains is included. | ||
374 | * | ||
375 | * | ||
376 | * local_msgqueue remote_msgqueue | ||
377 | * | ||
378 | * |/////////| |/////////| | ||
379 | * w_remote_GP.get --> +---------+ |/////////| | ||
380 | * | F | |/////////| | ||
381 | * remote_GP.get --> +---------+ +---------+ <-- local_GP->get | ||
382 | * | | | | | ||
383 | * | | | E | | ||
384 | * | | | | | ||
385 | * | | +---------+ <-- w_local_GP.get | ||
386 | * | B | |/////////| | ||
387 | * | | |////D////| | ||
388 | * | | |/////////| | ||
389 | * | | +---------+ <-- w_remote_GP.put | ||
390 | * | | |////C////| | ||
391 | * local_GP->put --> +---------+ +---------+ <-- remote_GP.put | ||
392 | * | | |/////////| | ||
393 | * | A | |/////////| | ||
394 | * | | |/////////| | ||
395 | * w_local_GP.put --> +---------+ |/////////| | ||
396 | * |/////////| |/////////| | ||
397 | * | ||
398 | * | ||
399 | * ( remote_GP.[get|put] are cached copies of the remote | ||
400 | * partition's local_GP->[get|put], and thus their values can | ||
401 | * lag behind their counterparts on the remote partition. ) | ||
402 | * | ||
403 | * | ||
404 | * A - Messages that have been allocated, but have not yet been sent to the | ||
405 | * remote partition. | ||
406 | * | ||
407 | * B - Messages that have been sent, but have not yet been acknowledged by the | ||
408 | * remote partition as having been received. | ||
409 | * | ||
410 | * C - Area that needs to be prepared for the copying of sent messages, by | ||
411 | * the clearing of the message flags of any previously received messages. | ||
412 | * | ||
413 | * D - Area into which sent messages are to be copied from the remote | ||
414 | * partition's local_msgqueue and then delivered to their intended | ||
415 | * recipients. [ To allow for a multi-message copy, another pointer | ||
416 | * (next_msg_to_pull) has been added to keep track of the next message | ||
417 | * number needing to be copied (pulled). It chases after w_remote_GP.put. | ||
418 | * Any messages lying between w_local_GP.get and next_msg_to_pull have | ||
419 | * been copied and are ready to be delivered. ] | ||
420 | * | ||
421 | * E - Messages that have been copied and delivered, but have not yet been | ||
422 | * acknowledged by the recipient as having been received. | ||
423 | * | ||
424 | * F - Messages that have been acknowledged, but XPC has not yet notified the | ||
425 | * sender that the message was received by its intended recipient. | ||
426 | * This is also an area that needs to be prepared for the allocating of | ||
427 | * new messages, by the clearing of the message flags of the acknowledged | ||
428 | * messages. | ||
429 | */ | ||
430 | struct xpc_channel { | ||
431 | partid_t partid; /* ID of remote partition connected */ | ||
432 | spinlock_t lock; /* lock for updating this structure */ | ||
433 | u32 flags; /* general flags */ | ||
434 | |||
435 | enum xpc_retval reason; /* reason why channel is disconnect'g */ | ||
436 | int reason_line; /* line# disconnect initiated from */ | ||
437 | |||
438 | u16 number; /* channel # */ | ||
439 | |||
440 | u16 msg_size; /* sizeof each msg entry */ | ||
441 | u16 local_nentries; /* #of msg entries in local msg queue */ | ||
442 | u16 remote_nentries; /* #of msg entries in remote msg queue*/ | ||
443 | |||
444 | void *local_msgqueue_base; /* base address of kmalloc'd space */ | ||
445 | struct xpc_msg *local_msgqueue; /* local message queue */ | ||
446 | void *remote_msgqueue_base; /* base address of kmalloc'd space */ | ||
447 | struct xpc_msg *remote_msgqueue;/* cached copy of remote partition's */ | ||
448 | /* local message queue */ | ||
449 | u64 remote_msgqueue_pa; /* phys addr of remote partition's */ | ||
450 | /* local message queue */ | ||
451 | |||
452 | atomic_t references; /* #of external references to queues */ | ||
453 | |||
454 | atomic_t n_on_msg_allocate_wq; /* #on msg allocation wait queue */ | ||
455 | wait_queue_head_t msg_allocate_wq; /* msg allocation wait queue */ | ||
456 | |||
457 | u8 delayed_IPI_flags; /* IPI flags received, but delayed */ | ||
458 | /* action until channel disconnected */ | ||
459 | |||
460 | /* queue of msg senders who want to be notified when msg received */ | ||
461 | |||
462 | atomic_t n_to_notify; /* #of msg senders to notify */ | ||
463 | struct xpc_notify *notify_queue;/* notify queue for messages sent */ | ||
464 | |||
465 | xpc_channel_func func; /* user's channel function */ | ||
466 | void *key; /* pointer to user's key */ | ||
467 | |||
468 | struct semaphore msg_to_pull_sema; /* next msg to pull serialization */ | ||
469 | struct semaphore wdisconnect_sema; /* wait for channel disconnect */ | ||
470 | |||
471 | struct xpc_openclose_args *local_openclose_args; /* args passed on */ | ||
472 | /* opening or closing of channel */ | ||
473 | |||
474 | /* various flavors of local and remote Get/Put values */ | ||
475 | |||
476 | struct xpc_gp *local_GP; /* local Get/Put values */ | ||
477 | struct xpc_gp remote_GP; /* remote Get/Put values */ | ||
478 | struct xpc_gp w_local_GP; /* working local Get/Put values */ | ||
479 | struct xpc_gp w_remote_GP; /* working remote Get/Put values */ | ||
480 | s64 next_msg_to_pull; /* Put value of next msg to pull */ | ||
481 | |||
482 | /* kthread management related fields */ | ||
483 | |||
484 | // >>> rethink having kthreads_assigned_limit and kthreads_idle_limit; perhaps | ||
485 | // >>> allow the assigned limit be unbounded and let the idle limit be dynamic | ||
486 | // >>> dependent on activity over the last interval of time | ||
487 | atomic_t kthreads_assigned; /* #of kthreads assigned to channel */ | ||
488 | u32 kthreads_assigned_limit; /* limit on #of kthreads assigned */ | ||
489 | atomic_t kthreads_idle; /* #of kthreads idle waiting for work */ | ||
490 | u32 kthreads_idle_limit; /* limit on #of kthreads idle */ | ||
491 | atomic_t kthreads_active; /* #of kthreads actively working */ | ||
492 | // >>> following field is temporary | ||
493 | u32 kthreads_created; /* total #of kthreads created */ | ||
494 | |||
495 | wait_queue_head_t idle_wq; /* idle kthread wait queue */ | ||
496 | |||
497 | } ____cacheline_aligned; | ||
498 | |||
499 | |||
500 | /* struct xpc_channel flags */ | ||
501 | |||
502 | #define XPC_C_WASCONNECTED 0x00000001 /* channel was connected */ | ||
503 | |||
504 | #define XPC_C_ROPENREPLY 0x00000002 /* remote open channel reply */ | ||
505 | #define XPC_C_OPENREPLY 0x00000004 /* local open channel reply */ | ||
506 | #define XPC_C_ROPENREQUEST 0x00000008 /* remote open channel request */ | ||
507 | #define XPC_C_OPENREQUEST 0x00000010 /* local open channel request */ | ||
508 | |||
509 | #define XPC_C_SETUP 0x00000020 /* channel's msgqueues are alloc'd */ | ||
510 | #define XPC_C_CONNECTCALLOUT 0x00000040 /* channel connected callout made */ | ||
511 | #define XPC_C_CONNECTED 0x00000080 /* local channel is connected */ | ||
512 | #define XPC_C_CONNECTING 0x00000100 /* channel is being connected */ | ||
513 | |||
514 | #define XPC_C_RCLOSEREPLY 0x00000200 /* remote close channel reply */ | ||
515 | #define XPC_C_CLOSEREPLY 0x00000400 /* local close channel reply */ | ||
516 | #define XPC_C_RCLOSEREQUEST 0x00000800 /* remote close channel request */ | ||
517 | #define XPC_C_CLOSEREQUEST 0x00001000 /* local close channel request */ | ||
518 | |||
519 | #define XPC_C_DISCONNECTED 0x00002000 /* channel is disconnected */ | ||
520 | #define XPC_C_DISCONNECTING 0x00004000 /* channel is being disconnected */ | ||
521 | #define XPC_C_DISCONNECTCALLOUT 0x00008000 /* chan disconnected callout made */ | ||
522 | #define XPC_C_WDISCONNECT 0x00010000 /* waiting for channel disconnect */ | ||
523 | |||
524 | |||
525 | |||
526 | /* | ||
527 | * Manages channels on a partition basis. There is one of these structures | ||
528 | * for each partition (a partition will never utilize the structure that | ||
529 | * represents itself). | ||
530 | */ | ||
531 | struct xpc_partition { | ||
532 | |||
533 | /* XPC HB infrastructure */ | ||
534 | |||
535 | u8 remote_rp_version; /* version# of partition's rsvd pg */ | ||
536 | struct timespec remote_rp_stamp;/* time when rsvd pg was initialized */ | ||
537 | u64 remote_rp_pa; /* phys addr of partition's rsvd pg */ | ||
538 | u64 remote_vars_pa; /* phys addr of partition's vars */ | ||
539 | u64 remote_vars_part_pa; /* phys addr of partition's vars part */ | ||
540 | u64 last_heartbeat; /* HB at last read */ | ||
541 | u64 remote_amos_page_pa; /* phys addr of partition's amos page */ | ||
542 | int remote_act_nasid; /* active part's act/deact nasid */ | ||
543 | int remote_act_phys_cpuid; /* active part's act/deact phys cpuid */ | ||
544 | u32 act_IRQ_rcvd; /* IRQs since activation */ | ||
545 | spinlock_t act_lock; /* protect updating of act_state */ | ||
546 | u8 act_state; /* from XPC HB viewpoint */ | ||
547 | u8 remote_vars_version; /* version# of partition's vars */ | ||
548 | enum xpc_retval reason; /* reason partition is deactivating */ | ||
549 | int reason_line; /* line# deactivation initiated from */ | ||
550 | int reactivate_nasid; /* nasid in partition to reactivate */ | ||
551 | |||
552 | unsigned long disengage_request_timeout; /* timeout in jiffies */ | ||
553 | struct timer_list disengage_request_timer; | ||
554 | |||
555 | |||
556 | /* XPC infrastructure referencing and teardown control */ | ||
557 | |||
558 | volatile u8 setup_state; /* infrastructure setup state */ | ||
559 | wait_queue_head_t teardown_wq; /* kthread waiting to teardown infra */ | ||
560 | atomic_t references; /* #of references to infrastructure */ | ||
561 | |||
562 | |||
563 | /* | ||
564 | * NONE OF THE PRECEDING FIELDS OF THIS STRUCTURE WILL BE CLEARED WHEN | ||
565 | * XPC SETS UP THE NECESSARY INFRASTRUCTURE TO SUPPORT CROSS PARTITION | ||
566 | * COMMUNICATION. ALL OF THE FOLLOWING FIELDS WILL BE CLEARED. (THE | ||
567 | * 'nchannels' FIELD MUST BE THE FIRST OF THE FIELDS TO BE CLEARED.) | ||
568 | */ | ||
569 | |||
570 | |||
571 | u8 nchannels; /* #of defined channels supported */ | ||
572 | atomic_t nchannels_active; /* #of channels that are not DISCONNECTED */ | ||
573 | atomic_t nchannels_engaged;/* #of channels engaged with remote part */ | ||
574 | struct xpc_channel *channels;/* array of channel structures */ | ||
575 | |||
576 | void *local_GPs_base; /* base address of kmalloc'd space */ | ||
577 | struct xpc_gp *local_GPs; /* local Get/Put values */ | ||
578 | void *remote_GPs_base; /* base address of kmalloc'd space */ | ||
579 | struct xpc_gp *remote_GPs;/* copy of remote partition's local Get/Put */ | ||
580 | /* values */ | ||
581 | u64 remote_GPs_pa; /* phys address of remote partition's local */ | ||
582 | /* Get/Put values */ | ||
583 | |||
584 | |||
585 | /* fields used to pass args when opening or closing a channel */ | ||
586 | |||
587 | void *local_openclose_args_base; /* base address of kmalloc'd space */ | ||
588 | struct xpc_openclose_args *local_openclose_args; /* local's args */ | ||
589 | void *remote_openclose_args_base; /* base address of kmalloc'd space */ | ||
590 | struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */ | ||
591 | /* args */ | ||
592 | u64 remote_openclose_args_pa; /* phys addr of remote's args */ | ||
593 | |||
594 | |||
595 | /* IPI sending, receiving and handling related fields */ | ||
596 | |||
597 | int remote_IPI_nasid; /* nasid of where to send IPIs */ | ||
598 | int remote_IPI_phys_cpuid; /* phys CPU ID of where to send IPIs */ | ||
599 | AMO_t *remote_IPI_amo_va; /* address of remote IPI AMO_t structure */ | ||
600 | |||
601 | AMO_t *local_IPI_amo_va; /* address of IPI AMO_t structure */ | ||
602 | u64 local_IPI_amo; /* IPI amo flags yet to be handled */ | ||
603 | char IPI_owner[8]; /* IPI owner's name */ | ||
604 | struct timer_list dropped_IPI_timer; /* dropped IPI timer */ | ||
605 | |||
606 | spinlock_t IPI_lock; /* IPI handler lock */ | ||
607 | |||
608 | |||
609 | /* channel manager related fields */ | ||
610 | |||
611 | atomic_t channel_mgr_requests; /* #of requests to activate chan mgr */ | ||
612 | wait_queue_head_t channel_mgr_wq; /* channel mgr's wait queue */ | ||
613 | |||
614 | } ____cacheline_aligned; | ||
615 | |||
616 | |||
617 | /* struct xpc_partition act_state values (for XPC HB) */ | ||
618 | |||
619 | #define XPC_P_INACTIVE 0x00 /* partition is not active */ | ||
620 | #define XPC_P_ACTIVATION_REQ 0x01 /* created thread to activate */ | ||
621 | #define XPC_P_ACTIVATING 0x02 /* activation thread started */ | ||
622 | #define XPC_P_ACTIVE 0x03 /* xpc_partition_up() was called */ | ||
623 | #define XPC_P_DEACTIVATING 0x04 /* partition deactivation initiated */ | ||
624 | |||
625 | |||
626 | #define XPC_DEACTIVATE_PARTITION(_p, _reason) \ | ||
627 | xpc_deactivate_partition(__LINE__, (_p), (_reason)) | ||
628 | |||
629 | |||
630 | /* struct xpc_partition setup_state values */ | ||
631 | |||
632 | #define XPC_P_UNSET 0x00 /* infrastructure was never setup */ | ||
633 | #define XPC_P_SETUP 0x01 /* infrastructure is setup */ | ||
634 | #define XPC_P_WTEARDOWN 0x02 /* waiting to teardown infrastructure */ | ||
635 | #define XPC_P_TORNDOWN 0x03 /* infrastructure is torndown */ | ||
636 | |||
637 | |||
638 | |||
639 | /* | ||
640 | * struct xpc_partition IPI_timer #of seconds to wait before checking for | ||
641 | * dropped IPIs. These occur whenever an IPI amo write doesn't complete until | ||
642 | * after the IPI was received. | ||
643 | */ | ||
644 | #define XPC_P_DROPPED_IPI_WAIT (0.25 * HZ) | ||
645 | |||
646 | |||
647 | /* number of seconds to wait for other partitions to disengage */ | ||
648 | #define XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT 90 | ||
649 | |||
650 | /* interval in seconds to print 'waiting disengagement' messages */ | ||
651 | #define XPC_DISENGAGE_PRINTMSG_INTERVAL 10 | ||
652 | |||
653 | |||
654 | #define XPC_PARTID(_p) ((partid_t) ((_p) - &xpc_partitions[0])) | ||
655 | |||
656 | |||
657 | |||
658 | /* found in xp_main.c */ | ||
659 | extern struct xpc_registration xpc_registrations[]; | ||
660 | |||
661 | |||
662 | /* found in xpc_main.c */ | ||
663 | extern struct device *xpc_part; | ||
664 | extern struct device *xpc_chan; | ||
665 | extern int xpc_disengage_request_timelimit; | ||
666 | extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *); | ||
667 | extern void xpc_dropped_IPI_check(struct xpc_partition *); | ||
668 | extern void xpc_activate_partition(struct xpc_partition *); | ||
669 | extern void xpc_activate_kthreads(struct xpc_channel *, int); | ||
670 | extern void xpc_create_kthreads(struct xpc_channel *, int); | ||
671 | extern void xpc_disconnect_wait(int); | ||
672 | |||
673 | |||
674 | /* found in xpc_partition.c */ | ||
675 | extern int xpc_exiting; | ||
676 | extern struct xpc_vars *xpc_vars; | ||
677 | extern struct xpc_rsvd_page *xpc_rsvd_page; | ||
678 | extern struct xpc_vars_part *xpc_vars_part; | ||
679 | extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1]; | ||
680 | extern char xpc_remote_copy_buffer[]; | ||
681 | extern struct xpc_rsvd_page *xpc_rsvd_page_init(void); | ||
682 | extern void xpc_allow_IPI_ops(void); | ||
683 | extern void xpc_restrict_IPI_ops(void); | ||
684 | extern int xpc_identify_act_IRQ_sender(void); | ||
685 | extern int xpc_partition_disengaged(struct xpc_partition *); | ||
686 | extern enum xpc_retval xpc_mark_partition_active(struct xpc_partition *); | ||
687 | extern void xpc_mark_partition_inactive(struct xpc_partition *); | ||
688 | extern void xpc_discovery(void); | ||
689 | extern void xpc_check_remote_hb(void); | ||
690 | extern void xpc_deactivate_partition(const int, struct xpc_partition *, | ||
691 | enum xpc_retval); | ||
692 | extern enum xpc_retval xpc_initiate_partid_to_nasids(partid_t, void *); | ||
693 | |||
694 | |||
695 | /* found in xpc_channel.c */ | ||
696 | extern void xpc_initiate_connect(int); | ||
697 | extern void xpc_initiate_disconnect(int); | ||
698 | extern enum xpc_retval xpc_initiate_allocate(partid_t, int, u32, void **); | ||
699 | extern enum xpc_retval xpc_initiate_send(partid_t, int, void *); | ||
700 | extern enum xpc_retval xpc_initiate_send_notify(partid_t, int, void *, | ||
701 | xpc_notify_func, void *); | ||
702 | extern void xpc_initiate_received(partid_t, int, void *); | ||
703 | extern enum xpc_retval xpc_setup_infrastructure(struct xpc_partition *); | ||
704 | extern enum xpc_retval xpc_pull_remote_vars_part(struct xpc_partition *); | ||
705 | extern void xpc_process_channel_activity(struct xpc_partition *); | ||
706 | extern void xpc_connected_callout(struct xpc_channel *); | ||
707 | extern void xpc_deliver_msg(struct xpc_channel *); | ||
708 | extern void xpc_disconnect_channel(const int, struct xpc_channel *, | ||
709 | enum xpc_retval, unsigned long *); | ||
710 | extern void xpc_disconnecting_callout(struct xpc_channel *); | ||
711 | extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval); | ||
712 | extern void xpc_teardown_infrastructure(struct xpc_partition *); | ||
713 | |||
714 | |||
715 | |||
716 | static inline void | ||
717 | xpc_wakeup_channel_mgr(struct xpc_partition *part) | ||
718 | { | ||
719 | if (atomic_inc_return(&part->channel_mgr_requests) == 1) { | ||
720 | wake_up(&part->channel_mgr_wq); | ||
721 | } | ||
722 | } | ||
723 | |||
724 | |||
725 | |||
726 | /* | ||
727 | * These next two inlines are used to keep us from tearing down a channel's | ||
728 | * msg queues while a thread may be referencing them. | ||
729 | */ | ||
730 | static inline void | ||
731 | xpc_msgqueue_ref(struct xpc_channel *ch) | ||
732 | { | ||
733 | atomic_inc(&ch->references); | ||
734 | } | ||
735 | |||
736 | static inline void | ||
737 | xpc_msgqueue_deref(struct xpc_channel *ch) | ||
738 | { | ||
739 | s32 refs = atomic_dec_return(&ch->references); | ||
740 | |||
741 | DBUG_ON(refs < 0); | ||
742 | if (refs == 0) { | ||
743 | xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]); | ||
744 | } | ||
745 | } | ||
746 | |||
747 | |||
748 | |||
749 | #define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \ | ||
750 | xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs) | ||
751 | |||
752 | |||
753 | /* | ||
754 | * These two inlines are used to keep us from tearing down a partition's | ||
755 | * setup infrastructure while a thread may be referencing it. | ||
756 | */ | ||
757 | static inline void | ||
758 | xpc_part_deref(struct xpc_partition *part) | ||
759 | { | ||
760 | s32 refs = atomic_dec_return(&part->references); | ||
761 | |||
762 | |||
763 | DBUG_ON(refs < 0); | ||
764 | if (refs == 0 && part->setup_state == XPC_P_WTEARDOWN) { | ||
765 | wake_up(&part->teardown_wq); | ||
766 | } | ||
767 | } | ||
768 | |||
769 | static inline int | ||
770 | xpc_part_ref(struct xpc_partition *part) | ||
771 | { | ||
772 | int setup; | ||
773 | |||
774 | |||
775 | atomic_inc(&part->references); | ||
776 | setup = (part->setup_state == XPC_P_SETUP); | ||
777 | if (!setup) { | ||
778 | xpc_part_deref(part); | ||
779 | } | ||
780 | return setup; | ||
781 | } | ||
782 | |||
783 | |||
784 | |||
785 | /* | ||
786 | * The following macro is to be used for the setting of the reason and | ||
787 | * reason_line fields in both the struct xpc_channel and struct xpc_partition | ||
788 | * structures. | ||
789 | */ | ||
790 | #define XPC_SET_REASON(_p, _reason, _line) \ | ||
791 | { \ | ||
792 | (_p)->reason = _reason; \ | ||
793 | (_p)->reason_line = _line; \ | ||
794 | } | ||
795 | |||
796 | |||
797 | |||
798 | /* | ||
799 | * This next set of inlines are used to keep track of when a partition is | ||
800 | * potentially engaged in accessing memory belonging to another partition. | ||
801 | */ | ||
802 | |||
803 | static inline void | ||
804 | xpc_mark_partition_engaged(struct xpc_partition *part) | ||
805 | { | ||
806 | unsigned long irq_flags; | ||
807 | AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa + | ||
808 | (XPC_ENGAGED_PARTITIONS_AMO * sizeof(AMO_t))); | ||
809 | |||
810 | |||
811 | local_irq_save(irq_flags); | ||
812 | |||
813 | /* set bit corresponding to our partid in remote partition's AMO */ | ||
814 | FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR, | ||
815 | (1UL << sn_partition_id)); | ||
816 | /* | ||
817 | * We must always use the nofault function regardless of whether we | ||
818 | * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we | ||
819 | * didn't, we'd never know that the other partition is down and would | ||
820 | * keep sending IPIs and AMOs to it until the heartbeat times out. | ||
821 | */ | ||
822 | (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo-> | ||
823 | variable), xp_nofault_PIOR_target)); | ||
824 | |||
825 | local_irq_restore(irq_flags); | ||
826 | } | ||
827 | |||
828 | static inline void | ||
829 | xpc_mark_partition_disengaged(struct xpc_partition *part) | ||
830 | { | ||
831 | unsigned long irq_flags; | ||
832 | AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa + | ||
833 | (XPC_ENGAGED_PARTITIONS_AMO * sizeof(AMO_t))); | ||
834 | |||
835 | |||
836 | local_irq_save(irq_flags); | ||
837 | |||
838 | /* clear bit corresponding to our partid in remote partition's AMO */ | ||
839 | FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND, | ||
840 | ~(1UL << sn_partition_id)); | ||
841 | /* | ||
842 | * We must always use the nofault function regardless of whether we | ||
843 | * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we | ||
844 | * didn't, we'd never know that the other partition is down and would | ||
845 | * keep sending IPIs and AMOs to it until the heartbeat times out. | ||
846 | */ | ||
847 | (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo-> | ||
848 | variable), xp_nofault_PIOR_target)); | ||
849 | |||
850 | local_irq_restore(irq_flags); | ||
851 | } | ||
852 | |||
853 | static inline void | ||
854 | xpc_request_partition_disengage(struct xpc_partition *part) | ||
855 | { | ||
856 | unsigned long irq_flags; | ||
857 | AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa + | ||
858 | (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t))); | ||
859 | |||
860 | |||
861 | local_irq_save(irq_flags); | ||
862 | |||
863 | /* set bit corresponding to our partid in remote partition's AMO */ | ||
864 | FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR, | ||
865 | (1UL << sn_partition_id)); | ||
866 | /* | ||
867 | * We must always use the nofault function regardless of whether we | ||
868 | * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we | ||
869 | * didn't, we'd never know that the other partition is down and would | ||
870 | * keep sending IPIs and AMOs to it until the heartbeat times out. | ||
871 | */ | ||
872 | (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo-> | ||
873 | variable), xp_nofault_PIOR_target)); | ||
874 | |||
875 | local_irq_restore(irq_flags); | ||
876 | } | ||
877 | |||
878 | static inline void | ||
879 | xpc_cancel_partition_disengage_request(struct xpc_partition *part) | ||
880 | { | ||
881 | unsigned long irq_flags; | ||
882 | AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa + | ||
883 | (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t))); | ||
884 | |||
885 | |||
886 | local_irq_save(irq_flags); | ||
887 | |||
888 | /* clear bit corresponding to our partid in remote partition's AMO */ | ||
889 | FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND, | ||
890 | ~(1UL << sn_partition_id)); | ||
891 | /* | ||
892 | * We must always use the nofault function regardless of whether we | ||
893 | * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we | ||
894 | * didn't, we'd never know that the other partition is down and would | ||
895 | * keep sending IPIs and AMOs to it until the heartbeat times out. | ||
896 | */ | ||
897 | (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo-> | ||
898 | variable), xp_nofault_PIOR_target)); | ||
899 | |||
900 | local_irq_restore(irq_flags); | ||
901 | } | ||
902 | |||
903 | static inline u64 | ||
904 | xpc_partition_engaged(u64 partid_mask) | ||
905 | { | ||
906 | AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO; | ||
907 | |||
908 | |||
909 | /* return our partition's AMO variable ANDed with partid_mask */ | ||
910 | return (FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_LOAD) & | ||
911 | partid_mask); | ||
912 | } | ||
913 | |||
914 | static inline u64 | ||
915 | xpc_partition_disengage_requested(u64 partid_mask) | ||
916 | { | ||
917 | AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO; | ||
918 | |||
919 | |||
920 | /* return our partition's AMO variable ANDed with partid_mask */ | ||
921 | return (FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_LOAD) & | ||
922 | partid_mask); | ||
923 | } | ||
924 | |||
925 | static inline void | ||
926 | xpc_clear_partition_engaged(u64 partid_mask) | ||
927 | { | ||
928 | AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO; | ||
929 | |||
930 | |||
931 | /* clear bit(s) based on partid_mask in our partition's AMO */ | ||
932 | FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND, | ||
933 | ~partid_mask); | ||
934 | } | ||
935 | |||
936 | static inline void | ||
937 | xpc_clear_partition_disengage_request(u64 partid_mask) | ||
938 | { | ||
939 | AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO; | ||
940 | |||
941 | |||
942 | /* clear bit(s) based on partid_mask in our partition's AMO */ | ||
943 | FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND, | ||
944 | ~partid_mask); | ||
945 | } | ||
946 | |||
947 | |||
948 | |||
949 | /* | ||
950 | * The following set of macros and inlines are used for the sending and | ||
951 | * receiving of IPIs (also known as IRQs). There are two flavors of IPIs, | ||
952 | * one that is associated with partition activity (SGI_XPC_ACTIVATE) and | ||
953 | * the other that is associated with channel activity (SGI_XPC_NOTIFY). | ||
954 | */ | ||
955 | |||
956 | static inline u64 | ||
957 | xpc_IPI_receive(AMO_t *amo) | ||
958 | { | ||
959 | return FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_CLEAR); | ||
960 | } | ||
961 | |||
962 | |||
963 | static inline enum xpc_retval | ||
964 | xpc_IPI_send(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector) | ||
965 | { | ||
966 | int ret = 0; | ||
967 | unsigned long irq_flags; | ||
968 | |||
969 | |||
970 | local_irq_save(irq_flags); | ||
971 | |||
972 | FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR, flag); | ||
973 | sn_send_IPI_phys(nasid, phys_cpuid, vector, 0); | ||
974 | |||
975 | /* | ||
976 | * We must always use the nofault function regardless of whether we | ||
977 | * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we | ||
978 | * didn't, we'd never know that the other partition is down and would | ||
979 | * keep sending IPIs and AMOs to it until the heartbeat times out. | ||
980 | */ | ||
981 | ret = xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->variable), | ||
982 | xp_nofault_PIOR_target)); | ||
983 | |||
984 | local_irq_restore(irq_flags); | ||
985 | |||
986 | return ((ret == 0) ? xpcSuccess : xpcPioReadError); | ||
987 | } | ||
988 | |||
989 | |||
990 | /* | ||
991 | * IPIs associated with SGI_XPC_ACTIVATE IRQ. | ||
992 | */ | ||
993 | |||
994 | /* | ||
995 | * Flag the appropriate AMO variable and send an IPI to the specified node. | ||
996 | */ | ||
997 | static inline void | ||
998 | xpc_activate_IRQ_send(u64 amos_page_pa, int from_nasid, int to_nasid, | ||
999 | int to_phys_cpuid) | ||
1000 | { | ||
1001 | int w_index = XPC_NASID_W_INDEX(from_nasid); | ||
1002 | int b_index = XPC_NASID_B_INDEX(from_nasid); | ||
1003 | AMO_t *amos = (AMO_t *) __va(amos_page_pa + | ||
1004 | (XPC_ACTIVATE_IRQ_AMOS * sizeof(AMO_t))); | ||
1005 | |||
1006 | |||
1007 | (void) xpc_IPI_send(&amos[w_index], (1UL << b_index), to_nasid, | ||
1008 | to_phys_cpuid, SGI_XPC_ACTIVATE); | ||
1009 | } | ||
1010 | |||
1011 | static inline void | ||
1012 | xpc_IPI_send_activate(struct xpc_vars *vars) | ||
1013 | { | ||
1014 | xpc_activate_IRQ_send(vars->amos_page_pa, cnodeid_to_nasid(0), | ||
1015 | vars->act_nasid, vars->act_phys_cpuid); | ||
1016 | } | ||
1017 | |||
1018 | static inline void | ||
1019 | xpc_IPI_send_activated(struct xpc_partition *part) | ||
1020 | { | ||
1021 | xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0), | ||
1022 | part->remote_act_nasid, part->remote_act_phys_cpuid); | ||
1023 | } | ||
1024 | |||
1025 | static inline void | ||
1026 | xpc_IPI_send_reactivate(struct xpc_partition *part) | ||
1027 | { | ||
1028 | xpc_activate_IRQ_send(xpc_vars->amos_page_pa, part->reactivate_nasid, | ||
1029 | xpc_vars->act_nasid, xpc_vars->act_phys_cpuid); | ||
1030 | } | ||
1031 | |||
1032 | static inline void | ||
1033 | xpc_IPI_send_disengage(struct xpc_partition *part) | ||
1034 | { | ||
1035 | xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0), | ||
1036 | part->remote_act_nasid, part->remote_act_phys_cpuid); | ||
1037 | } | ||
1038 | |||
1039 | |||
1040 | /* | ||
1041 | * IPIs associated with SGI_XPC_NOTIFY IRQ. | ||
1042 | */ | ||
1043 | |||
1044 | /* | ||
1045 | * Send an IPI to the remote partition that is associated with the | ||
1046 | * specified channel. | ||
1047 | */ | ||
1048 | #define XPC_NOTIFY_IRQ_SEND(_ch, _ipi_f, _irq_f) \ | ||
1049 | xpc_notify_IRQ_send(_ch, _ipi_f, #_ipi_f, _irq_f) | ||
1050 | |||
1051 | static inline void | ||
1052 | xpc_notify_IRQ_send(struct xpc_channel *ch, u8 ipi_flag, char *ipi_flag_string, | ||
1053 | unsigned long *irq_flags) | ||
1054 | { | ||
1055 | struct xpc_partition *part = &xpc_partitions[ch->partid]; | ||
1056 | enum xpc_retval ret; | ||
1057 | |||
1058 | |||
1059 | if (likely(part->act_state != XPC_P_DEACTIVATING)) { | ||
1060 | ret = xpc_IPI_send(part->remote_IPI_amo_va, | ||
1061 | (u64) ipi_flag << (ch->number * 8), | ||
1062 | part->remote_IPI_nasid, | ||
1063 | part->remote_IPI_phys_cpuid, | ||
1064 | SGI_XPC_NOTIFY); | ||
1065 | dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n", | ||
1066 | ipi_flag_string, ch->partid, ch->number, ret); | ||
1067 | if (unlikely(ret != xpcSuccess)) { | ||
1068 | if (irq_flags != NULL) { | ||
1069 | spin_unlock_irqrestore(&ch->lock, *irq_flags); | ||
1070 | } | ||
1071 | XPC_DEACTIVATE_PARTITION(part, ret); | ||
1072 | if (irq_flags != NULL) { | ||
1073 | spin_lock_irqsave(&ch->lock, *irq_flags); | ||
1074 | } | ||
1075 | } | ||
1076 | } | ||
1077 | } | ||
1078 | |||
1079 | |||
1080 | /* | ||
1081 | * Make it look like the remote partition, which is associated with the | ||
1082 | * specified channel, sent us an IPI. This faked IPI will be handled | ||
1083 | * by xpc_dropped_IPI_check(). | ||
1084 | */ | ||
1085 | #define XPC_NOTIFY_IRQ_SEND_LOCAL(_ch, _ipi_f) \ | ||
1086 | xpc_notify_IRQ_send_local(_ch, _ipi_f, #_ipi_f) | ||
1087 | |||
1088 | static inline void | ||
1089 | xpc_notify_IRQ_send_local(struct xpc_channel *ch, u8 ipi_flag, | ||
1090 | char *ipi_flag_string) | ||
1091 | { | ||
1092 | struct xpc_partition *part = &xpc_partitions[ch->partid]; | ||
1093 | |||
1094 | |||
1095 | FETCHOP_STORE_OP(TO_AMO((u64) &part->local_IPI_amo_va->variable), | ||
1096 | FETCHOP_OR, ((u64) ipi_flag << (ch->number * 8))); | ||
1097 | dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n", | ||
1098 | ipi_flag_string, ch->partid, ch->number); | ||
1099 | } | ||
1100 | |||
1101 | |||
1102 | /* | ||
1103 | * The sending and receiving of IPIs includes the setting of an AMO variable | ||
1104 | * to indicate the reason the IPI was sent. The 64-bit variable is divided | ||
1105 | * up into eight bytes, ordered from right to left. Byte zero pertains to | ||
1106 | * channel 0, byte one to channel 1, and so on. Each byte is described by | ||
1107 | * the following IPI flags. | ||
1108 | */ | ||
1109 | |||
1110 | #define XPC_IPI_CLOSEREQUEST 0x01 | ||
1111 | #define XPC_IPI_CLOSEREPLY 0x02 | ||
1112 | #define XPC_IPI_OPENREQUEST 0x04 | ||
1113 | #define XPC_IPI_OPENREPLY 0x08 | ||
1114 | #define XPC_IPI_MSGREQUEST 0x10 | ||
1115 | |||
1116 | |||
1117 | /* given an AMO variable and a channel#, get its associated IPI flags */ | ||
1118 | #define XPC_GET_IPI_FLAGS(_amo, _c) ((u8) (((_amo) >> ((_c) * 8)) & 0xff)) | ||
1119 | #define XPC_SET_IPI_FLAGS(_amo, _c, _f) (_amo) |= ((u64) (_f) << ((_c) * 8)) | ||
1120 | |||
1121 | #define XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0f) | ||
1122 | #define XPC_ANY_MSG_IPI_FLAGS_SET(_amo) ((_amo) & 0x1010101010101010) | ||
1123 | |||
1124 | |||
1125 | static inline void | ||
1126 | xpc_IPI_send_closerequest(struct xpc_channel *ch, unsigned long *irq_flags) | ||
1127 | { | ||
1128 | struct xpc_openclose_args *args = ch->local_openclose_args; | ||
1129 | |||
1130 | |||
1131 | args->reason = ch->reason; | ||
1132 | |||
1133 | XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREQUEST, irq_flags); | ||
1134 | } | ||
1135 | |||
1136 | static inline void | ||
1137 | xpc_IPI_send_closereply(struct xpc_channel *ch, unsigned long *irq_flags) | ||
1138 | { | ||
1139 | XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREPLY, irq_flags); | ||
1140 | } | ||
1141 | |||
1142 | static inline void | ||
1143 | xpc_IPI_send_openrequest(struct xpc_channel *ch, unsigned long *irq_flags) | ||
1144 | { | ||
1145 | struct xpc_openclose_args *args = ch->local_openclose_args; | ||
1146 | |||
1147 | |||
1148 | args->msg_size = ch->msg_size; | ||
1149 | args->local_nentries = ch->local_nentries; | ||
1150 | |||
1151 | XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREQUEST, irq_flags); | ||
1152 | } | ||
1153 | |||
1154 | static inline void | ||
1155 | xpc_IPI_send_openreply(struct xpc_channel *ch, unsigned long *irq_flags) | ||
1156 | { | ||
1157 | struct xpc_openclose_args *args = ch->local_openclose_args; | ||
1158 | |||
1159 | |||
1160 | args->remote_nentries = ch->remote_nentries; | ||
1161 | args->local_nentries = ch->local_nentries; | ||
1162 | args->local_msgqueue_pa = __pa(ch->local_msgqueue); | ||
1163 | |||
1164 | XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREPLY, irq_flags); | ||
1165 | } | ||
1166 | |||
1167 | static inline void | ||
1168 | xpc_IPI_send_msgrequest(struct xpc_channel *ch) | ||
1169 | { | ||
1170 | XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_MSGREQUEST, NULL); | ||
1171 | } | ||
1172 | |||
1173 | static inline void | ||
1174 | xpc_IPI_send_local_msgrequest(struct xpc_channel *ch) | ||
1175 | { | ||
1176 | XPC_NOTIFY_IRQ_SEND_LOCAL(ch, XPC_IPI_MSGREQUEST); | ||
1177 | } | ||
1178 | |||
1179 | |||
1180 | /* | ||
1181 | * Memory for XPC's AMO variables is allocated by the MSPEC driver. These | ||
1182 | * pages are located in the lowest granule. The lowest granule uses 4k pages | ||
1183 | * for cached references and an alternate TLB handler to never provide a | ||
1184 | * cacheable mapping for the entire region. This will prevent speculative | ||
1185 | * reading of cached copies of our lines from being issued which will cause | ||
1186 | * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64 | ||
1187 | * AMO variables (based on XP_MAX_PARTITIONS) for message notification and an | ||
1188 | * additional 128 AMO variables (based on XP_NASID_MASK_WORDS) for partition | ||
1189 | * activation and 2 AMO variables for partition deactivation. | ||
1190 | */ | ||
1191 | static inline AMO_t * | ||
1192 | xpc_IPI_init(int index) | ||
1193 | { | ||
1194 | AMO_t *amo = xpc_vars->amos_page + index; | ||
1195 | |||
1196 | |||
1197 | (void) xpc_IPI_receive(amo); /* clear AMO variable */ | ||
1198 | return amo; | ||
1199 | } | ||
1200 | |||
1201 | |||
1202 | |||
1203 | static inline enum xpc_retval | ||
1204 | xpc_map_bte_errors(bte_result_t error) | ||
1205 | { | ||
1206 | switch (error) { | ||
1207 | case BTE_SUCCESS: return xpcSuccess; | ||
1208 | case BTEFAIL_DIR: return xpcBteDirectoryError; | ||
1209 | case BTEFAIL_POISON: return xpcBtePoisonError; | ||
1210 | case BTEFAIL_WERR: return xpcBteWriteError; | ||
1211 | case BTEFAIL_ACCESS: return xpcBteAccessError; | ||
1212 | case BTEFAIL_PWERR: return xpcBtePWriteError; | ||
1213 | case BTEFAIL_PRERR: return xpcBtePReadError; | ||
1214 | case BTEFAIL_TOUT: return xpcBteTimeOutError; | ||
1215 | case BTEFAIL_XTERR: return xpcBteXtalkError; | ||
1216 | case BTEFAIL_NOTAVAIL: return xpcBteNotAvailable; | ||
1217 | default: return xpcBteUnmappedError; | ||
1218 | } | ||
1219 | } | ||
1220 | |||
1221 | |||
1222 | |||
1223 | static inline void * | ||
1224 | xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base) | ||
1225 | { | ||
1226 | /* see if kmalloc will give us cachline aligned memory by default */ | ||
1227 | *base = kmalloc(size, flags); | ||
1228 | if (*base == NULL) { | ||
1229 | return NULL; | ||
1230 | } | ||
1231 | if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) { | ||
1232 | return *base; | ||
1233 | } | ||
1234 | kfree(*base); | ||
1235 | |||
1236 | /* nope, we'll have to do it ourselves */ | ||
1237 | *base = kmalloc(size + L1_CACHE_BYTES, flags); | ||
1238 | if (*base == NULL) { | ||
1239 | return NULL; | ||
1240 | } | ||
1241 | return (void *) L1_CACHE_ALIGN((u64) *base); | ||
1242 | } | ||
1243 | |||
1244 | |||
1245 | /* | ||
1246 | * Check to see if there is any channel activity to/from the specified | ||
1247 | * partition. | ||
1248 | */ | ||
1249 | static inline void | ||
1250 | xpc_check_for_channel_activity(struct xpc_partition *part) | ||
1251 | { | ||
1252 | u64 IPI_amo; | ||
1253 | unsigned long irq_flags; | ||
1254 | |||
1255 | |||
1256 | IPI_amo = xpc_IPI_receive(part->local_IPI_amo_va); | ||
1257 | if (IPI_amo == 0) { | ||
1258 | return; | ||
1259 | } | ||
1260 | |||
1261 | spin_lock_irqsave(&part->IPI_lock, irq_flags); | ||
1262 | part->local_IPI_amo |= IPI_amo; | ||
1263 | spin_unlock_irqrestore(&part->IPI_lock, irq_flags); | ||
1264 | |||
1265 | dev_dbg(xpc_chan, "received IPI from partid=%d, IPI_amo=0x%lx\n", | ||
1266 | XPC_PARTID(part), IPI_amo); | ||
1267 | |||
1268 | xpc_wakeup_channel_mgr(part); | ||
1269 | } | ||
1270 | |||
1271 | |||
1272 | #endif /* _IA64_SN_KERNEL_XPC_H */ | ||
1273 | |||
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index abf4fc2a87..8d950c778b 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.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) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | 9 | ||
@@ -22,9 +22,11 @@ | |||
22 | #include <linux/cache.h> | 22 | #include <linux/cache.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/mutex.h> | ||
26 | #include <linux/completion.h> | ||
25 | #include <asm/sn/bte.h> | 27 | #include <asm/sn/bte.h> |
26 | #include <asm/sn/sn_sal.h> | 28 | #include <asm/sn/sn_sal.h> |
27 | #include "xpc.h" | 29 | #include <asm/sn/xpc.h> |
28 | 30 | ||
29 | 31 | ||
30 | /* | 32 | /* |
@@ -56,8 +58,8 @@ xpc_initialize_channels(struct xpc_partition *part, partid_t partid) | |||
56 | atomic_set(&ch->n_to_notify, 0); | 58 | atomic_set(&ch->n_to_notify, 0); |
57 | 59 | ||
58 | spin_lock_init(&ch->lock); | 60 | spin_lock_init(&ch->lock); |
59 | sema_init(&ch->msg_to_pull_sema, 1); /* mutex */ | 61 | mutex_init(&ch->msg_to_pull_mutex); |
60 | sema_init(&ch->wdisconnect_sema, 0); /* event wait */ | 62 | init_completion(&ch->wdisconnect_wait); |
61 | 63 | ||
62 | atomic_set(&ch->n_on_msg_allocate_wq, 0); | 64 | atomic_set(&ch->n_on_msg_allocate_wq, 0); |
63 | init_waitqueue_head(&ch->msg_allocate_wq); | 65 | init_waitqueue_head(&ch->msg_allocate_wq); |
@@ -534,7 +536,6 @@ static enum xpc_retval | |||
534 | xpc_allocate_msgqueues(struct xpc_channel *ch) | 536 | xpc_allocate_msgqueues(struct xpc_channel *ch) |
535 | { | 537 | { |
536 | unsigned long irq_flags; | 538 | unsigned long irq_flags; |
537 | int i; | ||
538 | enum xpc_retval ret; | 539 | enum xpc_retval ret; |
539 | 540 | ||
540 | 541 | ||
@@ -552,11 +553,6 @@ xpc_allocate_msgqueues(struct xpc_channel *ch) | |||
552 | return ret; | 553 | return ret; |
553 | } | 554 | } |
554 | 555 | ||
555 | for (i = 0; i < ch->local_nentries; i++) { | ||
556 | /* use a semaphore as an event wait queue */ | ||
557 | sema_init(&ch->notify_queue[i].sema, 0); | ||
558 | } | ||
559 | |||
560 | spin_lock_irqsave(&ch->lock, irq_flags); | 556 | spin_lock_irqsave(&ch->lock, irq_flags); |
561 | ch->flags |= XPC_C_SETUP; | 557 | ch->flags |= XPC_C_SETUP; |
562 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 558 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
@@ -779,6 +775,12 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) | |||
779 | 775 | ||
780 | /* both sides are disconnected now */ | 776 | /* both sides are disconnected now */ |
781 | 777 | ||
778 | if (ch->flags & XPC_C_CONNECTCALLOUT) { | ||
779 | spin_unlock_irqrestore(&ch->lock, *irq_flags); | ||
780 | xpc_disconnect_callout(ch, xpcDisconnected); | ||
781 | spin_lock_irqsave(&ch->lock, *irq_flags); | ||
782 | } | ||
783 | |||
782 | /* it's now safe to free the channel's message queues */ | 784 | /* it's now safe to free the channel's message queues */ |
783 | xpc_free_msgqueues(ch); | 785 | xpc_free_msgqueues(ch); |
784 | 786 | ||
@@ -793,10 +795,8 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) | |||
793 | } | 795 | } |
794 | 796 | ||
795 | if (ch->flags & XPC_C_WDISCONNECT) { | 797 | if (ch->flags & XPC_C_WDISCONNECT) { |
796 | spin_unlock_irqrestore(&ch->lock, *irq_flags); | 798 | /* we won't lose the CPU since we're holding ch->lock */ |
797 | up(&ch->wdisconnect_sema); | 799 | complete(&ch->wdisconnect_wait); |
798 | spin_lock_irqsave(&ch->lock, *irq_flags); | ||
799 | |||
800 | } else if (ch->delayed_IPI_flags) { | 800 | } else if (ch->delayed_IPI_flags) { |
801 | if (part->act_state != XPC_P_DEACTIVATING) { | 801 | if (part->act_state != XPC_P_DEACTIVATING) { |
802 | /* time to take action on any delayed IPI flags */ | 802 | /* time to take action on any delayed IPI flags */ |
@@ -1086,12 +1086,12 @@ xpc_connect_channel(struct xpc_channel *ch) | |||
1086 | struct xpc_registration *registration = &xpc_registrations[ch->number]; | 1086 | struct xpc_registration *registration = &xpc_registrations[ch->number]; |
1087 | 1087 | ||
1088 | 1088 | ||
1089 | if (down_trylock(®istration->sema) != 0) { | 1089 | if (mutex_trylock(®istration->mutex) == 0) { |
1090 | return xpcRetry; | 1090 | return xpcRetry; |
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | if (!XPC_CHANNEL_REGISTERED(ch->number)) { | 1093 | if (!XPC_CHANNEL_REGISTERED(ch->number)) { |
1094 | up(®istration->sema); | 1094 | mutex_unlock(®istration->mutex); |
1095 | return xpcUnregistered; | 1095 | return xpcUnregistered; |
1096 | } | 1096 | } |
1097 | 1097 | ||
@@ -1102,7 +1102,7 @@ xpc_connect_channel(struct xpc_channel *ch) | |||
1102 | 1102 | ||
1103 | if (ch->flags & XPC_C_DISCONNECTING) { | 1103 | if (ch->flags & XPC_C_DISCONNECTING) { |
1104 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 1104 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
1105 | up(®istration->sema); | 1105 | mutex_unlock(®istration->mutex); |
1106 | return ch->reason; | 1106 | return ch->reason; |
1107 | } | 1107 | } |
1108 | 1108 | ||
@@ -1134,7 +1134,7 @@ xpc_connect_channel(struct xpc_channel *ch) | |||
1134 | * channel lock be locked and will unlock and relock | 1134 | * channel lock be locked and will unlock and relock |
1135 | * the channel lock as needed. | 1135 | * the channel lock as needed. |
1136 | */ | 1136 | */ |
1137 | up(®istration->sema); | 1137 | mutex_unlock(®istration->mutex); |
1138 | XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes, | 1138 | XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes, |
1139 | &irq_flags); | 1139 | &irq_flags); |
1140 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 1140 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
@@ -1149,7 +1149,7 @@ xpc_connect_channel(struct xpc_channel *ch) | |||
1149 | atomic_inc(&xpc_partitions[ch->partid].nchannels_active); | 1149 | atomic_inc(&xpc_partitions[ch->partid].nchannels_active); |
1150 | } | 1150 | } |
1151 | 1151 | ||
1152 | up(®istration->sema); | 1152 | mutex_unlock(®istration->mutex); |
1153 | 1153 | ||
1154 | 1154 | ||
1155 | /* initiate the connection */ | 1155 | /* initiate the connection */ |
@@ -1645,7 +1645,7 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch, | |||
1645 | 1645 | ||
1646 | 1646 | ||
1647 | void | 1647 | void |
1648 | xpc_disconnecting_callout(struct xpc_channel *ch) | 1648 | xpc_disconnect_callout(struct xpc_channel *ch, enum xpc_retval reason) |
1649 | { | 1649 | { |
1650 | /* | 1650 | /* |
1651 | * Let the channel's registerer know that the channel is being | 1651 | * Let the channel's registerer know that the channel is being |
@@ -1654,15 +1654,13 @@ xpc_disconnecting_callout(struct xpc_channel *ch) | |||
1654 | */ | 1654 | */ |
1655 | 1655 | ||
1656 | if (ch->func != NULL) { | 1656 | if (ch->func != NULL) { |
1657 | dev_dbg(xpc_chan, "ch->func() called, reason=xpcDisconnecting," | 1657 | dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, " |
1658 | " partid=%d, channel=%d\n", ch->partid, ch->number); | 1658 | "channel=%d\n", reason, ch->partid, ch->number); |
1659 | 1659 | ||
1660 | ch->func(xpcDisconnecting, ch->partid, ch->number, NULL, | 1660 | ch->func(reason, ch->partid, ch->number, NULL, ch->key); |
1661 | ch->key); | ||
1662 | 1661 | ||
1663 | dev_dbg(xpc_chan, "ch->func() returned, reason=" | 1662 | dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, " |
1664 | "xpcDisconnecting, partid=%d, channel=%d\n", | 1663 | "channel=%d\n", reason, ch->partid, ch->number); |
1665 | ch->partid, ch->number); | ||
1666 | } | 1664 | } |
1667 | } | 1665 | } |
1668 | 1666 | ||
@@ -2085,7 +2083,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get) | |||
2085 | enum xpc_retval ret; | 2083 | enum xpc_retval ret; |
2086 | 2084 | ||
2087 | 2085 | ||
2088 | if (down_interruptible(&ch->msg_to_pull_sema) != 0) { | 2086 | if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) { |
2089 | /* we were interrupted by a signal */ | 2087 | /* we were interrupted by a signal */ |
2090 | return NULL; | 2088 | return NULL; |
2091 | } | 2089 | } |
@@ -2121,7 +2119,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get) | |||
2121 | 2119 | ||
2122 | XPC_DEACTIVATE_PARTITION(part, ret); | 2120 | XPC_DEACTIVATE_PARTITION(part, ret); |
2123 | 2121 | ||
2124 | up(&ch->msg_to_pull_sema); | 2122 | mutex_unlock(&ch->msg_to_pull_mutex); |
2125 | return NULL; | 2123 | return NULL; |
2126 | } | 2124 | } |
2127 | 2125 | ||
@@ -2130,7 +2128,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get) | |||
2130 | ch->next_msg_to_pull += nmsgs; | 2128 | ch->next_msg_to_pull += nmsgs; |
2131 | } | 2129 | } |
2132 | 2130 | ||
2133 | up(&ch->msg_to_pull_sema); | 2131 | mutex_unlock(&ch->msg_to_pull_mutex); |
2134 | 2132 | ||
2135 | /* return the message we were looking for */ | 2133 | /* return the message we were looking for */ |
2136 | msg_offset = (get % ch->remote_nentries) * ch->msg_size; | 2134 | msg_offset = (get % ch->remote_nentries) * ch->msg_size; |
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index b617236524..c75f8aeefc 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.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) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | 9 | ||
@@ -55,11 +55,12 @@ | |||
55 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
56 | #include <linux/delay.h> | 56 | #include <linux/delay.h> |
57 | #include <linux/reboot.h> | 57 | #include <linux/reboot.h> |
58 | #include <linux/completion.h> | ||
58 | #include <asm/sn/intr.h> | 59 | #include <asm/sn/intr.h> |
59 | #include <asm/sn/sn_sal.h> | 60 | #include <asm/sn/sn_sal.h> |
60 | #include <asm/kdebug.h> | 61 | #include <asm/kdebug.h> |
61 | #include <asm/uaccess.h> | 62 | #include <asm/uaccess.h> |
62 | #include "xpc.h" | 63 | #include <asm/sn/xpc.h> |
63 | 64 | ||
64 | 65 | ||
65 | /* define two XPC debug device structures to be used with dev_dbg() et al */ | 66 | /* define two XPC debug device structures to be used with dev_dbg() et al */ |
@@ -82,6 +83,9 @@ struct device *xpc_part = &xpc_part_dbg_subname; | |||
82 | struct device *xpc_chan = &xpc_chan_dbg_subname; | 83 | struct device *xpc_chan = &xpc_chan_dbg_subname; |
83 | 84 | ||
84 | 85 | ||
86 | static int xpc_kdebug_ignore; | ||
87 | |||
88 | |||
85 | /* systune related variables for /proc/sys directories */ | 89 | /* systune related variables for /proc/sys directories */ |
86 | 90 | ||
87 | static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL; | 91 | static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL; |
@@ -162,6 +166,8 @@ static ctl_table xpc_sys_dir[] = { | |||
162 | }; | 166 | }; |
163 | static struct ctl_table_header *xpc_sysctl; | 167 | static struct ctl_table_header *xpc_sysctl; |
164 | 168 | ||
169 | /* non-zero if any remote partition disengage request was timed out */ | ||
170 | int xpc_disengage_request_timedout; | ||
165 | 171 | ||
166 | /* #of IRQs received */ | 172 | /* #of IRQs received */ |
167 | static atomic_t xpc_act_IRQ_rcvd; | 173 | static atomic_t xpc_act_IRQ_rcvd; |
@@ -172,10 +178,10 @@ static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq); | |||
172 | static unsigned long xpc_hb_check_timeout; | 178 | static unsigned long xpc_hb_check_timeout; |
173 | 179 | ||
174 | /* notification that the xpc_hb_checker thread has exited */ | 180 | /* notification that the xpc_hb_checker thread has exited */ |
175 | static DECLARE_MUTEX_LOCKED(xpc_hb_checker_exited); | 181 | static DECLARE_COMPLETION(xpc_hb_checker_exited); |
176 | 182 | ||
177 | /* notification that the xpc_discovery thread has exited */ | 183 | /* notification that the xpc_discovery thread has exited */ |
178 | static DECLARE_MUTEX_LOCKED(xpc_discovery_exited); | 184 | static DECLARE_COMPLETION(xpc_discovery_exited); |
179 | 185 | ||
180 | 186 | ||
181 | static struct timer_list xpc_hb_timer; | 187 | static struct timer_list xpc_hb_timer; |
@@ -316,7 +322,7 @@ xpc_hb_checker(void *ignore) | |||
316 | 322 | ||
317 | 323 | ||
318 | /* mark this thread as having exited */ | 324 | /* mark this thread as having exited */ |
319 | up(&xpc_hb_checker_exited); | 325 | complete(&xpc_hb_checker_exited); |
320 | return 0; | 326 | return 0; |
321 | } | 327 | } |
322 | 328 | ||
@@ -336,7 +342,7 @@ xpc_initiate_discovery(void *ignore) | |||
336 | dev_dbg(xpc_part, "discovery thread is exiting\n"); | 342 | dev_dbg(xpc_part, "discovery thread is exiting\n"); |
337 | 343 | ||
338 | /* mark this thread as having exited */ | 344 | /* mark this thread as having exited */ |
339 | up(&xpc_discovery_exited); | 345 | complete(&xpc_discovery_exited); |
340 | return 0; | 346 | return 0; |
341 | } | 347 | } |
342 | 348 | ||
@@ -773,7 +779,7 @@ xpc_daemonize_kthread(void *args) | |||
773 | ch->flags |= XPC_C_DISCONNECTCALLOUT; | 779 | ch->flags |= XPC_C_DISCONNECTCALLOUT; |
774 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 780 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
775 | 781 | ||
776 | xpc_disconnecting_callout(ch); | 782 | xpc_disconnect_callout(ch, xpcDisconnecting); |
777 | } else { | 783 | } else { |
778 | spin_unlock_irqrestore(&ch->lock, irq_flags); | 784 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
779 | } | 785 | } |
@@ -888,7 +894,7 @@ xpc_disconnect_wait(int ch_number) | |||
888 | continue; | 894 | continue; |
889 | } | 895 | } |
890 | 896 | ||
891 | (void) down(&ch->wdisconnect_sema); | 897 | wait_for_completion(&ch->wdisconnect_wait); |
892 | 898 | ||
893 | spin_lock_irqsave(&ch->lock, irq_flags); | 899 | spin_lock_irqsave(&ch->lock, irq_flags); |
894 | DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED)); | 900 | DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED)); |
@@ -921,9 +927,9 @@ static void | |||
921 | xpc_do_exit(enum xpc_retval reason) | 927 | xpc_do_exit(enum xpc_retval reason) |
922 | { | 928 | { |
923 | partid_t partid; | 929 | partid_t partid; |
924 | int active_part_count; | 930 | int active_part_count, printed_waiting_msg = 0; |
925 | struct xpc_partition *part; | 931 | struct xpc_partition *part; |
926 | unsigned long printmsg_time; | 932 | unsigned long printmsg_time, disengage_request_timeout = 0; |
927 | 933 | ||
928 | 934 | ||
929 | /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */ | 935 | /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */ |
@@ -941,10 +947,10 @@ xpc_do_exit(enum xpc_retval reason) | |||
941 | free_irq(SGI_XPC_ACTIVATE, NULL); | 947 | free_irq(SGI_XPC_ACTIVATE, NULL); |
942 | 948 | ||
943 | /* wait for the discovery thread to exit */ | 949 | /* wait for the discovery thread to exit */ |
944 | down(&xpc_discovery_exited); | 950 | wait_for_completion(&xpc_discovery_exited); |
945 | 951 | ||
946 | /* wait for the heartbeat checker thread to exit */ | 952 | /* wait for the heartbeat checker thread to exit */ |
947 | down(&xpc_hb_checker_exited); | 953 | wait_for_completion(&xpc_hb_checker_exited); |
948 | 954 | ||
949 | 955 | ||
950 | /* sleep for a 1/3 of a second or so */ | 956 | /* sleep for a 1/3 of a second or so */ |
@@ -953,7 +959,8 @@ xpc_do_exit(enum xpc_retval reason) | |||
953 | 959 | ||
954 | /* wait for all partitions to become inactive */ | 960 | /* wait for all partitions to become inactive */ |
955 | 961 | ||
956 | printmsg_time = jiffies; | 962 | printmsg_time = jiffies + (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ); |
963 | xpc_disengage_request_timedout = 0; | ||
957 | 964 | ||
958 | do { | 965 | do { |
959 | active_part_count = 0; | 966 | active_part_count = 0; |
@@ -969,20 +976,39 @@ xpc_do_exit(enum xpc_retval reason) | |||
969 | active_part_count++; | 976 | active_part_count++; |
970 | 977 | ||
971 | XPC_DEACTIVATE_PARTITION(part, reason); | 978 | XPC_DEACTIVATE_PARTITION(part, reason); |
972 | } | ||
973 | 979 | ||
974 | if (active_part_count == 0) { | 980 | if (part->disengage_request_timeout > |
975 | break; | 981 | disengage_request_timeout) { |
982 | disengage_request_timeout = | ||
983 | part->disengage_request_timeout; | ||
984 | } | ||
976 | } | 985 | } |
977 | 986 | ||
978 | if (jiffies >= printmsg_time) { | 987 | if (xpc_partition_engaged(-1UL)) { |
979 | dev_info(xpc_part, "waiting for partitions to " | 988 | if (time_after(jiffies, printmsg_time)) { |
980 | "deactivate/disengage, active count=%d, remote " | 989 | dev_info(xpc_part, "waiting for remote " |
981 | "engaged=0x%lx\n", active_part_count, | 990 | "partitions to disengage, timeout in " |
982 | xpc_partition_engaged(1UL << partid)); | 991 | "%ld seconds\n", |
983 | 992 | (disengage_request_timeout - jiffies) | |
984 | printmsg_time = jiffies + | 993 | / HZ); |
994 | printmsg_time = jiffies + | ||
985 | (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ); | 995 | (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ); |
996 | printed_waiting_msg = 1; | ||
997 | } | ||
998 | |||
999 | } else if (active_part_count > 0) { | ||
1000 | if (printed_waiting_msg) { | ||
1001 | dev_info(xpc_part, "waiting for local partition" | ||
1002 | " to disengage\n"); | ||
1003 | printed_waiting_msg = 0; | ||
1004 | } | ||
1005 | |||
1006 | } else { | ||
1007 | if (!xpc_disengage_request_timedout) { | ||
1008 | dev_info(xpc_part, "all partitions have " | ||
1009 | "disengaged\n"); | ||
1010 | } | ||
1011 | break; | ||
986 | } | 1012 | } |
987 | 1013 | ||
988 | /* sleep for a 1/3 of a second or so */ | 1014 | /* sleep for a 1/3 of a second or so */ |
@@ -1000,11 +1026,13 @@ xpc_do_exit(enum xpc_retval reason) | |||
1000 | del_timer_sync(&xpc_hb_timer); | 1026 | del_timer_sync(&xpc_hb_timer); |
1001 | DBUG_ON(xpc_vars->heartbeating_to_mask != 0); | 1027 | DBUG_ON(xpc_vars->heartbeating_to_mask != 0); |
1002 | 1028 | ||
1003 | /* take ourselves off of the reboot_notifier_list */ | 1029 | if (reason == xpcUnloading) { |
1004 | (void) unregister_reboot_notifier(&xpc_reboot_notifier); | 1030 | /* take ourselves off of the reboot_notifier_list */ |
1031 | (void) unregister_reboot_notifier(&xpc_reboot_notifier); | ||
1005 | 1032 | ||
1006 | /* take ourselves off of the die_notifier list */ | 1033 | /* take ourselves off of the die_notifier list */ |
1007 | (void) unregister_die_notifier(&xpc_die_notifier); | 1034 | (void) unregister_die_notifier(&xpc_die_notifier); |
1035 | } | ||
1008 | 1036 | ||
1009 | /* close down protections for IPI operations */ | 1037 | /* close down protections for IPI operations */ |
1010 | xpc_restrict_IPI_ops(); | 1038 | xpc_restrict_IPI_ops(); |
@@ -1020,7 +1048,35 @@ xpc_do_exit(enum xpc_retval reason) | |||
1020 | 1048 | ||
1021 | 1049 | ||
1022 | /* | 1050 | /* |
1023 | * Called when the system is about to be either restarted or halted. | 1051 | * This function is called when the system is being rebooted. |
1052 | */ | ||
1053 | static int | ||
1054 | xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) | ||
1055 | { | ||
1056 | enum xpc_retval reason; | ||
1057 | |||
1058 | |||
1059 | switch (event) { | ||
1060 | case SYS_RESTART: | ||
1061 | reason = xpcSystemReboot; | ||
1062 | break; | ||
1063 | case SYS_HALT: | ||
1064 | reason = xpcSystemHalt; | ||
1065 | break; | ||
1066 | case SYS_POWER_OFF: | ||
1067 | reason = xpcSystemPoweroff; | ||
1068 | break; | ||
1069 | default: | ||
1070 | reason = xpcSystemGoingDown; | ||
1071 | } | ||
1072 | |||
1073 | xpc_do_exit(reason); | ||
1074 | return NOTIFY_DONE; | ||
1075 | } | ||
1076 | |||
1077 | |||
1078 | /* | ||
1079 | * Notify other partitions to disengage from all references to our memory. | ||
1024 | */ | 1080 | */ |
1025 | static void | 1081 | static void |
1026 | xpc_die_disengage(void) | 1082 | xpc_die_disengage(void) |
@@ -1028,7 +1084,7 @@ xpc_die_disengage(void) | |||
1028 | struct xpc_partition *part; | 1084 | struct xpc_partition *part; |
1029 | partid_t partid; | 1085 | partid_t partid; |
1030 | unsigned long engaged; | 1086 | unsigned long engaged; |
1031 | long time, print_time, disengage_request_timeout; | 1087 | long time, printmsg_time, disengage_request_timeout; |
1032 | 1088 | ||
1033 | 1089 | ||
1034 | /* keep xpc_hb_checker thread from doing anything (just in case) */ | 1090 | /* keep xpc_hb_checker thread from doing anything (just in case) */ |
@@ -1055,57 +1111,53 @@ xpc_die_disengage(void) | |||
1055 | } | 1111 | } |
1056 | } | 1112 | } |
1057 | 1113 | ||
1058 | print_time = rtc_time(); | 1114 | time = rtc_time(); |
1059 | disengage_request_timeout = print_time + | 1115 | printmsg_time = time + |
1116 | (XPC_DISENGAGE_PRINTMSG_INTERVAL * sn_rtc_cycles_per_second); | ||
1117 | disengage_request_timeout = time + | ||
1060 | (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second); | 1118 | (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second); |
1061 | 1119 | ||
1062 | /* wait for all other partitions to disengage from us */ | 1120 | /* wait for all other partitions to disengage from us */ |
1063 | 1121 | ||
1064 | while ((engaged = xpc_partition_engaged(-1UL)) && | 1122 | while (1) { |
1065 | (time = rtc_time()) < disengage_request_timeout) { | 1123 | engaged = xpc_partition_engaged(-1UL); |
1124 | if (!engaged) { | ||
1125 | dev_info(xpc_part, "all partitions have disengaged\n"); | ||
1126 | break; | ||
1127 | } | ||
1066 | 1128 | ||
1067 | if (time >= print_time) { | 1129 | time = rtc_time(); |
1130 | if (time >= disengage_request_timeout) { | ||
1131 | for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) { | ||
1132 | if (engaged & (1UL << partid)) { | ||
1133 | dev_info(xpc_part, "disengage from " | ||
1134 | "remote partition %d timed " | ||
1135 | "out\n", partid); | ||
1136 | } | ||
1137 | } | ||
1138 | break; | ||
1139 | } | ||
1140 | |||
1141 | if (time >= printmsg_time) { | ||
1068 | dev_info(xpc_part, "waiting for remote partitions to " | 1142 | dev_info(xpc_part, "waiting for remote partitions to " |
1069 | "disengage, engaged=0x%lx\n", engaged); | 1143 | "disengage, timeout in %ld seconds\n", |
1070 | print_time = time + (XPC_DISENGAGE_PRINTMSG_INTERVAL * | 1144 | (disengage_request_timeout - time) / |
1145 | sn_rtc_cycles_per_second); | ||
1146 | printmsg_time = time + | ||
1147 | (XPC_DISENGAGE_PRINTMSG_INTERVAL * | ||
1071 | sn_rtc_cycles_per_second); | 1148 | sn_rtc_cycles_per_second); |
1072 | } | 1149 | } |
1073 | } | 1150 | } |
1074 | dev_info(xpc_part, "finished waiting for remote partitions to " | ||
1075 | "disengage, engaged=0x%lx\n", engaged); | ||
1076 | } | ||
1077 | |||
1078 | |||
1079 | /* | ||
1080 | * This function is called when the system is being rebooted. | ||
1081 | */ | ||
1082 | static int | ||
1083 | xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) | ||
1084 | { | ||
1085 | enum xpc_retval reason; | ||
1086 | |||
1087 | |||
1088 | switch (event) { | ||
1089 | case SYS_RESTART: | ||
1090 | reason = xpcSystemReboot; | ||
1091 | break; | ||
1092 | case SYS_HALT: | ||
1093 | reason = xpcSystemHalt; | ||
1094 | break; | ||
1095 | case SYS_POWER_OFF: | ||
1096 | reason = xpcSystemPoweroff; | ||
1097 | break; | ||
1098 | default: | ||
1099 | reason = xpcSystemGoingDown; | ||
1100 | } | ||
1101 | |||
1102 | xpc_do_exit(reason); | ||
1103 | return NOTIFY_DONE; | ||
1104 | } | 1151 | } |
1105 | 1152 | ||
1106 | 1153 | ||
1107 | /* | 1154 | /* |
1108 | * This function is called when the system is being rebooted. | 1155 | * This function is called when the system is being restarted or halted due |
1156 | * to some sort of system failure. If this is the case we need to notify the | ||
1157 | * other partitions to disengage from all references to our memory. | ||
1158 | * This function can also be called when our heartbeater could be offlined | ||
1159 | * for a time. In this case we need to notify other partitions to not worry | ||
1160 | * about the lack of a heartbeat. | ||
1109 | */ | 1161 | */ |
1110 | static int | 1162 | static int |
1111 | xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | 1163 | xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) |
@@ -1115,11 +1167,25 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | |||
1115 | case DIE_MACHINE_HALT: | 1167 | case DIE_MACHINE_HALT: |
1116 | xpc_die_disengage(); | 1168 | xpc_die_disengage(); |
1117 | break; | 1169 | break; |
1170 | |||
1171 | case DIE_KDEBUG_ENTER: | ||
1172 | /* Should lack of heartbeat be ignored by other partitions? */ | ||
1173 | if (!xpc_kdebug_ignore) { | ||
1174 | break; | ||
1175 | } | ||
1176 | /* fall through */ | ||
1118 | case DIE_MCA_MONARCH_ENTER: | 1177 | case DIE_MCA_MONARCH_ENTER: |
1119 | case DIE_INIT_MONARCH_ENTER: | 1178 | case DIE_INIT_MONARCH_ENTER: |
1120 | xpc_vars->heartbeat++; | 1179 | xpc_vars->heartbeat++; |
1121 | xpc_vars->heartbeat_offline = 1; | 1180 | xpc_vars->heartbeat_offline = 1; |
1122 | break; | 1181 | break; |
1182 | |||
1183 | case DIE_KDEBUG_LEAVE: | ||
1184 | /* Is lack of heartbeat being ignored by other partitions? */ | ||
1185 | if (!xpc_kdebug_ignore) { | ||
1186 | break; | ||
1187 | } | ||
1188 | /* fall through */ | ||
1123 | case DIE_MCA_MONARCH_LEAVE: | 1189 | case DIE_MCA_MONARCH_LEAVE: |
1124 | case DIE_INIT_MONARCH_LEAVE: | 1190 | case DIE_INIT_MONARCH_LEAVE: |
1125 | xpc_vars->heartbeat++; | 1191 | xpc_vars->heartbeat++; |
@@ -1302,7 +1368,7 @@ xpc_init(void) | |||
1302 | dev_err(xpc_part, "failed while forking discovery thread\n"); | 1368 | dev_err(xpc_part, "failed while forking discovery thread\n"); |
1303 | 1369 | ||
1304 | /* mark this new thread as a non-starter */ | 1370 | /* mark this new thread as a non-starter */ |
1305 | up(&xpc_discovery_exited); | 1371 | complete(&xpc_discovery_exited); |
1306 | 1372 | ||
1307 | xpc_do_exit(xpcUnloading); | 1373 | xpc_do_exit(xpcUnloading); |
1308 | return -EBUSY; | 1374 | return -EBUSY; |
@@ -1344,3 +1410,7 @@ module_param(xpc_disengage_request_timelimit, int, 0); | |||
1344 | MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait " | 1410 | MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait " |
1345 | "for disengage request to complete."); | 1411 | "for disengage request to complete."); |
1346 | 1412 | ||
1413 | module_param(xpc_kdebug_ignore, int, 0); | ||
1414 | MODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by " | ||
1415 | "other partitions when dropping into kdebug."); | ||
1416 | |||
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c index cdd6431853..88a730e6cf 100644 --- a/arch/ia64/sn/kernel/xpc_partition.c +++ b/arch/ia64/sn/kernel/xpc_partition.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) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | 9 | ||
@@ -28,7 +28,7 @@ | |||
28 | #include <asm/sn/sn_sal.h> | 28 | #include <asm/sn/sn_sal.h> |
29 | #include <asm/sn/nodepda.h> | 29 | #include <asm/sn/nodepda.h> |
30 | #include <asm/sn/addrs.h> | 30 | #include <asm/sn/addrs.h> |
31 | #include "xpc.h" | 31 | #include <asm/sn/xpc.h> |
32 | 32 | ||
33 | 33 | ||
34 | /* XPC is exiting flag */ | 34 | /* XPC is exiting flag */ |
@@ -771,7 +771,8 @@ xpc_identify_act_IRQ_req(int nasid) | |||
771 | } | 771 | } |
772 | } | 772 | } |
773 | 773 | ||
774 | if (!xpc_partition_disengaged(part)) { | 774 | if (part->disengage_request_timeout > 0 && |
775 | !xpc_partition_disengaged(part)) { | ||
775 | /* still waiting on other side to disengage from us */ | 776 | /* still waiting on other side to disengage from us */ |
776 | return; | 777 | return; |
777 | } | 778 | } |
@@ -873,6 +874,9 @@ xpc_partition_disengaged(struct xpc_partition *part) | |||
873 | * request in a timely fashion, so assume it's dead. | 874 | * request in a timely fashion, so assume it's dead. |
874 | */ | 875 | */ |
875 | 876 | ||
877 | dev_info(xpc_part, "disengage from remote partition %d " | ||
878 | "timed out\n", partid); | ||
879 | xpc_disengage_request_timedout = 1; | ||
876 | xpc_clear_partition_engaged(1UL << partid); | 880 | xpc_clear_partition_engaged(1UL << partid); |
877 | disengaged = 1; | 881 | disengaged = 1; |
878 | } | 882 | } |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c index d1647b863e..aa3fa5152a 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_ate.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_ate.c | |||
@@ -18,10 +18,10 @@ int pcibr_invalidate_ate = 0; /* by default don't invalidate ATE on free */ | |||
18 | * mark_ate: Mark the ate as either free or inuse. | 18 | * mark_ate: Mark the ate as either free or inuse. |
19 | */ | 19 | */ |
20 | static void mark_ate(struct ate_resource *ate_resource, int start, int number, | 20 | static void mark_ate(struct ate_resource *ate_resource, int start, int number, |
21 | uint64_t value) | 21 | u64 value) |
22 | { | 22 | { |
23 | 23 | ||
24 | uint64_t *ate = ate_resource->ate; | 24 | u64 *ate = ate_resource->ate; |
25 | int index; | 25 | int index; |
26 | int length = 0; | 26 | int length = 0; |
27 | 27 | ||
@@ -38,7 +38,7 @@ static int find_free_ate(struct ate_resource *ate_resource, int start, | |||
38 | int count) | 38 | int count) |
39 | { | 39 | { |
40 | 40 | ||
41 | uint64_t *ate = ate_resource->ate; | 41 | u64 *ate = ate_resource->ate; |
42 | int index; | 42 | int index; |
43 | int start_free; | 43 | int start_free; |
44 | 44 | ||
@@ -119,7 +119,7 @@ static inline int alloc_ate_resource(struct ate_resource *ate_resource, | |||
119 | int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) | 119 | int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) |
120 | { | 120 | { |
121 | int status = 0; | 121 | int status = 0; |
122 | uint64_t flag; | 122 | u64 flag; |
123 | 123 | ||
124 | flag = pcibr_lock(pcibus_info); | 124 | flag = pcibr_lock(pcibus_info); |
125 | status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count); | 125 | status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count); |
@@ -139,7 +139,7 @@ int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) | |||
139 | * Setup an Address Translation Entry as specified. Use either the Bridge | 139 | * Setup an Address Translation Entry as specified. Use either the Bridge |
140 | * internal maps or the external map RAM, as appropriate. | 140 | * internal maps or the external map RAM, as appropriate. |
141 | */ | 141 | */ |
142 | static inline uint64_t *pcibr_ate_addr(struct pcibus_info *pcibus_info, | 142 | static inline u64 *pcibr_ate_addr(struct pcibus_info *pcibus_info, |
143 | int ate_index) | 143 | int ate_index) |
144 | { | 144 | { |
145 | if (ate_index < pcibus_info->pbi_int_ate_size) { | 145 | if (ate_index < pcibus_info->pbi_int_ate_size) { |
@@ -153,7 +153,7 @@ static inline uint64_t *pcibr_ate_addr(struct pcibus_info *pcibus_info, | |||
153 | */ | 153 | */ |
154 | void inline | 154 | void inline |
155 | ate_write(struct pcibus_info *pcibus_info, int ate_index, int count, | 155 | ate_write(struct pcibus_info *pcibus_info, int ate_index, int count, |
156 | volatile uint64_t ate) | 156 | volatile u64 ate) |
157 | { | 157 | { |
158 | while (count-- > 0) { | 158 | while (count-- > 0) { |
159 | if (ate_index < pcibus_info->pbi_int_ate_size) { | 159 | if (ate_index < pcibus_info->pbi_int_ate_size) { |
@@ -171,9 +171,9 @@ ate_write(struct pcibus_info *pcibus_info, int ate_index, int count, | |||
171 | void pcibr_ate_free(struct pcibus_info *pcibus_info, int index) | 171 | void pcibr_ate_free(struct pcibus_info *pcibus_info, int index) |
172 | { | 172 | { |
173 | 173 | ||
174 | volatile uint64_t ate; | 174 | volatile u64 ate; |
175 | int count; | 175 | int count; |
176 | uint64_t flags; | 176 | u64 flags; |
177 | 177 | ||
178 | if (pcibr_invalidate_ate) { | 178 | if (pcibr_invalidate_ate) { |
179 | /* For debugging purposes, clear the valid bit in the ATE */ | 179 | /* For debugging purposes, clear the valid bit in the ATE */ |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index 34093476e9..54ce5b7cee 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c | |||
@@ -41,21 +41,21 @@ extern int sn_ioif_inited; | |||
41 | 41 | ||
42 | static dma_addr_t | 42 | static dma_addr_t |
43 | pcibr_dmamap_ate32(struct pcidev_info *info, | 43 | pcibr_dmamap_ate32(struct pcidev_info *info, |
44 | uint64_t paddr, size_t req_size, uint64_t flags) | 44 | u64 paddr, size_t req_size, u64 flags) |
45 | { | 45 | { |
46 | 46 | ||
47 | struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; | 47 | struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; |
48 | struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> | 48 | struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> |
49 | pdi_pcibus_info; | 49 | pdi_pcibus_info; |
50 | uint8_t internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info-> | 50 | u8 internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info-> |
51 | pdi_linux_pcidev->devfn)) - 1; | 51 | pdi_linux_pcidev->devfn)) - 1; |
52 | int ate_count; | 52 | int ate_count; |
53 | int ate_index; | 53 | int ate_index; |
54 | uint64_t ate_flags = flags | PCI32_ATE_V; | 54 | u64 ate_flags = flags | PCI32_ATE_V; |
55 | uint64_t ate; | 55 | u64 ate; |
56 | uint64_t pci_addr; | 56 | u64 pci_addr; |
57 | uint64_t xio_addr; | 57 | u64 xio_addr; |
58 | uint64_t offset; | 58 | u64 offset; |
59 | 59 | ||
60 | /* PIC in PCI-X mode does not supports 32bit PageMap mode */ | 60 | /* PIC in PCI-X mode does not supports 32bit PageMap mode */ |
61 | if (IS_PIC_SOFT(pcibus_info) && IS_PCIX(pcibus_info)) { | 61 | if (IS_PIC_SOFT(pcibus_info) && IS_PCIX(pcibus_info)) { |
@@ -109,12 +109,12 @@ pcibr_dmamap_ate32(struct pcidev_info *info, | |||
109 | } | 109 | } |
110 | 110 | ||
111 | static dma_addr_t | 111 | static dma_addr_t |
112 | pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, | 112 | pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, |
113 | uint64_t dma_attributes) | 113 | u64 dma_attributes) |
114 | { | 114 | { |
115 | struct pcibus_info *pcibus_info = (struct pcibus_info *) | 115 | struct pcibus_info *pcibus_info = (struct pcibus_info *) |
116 | ((info->pdi_host_pcidev_info)->pdi_pcibus_info); | 116 | ((info->pdi_host_pcidev_info)->pdi_pcibus_info); |
117 | uint64_t pci_addr; | 117 | u64 pci_addr; |
118 | 118 | ||
119 | /* Translate to Crosstalk View of Physical Address */ | 119 | /* Translate to Crosstalk View of Physical Address */ |
120 | pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : | 120 | pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : |
@@ -127,7 +127,7 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, | |||
127 | /* Handle Bridge Chipset differences */ | 127 | /* Handle Bridge Chipset differences */ |
128 | if (IS_PIC_SOFT(pcibus_info)) { | 128 | if (IS_PIC_SOFT(pcibus_info)) { |
129 | pci_addr |= | 129 | pci_addr |= |
130 | ((uint64_t) pcibus_info-> | 130 | ((u64) pcibus_info-> |
131 | pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT); | 131 | pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT); |
132 | } else | 132 | } else |
133 | pci_addr |= TIOCP_PCI64_CMDTYPE_MEM; | 133 | pci_addr |= TIOCP_PCI64_CMDTYPE_MEM; |
@@ -142,17 +142,17 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, | |||
142 | 142 | ||
143 | static dma_addr_t | 143 | static dma_addr_t |
144 | pcibr_dmatrans_direct32(struct pcidev_info * info, | 144 | pcibr_dmatrans_direct32(struct pcidev_info * info, |
145 | uint64_t paddr, size_t req_size, uint64_t flags) | 145 | u64 paddr, size_t req_size, u64 flags) |
146 | { | 146 | { |
147 | 147 | ||
148 | struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; | 148 | struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; |
149 | struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> | 149 | struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> |
150 | pdi_pcibus_info; | 150 | pdi_pcibus_info; |
151 | uint64_t xio_addr; | 151 | u64 xio_addr; |
152 | 152 | ||
153 | uint64_t xio_base; | 153 | u64 xio_base; |
154 | uint64_t offset; | 154 | u64 offset; |
155 | uint64_t endoff; | 155 | u64 endoff; |
156 | 156 | ||
157 | if (IS_PCIX(pcibus_info)) { | 157 | if (IS_PCIX(pcibus_info)) { |
158 | return 0; | 158 | return 0; |
@@ -209,16 +209,18 @@ pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle, int direction) | |||
209 | * unlike the PIC Device(x) Write Request Buffer Flush register. | 209 | * unlike the PIC Device(x) Write Request Buffer Flush register. |
210 | */ | 210 | */ |
211 | 211 | ||
212 | void sn_dma_flush(uint64_t addr) | 212 | void sn_dma_flush(u64 addr) |
213 | { | 213 | { |
214 | nasid_t nasid; | 214 | nasid_t nasid; |
215 | int is_tio; | 215 | int is_tio; |
216 | int wid_num; | 216 | int wid_num; |
217 | int i, j; | 217 | int i, j; |
218 | uint64_t flags; | 218 | u64 flags; |
219 | uint64_t itte; | 219 | u64 itte; |
220 | struct hubdev_info *hubinfo; | 220 | struct hubdev_info *hubinfo; |
221 | volatile struct sn_flush_device_list *p; | 221 | volatile struct sn_flush_device_kernel *p; |
222 | volatile struct sn_flush_device_common *common; | ||
223 | |||
222 | struct sn_flush_nasid_entry *flush_nasid_list; | 224 | struct sn_flush_nasid_entry *flush_nasid_list; |
223 | 225 | ||
224 | if (!sn_ioif_inited) | 226 | if (!sn_ioif_inited) |
@@ -268,17 +270,17 @@ void sn_dma_flush(uint64_t addr) | |||
268 | p = &flush_nasid_list->widget_p[wid_num][0]; | 270 | p = &flush_nasid_list->widget_p[wid_num][0]; |
269 | 271 | ||
270 | /* find a matching BAR */ | 272 | /* find a matching BAR */ |
271 | for (i = 0; i < DEV_PER_WIDGET; i++) { | 273 | for (i = 0; i < DEV_PER_WIDGET; i++,p++) { |
274 | common = p->common; | ||
272 | for (j = 0; j < PCI_ROM_RESOURCE; j++) { | 275 | for (j = 0; j < PCI_ROM_RESOURCE; j++) { |
273 | if (p->sfdl_bar_list[j].start == 0) | 276 | if (common->sfdl_bar_list[j].start == 0) |
274 | break; | 277 | break; |
275 | if (addr >= p->sfdl_bar_list[j].start | 278 | if (addr >= common->sfdl_bar_list[j].start |
276 | && addr <= p->sfdl_bar_list[j].end) | 279 | && addr <= common->sfdl_bar_list[j].end) |
277 | break; | 280 | break; |
278 | } | 281 | } |
279 | if (j < PCI_ROM_RESOURCE && p->sfdl_bar_list[j].start != 0) | 282 | if (j < PCI_ROM_RESOURCE && common->sfdl_bar_list[j].start != 0) |
280 | break; | 283 | break; |
281 | p++; | ||
282 | } | 284 | } |
283 | 285 | ||
284 | /* if no matching BAR, return without doing anything. */ | 286 | /* if no matching BAR, return without doing anything. */ |
@@ -297,31 +299,31 @@ void sn_dma_flush(uint64_t addr) | |||
297 | * If CE ever needs the sn_dma_flush mechanism, we will have | 299 | * If CE ever needs the sn_dma_flush mechanism, we will have |
298 | * to account for that here and in tioce_bus_fixup(). | 300 | * to account for that here and in tioce_bus_fixup(). |
299 | */ | 301 | */ |
300 | uint32_t tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID)); | 302 | u32 tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID)); |
301 | uint32_t revnum = XWIDGET_PART_REV_NUM(tio_id); | 303 | u32 revnum = XWIDGET_PART_REV_NUM(tio_id); |
302 | 304 | ||
303 | /* TIOCP BRINGUP WAR (PV907516): Don't write buffer flush reg */ | 305 | /* TIOCP BRINGUP WAR (PV907516): Don't write buffer flush reg */ |
304 | if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) { | 306 | if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) { |
305 | return; | 307 | return; |
306 | } else { | 308 | } else { |
307 | pcireg_wrb_flush_get(p->sfdl_pcibus_info, | 309 | pcireg_wrb_flush_get(common->sfdl_pcibus_info, |
308 | (p->sfdl_slot - 1)); | 310 | (common->sfdl_slot - 1)); |
309 | } | 311 | } |
310 | } else { | 312 | } else { |
311 | spin_lock_irqsave(&((struct sn_flush_device_list *)p)-> | 313 | spin_lock_irqsave((spinlock_t *)&p->sfdl_flush_lock, |
312 | sfdl_flush_lock, flags); | 314 | flags); |
313 | 315 | *common->sfdl_flush_addr = 0; | |
314 | *p->sfdl_flush_addr = 0; | ||
315 | 316 | ||
316 | /* force an interrupt. */ | 317 | /* force an interrupt. */ |
317 | *(volatile uint32_t *)(p->sfdl_force_int_addr) = 1; | 318 | *(volatile u32 *)(common->sfdl_force_int_addr) = 1; |
318 | 319 | ||
319 | /* wait for the interrupt to come back. */ | 320 | /* wait for the interrupt to come back. */ |
320 | while (*(p->sfdl_flush_addr) != 0x10f) | 321 | while (*(common->sfdl_flush_addr) != 0x10f) |
321 | cpu_relax(); | 322 | cpu_relax(); |
322 | 323 | ||
323 | /* okay, everything is synched up. */ | 324 | /* okay, everything is synched up. */ |
324 | spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, flags); | 325 | spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, |
326 | flags); | ||
325 | } | 327 | } |
326 | return; | 328 | return; |
327 | } | 329 | } |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 1f500c8100..2fac27049b 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c | |||
@@ -23,14 +23,16 @@ int | |||
23 | sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp) | 23 | sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp) |
24 | { | 24 | { |
25 | struct ia64_sal_retval ret_stuff; | 25 | struct ia64_sal_retval ret_stuff; |
26 | uint64_t busnum; | 26 | u64 busnum; |
27 | u64 segment; | ||
27 | 28 | ||
28 | ret_stuff.status = 0; | 29 | ret_stuff.status = 0; |
29 | ret_stuff.v0 = 0; | 30 | ret_stuff.v0 = 0; |
30 | 31 | ||
32 | segment = soft->pbi_buscommon.bs_persist_segment; | ||
31 | busnum = soft->pbi_buscommon.bs_persist_busnum; | 33 | busnum = soft->pbi_buscommon.bs_persist_busnum; |
32 | SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, (u64) busnum, | 34 | SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, segment, |
33 | (u64) device, (u64) resp, 0, 0, 0, 0); | 35 | busnum, (u64) device, (u64) resp, 0, 0, 0); |
34 | 36 | ||
35 | return (int)ret_stuff.v0; | 37 | return (int)ret_stuff.v0; |
36 | } | 38 | } |
@@ -40,15 +42,17 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action, | |||
40 | void *resp) | 42 | void *resp) |
41 | { | 43 | { |
42 | struct ia64_sal_retval ret_stuff; | 44 | struct ia64_sal_retval ret_stuff; |
43 | uint64_t busnum; | 45 | u64 busnum; |
46 | u64 segment; | ||
44 | 47 | ||
45 | ret_stuff.status = 0; | 48 | ret_stuff.status = 0; |
46 | ret_stuff.v0 = 0; | 49 | ret_stuff.v0 = 0; |
47 | 50 | ||
51 | segment = soft->pbi_buscommon.bs_persist_segment; | ||
48 | busnum = soft->pbi_buscommon.bs_persist_busnum; | 52 | busnum = soft->pbi_buscommon.bs_persist_busnum; |
49 | SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_DISABLE, | 53 | SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_DISABLE, |
50 | (u64) busnum, (u64) device, (u64) action, | 54 | segment, busnum, (u64) device, (u64) action, |
51 | (u64) resp, 0, 0, 0); | 55 | (u64) resp, 0, 0); |
52 | 56 | ||
53 | return (int)ret_stuff.v0; | 57 | return (int)ret_stuff.v0; |
54 | } | 58 | } |
@@ -56,7 +60,7 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action, | |||
56 | static int sal_pcibr_error_interrupt(struct pcibus_info *soft) | 60 | static int sal_pcibr_error_interrupt(struct pcibus_info *soft) |
57 | { | 61 | { |
58 | struct ia64_sal_retval ret_stuff; | 62 | struct ia64_sal_retval ret_stuff; |
59 | uint64_t busnum; | 63 | u64 busnum; |
60 | int segment; | 64 | int segment; |
61 | ret_stuff.status = 0; | 65 | ret_stuff.status = 0; |
62 | ret_stuff.v0 = 0; | 66 | ret_stuff.v0 = 0; |
@@ -92,7 +96,8 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont | |||
92 | cnodeid_t near_cnode; | 96 | cnodeid_t near_cnode; |
93 | struct hubdev_info *hubdev_info; | 97 | struct hubdev_info *hubdev_info; |
94 | struct pcibus_info *soft; | 98 | struct pcibus_info *soft; |
95 | struct sn_flush_device_list *sn_flush_device_list; | 99 | struct sn_flush_device_kernel *sn_flush_device_kernel; |
100 | struct sn_flush_device_common *common; | ||
96 | 101 | ||
97 | if (! IS_PCI_BRIDGE_ASIC(prom_bussoft->bs_asic_type)) { | 102 | if (! IS_PCI_BRIDGE_ASIC(prom_bussoft->bs_asic_type)) { |
98 | return NULL; | 103 | return NULL; |
@@ -137,20 +142,19 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont | |||
137 | hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); | 142 | hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); |
138 | 143 | ||
139 | if (hubdev_info->hdi_flush_nasid_list.widget_p) { | 144 | if (hubdev_info->hdi_flush_nasid_list.widget_p) { |
140 | sn_flush_device_list = hubdev_info->hdi_flush_nasid_list. | 145 | sn_flush_device_kernel = hubdev_info->hdi_flush_nasid_list. |
141 | widget_p[(int)soft->pbi_buscommon.bs_xid]; | 146 | widget_p[(int)soft->pbi_buscommon.bs_xid]; |
142 | if (sn_flush_device_list) { | 147 | if (sn_flush_device_kernel) { |
143 | for (j = 0; j < DEV_PER_WIDGET; | 148 | for (j = 0; j < DEV_PER_WIDGET; |
144 | j++, sn_flush_device_list++) { | 149 | j++, sn_flush_device_kernel++) { |
145 | if (sn_flush_device_list->sfdl_slot == -1) | 150 | common = sn_flush_device_kernel->common; |
151 | if (common->sfdl_slot == -1) | ||
146 | continue; | 152 | continue; |
147 | if ((sn_flush_device_list-> | 153 | if ((common->sfdl_persistent_segment == |
148 | sfdl_persistent_segment == | ||
149 | soft->pbi_buscommon.bs_persist_segment) && | 154 | soft->pbi_buscommon.bs_persist_segment) && |
150 | (sn_flush_device_list-> | 155 | (common->sfdl_persistent_busnum == |
151 | sfdl_persistent_busnum == | ||
152 | soft->pbi_buscommon.bs_persist_busnum)) | 156 | soft->pbi_buscommon.bs_persist_busnum)) |
153 | sn_flush_device_list->sfdl_pcibus_info = | 157 | common->sfdl_pcibus_info = |
154 | soft; | 158 | soft; |
155 | } | 159 | } |
156 | } | 160 | } |
@@ -159,9 +163,9 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont | |||
159 | /* Setup the PMU ATE map */ | 163 | /* Setup the PMU ATE map */ |
160 | soft->pbi_int_ate_resource.lowest_free_index = 0; | 164 | soft->pbi_int_ate_resource.lowest_free_index = 0; |
161 | soft->pbi_int_ate_resource.ate = | 165 | soft->pbi_int_ate_resource.ate = |
162 | kmalloc(soft->pbi_int_ate_size * sizeof(uint64_t), GFP_KERNEL); | 166 | kmalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL); |
163 | memset(soft->pbi_int_ate_resource.ate, 0, | 167 | memset(soft->pbi_int_ate_resource.ate, 0, |
164 | (soft->pbi_int_ate_size * sizeof(uint64_t))); | 168 | (soft->pbi_int_ate_size * sizeof(u64))); |
165 | 169 | ||
166 | if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) { | 170 | if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) { |
167 | /* TIO PCI Bridge: find nearest node with CPUs */ | 171 | /* TIO PCI Bridge: find nearest node with CPUs */ |
@@ -203,7 +207,7 @@ void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info) | |||
203 | struct pcidev_info *pcidev_info; | 207 | struct pcidev_info *pcidev_info; |
204 | struct pcibus_info *pcibus_info; | 208 | struct pcibus_info *pcibus_info; |
205 | int bit = sn_irq_info->irq_int_bit; | 209 | int bit = sn_irq_info->irq_int_bit; |
206 | uint64_t xtalk_addr = sn_irq_info->irq_xtalkaddr; | 210 | u64 xtalk_addr = sn_irq_info->irq_xtalkaddr; |
207 | 211 | ||
208 | pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; | 212 | pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; |
209 | if (pcidev_info) { | 213 | if (pcidev_info) { |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_reg.c b/arch/ia64/sn/pci/pcibr/pcibr_reg.c index 5d53409126..8b8bbd51d4 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_reg.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_reg.c | |||
@@ -23,9 +23,9 @@ union br_ptr { | |||
23 | /* | 23 | /* |
24 | * Control Register Access -- Read/Write 0000_0020 | 24 | * Control Register Access -- Read/Write 0000_0020 |
25 | */ | 25 | */ |
26 | void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) | 26 | void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, u64 bits) |
27 | { | 27 | { |
28 | union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; | 28 | union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; |
29 | 29 | ||
30 | if (pcibus_info) { | 30 | if (pcibus_info) { |
31 | switch (pcibus_info->pbi_bridge_type) { | 31 | switch (pcibus_info->pbi_bridge_type) { |
@@ -38,14 +38,14 @@ void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) | |||
38 | default: | 38 | default: |
39 | panic | 39 | panic |
40 | ("pcireg_control_bit_clr: unknown bridgetype bridge 0x%p", | 40 | ("pcireg_control_bit_clr: unknown bridgetype bridge 0x%p", |
41 | (void *)ptr); | 41 | ptr); |
42 | } | 42 | } |
43 | } | 43 | } |
44 | } | 44 | } |
45 | 45 | ||
46 | void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) | 46 | void pcireg_control_bit_set(struct pcibus_info *pcibus_info, u64 bits) |
47 | { | 47 | { |
48 | union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; | 48 | union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; |
49 | 49 | ||
50 | if (pcibus_info) { | 50 | if (pcibus_info) { |
51 | switch (pcibus_info->pbi_bridge_type) { | 51 | switch (pcibus_info->pbi_bridge_type) { |
@@ -58,7 +58,7 @@ void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) | |||
58 | default: | 58 | default: |
59 | panic | 59 | panic |
60 | ("pcireg_control_bit_set: unknown bridgetype bridge 0x%p", | 60 | ("pcireg_control_bit_set: unknown bridgetype bridge 0x%p", |
61 | (void *)ptr); | 61 | ptr); |
62 | } | 62 | } |
63 | } | 63 | } |
64 | } | 64 | } |
@@ -66,10 +66,10 @@ void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) | |||
66 | /* | 66 | /* |
67 | * PCI/PCIX Target Flush Register Access -- Read Only 0000_0050 | 67 | * PCI/PCIX Target Flush Register Access -- Read Only 0000_0050 |
68 | */ | 68 | */ |
69 | uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info) | 69 | u64 pcireg_tflush_get(struct pcibus_info *pcibus_info) |
70 | { | 70 | { |
71 | union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; | 71 | union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; |
72 | uint64_t ret = 0; | 72 | u64 ret = 0; |
73 | 73 | ||
74 | if (pcibus_info) { | 74 | if (pcibus_info) { |
75 | switch (pcibus_info->pbi_bridge_type) { | 75 | switch (pcibus_info->pbi_bridge_type) { |
@@ -82,7 +82,7 @@ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info) | |||
82 | default: | 82 | default: |
83 | panic | 83 | panic |
84 | ("pcireg_tflush_get: unknown bridgetype bridge 0x%p", | 84 | ("pcireg_tflush_get: unknown bridgetype bridge 0x%p", |
85 | (void *)ptr); | 85 | ptr); |
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
@@ -96,10 +96,10 @@ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info) | |||
96 | /* | 96 | /* |
97 | * Interrupt Status Register Access -- Read Only 0000_0100 | 97 | * Interrupt Status Register Access -- Read Only 0000_0100 |
98 | */ | 98 | */ |
99 | uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info) | 99 | u64 pcireg_intr_status_get(struct pcibus_info * pcibus_info) |
100 | { | 100 | { |
101 | union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; | 101 | union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; |
102 | uint64_t ret = 0; | 102 | u64 ret = 0; |
103 | 103 | ||
104 | if (pcibus_info) { | 104 | if (pcibus_info) { |
105 | switch (pcibus_info->pbi_bridge_type) { | 105 | switch (pcibus_info->pbi_bridge_type) { |
@@ -112,7 +112,7 @@ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info) | |||
112 | default: | 112 | default: |
113 | panic | 113 | panic |
114 | ("pcireg_intr_status_get: unknown bridgetype bridge 0x%p", | 114 | ("pcireg_intr_status_get: unknown bridgetype bridge 0x%p", |
115 | (void *)ptr); | 115 | ptr); |
116 | } | 116 | } |
117 | } | 117 | } |
118 | return ret; | 118 | return ret; |
@@ -121,9 +121,9 @@ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info) | |||
121 | /* | 121 | /* |
122 | * Interrupt Enable Register Access -- Read/Write 0000_0108 | 122 | * Interrupt Enable Register Access -- Read/Write 0000_0108 |
123 | */ | 123 | */ |
124 | void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) | 124 | void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, u64 bits) |
125 | { | 125 | { |
126 | union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; | 126 | union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; |
127 | 127 | ||
128 | if (pcibus_info) { | 128 | if (pcibus_info) { |
129 | switch (pcibus_info->pbi_bridge_type) { | 129 | switch (pcibus_info->pbi_bridge_type) { |
@@ -136,14 +136,14 @@ void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) | |||
136 | default: | 136 | default: |
137 | panic | 137 | panic |
138 | ("pcireg_intr_enable_bit_clr: unknown bridgetype bridge 0x%p", | 138 | ("pcireg_intr_enable_bit_clr: unknown bridgetype bridge 0x%p", |
139 | (void *)ptr); | 139 | ptr); |
140 | } | 140 | } |
141 | } | 141 | } |
142 | } | 142 | } |
143 | 143 | ||
144 | void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) | 144 | void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, u64 bits) |
145 | { | 145 | { |
146 | union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; | 146 | union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; |
147 | 147 | ||
148 | if (pcibus_info) { | 148 | if (pcibus_info) { |
149 | switch (pcibus_info->pbi_bridge_type) { | 149 | switch (pcibus_info->pbi_bridge_type) { |
@@ -156,7 +156,7 @@ void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) | |||
156 | default: | 156 | default: |
157 | panic | 157 | panic |
158 | ("pcireg_intr_enable_bit_set: unknown bridgetype bridge 0x%p", | 158 | ("pcireg_intr_enable_bit_set: unknown bridgetype bridge 0x%p", |
159 | (void *)ptr); | 159 | ptr); |
160 | } | 160 | } |
161 | } | 161 | } |
162 | } | 162 | } |
@@ -165,9 +165,9 @@ void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) | |||
165 | * Intr Host Address Register (int_addr) -- Read/Write 0000_0130 - 0000_0168 | 165 | * Intr Host Address Register (int_addr) -- Read/Write 0000_0130 - 0000_0168 |
166 | */ | 166 | */ |
167 | void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n, | 167 | void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n, |
168 | uint64_t addr) | 168 | u64 addr) |
169 | { | 169 | { |
170 | union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; | 170 | union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; |
171 | 171 | ||
172 | if (pcibus_info) { | 172 | if (pcibus_info) { |
173 | switch (pcibus_info->pbi_bridge_type) { | 173 | switch (pcibus_info->pbi_bridge_type) { |
@@ -186,7 +186,7 @@ void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n, | |||
186 | default: | 186 | default: |
187 | panic | 187 | panic |
188 | ("pcireg_intr_addr_addr_get: unknown bridgetype bridge 0x%p", | 188 | ("pcireg_intr_addr_addr_get: unknown bridgetype bridge 0x%p", |
189 | (void *)ptr); | 189 | ptr); |
190 | } | 190 | } |
191 | } | 191 | } |
192 | } | 192 | } |
@@ -196,7 +196,7 @@ void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n, | |||
196 | */ | 196 | */ |
197 | void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n) | 197 | void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n) |
198 | { | 198 | { |
199 | union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; | 199 | union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; |
200 | 200 | ||
201 | if (pcibus_info) { | 201 | if (pcibus_info) { |
202 | switch (pcibus_info->pbi_bridge_type) { | 202 | switch (pcibus_info->pbi_bridge_type) { |
@@ -209,7 +209,7 @@ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n) | |||
209 | default: | 209 | default: |
210 | panic | 210 | panic |
211 | ("pcireg_force_intr_set: unknown bridgetype bridge 0x%p", | 211 | ("pcireg_force_intr_set: unknown bridgetype bridge 0x%p", |
212 | (void *)ptr); | 212 | ptr); |
213 | } | 213 | } |
214 | } | 214 | } |
215 | } | 215 | } |
@@ -217,10 +217,10 @@ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n) | |||
217 | /* | 217 | /* |
218 | * Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258 | 218 | * Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258 |
219 | */ | 219 | */ |
220 | uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) | 220 | u64 pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) |
221 | { | 221 | { |
222 | union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; | 222 | union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; |
223 | uint64_t ret = 0; | 223 | u64 ret = 0; |
224 | 224 | ||
225 | if (pcibus_info) { | 225 | if (pcibus_info) { |
226 | switch (pcibus_info->pbi_bridge_type) { | 226 | switch (pcibus_info->pbi_bridge_type) { |
@@ -233,7 +233,7 @@ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) | |||
233 | __sn_readq_relaxed(&ptr->pic.p_wr_req_buf[device]); | 233 | __sn_readq_relaxed(&ptr->pic.p_wr_req_buf[device]); |
234 | break; | 234 | break; |
235 | default: | 235 | default: |
236 | panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", (void *)ptr); | 236 | panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", ptr); |
237 | } | 237 | } |
238 | 238 | ||
239 | } | 239 | } |
@@ -242,9 +242,9 @@ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) | |||
242 | } | 242 | } |
243 | 243 | ||
244 | void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index, | 244 | void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index, |
245 | uint64_t val) | 245 | u64 val) |
246 | { | 246 | { |
247 | union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; | 247 | union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; |
248 | 248 | ||
249 | if (pcibus_info) { | 249 | if (pcibus_info) { |
250 | switch (pcibus_info->pbi_bridge_type) { | 250 | switch (pcibus_info->pbi_bridge_type) { |
@@ -257,15 +257,15 @@ void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index, | |||
257 | default: | 257 | default: |
258 | panic | 258 | panic |
259 | ("pcireg_int_ate_set: unknown bridgetype bridge 0x%p", | 259 | ("pcireg_int_ate_set: unknown bridgetype bridge 0x%p", |
260 | (void *)ptr); | 260 | ptr); |
261 | } | 261 | } |
262 | } | 262 | } |
263 | } | 263 | } |
264 | 264 | ||
265 | uint64_t *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) | 265 | u64 __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) |
266 | { | 266 | { |
267 | union br_ptr *ptr = (union br_ptr *)pcibus_info->pbi_buscommon.bs_base; | 267 | union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; |
268 | uint64_t *ret = (uint64_t *) 0; | 268 | u64 __iomem *ret = NULL; |
269 | 269 | ||
270 | if (pcibus_info) { | 270 | if (pcibus_info) { |
271 | switch (pcibus_info->pbi_bridge_type) { | 271 | switch (pcibus_info->pbi_bridge_type) { |
@@ -278,7 +278,7 @@ uint64_t *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) | |||
278 | default: | 278 | default: |
279 | panic | 279 | panic |
280 | ("pcireg_int_ate_addr: unknown bridgetype bridge 0x%p", | 280 | ("pcireg_int_ate_addr: unknown bridgetype bridge 0x%p", |
281 | (void *)ptr); | 281 | ptr); |
282 | } | 282 | } |
283 | } | 283 | } |
284 | return ret; | 284 | return ret; |
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 46b646a6d3..7571a40255 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <asm/sn/pcibus_provider_defs.h> | 16 | #include <asm/sn/pcibus_provider_defs.h> |
17 | #include <asm/sn/tioca_provider.h> | 17 | #include <asm/sn/tioca_provider.h> |
18 | 18 | ||
19 | uint32_t tioca_gart_found; | 19 | u32 tioca_gart_found; |
20 | EXPORT_SYMBOL(tioca_gart_found); /* used by agp-sgi */ | 20 | EXPORT_SYMBOL(tioca_gart_found); /* used by agp-sgi */ |
21 | 21 | ||
22 | LIST_HEAD(tioca_list); | 22 | LIST_HEAD(tioca_list); |
@@ -34,14 +34,14 @@ static int tioca_gart_init(struct tioca_kernel *); | |||
34 | static int | 34 | static int |
35 | tioca_gart_init(struct tioca_kernel *tioca_kern) | 35 | tioca_gart_init(struct tioca_kernel *tioca_kern) |
36 | { | 36 | { |
37 | uint64_t ap_reg; | 37 | u64 ap_reg; |
38 | uint64_t offset; | 38 | u64 offset; |
39 | struct page *tmp; | 39 | struct page *tmp; |
40 | struct tioca_common *tioca_common; | 40 | struct tioca_common *tioca_common; |
41 | struct tioca *ca_base; | 41 | struct tioca __iomem *ca_base; |
42 | 42 | ||
43 | tioca_common = tioca_kern->ca_common; | 43 | tioca_common = tioca_kern->ca_common; |
44 | ca_base = (struct tioca *)tioca_common->ca_common.bs_base; | 44 | ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base; |
45 | 45 | ||
46 | if (list_empty(tioca_kern->ca_devices)) | 46 | if (list_empty(tioca_kern->ca_devices)) |
47 | return 0; | 47 | return 0; |
@@ -214,8 +214,8 @@ void | |||
214 | tioca_fastwrite_enable(struct tioca_kernel *tioca_kern) | 214 | tioca_fastwrite_enable(struct tioca_kernel *tioca_kern) |
215 | { | 215 | { |
216 | int cap_ptr; | 216 | int cap_ptr; |
217 | uint32_t reg; | 217 | u32 reg; |
218 | struct tioca *tioca_base; | 218 | struct tioca __iomem *tioca_base; |
219 | struct pci_dev *pdev; | 219 | struct pci_dev *pdev; |
220 | struct tioca_common *common; | 220 | struct tioca_common *common; |
221 | 221 | ||
@@ -257,7 +257,7 @@ tioca_fastwrite_enable(struct tioca_kernel *tioca_kern) | |||
257 | * Set ca's fw to match | 257 | * Set ca's fw to match |
258 | */ | 258 | */ |
259 | 259 | ||
260 | tioca_base = (struct tioca *)common->ca_common.bs_base; | 260 | tioca_base = (struct tioca __iomem*)common->ca_common.bs_base; |
261 | __sn_setq_relaxed(&tioca_base->ca_control1, CA_AGP_FW_ENABLE); | 261 | __sn_setq_relaxed(&tioca_base->ca_control1, CA_AGP_FW_ENABLE); |
262 | } | 262 | } |
263 | 263 | ||
@@ -276,7 +276,7 @@ EXPORT_SYMBOL(tioca_fastwrite_enable); /* used by agp-sgi */ | |||
276 | * We will always use 0x1 | 276 | * We will always use 0x1 |
277 | * 55:55 - Swap bytes Currently unused | 277 | * 55:55 - Swap bytes Currently unused |
278 | */ | 278 | */ |
279 | static uint64_t | 279 | static u64 |
280 | tioca_dma_d64(unsigned long paddr) | 280 | tioca_dma_d64(unsigned long paddr) |
281 | { | 281 | { |
282 | dma_addr_t bus_addr; | 282 | dma_addr_t bus_addr; |
@@ -318,19 +318,19 @@ tioca_dma_d64(unsigned long paddr) | |||
318 | * and so a given CA can only directly target nodes in the range | 318 | * and so a given CA can only directly target nodes in the range |
319 | * xxx - xxx+255. | 319 | * xxx - xxx+255. |
320 | */ | 320 | */ |
321 | static uint64_t | 321 | static u64 |
322 | tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr) | 322 | tioca_dma_d48(struct pci_dev *pdev, u64 paddr) |
323 | { | 323 | { |
324 | struct tioca_common *tioca_common; | 324 | struct tioca_common *tioca_common; |
325 | struct tioca *ca_base; | 325 | struct tioca __iomem *ca_base; |
326 | uint64_t ct_addr; | 326 | u64 ct_addr; |
327 | dma_addr_t bus_addr; | 327 | dma_addr_t bus_addr; |
328 | uint32_t node_upper; | 328 | u32 node_upper; |
329 | uint64_t agp_dma_extn; | 329 | u64 agp_dma_extn; |
330 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev); | 330 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev); |
331 | 331 | ||
332 | tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info; | 332 | tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info; |
333 | ca_base = (struct tioca *)tioca_common->ca_common.bs_base; | 333 | ca_base = (struct tioca __iomem *)tioca_common->ca_common.bs_base; |
334 | 334 | ||
335 | ct_addr = PHYS_TO_TIODMA(paddr); | 335 | ct_addr = PHYS_TO_TIODMA(paddr); |
336 | if (!ct_addr) | 336 | if (!ct_addr) |
@@ -367,10 +367,10 @@ tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr) | |||
367 | * dma_addr_t is guarenteed to be contiguous in CA bus space. | 367 | * dma_addr_t is guarenteed to be contiguous in CA bus space. |
368 | */ | 368 | */ |
369 | static dma_addr_t | 369 | static dma_addr_t |
370 | tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size) | 370 | tioca_dma_mapped(struct pci_dev *pdev, u64 paddr, size_t req_size) |
371 | { | 371 | { |
372 | int i, ps, ps_shift, entry, entries, mapsize, last_entry; | 372 | int i, ps, ps_shift, entry, entries, mapsize, last_entry; |
373 | uint64_t xio_addr, end_xio_addr; | 373 | u64 xio_addr, end_xio_addr; |
374 | struct tioca_common *tioca_common; | 374 | struct tioca_common *tioca_common; |
375 | struct tioca_kernel *tioca_kern; | 375 | struct tioca_kernel *tioca_kern; |
376 | dma_addr_t bus_addr = 0; | 376 | dma_addr_t bus_addr = 0; |
@@ -514,10 +514,10 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) | |||
514 | * The mapping mode used is based on the devices dma_mask. As a last resort | 514 | * The mapping mode used is based on the devices dma_mask. As a last resort |
515 | * use the GART mapped mode. | 515 | * use the GART mapped mode. |
516 | */ | 516 | */ |
517 | static uint64_t | 517 | static u64 |
518 | tioca_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) | 518 | tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count) |
519 | { | 519 | { |
520 | uint64_t mapaddr; | 520 | u64 mapaddr; |
521 | 521 | ||
522 | /* | 522 | /* |
523 | * If card is 64 or 48 bit addresable, use a direct mapping. 32 | 523 | * If card is 64 or 48 bit addresable, use a direct mapping. 32 |
@@ -554,8 +554,8 @@ tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt) | |||
554 | { | 554 | { |
555 | struct tioca_common *soft = arg; | 555 | struct tioca_common *soft = arg; |
556 | struct ia64_sal_retval ret_stuff; | 556 | struct ia64_sal_retval ret_stuff; |
557 | uint64_t segment; | 557 | u64 segment; |
558 | uint64_t busnum; | 558 | u64 busnum; |
559 | ret_stuff.status = 0; | 559 | ret_stuff.status = 0; |
560 | ret_stuff.v0 = 0; | 560 | ret_stuff.v0 = 0; |
561 | 561 | ||
@@ -620,7 +620,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont | |||
620 | INIT_LIST_HEAD(&tioca_kern->ca_dmamaps); | 620 | INIT_LIST_HEAD(&tioca_kern->ca_dmamaps); |
621 | tioca_kern->ca_closest_node = | 621 | tioca_kern->ca_closest_node = |
622 | nasid_to_cnodeid(tioca_common->ca_closest_nasid); | 622 | nasid_to_cnodeid(tioca_common->ca_closest_nasid); |
623 | tioca_common->ca_kernel_private = (uint64_t) tioca_kern; | 623 | tioca_common->ca_kernel_private = (u64) tioca_kern; |
624 | 624 | ||
625 | bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment, | 625 | bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment, |
626 | tioca_common->ca_common.bs_persist_busnum); | 626 | tioca_common->ca_common.bs_persist_busnum); |
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index dda196c9e3..e52831ed93 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c | |||
@@ -81,10 +81,10 @@ | |||
81 | * 61 - 0 since this is not an MSI transaction | 81 | * 61 - 0 since this is not an MSI transaction |
82 | * 60:54 - reserved, MBZ | 82 | * 60:54 - reserved, MBZ |
83 | */ | 83 | */ |
84 | static uint64_t | 84 | static u64 |
85 | tioce_dma_d64(unsigned long ct_addr) | 85 | tioce_dma_d64(unsigned long ct_addr) |
86 | { | 86 | { |
87 | uint64_t bus_addr; | 87 | u64 bus_addr; |
88 | 88 | ||
89 | bus_addr = ct_addr | (1UL << 63); | 89 | bus_addr = ct_addr | (1UL << 63); |
90 | 90 | ||
@@ -141,9 +141,9 @@ pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base, | |||
141 | * length, and if enough resources exist, fill in the ATE's and construct a | 141 | * length, and if enough resources exist, fill in the ATE's and construct a |
142 | * tioce_dmamap struct to track the mapping. | 142 | * tioce_dmamap struct to track the mapping. |
143 | */ | 143 | */ |
144 | static uint64_t | 144 | static u64 |
145 | tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | 145 | tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, |
146 | uint64_t ct_addr, int len) | 146 | u64 ct_addr, int len) |
147 | { | 147 | { |
148 | int i; | 148 | int i; |
149 | int j; | 149 | int j; |
@@ -152,11 +152,11 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
152 | int entries; | 152 | int entries; |
153 | int nates; | 153 | int nates; |
154 | int pagesize; | 154 | int pagesize; |
155 | uint64_t *ate_shadow; | 155 | u64 *ate_shadow; |
156 | uint64_t *ate_reg; | 156 | u64 *ate_reg; |
157 | uint64_t addr; | 157 | u64 addr; |
158 | struct tioce *ce_mmr; | 158 | struct tioce *ce_mmr; |
159 | uint64_t bus_base; | 159 | u64 bus_base; |
160 | struct tioce_dmamap *map; | 160 | struct tioce_dmamap *map; |
161 | 161 | ||
162 | ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base; | 162 | ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base; |
@@ -224,7 +224,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
224 | 224 | ||
225 | addr = ct_addr; | 225 | addr = ct_addr; |
226 | for (j = 0; j < nates; j++) { | 226 | for (j = 0; j < nates; j++) { |
227 | uint64_t ate; | 227 | u64 ate; |
228 | 228 | ||
229 | ate = ATE_MAKE(addr, pagesize); | 229 | ate = ATE_MAKE(addr, pagesize); |
230 | ate_shadow[i + j] = ate; | 230 | ate_shadow[i + j] = ate; |
@@ -252,15 +252,15 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
252 | * | 252 | * |
253 | * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info. | 253 | * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info. |
254 | */ | 254 | */ |
255 | static uint64_t | 255 | static u64 |
256 | tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) | 256 | tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr) |
257 | { | 257 | { |
258 | int dma_ok; | 258 | int dma_ok; |
259 | int port; | 259 | int port; |
260 | struct tioce *ce_mmr; | 260 | struct tioce *ce_mmr; |
261 | struct tioce_kernel *ce_kern; | 261 | struct tioce_kernel *ce_kern; |
262 | uint64_t ct_upper; | 262 | u64 ct_upper; |
263 | uint64_t ct_lower; | 263 | u64 ct_lower; |
264 | dma_addr_t bus_addr; | 264 | dma_addr_t bus_addr; |
265 | 265 | ||
266 | ct_upper = ct_addr & ~0x3fffffffUL; | 266 | ct_upper = ct_addr & ~0x3fffffffUL; |
@@ -269,7 +269,7 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) | |||
269 | pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port); | 269 | pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port); |
270 | 270 | ||
271 | if (ce_kern->ce_port[port].dirmap_refcnt == 0) { | 271 | if (ce_kern->ce_port[port].dirmap_refcnt == 0) { |
272 | uint64_t tmp; | 272 | u64 tmp; |
273 | 273 | ||
274 | ce_kern->ce_port[port].dirmap_shadow = ct_upper; | 274 | ce_kern->ce_port[port].dirmap_shadow = ct_upper; |
275 | writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]); | 275 | writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]); |
@@ -295,10 +295,10 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) | |||
295 | * Given a TIOCE bus address, set the appropriate bit to indicate barrier | 295 | * Given a TIOCE bus address, set the appropriate bit to indicate barrier |
296 | * attributes. | 296 | * attributes. |
297 | */ | 297 | */ |
298 | static uint64_t | 298 | static u64 |
299 | tioce_dma_barrier(uint64_t bus_addr, int on) | 299 | tioce_dma_barrier(u64 bus_addr, int on) |
300 | { | 300 | { |
301 | uint64_t barrier_bit; | 301 | u64 barrier_bit; |
302 | 302 | ||
303 | /* barrier not supported in M40/M40S mode */ | 303 | /* barrier not supported in M40/M40S mode */ |
304 | if (TIOCE_M40_ADDR(bus_addr) || TIOCE_M40S_ADDR(bus_addr)) | 304 | if (TIOCE_M40_ADDR(bus_addr) || TIOCE_M40S_ADDR(bus_addr)) |
@@ -351,7 +351,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) | |||
351 | 351 | ||
352 | list_for_each_entry(map, &ce_kern->ce_dmamap_list, | 352 | list_for_each_entry(map, &ce_kern->ce_dmamap_list, |
353 | ce_dmamap_list) { | 353 | ce_dmamap_list) { |
354 | uint64_t last; | 354 | u64 last; |
355 | 355 | ||
356 | last = map->pci_start + map->nbytes - 1; | 356 | last = map->pci_start + map->nbytes - 1; |
357 | if (bus_addr >= map->pci_start && bus_addr <= last) | 357 | if (bus_addr >= map->pci_start && bus_addr <= last) |
@@ -385,17 +385,17 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) | |||
385 | * This is the main wrapper for mapping host physical pages to CE PCI space. | 385 | * This is the main wrapper for mapping host physical pages to CE PCI space. |
386 | * The mapping mode used is based on the device's dma_mask. | 386 | * The mapping mode used is based on the device's dma_mask. |
387 | */ | 387 | */ |
388 | static uint64_t | 388 | static u64 |
389 | tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count, | 389 | tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, |
390 | int barrier) | 390 | int barrier) |
391 | { | 391 | { |
392 | unsigned long flags; | 392 | unsigned long flags; |
393 | uint64_t ct_addr; | 393 | u64 ct_addr; |
394 | uint64_t mapaddr = 0; | 394 | u64 mapaddr = 0; |
395 | struct tioce_kernel *ce_kern; | 395 | struct tioce_kernel *ce_kern; |
396 | struct tioce_dmamap *map; | 396 | struct tioce_dmamap *map; |
397 | int port; | 397 | int port; |
398 | uint64_t dma_mask; | 398 | u64 dma_mask; |
399 | 399 | ||
400 | dma_mask = (barrier) ? pdev->dev.coherent_dma_mask : pdev->dma_mask; | 400 | dma_mask = (barrier) ? pdev->dev.coherent_dma_mask : pdev->dma_mask; |
401 | 401 | ||
@@ -425,7 +425,7 @@ tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count, | |||
425 | * address bits than this device can support. | 425 | * address bits than this device can support. |
426 | */ | 426 | */ |
427 | list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) { | 427 | list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) { |
428 | uint64_t last; | 428 | u64 last; |
429 | 429 | ||
430 | last = map->ct_start + map->nbytes - 1; | 430 | last = map->ct_start + map->nbytes - 1; |
431 | if (ct_addr >= map->ct_start && | 431 | if (ct_addr >= map->ct_start && |
@@ -501,8 +501,8 @@ dma_map_done: | |||
501 | * Simply call tioce_do_dma_map() to create a map with the barrier bit clear | 501 | * Simply call tioce_do_dma_map() to create a map with the barrier bit clear |
502 | * in the address. | 502 | * in the address. |
503 | */ | 503 | */ |
504 | static uint64_t | 504 | static u64 |
505 | tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) | 505 | tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count) |
506 | { | 506 | { |
507 | return tioce_do_dma_map(pdev, paddr, byte_count, 0); | 507 | return tioce_do_dma_map(pdev, paddr, byte_count, 0); |
508 | } | 508 | } |
@@ -515,8 +515,8 @@ tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) | |||
515 | * | 515 | * |
516 | * Simply call tioce_do_dma_map() to create a map with the barrier bit set | 516 | * Simply call tioce_do_dma_map() to create a map with the barrier bit set |
517 | * in the address. | 517 | * in the address. |
518 | */ static uint64_t | 518 | */ static u64 |
519 | tioce_dma_consistent(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) | 519 | tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count) |
520 | { | 520 | { |
521 | return tioce_do_dma_map(pdev, paddr, byte_count, 1); | 521 | return tioce_do_dma_map(pdev, paddr, byte_count, 1); |
522 | } | 522 | } |
@@ -551,7 +551,7 @@ tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt) | |||
551 | tioce_kern_init(struct tioce_common *tioce_common) | 551 | tioce_kern_init(struct tioce_common *tioce_common) |
552 | { | 552 | { |
553 | int i; | 553 | int i; |
554 | uint32_t tmp; | 554 | u32 tmp; |
555 | struct tioce *tioce_mmr; | 555 | struct tioce *tioce_mmr; |
556 | struct tioce_kernel *tioce_kern; | 556 | struct tioce_kernel *tioce_kern; |
557 | 557 | ||
@@ -563,7 +563,7 @@ tioce_kern_init(struct tioce_common *tioce_common) | |||
563 | tioce_kern->ce_common = tioce_common; | 563 | tioce_kern->ce_common = tioce_common; |
564 | spin_lock_init(&tioce_kern->ce_lock); | 564 | spin_lock_init(&tioce_kern->ce_lock); |
565 | INIT_LIST_HEAD(&tioce_kern->ce_dmamap_list); | 565 | INIT_LIST_HEAD(&tioce_kern->ce_dmamap_list); |
566 | tioce_common->ce_kernel_private = (uint64_t) tioce_kern; | 566 | tioce_common->ce_kernel_private = (u64) tioce_kern; |
567 | 567 | ||
568 | /* | 568 | /* |
569 | * Determine the secondary bus number of the port2 logical PPB. | 569 | * Determine the secondary bus number of the port2 logical PPB. |
@@ -575,7 +575,7 @@ tioce_kern_init(struct tioce_common *tioce_common) | |||
575 | raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment, | 575 | raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment, |
576 | tioce_common->ce_pcibus.bs_persist_busnum, | 576 | tioce_common->ce_pcibus.bs_persist_busnum, |
577 | PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp); | 577 | PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp); |
578 | tioce_kern->ce_port1_secondary = (uint8_t) tmp; | 578 | tioce_kern->ce_port1_secondary = (u8) tmp; |
579 | 579 | ||
580 | /* | 580 | /* |
581 | * Set PMU pagesize to the largest size available, and zero out | 581 | * Set PMU pagesize to the largest size available, and zero out |
@@ -615,7 +615,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info) | |||
615 | struct pcidev_info *pcidev_info; | 615 | struct pcidev_info *pcidev_info; |
616 | struct tioce_common *ce_common; | 616 | struct tioce_common *ce_common; |
617 | struct tioce *ce_mmr; | 617 | struct tioce *ce_mmr; |
618 | uint64_t force_int_val; | 618 | u64 force_int_val; |
619 | 619 | ||
620 | if (!sn_irq_info->irq_bridge) | 620 | if (!sn_irq_info->irq_bridge) |
621 | return; | 621 | return; |
@@ -687,7 +687,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) | |||
687 | struct tioce_common *ce_common; | 687 | struct tioce_common *ce_common; |
688 | struct tioce *ce_mmr; | 688 | struct tioce *ce_mmr; |
689 | int bit; | 689 | int bit; |
690 | uint64_t vector; | 690 | u64 vector; |
691 | 691 | ||
692 | pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; | 692 | pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; |
693 | if (!pcidev_info) | 693 | if (!pcidev_info) |
@@ -699,7 +699,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) | |||
699 | bit = sn_irq_info->irq_int_bit; | 699 | bit = sn_irq_info->irq_int_bit; |
700 | 700 | ||
701 | __sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); | 701 | __sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); |
702 | vector = (uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT; | 702 | vector = (u64)sn_irq_info->irq_irq << INTR_VECTOR_SHFT; |
703 | vector |= sn_irq_info->irq_xtalkaddr; | 703 | vector |= sn_irq_info->irq_xtalkaddr; |
704 | writeq(vector, &ce_mmr->ce_adm_int_dest[bit]); | 704 | writeq(vector, &ce_mmr->ce_adm_int_dest[bit]); |
705 | __sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); | 705 | __sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); |