Author: jchandra
Date: Sun Oct  3 04:33:58 2010
New Revision: 213377
URL: http://svn.freebsd.org/changeset/base/213377

Log:
  Update message ring handling code for XLR/XLS
  
  - Wakeup multiple threads per core using message ring watermark interrupts.
  - Update message ring handler registration, use the real device station id
    for registering interrupts.
  - rge/nlge: update for the new message ring registration code.
  - rge/nlge: use 2 message ring stations for incoming packets, this will
    allow more messages to be queued.
  - nlge: comment fixes, remove unused variable
  - style and whitespace fixes

Modified:
  head/sys/mips/rmi/board.c
  head/sys/mips/rmi/dev/nlge/if_nlge.c
  head/sys/mips/rmi/dev/xlr/rge.c
  head/sys/mips/rmi/fmn.c
  head/sys/mips/rmi/msgring.h
  head/sys/mips/rmi/rmi_mips_exts.h
  head/sys/mips/rmi/xlr_machdep.c

Modified: head/sys/mips/rmi/board.c
==============================================================================
--- head/sys/mips/rmi/board.c   Sat Oct  2 22:21:01 2010        (r213376)
+++ head/sys/mips/rmi/board.c   Sun Oct  3 04:33:58 2010        (r213377)
@@ -42,42 +42,6 @@ __FBSDID("$FreeBSD$");
 #include <mips/rmi/board.h>
 #include <mips/rmi/pic.h>
 
-static int xlr_rxstn_to_txstn_map[128] = {
-       [0 ... 7] = TX_STN_CPU_0,
-       [8 ... 15] = TX_STN_CPU_1,
-       [16 ... 23] = TX_STN_CPU_2,
-       [24 ... 31] = TX_STN_CPU_3,
-       [32 ... 39] = TX_STN_CPU_4,
-       [40 ... 47] = TX_STN_CPU_5,
-       [48 ... 55] = TX_STN_CPU_6,
-       [56 ... 63] = TX_STN_CPU_7,
-       [64 ... 95] = TX_STN_INVALID,
-       [96 ... 103] = TX_STN_GMAC,
-       [104 ... 107] = TX_STN_DMA,
-       [108 ... 111] = TX_STN_INVALID,
-       [112 ... 113] = TX_STN_XGS_0,
-       [114 ... 115] = TX_STN_XGS_1,
-       [116 ... 119] = TX_STN_INVALID,
-       [120 ... 127] = TX_STN_SAE
-};
-
-static int xls_rxstn_to_txstn_map[128] = {
-       [0 ... 7] = TX_STN_CPU_0,
-       [8 ... 15] = TX_STN_CPU_1,
-       [16 ... 23] = TX_STN_CPU_2,
-       [24 ... 31] = TX_STN_CPU_3,
-       [32 ... 63] = TX_STN_INVALID,
-       [64 ... 71] = TX_STN_PCIE,
-       [72 ... 79] = TX_STN_INVALID,
-       [80 ... 87] = TX_STN_GMAC1,
-       [88 ... 95] = TX_STN_INVALID,
-       [96 ... 103] = TX_STN_GMAC0,
-       [104 ... 107] = TX_STN_DMA,
-       [108 ... 111] = TX_STN_CDE,
-       [112 ... 119] = TX_STN_INVALID,
-       [120 ... 127] = TX_STN_SAE
-};
-
 struct stn_cc *xlr_core_cc_configs[] = { &cc_table_cpu_0, &cc_table_cpu_1,
     &cc_table_cpu_2, &cc_table_cpu_3, &cc_table_cpu_4, &cc_table_cpu_5,
     &cc_table_cpu_6, &cc_table_cpu_7};
@@ -351,7 +315,6 @@ xlr_board_info_setup()
                xlr_board_info.pci_irq = 0;
                xlr_board_info.credit_configs = xls_core_cc_configs;
                xlr_board_info.bucket_sizes   = &xls_bucket_sizes;
-               xlr_board_info.msgmap         = xls_rxstn_to_txstn_map;
                xlr_board_info.gmacports      = MAX_NA_PORTS;
 
                /* ---------------- Network Acc 0 ---------------- */
@@ -359,7 +322,7 @@ xlr_board_info_setup()
                blk0->type              = XLR_GMAC;
                blk0->enabled           = 0xf;
                blk0->credit_config     = &xls_cc_table_gmac0;
-               blk0->station_id        = TX_STN_GMAC0;
+               blk0->station_id        = MSGRNG_STNID_GMAC;
                blk0->station_txbase    = MSGRNG_STNID_GMACTX0;
                blk0->station_rfr       = MSGRNG_STNID_GMACRFR_0;
                blk0->mode              = XLR_SGMII;
@@ -388,7 +351,7 @@ xlr_board_info_setup()
                blk1->type              = XLR_GMAC;
                blk1->enabled           = 0xf;
                blk1->credit_config     = &xls_cc_table_gmac1;
-               blk1->station_id        = TX_STN_GMAC1;
+               blk1->station_id        = MSGRNG_STNID_GMAC1;
                blk1->station_txbase    = MSGRNG_STNID_GMAC1_TX0;
                blk1->station_rfr       = MSGRNG_STNID_GMAC1_FR_0;
                blk1->mode              = XLR_SGMII;
@@ -424,14 +387,13 @@ xlr_board_info_setup()
                xlr_board_info.pci_irq = 0;
                xlr_board_info.credit_configs = xlr_core_cc_configs;
                xlr_board_info.bucket_sizes   = &bucket_sizes;
-               xlr_board_info.msgmap         =  xlr_rxstn_to_txstn_map;
                xlr_board_info.gmacports         = 4;
 
                /* ---------------- GMAC0 ---------------- */
                blk0->type              = XLR_GMAC;
                blk0->enabled           = 0xf;
                blk0->credit_config     = &cc_table_gmac;
-               blk0->station_id        = TX_STN_GMAC;
+               blk0->station_id        = MSGRNG_STNID_GMAC;
                blk0->station_txbase    = MSGRNG_STNID_GMACTX0;
                blk0->station_rfr       = MSGRNG_STNID_GMACRFR_0;
                blk0->mode              = XLR_RGMII;
@@ -461,7 +423,7 @@ xlr_board_info_setup()
                blk1->credit_config     = &cc_table_xgs_0;
                blk1->station_txbase    = MSGRNG_STNID_XGS0_TX;
                blk1->station_rfr       = MSGRNG_STNID_XMAC0RFR;
-               blk1->station_id        = TX_STN_XGS_0; /* TBD: is this correct 
? */
+               blk1->station_id        = MSGRNG_STNID_XGS0FR;
                blk1->baseaddr          = XLR_IO_XGMAC_0_OFFSET;
                blk1->baseirq           = PIC_XGS_0_IRQ;
                blk1->baseinst          = 4;
@@ -481,7 +443,7 @@ xlr_board_info_setup()
                blk2->credit_config     = &cc_table_xgs_1;
                blk2->station_txbase    = MSGRNG_STNID_XGS1_TX;
                blk2->station_rfr       = MSGRNG_STNID_XMAC1RFR;
-               blk2->station_id        = TX_STN_XGS_1; /* TBD: is this correct 
? */
+               blk2->station_id        = MSGRNG_STNID_XGS1FR;
                blk2->baseaddr          = XLR_IO_XGMAC_1_OFFSET;
                blk2->baseirq           = PIC_XGS_1_IRQ;
                blk2->baseinst          = 5;

Modified: head/sys/mips/rmi/dev/nlge/if_nlge.c
==============================================================================
--- head/sys/mips/rmi/dev/nlge/if_nlge.c        Sat Oct  2 22:21:01 2010        
(r213376)
+++ head/sys/mips/rmi/dev/nlge/if_nlge.c        Sun Oct  3 04:33:58 2010        
(r213377)
@@ -902,11 +902,12 @@ nlna_hw_init(struct nlna_softc *sc)
 {
 
        /*
-        * It is seen that this is a critical function in bringing up FreeBSD.
-        * When it is not invoked, FreeBSD panics and fails during the
-        * multi-processor init (SI_SUB_SMP of * mi_startup). The key function
-        * in this sequence seems to be platform_prep_smp_launch. */
-       if (register_msgring_handler(sc->station_id, nlge_msgring_handler, sc)) 
{
+        * Register message ring handler for the NA block, messages from
+        * the GMAC will have sourec station id to the first bucket of the 
+        * NA FMN station, so register just that station id.
+        */
+       if (register_msgring_handler(sc->station_id, sc->station_id + 1,
+           nlge_msgring_handler, sc)) {
                panic("Couldn't register msgring handler\n");
        }
        nlna_config_fifo_spill_area(sc);
@@ -1143,13 +1144,13 @@ nlna_config_pde(struct nlna_softc *sc)
        if (smp_started)
                cpumask = xlr_hw_thread_mask;
 #endif
-
        bucket_map = 0;
        for (i = 0; i < 32; i++) {
                if (cpumask & (1 << i)) {
                        cpu = i;
-                       bucket = ((cpu >> 2) << 3);
-                       bucket_map |= (1ULL << bucket);
+                       /* use bucket 0 and 1 on every core for NA msgs */
+                       bucket = cpu/4 * 8;
+                       bucket_map |= (3ULL << bucket);
                }
        }
        NLGE_WRITE(sc->base, R_PDE_CLASS_0, (bucket_map & 0xffffffff));
@@ -1165,6 +1166,11 @@ nlna_config_pde(struct nlna_softc *sc)
        NLGE_WRITE(sc->base, R_PDE_CLASS_3 + 1, ((bucket_map >> 32) & 
0xffffffff));
 }
 
+/*
+ * Update the network accelerator packet distribution engine for SMP.
+ * On bootup, we have just the boot hw thread handling all packets, on SMP
+ * start, we can start distributing packets across all the cores which are up.
+ */
 static void
 nlna_smp_update_pde(void *dummy __unused)
 {
@@ -1235,11 +1241,9 @@ nlna_config_common(struct nlna_softc *sc
 {
        struct xlr_gmac_block_t *block_info;
        struct stn_cc           *gmac_cc_config;
-       int                     i, id;
+       int                     i;
 
        block_info = device_get_ivars(sc->nlna_dev);
-
-       id = device_get_unit(sc->nlna_dev);
        gmac_cc_config = block_info->credit_config;
        for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) {
                NLGE_WRITE(sc->base, R_CC_CPU0_0 + i,

Modified: head/sys/mips/rmi/dev/xlr/rge.c
==============================================================================
--- head/sys/mips/rmi/dev/xlr/rge.c     Sat Oct  2 22:21:01 2010        
(r213376)
+++ head/sys/mips/rmi/dev/xlr/rge.c     Sun Oct  3 04:33:58 2010        
(r213377)
@@ -971,7 +971,7 @@ rmi_xlr_config_pde(struct driver_data *p
                if (cpumask & (1 << i)) {
                        cpu = i;
                        bucket = ((cpu >> 2) << 3);
-                       bucket_map |= (1ULL << bucket);
+                       bucket_map |= (3ULL << bucket);
                }
        }
        printf("rmi_xlr_config_pde: bucket_map=%jx\n", (uintmax_t)bucket_map);
@@ -2539,17 +2539,20 @@ mac_common_init(void)
        init_tx_ring();
 
        if (xlr_board_info.is_xls) {
-               if (register_msgring_handler(TX_STN_GMAC0,
-                   rmi_xlr_mac_msgring_handler, NULL)) {
+               if (register_msgring_handler(MSGRNG_STNID_GMAC,
+                  MSGRNG_STNID_GMAC + 1, rmi_xlr_mac_msgring_handler,
+                  NULL)) {
                        panic("Couldn't register msgring handler\n");
                }
-               if (register_msgring_handler(TX_STN_GMAC1,
-                   rmi_xlr_mac_msgring_handler, NULL)) {
+               if (register_msgring_handler(MSGRNG_STNID_GMAC1,
+                   MSGRNG_STNID_GMAC1 + 1, rmi_xlr_mac_msgring_handler,
+                   NULL)) {
                        panic("Couldn't register msgring handler\n");
                }
        } else {
-               if (register_msgring_handler(TX_STN_GMAC,
-                   rmi_xlr_mac_msgring_handler, NULL)) {
+               if (register_msgring_handler(MSGRNG_STNID_GMAC,
+                  MSGRNG_STNID_GMAC + 1, rmi_xlr_mac_msgring_handler,
+                  NULL)) {
                        panic("Couldn't register msgring handler\n");
                }
        }

Modified: head/sys/mips/rmi/fmn.c
==============================================================================
--- head/sys/mips/rmi/fmn.c     Sat Oct  2 22:21:01 2010        (r213376)
+++ head/sys/mips/rmi/fmn.c     Sun Oct  3 04:33:58 2010        (r213377)
@@ -60,25 +60,6 @@ __FBSDID("$FreeBSD$");
 #include <mips/rmi/pic.h>
 #include <mips/rmi/board.h>
 
-/* definitions */
-struct tx_stn_handler {
-       void (*action) (int, int, int, int, struct msgrng_msg *, void *);
-       void *dev_id;
-};
-
-struct msgring_ithread {
-       struct thread *i_thread;
-       u_int i_pending;
-       u_int i_flags;
-       int i_cpu;
-       int i_core;
-};
-
-struct msgring_ithread *msgring_ithreads[MAXCPU];
-
-/* globals */
-static struct tx_stn_handler tx_stn_handlers[MAX_TX_STNS];
-
 #define MSGRNG_CC_INIT_CPU_DEST(dest, counter) \
 do { \
      msgrng_write_cc(MSGRNG_CC_##dest##_REG, counter[dest][0], 0 ); \
@@ -92,40 +73,68 @@ do { \
 } while(0)
 
 
-/* make this a read/write spinlock */
-static struct mtx msgrng_lock;
-static int msgring_int_enabled;
-static int msgring_pop_num_buckets;
-static uint8_t msgring_pop_bucket_mask;
-static int msgring_int_type;
-static int msgring_watermark_count;
-static uint32_t msgring_thread_mask;
-uint32_t msgrng_msg_cycles = 0;
+/*
+ * Keep track of our message ring handler threads, each core has a 
+ * different message station. Ideally we will need to start a few
+ * message handling threads every core, and wake them up depending on
+ * load
+ */
+struct msgring_thread {
+       struct {
+               struct thread   *thread; /* msgring handler threads */
+               int     needed;         /* thread needs to wake up */
+       } threads[XLR_NTHREADS];
+       int     running;                /* number of threads running */
+       int     nthreads;               /* number of threads started */
+       struct mtx lock;                /* for changing running/active */
+};
+static struct msgring_thread msgring_threads[XLR_MAX_CORES];
+static struct proc *msgring_proc;      /* all threads are under a proc */
+
+/*
+ * The maximum number of software message handler threads to be started 
+ * per core. Default is 2 per core
+ */
+static int     msgring_maxthreads = 2; 
+TUNABLE_INT("hw.fmn.maxthreads", &msgring_maxthreads);
+
+/* 
+ * The device drivers can register a handler for the the messages sent
+ * from a station (corresponding to the device). 
+ */
+struct tx_stn_handler {
+       msgring_handler action;
+       void *arg;
+};
+static struct tx_stn_handler msgmap[MSGRNG_NSTATIONS];
+static struct mtx      msgmap_lock;
 
+/*
+ * Initialize the messaging subsystem.
+ * 
+ * Message Stations are shared among all threads in a cpu core, this 
+ * has to be called once from every core which is online.
+ */
 void 
 xlr_msgring_cpu_init(void)
 {
        struct stn_cc *cc_config;
        struct bucket_size *bucket_sizes;
-       int id;
        uint32_t flags;
+       int id;
 
        KASSERT(xlr_thr_id() == 0,
-               ("xlr_msgring_cpu_init from non-zero thread\n"));
-
+               ("xlr_msgring_cpu_init from non-zero thread"));
        id = xlr_core_id();
-
        bucket_sizes = xlr_board_info.bucket_sizes;
        cc_config = xlr_board_info.credit_configs[id];
 
+       flags = msgrng_access_enable();
 
        /*
-        * Message Stations are shared among all threads in a cpu core
-        * Assume, thread 0 on all cores are always active when more than 1
-        * thread is active in a core
+        * FMN messages are received in 8 buckets per core, set up
+        * the bucket sizes for each bucket
         */
-       flags = msgrng_access_enable();
-
        msgrng_write_bucksize(0, bucket_sizes->bucket[id * 8 + 0]);
        msgrng_write_bucksize(1, bucket_sizes->bucket[id * 8 + 1]);
        msgrng_write_bucksize(2, bucket_sizes->bucket[id * 8 + 2]);
@@ -135,36 +144,43 @@ xlr_msgring_cpu_init(void)
        msgrng_write_bucksize(6, bucket_sizes->bucket[id * 8 + 6]);
        msgrng_write_bucksize(7, bucket_sizes->bucket[id * 8 + 7]);
 
-       MSGRNG_CC_INIT_CPU_DEST(0, cc_config->counters);
-       MSGRNG_CC_INIT_CPU_DEST(1, cc_config->counters);
-       MSGRNG_CC_INIT_CPU_DEST(2, cc_config->counters);
-       MSGRNG_CC_INIT_CPU_DEST(3, cc_config->counters);
-       MSGRNG_CC_INIT_CPU_DEST(4, cc_config->counters);
-       MSGRNG_CC_INIT_CPU_DEST(5, cc_config->counters);
-       MSGRNG_CC_INIT_CPU_DEST(6, cc_config->counters);
-       MSGRNG_CC_INIT_CPU_DEST(7, cc_config->counters);
-       MSGRNG_CC_INIT_CPU_DEST(8, cc_config->counters);
-       MSGRNG_CC_INIT_CPU_DEST(9, cc_config->counters);
+       /* 
+        * For sending FMN messages, we need credits on the destination
+        * bucket.  Program the credits this core has on the 128 possible
+        * destination buckets.
+        * We cannot use a loop, because the the first argument has to
+        * be a constant integer value.
+        */
+       MSGRNG_CC_INIT_CPU_DEST(0,  cc_config->counters);
+       MSGRNG_CC_INIT_CPU_DEST(1,  cc_config->counters);
+       MSGRNG_CC_INIT_CPU_DEST(2,  cc_config->counters);
+       MSGRNG_CC_INIT_CPU_DEST(3,  cc_config->counters);
+       MSGRNG_CC_INIT_CPU_DEST(4,  cc_config->counters);
+       MSGRNG_CC_INIT_CPU_DEST(5,  cc_config->counters);
+       MSGRNG_CC_INIT_CPU_DEST(6,  cc_config->counters);
+       MSGRNG_CC_INIT_CPU_DEST(7,  cc_config->counters);
+       MSGRNG_CC_INIT_CPU_DEST(8,  cc_config->counters);
+       MSGRNG_CC_INIT_CPU_DEST(9,  cc_config->counters);
        MSGRNG_CC_INIT_CPU_DEST(10, cc_config->counters);
        MSGRNG_CC_INIT_CPU_DEST(11, cc_config->counters);
        MSGRNG_CC_INIT_CPU_DEST(12, cc_config->counters);
        MSGRNG_CC_INIT_CPU_DEST(13, cc_config->counters);
        MSGRNG_CC_INIT_CPU_DEST(14, cc_config->counters);
        MSGRNG_CC_INIT_CPU_DEST(15, cc_config->counters);
-
        msgrng_restore(flags);
 }
 
+/*
+ * Boot time init, called only once
+ */
 void 
 xlr_msgring_config(void)
 {
-       mtx_init(&msgrng_lock, "msgring", NULL, MTX_SPIN | MTX_RECURSE);
-       msgring_int_type = 0x02;
-       msgring_pop_num_buckets = 8;
-       msgring_pop_bucket_mask = 0xff;
-       msgring_int_enabled = 0;
-       msgring_watermark_count = 1;
-       msgring_thread_mask = 0x01;
+       mtx_init(&msgmap_lock, "msgring", NULL, MTX_SPIN);
+       
+       /* check value */
+       if (msgring_maxthreads < 0 || msgring_maxthreads > XLR_NTHREADS)
+               msgring_maxthreads = XLR_NTHREADS;
 }
 
 /*
@@ -175,44 +191,42 @@ uint32_t
 xlr_msgring_handler(uint8_t bucket_mask, uint32_t max_messages)
 {
        int bucket = 0;
-       int size = 0, code = 0, rx_stid = 0, tx_stid = 0;
+       int size = 0, code = 0, rx_stid = 0;
        struct msgrng_msg msg;
-       uint8_t bucket_empty_bm = 0;
+       struct tx_stn_handler *he;
        unsigned int status = 0;
        unsigned long mflags;
-       uint32_t  n_msgs;
+       uint32_t n_msgs;
+       uint32_t msgbuckets;
 
        n_msgs = 0;
        mflags = msgrng_access_enable();
-       /* First Drain all the high priority messages */
        for (;;) {
-               bucket_empty_bm = (msgrng_read_status() >> 24) & bucket_mask;
+               msgbuckets = (~msgrng_read_status() >> 24) & bucket_mask;
 
                /* all buckets empty, break */
-               if (bucket_empty_bm == bucket_mask)
+               if (msgbuckets == 0)
                        break;
 
-               for (bucket = 0; bucket < msgring_pop_num_buckets; bucket++) {
-                       if (!((1 << bucket) & bucket_mask)        /* bucket not 
in mask */
-                           || (bucket_empty_bm & (1 << bucket))) /* empty */
+               for (bucket = 0; bucket < 8; bucket++) {
+                       if ((msgbuckets & (1 << bucket)) == 0) /* empty */
                                continue;
 
-                       status = message_receive(bucket, &size, &code, 
&rx_stid, &msg);
-                       if (status)
+                       status = message_receive(bucket, &size, &code,
+                           &rx_stid, &msg);
+                       if (status != 0)
                                continue;
-
-                       tx_stid = xlr_board_info.msgmap[rx_stid];
                        n_msgs++;
-
-                       if (!tx_stn_handlers[tx_stid].action) {
-                               printf("[%s]: No Handler for message from 
stn_id=%d, bucket=%d, "
-                                   "size=%d, msg0=%jx, dropping message\n",
-                                   __FUNCTION__, tx_stid, bucket, size, 
(uintmax_t)msg.msg0);
+                       he = &msgmap[rx_stid];
+                       if (he->action == NULL) {
+                               printf("[%s]: No Handler for message from "
+                                   "stn_id=%d, bucket=%d, size=%d, msg0=%jx\n",
+                                   __func__, rx_stid, bucket, size,
+                                   (uintmax_t)msg.msg0);
                        } else {
-                               //printf("[%s]: rx_stid = %d\n", __FUNCTION__, 
rx_stid);
                                msgrng_restore(mflags);
-                               (*tx_stn_handlers[tx_stid].action) (bucket, 
size, code, rx_stid,
-                                   &msg, tx_stn_handlers[tx_stid].dev_id);
+                               (*he->action)(bucket, size, code, rx_stid,
+                                   &msg, he->arg);
                                mflags = msgrng_access_enable();
                        }
                        if (max_messages > 0 && n_msgs >= max_messages)
@@ -222,132 +236,166 @@ xlr_msgring_handler(uint8_t bucket_mask,
 
 done:
        msgrng_restore(mflags);
-
        return (n_msgs);
 }
 
-static void 
-enable_msgring_int(void)
+/* 
+ * XLR COP2 supports watermark interrupts based on the number of 
+ * messages pending in all the buckets in the core.  We increase 
+ * the watermark until all the possible handler threads in the core
+ * are woken up.
+ */
+static void
+msgrng_setconfig(int running, int nthr)
 {
        uint32_t config, mflags;
+       int watermark = 1;      /* non zero needed */
+       int wm_intr_value;
 
-       config = (msgring_watermark_count << 24) | (IRQ_MSGRING << 16) |
-           (msgring_thread_mask << 8) | msgring_int_type;
+       KASSERT(nthr >= 0 && nthr <= msgring_maxthreads,
+           ("Bad value of nthr %d", nthr));
+       KASSERT(running <= nthr, ("Bad value of running %d", running));
+
+       if (running == nthr) {
+               wm_intr_value = 0;
+       } else {
+               switch (running) {
+               case 0: break;          /* keep default */
+               case 1:
+                       watermark = 16; break;
+               case 2:
+                       watermark = 32; break;
+               case 3: 
+                       watermark = 48; break;
+               }
+               wm_intr_value = 0x2;    /* set watermark enable interrupt */
+       }
        mflags = msgrng_access_enable();
+       config = (watermark << 24) | (IRQ_MSGRING << 16) | (1 << 8) |
+               wm_intr_value;
+       /* clear any pending interrupts */
+       write_c0_eirr64(1ULL << IRQ_MSGRING);
        msgrng_write_config(config);
        msgrng_restore(mflags);
 }
 
-static void 
-disable_msgring_int(void)
+static int
+msgring_process_fast_intr(void *arg)
 {
-       uint32_t config, mflags;
+       struct msgring_thread *mthd;
+       struct thread   *td;
+       uint32_t        mflags;
+       int             core, nt;
+
+       core = xlr_core_id();
+       mthd = &msgring_threads[core];
+
+       mtx_lock_spin(&mthd->lock);
+       nt = mthd->running;
+       if(nt >= mthd->nthreads) {
+               mtx_unlock_spin(&mthd->lock);
+               return (FILTER_HANDLED);
+       }
 
+       td = mthd->threads[nt].thread;
        mflags = msgrng_access_enable();
-       config = msgrng_read_config() & ~0x3;
-       msgrng_write_config(config);
-       msgrng_restore(mflags);
-}
 
-static int
-msgring_process_fast_intr(void *arg)
-{
-       int core = xlr_core_id();
-       volatile struct msgring_ithread *it;
-       struct thread *td;
+       /* default value with interrupts disabled */
+       msgrng_write_config((1 << 24) | (IRQ_MSGRING << 16) | (1 << 8));
 
-       /* wakeup an appropriate intr_thread for processing this interrupt */
-       it = (volatile struct msgring_ithread *)msgring_ithreads[core];
-       KASSERT(it != NULL, ("No interrupt thread on cpu %d", core));
-       td = it->i_thread;
+       msgrng_restore(mflags);
+       mtx_unlock_spin(&mthd->lock);
 
-       /*
-        * Interrupt thread will enable the interrupts after processing all
-        * messages
-        */
-       disable_msgring_int();
-       atomic_store_rel_int(&it->i_pending, 1);
+       /* wake up the target thread */
+       mthd->threads[nt].needed = 1;
        thread_lock(td);
        if (TD_AWAITING_INTR(td)) {
                TD_CLR_IWAIT(td);
                sched_add(td, SRQ_INTR);
        }
        thread_unlock(td);
-       return FILTER_HANDLED;
+       return (FILTER_HANDLED);
 }
 
 static void
 msgring_process(void *arg)
 {
-       volatile struct msgring_ithread *ithd;
-       struct thread *td;
-       struct proc *p;
-
-       td = curthread;
-       p = td->td_proc;
-       ithd = (volatile struct msgring_ithread *)arg;
-       KASSERT(ithd->i_thread == td,
-           ("%s:msg_ithread and proc linkage out of sync", __func__));
+       struct msgring_thread *mthd;
+       struct thread   *td;
+       int             hwtid, tid, core;
+       int             nmsgs;
+
+       hwtid = (intptr_t)arg;
+       core = hwtid / 4;
+       tid = hwtid % 4;
+       mthd = &msgring_threads[core];
+       td = mthd->threads[tid].thread;
+       KASSERT(curthread == td,
+           ("Incorrect thread core %d, thread %d", core, hwtid));
 
        /* First bind this thread to the right CPU */
        thread_lock(td);
-       
-       sched_bind(td, ithd->i_cpu);
+       sched_bind(td, xlr_hwtid_to_cpuid[hwtid]);
        thread_unlock(td);
 
-       atomic_store_rel_ptr((volatile uintptr_t 
*)&msgring_ithreads[ithd->i_core],
-            (uintptr_t)arg);
-       enable_msgring_int();
-       
-       while (1) {
-               while (ithd->i_pending) {
-                       /*
-                        * This might need a full read and write barrier to
-                        * make sure that this write posts before any of the
-                        * memory or device accesses in the handlers.
-                        */
-                       xlr_msgring_handler(msgring_pop_bucket_mask, 0);
-                       atomic_store_rel_int(&ithd->i_pending, 0);
-                       enable_msgring_int();
-               }
-               if (!ithd->i_pending) {
-                       thread_lock(td);
-                       if (ithd->i_pending) {
-                         thread_unlock(td);
-                         continue;
-                       }
-                       sched_class(td, PRI_ITHD);
-                       TD_SET_IWAIT(td);
-                       mi_switch(SW_VOL, NULL);
+       /*
+        * Mark ourselves as a running thread, and update the 
+        * message watermark config for this thread
+        */
+       mtx_lock_spin(&mthd->lock);
+       ++mthd->nthreads;
+       mtx_unlock_spin(&mthd->lock);
+
+       /* start processing messages */
+       for(;;) {
+               mtx_lock_spin(&mthd->lock);
+               ++mthd->running;
+               msgrng_setconfig(mthd->running, mthd->nthreads);
+               mtx_unlock_spin(&mthd->lock);
+
+               atomic_store_rel_int(&mthd->threads[tid].needed, 0);
+               nmsgs = xlr_msgring_handler(0xff, 0);
+
+               mtx_lock_spin(&mthd->lock);
+               --mthd->running;
+               msgrng_setconfig(mthd->running, mthd->nthreads);
+               mtx_unlock_spin(&mthd->lock);
+
+               /* sleep */
+               thread_lock(td);
+               if (mthd->threads[tid].needed) {
                        thread_unlock(td);
+                       continue;
                }
+               sched_class(td, PRI_ITHD);
+               TD_SET_IWAIT(td);
+               mi_switch(SW_VOL, NULL);
+               thread_unlock(td);
        }
-
 }
 
 static void 
-create_msgring_thread(int core, int cpu)
+create_msgring_thread(int hwtid)
 {
-       struct msgring_ithread *ithd;
+       struct msgring_thread *mthd;
        struct thread *td;
-       struct proc *p;
-       int error;
+       int     tid, core;
+       int     error;
 
-       /* Create kernel thread for message ring interrupt processing */
-       /* Currently create one task for thread 0 of each core */
-       ithd = malloc(sizeof(struct msgring_ithread),
-           M_DEVBUF, M_WAITOK | M_ZERO);
-       error = kproc_create(msgring_process, (void *)ithd, &p,
-           RFSTOPPED | RFHIGHPID, 2, "msg_intr%d", cpu);
+       core = hwtid / 4;
+       tid = hwtid % 4;
 
+       mthd = &msgring_threads[core];
+       if (tid == 0) {
+               mtx_init(&mthd->lock, "msgrngcore", NULL, MTX_SPIN);
+               mthd->running = mthd->nthreads = 0;
+       }
+       error = kproc_kthread_add(msgring_process, (void *)hwtid,
+           &msgring_proc, &td, RFSTOPPED, 2, "msgrngproc",
+           "msgthr%d", hwtid);
        if (error)
-               panic("kproc_create() failed with %d", error);
-       td = FIRST_THREAD_IN_PROC(p);   /* XXXKSE */
-
-       ithd->i_thread = td;
-       ithd->i_pending = 0;
-       ithd->i_cpu = cpu;
-       ithd->i_core = core;
+               panic("kproc_kthread_add() failed with %d", error);
+       mthd->threads[tid].thread = td;
 
        thread_lock(td);
        sched_class(td, PRI_ITHD);
@@ -357,40 +405,49 @@ create_msgring_thread(int core, int cpu)
 }
 
 int 
-register_msgring_handler(int major,
-    void (*action) (int, int, int, int, struct msgrng_msg *, void *),
-    void *dev_id)
+register_msgring_handler(int startb, int endb, msgring_handler action,
+    void *arg)
 {
-       void *cookie;           /* FIXME - use? */
-
-       if (major >= MAX_TX_STNS)
-               return 1;
-
-       mtx_lock_spin(&msgrng_lock);
-       tx_stn_handlers[major].action = action;
-       tx_stn_handlers[major].dev_id = dev_id;
-       mtx_unlock_spin(&msgrng_lock);
+       void    *cookie;
+       int     i;
+       static int msgring_int_enabled = 0;
+
+       printf("register handler %d-%d %p %p\n", startb, endb, action, arg);
+       KASSERT(startb >= 0 && startb <= endb && endb < MSGRNG_NSTATIONS,
+           ("Invalid value for for bucket range %d,%d", startb, endb));
+
+       mtx_lock_spin(&msgmap_lock);
+       for (i = startb; i <= endb; i++) {
+               KASSERT(msgmap[i].action == NULL,
+                  ("Bucket %d already used [action %p]", i, msgmap[i].action));
+               msgmap[i].action = action;
+               msgmap[i].arg = arg;
+       }
+       mtx_unlock_spin(&msgmap_lock);
 
        if (xlr_test_and_set(&msgring_int_enabled)) {
-               create_msgring_thread(0, 0);
-               cpu_establish_hardintr("msgring", (driver_filter_t *) 
msgring_process_fast_intr,
+               create_msgring_thread(0);
+               if (msgring_maxthreads > xlr_threads_per_core)
+                       msgring_maxthreads = xlr_threads_per_core;
+               cpu_establish_hardintr("msgring", msgring_process_fast_intr,
                        NULL, NULL, IRQ_MSGRING, 
                        INTR_TYPE_NET | INTR_FAST, &cookie);
        }
-       return 0;
+       return (0);
 }
 
 static void
 start_msgring_threads(void *arg)
 {
-       int core, cpu;
+       int     hwt, tid;
 
-       for (core = 1; core < XLR_MAX_CORES; core++) {
-               if ((xlr_hw_thread_mask >> (4 * core)) & 0xf) {
-                       /* start one thread for an enabled core */
-                       cpu = xlr_hwtid_to_cpuid[4 * core];
-                       create_msgring_thread(core, cpu);
-               }
+       for (hwt = 1; hwt < XLR_MAX_CORES * XLR_NTHREADS; hwt++) {
+               if ((xlr_hw_thread_mask & (1 << hwt)) == 0)
+                       continue;
+               tid = hwt % XLR_NTHREADS;
+               if (tid >= msgring_maxthreads)
+                       continue;
+               create_msgring_thread(hwt);
        }
 }
 

Modified: head/sys/mips/rmi/msgring.h
==============================================================================
--- head/sys/mips/rmi/msgring.h Sat Oct  2 22:21:01 2010        (r213376)
+++ head/sys/mips/rmi/msgring.h Sun Oct  3 04:33:58 2010        (r213377)
@@ -171,14 +171,12 @@
 #define        MSGRNG_CODE_SEC         0
 #define        MSGRNG_CODE_BOOT_WAKEUP 200
 #define        MSGRNG_CODE_SPI4        3
-#define        msgrng_read_status()    
read_c2_register32(MSGRNG_MSG_STATUS_REG, 0)
 
+#define        msgrng_read_status()    
read_c2_register32(MSGRNG_MSG_STATUS_REG, 0)
 #define        msgrng_read_config()    
read_c2_register32(MSGRNG_MSG_CONFIG_REG, 0)
 #define        msgrng_write_config(v)  
write_c2_register32(MSGRNG_MSG_CONFIG_REG, 0, v)
-
 #define        msgrng_read_bucksize(b) 
read_c2_register32(MSGRNG_MSG_BUCKSIZE_REG, b)
 #define        msgrng_write_bucksize(b, v)     
write_c2_register32(MSGRNG_MSG_BUCKSIZE_REG, b, v)
-
 #define        msgrng_read_cc(r, s)    read_c2_register32(r, s)
 #define        msgrng_write_cc(r, v, s)        write_c2_register32(r, s, v)
 
@@ -321,14 +319,16 @@ message_receive(int bucket, int *size, i
        return (0);
 }
 
-#define MSGRNG_STN_RX_QSIZE 256
+#define        MSGRNG_STN_RX_QSIZE     256
+#define        MSGRNG_NSTATIONS        128
+#define        MSGRNG_CORE_NBUCKETS    8
 
 struct stn_cc {
        unsigned short counters[16][8];
 };
 
 struct bucket_size {
-       unsigned short bucket[128];
+       unsigned short bucket[MSGRNG_NSTATIONS];
 };
 
 extern struct bucket_size bucket_sizes;
@@ -360,35 +360,9 @@ extern struct stn_cc xls_cc_table_pcie;
 extern struct stn_cc xls_cc_table_dma;
 extern struct stn_cc xls_cc_table_sec;
 
-/*
- * NOTE: this is not stationid/8, ie the station numbers below are just
- * for internal use
- */
-enum {
-       TX_STN_CPU_0,
-       TX_STN_CPU_1,
-       TX_STN_CPU_2,
-       TX_STN_CPU_3,
-       TX_STN_CPU_4,
-       TX_STN_CPU_5,
-       TX_STN_CPU_6,
-       TX_STN_CPU_7,
-       TX_STN_GMAC,
-       TX_STN_DMA,
-       TX_STN_XGS_0,
-       TX_STN_XGS_1,
-       TX_STN_SAE,
-       TX_STN_GMAC0,
-       TX_STN_GMAC1,
-       TX_STN_CDE,
-       TX_STN_PCIE,
-       TX_STN_INVALID,
-       MAX_TX_STNS
-};
-
-int register_msgring_handler(int major,
-    void (*action) (int, int, int, int, struct msgrng_msg *, void *),
-    void *dev_id);
+typedef void (*msgring_handler)(int, int, int, int, struct msgrng_msg *, void 
*);
+int register_msgring_handler(int startb, int endb, msgring_handler action,
+                   void *arg);
 uint32_t xlr_msgring_handler(uint8_t bucket_mask, uint32_t max_messages);
 void xlr_msgring_cpu_init(void);
 void xlr_msgring_config(void);

Modified: head/sys/mips/rmi/rmi_mips_exts.h
==============================================================================
--- head/sys/mips/rmi/rmi_mips_exts.h   Sat Oct  2 22:21:01 2010        
(r213376)
+++ head/sys/mips/rmi/rmi_mips_exts.h   Sun Oct  3 04:33:58 2010        
(r213377)
@@ -309,7 +309,6 @@ xlr_thr_id(void)
 /* Additional registers on the XLR */
 #define        MIPS_COP_0_OSSCRATCH    22
 #define        XLR_CACHELINE_SIZE      32
-#define        XLR_MAX_CORES           8
 
 /* functions to write to and read from the extended
  * cp0 registers.
@@ -559,7 +558,19 @@ xlr_restore_kx(uint32_t sr)
 }
 #endif /* defined(__mips_n64) || defined(__mips_n32) */
 
-/* for cpuid to hardware thread id mapping */
+/*
+ * XLR/XLS processors have maximum 8 cores, and maximum 4 threads
+ * per core
+ */
+#define        XLR_MAX_CORES           8
+#define        XLR_NTHREADS            4
+
+/*
+ * FreeBSD can be started with few threads and cores turned off,
+ * so have a hardware thread id to FreeBSD cpuid mapping.
+ */
+extern int xlr_ncores;
+extern int xlr_threads_per_core;
 extern uint32_t xlr_hw_thread_mask;
 extern int xlr_cpuid_to_hwtid[];
 extern int xlr_hwtid_to_cpuid[];

Modified: head/sys/mips/rmi/xlr_machdep.c
==============================================================================
--- head/sys/mips/rmi/xlr_machdep.c     Sat Oct  2 22:21:01 2010        
(r213376)
+++ head/sys/mips/rmi/xlr_machdep.c     Sun Oct  3 04:33:58 2010        
(r213377)
@@ -596,7 +596,6 @@ platform_ipi_send(int cpuid)
 {
 
        pic_send_ipi(xlr_cpuid_to_hwtid[cpuid], platform_ipi_intrnum());
-
 }
 
 void
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to