]> git.karo-electronics.de Git - linux-beck.git/commitdiff
can: flexcan: Consolidate and unify state change handling
authorAndri Yngvason <andri.yngvason@marel.com>
Wed, 3 Dec 2014 17:54:15 +0000 (17:54 +0000)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Sun, 7 Dec 2014 20:22:10 +0000 (21:22 +0100)
Replacing error state change handling with the new mechanism.

Signed-off-by: Andri Yngvason <andri.yngvason@marel.com>
Acked-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/flexcan.c

index 60f86bd0434af7cd93c394677809a3e60932d768..dde05486bc9917fb88126b79933c53d5868bd0e7 100644 (file)
@@ -577,98 +577,30 @@ static int flexcan_poll_bus_err(struct net_device *dev, u32 reg_esr)
        return 1;
 }
 
-static void do_state(struct net_device *dev,
-                    struct can_frame *cf, enum can_state new_state)
-{
-       struct flexcan_priv *priv = netdev_priv(dev);
-       struct can_berr_counter bec;
-
-       __flexcan_get_berr_counter(dev, &bec);
-
-       switch (priv->can.state) {
-       case CAN_STATE_ERROR_ACTIVE:
-               /*
-                * from: ERROR_ACTIVE
-                * to  : ERROR_WARNING, ERROR_PASSIVE, BUS_OFF
-                * =>  : there was a warning int
-                */
-               if (new_state >= CAN_STATE_ERROR_WARNING &&
-                   new_state <= CAN_STATE_BUS_OFF) {
-                       netdev_dbg(dev, "Error Warning IRQ\n");
-                       priv->can.can_stats.error_warning++;
-
-                       cf->can_id |= CAN_ERR_CRTL;
-                       cf->data[1] = (bec.txerr > bec.rxerr) ?
-                               CAN_ERR_CRTL_TX_WARNING :
-                               CAN_ERR_CRTL_RX_WARNING;
-               }
-       case CAN_STATE_ERROR_WARNING:   /* fallthrough */
-               /*
-                * from: ERROR_ACTIVE, ERROR_WARNING
-                * to  : ERROR_PASSIVE, BUS_OFF
-                * =>  : error passive int
-                */
-               if (new_state >= CAN_STATE_ERROR_PASSIVE &&
-                   new_state <= CAN_STATE_BUS_OFF) {
-                       netdev_dbg(dev, "Error Passive IRQ\n");
-                       priv->can.can_stats.error_passive++;
-
-                       cf->can_id |= CAN_ERR_CRTL;
-                       cf->data[1] = (bec.txerr > bec.rxerr) ?
-                               CAN_ERR_CRTL_TX_PASSIVE :
-                               CAN_ERR_CRTL_RX_PASSIVE;
-               }
-               break;
-       case CAN_STATE_BUS_OFF:
-               netdev_err(dev, "BUG! "
-                          "hardware recovered automatically from BUS_OFF\n");
-               break;
-       default:
-               break;
-       }
-
-       /* process state changes depending on the new state */
-       switch (new_state) {
-       case CAN_STATE_ERROR_WARNING:
-               netdev_dbg(dev, "Error Warning\n");
-               cf->can_id |= CAN_ERR_CRTL;
-               cf->data[1] = (bec.txerr > bec.rxerr) ?
-                       CAN_ERR_CRTL_TX_WARNING :
-                       CAN_ERR_CRTL_RX_WARNING;
-               break;
-       case CAN_STATE_ERROR_ACTIVE:
-               netdev_dbg(dev, "Error Active\n");
-               cf->can_id |= CAN_ERR_PROT;
-               cf->data[2] = CAN_ERR_PROT_ACTIVE;
-               break;
-       case CAN_STATE_BUS_OFF:
-               cf->can_id |= CAN_ERR_BUSOFF;
-               can_bus_off(dev);
-               break;
-       default:
-               break;
-       }
-}
-
 static int flexcan_poll_state(struct net_device *dev, u32 reg_esr)
 {
        struct flexcan_priv *priv = netdev_priv(dev);
        struct sk_buff *skb;
        struct can_frame *cf;
-       enum can_state new_state;
+       enum can_state new_state = 0, rx_state = 0, tx_state = 0;
        int flt;
+       struct can_berr_counter bec;
 
        flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK;
        if (likely(flt == FLEXCAN_ESR_FLT_CONF_ACTIVE)) {
-               if (likely(!(reg_esr & (FLEXCAN_ESR_TX_WRN |
-                                       FLEXCAN_ESR_RX_WRN))))
-                       new_state = CAN_STATE_ERROR_ACTIVE;
-               else
-                       new_state = CAN_STATE_ERROR_WARNING;
-       } else if (unlikely(flt == FLEXCAN_ESR_FLT_CONF_PASSIVE))
+               tx_state = unlikely(reg_esr & FLEXCAN_ESR_TX_WRN) ?
+                          CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
+               rx_state = unlikely(reg_esr & FLEXCAN_ESR_RX_WRN) ?
+                          CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
+               new_state = max(tx_state, rx_state);
+       } else if (unlikely(flt == FLEXCAN_ESR_FLT_CONF_PASSIVE)) {
+               __flexcan_get_berr_counter(dev, &bec);
                new_state = CAN_STATE_ERROR_PASSIVE;
-       else
+               rx_state = bec.rxerr >= bec.txerr ? new_state : 0;
+               tx_state = bec.rxerr <= bec.txerr ? new_state : 0;
+       } else {
                new_state = CAN_STATE_BUS_OFF;
+       }
 
        /* state hasn't changed */
        if (likely(new_state == priv->can.state))
@@ -678,8 +610,11 @@ static int flexcan_poll_state(struct net_device *dev, u32 reg_esr)
        if (unlikely(!skb))
                return 0;
 
-       do_state(dev, cf, new_state);
-       priv->can.state = new_state;
+       can_change_state(dev, cf, tx_state, rx_state);
+
+       if (unlikely(new_state == CAN_STATE_BUS_OFF))
+               can_bus_off(dev);
+
        netif_receive_skb(skb);
 
        dev->stats.rx_packets++;