Commit 9859ccd2 authored by Oliver Hartkopp's avatar Oliver Hartkopp Committed by Marc Kleine-Budde

can: introduce the data bitrate configuration for CAN FD

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: default avatarOliver Hartkopp <socketcan@hartkopp.net>
Acked-by: default avatarStephane Grosjean <s.grosjean@peak-system.com>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 08da7da4
...@@ -647,6 +647,10 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { ...@@ -647,6 +647,10 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
= { .len = sizeof(struct can_bittiming_const) }, = { .len = sizeof(struct can_bittiming_const) },
[IFLA_CAN_CLOCK] = { .len = sizeof(struct can_clock) }, [IFLA_CAN_CLOCK] = { .len = sizeof(struct can_clock) },
[IFLA_CAN_BERR_COUNTER] = { .len = sizeof(struct can_berr_counter) }, [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, static int can_changelink(struct net_device *dev,
...@@ -707,6 +711,27 @@ static int can_changelink(struct net_device *dev, ...@@ -707,6 +711,27 @@ static int can_changelink(struct net_device *dev,
return err; 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; return 0;
} }
...@@ -725,6 +750,10 @@ static size_t can_get_size(const struct net_device *dev) ...@@ -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 */ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */
if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */ if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */
size += nla_total_size(sizeof(struct 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; return size;
} }
...@@ -738,20 +767,34 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) ...@@ -738,20 +767,34 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
if (priv->do_get_state) if (priv->do_get_state)
priv->do_get_state(dev, &state); priv->do_get_state(dev, &state);
if ((priv->bittiming.bitrate && if ((priv->bittiming.bitrate &&
nla_put(skb, IFLA_CAN_BITTIMING, nla_put(skb, IFLA_CAN_BITTIMING,
sizeof(priv->bittiming), &priv->bittiming)) || sizeof(priv->bittiming), &priv->bittiming)) ||
(priv->bittiming_const && (priv->bittiming_const &&
nla_put(skb, IFLA_CAN_BITTIMING_CONST, nla_put(skb, IFLA_CAN_BITTIMING_CONST,
sizeof(*priv->bittiming_const), priv->bittiming_const)) || sizeof(*priv->bittiming_const), priv->bittiming_const)) ||
nla_put(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock) || nla_put(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock) ||
nla_put_u32(skb, IFLA_CAN_STATE, state) || nla_put_u32(skb, IFLA_CAN_STATE, state) ||
nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) || nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) || nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
(priv->do_get_berr_counter && (priv->do_get_berr_counter &&
!priv->do_get_berr_counter(dev, &bec) && !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 -EMSGSIZE;
return 0; return 0;
} }
......
...@@ -33,8 +33,9 @@ enum can_mode { ...@@ -33,8 +33,9 @@ enum can_mode {
struct can_priv { struct can_priv {
struct can_device_stats can_stats; struct can_device_stats can_stats;
struct can_bittiming bittiming; struct can_bittiming bittiming, data_bittiming;
const struct can_bittiming_const *bittiming_const; const struct can_bittiming_const *bittiming_const,
*data_bittiming_const;
struct can_clock clock; struct can_clock clock;
enum can_state state; enum can_state state;
...@@ -45,6 +46,7 @@ struct can_priv { ...@@ -45,6 +46,7 @@ struct can_priv {
struct timer_list restart_timer; struct timer_list restart_timer;
int (*do_set_bittiming)(struct net_device *dev); 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_set_mode)(struct net_device *dev, enum can_mode mode);
int (*do_get_state)(const struct net_device *dev, int (*do_get_state)(const struct net_device *dev,
enum can_state *state); enum can_state *state);
......
...@@ -122,6 +122,8 @@ enum { ...@@ -122,6 +122,8 @@ enum {
IFLA_CAN_RESTART_MS, IFLA_CAN_RESTART_MS,
IFLA_CAN_RESTART, IFLA_CAN_RESTART,
IFLA_CAN_BERR_COUNTER, IFLA_CAN_BERR_COUNTER,
IFLA_CAN_DATA_BITTIMING,
IFLA_CAN_DATA_BITTIMING_CONST,
__IFLA_CAN_MAX __IFLA_CAN_MAX
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment