Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Marc Kleine-Budde <mkl@pengutronix.de>

+71 -16
+65 -16
drivers/net/can/dev.c
··· 279 279 return 0; 280 280 } 281 281 282 + /* Checks the validity of predefined bitrate settings */ 283 + static int can_validate_bitrate(struct net_device *dev, struct can_bittiming *bt, 284 + const u32 *bitrate_const, 285 + const unsigned int bitrate_const_cnt) 286 + { 287 + struct can_priv *priv = netdev_priv(dev); 288 + unsigned int i; 289 + 290 + for (i = 0; i < bitrate_const_cnt; i++) { 291 + if (bt->bitrate == bitrate_const[i]) 292 + break; 293 + } 294 + 295 + if (i >= priv->bitrate_const_cnt) 296 + return -EINVAL; 297 + 298 + return 0; 299 + } 300 + 282 301 static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt, 283 - const struct can_bittiming_const *btc) 302 + const struct can_bittiming_const *btc, 303 + const u32 *bitrate_const, 304 + const unsigned int bitrate_const_cnt) 284 305 { 285 306 int err; 286 307 ··· 311 290 * alternatively the CAN timing parameters (tq, prop_seg, etc.) are 312 291 * provided directly which are then checked and fixed up. 313 292 */ 314 - if (!bt->tq && bt->bitrate) 293 + if (!bt->tq && bt->bitrate && btc) 315 294 err = can_calc_bittiming(dev, bt, btc); 316 - else if (bt->tq && !bt->bitrate) 295 + else if (bt->tq && !bt->bitrate && btc) 317 296 err = can_fixup_bittiming(dev, bt, btc); 297 + else if (!bt->tq && bt->bitrate && bitrate_const) 298 + err = can_validate_bitrate(dev, bt, bitrate_const, 299 + bitrate_const_cnt); 318 300 else 319 301 err = -EINVAL; 320 302 ··· 902 878 return -EOPNOTSUPP; 903 879 904 880 memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt)); 905 - if (priv->bittiming_const) { 906 - err = can_get_bittiming(dev, &bt, 907 - priv->bittiming_const); 908 - if (err) 909 - return err; 910 - } 881 + err = can_get_bittiming(dev, &bt, 882 + priv->bittiming_const, 883 + priv->bitrate_const, 884 + priv->bitrate_const_cnt); 885 + if (err) 886 + return err; 911 887 memcpy(&priv->bittiming, &bt, sizeof(bt)); 912 888 913 889 if (priv->do_set_bittiming) { ··· 986 962 987 963 memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]), 988 964 sizeof(dbt)); 989 - if (priv->data_bittiming_const) { 990 - err = can_get_bittiming(dev, &dbt, 991 - priv->data_bittiming_const); 992 - if (err) 993 - return err; 994 - } 965 + err = can_get_bittiming(dev, &dbt, 966 + priv->data_bittiming_const, 967 + priv->data_bitrate_const, 968 + priv->data_bitrate_const_cnt); 969 + if (err) 970 + return err; 995 971 memcpy(&priv->data_bittiming, &dbt, sizeof(dbt)); 996 972 997 973 if (priv->do_set_data_bittiming) { ··· 1053 1029 size += nla_total_size(sizeof(*priv->termination_const) * /* IFLA_CAN_TERMINATION_CONST */ 1054 1030 priv->termination_const_cnt); 1055 1031 } 1032 + if (priv->bitrate_const) /* IFLA_CAN_BITRATE_CONST */ 1033 + size += nla_total_size(sizeof(*priv->bitrate_const) * 1034 + priv->bitrate_const_cnt); 1035 + if (priv->data_bitrate_const) /* IFLA_CAN_DATA_BITRATE_CONST */ 1036 + size += nla_total_size(sizeof(*priv->data_bitrate_const) * 1037 + priv->data_bitrate_const_cnt); 1056 1038 1057 1039 return size; 1058 1040 } ··· 1104 1074 nla_put(skb, IFLA_CAN_TERMINATION_CONST, 1105 1075 sizeof(*priv->termination_const) * 1106 1076 priv->termination_const_cnt, 1107 - priv->termination_const)))) 1077 + priv->termination_const))) || 1078 + 1079 + (priv->bitrate_const && 1080 + nla_put(skb, IFLA_CAN_BITRATE_CONST, 1081 + sizeof(*priv->bitrate_const) * 1082 + priv->bitrate_const_cnt, 1083 + priv->bitrate_const)) || 1084 + 1085 + (priv->data_bitrate_const && 1086 + nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST, 1087 + sizeof(*priv->data_bitrate_const) * 1088 + priv->data_bitrate_const_cnt, 1089 + priv->data_bitrate_const)) 1090 + ) 1108 1091 1109 1092 return -EMSGSIZE; 1110 1093 ··· 1181 1138 */ 1182 1139 if ((!priv->termination_const != !priv->termination_const_cnt) || 1183 1140 (!priv->termination_const != !priv->do_set_termination)) 1141 + return -EINVAL; 1142 + 1143 + if (!priv->bitrate_const != !priv->bitrate_const_cnt) 1144 + return -EINVAL; 1145 + 1146 + if (!priv->data_bitrate_const != !priv->data_bitrate_const_cnt) 1184 1147 return -EINVAL; 1185 1148 1186 1149 dev->rtnl_link_ops = &can_link_ops;
+4
include/linux/can/dev.h
··· 41 41 const u16 *termination_const; 42 42 unsigned int termination_const_cnt; 43 43 u16 termination; 44 + const u32 *bitrate_const; 45 + unsigned int bitrate_const_cnt; 46 + const u32 *data_bitrate_const; 47 + unsigned int data_bitrate_const_cnt; 44 48 struct can_clock clock; 45 49 46 50 enum can_state state;
+2
include/uapi/linux/can/netlink.h
··· 129 129 IFLA_CAN_DATA_BITTIMING_CONST, 130 130 IFLA_CAN_TERMINATION, 131 131 IFLA_CAN_TERMINATION_CONST, 132 + IFLA_CAN_BITRATE_CONST, 133 + IFLA_CAN_DATA_BITRATE_CONST, 132 134 __IFLA_CAN_MAX 133 135 }; 134 136