All of lore.kernel.org
 help / color / mirror / Atom feed
From: Fabrice Gasnier <fabrice.gasnier@domain.hid>
To: xenomai@xenomai.org
Subject: [Xenomai-core] insmod xeno_rtcan_mscan gets stuck on MPC5121
Date: Wed, 07 Sep 2011 11:03:18 +0200	[thread overview]
Message-ID: <4E673356.2090306@domain.hid> (raw)

[-- 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. */

                 reply	other threads:[~2011-09-07  9:03 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4E673356.2090306@domain.hid \
    --to=fabrice.gasnier@domain.hid \
    --cc=xenomai@xenomai.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.