can: introduce the data bitrate configuration for CAN FD
authorOliver Hartkopp <socketcan@hartkopp.net>
Fri, 28 Feb 2014 15:36:23 +0000 (16:36 +0100)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Fri, 7 Mar 2014 08:18:22 +0000 (09:18 +0100)
As CAN FD offers a second bitrate for the data section of the CAN frame the
infrastructure for storing and configuring this second bitrate is introduced.
Improved the readability of the if-statement by inserting some newlines.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Acked-by: Stephane Grosjean <s.grosjean@peak-system.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/dev.c
include/linux/can/dev.h
include/uapi/linux/can/netlink.h

index 8141290e4c1837e6fc6f5900fd9880690999956d..8ebe112458c4669f615d923e73d0280e38ba3477 100644 (file)
@@ -647,6 +647,10 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
                                = { .len = sizeof(struct can_bittiming_const) },
        [IFLA_CAN_CLOCK]        = { .len = sizeof(struct can_clock) },
        [IFLA_CAN_BERR_COUNTER] = { .len = sizeof(struct can_berr_counter) },
+       [IFLA_CAN_DATA_BITTIMING]
+                               = { .len = sizeof(struct can_bittiming) },
+       [IFLA_CAN_DATA_BITTIMING_CONST]
+                               = { .len = sizeof(struct can_bittiming_const) },
 };
 
 static int can_changelink(struct net_device *dev,
@@ -707,6 +711,27 @@ static int can_changelink(struct net_device *dev,
                        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;
+               memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
+                      sizeof(dbt));
+               err = can_get_bittiming(dev, &dbt, priv->data_bittiming_const);
+               if (err)
+                       return err;
+               memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));
+
+               if (priv->do_set_data_bittiming) {
+                       /* Finally, set the bit-timing registers */
+                       err = priv->do_set_data_bittiming(dev);
+                       if (err)
+                               return err;
+               }
+       }
+
        return 0;
 }
 
@@ -725,6 +750,10 @@ static size_t can_get_size(const struct net_device *dev)
        size += nla_total_size(sizeof(u32));                    /* IFLA_CAN_RESTART_MS */
        if (priv->do_get_berr_counter)                          /* IFLA_CAN_BERR_COUNTER */
                size += nla_total_size(sizeof(struct can_berr_counter));
+       if (priv->data_bittiming.bitrate)                       /* IFLA_CAN_DATA_BITTIMING */
+               size += nla_total_size(sizeof(struct can_bittiming));
+       if (priv->data_bittiming_const)                         /* IFLA_CAN_DATA_BITTIMING_CONST */
+               size += nla_total_size(sizeof(struct can_bittiming_const));
 
        return size;
 }
@@ -738,20 +767,34 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
 
        if (priv->do_get_state)
                priv->do_get_state(dev, &state);
+
        if ((priv->bittiming.bitrate &&
             nla_put(skb, IFLA_CAN_BITTIMING,
                     sizeof(priv->bittiming), &priv->bittiming)) ||
+
            (priv->bittiming_const &&
             nla_put(skb, IFLA_CAN_BITTIMING_CONST,
                     sizeof(*priv->bittiming_const), priv->bittiming_const)) ||
+
            nla_put(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock) ||
            nla_put_u32(skb, IFLA_CAN_STATE, state) ||
            nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
            nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
+
            (priv->do_get_berr_counter &&
             !priv->do_get_berr_counter(dev, &bec) &&
-            nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)))
+            nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
+
+           (priv->data_bittiming.bitrate &&
+            nla_put(skb, IFLA_CAN_DATA_BITTIMING,
+                    sizeof(priv->data_bittiming), &priv->data_bittiming)) ||
+
+           (priv->data_bittiming_const &&
+            nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
+                    sizeof(*priv->data_bittiming_const),
+                    priv->data_bittiming_const)))
                return -EMSGSIZE;
+
        return 0;
 }
 
index dc5f9026b67fb83fdff4129f1bfac0337cc7a595..8adaee96f29285c2b301b3494a94bc5d5dfc1f2b 100644 (file)
@@ -33,8 +33,9 @@ enum can_mode {
 struct can_priv {
        struct can_device_stats can_stats;
 
-       struct can_bittiming bittiming;
-       const struct can_bittiming_const *bittiming_const;
+       struct can_bittiming bittiming, data_bittiming;
+       const struct can_bittiming_const *bittiming_const,
+               *data_bittiming_const;
        struct can_clock clock;
 
        enum can_state state;
@@ -45,6 +46,7 @@ struct can_priv {
        struct timer_list restart_timer;
 
        int (*do_set_bittiming)(struct net_device *dev);
+       int (*do_set_data_bittiming)(struct net_device *dev);
        int (*do_set_mode)(struct net_device *dev, enum can_mode mode);
        int (*do_get_state)(const struct net_device *dev,
                            enum can_state *state);
index df944ed206a8e4bd23d9f9a3ec9e08c9e0ad6e3b..b41933d6bdcd2de7eb0847e5ccdf387b52c4e069 100644 (file)
@@ -122,6 +122,8 @@ enum {
        IFLA_CAN_RESTART_MS,
        IFLA_CAN_RESTART,
        IFLA_CAN_BERR_COUNTER,
+       IFLA_CAN_DATA_BITTIMING,
+       IFLA_CAN_DATA_BITTIMING_CONST,
        __IFLA_CAN_MAX
 };