On Thu, Nov 12, 2009 at 02:17:21PM +0100, Wolfgang Grandegger wrote: > Fine for me. But how do we select the clocks for the MSCAN on the > MPC5200? Currently it's implemented as shown below: > > if (of_get_property(np, "clock-ipb", NULL)) > clock_src = MSCAN_CLKSRC_BUS; > else > clock_src = MSCAN_CLKSRC_XTAL; > > But we should have something compatible with the MPC512x, e.g.: > > fsl,mscan-clock-source = "clk-ipb".
Hmmm, will try to come up with something tomorrow. > Marc has implemented it for the AT91 CAN. Search for "restart_ms" and > "RESTARTED" in "at_can.c" to understand what I'm speaking about. Okay, I talked with him and had a try. Could you say if it at least looks not totally wrong? If it is at least somewhat the right direction? Then, just the clocking-property is left for tomorrow and I will post the final patch and my branch. Regards (and thanks!), Wolfram Subject: [PATCH] [RFC] net/can/mscan: add proper BUS_OFF handling As hardware recovery can't be switched off, copy the mechanism from at91_can. Signed-off-by: Wolfram Sang <[email protected]> --- drivers/net/can/mscan/mscan.c | 54 +++++++++++++++++++++++++++++----------- 1 files changed, 39 insertions(+), 15 deletions(-) diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 71e4233..d734d8b 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -202,6 +202,16 @@ static int mscan_start(struct net_device *dev) return 0; } +static void mscan_stop(struct net_device *dev) +{ + struct mscan_priv *priv = netdev_priv(dev); + struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + + out_8(®s->cantier, 0); + out_8(®s->canrier, 0); + mscan_set_mode(dev, MSCAN_INIT_MODE); +} + static int mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct can_frame *frame = (struct can_frame *)skb->data; @@ -289,21 +299,20 @@ static int mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static inline int check_set_state(struct net_device *dev, u8 canrflg) +/* This function returns the old state to see where we came from */ +static enum can_state check_set_state(struct net_device *dev, u8 canrflg) { struct mscan_priv *priv = netdev_priv(dev); - enum can_state state; - int ret = 0; + enum can_state state, old_state = priv->can.state; - if (!(canrflg & MSCAN_CSCIF) || priv->can.state > CAN_STATE_BUS_OFF) - return 0; + if (!(canrflg & MSCAN_CSCIF) || old_state > CAN_STATE_BUS_OFF) + return old_state; state = state_map[max(MSCAN_STATE_RX(canrflg), MSCAN_STATE_TX(canrflg))]; - if (priv->can.state < state) - ret = 1; + priv->can.state = state; - return ret; + return old_state; } static int mscan_rx_poll(struct napi_struct *napi, int quota) @@ -312,6 +321,7 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota) struct net_device *dev = napi->dev; struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; struct net_device_stats *stats = &dev->stats; + enum can_state old_state; int npackets = 0; int ret = 1; struct sk_buff *skb; @@ -376,7 +386,17 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota) } else frame->data[1] = 0; - if (check_set_state(dev, canrflg)) { + old_state = check_set_state(dev, canrflg); + /* State out of BUS_OFF */ + if (old_state == CAN_STATE_BUS_OFF + && priv->can.state < old_state) { + frame->can_id |= CAN_ERR_RESTARTED; + priv->can.can_stats.restarts++; + netif_carrier_on(dev); + netif_wake_queue(dev); + } + /* State got worse */ + if (old_state < priv->can.state) { switch (priv->can.state) { case CAN_STATE_ERROR_WARNING: frame->can_id |= CAN_ERR_CRTL; @@ -401,7 +421,15 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota) break; case CAN_STATE_BUS_OFF: frame->can_id |= CAN_ERR_BUSOFF; - can_bus_off(dev); + netif_carrier_off(dev); + priv->can.can_stats.bus_off++; + + /* turn off chip, if restart is disabled */ + if (!priv->can.restart_ms) { + mscan_stop(dev); + priv->can.state = CAN_STATE_BUS_OFF; + return 0; // FIXME: What to return here? + } break; default: break; @@ -578,14 +606,10 @@ static int mscan_open(struct net_device *dev) static int mscan_close(struct net_device *dev) { struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; netif_stop_queue(dev); napi_disable(&priv->napi); - - out_8(®s->cantier, 0); - out_8(®s->canrier, 0); - mscan_set_mode(dev, MSCAN_INIT_MODE); + mscan_stop(dev); close_candev(dev); free_irq(dev->irq, dev); priv->open_time = 0; -- Pengutronix e.K. | Wolfram Sang | Industrial Linux Solutions | http://www.pengutronix.de/ |
signature.asc
Description: Digital signature
_______________________________________________ Socketcan-core mailing list [email protected] https://lists.berlios.de/mailman/listinfo/socketcan-core
