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