aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/can
diff options
context:
space:
mode:
authorOliver Hartkopp <socketcan@hartkopp.net>2012-06-13 20:48:21 +0200
committerMarc Kleine-Budde <mkl@pengutronix.de>2012-06-19 21:40:14 +0200
commit1e0625facab2e871472472b7df87d8fbe6caf75a (patch)
tree831d0adba939e1d19e33d59b73508b5d306ed412 /include/linux/can
parentcanfd: add support for CAN FD in CAN_RAW sockets (diff)
downloadlinux-dev-1e0625facab2e871472472b7df87d8fbe6caf75a.tar.xz
linux-dev-1e0625facab2e871472472b7df87d8fbe6caf75a.zip
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>
Diffstat (limited to 'include/linux/can')
-rw-r--r--include/linux/can/dev.h33
1 files changed, 25 insertions, 8 deletions
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 5d2efe7e3f1b..ee5a771fb20d 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -61,23 +61,40 @@ struct can_priv {
* To be used in the CAN netdriver receive path to ensure conformance with
* ISO 11898-1 Chapter 8.4.2.3 (DLC field)
*/
-#define get_can_dlc(i) (min_t(__u8, (i), 8))
+#define get_can_dlc(i) (min_t(__u8, (i), CAN_MAX_DLC))
+#define get_canfd_dlc(i) (min_t(__u8, (i), CANFD_MAX_DLC))
/* Drop a given socketbuffer if it does not contain a valid CAN frame. */
static inline int can_dropped_invalid_skb(struct net_device *dev,
struct sk_buff *skb)
{
- const struct can_frame *cf = (struct can_frame *)skb->data;
-
- if (unlikely(skb->len != sizeof(*cf) || cf->can_dlc > 8)) {
- kfree_skb(skb);
- dev->stats.tx_dropped++;
- return 1;
- }
+ const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
+
+ if (skb->protocol == htons(ETH_P_CAN)) {
+ if (unlikely(skb->len != CAN_MTU ||
+ cfd->len > CAN_MAX_DLEN))
+ goto inval_skb;
+ } else if (skb->protocol == htons(ETH_P_CANFD)) {
+ if (unlikely(skb->len != CANFD_MTU ||
+ cfd->len > CANFD_MAX_DLEN))
+ goto inval_skb;
+ } else
+ goto inval_skb;
return 0;
+
+inval_skb:
+ kfree_skb(skb);
+ dev->stats.tx_dropped++;
+ return 1;
}
+/* get data length from can_dlc with sanitized can_dlc */
+u8 can_dlc2len(u8 can_dlc);
+
+/* map the sanitized data length to an appropriate data length code */
+u8 can_len2dlc(u8 len);
+
struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max);
void free_candev(struct net_device *dev);