can: netlink: add can_priv::do_get_auto_tdcv() to retrieve tdcv from device
authorVincent Mailhol <mailhol.vincent@wanadoo.fr>
Sat, 18 Sep 2021 09:56:36 +0000 (18:56 +0900)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Sun, 24 Oct 2021 14:24:29 +0000 (16:24 +0200)
Some CAN device can measure the TDCV (Transmission Delay Compensation
Value) automatically for each transmitted CAN frames.

A callback function do_get_auto_tdcv() is added to retrieve that
value. This function is used only if CAN_CTRLMODE_TDC_AUTO is enabled
(if CAN_CTRLMODE_TDC_MANUAL is selected, the TDCV value is provided by
the user).

If the device does not support reporting of TDCV, do_get_auto_tdcv()
should be set to NULL and TDCV will not be reported by the netlink
interface.

On success, do_get_auto_tdcv() shall return 0. If the value can not be
measured by the device, for example because network is down or because
no frames were transmitted yet, can_priv::do_get_auto_tdcv() shall
return a negative error code (e.g. -EINVAL) to signify that the value
is not yet available. In such cases, TDCV is not reported by the
netlink interface.

Link: https://lore.kernel.org/all/20210918095637.20108-6-mailhol.vincent@wanadoo.fr
CC: Stefan Mätje <stefan.maetje@esd.eu>
Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/dev/netlink.c
include/linux/can/dev.h

index c77cc6ae88b627c1b9f5dd653a98b8fe6dccda88..95cca4e5251f0a014551fc313e134caaf18feac4 100644 (file)
@@ -372,7 +372,8 @@ static size_t can_tdc_get_size(const struct net_device *dev)
        }
 
        if (can_tdc_is_enabled(priv)) {
-               if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL)
+               if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL ||
+                   priv->do_get_auto_tdcv)
                        size += nla_total_size(sizeof(u32));    /* IFLA_CAN_TDCV */
                size += nla_total_size(sizeof(u32));            /* IFLA_CAN_TDCO */
                if (priv->tdc_const->tdcf_max)
@@ -445,8 +446,16 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev)
                goto err_cancel;
 
        if (can_tdc_is_enabled(priv)) {
-               if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL &&
-                   nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdc->tdcv))
+               u32 tdcv;
+               int err = -EINVAL;
+
+               if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL) {
+                       tdcv = tdc->tdcv;
+                       err = 0;
+               } else if (priv->do_get_auto_tdcv) {
+                       err = priv->do_get_auto_tdcv(dev, &tdcv);
+               }
+               if (!err && nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdcv))
                        goto err_cancel;
                if (nla_put_u32(skb, IFLA_CAN_TDC_TDCO, tdc->tdco))
                        goto err_cancel;
index 6dacbbb41e68c98c26d81687eed3d7f16015e8dd..b4aa0f048cab8d2a29679c2992300117c922fbde 100644 (file)
@@ -82,6 +82,7 @@ struct can_priv {
                            enum can_state *state);
        int (*do_get_berr_counter)(const struct net_device *dev,
                                   struct can_berr_counter *bec);
+       int (*do_get_auto_tdcv)(const struct net_device *dev, u32 *tdcv);
 
        unsigned int echo_skb_max;
        struct sk_buff **echo_skb;