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

candev: add/update helpers for CAN FD

- update sanity checks
- add DLC to length conversion helpers
- can_dlc2len() - get data length from can_dlc with sanitized can_dlc
- can_len2dlc() - map the sanitized data length to an appropriate DLC

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Oliver Hartkopp and committed by
Marc Kleine-Budde
1e0625fa e2d265d3

+58 -8
+34 -1
drivers/net/can/dev.c
··· 33 33 MODULE_LICENSE("GPL v2"); 34 34 MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>"); 35 35 36 + /* CAN DLC to real data length conversion helpers */ 37 + 38 + static const u8 dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7, 39 + 8, 12, 16, 20, 24, 32, 48, 64}; 40 + 41 + /* get data length from can_dlc with sanitized can_dlc */ 42 + u8 can_dlc2len(u8 can_dlc) 43 + { 44 + return dlc2len[can_dlc & 0x0F]; 45 + } 46 + EXPORT_SYMBOL_GPL(can_dlc2len); 47 + 48 + static const u8 len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */ 49 + 9, 9, 9, 9, /* 9 - 12 */ 50 + 10, 10, 10, 10, /* 13 - 16 */ 51 + 11, 11, 11, 11, /* 17 - 20 */ 52 + 12, 12, 12, 12, /* 21 - 24 */ 53 + 13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */ 54 + 14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */ 55 + 14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */ 56 + 15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */ 57 + 15, 15, 15, 15, 15, 15, 15, 15}; /* 57 - 64 */ 58 + 59 + /* map the sanitized data length to an appropriate data length code */ 60 + u8 can_len2dlc(u8 len) 61 + { 62 + if (unlikely(len > 64)) 63 + return 0xF; 64 + 65 + return len2dlc[len]; 66 + } 67 + EXPORT_SYMBOL_GPL(can_len2dlc); 68 + 36 69 #ifdef CONFIG_CAN_CALC_BITTIMING 37 70 #define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */ 38 71 ··· 487 454 static void can_setup(struct net_device *dev) 488 455 { 489 456 dev->type = ARPHRD_CAN; 490 - dev->mtu = sizeof(struct can_frame); 457 + dev->mtu = CAN_MTU; 491 458 dev->hard_header_len = 0; 492 459 dev->addr_len = 0; 493 460 dev->tx_queue_len = 10;
+24 -7
include/linux/can/dev.h
··· 61 61 * To be used in the CAN netdriver receive path to ensure conformance with 62 62 * ISO 11898-1 Chapter 8.4.2.3 (DLC field) 63 63 */ 64 - #define get_can_dlc(i) (min_t(__u8, (i), 8)) 64 + #define get_can_dlc(i) (min_t(__u8, (i), CAN_MAX_DLC)) 65 + #define get_canfd_dlc(i) (min_t(__u8, (i), CANFD_MAX_DLC)) 65 66 66 67 /* Drop a given socketbuffer if it does not contain a valid CAN frame. */ 67 68 static inline int can_dropped_invalid_skb(struct net_device *dev, 68 69 struct sk_buff *skb) 69 70 { 70 - const struct can_frame *cf = (struct can_frame *)skb->data; 71 + const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 71 72 72 - if (unlikely(skb->len != sizeof(*cf) || cf->can_dlc > 8)) { 73 - kfree_skb(skb); 74 - dev->stats.tx_dropped++; 75 - return 1; 76 - } 73 + if (skb->protocol == htons(ETH_P_CAN)) { 74 + if (unlikely(skb->len != CAN_MTU || 75 + cfd->len > CAN_MAX_DLEN)) 76 + goto inval_skb; 77 + } else if (skb->protocol == htons(ETH_P_CANFD)) { 78 + if (unlikely(skb->len != CANFD_MTU || 79 + cfd->len > CANFD_MAX_DLEN)) 80 + goto inval_skb; 81 + } else 82 + goto inval_skb; 77 83 78 84 return 0; 85 + 86 + inval_skb: 87 + kfree_skb(skb); 88 + dev->stats.tx_dropped++; 89 + return 1; 79 90 } 91 + 92 + /* get data length from can_dlc with sanitized can_dlc */ 93 + u8 can_dlc2len(u8 can_dlc); 94 + 95 + /* map the sanitized data length to an appropriate data length code */ 96 + u8 can_len2dlc(u8 len); 80 97 81 98 struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max); 82 99 void free_candev(struct net_device *dev);