The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mips/rmi/on_chip.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: 8fcb4f12975c304a6d23c86f8442b2e1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.