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

can: skb: add skb CAN frame data length helpers

Add two helpers to retrieve the data length from CAN sk_buffs and prepare
the length information to be a uint16 value for the CAN XL support.

Acked-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://lore.kernel.org/all/20220912170725.120748-3-socketcan@hartkopp.net
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Oliver Hartkopp and committed by
Marc Kleine-Budde
467ef4c7 96a7457a

+28 -10
+1 -1
drivers/net/can/dev/rx-offload.c
··· 247 247 struct net_device *dev = offload->dev; 248 248 struct net_device_stats *stats = &dev->stats; 249 249 struct sk_buff *skb; 250 - u8 len; 250 + unsigned int len; 251 251 int err; 252 252 253 253 skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr);
+4 -8
drivers/net/can/dev/skb.c
··· 91 91 EXPORT_SYMBOL_GPL(can_put_echo_skb); 92 92 93 93 struct sk_buff * 94 - __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr, 95 - unsigned int *frame_len_ptr) 94 + __can_get_echo_skb(struct net_device *dev, unsigned int idx, 95 + unsigned int *len_ptr, unsigned int *frame_len_ptr) 96 96 { 97 97 struct can_priv *priv = netdev_priv(dev); 98 98 ··· 108 108 */ 109 109 struct sk_buff *skb = priv->echo_skb[idx]; 110 110 struct can_skb_priv *can_skb_priv = can_skb_prv(skb); 111 - struct canfd_frame *cf = (struct canfd_frame *)skb->data; 112 111 113 112 if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) 114 113 skb_tstamp_tx(skb, skb_hwtstamps(skb)); 115 114 116 115 /* get the real payload length for netdev statistics */ 117 - if (cf->can_id & CAN_RTR_FLAG) 118 - *len_ptr = 0; 119 - else 120 - *len_ptr = cf->len; 116 + *len_ptr = can_skb_get_data_len(skb); 121 117 122 118 if (frame_len_ptr) 123 119 *frame_len_ptr = can_skb_priv->frame_len; ··· 143 147 unsigned int *frame_len_ptr) 144 148 { 145 149 struct sk_buff *skb; 146 - u8 len; 150 + unsigned int len; 147 151 148 152 skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr); 149 153 if (!skb)
+23 -1
include/linux/can/skb.h
··· 20 20 int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, 21 21 unsigned int idx, unsigned int frame_len); 22 22 struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, 23 - u8 *len_ptr, unsigned int *frame_len_ptr); 23 + unsigned int *len_ptr, 24 + unsigned int *frame_len_ptr); 24 25 unsigned int __must_check can_get_echo_skb(struct net_device *dev, 25 26 unsigned int idx, 26 27 unsigned int *frame_len_ptr); ··· 112 111 113 112 /* the CAN specific type of skb is identified by its data length */ 114 113 return (skb->len == CANFD_MTU && cfd->len <= CANFD_MAX_DLEN); 114 + } 115 + 116 + /* get length element value from can[fd]_frame structure */ 117 + static inline unsigned int can_skb_get_len_val(struct sk_buff *skb) 118 + { 119 + const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 120 + 121 + return cfd->len; 122 + } 123 + 124 + /* get needed data length inside CAN frame for all frame types (RTR aware) */ 125 + static inline unsigned int can_skb_get_data_len(struct sk_buff *skb) 126 + { 127 + unsigned int len = can_skb_get_len_val(skb); 128 + const struct can_frame *cf = (struct can_frame *)skb->data; 129 + 130 + /* RTR frames have an actual length of zero */ 131 + if (can_is_can_skb(skb) && cf->can_id & CAN_RTR_FLAG) 132 + return 0; 133 + 134 + return len; 115 135 } 116 136 117 137 #endif /* !_CAN_SKB_H */