svn commit: r213377 - in head/sys/mips/rmi: . dev/nlge dev/xlr

Jayachandran C. jchandra at FreeBSD.org
Sun Oct 3 04:33:59 UTC 2010


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


More information about the svn-src-all mailing list