aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRamesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>2016-06-22 08:31:47 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2016-06-23 05:23:49 -0400
commit926f10359a69fa82f0ec022f3b54ca8a05ea8440 (patch)
tree6fa6237d5fa3de26bc712da9bc326ce9ec34c537
parent6f4c2eea353809fb85386d5ce17a30e37042847d (diff)
can: rcar_canfd: Add back-to-error-active support
As per Wolfgang G, all new drivers should support decreasing state transition(back-to-error-active). This patch adds this support. This driver configures the controller to halt on bus-off entry. Hence, when in error states less than bus off state, the TEC/REC counters are checked for lower state transition eligibility and action. Signed-off-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r--drivers/net/can/rcar/rcar_canfd.c76
1 files changed, 56 insertions, 20 deletions
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index 6bcc47408423..43cdd5544b0c 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -917,16 +917,17 @@ static void rcar_canfd_global_error(struct net_device *ndev)
917 rcar_canfd_write(priv->base, RCANFD_GERFL, 0); 917 rcar_canfd_write(priv->base, RCANFD_GERFL, 0);
918} 918}
919 919
920static void rcar_canfd_error(struct net_device *ndev) 920static void rcar_canfd_error(struct net_device *ndev, u32 cerfl,
921 u16 txerr, u16 rxerr)
921{ 922{
922 struct rcar_canfd_channel *priv = netdev_priv(ndev); 923 struct rcar_canfd_channel *priv = netdev_priv(ndev);
923 struct net_device_stats *stats = &ndev->stats; 924 struct net_device_stats *stats = &ndev->stats;
924 struct can_frame *cf; 925 struct can_frame *cf;
925 struct sk_buff *skb; 926 struct sk_buff *skb;
926 u32 cerfl, csts;
927 u32 txerr = 0, rxerr = 0;
928 u32 ch = priv->channel; 927 u32 ch = priv->channel;
929 928
929 netdev_dbg(ndev, "ch erfl %x txerr %u rxerr %u\n", cerfl, txerr, rxerr);
930
930 /* Propagate the error condition to the CAN stack */ 931 /* Propagate the error condition to the CAN stack */
931 skb = alloc_can_err_skb(ndev, &cf); 932 skb = alloc_can_err_skb(ndev, &cf);
932 if (!skb) { 933 if (!skb) {
@@ -934,15 +935,7 @@ static void rcar_canfd_error(struct net_device *ndev)
934 return; 935 return;
935 } 936 }
936 937
937 /* Channel error interrupt */ 938 /* Channel error interrupts */
938 cerfl = rcar_canfd_read(priv->base, RCANFD_CERFL(ch));
939 csts = rcar_canfd_read(priv->base, RCANFD_CSTS(ch));
940 txerr = RCANFD_CSTS_TECCNT(csts);
941 rxerr = RCANFD_CSTS_RECCNT(csts);
942
943 netdev_dbg(ndev, "ch erfl %x sts %x txerr %u rxerr %u\n",
944 cerfl, csts, txerr, rxerr);
945
946 if (cerfl & RCANFD_CERFL_BEF) { 939 if (cerfl & RCANFD_CERFL_BEF) {
947 netdev_dbg(ndev, "Bus error\n"); 940 netdev_dbg(ndev, "Bus error\n");
948 cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT; 941 cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
@@ -1032,8 +1025,9 @@ static void rcar_canfd_error(struct net_device *ndev)
1032 cf->data[2] |= CAN_ERR_PROT_OVERLOAD; 1025 cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
1033 } 1026 }
1034 1027
1035 /* Clear all channel error interrupts */ 1028 /* Clear channel error interrupts that are handled */
1036 rcar_canfd_write(priv->base, RCANFD_CERFL(ch), 0); 1029 rcar_canfd_write(priv->base, RCANFD_CERFL(ch),
1030 RCANFD_CERFL_ERR(~cerfl));
1037 stats->rx_packets++; 1031 stats->rx_packets++;
1038 stats->rx_bytes += cf->can_dlc; 1032 stats->rx_bytes += cf->can_dlc;
1039 netif_rx(skb); 1033 netif_rx(skb);
@@ -1098,12 +1092,12 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)
1098 1092
1099 /* Global error interrupts */ 1093 /* Global error interrupts */
1100 gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL); 1094 gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL);
1101 if (RCANFD_GERFL_ERR(gpriv, gerfl)) 1095 if (unlikely(RCANFD_GERFL_ERR(gpriv, gerfl)))
1102 rcar_canfd_global_error(ndev); 1096 rcar_canfd_global_error(ndev);
1103 1097
1104 /* Handle Rx interrupts */ 1098 /* Handle Rx interrupts */
1105 sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx)); 1099 sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx));
1106 if (sts & RCANFD_RFSTS_RFIF) { 1100 if (likely(sts & RCANFD_RFSTS_RFIF)) {
1107 if (napi_schedule_prep(&priv->napi)) { 1101 if (napi_schedule_prep(&priv->napi)) {
1108 /* Disable Rx FIFO interrupts */ 1102 /* Disable Rx FIFO interrupts */
1109 rcar_canfd_clear_bit(priv->base, 1103 rcar_canfd_clear_bit(priv->base,
@@ -1116,12 +1110,46 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)
1116 return IRQ_HANDLED; 1110 return IRQ_HANDLED;
1117} 1111}
1118 1112
1113static void rcar_canfd_state_change(struct net_device *ndev,
1114 u16 txerr, u16 rxerr)
1115{
1116 struct rcar_canfd_channel *priv = netdev_priv(ndev);
1117 struct net_device_stats *stats = &ndev->stats;
1118 enum can_state rx_state, tx_state, state = priv->can.state;
1119 struct can_frame *cf;
1120 struct sk_buff *skb;
1121
1122 /* Handle transition from error to normal states */
1123 if (txerr < 96 && rxerr < 96)
1124 state = CAN_STATE_ERROR_ACTIVE;
1125 else if (txerr < 128 && rxerr < 128)
1126 state = CAN_STATE_ERROR_WARNING;
1127
1128 if (state != priv->can.state) {
1129 netdev_dbg(ndev, "state: new %d, old %d: txerr %u, rxerr %u\n",
1130 state, priv->can.state, txerr, rxerr);
1131 skb = alloc_can_err_skb(ndev, &cf);
1132 if (!skb) {
1133 stats->rx_dropped++;
1134 return;
1135 }
1136 tx_state = txerr >= rxerr ? state : 0;
1137 rx_state = txerr <= rxerr ? state : 0;
1138
1139 can_change_state(ndev, cf, tx_state, rx_state);
1140 stats->rx_packets++;
1141 stats->rx_bytes += cf->can_dlc;
1142 netif_rx(skb);
1143 }
1144}
1145
1119static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id) 1146static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id)
1120{ 1147{
1121 struct rcar_canfd_global *gpriv = dev_id; 1148 struct rcar_canfd_global *gpriv = dev_id;
1122 struct net_device *ndev; 1149 struct net_device *ndev;
1123 struct rcar_canfd_channel *priv; 1150 struct rcar_canfd_channel *priv;
1124 u32 sts, cerfl, ch; 1151 u32 sts, ch, cerfl;
1152 u16 txerr, rxerr;
1125 1153
1126 /* Common FIFO is a per channel resource */ 1154 /* Common FIFO is a per channel resource */
1127 for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { 1155 for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) {
@@ -1130,13 +1158,21 @@ static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id)
1130 1158
1131 /* Channel error interrupts */ 1159 /* Channel error interrupts */
1132 cerfl = rcar_canfd_read(priv->base, RCANFD_CERFL(ch)); 1160 cerfl = rcar_canfd_read(priv->base, RCANFD_CERFL(ch));
1133 if (RCANFD_CERFL_ERR(cerfl)) 1161 sts = rcar_canfd_read(priv->base, RCANFD_CSTS(ch));
1134 rcar_canfd_error(ndev); 1162 txerr = RCANFD_CSTS_TECCNT(sts);
1163 rxerr = RCANFD_CSTS_RECCNT(sts);
1164 if (unlikely(RCANFD_CERFL_ERR(cerfl)))
1165 rcar_canfd_error(ndev, cerfl, txerr, rxerr);
1166
1167 /* Handle state change to lower states */
1168 if (unlikely((priv->can.state != CAN_STATE_ERROR_ACTIVE) &&
1169 (priv->can.state != CAN_STATE_BUS_OFF)))
1170 rcar_canfd_state_change(ndev, txerr, rxerr);
1135 1171
1136 /* Handle Tx interrupts */ 1172 /* Handle Tx interrupts */
1137 sts = rcar_canfd_read(priv->base, 1173 sts = rcar_canfd_read(priv->base,
1138 RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX)); 1174 RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX));
1139 if (sts & RCANFD_CFSTS_CFTXIF) 1175 if (likely(sts & RCANFD_CFSTS_CFTXIF))
1140 rcar_canfd_tx_done(ndev); 1176 rcar_canfd_tx_done(ndev);
1141 } 1177 }
1142 return IRQ_HANDLED; 1178 return IRQ_HANDLED;