aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Kleine-Budde <mkl@pengutronix.de>2023-05-01 18:14:41 +0200
committerMarc Kleine-Budde <mkl@pengutronix.de>2023-10-05 21:46:56 +0200
commitaa3f5d935cbb302dce89e8f278f6e8a3e2ecea18 (patch)
tree0d3b1d7776dd766af070c16f6c4548052f315121
parent864c6f07d3c4a4ed40fca932d9aec17607c6cc96 (diff)
downloadnf-next-aa3f5d935cbb302dce89e8f278f6e8a3e2ecea18.tar.gz
can: at91_can: at91_poll_err(): increase stats even if no quota left or OOM
at91_poll_err() allocates a can error SKB, to inform the user space about the CAN error. Then it fills the SKB with information the error information and increases the net device error stats. In case no SBK can be allocated (e.g. due to an OOM) or the NAPI quota is 0 the function is left early and no stats are updated. This is not helpful to the user, as there is no information about the faulty CAN bus. Increase the error stats even if no quota is left or no SKB can be allocated. While there treat No-Acknowledgment as a bus error, too. Link: https://lore.kernel.org/all/20231005-at91_can-rx_offload-v2-18-9987d53600e0@pengutronix.de Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r--drivers/net/can/at91_can.c71
1 files changed, 38 insertions, 33 deletions
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 2071011ee81271..5b611657b41fa2 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;