mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-09 16:00:22 +08:00
can: netlink: add can_dtb_changelink()
Factorise the databittiming parsing out of can_changelink() and move it in the new can_dtb_changelink() function. This is a preparation patch for the introduction of CAN XL because the databittiming changelink logic will be reused later on. Signed-off-by: Vincent Mailhol <mailhol@kernel.org> Link: https://patch.msgid.link/20250923-canxl-netlink-prep-v4-10-e720d28f66fe@kernel.org Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
committed by
Marc Kleine-Budde
parent
530c918f8c
commit
2e543af483
@@ -221,12 +221,95 @@ static int can_tdc_changelink(struct data_bittiming_params *dbt_params,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int can_dbt_changelink(struct net_device *dev, struct nlattr *data[],
|
||||
bool fd, struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct nlattr *data_bittiming, *data_tdc;
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
struct data_bittiming_params *dbt_params;
|
||||
struct can_bittiming dbt;
|
||||
bool need_tdc_calc = false;
|
||||
u32 tdc_mask;
|
||||
int err;
|
||||
|
||||
if (fd) {
|
||||
data_bittiming = data[IFLA_CAN_DATA_BITTIMING];
|
||||
data_tdc = data[IFLA_CAN_TDC];
|
||||
dbt_params = &priv->fd;
|
||||
tdc_mask = CAN_CTRLMODE_FD_TDC_MASK;
|
||||
} else {
|
||||
return -EOPNOTSUPP; /* Place holder for CAN XL */
|
||||
}
|
||||
|
||||
if (!data_bittiming)
|
||||
return 0;
|
||||
|
||||
/* Do not allow changing bittiming while running */
|
||||
if (dev->flags & IFF_UP)
|
||||
return -EBUSY;
|
||||
|
||||
/* Calculate bittiming parameters based on data_bittiming_const
|
||||
* if set, otherwise pass bitrate directly via do_set_bitrate().
|
||||
* Bail out if neither is given.
|
||||
*/
|
||||
if (!dbt_params->data_bittiming_const && !dbt_params->do_set_data_bittiming &&
|
||||
!dbt_params->data_bitrate_const)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
memcpy(&dbt, nla_data(data_bittiming), sizeof(dbt));
|
||||
err = can_get_bittiming(dev, &dbt, dbt_params->data_bittiming_const,
|
||||
dbt_params->data_bitrate_const,
|
||||
dbt_params->data_bitrate_const_cnt, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) {
|
||||
NL_SET_ERR_MSG_FMT(extack,
|
||||
"CAN data bitrate %u bps surpasses transceiver capabilities of %u bps",
|
||||
dbt.bitrate, priv->bitrate_max);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&dbt_params->tdc, 0, sizeof(dbt_params->tdc));
|
||||
if (data[IFLA_CAN_CTRLMODE]) {
|
||||
struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
|
||||
|
||||
need_tdc_calc = !(cm->mask & tdc_mask);
|
||||
}
|
||||
if (data_tdc) {
|
||||
/* TDC parameters are provided: use them */
|
||||
err = can_tdc_changelink(dbt_params, data_tdc, extack);
|
||||
if (err) {
|
||||
priv->ctrlmode &= ~tdc_mask;
|
||||
return err;
|
||||
}
|
||||
} else if (need_tdc_calc) {
|
||||
/* Neither of TDC parameters nor TDC flags are provided:
|
||||
* do calculation
|
||||
*/
|
||||
can_calc_tdco(&dbt_params->tdc, dbt_params->tdc_const, &dbt,
|
||||
&priv->ctrlmode, priv->ctrlmode_supported);
|
||||
} /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly
|
||||
* turned off. TDC is disabled: do nothing
|
||||
*/
|
||||
|
||||
memcpy(&dbt_params->data_bittiming, &dbt, sizeof(dbt));
|
||||
|
||||
if (dbt_params->do_set_data_bittiming) {
|
||||
/* Finally, set the bit-timing registers */
|
||||
err = dbt_params->do_set_data_bittiming(dev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int can_changelink(struct net_device *dev, struct nlattr *tb[],
|
||||
struct nlattr *data[],
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
bool fd_tdc_flag_provided = false;
|
||||
int err;
|
||||
|
||||
/* We need synchronization with dev->stop() */
|
||||
@@ -273,8 +356,6 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
|
||||
}
|
||||
|
||||
can_set_default_mtu(dev);
|
||||
|
||||
fd_tdc_flag_provided = cm->mask & CAN_CTRLMODE_FD_TDC_MASK;
|
||||
}
|
||||
|
||||
if (data[IFLA_CAN_BITTIMING]) {
|
||||
@@ -347,67 +428,10 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
|
||||
return err;
|
||||
}
|
||||
|
||||
if (data[IFLA_CAN_DATA_BITTIMING]) {
|
||||
struct can_bittiming dbt;
|
||||
|
||||
/* Do not allow changing bittiming while running */
|
||||
if (dev->flags & IFF_UP)
|
||||
return -EBUSY;
|
||||
|
||||
/* Calculate bittiming parameters based on
|
||||
* data_bittiming_const if set, otherwise pass bitrate
|
||||
* directly via do_set_bitrate(). Bail out if neither
|
||||
* is given.
|
||||
*/
|
||||
if (!priv->fd.data_bittiming_const && !priv->fd.do_set_data_bittiming &&
|
||||
!priv->fd.data_bitrate_const)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
|
||||
sizeof(dbt));
|
||||
err = can_get_bittiming(dev, &dbt,
|
||||
priv->fd.data_bittiming_const,
|
||||
priv->fd.data_bitrate_const,
|
||||
priv->fd.data_bitrate_const_cnt,
|
||||
extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) {
|
||||
NL_SET_ERR_MSG_FMT(extack,
|
||||
"CANFD data bitrate %u bps surpasses transceiver capabilities of %u bps",
|
||||
dbt.bitrate, priv->bitrate_max);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc));
|
||||
if (data[IFLA_CAN_TDC]) {
|
||||
/* TDC parameters are provided: use them */
|
||||
err = can_tdc_changelink(&priv->fd,
|
||||
data[IFLA_CAN_TDC], extack);
|
||||
if (err) {
|
||||
priv->ctrlmode &= ~CAN_CTRLMODE_FD_TDC_MASK;
|
||||
return err;
|
||||
}
|
||||
} else if (!fd_tdc_flag_provided) {
|
||||
/* Neither of TDC parameters nor TDC flags are
|
||||
* provided: do calculation
|
||||
*/
|
||||
can_calc_tdco(&priv->fd.tdc, priv->fd.tdc_const, &dbt,
|
||||
&priv->ctrlmode, priv->ctrlmode_supported);
|
||||
} /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly
|
||||
* turned off. TDC is disabled: do nothing
|
||||
*/
|
||||
|
||||
memcpy(&priv->fd.data_bittiming, &dbt, sizeof(dbt));
|
||||
|
||||
if (priv->fd.do_set_data_bittiming) {
|
||||
/* Finally, set the bit-timing registers */
|
||||
err = priv->fd.do_set_data_bittiming(dev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
/* CAN FD */
|
||||
err = can_dbt_changelink(dev, data, true, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (data[IFLA_CAN_TERMINATION]) {
|
||||
const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]);
|
||||
|
||||
Reference in New Issue
Block a user