mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
can: dev: add CAN interface termination API
This patch adds a netlink interface to configure the CAN bus termination of CAN interfaces. Inside the driver an array of supported termination values is defined: const u16 drvname_termination[] = { 60, 120, CAN_TERMINATION_DISABLED }; struct drvname_priv *priv; priv = netdev_priv(dev); priv->termination_const = drvname_termination; priv->termination_const_cnt = ARRAY_SIZE(drvname_termination); priv->termination = CAN_TERMINATION_DISABLED; And the funtion to set the value has to be defined: priv->do_set_termination = drvname_set_termination; Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> Reviewed-by: Ramesh Shanmugasundaram <Ramesh.shanmugasundaram@bp.renesas.com> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
parent
d140199af5
commit
12a6075cab
3 changed files with 57 additions and 1 deletions
|
@ -958,6 +958,30 @@ static int can_changelink(struct net_device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
if (data[IFLA_CAN_TERMINATION]) {
|
||||
const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]);
|
||||
const unsigned int num_term = priv->termination_const_cnt;
|
||||
unsigned int i;
|
||||
|
||||
if (!priv->do_set_termination)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* check whether given value is supported by the interface */
|
||||
for (i = 0; i < num_term; i++) {
|
||||
if (termval == priv->termination_const[i])
|
||||
break;
|
||||
}
|
||||
if (i >= num_term)
|
||||
return -EINVAL;
|
||||
|
||||
/* Finally, set the termination value */
|
||||
err = priv->do_set_termination(dev, termval);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
priv->termination = termval;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -980,6 +1004,11 @@ static size_t can_get_size(const struct net_device *dev)
|
|||
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));
|
||||
if (priv->termination_const) {
|
||||
size += nla_total_size(sizeof(priv->termination)); /* IFLA_CAN_TERMINATION */
|
||||
size += nla_total_size(sizeof(*priv->termination_const) * /* IFLA_CAN_TERMINATION_CONST */
|
||||
priv->termination_const_cnt);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -1018,7 +1047,15 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|||
(priv->data_bittiming_const &&
|
||||
nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
|
||||
sizeof(*priv->data_bittiming_const),
|
||||
priv->data_bittiming_const)))
|
||||
priv->data_bittiming_const)) ||
|
||||
|
||||
(priv->termination_const &&
|
||||
(nla_put_u16(skb, IFLA_CAN_TERMINATION, priv->termination) ||
|
||||
nla_put(skb, IFLA_CAN_TERMINATION_CONST,
|
||||
sizeof(*priv->termination_const) *
|
||||
priv->termination_const_cnt,
|
||||
priv->termination_const))))
|
||||
|
||||
return -EMSGSIZE;
|
||||
|
||||
return 0;
|
||||
|
@ -1073,6 +1110,16 @@ static struct rtnl_link_ops can_link_ops __read_mostly = {
|
|||
*/
|
||||
int register_candev(struct net_device *dev)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
|
||||
/* Ensure termination_const, termination_const_cnt and
|
||||
* do_set_termination consistency. All must be either set or
|
||||
* unset.
|
||||
*/
|
||||
if ((!priv->termination_const != !priv->termination_const_cnt) ||
|
||||
(!priv->termination_const != !priv->do_set_termination))
|
||||
return -EINVAL;
|
||||
|
||||
dev->rtnl_link_ops = &can_link_ops;
|
||||
return register_netdev(dev);
|
||||
}
|
||||
|
|
|
@ -38,6 +38,9 @@ struct can_priv {
|
|||
struct can_bittiming bittiming, data_bittiming;
|
||||
const struct can_bittiming_const *bittiming_const,
|
||||
*data_bittiming_const;
|
||||
const u16 *termination_const;
|
||||
unsigned int termination_const_cnt;
|
||||
u16 termination;
|
||||
struct can_clock clock;
|
||||
|
||||
enum can_state state;
|
||||
|
@ -53,6 +56,7 @@ struct can_priv {
|
|||
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_termination)(struct net_device *dev, u16 term);
|
||||
int (*do_get_state)(const struct net_device *dev,
|
||||
enum can_state *state);
|
||||
int (*do_get_berr_counter)(const struct net_device *dev,
|
||||
|
|
|
@ -127,9 +127,14 @@ enum {
|
|||
IFLA_CAN_BERR_COUNTER,
|
||||
IFLA_CAN_DATA_BITTIMING,
|
||||
IFLA_CAN_DATA_BITTIMING_CONST,
|
||||
IFLA_CAN_TERMINATION,
|
||||
IFLA_CAN_TERMINATION_CONST,
|
||||
__IFLA_CAN_MAX
|
||||
};
|
||||
|
||||
#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1)
|
||||
|
||||
/* u16 termination range: 1..65535 Ohms */
|
||||
#define CAN_TERMINATION_DISABLED 0
|
||||
|
||||
#endif /* !_UAPI_CAN_NETLINK_H */
|
||||
|
|
Loading…
Reference in a new issue