FreeBSD/Linux Kernel Cross Reference
sys/mips/rmi/on_chip.c
1 /*-
2 * Copyright (c) 2003-2009 RMI Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of RMI Corporation, nor the names of its contributors,
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * RMI_BSD */
30 #include <sys/types.h>
31 #include <sys/systm.h>
32 #include <sys/param.h>
33 #include <sys/lock.h>
34 #include <sys/mutex.h>
35 #include <sys/proc.h>
36 #include <sys/limits.h>
37 #include <sys/bus.h>
38
39 #include <machine/reg.h>
40 #include <machine/cpu.h>
41 #include <machine/mips_opcode.h>
42
43 #include <machine/param.h>
44 #include <machine/intr_machdep.h>
45 #include <mips/rmi/interrupt.h>
46 #include <mips/rmi/msgring.h>
47 #include <mips/rmi/iomap.h>
48 #include <mips/rmi/debug.h>
49 #include <mips/rmi/pic.h>
50 #include <mips/rmi/board.h>
51
52 void
53 disable_msgring_int(void *arg);
54 void
55 enable_msgring_int(void *arg);
56
57 /* definitions */
58 struct tx_stn_handler {
59 void (*action) (int, int, int, int, struct msgrng_msg *, void *);
60 void *dev_id;
61 };
62
63 /* globals */
64 static struct tx_stn_handler tx_stn_handlers[MAX_TX_STNS];
65
66 #define MSGRNG_CC_INIT_CPU_DEST(dest, counter) \
67 do { \
68 msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][0], 0 ); \
69 msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][1], 1 ); \
70 msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][2], 2 ); \
71 msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][3], 3 ); \
72 msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][4], 4 ); \
73 msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][5], 5 ); \
74 msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][6], 6 ); \
75 msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][7], 7 ); \
76 } while(0)
77
78
79 /* make this a read/write spinlock */
80 static struct mtx msgrng_lock;
81 static int msgring_int_enabled;
82 struct mtx xlr_pic_lock;
83
84 static int msgring_pop_num_buckets;
85 static uint32_t msgring_pop_bucket_mask;
86 static int msgring_int_type;
87 static int msgring_watermark_count;
88 static uint32_t msgring_thread_mask;
89
90 uint32_t msgrng_msg_cycles = 0;
91
92 int xlr_counters[MAXCPU][XLR_MAX_COUNTERS] __aligned(XLR_CACHELINE_SIZE);
93
94 void xlr_msgring_handler(struct trapframe *);
95
96 void
97 xlr_msgring_cpu_init(void)
98 {
99 struct stn_cc *cc_config;
100 struct bucket_size *bucket_sizes;
101 int id;
102 unsigned long flags;
103
104 /* if not thread 0 */
105 if (xlr_thr_id() != 0)
106 return;
107 id = xlr_cpu_id();
108
109 bucket_sizes = xlr_board_info.bucket_sizes;
110 cc_config = xlr_board_info.credit_configs[id];
111
112 msgrng_flags_save(flags);
113
114 /*
115 * Message Stations are shared among all threads in a cpu core
116 * Assume, thread 0 on all cores are always active when more than 1
117 * thread is active in a core
118 */
119 msgrng_write_bucksize(0, bucket_sizes->bucket[id * 8 + 0]);
120 msgrng_write_bucksize(1, bucket_sizes->bucket[id * 8 + 1]);
121 msgrng_write_bucksize(2, bucket_sizes->bucket[id * 8 + 2]);
122 msgrng_write_bucksize(3, bucket_sizes->bucket[id * 8 + 3]);
123 msgrng_write_bucksize(4, bucket_sizes->bucket[id * 8 + 4]);
124 msgrng_write_bucksize(5, bucket_sizes->bucket[id * 8 + 5]);
125 msgrng_write_bucksize(6, bucket_sizes->bucket[id * 8 + 6]);
126 msgrng_write_bucksize(7, bucket_sizes->bucket[id * 8 + 7]);
127
128 MSGRNG_CC_INIT_CPU_DEST(0, cc_config->counters);
129 MSGRNG_CC_INIT_CPU_DEST(1, cc_config->counters);
130 MSGRNG_CC_INIT_CPU_DEST(2, cc_config->counters);
131 MSGRNG_CC_INIT_CPU_DEST(3, cc_config->counters);
132 MSGRNG_CC_INIT_CPU_DEST(4, cc_config->counters);
133 MSGRNG_CC_INIT_CPU_DEST(5, cc_config->counters);
134 MSGRNG_CC_INIT_CPU_DEST(6, cc_config->counters);
135 MSGRNG_CC_INIT_CPU_DEST(7, cc_config->counters);
136 MSGRNG_CC_INIT_CPU_DEST(8, cc_config->counters);
137 MSGRNG_CC_INIT_CPU_DEST(9, cc_config->counters);
138 MSGRNG_CC_INIT_CPU_DEST(10, cc_config->counters);
139 MSGRNG_CC_INIT_CPU_DEST(11, cc_config->counters);
140 MSGRNG_CC_INIT_CPU_DEST(12, cc_config->counters);
141 MSGRNG_CC_INIT_CPU_DEST(13, cc_config->counters);
142 MSGRNG_CC_INIT_CPU_DEST(14, cc_config->counters);
143 MSGRNG_CC_INIT_CPU_DEST(15, cc_config->counters);
144
145 msgrng_flags_restore(flags);
146 }
147
148 void
149 xlr_msgring_config(void)
150 {
151 msgring_int_type = 0x02;
152 msgring_pop_num_buckets = 8;
153 msgring_pop_bucket_mask = 0xff;
154
155 msgring_watermark_count = 1;
156 msgring_thread_mask = 0x01;
157 /* printf("[%s]: int_type = 0x%x, pop_num_buckets=%d, pop_bucket_mask=%x" */
158 /* "watermark_count=%d, thread_mask=%x\n", __FUNCTION__, */
159 /* msgring_int_type, msgring_pop_num_buckets, msgring_pop_bucket_mask, */
160 /* msgring_watermark_count, msgring_thread_mask); */
161 }
162
163 void
164 xlr_msgring_handler(struct trapframe *tf)
165 {
166 unsigned long mflags;
167 int bucket = 0;
168 int size = 0, code = 0, rx_stid = 0, tx_stid = 0;
169 struct msgrng_msg msg;
170 unsigned int bucket_empty_bm = 0;
171 unsigned int status = 0;
172
173 xlr_inc_counter(MSGRNG_INT);
174 /* TODO: not necessary to disable preemption */
175 msgrng_flags_save(mflags);
176
177 /* First Drain all the high priority messages */
178 for (;;) {
179 bucket_empty_bm = (msgrng_read_status() >> 24) & msgring_pop_bucket_mask;
180
181 /* all buckets empty, break */
182 if (bucket_empty_bm == msgring_pop_bucket_mask)
183 break;
184
185 for (bucket = 0; bucket < msgring_pop_num_buckets; bucket++) {
186 uint32_t cycles = 0;
187
188 if ((bucket_empty_bm & (1 << bucket)) /* empty */ )
189 continue;
190
191 status = message_receive(bucket, &size, &code, &rx_stid, &msg);
192 if (status)
193 continue;
194
195 xlr_inc_counter(MSGRNG_MSG);
196 msgrng_msg_cycles = mips_rd_count();
197 cycles = msgrng_msg_cycles;
198
199 tx_stid = xlr_board_info.msgmap[rx_stid];
200
201 if (!tx_stn_handlers[tx_stid].action) {
202 printf("[%s]: No Handler for message from stn_id=%d, bucket=%d, "
203 "size=%d, msg0=%llx, dropping message\n",
204 __FUNCTION__, tx_stid, bucket, size, msg.msg0);
205 } else {
206 //printf("[%s]: rx_stid = %d\n", __FUNCTION__, rx_stid);
207 msgrng_flags_restore(mflags);
208 (*tx_stn_handlers[tx_stid].action) (bucket, size, code, rx_stid,
209 &msg, tx_stn_handlers[tx_stid].dev_id);
210 msgrng_flags_save(mflags);
211 }
212 xlr_set_counter(MSGRNG_MSG_CYCLES, (read_c0_count() - cycles));
213 }
214 }
215
216 xlr_set_counter(MSGRNG_EXIT_STATUS, msgrng_read_status());
217
218 msgrng_flags_restore(mflags);
219
220 //dbg_msg("OUT irq=%d\n", irq);
221
222 /* Call the msg callback */
223 }
224
225 void
226 enable_msgring_int(void *arg)
227 {
228 unsigned long mflags = 0;
229
230 msgrng_access_save(&msgrng_lock, mflags);
231 /* enable the message ring interrupts */
232 msgrng_write_config((msgring_watermark_count << 24) | (IRQ_MSGRING << 16)
233 | (msgring_thread_mask << 8) | msgring_int_type);
234 msgrng_access_restore(&msgrng_lock, mflags);
235 }
236
237 void
238 disable_msgring_int(void *arg)
239 {
240 unsigned long mflags = 0;
241 uint32_t config;
242
243 msgrng_access_save(&msgrng_lock, mflags);
244 config = msgrng_read_config();
245 config &= ~0x3;
246 msgrng_write_config(config);
247 msgrng_access_restore(&msgrng_lock, mflags);
248 }
249
250 extern void platform_prep_smp_launch(void);
251 extern void msgring_process_fast_intr(void *arg);
252
253 int
254 register_msgring_handler(int major,
255 void (*action) (int, int, int, int, struct msgrng_msg *, void *),
256 void *dev_id)
257 {
258 void *cookie; /* FIXME - use? */
259
260 if (major >= MAX_TX_STNS)
261 return 1;
262
263 //dbg_msg("major=%d, action=%p, dev_id=%p\n", major, action, dev_id);
264
265 if (rmi_spin_mutex_safe)
266 mtx_lock_spin(&msgrng_lock);
267 tx_stn_handlers[major].action = action;
268 tx_stn_handlers[major].dev_id = dev_id;
269 if (rmi_spin_mutex_safe)
270 mtx_unlock_spin(&msgrng_lock);
271
272 if (xlr_test_and_set(&msgring_int_enabled)) {
273 platform_prep_smp_launch();
274
275 cpu_establish_hardintr("msgring", (driver_filter_t *) NULL,
276 (driver_intr_t *) msgring_process_fast_intr,
277 NULL, IRQ_MSGRING, INTR_TYPE_NET | INTR_FAST, &cookie);
278
279 /* configure the msgring interrupt on cpu 0 */
280 enable_msgring_int(NULL);
281 }
282 return 0;
283 }
284
285 static void
286 pic_init(void)
287 {
288 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
289 int i = 0;
290 int level;
291
292 dbg_msg("Initializing PIC...\n");
293 for (i = 0; i < PIC_NUM_IRTS; i++) {
294
295 level = PIC_IRQ_IS_EDGE_TRIGGERED(i);
296
297 /* Bind all PIC irqs to cpu 0 */
298 xlr_write_reg(mmio, PIC_IRT_0_BASE + i, 0x01);
299
300 /*
301 * Use local scheduling and high polarity for all IRTs
302 * Invalidate all IRTs, by default
303 */
304 xlr_write_reg(mmio, PIC_IRT_1_BASE + i, (level << 30) | (1 << 6) | (PIC_IRQ_BASE + i));
305 }
306 dbg_msg("PIC init now done\n");
307 }
308
309 void
310 on_chip_init(void)
311 {
312 int i = 0, j = 0;
313
314 /* Set xlr_io_base to the run time value */
315 mtx_init(&msgrng_lock, "msgring", NULL, MTX_SPIN | MTX_RECURSE);
316 mtx_init(&xlr_pic_lock, "pic", NULL, MTX_SPIN);
317
318 xlr_board_info_setup();
319
320 msgring_int_enabled = 0;
321
322 xlr_msgring_config();
323 pic_init();
324
325 xlr_msgring_cpu_init();
326
327 for (i = 0; i < MAXCPU; i++)
328 for (j = 0; j < XLR_MAX_COUNTERS; j++)
329 atomic_set_int(&xlr_counters[i][j], 0);
330 }
Cache object: 859a788397374283b87eaa80e4697178
|