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