can: netlink: add can_validate_tdc()

Factorise the TDC validation out of can_validate() and move it in the
new can_validate_tdc() function. This is a preparation patch for the
introduction of CAN XL because this TDC validation will be reused
later on.

Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
Link: https://patch.msgid.link/20250923-canxl-netlink-prep-v4-5-e720d28f66fe@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
Vincent Mailhol
2025-09-24 17:09:44 +02:00
committed by Marc Kleine-Budde
parent f5ae5a7541
commit b23a8425cb
2 changed files with 52 additions and 34 deletions
+48 -34
View File
@@ -57,6 +57,49 @@ static int can_validate_bittiming(struct nlattr *data[],
return 0;
}
static int can_validate_tdc(struct nlattr *data_tdc,
struct netlink_ext_ack *extack, u32 tdc_flags)
{
bool tdc_manual = tdc_flags & CAN_CTRLMODE_TDC_MANUAL_MASK;
bool tdc_auto = tdc_flags & CAN_CTRLMODE_TDC_AUTO_MASK;
int err;
/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */
if (tdc_auto && tdc_manual)
return -EOPNOTSUPP;
/* If one of the CAN_CTRLMODE_TDC_* flag is set then TDC
* must be set and vice-versa
*/
if ((tdc_auto || tdc_manual) != !!data_tdc)
return -EOPNOTSUPP;
/* If providing TDC parameters, at least TDCO is needed. TDCV
* is needed if and only if CAN_CTRLMODE_TDC_MANUAL is set
*/
if (data_tdc) {
struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1];
err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX,
data_tdc, can_tdc_policy, extack);
if (err)
return err;
if (tb_tdc[IFLA_CAN_TDC_TDCV]) {
if (tdc_auto)
return -EOPNOTSUPP;
} else {
if (tdc_manual)
return -EOPNOTSUPP;
}
if (!tb_tdc[IFLA_CAN_TDC_TDCO])
return -EOPNOTSUPP;
}
return 0;
}
static int can_validate(struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -67,7 +110,7 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
* - nominal/arbitration bittiming
* - data bittiming
* - control mode with CAN_CTRLMODE_FD set
* - TDC parameters are coherent (details below)
* - TDC parameters are coherent (details in can_validate_tdc())
*/
if (!data)
@@ -75,42 +118,13 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
if (data[IFLA_CAN_CTRLMODE]) {
struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
u32 tdc_flags = cm->flags & CAN_CTRLMODE_FD_TDC_MASK;
is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */
if (tdc_flags == CAN_CTRLMODE_FD_TDC_MASK)
return -EOPNOTSUPP;
/* If one of the CAN_CTRLMODE_TDC_* flag is set then
* TDC must be set and vice-versa
*/
if (!!tdc_flags != !!data[IFLA_CAN_TDC])
return -EOPNOTSUPP;
/* If providing TDC parameters, at least TDCO is
* needed. TDCV is needed if and only if
* CAN_CTRLMODE_TDC_MANUAL is set
*/
if (data[IFLA_CAN_TDC]) {
struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1];
err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX,
data[IFLA_CAN_TDC],
can_tdc_policy, extack);
if (err)
return err;
if (tb_tdc[IFLA_CAN_TDC_TDCV]) {
if (tdc_flags & CAN_CTRLMODE_TDC_AUTO)
return -EOPNOTSUPP;
} else {
if (tdc_flags & CAN_CTRLMODE_TDC_MANUAL)
return -EOPNOTSUPP;
}
if (!tb_tdc[IFLA_CAN_TDC_TDCO])
return -EOPNOTSUPP;
}
err = can_validate_tdc(data[IFLA_CAN_TDC], extack,
cm->flags & CAN_CTRLMODE_FD_TDC_MASK);
if (err)
return err;
}
err = can_validate_bittiming(data, extack, IFLA_CAN_BITTIMING);
+4
View File
@@ -16,6 +16,10 @@
#define CAN_CTRLMODE_FD_TDC_MASK \
(CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_TDC_MANUAL)
#define CAN_CTRLMODE_TDC_AUTO_MASK \
(CAN_CTRLMODE_TDC_AUTO)
#define CAN_CTRLMODE_TDC_MANUAL_MASK \
(CAN_CTRLMODE_TDC_MANUAL)
/*
* struct can_tdc - CAN FD Transmission Delay Compensation parameters