diff options
author | jchandra <jchandra@FreeBSD.org> | 2010-10-03 04:33:58 +0000 |
---|---|---|
committer | jchandra <jchandra@FreeBSD.org> | 2010-10-03 04:33:58 +0000 |
commit | a5c3ee2add2670be35d89c08799c802d0cb68245 (patch) | |
tree | ee23fad591e434c716c121102dde918583cca4e9 /sys/mips/rmi | |
parent | dd58e025216b85edf1409ceb0856c5d4d2455c08 (diff) | |
download | FreeBSD-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.c | 48 | ||||
-rw-r--r-- | sys/mips/rmi/dev/nlge/if_nlge.c | 26 | ||||
-rw-r--r-- | sys/mips/rmi/dev/xlr/rge.c | 17 | ||||
-rw-r--r-- | sys/mips/rmi/fmn.c | 421 | ||||
-rw-r--r-- | sys/mips/rmi/msgring.h | 42 | ||||
-rw-r--r-- | sys/mips/rmi/rmi_mips_exts.h | 15 | ||||
-rw-r--r-- | sys/mips/rmi/xlr_machdep.c | 1 |
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 |