[PATCH 04/15] can: m_can: Use transmit event FIFO watermark level interrupt
From: Markus Schneider-Pargmann
Date: Wed Nov 16 2022 - 15:54:21 EST
Currently the only mode of operation is an interrupt for every transmit
event. This is inefficient for peripheral chips. Use the transmit FIFO
event watermark interrupt instead if the FIFO size is more than 2. Use
FIFOsize - 1 for the watermark so the interrupt is triggered early
enough to not stop transmitting.
Note that if the number of transmits is less than the watermark level,
the transmit events will not be processed until there is any other
interrupt. This will only affect statistic counters. Also there is an
interrupt every time the timestamp wraps around.
Signed-off-by: Markus Schneider-Pargmann <msp@xxxxxxxxxxxx>
---
drivers/net/can/m_can/m_can.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index f5bba848bd56..4a6972c8bacd 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -254,6 +254,7 @@ enum m_can_reg {
#define TXESC_TBDS_64B 0x7
/* Tx Event FIFO Configuration (TXEFC) */
+#define TXEFC_EFWM_MASK GENMASK(29, 24)
#define TXEFC_EFS_MASK GENMASK(21, 16)
/* Tx Event FIFO Status (TXEFS) */
@@ -1094,8 +1095,8 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
netif_wake_queue(dev);
}
} else {
- if (ir & IR_TEFN) {
- /* New TX FIFO Element arrived */
+ if (ir & (IR_TEFN | IR_TEFW)) {
+ /* New TX FIFO Element arrived or watermark reached */
if (m_can_echo_tx_event(dev) != 0)
goto out_fail;
if (!cdev->tx_skb && netif_queue_stopped(dev))
@@ -1242,6 +1243,7 @@ static void m_can_chip_config(struct net_device *dev)
{
struct m_can_classdev *cdev = netdev_priv(dev);
u32 cccr, test;
+ u32 interrupts = IR_ALL_INT;
m_can_config_endisable(cdev, true);
@@ -1276,11 +1278,20 @@ static void m_can_chip_config(struct net_device *dev)
FIELD_PREP(TXEFC_EFS_MASK, 1) |
cdev->mcfg[MRAM_TXE].off);
} else {
+ u32 txe_watermark;
+
+ txe_watermark = cdev->mcfg[MRAM_TXE].num - 1;
/* Full TX Event FIFO is used */
m_can_write(cdev, M_CAN_TXEFC,
+ FIELD_PREP(TXEFC_EFWM_MASK,
+ txe_watermark) |
FIELD_PREP(TXEFC_EFS_MASK,
cdev->mcfg[MRAM_TXE].num) |
cdev->mcfg[MRAM_TXE].off);
+
+ /* Watermark interrupt mode */
+ if (txe_watermark)
+ interrupts &= ~IR_TEFN;
}
/* rx fifo configuration, blocking mode, fifo size 1 */
@@ -1338,15 +1349,13 @@ static void m_can_chip_config(struct net_device *dev)
/* Enable interrupts */
m_can_write(cdev, M_CAN_IR, IR_ALL_INT);
- if (!(cdev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
+ if (!(cdev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) {
if (cdev->version == 30)
- m_can_write(cdev, M_CAN_IE, IR_ALL_INT &
- ~(IR_ERR_LEC_30X));
+ interrupts &= ~(IR_ERR_LEC_30X);
else
- m_can_write(cdev, M_CAN_IE, IR_ALL_INT &
- ~(IR_ERR_LEC_31X));
- else
- m_can_write(cdev, M_CAN_IE, IR_ALL_INT);
+ interrupts &= ~(IR_ERR_LEC_31X);
+ }
+ m_can_write(cdev, M_CAN_IE, interrupts);
/* route all interrupts to INT0 */
m_can_write(cdev, M_CAN_ILS, ILS_ALL_INT0);
--
2.38.1