diff options
Diffstat (limited to 'drivers/net/can/at91_can.c')
-rw-r--r-- | drivers/net/can/at91_can.c | 71 |
1 files changed, 38 insertions, 33 deletions
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 2071011ee812..5b611657b41f 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -753,59 +753,64 @@ static int at91_poll_rx(struct net_device *dev, int quota) static int at91_poll_err(struct net_device *dev, int quota, u32 reg_sr) { + struct net_device_stats *stats = &dev->stats; struct at91_priv *priv = netdev_priv(dev); struct sk_buff *skb; - struct can_frame *cf; + struct can_frame *cf = NULL; - if (quota == 0) - return 0; + priv->can.can_stats.bus_error++; - skb = alloc_can_err_skb(dev, &cf); - if (unlikely(!skb)) - return 0; + if (quota) { + skb = alloc_can_err_skb(dev, &cf); + if (cf) + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + } - /* CRC error */ if (reg_sr & AT91_IRQ_CERR) { - netdev_dbg(dev, "CERR irq\n"); - dev->stats.rx_errors++; - priv->can.can_stats.bus_error++; - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + netdev_dbg(dev, "CRC error\n"); + + stats->rx_errors++; + if (cf) + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; } - /* Stuffing Error */ if (reg_sr & AT91_IRQ_SERR) { - netdev_dbg(dev, "SERR irq\n"); - dev->stats.rx_errors++; - priv->can.can_stats.bus_error++; - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; - cf->data[2] |= CAN_ERR_PROT_STUFF; + netdev_dbg(dev, "Stuff error\n"); + + stats->rx_errors++; + if (cf) + cf->data[2] |= CAN_ERR_PROT_STUFF; } - /* Acknowledgement Error */ if (reg_sr & AT91_IRQ_AERR) { - netdev_dbg(dev, "AERR irq\n"); - dev->stats.tx_errors++; - cf->can_id |= CAN_ERR_ACK; + netdev_dbg(dev, "NACK error\n"); + + stats->tx_errors++; + if (cf) { + cf->can_id |= CAN_ERR_ACK; + cf->data[2] |= CAN_ERR_PROT_TX; + } } - /* Form error */ if (reg_sr & AT91_IRQ_FERR) { - netdev_dbg(dev, "FERR irq\n"); - dev->stats.rx_errors++; - priv->can.can_stats.bus_error++; - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; - cf->data[2] |= CAN_ERR_PROT_FORM; + netdev_dbg(dev, "Format error\n"); + + stats->rx_errors++; + if (cf) + cf->data[2] |= CAN_ERR_PROT_FORM; } - /* Bit Error */ if (reg_sr & AT91_IRQ_BERR) { - netdev_dbg(dev, "BERR irq\n"); - dev->stats.tx_errors++; - priv->can.can_stats.bus_error++; - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; - cf->data[2] |= CAN_ERR_PROT_BIT; + netdev_dbg(dev, "Bit error\n"); + + stats->tx_errors++; + if (cf) + cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT; } + if (!cf) + return 0; + netif_receive_skb(skb); return 1; |