can: m_can: Batch acknowledge transmit events
authorMarkus Schneider-Pargmann <msp@baylibre.com>
Tue, 6 Dec 2022 11:57:23 +0000 (12:57 +0100)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Mon, 12 Dec 2022 10:58:32 +0000 (11:58 +0100)
Transmit events from the txe fifo can be batch acknowledged by
acknowledging the last read txe fifo item. This will save txe_count
writes which is important for peripheral chips.

Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
Link: https://lore.kernel.org/all/20221206115728.1056014-7-msp@baylibre.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/m_can/m_can.c

index 9476d96..656d2da 100644 (file)
@@ -1023,7 +1023,9 @@ static int m_can_echo_tx_event(struct net_device *dev)
        u32 txe_count = 0;
        u32 m_can_txefs;
        u32 fgi = 0;
+       int ack_fgi = -1;
        int i = 0;
+       int err = 0;
        unsigned int msg_mark;
 
        struct m_can_classdev *cdev = netdev_priv(dev);
@@ -1038,28 +1040,29 @@ static int m_can_echo_tx_event(struct net_device *dev)
        /* Get and process all sent elements */
        for (i = 0; i < txe_count; i++) {
                u32 txe, timestamp = 0;
-               int err;
 
                /* get message marker, timestamp */
                err = m_can_txe_fifo_read(cdev, fgi, 4, &txe);
                if (err) {
                        netdev_err(dev, "TXE FIFO read returned %d\n", err);
-                       return err;
+                       break;
                }
 
                msg_mark = FIELD_GET(TX_EVENT_MM_MASK, txe);
                timestamp = FIELD_GET(TX_EVENT_TXTS_MASK, txe) << 16;
 
-               /* ack txe element */
-               m_can_write(cdev, M_CAN_TXEFA, FIELD_PREP(TXEFA_EFAI_MASK,
-                                                         fgi));
+               ack_fgi = fgi;
                fgi = (++fgi >= cdev->mcfg[MRAM_TXE].num ? 0 : fgi);
 
                /* update stats */
                m_can_tx_update_stats(cdev, msg_mark, timestamp);
        }
 
-       return 0;
+       if (ack_fgi != -1)
+               m_can_write(cdev, M_CAN_TXEFA, FIELD_PREP(TXEFA_EFAI_MASK,
+                                                         ack_fgi));
+
+       return err;
 }
 
 static irqreturn_t m_can_isr(int irq, void *dev_id)