diff options
author | Andri Yngvason <andri.yngvason@marel.com> | 2014-12-03 12:54:15 -0500 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2014-12-07 15:22:10 -0500 |
commit | 71a3aedce6b37318d0e38676681dff179ec42874 (patch) | |
tree | ec12182e4fae48fa45bd93548f74fdf03055120f /drivers/net/can | |
parent | b12a43e6dd0f201b81f4c1a9654f30d54c4e6838 (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.c | 101 |
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 | ||
580 | static 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 | |||
653 | static int flexcan_poll_state(struct net_device *dev, u32 reg_esr) | 580 | static 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++; |