]> www.infradead.org Git - users/hch/misc.git/commitdiff
can: netlink: add can_dtb_changelink()
authorVincent Mailhol <mailhol@kernel.org>
Tue, 23 Sep 2025 06:58:35 +0000 (15:58 +0900)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Wed, 24 Sep 2025 15:09:45 +0000 (17:09 +0200)
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>
drivers/net/can/dev/netlink.c

index abff7b84fdce9641e1a5338ec6cef992774b0ec0..5f2962aab5763a0dc8f86a6fa7fa3afbef125d26 100644 (file)
@@ -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]);