Re: [PATCH v2 18/18] can: m_can: Implement transmit submission coalescing

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

 



Hi Markus,

I did not have time for a deep review yet. But so far, I didn't find
anything odd aside from two nitpicks.

On Thu. 26 Jan 2023 à 04:53, Markus Schneider-Pargmann
<msp@xxxxxxxxxxxx> a écrit :
>
> m_can supports submitting mulitple transmits with one register write.
                            ^^^^^^^^
multiple

> This is an interesting option to reduce the number of SPI transfers for
> peripheral chips.
>
> The m_can_tx_op is extended with a bool that signals if it is the last
> transmission and the submit should be executed immediately.
>
> The worker then writes the skb to the FIFO and submits it only if the
> submit bool is set. If it isn't set, the worker will write the next skb
> which is waiting in the workqueue to the FIFO, etc.
>
> Signed-off-by: Markus Schneider-Pargmann <msp@xxxxxxxxxxxx>
> ---
>
> Notes:
>     Notes:
>     - I ran into lost messages in the receive FIFO when using this
>       implementation. I guess this only shows up with my test setup in
>       loopback mode and maybe not enough CPU power.
>     - I put this behind the tx-frames ethtool coalescing option as we do
>       wait before submitting packages but it is something different than the
>       tx-frames-irq option. I am not sure if this is the correct option,
>       please let me know.
>
>  drivers/net/can/m_can/m_can.c | 55 ++++++++++++++++++++++++++++++++---
>  drivers/net/can/m_can/m_can.h |  6 ++++
>  2 files changed, 57 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
> index c6a09369d1aa..99bfcfec3775 100644
> --- a/drivers/net/can/m_can/m_can.c
> +++ b/drivers/net/can/m_can/m_can.c
> @@ -1504,6 +1504,9 @@ static int m_can_start(struct net_device *dev)
>         if (ret)
>                 return ret;
>
> +       netdev_queue_set_dql_min_limit(netdev_get_tx_queue(cdev->net, 0),
> +                                      cdev->tx_max_coalesced_frames);
> +
>         cdev->can.state = CAN_STATE_ERROR_ACTIVE;
>
>         m_can_enable_all_interrupts(cdev);
> @@ -1813,8 +1816,13 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev,
>                  */
>                 can_put_echo_skb(skb, dev, putidx, frame_len);
>
> -               /* Enable TX FIFO element to start transfer  */
> -               m_can_write(cdev, M_CAN_TXBAR, (1 << putidx));
> +               if (cdev->is_peripheral) {
> +                       /* Delay enabling TX FIFO element */
> +                       cdev->tx_peripheral_submit |= BIT(putidx);
> +               } else {
> +                       /* Enable TX FIFO element to start transfer  */
> +                       m_can_write(cdev, M_CAN_TXBAR, BIT(putidx));
> +               }
>                 cdev->tx_fifo_putidx = (++cdev->tx_fifo_putidx >= cdev->can.echo_skb_max ?
>                                         0 : cdev->tx_fifo_putidx);
>         }
> @@ -1827,6 +1835,17 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev,
>         return NETDEV_TX_BUSY;
>  }
>
> +static void m_can_tx_submit(struct m_can_classdev *cdev)
> +{
> +       if (cdev->version == 30)
> +               return;
> +       if (!cdev->is_peripheral)
> +               return;
> +
> +       m_can_write(cdev, M_CAN_TXBAR, cdev->tx_peripheral_submit);
> +       cdev->tx_peripheral_submit = 0;
> +}
> +
>  static void m_can_tx_work_queue(struct work_struct *ws)
>  {
>         struct m_can_tx_op *op = container_of(ws, struct m_can_tx_op, work);
> @@ -1835,11 +1854,15 @@ static void m_can_tx_work_queue(struct work_struct *ws)
>
>         op->skb = NULL;
>         m_can_tx_handler(cdev, skb);
> +       if (op->submit)
> +               m_can_tx_submit(cdev);
>  }
>
> -static void m_can_tx_queue_skb(struct m_can_classdev *cdev, struct sk_buff *skb)
> +static void m_can_tx_queue_skb(struct m_can_classdev *cdev, struct sk_buff *skb,
> +                              bool submit)
>  {
>         cdev->tx_ops[cdev->next_tx_op].skb = skb;
> +       cdev->tx_ops[cdev->next_tx_op].submit = submit;
>         queue_work(cdev->tx_wq, &cdev->tx_ops[cdev->next_tx_op].work);
>
>         ++cdev->next_tx_op;
> @@ -1851,6 +1874,7 @@ static netdev_tx_t m_can_start_peripheral_xmit(struct m_can_classdev *cdev,
>                                                struct sk_buff *skb)
>  {
>         netdev_tx_t err;
> +       bool submit;
>
>         if (cdev->can.state == CAN_STATE_BUS_OFF) {
>                 m_can_clean(cdev->net);
> @@ -1861,7 +1885,15 @@ static netdev_tx_t m_can_start_peripheral_xmit(struct m_can_classdev *cdev,
>         if (err != NETDEV_TX_OK)
>                 return err;
>
> -       m_can_tx_queue_skb(cdev, skb);
> +       ++cdev->nr_txs_without_submit;
> +       if (cdev->nr_txs_without_submit >= cdev->tx_max_coalesced_frames ||
> +           !netdev_xmit_more()) {
> +               cdev->nr_txs_without_submit = 0;
> +               submit = true;
> +       } else {
> +               submit = false;
> +       }
> +       m_can_tx_queue_skb(cdev, skb, submit);
>
>         return NETDEV_TX_OK;
>  }
> @@ -1993,6 +2025,7 @@ static int m_can_get_coalesce(struct net_device *dev,
>
>         ec->rx_max_coalesced_frames_irq = cdev->rx_max_coalesced_frames_irq;
>         ec->rx_coalesce_usecs_irq = cdev->rx_coalesce_usecs_irq;
> +       ec->tx_max_coalesced_frames = cdev->tx_max_coalesced_frames;
>         ec->tx_max_coalesced_frames_irq = cdev->tx_max_coalesced_frames_irq;
>         ec->tx_coalesce_usecs_irq = cdev->tx_coalesce_usecs_irq;
>
> @@ -2037,6 +2070,18 @@ static int m_can_set_coalesce(struct net_device *dev,
>                 netdev_err(dev, "tx-frames-irq and tx-usecs-irq can only be set together\n");
>                 return -EINVAL;
>         }
> +       if (ec->tx_max_coalesced_frames > cdev->mcfg[MRAM_TXE].num) {
> +               netdev_err(dev, "tx-frames (%u) greater than the TX event FIFO (%u)\n",
                                             ^^^^
          ^^^^
Avoid parenthesis.
Ref: https://www.kernel.org/doc/html/latest/process/coding-style.html#printing-kernel-messages:

  Printing numbers in parentheses (%d) adds no value and should be avoided.

This comment applies to other patches in the series as well.

> +                          ec->tx_max_coalesced_frames,
> +                          cdev->mcfg[MRAM_TXE].num);
> +               return -EINVAL;
> +       }
> +       if (ec->tx_max_coalesced_frames > cdev->mcfg[MRAM_TXB].num) {
> +               netdev_err(dev, "tx-frames (%u) greater than the TX FIFO (%u)\n",
> +                          ec->tx_max_coalesced_frames,
> +                          cdev->mcfg[MRAM_TXB].num);
> +               return -EINVAL;
> +       }
>         if (ec->rx_coalesce_usecs_irq != 0 && ec->tx_coalesce_usecs_irq != 0 &&
>             ec->rx_coalesce_usecs_irq != ec->tx_coalesce_usecs_irq) {
>                 netdev_err(dev, "rx-usecs-irq (%u) needs to be equal to tx-usecs-irq (%u) if both are enabled\n",
> @@ -2047,6 +2092,7 @@ static int m_can_set_coalesce(struct net_device *dev,
>
>         cdev->rx_max_coalesced_frames_irq = ec->rx_max_coalesced_frames_irq;
>         cdev->rx_coalesce_usecs_irq = ec->rx_coalesce_usecs_irq;
> +       cdev->tx_max_coalesced_frames = ec->tx_max_coalesced_frames;
>         cdev->tx_max_coalesced_frames_irq = ec->tx_max_coalesced_frames_irq;
>         cdev->tx_coalesce_usecs_irq = ec->tx_coalesce_usecs_irq;
>
> @@ -2064,6 +2110,7 @@ static const struct ethtool_ops m_can_ethtool_ops = {
>         .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS_IRQ |
>                 ETHTOOL_COALESCE_RX_MAX_FRAMES_IRQ |
>                 ETHTOOL_COALESCE_TX_USECS_IRQ |
> +               ETHTOOL_COALESCE_TX_MAX_FRAMES |
>                 ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ,
>         .get_ts_info = ethtool_op_get_ts_info,
>         .get_coalesce = m_can_get_coalesce,
> diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h
> index bfef2c89e239..e209de81b5a4 100644
> --- a/drivers/net/can/m_can/m_can.h
> +++ b/drivers/net/can/m_can/m_can.h
> @@ -74,6 +74,7 @@ struct m_can_tx_op {
>         struct m_can_classdev *cdev;
>         struct work_struct work;
>         struct sk_buff *skb;
> +       bool submit;
>  };
>
>  struct m_can_classdev {
> @@ -103,6 +104,7 @@ struct m_can_classdev {
>         u32 active_interrupts;
>         u32 rx_max_coalesced_frames_irq;
>         u32 rx_coalesce_usecs_irq;
> +       u32 tx_max_coalesced_frames;
>         u32 tx_max_coalesced_frames_irq;
>         u32 tx_coalesce_usecs_irq;
>
> @@ -117,6 +119,10 @@ struct m_can_classdev {
>         int tx_fifo_size;
>         int next_tx_op;
>
> +       int nr_txs_without_submit;
> +       /* bitfield of fifo elements that will be submitted together */
> +       u32 tx_peripheral_submit;
> +
>         struct mram_cfg mcfg[MRAM_CFG_NUM];
>  };



[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