Commit 431af779 authored by Marc Kleine-Budde's avatar Marc Kleine-Budde

can: dev: add CAN interface API for fixed bitrates

Some CAN interfaces only support fixed fixed bitrates. This patch adds a
netlink interface to get the list of the CAN interface's fixed bitrates and
data bitrates.

Inside the driver arrays of supported data- bitrate values are defined.

const u32 drvname_bitrate[] = { 20000, 50000, 100000 };
const u32 drvname_data_bitrate[] = { 200000, 500000, 1000000 };

struct drvname_priv *priv;
priv = netdev_priv(dev);

priv->bitrate_const = drvname_bitrate;
priv->bitrate_const_cnt = ARRAY_SIZE(drvname_bitrate);
priv->data_bitrate_const = drvname_data_bitrate;
priv->data_bitrate_const_cnt = ARRAY_SIZE(drvname_data_bitrate);
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent c3606d43
...@@ -279,8 +279,29 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, ...@@ -279,8 +279,29 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt,
return 0; return 0;
} }
/* Checks the validity of predefined bitrate settings */
static int can_validate_bitrate(struct net_device *dev, struct can_bittiming *bt,
const u32 *bitrate_const,
const unsigned int bitrate_const_cnt)
{
struct can_priv *priv = netdev_priv(dev);
unsigned int i;
for (i = 0; i < bitrate_const_cnt; i++) {
if (bt->bitrate == bitrate_const[i])
break;
}
if (i >= priv->bitrate_const_cnt)
return -EINVAL;
return 0;
}
static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt, static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc) const struct can_bittiming_const *btc,
const u32 *bitrate_const,
const unsigned int bitrate_const_cnt)
{ {
int err; int err;
...@@ -290,10 +311,13 @@ static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt, ...@@ -290,10 +311,13 @@ static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
* alternatively the CAN timing parameters (tq, prop_seg, etc.) are * alternatively the CAN timing parameters (tq, prop_seg, etc.) are
* provided directly which are then checked and fixed up. * provided directly which are then checked and fixed up.
*/ */
if (!bt->tq && bt->bitrate) if (!bt->tq && bt->bitrate && btc)
err = can_calc_bittiming(dev, bt, btc); err = can_calc_bittiming(dev, bt, btc);
else if (bt->tq && !bt->bitrate) else if (bt->tq && !bt->bitrate && btc)
err = can_fixup_bittiming(dev, bt, btc); err = can_fixup_bittiming(dev, bt, btc);
else if (!bt->tq && bt->bitrate && bitrate_const)
err = can_validate_bitrate(dev, bt, bitrate_const,
bitrate_const_cnt);
else else
err = -EINVAL; err = -EINVAL;
...@@ -878,12 +902,12 @@ static int can_changelink(struct net_device *dev, ...@@ -878,12 +902,12 @@ static int can_changelink(struct net_device *dev,
return -EOPNOTSUPP; return -EOPNOTSUPP;
memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt)); memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
if (priv->bittiming_const) { err = can_get_bittiming(dev, &bt,
err = can_get_bittiming(dev, &bt, priv->bittiming_const,
priv->bittiming_const); priv->bitrate_const,
if (err) priv->bitrate_const_cnt);
return err; if (err)
} return err;
memcpy(&priv->bittiming, &bt, sizeof(bt)); memcpy(&priv->bittiming, &bt, sizeof(bt));
if (priv->do_set_bittiming) { if (priv->do_set_bittiming) {
...@@ -962,12 +986,12 @@ static int can_changelink(struct net_device *dev, ...@@ -962,12 +986,12 @@ static int can_changelink(struct net_device *dev,
memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]), memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
sizeof(dbt)); sizeof(dbt));
if (priv->data_bittiming_const) { err = can_get_bittiming(dev, &dbt,
err = can_get_bittiming(dev, &dbt, priv->data_bittiming_const,
priv->data_bittiming_const); priv->data_bitrate_const,
if (err) priv->data_bitrate_const_cnt);
return err; if (err)
} return err;
memcpy(&priv->data_bittiming, &dbt, sizeof(dbt)); memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));
if (priv->do_set_data_bittiming) { if (priv->do_set_data_bittiming) {
...@@ -1029,6 +1053,12 @@ static size_t can_get_size(const struct net_device *dev) ...@@ -1029,6 +1053,12 @@ static size_t can_get_size(const struct net_device *dev)
size += nla_total_size(sizeof(*priv->termination_const) * /* IFLA_CAN_TERMINATION_CONST */ size += nla_total_size(sizeof(*priv->termination_const) * /* IFLA_CAN_TERMINATION_CONST */
priv->termination_const_cnt); priv->termination_const_cnt);
} }
if (priv->bitrate_const) /* IFLA_CAN_BITRATE_CONST */
size += nla_total_size(sizeof(*priv->bitrate_const) *
priv->bitrate_const_cnt);
if (priv->data_bitrate_const) /* IFLA_CAN_DATA_BITRATE_CONST */
size += nla_total_size(sizeof(*priv->data_bitrate_const) *
priv->data_bitrate_const_cnt);
return size; return size;
} }
...@@ -1074,7 +1104,20 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) ...@@ -1074,7 +1104,20 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
nla_put(skb, IFLA_CAN_TERMINATION_CONST, nla_put(skb, IFLA_CAN_TERMINATION_CONST,
sizeof(*priv->termination_const) * sizeof(*priv->termination_const) *
priv->termination_const_cnt, priv->termination_const_cnt,
priv->termination_const)))) priv->termination_const))) ||
(priv->bitrate_const &&
nla_put(skb, IFLA_CAN_BITRATE_CONST,
sizeof(*priv->bitrate_const) *
priv->bitrate_const_cnt,
priv->bitrate_const)) ||
(priv->data_bitrate_const &&
nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST,
sizeof(*priv->data_bitrate_const) *
priv->data_bitrate_const_cnt,
priv->data_bitrate_const))
)
return -EMSGSIZE; return -EMSGSIZE;
...@@ -1140,6 +1183,12 @@ int register_candev(struct net_device *dev) ...@@ -1140,6 +1183,12 @@ int register_candev(struct net_device *dev)
(!priv->termination_const != !priv->do_set_termination)) (!priv->termination_const != !priv->do_set_termination))
return -EINVAL; return -EINVAL;
if (!priv->bitrate_const != !priv->bitrate_const_cnt)
return -EINVAL;
if (!priv->data_bitrate_const != !priv->data_bitrate_const_cnt)
return -EINVAL;
dev->rtnl_link_ops = &can_link_ops; dev->rtnl_link_ops = &can_link_ops;
return register_netdev(dev); return register_netdev(dev);
} }
......
...@@ -41,6 +41,10 @@ struct can_priv { ...@@ -41,6 +41,10 @@ struct can_priv {
const u16 *termination_const; const u16 *termination_const;
unsigned int termination_const_cnt; unsigned int termination_const_cnt;
u16 termination; u16 termination;
const u32 *bitrate_const;
unsigned int bitrate_const_cnt;
const u32 *data_bitrate_const;
unsigned int data_bitrate_const_cnt;
struct can_clock clock; struct can_clock clock;
enum can_state state; enum can_state state;
......
...@@ -129,6 +129,8 @@ enum { ...@@ -129,6 +129,8 @@ enum {
IFLA_CAN_DATA_BITTIMING_CONST, IFLA_CAN_DATA_BITTIMING_CONST,
IFLA_CAN_TERMINATION, IFLA_CAN_TERMINATION,
IFLA_CAN_TERMINATION_CONST, IFLA_CAN_TERMINATION_CONST,
IFLA_CAN_BITRATE_CONST,
IFLA_CAN_DATA_BITRATE_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