All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai-core] insmod xeno_rtcan_mscan gets stuck on MPC5121
@ 2011-09-07  9:03 Fabrice Gasnier
  0 siblings, 0 replies; only message in thread
From: Fabrice Gasnier @ 2011-09-07  9:03 UTC (permalink / raw)
  To: xenomai

[-- Attachment #1: Type: text/plain, Size: 1635 bytes --]

Dear all,

I'm currently evaluating xeno_rtcan_mscan driver on a phyCORE-MPC5121e.
I'm using linux-2.6.33.5 with Xenomai 2.5.6 
(adeos-ipipe-2.6.33.5-powerpc-2.10-03.patch).
Kernel has been configured with CONFIG_XENO_DRIVERS_CAN_MSCAN

Everything is ok until module is been loaded: insmod xeno_can_mscan hangs.
$insmod xeno_can.ko
RT-Socket-CAN 0.90.2 - (C) 2006 RT-Socket-CAN Development Team
$insmod xeno_can_mscan.ko
=> get stuck then

I went through module source code. Module loading is stuck in an endless 
loop in "rtcan_mscan_mode_stop" routine in 
ksrc/drivers/can/mscan/rtcan_mscan.c. The driver expects can controller 
to acknowledge a sleep and init command.
Having a look at native linux source code shows a different way to 
initialize CAN controller. A strategy is being implemented to avoid 
being stuck here.

I've come to the attached patch to replicate native linux kernel module 
behaviour regarding this init routine. Insterting patched module shows:
rtcan_mscan: device failed to enter sleep mode. We proceed anyhow.
rtcan: registered rtcan0
rtcan_mscan 80001300.mscan: MSCAN at 0xd314c300, irq 23, clock 66660000 Hz
rtcan_mscan: device failed to enter sleep mode. We proceed anyhow.
rtcan: registered rtcan1
rtcan_mscan 80001380.mscan: MSCAN at 0xd3154380, irq 24, clock 66660000 Hz

I've tested it successfully: i'm now able to load driver and to use it 
(using canfestival for instance).
I'm not sure about the cause of this behaviour (e.g. chip revision, or 
something else ?) but i'm quite confident it solves this issue.

Could someone advise on the modifications brought here?

Thanks in advance
Fabrice


[-- Attachment #2: 001_fix_rtcan_mscan_mpc5121.patch --]
[-- Type: text/x-patch, Size: 2768 bytes --]

Index: xenomai-2.5.6/ksrc/drivers/can/mscan/rtcan_mscan.c
===================================================================
--- xenomai-2.5.6.orig/ksrc/drivers/can/mscan/rtcan_mscan.c	2011-09-06 11:19:29.000000000 +0200
+++ xenomai-2.5.6/ksrc/drivers/can/mscan/rtcan_mscan.c	2011-09-06 14:20:03.000000000 +0200
@@ -40,6 +40,8 @@
 #include "rtcan_mscan_regs.h"
 #include "rtcan_mscan.h"
 
+#define MSCAN_SET_MODE_RETRIES	255
+
 /**
  *  Reception Interrupt handler
  *
@@ -294,31 +296,54 @@
 				 rtdm_lockctx_t *lock_ctx)
 {
 	int ret = 0;
-	int rinit = 0;
+	int i=0;
 	can_state_t state;
 	struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
-	u8 reg;
+	u8 canctl1;
 
 	state = dev->state;
 	/* If controller is not operating anyway, go out */
 	if (!CAN_STATE_OPERATING(state))
 		goto out;
 
-	/* Switch to sleep mode */
-	setbits8(&regs->canctl0, MSCAN_SLPRQ);
-	setbits8(&regs->canctl0, MSCAN_INITRQ);
-
-	reg = in_8(&regs->canctl1);
-	while (!(reg & MSCAN_SLPAK) ||
-	       !(reg & MSCAN_INITAK)) {
-		if (likely(lock_ctx != NULL))
-			rtdm_lock_put_irqrestore(&dev->device_lock, *lock_ctx);
-		/* Busy sleep 1 microsecond */
-		rtdm_task_busy_sleep(1000);
-		if (likely(lock_ctx != NULL))
-			rtdm_lock_get_irqsave(&dev->device_lock, *lock_ctx);
-		rinit++;
-		reg = in_8(&regs->canctl1);
+	canctl1 = in_8(&regs->canctl1);
+	if (!(canctl1 & MSCAN_SLPAK)) {
+		setbits8(&regs->canctl0, MSCAN_SLPRQ);
+		for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
+			if (in_8(&regs->canctl1) & MSCAN_SLPAK)
+				break;
+			if (likely(lock_ctx != NULL))
+				rtdm_lock_put_irqrestore(&dev->device_lock, *lock_ctx);
+			/* Busy sleep 1 microsecond */
+			rtdm_task_busy_sleep(1000);
+			if (likely(lock_ctx != NULL))
+				rtdm_lock_get_irqsave(&dev->device_lock, *lock_ctx);
+		}
+		/*
+		 * The mscan controller will fail to enter sleep mode,
+		 * while there are irregular activities on bus, like
+		 * somebody keeps retransmitting. This behavior is
+		 * undocumented and seems to differ between mscan built
+		 * in mpc5200b and mpc5200. We proceed in that case,
+		 * since otherwise the slprq will be kept set and the
+		 * controller will get stuck. NOTE: INITRQ or CSWAI
+		 * will abort all active transmit actions, if still
+		 * any, at once.
+		 */
+		if (i >= MSCAN_SET_MODE_RETRIES)
+			rtdm_printk("rtcan_mscan: device failed to enter sleep mode. "
+				    "We proceed anyhow.\n");
+		else
+			dev->state = CAN_STATE_SLEEPING;
+	}
+	if (!(canctl1 & MSCAN_INITAK)) {
+		setbits8(&regs->canctl0, MSCAN_INITRQ);
+		for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
+			if (in_8(&regs->canctl1) & MSCAN_INITAK)
+				break;
+		}
+		if (i >= MSCAN_SET_MODE_RETRIES)
+			ret = -ENODEV;
 	}
 
 	/* Volatile state could have changed while we slept busy. */

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2011-09-07  9:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-07  9:03 [Xenomai-core] insmod xeno_rtcan_mscan gets stuck on MPC5121 Fabrice Gasnier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.