diff options
| author | 2022-09-15 09:13:31 +0200 | |
|---|---|---|
| committer | 2022-09-15 09:13:31 +0200 | |
| commit | c337f103f7781bc8223c650e94492bf08df71482 (patch) | |
| tree | c1532f305f9e94718e2ff618c36452ad6d818dda /include/linux | |
| parent | can: flexcan: Switch to use dev_err_probe() helper (diff) | |
| parent | can: raw: add CAN XL support (diff) | |
| download | linux-dev-c337f103f7781bc8223c650e94492bf08df71482.tar.xz linux-dev-c337f103f7781bc8223c650e94492bf08df71482.zip | |
Merge patch series "can: support CAN XL"
Oliver Hartkopp <socketcan@hartkopp.net> says:
The CAN with eXtended data Length (CAN XL) is a new CAN protocol with
a 10Mbit/s data transfer with a new physical layer transceiver (for
this data section). CAN XL allows up to 2048 byte of payload and
shares the arbitration principle (11 bit priority) known from
Classical CAN and CAN FD. RTR and 29 bit identifiers are not
implemented in CAN XL.
A short introduction to CAN XL can be found here:
https://www.can-cia.org/can-knowledge/can/can-xl/
https://github.com/linux-can/can-doc/blob/master/presentations/CAN-XL-Intro.pdf
V1: https://lore.kernel.org/all/20220711183426.96446-1-socketcan@hartkopp.net
V2: Major rework after discussion and feedback on Linux-CAN ML
https://lore.kernel.org/all/20220714160541.2071-1-socketcan@hartkopp.net
- rework of struct canxl_frame
- CANXL_XLF flag is now the switch between CAN XL and CAN/CANFD
- variable length in r/w operations for CAN XL frames
- write CAN XL frame to raw socket enforces size <-> canxl_frame.len sync
V3: Fix length for CAN XL frames inside the sk_buff
https://lore.kernel.org/all/20220717132730.30295-1-socketcan@hartkopp.net
- extend the CAN_RAW sockopt to handle fixed/truncated read/write operations
V4: Fix patch 5 (can: raw: add CAN XL support)
https://lore.kernel.org/all/20220719054204.29061-1-socketcan@hartkopp.net
- fix return value (move 'err = -EINVAL' in raw_sendmsg())
- add CAN XL frame handling in can_rcv()
- change comment for CAN_RAW_XL_[RT]X_DYN definition (allow -> enable)
V5: Remove CAN_RAW_XL_[RT]X_DYN definition again
https://lore.kernel.org/all/20220719112748.3281-1-socketcan@hartkopp.net
- CAN_RAW_XL_[RT]X_DYN (truncated data) feature is now enabled by default
- use CANXL_MIN_DLEN instead of '1' in canxl_frame definition
- add missing 'err = -EINVAL' initialization in raw_sendmsg())
V6: https://lore.kernel.org/all/20220724074402.117394-1-socketcan@hartkopp.net
- rework an separate skb identification and length helpers
- add CANFD_FDF flag in all CAN FD frame structures
- simplify patches for infrastructure and raw sockets
- add vxcan support in virtual CAN interface patch
V7: https://lore.kernel.org/all/20220729154107.1875-1-socketcan@hartkopp.net
- fixed indention as remarked by Marc
- set CANFD_FDF flag when detecting CAN FD frames generated by PF_PACKET
- Allow to use variable CAN XL MTU sizes to enforce real time requirements
on CAN XL segments (e.g. to support of CAN CiA segmentation concept)
V8: https://lore.kernel.org/all/20220801190010.3344-1-socketcan@hartkopp.net
- fixed typo as remarked by Vincent
- rebased to latest can-next/net-next tree
V9: https://lore.kernel.org/all/20220912170725.120748-1-socketcan@hartkopp.net
- rebased to latest can-next/net-next tree
- updated and extended public available CAN XL documenatation in cover letter
- renamed struct canxl_frame variable cfx to cxl as suggested by Vincent
- Added Acked-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr> tag
Link: https://lore.kernel.org/all/20220912170725.120748-1-socketcan@hartkopp.net
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/can/dev.h | 5 | ||||
| -rw-r--r-- | include/linux/can/skb.h | 57 |
2 files changed, 60 insertions, 2 deletions
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index c3e50e537e39..58f5431a5559 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -147,6 +147,11 @@ static inline u32 can_get_static_ctrlmode(struct can_priv *priv) return priv->ctrlmode & ~priv->ctrlmode_supported; } +static inline bool can_is_canxl_dev_mtu(unsigned int mtu) +{ + return (mtu >= CANXL_MIN_MTU && mtu <= CANXL_MAX_MTU); +} + void can_setup(struct net_device *dev); struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max, diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h index 182749e858b3..1abc25a8d144 100644 --- a/include/linux/can/skb.h +++ b/include/linux/can/skb.h @@ -20,7 +20,8 @@ void can_flush_echo_skb(struct net_device *dev); int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, unsigned int idx, unsigned int frame_len); struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, - u8 *len_ptr, unsigned int *frame_len_ptr); + unsigned int *len_ptr, + unsigned int *frame_len_ptr); unsigned int __must_check can_get_echo_skb(struct net_device *dev, unsigned int idx, unsigned int *frame_len_ptr); @@ -29,6 +30,9 @@ void can_free_echo_skb(struct net_device *dev, unsigned int idx, struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf); struct sk_buff *alloc_canfd_skb(struct net_device *dev, struct canfd_frame **cfd); +struct sk_buff *alloc_canxl_skb(struct net_device *dev, + struct canxl_frame **cxl, + unsigned int data_len); struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf); bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb); @@ -97,10 +101,59 @@ static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb) return nskb; } +static inline bool can_is_can_skb(const struct sk_buff *skb) +{ + struct can_frame *cf = (struct can_frame *)skb->data; + + /* the CAN specific type of skb is identified by its data length */ + return (skb->len == CAN_MTU && cf->len <= CAN_MAX_DLEN); +} + static inline bool can_is_canfd_skb(const struct sk_buff *skb) { + struct canfd_frame *cfd = (struct canfd_frame *)skb->data; + /* the CAN specific type of skb is identified by its data length */ - return skb->len == CANFD_MTU; + return (skb->len == CANFD_MTU && cfd->len <= CANFD_MAX_DLEN); +} + +static inline bool can_is_canxl_skb(const struct sk_buff *skb) +{ + const struct canxl_frame *cxl = (struct canxl_frame *)skb->data; + + if (skb->len < CANXL_HDR_SIZE + CANXL_MIN_DLEN || skb->len > CANXL_MTU) + return false; + + /* this also checks valid CAN XL data length boundaries */ + if (skb->len != CANXL_HDR_SIZE + cxl->len) + return false; + + return cxl->flags & CANXL_XLF; +} + +/* get length element value from can[|fd|xl]_frame structure */ +static inline unsigned int can_skb_get_len_val(struct sk_buff *skb) +{ + const struct canxl_frame *cxl = (struct canxl_frame *)skb->data; + const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; + + if (can_is_canxl_skb(skb)) + return cxl->len; + + return cfd->len; +} + +/* get needed data length inside CAN frame for all frame types (RTR aware) */ +static inline unsigned int can_skb_get_data_len(struct sk_buff *skb) +{ + unsigned int len = can_skb_get_len_val(skb); + const struct can_frame *cf = (struct can_frame *)skb->data; + + /* RTR frames have an actual length of zero */ + if (can_is_can_skb(skb) && cf->can_id & CAN_RTR_FLAG) + return 0; + + return len; } #endif /* !_CAN_SKB_H */ |
