summaryrefslogtreecommitdiffstats
path: root/sys/mips/rmi
diff options
context:
space:
mode:
authorjchandra <jchandra@FreeBSD.org>2010-10-03 04:33:58 +0000
committerjchandra <jchandra@FreeBSD.org>2010-10-03 04:33:58 +0000
commita5c3ee2add2670be35d89c08799c802d0cb68245 (patch)
treeee23fad591e434c716c121102dde918583cca4e9 /sys/mips/rmi
parentdd58e025216b85edf1409ceb0856c5d4d2455c08 (diff)
downloadFreeBSD-src-a5c3ee2add2670be35d89c08799c802d0cb68245.zip
FreeBSD-src-a5c3ee2add2670be35d89c08799c802d0cb68245.tar.gz
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
Diffstat (limited to 'sys/mips/rmi')
-rw-r--r--sys/mips/rmi/board.c48
-rw-r--r--sys/mips/rmi/dev/nlge/if_nlge.c26
-rw-r--r--sys/mips/rmi/dev/xlr/rge.c17
-rw-r--r--sys/mips/rmi/fmn.c421
-rw-r--r--sys/mips/rmi/msgring.h42
-rw-r--r--sys/mips/rmi/rmi_mips_exts.h15
-rw-r--r--sys/mips/rmi/xlr_machdep.c1
7 files changed, 290 insertions, 280 deletions
diff --git a/sys/mips/rmi/board.c b/sys/mips/rmi/board.c
index 26658a5..7b9f62f 100644
--- a/sys/mips/rmi/board.c
+++ b/sys/mips/rmi/board.c
@@ -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;
diff --git a/sys/mips/rmi/dev/nlge/if_nlge.c b/sys/mips/rmi/dev/nlge/if_nlge.c
index 9911890..7956224 100644
--- a/sys/mips/rmi/dev/nlge/if_nlge.c
+++ b/sys/mips/rmi/dev/nlge/if_nlge.c
@@ -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,
diff --git a/sys/mips/rmi/dev/xlr/rge.c b/sys/mips/rmi/dev/xlr/rge.c
index 09045f4..a529377 100644
--- a/sys/mips/rmi/dev/xlr/rge.c
+++ b/sys/mips/rmi/dev/xlr/rge.c
@@ -971,7 +971,7 @@ rmi_xlr_config_pde(struct driver_data *priv)
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");
}
}
diff --git a/sys/mips/rmi/fmn.c b/sys/mips/rmi/fmn.c
index f55f39f..776ed80 100644
--- a/sys/mips/rmi/fmn.c
+++ b/sys/mips/rmi/fmn.c
@@ -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, uint32_t max_messages)
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;
-
- config = (msgring_watermark_count << 24) | (IRQ_MSGRING << 16) |
- (msgring_thread_mask << 8) | msgring_int_type;
+ int watermark = 1; /* non zero needed */
+ int wm_intr_value;
+
+ 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;
-
- 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);
- }
+ int hwt, tid;
+
+ 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);
}
}
diff --git a/sys/mips/rmi/msgring.h b/sys/mips/rmi/msgring.h
index c55d0de..6110f5f 100644
--- a/sys/mips/rmi/msgring.h
+++ b/sys/mips/rmi/msgring.h
@@ -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, int *code, int *stid,
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);
diff --git a/sys/mips/rmi/rmi_mips_exts.h b/sys/mips/rmi/rmi_mips_exts.h
index 72a38ce..9f5f6aa 100644
--- a/sys/mips/rmi/rmi_mips_exts.h
+++ b/sys/mips/rmi/rmi_mips_exts.h
@@ -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[];
diff --git a/sys/mips/rmi/xlr_machdep.c b/sys/mips/rmi/xlr_machdep.c
index 8728555..b34955d 100644
--- a/sys/mips/rmi/xlr_machdep.c
+++ b/sys/mips/rmi/xlr_machdep.c
@@ -596,7 +596,6 @@ platform_ipi_send(int cpuid)
{
pic_send_ipi(xlr_cpuid_to_hwtid[cpuid], platform_ipi_intrnum());
-
}
void
OpenPOWER on IntegriCloud