fmn.c revision 202175
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 52void 53disable_msgring_int(void *arg); 54void 55enable_msgring_int(void *arg); 56 57/* definitions */ 58struct tx_stn_handler { 59 void (*action) (int, int, int, int, struct msgrng_msg *, void *); 60 void *dev_id; 61}; 62 63/* globals */ 64static struct tx_stn_handler tx_stn_handlers[MAX_TX_STNS]; 65 66#define MSGRNG_CC_INIT_CPU_DEST(dest, counter) \ 67do { \ 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 */ 80static struct mtx msgrng_lock; 81static int msgring_int_enabled; 82struct mtx xlr_pic_lock; 83 84static int msgring_pop_num_buckets; 85static uint32_t msgring_pop_bucket_mask; 86static int msgring_int_type; 87static int msgring_watermark_count; 88static uint32_t msgring_thread_mask; 89 90uint32_t msgrng_msg_cycles = 0; 91 92int xlr_counters[MAXCPU][XLR_MAX_COUNTERS] __aligned(XLR_CACHELINE_SIZE); 93 94void xlr_msgring_handler(struct trapframe *); 95 96void 97xlr_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 148void 149xlr_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 163void 164xlr_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 225void 226enable_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 237void 238disable_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 250extern void platform_prep_smp_launch(void); 251extern void msgring_process_fast_intr(void *arg); 252 253int 254register_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 285static void 286pic_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 309void 310on_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} 331