]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
can: netlink: add can_validate_tdc()
authorVincent Mailhol <mailhol@kernel.org>
Tue, 23 Sep 2025 06:58:30 +0000 (15:58 +0900)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Wed, 24 Sep 2025 15:09:44 +0000 (17:09 +0200)
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>
drivers/net/can/dev/netlink.c
include/linux/can/bittiming.h

index 13555253e789ec6ca9c8c30571c990ad6bfde770..25c08adee9ade22a5dabdd3dec1b5eb1ee16a78e 100644 (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);
index 4d5f7794194ab13641c7854c2d66625c4e942f6c..71f839c3f0325b2a496a4bc447044a4853541338 100644 (file)
 
 #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