Re: [RFC PATCH v2 3/5] can: dev: add CAN XL support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 14.07.2022 18:05:39, Oliver Hartkopp wrote:
> Extend the CAN device driver infrastructure to handle CAN XL frames.
> This especially addresses the increased data length which is extended
> to uint16 for CAN XL.
> 
> Signed-off-by: Oliver Hartkopp <socketcan@xxxxxxxxxxxx>
> ---
>  drivers/net/can/dev/rx-offload.c |  2 +-
>  drivers/net/can/dev/skb.c        | 55 ++++++++++++++++++++++++++------
>  include/linux/can/skb.h          |  6 +++-
>  3 files changed, 52 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c
> index a32a01c172d4..8505e547e922 100644
> --- a/drivers/net/can/dev/rx-offload.c
> +++ b/drivers/net/can/dev/rx-offload.c
> @@ -245,11 +245,11 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
>  					 unsigned int *frame_len_ptr)
>  {
>  	struct net_device *dev = offload->dev;
>  	struct net_device_stats *stats = &dev->stats;
>  	struct sk_buff *skb;
> -	u8 len;
> +	unsigned int len;
>  	int err;
>  
>  	skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr);
>  	if (!skb)
>  		return 0;
> diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
> index 8bb62dd864c8..c4283fa680be 100644
> --- a/drivers/net/can/dev/skb.c
> +++ b/drivers/net/can/dev/skb.c
> @@ -53,11 +53,12 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
>  	BUG_ON(idx >= priv->echo_skb_max);
>  
>  	/* check flag whether this packet has to be looped back */
>  	if (!(dev->flags & IFF_ECHO) ||
>  	    (skb->protocol != htons(ETH_P_CAN) &&
> -	     skb->protocol != htons(ETH_P_CANFD))) {
> +	     skb->protocol != htons(ETH_P_CANFD) &&
> +	     skb->protocol != htons(ETH_P_CANXL))) {
>  		kfree_skb(skb);
>  		return 0;
>  	}
>  
>  	if (!priv->echo_skb[idx]) {
> @@ -86,12 +87,12 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(can_put_echo_skb);
>  
>  struct sk_buff *
> -__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
> -		   unsigned int *frame_len_ptr)
> +__can_get_echo_skb(struct net_device *dev, unsigned int idx,
> +		   unsigned int *len_ptr, unsigned int *frame_len_ptr)
>  {
>  	struct can_priv *priv = netdev_priv(dev);
>  
>  	if (idx >= priv->echo_skb_max) {
>  		netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
> @@ -103,17 +104,13 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
>  		/* Using "struct canfd_frame::len" for the frame
>  		 * length is supported on both CAN and CANFD frames.
>  		 */
>  		struct sk_buff *skb = priv->echo_skb[idx];
>  		struct can_skb_priv *can_skb_priv = can_skb_prv(skb);
> -		struct canfd_frame *cf = (struct canfd_frame *)skb->data;
>  
>  		/* get the real payload length for netdev statistics */
> -		if (cf->can_id & CAN_RTR_FLAG)
> -			*len_ptr = 0;
> -		else
> -			*len_ptr = cf->len;
> +		*len_ptr = can_skb_get_data_len(skb);
>  
>  		if (frame_len_ptr)
>  			*frame_len_ptr = can_skb_priv->frame_len;
>  
>  		priv->echo_skb[idx] = NULL;
> @@ -139,11 +136,11 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
>   */
>  unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx,
>  			      unsigned int *frame_len_ptr)
>  {
>  	struct sk_buff *skb;
> -	u8 len;
> +	unsigned int len;
>  
>  	skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr);
>  	if (!skb)
>  		return 0;
>  
> @@ -244,10 +241,47 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
>  
>  	return skb;
>  }
>  EXPORT_SYMBOL_GPL(alloc_canfd_skb);
>  
> +struct sk_buff *alloc_canxl_skb(struct net_device *dev,
> +				struct canxl_frame **cfx,
> +				unsigned int datalen)
> +{
> +	struct sk_buff *skb;
> +
> +	if (datalen < CANXL_MIN_DLEN || datalen > CANXL_MAX_DLEN)
> +		goto out_error;
> +
> +	skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
> +			       CANXL_HEAD_SZ + datalen);
> +	if (unlikely(!skb))
> +		goto out_error;
> +
> +	skb->protocol = htons(ETH_P_CANXL);
> +	skb->pkt_type = PACKET_BROADCAST;
> +	skb->ip_summed = CHECKSUM_UNNECESSARY;
> +
> +	skb_reset_mac_header(skb);
> +	skb_reset_network_header(skb);
> +	skb_reset_transport_header(skb);
> +
> +	can_skb_reserve(skb);
> +	can_skb_prv(skb)->ifindex = dev->ifindex;
> +	can_skb_prv(skb)->skbcnt = 0;
> +
> +	*cfx = skb_put_zero(skb, CANXL_HEAD_SZ + datalen);

Should the CANXL_XLF be set here?

I have a bad feeling if we have a struct canxl_frame with a fixed size,
but it might not completely be backed by data.....

For example, I've updated the gs_usb driver to work with flexible arrays
to accommodate the different USB frame length: 

https://elixir.bootlin.com/linux/latest/source/drivers/net/can/usb/gs_usb.c#L216

Maybe we should talk to Kees Cook what's best to use here.

Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux