diff options
author | Ahmed S. Darwish <ahmed.darwish@valeo.com> | 2015-01-26 00:29:15 -0500 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2015-01-28 07:39:37 -0500 |
commit | 96d7f10634e66b27e23854c774fbcc0a2a654e82 (patch) | |
tree | f21dfcbeb5b0211caebc34f61df1a7929713ee6e /drivers/net/can/usb | |
parent | 3b07a444ee48a8081d2ed3f0abeeabd038404ac1 (diff) |
can: kvaser_usb: Consolidate and unify state change handling
Replace most of the can interface's state and error counters
handling with the new can-dev can_change_state() mechanism.
Suggested-by: Andri Yngvason <andri.yngvason@marel.com>
Signed-off-by: Ahmed S. Darwish <ahmed.darwish@valeo.com>
Acked-by: Andri Yngvason <andri.yngvason@marel.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can/usb')
-rw-r--r-- | drivers/net/can/usb/kvaser_usb.c | 113 |
1 files changed, 49 insertions, 64 deletions
diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index f57ce556c678..ddc29549aded 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c | |||
@@ -620,39 +620,44 @@ static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv) | |||
620 | } | 620 | } |
621 | 621 | ||
622 | static void kvaser_usb_rx_error_update_can_state(struct kvaser_usb_net_priv *priv, | 622 | static void kvaser_usb_rx_error_update_can_state(struct kvaser_usb_net_priv *priv, |
623 | const struct kvaser_usb_error_summary *es) | 623 | const struct kvaser_usb_error_summary *es, |
624 | struct can_frame *cf) | ||
624 | { | 625 | { |
625 | struct net_device_stats *stats; | 626 | struct net_device_stats *stats; |
626 | enum can_state new_state; | 627 | enum can_state cur_state, new_state, tx_state, rx_state; |
627 | |||
628 | stats = &priv->netdev->stats; | ||
629 | new_state = priv->can.state; | ||
630 | 628 | ||
631 | netdev_dbg(priv->netdev, "Error status: 0x%02x\n", es->status); | 629 | netdev_dbg(priv->netdev, "Error status: 0x%02x\n", es->status); |
632 | 630 | ||
633 | if (es->status & (M16C_STATE_BUS_OFF | M16C_STATE_BUS_RESET)) { | 631 | stats = &priv->netdev->stats; |
634 | priv->can.can_stats.bus_off++; | 632 | new_state = cur_state = priv->can.state; |
633 | |||
634 | if (es->status & (M16C_STATE_BUS_OFF | M16C_STATE_BUS_RESET)) | ||
635 | new_state = CAN_STATE_BUS_OFF; | 635 | new_state = CAN_STATE_BUS_OFF; |
636 | } else if (es->status & M16C_STATE_BUS_PASSIVE) { | 636 | else if (es->status & M16C_STATE_BUS_PASSIVE) |
637 | if (priv->can.state != CAN_STATE_ERROR_PASSIVE) | ||
638 | priv->can.can_stats.error_passive++; | ||
639 | new_state = CAN_STATE_ERROR_PASSIVE; | 637 | new_state = CAN_STATE_ERROR_PASSIVE; |
640 | } else if (es->status & M16C_STATE_BUS_ERROR) { | 638 | else if (es->status & M16C_STATE_BUS_ERROR) { |
641 | if ((priv->can.state < CAN_STATE_ERROR_WARNING) && | 639 | if ((es->txerr >= 256) || (es->rxerr >= 256)) |
642 | ((es->txerr >= 96) || (es->rxerr >= 96))) { | 640 | new_state = CAN_STATE_BUS_OFF; |
643 | priv->can.can_stats.error_warning++; | 641 | else if ((es->txerr >= 128) || (es->rxerr >= 128)) |
642 | new_state = CAN_STATE_ERROR_PASSIVE; | ||
643 | else if ((es->txerr >= 96) || (es->rxerr >= 96)) | ||
644 | new_state = CAN_STATE_ERROR_WARNING; | 644 | new_state = CAN_STATE_ERROR_WARNING; |
645 | } else if ((priv->can.state > CAN_STATE_ERROR_ACTIVE) && | 645 | else if (cur_state > CAN_STATE_ERROR_ACTIVE) |
646 | ((es->txerr < 96) && (es->rxerr < 96))) { | ||
647 | new_state = CAN_STATE_ERROR_ACTIVE; | 646 | new_state = CAN_STATE_ERROR_ACTIVE; |
648 | } | ||
649 | } | 647 | } |
650 | 648 | ||
651 | if (!es->status) | 649 | if (!es->status) |
652 | new_state = CAN_STATE_ERROR_ACTIVE; | 650 | new_state = CAN_STATE_ERROR_ACTIVE; |
653 | 651 | ||
652 | if (new_state != cur_state) { | ||
653 | tx_state = (es->txerr >= es->rxerr) ? new_state : 0; | ||
654 | rx_state = (es->txerr <= es->rxerr) ? new_state : 0; | ||
655 | |||
656 | can_change_state(priv->netdev, cf, tx_state, rx_state); | ||
657 | } | ||
658 | |||
654 | if (priv->can.restart_ms && | 659 | if (priv->can.restart_ms && |
655 | (priv->can.state >= CAN_STATE_BUS_OFF) && | 660 | (cur_state >= CAN_STATE_BUS_OFF) && |
656 | (new_state < CAN_STATE_BUS_OFF)) { | 661 | (new_state < CAN_STATE_BUS_OFF)) { |
657 | priv->can.can_stats.restarts++; | 662 | priv->can.can_stats.restarts++; |
658 | } | 663 | } |
@@ -664,18 +669,17 @@ static void kvaser_usb_rx_error_update_can_state(struct kvaser_usb_net_priv *pri | |||
664 | 669 | ||
665 | priv->bec.txerr = es->txerr; | 670 | priv->bec.txerr = es->txerr; |
666 | priv->bec.rxerr = es->rxerr; | 671 | priv->bec.rxerr = es->rxerr; |
667 | priv->can.state = new_state; | ||
668 | } | 672 | } |
669 | 673 | ||
670 | static void kvaser_usb_rx_error(const struct kvaser_usb *dev, | 674 | static void kvaser_usb_rx_error(const struct kvaser_usb *dev, |
671 | const struct kvaser_msg *msg) | 675 | const struct kvaser_msg *msg) |
672 | { | 676 | { |
673 | struct can_frame *cf; | 677 | struct can_frame *cf, tmp_cf = { .can_id = CAN_ERR_FLAG, .can_dlc = CAN_ERR_DLC }; |
674 | struct sk_buff *skb; | 678 | struct sk_buff *skb; |
675 | struct net_device_stats *stats; | 679 | struct net_device_stats *stats; |
676 | struct kvaser_usb_net_priv *priv; | 680 | struct kvaser_usb_net_priv *priv; |
677 | struct kvaser_usb_error_summary es = { }; | 681 | struct kvaser_usb_error_summary es = { }; |
678 | enum can_state old_state; | 682 | enum can_state old_state, new_state; |
679 | 683 | ||
680 | switch (msg->id) { | 684 | switch (msg->id) { |
681 | case CMD_CAN_ERROR_EVENT: | 685 | case CMD_CAN_ERROR_EVENT: |
@@ -715,59 +719,40 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, | |||
715 | stats = &priv->netdev->stats; | 719 | stats = &priv->netdev->stats; |
716 | 720 | ||
717 | /* Update all of the can interface's state and error counters before | 721 | /* Update all of the can interface's state and error counters before |
718 | * trying any skb allocation that can actually fail with -ENOMEM. | 722 | * trying any memory allocation that can actually fail with -ENOMEM. |
723 | * | ||
724 | * We send a temporary stack-allocated error can frame to | ||
725 | * can_change_state() for the very same reason. | ||
726 | * | ||
727 | * TODO: Split can_change_state() responsibility between updating the | ||
728 | * can interface's state and counters, and the setting up of can error | ||
729 | * frame ID and data to userspace. Remove stack allocation afterwards. | ||
719 | */ | 730 | */ |
720 | old_state = priv->can.state; | 731 | old_state = priv->can.state; |
721 | kvaser_usb_rx_error_update_can_state(priv, &es); | 732 | kvaser_usb_rx_error_update_can_state(priv, &es, &tmp_cf); |
733 | new_state = priv->can.state; | ||
722 | 734 | ||
723 | skb = alloc_can_err_skb(priv->netdev, &cf); | 735 | skb = alloc_can_err_skb(priv->netdev, &cf); |
724 | if (!skb) { | 736 | if (!skb) { |
725 | stats->rx_dropped++; | 737 | stats->rx_dropped++; |
726 | return; | 738 | return; |
727 | } | 739 | } |
728 | 740 | memcpy(cf, &tmp_cf, sizeof(*cf)); | |
729 | if (es.status & (M16C_STATE_BUS_OFF | M16C_STATE_BUS_RESET)) { | 741 | |
730 | cf->can_id |= CAN_ERR_BUSOFF; | 742 | if (new_state != old_state) { |
731 | 743 | if (es.status & | |
732 | if (!priv->can.restart_ms) | 744 | (M16C_STATE_BUS_OFF | M16C_STATE_BUS_RESET)) { |
733 | kvaser_usb_simple_msg_async(priv, CMD_STOP_CHIP); | 745 | if (!priv->can.restart_ms) |
734 | netif_carrier_off(priv->netdev); | 746 | kvaser_usb_simple_msg_async(priv, CMD_STOP_CHIP); |
735 | } else if (es.status & M16C_STATE_BUS_PASSIVE) { | 747 | netif_carrier_off(priv->netdev); |
736 | if (old_state != CAN_STATE_ERROR_PASSIVE) { | ||
737 | cf->can_id |= CAN_ERR_CRTL; | ||
738 | |||
739 | if (es.txerr || es.rxerr) | ||
740 | cf->data[1] = (es.txerr > es.rxerr) | ||
741 | ? CAN_ERR_CRTL_TX_PASSIVE | ||
742 | : CAN_ERR_CRTL_RX_PASSIVE; | ||
743 | else | ||
744 | cf->data[1] = CAN_ERR_CRTL_TX_PASSIVE | | ||
745 | CAN_ERR_CRTL_RX_PASSIVE; | ||
746 | } | ||
747 | } else if (es.status & M16C_STATE_BUS_ERROR) { | ||
748 | if ((old_state < CAN_STATE_ERROR_WARNING) && | ||
749 | ((es.txerr >= 96) || (es.rxerr >= 96))) { | ||
750 | cf->can_id |= CAN_ERR_CRTL; | ||
751 | cf->data[1] = (es.txerr > es.rxerr) | ||
752 | ? CAN_ERR_CRTL_TX_WARNING | ||
753 | : CAN_ERR_CRTL_RX_WARNING; | ||
754 | } else if ((old_state > CAN_STATE_ERROR_ACTIVE) && | ||
755 | ((es.txerr < 96) && (es.rxerr < 96))) { | ||
756 | cf->can_id |= CAN_ERR_PROT; | ||
757 | cf->data[2] = CAN_ERR_PROT_ACTIVE; | ||
758 | } | 748 | } |
759 | } | ||
760 | |||
761 | if (!es.status) { | ||
762 | cf->can_id |= CAN_ERR_PROT; | ||
763 | cf->data[2] = CAN_ERR_PROT_ACTIVE; | ||
764 | } | ||
765 | 749 | ||
766 | if (priv->can.restart_ms && | 750 | if (priv->can.restart_ms && |
767 | (old_state >= CAN_STATE_BUS_OFF) && | 751 | (old_state >= CAN_STATE_BUS_OFF) && |
768 | (priv->can.state < CAN_STATE_BUS_OFF)) { | 752 | (new_state < CAN_STATE_BUS_OFF)) { |
769 | cf->can_id |= CAN_ERR_RESTARTED; | 753 | cf->can_id |= CAN_ERR_RESTARTED; |
770 | netif_carrier_on(priv->netdev); | 754 | netif_carrier_on(priv->netdev); |
755 | } | ||
771 | } | 756 | } |
772 | 757 | ||
773 | if (es.error_factor) { | 758 | if (es.error_factor) { |