can: dev: can_tdc_fill_info(): don't read automatic TDCV if interface is down

The automatic TDCV readback calls into the driver via do_get_auto_tdcv().
Some drivers, such as xcan_get_auto_tdcv(), read controller registers
without taking a runtime PM reference, so calling this while the
interface is down can touch registers whose clocks are gated.

Gate do_get_auto_tdcv() on netif_running() in can_tdc_fill_info() and
adjust can_tdc_get_size() and can_data_bittiming_get_size() so that only
the automatic TDCV size is skipped when the interface is down. The other
TDC parameters are still reported, as they are meaningful while the
interface is down.

This is a defensive hardening based on code inspection; the automatic
TDCV path has not been triggered on hardware.

Signed-off-by: ChunYuZhiQiang <chunyuzhiqiang@yinhe.ht>
Reviewed-by: Vincent Mailhol <mailhol@kernel.org>
Fixes: e8060f08cd ("can: netlink: add can_priv::do_get_auto_tdcv() to retrieve tdcv from device")
Link: https://patch.msgid.link/20261027065012.191348-2-chunyuzhiqiang@yinhe.ht
[mkl: fix open parenthesis alignment]
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
ChunYuZhiQiang 2026-10-27 14:50:12 +08:00 committed by Marc Kleine-Budde
parent 75332c410c
commit f5128a7672

View File

@ -720,7 +720,8 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
return 0;
}
static size_t can_tdc_get_size(struct data_bittiming_params *dbt_params,
static size_t can_tdc_get_size(const struct net_device *dev,
struct data_bittiming_params *dbt_params,
u32 tdc_flags)
{
bool tdc_manual = tdc_flags & CAN_CTRLMODE_TDC_MANUAL_MASK;
@ -742,7 +743,8 @@ static size_t can_tdc_get_size(struct data_bittiming_params *dbt_params,
}
if (tdc_flags) {
if (tdc_manual || dbt_params->do_get_auto_tdcv)
if (tdc_manual ||
(dbt_params->do_get_auto_tdcv && netif_running(dev)))
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV */
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO */
if (dbt_params->tdc_const->tdcf_max)
@ -752,7 +754,8 @@ static size_t can_tdc_get_size(struct data_bittiming_params *dbt_params,
return size;
}
static size_t can_data_bittiming_get_size(struct data_bittiming_params *dbt_params,
static size_t can_data_bittiming_get_size(const struct net_device *dev,
struct data_bittiming_params *dbt_params,
u32 tdc_flags)
{
size_t size = 0;
@ -764,7 +767,7 @@ static size_t can_data_bittiming_get_size(struct data_bittiming_params *dbt_para
if (dbt_params->data_bitrate_const) /* IFLA_CAN_{,XL}_DATA_BITRATE_CONST */
size += nla_total_size(sizeof(*dbt_params->data_bitrate_const) *
dbt_params->data_bitrate_const_cnt);
size += can_tdc_get_size(dbt_params, tdc_flags);/* IFLA_CAN_{,XL}_TDC */
size += can_tdc_get_size(dev, dbt_params, tdc_flags);/* IFLA_CAN_{,XL}_TDC */
return size;
}
@ -825,10 +828,10 @@ static size_t can_get_size(const struct net_device *dev)
size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */
size += can_ctrlmode_ext_get_size(); /* IFLA_CAN_CTRLMODE_EXT */
size += can_data_bittiming_get_size(&priv->fd,
size += can_data_bittiming_get_size(dev, &priv->fd,
priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK);
size += can_data_bittiming_get_size(&priv->xl,
size += can_data_bittiming_get_size(dev, &priv->xl,
priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MASK);
size += can_pwm_get_size(priv->xl.pwm_const, /* IFLA_CAN_XL_PWM */
priv->ctrlmode & CAN_CTRLMODE_XL_TMS);
@ -910,7 +913,7 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev,
if (tdc_manual) {
tdcv = tdc->tdcv;
err = 0;
} else if (dbt_params->do_get_auto_tdcv) {
} else if (dbt_params->do_get_auto_tdcv && netif_running(dev)) {
err = dbt_params->do_get_auto_tdcv(dev, &tdcv);
}
if (!err && nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdcv))