Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

can: netlink: add can_priv::do_get_auto_tdcv() to retrieve tdcv from device

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>

authored by

Vincent Mailhol and committed by
Marc Kleine-Budde
e8060f08 d99755f7

+13 -3
+12 -3
drivers/net/can/dev/netlink.c
··· 372 372 } 373 373 374 374 if (can_tdc_is_enabled(priv)) { 375 - if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL) 375 + if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL || 376 + priv->do_get_auto_tdcv) 376 377 size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV */ 377 378 size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO */ 378 379 if (priv->tdc_const->tdcf_max) ··· 446 445 goto err_cancel; 447 446 448 447 if (can_tdc_is_enabled(priv)) { 449 - if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL && 450 - nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdc->tdcv)) 448 + u32 tdcv; 449 + int err = -EINVAL; 450 + 451 + if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL) { 452 + tdcv = tdc->tdcv; 453 + err = 0; 454 + } else if (priv->do_get_auto_tdcv) { 455 + err = priv->do_get_auto_tdcv(dev, &tdcv); 456 + } 457 + if (!err && nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdcv)) 451 458 goto err_cancel; 452 459 if (nla_put_u32(skb, IFLA_CAN_TDC_TDCO, tdc->tdco)) 453 460 goto err_cancel;
+1
include/linux/can/dev.h
··· 82 82 enum can_state *state); 83 83 int (*do_get_berr_counter)(const struct net_device *dev, 84 84 struct can_berr_counter *bec); 85 + int (*do_get_auto_tdcv)(const struct net_device *dev, u32 *tdcv); 85 86 86 87 unsigned int echo_skb_max; 87 88 struct sk_buff **echo_skb;