can: add CAN_ERR_CNT flag to notify availability of error counter
authorVincent Mailhol <mailhol.vincent@wanadoo.fr>
Tue, 19 Jul 2022 14:35:49 +0000 (23:35 +0900)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Wed, 20 Jul 2022 07:27:37 +0000 (09:27 +0200)
Add a dedicated flag in uapi/linux/can/error.h to notify the userland
that fields data[6] and data[7] of the CAN error frame were
respectively populated with the tx and rx error counters.

For all driver tree-wide, set up this flags whenever needed.

Link: https://lore.kernel.org/all/20220719143550.3681-12-mailhol.vincent@wanadoo.fr
Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
25 files changed:
drivers/net/can/c_can/c_can_main.c
drivers/net/can/cc770/cc770.c
drivers/net/can/ctucanfd/ctucanfd_base.c
drivers/net/can/grcan.c
drivers/net/can/ifi_canfd/ifi_canfd.c
drivers/net/can/janz-ican3.c
drivers/net/can/kvaser_pciefd.c
drivers/net/can/m_can/m_can.c
drivers/net/can/pch_can.c
drivers/net/can/peak_canfd/peak_canfd.c
drivers/net/can/rcar/rcar_can.c
drivers/net/can/rcar/rcar_canfd.c
drivers/net/can/sja1000/sja1000.c
drivers/net/can/slcan/slcan-core.c
drivers/net/can/spi/hi311x.c
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
drivers/net/can/sun4i_can.c
drivers/net/can/ti_hecc.c
drivers/net/can/usb/esd_usb.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
drivers/net/can/usb/peak_usb/pcan_usb.c
drivers/net/can/usb/usb_8dev.c
drivers/net/can/xilinx_can.c
include/uapi/linux/can/error.h

index ed4db4cf87163cf8b67aa55e815c4a33e9166573..de38d8f7b5f7a55ed1706871ecf32b2734550885 100644 (file)
@@ -952,14 +952,14 @@ static int c_can_handle_state_change(struct net_device *dev,
 
        switch (error_type) {
        case C_CAN_NO_ERROR:
-               cf->can_id |= CAN_ERR_CRTL;
+               cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                cf->data[1] = CAN_ERR_CRTL_ACTIVE;
                cf->data[6] = bec.txerr;
                cf->data[7] = bec.rxerr;
                break;
        case C_CAN_ERROR_WARNING:
                /* error warning state */
-               cf->can_id |= CAN_ERR_CRTL;
+               cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                cf->data[1] = (bec.txerr > bec.rxerr) ?
                        CAN_ERR_CRTL_TX_WARNING :
                        CAN_ERR_CRTL_RX_WARNING;
@@ -969,7 +969,7 @@ static int c_can_handle_state_change(struct net_device *dev,
                break;
        case C_CAN_ERROR_PASSIVE:
                /* error passive state */
-               cf->can_id |= CAN_ERR_CRTL;
+               cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                if (rx_err_passive)
                        cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
                if (bec.txerr > 127)
index bb7224cfc6ab5fbbc208e3980ff2ced3b27e8e5e..797a954bb1a0c316dbb02187fabe95d0f24d8328 100644 (file)
@@ -512,6 +512,7 @@ static int cc770_err(struct net_device *dev, u8 status)
 
        /* Use extended functions of the CC770 */
        if (priv->control_normal_mode & CTRL_EAF) {
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = cc770_read_reg(priv, tx_error_counter);
                cf->data[7] = cc770_read_reg(priv, rx_error_counter);
        }
index 14ac7c0ee04ce997e0a79357d0aacb8c4b267972..6b281f6eb9b41a0c2489bbddcaaef820e807861a 100644 (file)
@@ -847,7 +847,7 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr)
                case CAN_STATE_ERROR_PASSIVE:
                        priv->can.can_stats.error_passive++;
                        if (skb) {
-                               cf->can_id |= CAN_ERR_CRTL;
+                               cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                                cf->data[1] = (bec.rxerr > 127) ?
                                                CAN_ERR_CRTL_RX_PASSIVE :
                                                CAN_ERR_CRTL_TX_PASSIVE;
@@ -858,7 +858,7 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr)
                case CAN_STATE_ERROR_WARNING:
                        priv->can.can_stats.error_warning++;
                        if (skb) {
-                               cf->can_id |= CAN_ERR_CRTL;
+                               cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                                cf->data[1] |= (bec.txerr > bec.rxerr) ?
                                        CAN_ERR_CRTL_TX_WARNING :
                                        CAN_ERR_CRTL_RX_WARNING;
@@ -867,6 +867,7 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr)
                        }
                        break;
                case CAN_STATE_ERROR_ACTIVE:
+                       cf->can_id |= CAN_ERR_CNT;
                        cf->data[1] = CAN_ERR_CRTL_ACTIVE;
                        cf->data[6] = bec.txerr;
                        cf->data[7] = bec.rxerr;
index 4c47c1055eff9367c009f88352b33f60df172aad..24035a6187c98a7fa0c5aee50e1c04e7b1f543c1 100644 (file)
@@ -671,6 +671,7 @@ static void grcan_err(struct net_device *dev, u32 sources, u32 status)
                                /* There are no others at this point */
                                break;
                        }
+                       cf.can_id |= CAN_ERR_CNT;
                        cf.data[6] = txerr;
                        cf.data[7] = rxerr;
                        priv->can.state = state;
index 968ed6d7316bb3db0b40a09c92c82b1347ab8046..64e3be8b73af59908600be9197021e9003ed66e6 100644 (file)
@@ -492,7 +492,7 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev,
        switch (new_state) {
        case CAN_STATE_ERROR_WARNING:
                /* error warning state */
-               cf->can_id |= CAN_ERR_CRTL;
+               cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                cf->data[1] = (bec.txerr > bec.rxerr) ?
                        CAN_ERR_CRTL_TX_WARNING :
                        CAN_ERR_CRTL_RX_WARNING;
@@ -501,7 +501,7 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev,
                break;
        case CAN_STATE_ERROR_PASSIVE:
                /* error passive state */
-               cf->can_id |= CAN_ERR_CRTL;
+               cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
                if (bec.txerr > 127)
                        cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
index 35bfb82d69299af9f485959ee7cb167f0c4d69df..ccb5c5405224ebf444ae8fec70191cca7d24c903 100644 (file)
@@ -1127,7 +1127,7 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
        /* bus error interrupt */
        if (isrc == CEVTIND_BEI) {
                mod->can.can_stats.bus_error++;
-               cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+               cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR | CAN_ERR_CNT;
 
                switch (ecc & ECC_MASK) {
                case ECC_BIT:
@@ -1153,7 +1153,7 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
 
        if (state != mod->can.state && (state == CAN_STATE_ERROR_WARNING ||
                                        state == CAN_STATE_ERROR_PASSIVE)) {
-               cf->can_id |= CAN_ERR_CRTL;
+               cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                if (state == CAN_STATE_ERROR_WARNING) {
                        mod->can.can_stats.error_warning++;
                        cf->data[1] = (txerr > rxerr) ?
index 017f2d36ffc387ad09f373699a3ae1d4397a45d5..dcd2c9d50d5e2aba6e2b14e571541b1db811cabf 100644 (file)
@@ -1306,7 +1306,7 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can,
        shhwtstamps->hwtstamp =
                ns_to_ktime(div_u64(p->timestamp * 1000,
                                    can->kv_pcie->freq_to_ticks_div));
-       cf->can_id |= CAN_ERR_BUSERROR;
+       cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_CNT;
 
        cf->data[6] = bec.txerr;
        cf->data[7] = bec.rxerr;
index afaaeb610c005621e03a07cfd108761e77f764f5..713a4b0edf860b05caa72d8a6c1d285db05613d5 100644 (file)
@@ -741,7 +741,7 @@ static int m_can_handle_state_change(struct net_device *dev,
        switch (new_state) {
        case CAN_STATE_ERROR_WARNING:
                /* error warning state */
-               cf->can_id |= CAN_ERR_CRTL;
+               cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                cf->data[1] = (bec.txerr > bec.rxerr) ?
                        CAN_ERR_CRTL_TX_WARNING :
                        CAN_ERR_CRTL_RX_WARNING;
@@ -750,7 +750,7 @@ static int m_can_handle_state_change(struct net_device *dev,
                break;
        case CAN_STATE_ERROR_PASSIVE:
                /* error passive state */
-               cf->can_id |= CAN_ERR_CRTL;
+               cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                ecr = m_can_read(cdev, M_CAN_ECR);
                if (ecr & ECR_RP)
                        cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
index 497ef77340ea056da7668fb701287d96b317c1cd..50f6719b3aa4414a20a1320f01fd8dc93a061ba8 100644 (file)
@@ -497,6 +497,7 @@ static void pch_can_error(struct net_device *ndev, u32 status)
                priv->can.can_stats.bus_off++;
                can_bus_off(ndev);
        } else {
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = errc & PCH_TEC;
                cf->data[7] = (errc & PCH_REC) >> 8;
        }
index b2dea360813d26219e8ee1572e0853edb5c7d22d..afb9adb3d5c296eeb70ca3aafb1b65b301e4157b 100644 (file)
@@ -373,7 +373,7 @@ static int pucan_handle_status(struct peak_canfd_priv *priv,
                priv->can.state = CAN_STATE_ERROR_PASSIVE;
                priv->can.can_stats.error_passive++;
                if (skb) {
-                       cf->can_id |= CAN_ERR_CRTL;
+                       cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                        cf->data[1] = (priv->bec.txerr > priv->bec.rxerr) ?
                                        CAN_ERR_CRTL_TX_PASSIVE :
                                        CAN_ERR_CRTL_RX_PASSIVE;
@@ -386,7 +386,7 @@ static int pucan_handle_status(struct peak_canfd_priv *priv,
                priv->can.state = CAN_STATE_ERROR_WARNING;
                priv->can.can_stats.error_warning++;
                if (skb) {
-                       cf->can_id |= CAN_ERR_CRTL;
+                       cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                        cf->data[1] = (priv->bec.txerr > priv->bec.rxerr) ?
                                        CAN_ERR_CRTL_TX_WARNING :
                                        CAN_ERR_CRTL_RX_WARNING;
@@ -430,7 +430,7 @@ static int pucan_handle_cache_critical(struct peak_canfd_priv *priv)
                return -ENOMEM;
        }
 
-       cf->can_id |= CAN_ERR_CRTL;
+       cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
        cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
 
        cf->data[6] = priv->bec.txerr;
index 24d7a71def6a0d5fdf152096b6b04224182dc78e..d11db2112a4a715101412f55d4d19752c469677a 100644 (file)
@@ -334,6 +334,7 @@ static void rcar_can_error(struct net_device *ndev)
                if (skb)
                        cf->can_id |= CAN_ERR_BUSOFF;
        } else if (skb) {
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = txerr;
                cf->data[7] = rxerr;
        }
index ba42cef10a532df6fe0c4ecf85384d257f9c1c8d..e3382284e172ec9717692d8be9c4328529e8e946 100644 (file)
@@ -1052,7 +1052,7 @@ static void rcar_canfd_error(struct net_device *ndev, u32 cerfl,
                netdev_dbg(ndev, "Error warning interrupt\n");
                priv->can.state = CAN_STATE_ERROR_WARNING;
                priv->can.can_stats.error_warning++;
-               cf->can_id |= CAN_ERR_CRTL;
+               cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                cf->data[1] = txerr > rxerr ? CAN_ERR_CRTL_TX_WARNING :
                        CAN_ERR_CRTL_RX_WARNING;
                cf->data[6] = txerr;
@@ -1062,7 +1062,7 @@ static void rcar_canfd_error(struct net_device *ndev, u32 cerfl,
                netdev_dbg(ndev, "Error passive interrupt\n");
                priv->can.state = CAN_STATE_ERROR_PASSIVE;
                priv->can.can_stats.error_passive++;
-               cf->can_id |= CAN_ERR_CRTL;
+               cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                cf->data[1] = txerr > rxerr ? CAN_ERR_CRTL_TX_PASSIVE :
                        CAN_ERR_CRTL_RX_PASSIVE;
                cf->data[6] = txerr;
index 74bff5092b4724b8b9abb9416b630dd24ab9c5fd..75a2f9bf8c16bb173518ccb0d9cd7b749eca6a92 100644 (file)
@@ -426,6 +426,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
                        state = CAN_STATE_ERROR_ACTIVE;
        }
        if (state != CAN_STATE_BUS_OFF) {
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = txerr;
                cf->data[7] = rxerr;
        }
index dfd1baba41300d154443a4eb2957d8bfd831dcd4..dc28e715bbe17711dec93de1b475313d74dc8a52 100644 (file)
@@ -314,6 +314,7 @@ static void slc_bump_state(struct slcan *sl)
        if (state == CAN_STATE_BUS_OFF) {
                can_bus_off(dev);
        } else if (skb) {
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = txerr;
                cf->data[7] = rxerr;
        }
index bfb7c4bb5bc324747a13a11ccafcdda6798547ad..167114aae6dd1f60aa13ee8da3e9fb4375ecdc99 100644 (file)
@@ -680,6 +680,7 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
                                        break;
                                }
                        } else {
+                               cf->can_id |= CAN_ERR_CNT;
                                cf->data[6] = txerr;
                                cf->data[7] = rxerr;
                        }
index 9b47b07162fe5292aca355aaf45ba008189be6a0..f4e174cadd4ef291012064fed4c84975bc50e295 100644 (file)
@@ -1099,6 +1099,7 @@ static int mcp251xfd_handle_cerrif(struct mcp251xfd_priv *priv)
                err = mcp251xfd_get_berr_counter(priv->ndev, &bec);
                if (err)
                        return err;
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = bec.txerr;
                cf->data[7] = bec.rxerr;
        }
index afe9b541f03765333a329fffb0763b5110bd991b..b90dfb429ccdc33e617caae5df8c1de346f7a1a3 100644 (file)
@@ -566,6 +566,7 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
                        state = CAN_STATE_ERROR_ACTIVE;
        }
        if (skb && state != CAN_STATE_BUS_OFF) {
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = txerr;
                cf->data[7] = rxerr;
        }
index debe17bfd0f0e331b9fe4e2ffe6a2ed8c41c65a5..afa38771520ebcc95c6e0a3565dff46cfa6e6062 100644 (file)
@@ -662,6 +662,7 @@ static void ti_hecc_change_state(struct net_device *ndev,
        can_change_state(priv->ndev, cf, tx_state, rx_state);
 
        if (max(tx_state, rx_state) != CAN_STATE_BUS_OFF) {
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = hecc_read(priv, HECC_CANTEC);
                cf->data[7] = hecc_read(priv, HECC_CANREC);
        }
index 8a4bf2961f3d85e1c587fac16704418904ef557a..177ed33e08d9e23a8d00d424c4a891bd5e7b4ae8 100644 (file)
@@ -265,7 +265,8 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
                        priv->can.can_stats.bus_error++;
                        stats->rx_errors++;
 
-                       cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+                       cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR |
+                                     CAN_ERR_CNT;
 
                        switch (ecc & SJA1000_ECC_MASK) {
                        case SJA1000_ECC_BIT:
index 404093468b2f1374181ec709bb947cf4ad65a54d..dd65c101bfb8ef19a3b4e144fbc40fda94d3501d 100644 (file)
@@ -918,6 +918,7 @@ static void kvaser_usb_hydra_update_state(struct kvaser_usb_net_priv *priv,
                priv->can.can_stats.restarts++;
 
        if (new_state != CAN_STATE_BUS_OFF) {
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = bec->txerr;
                cf->data[7] = bec->rxerr;
        }
@@ -1072,6 +1073,7 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv,
 
        cf->can_id |= CAN_ERR_BUSERROR;
        if (new_state != CAN_STATE_BUS_OFF) {
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = bec.txerr;
                cf->data[7] = bec.rxerr;
        }
index f551fde16a709a5a43d3e454f8006798b493eb8d..07f687f29b3414d76018ff525c4a596bffbefabf 100644 (file)
@@ -854,6 +854,7 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev,
        }
 
        if (new_state != CAN_STATE_BUS_OFF) {
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = es->txerr;
                cf->data[7] = es->rxerr;
        }
index 091c631ebe235022e9cb8d4bb4d600abd8eef8a0..d07b7ee79e3e4d4614f23c425948461fda6d2576 100644 (file)
@@ -506,6 +506,7 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n,
                        /* Supply TX/RX error counters in case of
                         * controller error.
                         */
+                       cf->can_id = CAN_ERR_CNT;
                        cf->data[6] = mc->pdev->bec.txerr;
                        cf->data[7] = mc->pdev->bec.rxerr;
                }
index 4d38dc90472a8ac18d07c5c8480333fcc0b55b0f..8b7cd69e20b043fbdf5298dfd0fc2c1a767c7b29 100644 (file)
@@ -439,6 +439,7 @@ static void usb_8dev_rx_err_msg(struct usb_8dev_priv *priv,
        if (rx_errors)
                stats->rx_errors++;
        if (priv->can.state != CAN_STATE_BUS_OFF) {
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = txerr;
                cf->data[7] = rxerr;
        }
index 0de2f97d9f62f2e94105509872f8b9e180429f80..caa6b4cee63f2ec09b10e3e1b89017f43cfbb016 100644 (file)
@@ -965,6 +965,7 @@ static void xcan_set_error_state(struct net_device *ndev,
        can_change_state(ndev, cf, tx_state, rx_state);
 
        if (cf) {
+               cf->can_id |= CAN_ERR_CNT;
                cf->data[6] = txerr;
                cf->data[7] = rxerr;
        }
index a1000cb630632ba95ac51ce43329f7ad1b9b2fdc..b7c3efd9ff99285f49e8c37de33636ff1a4471b8 100644 (file)
@@ -57,6 +57,8 @@
 #define CAN_ERR_BUSOFF       0x00000040U /* bus off */
 #define CAN_ERR_BUSERROR     0x00000080U /* bus error (may flood!) */
 #define CAN_ERR_RESTARTED    0x00000100U /* controller restarted */
+#define CAN_ERR_CNT          0x00000200U /* TX error counter / data[6] */
+                                        /* RX error counter / data[7] */
 
 /* arbitration lost in bit ... / data[0] */
 #define CAN_ERR_LOSTARB_UNSPEC   0x00 /* unspecified */