Re: [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length

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

 



On Sun. 10 Jan 2021 at 02:40, Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx> wrote:
>
> In order to implement byte queue limits (bql) in CAN drivers, the length of the
> CAN frame needs to be passed into the networking stack after queueing and after
> transmission completion.
>
> To avoid to calculate this length twice, extend the struct can_skb_priv to hold
> the length of the CAN frame and extend __can_get_echo_skb() to return that
> value.
>
> Signed-off-by: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx>
> ---
>  drivers/net/can/dev/rx-offload.c | 2 +-
>  drivers/net/can/dev/skb.c        | 9 +++++++--
>  include/linux/can/skb.h          | 4 +++-
>  3 files changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c
> index 3c1912c0430b..6a26b5282df1 100644
> --- a/drivers/net/can/dev/rx-offload.c
> +++ b/drivers/net/can/dev/rx-offload.c
> @@ -271,7 +271,7 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
>         u8 len;
>         int err;
>
> -       skb = __can_get_echo_skb(dev, idx, &len);
> +       skb = __can_get_echo_skb(dev, idx, &len, NULL);
>         if (!skb)
>                 return 0;
>
> diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
> index 26cd597ff771..24f782a23409 100644
> --- a/drivers/net/can/dev/skb.c
> +++ b/drivers/net/can/dev/skb.c
> @@ -76,7 +76,8 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
>  EXPORT_SYMBOL_GPL(can_put_echo_skb);
>
>  struct sk_buff *
> -__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
> +__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
> +                  unsigned int *frame_len_ptr)
>  {
>         struct can_priv *priv = netdev_priv(dev);
>
> @@ -91,6 +92,7 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
>                  * 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 */
> @@ -99,6 +101,9 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
>                 else
>                         *len_ptr = cf->len;
>
> +               if (frame_len_ptr)
> +                       *frame_len_ptr = can_skb_priv->frame_len;
> +
>                 priv->echo_skb[idx] = NULL;
>
>                 return skb;
> @@ -118,7 +123,7 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
>         struct sk_buff *skb;
>         u8 len;
>
> -       skb = __can_get_echo_skb(dev, idx, &len);
> +       skb = __can_get_echo_skb(dev, idx, &len, NULL);
>         if (!skb)
>                 return 0;
>

The can_skb_priv->frame_len is smart. Nice change :)

I have one knit pick concerning the symmetry between
can_put_echo_skb() and can_get_echo_skb().

My current understanding is that:
  * In the tx branch, we need to manually set can_skb_priv->frame_len. Example:
        can_skb_prv(skb)->frame_len = can_skb_get_frame_len(skb);
        can_put_echo_skb(skb, netdev, skb_idx);
  * In the rx branch, it is accessed through the function can_get_echo_skb():
        unsigned int frame_len;
        can_get_echo_skb(skb, netdev, skb_idx, &frame_len);

Please correct me if my understanding is wrong.

I think that you did not modify can_put_echo_skb() so that the
drivers which do not implement the BQL would not have to call
can_skb_get_frame_len(skb) and thus saving computing resources. I
also understand that the motivation to modify can_put_echo_skb()
is to factorise the code.

But the absence of symmetry in the final result bothers me a
bit. Reading manually can_skb_prv(skb)->frame_len by hand would
look as below, which I think is short enough not to be
factorized within can_get_echo_skb():
        struct sk_buff *skb = priv->echo_skb[skb_idx];
        unsigned int frame_len = can_skb_prv(skb)->frame_len;
        can_get_echo_skb(skb, netdev, skb_idx);

So at the end, I would suggest not to modify can_get_echo_skb()
so that it is a better "mirror" of can_put_echo_skb().

> diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
> index c90ebbd3008c..5db9da30843c 100644
> --- a/include/linux/can/skb.h
> +++ b/include/linux/can/skb.h
> @@ -20,7 +20,7 @@ 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);
>  struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
> -                                  u8 *len_ptr);
> +                                  u8 *len_ptr, unsigned int *frame_len_ptr);
>  unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx);
>  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);
> @@ -42,11 +42,13 @@ struct sk_buff *alloc_can_err_skb(struct net_device *dev,
>   * struct can_skb_priv - private additional data inside CAN sk_buffs
>   * @ifindex:   ifindex of the first interface the CAN frame appeared on
>   * @skbcnt:    atomic counter to have an unique id together with skb pointer
> + * @frame_len: length of CAN frame in data link layer
>   * @cf:                align to the following CAN frame at skb->data
>   */
>  struct can_skb_priv {
>         int ifindex;
>         int skbcnt;
> +       unsigned int frame_len;
>         struct can_frame cf[];
>  };
>
> --
> 2.29.2
>
>



[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