|
@@ -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;
|
|
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));
|
|
size += nla_total_size(sizeof(struct can_bittiming));
|
|
if (priv->data_bittiming_const) /* IFLA_CAN_DATA_BITTIMING_CONST */
|
|
if (priv->data_bittiming_const) /* IFLA_CAN_DATA_BITTIMING_CONST */
|
|
size += nla_total_size(sizeof(struct can_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;
|
|
return size;
|
|
}
|
|
}
|
|
@@ -1018,7 +1047,15 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|
(priv->data_bittiming_const &&
|
|
(priv->data_bittiming_const &&
|
|
nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
|
|
nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
|
|
sizeof(*priv->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 -EMSGSIZE;
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -1073,6 +1110,16 @@ static struct rtnl_link_ops can_link_ops __read_mostly = {
|
|
*/
|
|
*/
|
|
int register_candev(struct net_device *dev)
|
|
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;
|
|
dev->rtnl_link_ops = &can_link_ops;
|
|
return register_netdev(dev);
|
|
return register_netdev(dev);
|
|
}
|
|
}
|