aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
authorAndri Yngvason <andri.yngvason@marel.com>2014-12-03 12:54:15 -0500
committerMarc Kleine-Budde <mkl@pengutronix.de>2014-12-07 15:22:10 -0500
commit71a3aedce6b37318d0e38676681dff179ec42874 (patch)
treeec12182e4fae48fa45bd93548f74fdf03055120f /drivers/net/can
parentb12a43e6dd0f201b81f4c1a9654f30d54c4e6838 (diff)
can: flexcan: Consolidate and unify state change handling
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>
Diffstat (limited to 'drivers/net/can')
-rw-r--r--drivers/net/can/flexcan.c101
1 files changed, 18 insertions, 83 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 60f86bd0434a..dde05486bc99 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -577,98 +577,30 @@ static int flexcan_poll_bus_err(struct net_device *dev, u32 reg_esr)
577 return 1; 577 return 1;
578} 578}
579 579
580static void do_state(struct net_device *dev,
581 struct can_frame *cf, enum can_state new_state)
582{
583 struct flexcan_priv *priv = netdev_priv(dev);
584 struct can_berr_counter bec;
585
586 __flexcan_get_berr_counter(dev, &bec);
587
588 switch (priv->can.state) {
589 case CAN_STATE_ERROR_ACTIVE:
590 /*
591 * from: ERROR_ACTIVE
592 * to : ERROR_WARNING, ERROR_PASSIVE, BUS_OFF
593 * => : there was a warning int
594 */
595 if (new_state >= CAN_STATE_ERROR_WARNING &&
596 new_state <= CAN_STATE_BUS_OFF) {
597 netdev_dbg(dev, "Error Warning IRQ\n");
598 priv->can.can_stats.error_warning++;
599
600 cf->can_id |= CAN_ERR_CRTL;
601 cf->data[1] = (bec.txerr > bec.rxerr) ?
602 CAN_ERR_CRTL_TX_WARNING :
603 CAN_ERR_CRTL_RX_WARNING;
604 }
605 case CAN_STATE_ERROR_WARNING: /* fallthrough */
606 /*
607 * from: ERROR_ACTIVE, ERROR_WARNING
608 * to : ERROR_PASSIVE, BUS_OFF
609 * => : error passive int
610 */
611 if (new_state >= CAN_STATE_ERROR_PASSIVE &&
612 new_state <= CAN_STATE_BUS_OFF) {
613 netdev_dbg(dev, "Error Passive IRQ\n");
614 priv->can.can_stats.error_passive++;
615
616 cf->can_id |= CAN_ERR_CRTL;
617 cf->data[1] = (bec.txerr > bec.rxerr) ?
618 CAN_ERR_CRTL_TX_PASSIVE :
619 CAN_ERR_CRTL_RX_PASSIVE;
620 }
621 break;
622 case CAN_STATE_BUS_OFF:
623 netdev_err(dev, "BUG! "
624 "hardware recovered automatically from BUS_OFF\n");
625 break;
626 default:
627 break;
628 }
629
630 /* process state changes depending on the new state */
631 switch (new_state) {
632 case CAN_STATE_ERROR_WARNING:
633 netdev_dbg(dev, "Error Warning\n");
634 cf->can_id |= CAN_ERR_CRTL;
635 cf->data[1] = (bec.txerr > bec.rxerr) ?
636 CAN_ERR_CRTL_TX_WARNING :
637 CAN_ERR_CRTL_RX_WARNING;
638 break;
639 case CAN_STATE_ERROR_ACTIVE:
640 netdev_dbg(dev, "Error Active\n");
641 cf->can_id |= CAN_ERR_PROT;
642 cf->data[2] = CAN_ERR_PROT_ACTIVE;
643 break;
644 case CAN_STATE_BUS_OFF:
645 cf->can_id |= CAN_ERR_BUSOFF;
646 can_bus_off(dev);
647 break;
648 default:
649 break;
650 }
651}
652
653static int flexcan_poll_state(struct net_device *dev, u32 reg_esr) 580static int flexcan_poll_state(struct net_device *dev, u32 reg_esr)
654{ 581{
655 struct flexcan_priv *priv = netdev_priv(dev); 582 struct flexcan_priv *priv = netdev_priv(dev);
656 struct sk_buff *skb; 583 struct sk_buff *skb;
657 struct can_frame *cf; 584 struct can_frame *cf;
658 enum can_state new_state; 585 enum can_state new_state = 0, rx_state = 0, tx_state = 0;
659 int flt; 586 int flt;
587 struct can_berr_counter bec;
660 588
661 flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK; 589 flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK;
662 if (likely(flt == FLEXCAN_ESR_FLT_CONF_ACTIVE)) { 590 if (likely(flt == FLEXCAN_ESR_FLT_CONF_ACTIVE)) {
663 if (likely(!(reg_esr & (FLEXCAN_ESR_TX_WRN | 591 tx_state = unlikely(reg_esr & FLEXCAN_ESR_TX_WRN) ?
664 FLEXCAN_ESR_RX_WRN)))) 592 CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
665 new_state = CAN_STATE_ERROR_ACTIVE; 593 rx_state = unlikely(reg_esr & FLEXCAN_ESR_RX_WRN) ?
666 else 594 CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
667 new_state = CAN_STATE_ERROR_WARNING; 595 new_state = max(tx_state, rx_state);
668 } else if (unlikely(flt == FLEXCAN_ESR_FLT_CONF_PASSIVE)) 596 } else if (unlikely(flt == FLEXCAN_ESR_FLT_CONF_PASSIVE)) {
597 __flexcan_get_berr_counter(dev, &bec);
669 new_state = CAN_STATE_ERROR_PASSIVE; 598 new_state = CAN_STATE_ERROR_PASSIVE;
670 else 599 rx_state = bec.rxerr >= bec.txerr ? new_state : 0;
600 tx_state = bec.rxerr <= bec.txerr ? new_state : 0;
601 } else {
671 new_state = CAN_STATE_BUS_OFF; 602 new_state = CAN_STATE_BUS_OFF;
603 }
672 604
673 /* state hasn't changed */ 605 /* state hasn't changed */
674 if (likely(new_state == priv->can.state)) 606 if (likely(new_state == priv->can.state))
@@ -678,8 +610,11 @@ static int flexcan_poll_state(struct net_device *dev, u32 reg_esr)
678 if (unlikely(!skb)) 610 if (unlikely(!skb))
679 return 0; 611 return 0;
680 612
681 do_state(dev, cf, new_state); 613 can_change_state(dev, cf, tx_state, rx_state);
682 priv->can.state = new_state; 614
615 if (unlikely(new_state == CAN_STATE_BUS_OFF))
616 can_bus_off(dev);
617
683 netif_receive_skb(skb); 618 netif_receive_skb(skb);
684 619
685 dev->stats.rx_packets++; 620 dev->stats.rx_packets++;