Commit 1e0625fa authored by Oliver Hartkopp's avatar Oliver Hartkopp Committed by Marc Kleine-Budde

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: default avatarOliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent e2d265d3
...@@ -33,6 +33,39 @@ MODULE_DESCRIPTION(MOD_DESC); ...@@ -33,6 +33,39 @@ MODULE_DESCRIPTION(MOD_DESC);
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>"); MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
/* CAN DLC to real data length conversion helpers */
static const u8 dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
8, 12, 16, 20, 24, 32, 48, 64};
/* get data length from can_dlc with sanitized can_dlc */
u8 can_dlc2len(u8 can_dlc)
{
return dlc2len[can_dlc & 0x0F];
}
EXPORT_SYMBOL_GPL(can_dlc2len);
static const u8 len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */
9, 9, 9, 9, /* 9 - 12 */
10, 10, 10, 10, /* 13 - 16 */
11, 11, 11, 11, /* 17 - 20 */
12, 12, 12, 12, /* 21 - 24 */
13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */
14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */
14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */
15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */
15, 15, 15, 15, 15, 15, 15, 15}; /* 57 - 64 */
/* map the sanitized data length to an appropriate data length code */
u8 can_len2dlc(u8 len)
{
if (unlikely(len > 64))
return 0xF;
return len2dlc[len];
}
EXPORT_SYMBOL_GPL(can_len2dlc);
#ifdef CONFIG_CAN_CALC_BITTIMING #ifdef CONFIG_CAN_CALC_BITTIMING
#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */ #define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
...@@ -454,7 +487,7 @@ EXPORT_SYMBOL_GPL(can_bus_off); ...@@ -454,7 +487,7 @@ EXPORT_SYMBOL_GPL(can_bus_off);
static void can_setup(struct net_device *dev) static void can_setup(struct net_device *dev)
{ {
dev->type = ARPHRD_CAN; dev->type = ARPHRD_CAN;
dev->mtu = sizeof(struct can_frame); dev->mtu = CAN_MTU;
dev->hard_header_len = 0; dev->hard_header_len = 0;
dev->addr_len = 0; dev->addr_len = 0;
dev->tx_queue_len = 10; dev->tx_queue_len = 10;
......
...@@ -61,23 +61,40 @@ struct can_priv { ...@@ -61,23 +61,40 @@ struct can_priv {
* To be used in the CAN netdriver receive path to ensure conformance with * To be used in the CAN netdriver receive path to ensure conformance with
* ISO 11898-1 Chapter 8.4.2.3 (DLC field) * 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. */ /* Drop a given socketbuffer if it does not contain a valid CAN frame. */
static inline int can_dropped_invalid_skb(struct net_device *dev, static inline int can_dropped_invalid_skb(struct net_device *dev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
const struct can_frame *cf = (struct can_frame *)skb->data; 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;
if (unlikely(skb->len != sizeof(*cf) || cf->can_dlc > 8)) { return 0;
inval_skb:
kfree_skb(skb); kfree_skb(skb);
dev->stats.tx_dropped++; dev->stats.tx_dropped++;
return 1; return 1;
}
return 0;
} }
/* 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); struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max);
void free_candev(struct net_device *dev); void free_candev(struct net_device *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment