[PATCH 42/44] leon, grspw_pkt: SMP support

Daniel Hellstrom daniel at gaisler.com
Fri Mar 3 14:57:15 UTC 2017


The driver already was developed with SMP in mind however SMP was
disabled waiting for final fixups and testing.

The new function to control the affinity of the ISR was added
but does not work for now since the LEON BSP does not reroute
IRQs between CPUs during run-time:
 grspw_isr_affinity()
---
 c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h |  7 ++
 c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c     | 82 +++++++++++++----------
 2 files changed, 53 insertions(+), 36 deletions(-)

diff --git a/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h b/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h
index d14d434..a74a7c9 100644
--- a/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h
+++ b/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h
@@ -431,6 +431,13 @@ enum grspw_worktask_ev {
  */
 extern void grspw_work_event(enum grspw_worktask_ev ev, unsigned int msg);
 
+#ifdef RTEMS_SMP
+/* Set ISR interrupt affinity. The LEON IRQCtrl requires that the cpumask shall
+ * always have one bit set.
+ */
+extern int grspw_isr_affinity(void *d, const cpu_set_t *cpus);
+#endif
+
 extern int grspw_dev_count(void);
 extern void *grspw_open(int dev_no);
 extern int grspw_close(void *d);
diff --git a/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c b/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
index ce5b732..e44ca56 100644
--- a/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
+++ b/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
@@ -28,33 +28,38 @@
 #include <drvmgr/ambapp_bus.h>
 #include <bsp/grspw_pkt.h>
 
-/* This driver has been prepared for SMP operation however never tested 
- * on a SMP system - use on your own risk.
+/* Use interrupt lock privmitives compatible with SMP defined in
+ * RTEMS 4.11.99 and higher.
  */
-#ifdef RTEMS_HAS_SMP
+#if (((__RTEMS_MAJOR__ << 16) | (__RTEMS_MINOR__ << 8) | __RTEMS_REVISION__) >= 0x040b63)
 
-#include <rtems/score/smplock.h> /* spin-lock */
+#include <rtems/score/isrlock.h> /* spin-lock */
 
-/* SPIN_LOCK() and SPIN_UNLOCK() NOT_IMPLEMENTED_BY_RTEMS. Use _IRQ version
- * to implement.
- */
-#define SPIN_DECLARE(name) SMP_lock_spinlock_simple_Control name
-#define SPIN_INIT(lock) _SMP_lock_spinlock_simple_Initialize(lock)
-#define SPIN_LOCK(lock, level) SPIN_LOCK_IRQ(lock, level)
-#define SPIN_LOCK_IRQ(lock, level) (level) = _SMP_lock_spinlock_simple_Obtain(lock)
-#define SPIN_UNLOCK(lock, level) SPIN_UNLOCK_IRQ(lock, level)
-#define SPIN_UNLOCK_IRQ(lock, level) _SMP_lock_spinlock_simple_Release(lock, level)
-#define IRQFLAGS_TYPE ISR_Level
+/* map via ISR lock: */
+#define SPIN_DECLARE(lock) ISR_LOCK_MEMBER(lock)
+#define SPIN_INIT(lock, name) _ISR_lock_Initialize(lock, name)
+#define SPIN_LOCK(lock, level) _ISR_lock_Acquire_inline(lock, &level)
+#define SPIN_LOCK_IRQ(lock, level) _ISR_lock_ISR_disable_and_acquire(lock, &level)
+#define SPIN_UNLOCK(lock, level) _ISR_lock_Release_inline(lock, &level)
+#define SPIN_UNLOCK_IRQ(lock, level) _ISR_lock_Release_and_ISR_enable(lock, &level)
+#define SPIN_IRQFLAGS(k) ISR_lock_Context k
+#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k)
 
 #else
 
+/* maintain sinlge-core compatibility with older versions of RTEMS: */
 #define SPIN_DECLARE(name)
-#define SPIN_INIT(lock)
+#define SPIN_INIT(lock, name)
 #define SPIN_LOCK(lock, level)
 #define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_disable(level)
 #define SPIN_UNLOCK(lock, level)
 #define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_enable(level)
-#define IRQFLAGS_TYPE rtems_interrupt_level
+#define SPIN_IRQFLAGS(k) rtems_interrupt_level k
+#define SPIN_ISR_IRQFLAGS(k)
+
+#ifdef RTEMS_SMP
+#error SMP mode not compatible with these interrupt lock primitives
+#endif
 
 #endif
 
@@ -542,7 +547,7 @@ void *grspw_open(int dev_no)
 	/* Initialize Spin-lock for GRSPW Device. This is to protect
 	 * CTRL and DMACTRL registers from ISR.
 	 */
-	SPIN_INIT(&priv->devlock);
+	SPIN_INIT(&priv->devlock, priv->devname);
 
 	priv->tcisr = NULL;
 	priv->tcisr_arg = NULL;
@@ -684,7 +689,7 @@ void grspw_addr_ctrl(void *d, struct grspw_addr_config *cfg)
 	struct grspw_priv *priv = d;
 	struct grspw_regs *regs = priv->regs;
 	unsigned int ctrl, nodeaddr;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 	int i;
 
 	if (!priv || !cfg)
@@ -786,7 +791,7 @@ void grspw_link_ctrl(void *d, int *options, int *stscfg, int *clkdiv)
 	struct grspw_priv *priv = d;
 	struct grspw_regs *regs = priv->regs;
 	unsigned int ctrl;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 
 	/* Write? */
 	if (clkdiv) {
@@ -831,7 +836,7 @@ void grspw_tc_tx(void *d)
 {
 	struct grspw_priv *priv = d;
 	struct grspw_regs *regs = priv->regs;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 
 	SPIN_LOCK_IRQ(&priv->devlock, irqflags);
 	REG_WRITE(&regs->ctrl, REG_READ(&regs->ctrl) | GRSPW_CTRL_TI);
@@ -843,7 +848,7 @@ void grspw_tc_ctrl(void *d, int *options)
 	struct grspw_priv *priv = d;
 	struct grspw_regs *regs = priv->regs;
 	unsigned int ctrl;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 
 	if (options == NULL)
 		return;
@@ -902,7 +907,7 @@ int grspw_ic_tickin(void *d, int ic)
 {
 	struct grspw_priv *priv = d;
 	struct grspw_regs *regs = priv->regs;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 	unsigned int icctrl, mask;
 
 	/* Prepare before turning off IRQ */
@@ -940,7 +945,7 @@ void grspw_ic_ctrl(void *d, unsigned int *options)
 	struct grspw_regs *regs = priv->regs;
 	unsigned int ctrl;
 	unsigned int icctrl;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 
 	if (options == NULL)
 		return;
@@ -1042,7 +1047,7 @@ int grspw_rmap_ctrl(void *d, int *options, int *dstkey)
 	struct grspw_priv *priv = d;
 	struct grspw_regs *regs = priv->regs;
 	unsigned int ctrl;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 
 	if (dstkey) {
 		if (*dstkey != -1)
@@ -1089,7 +1094,7 @@ int grspw_port_ctrl(void *d, int *port)
 	struct grspw_priv *priv = d;
 	struct grspw_regs *regs = priv->regs;
 	unsigned int ctrl;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 
 	if (port == NULL)
 		return -1;
@@ -1226,7 +1231,7 @@ STATIC int grspw_rx_schedule_ready(struct grspw_dma_priv *dma)
 	struct grspw_rxring *curr_bd;
 	struct grspw_pkt *curr_pkt, *last_pkt;
 	struct grspw_list lst;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 
 	/* Is Ready Q empty? */
 	if (grspw_list_is_empty(&dma->ready))
@@ -1440,7 +1445,7 @@ STATIC int grspw_tx_schedule_send(struct grspw_dma_priv *dma)
 	struct grspw_txring *curr_bd;
 	struct grspw_pkt *curr_pkt, *last_pkt;
 	struct grspw_list lst;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 
 	/* Is Ready Q empty? */
 	if (grspw_list_is_empty(&dma->send))
@@ -1844,7 +1849,7 @@ unsigned int grspw_dma_enable_int(void *c, int rxtx, int force)
 	struct grspw_dma_priv *dma = c;
 	int rc = 0;
 	unsigned int ctrl, ctrl_old;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 
 	SPIN_LOCK_IRQ(&dma->core->devlock, irqflags);
 	if (dma->started == 0) {
@@ -2438,7 +2443,7 @@ int grspw_dma_start(void *c)
 	struct grspw_dma_priv *dma = c;
 	struct grspw_dma_regs *dregs = dma->regs;
 	unsigned int ctrl;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 
 	if (dma->started)
 		return 0;
@@ -2506,15 +2511,15 @@ int grspw_dma_start(void *c)
 
 STATIC void grspw_dma_stop_locked(struct grspw_dma_priv *dma)
 {
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 
 	if (dma->started == 0)
 		return;
 	dma->started = 0;
 
-	SPIN_LOCK_IRQ(&priv->devlock, irqflags);
+	SPIN_LOCK_IRQ(&dma->core->devlock, irqflags);
 	grspw_hw_dma_stop(dma);
-	SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
+	SPIN_UNLOCK_IRQ(&dma->core->devlock, irqflags);
 
 	/* From here no more packets will be sent, however
 	 * there may still exist scheduled packets that has been
@@ -2747,9 +2752,7 @@ STATIC void grspw_isr(void *data)
 	unsigned int rxirq, rxack, intto;
 	int i, handled = 0, call_user_int_isr;
 	unsigned int message = WORK_NONE, dma_en;
-#ifdef RTEMS_HAS_SMP
-	IRQFLAGS_TYPE irqflags;
-#endif
+	SPIN_ISR_IRQFLAGS(irqflags);
 
 	/* Get Status from Hardware */
 	stat = REG_READ(&priv->regs->status);
@@ -2959,7 +2962,7 @@ STATIC void grspw_hw_stop(struct grspw_priv *priv)
 {
 	int i;
 	unsigned int ctrl;
-	IRQFLAGS_TYPE irqflags;
+	SPIN_IRQFLAGS(irqflags);
 
 	SPIN_LOCK_IRQ(&priv->devlock, irqflags);
 
@@ -3282,6 +3285,13 @@ void grspw_work_cfg(void *d, struct grspw_work_config *wc)
 	priv->wc = *wc;
 }
 
+#ifdef RTEMS_SMP
+int grspw_isr_affinity(void *d, const cpu_set_t *cpus)
+{
+	return -1; /* BSP support only static configured IRQ affinity */
+}
+#endif
+
 static int grspw_common_init(void)
 {
 	if (grspw_initialized == 1)
-- 
2.7.4



More information about the devel mailing list