@@ -255,6 +255,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) */
@@ -429,7 +430,7 @@ static void m_can_interrupt_enable(struct m_can_classdev *cdev, u32 interrupts)
static void m_can_coalescing_disable(struct m_can_classdev *cdev)
{
- u32 new_interrupts = cdev->active_interrupts | IR_RF0N;
+ u32 new_interrupts = cdev->active_interrupts | IR_RF0N | IR_TEFN;
hrtimer_cancel(&cdev->irq_timer);
m_can_interrupt_enable(cdev, new_interrupts);
@@ -1096,21 +1097,26 @@ static int m_can_echo_tx_event(struct net_device *dev)
static void m_can_coalescing_update(struct m_can_classdev *cdev, u32 ir)
{
u32 new_interrupts = cdev->active_interrupts;
- bool enable_timer = false;
+ bool enable_rx_timer = false;
+ bool enable_tx_timer = false;
if (cdev->rx_coalesce_usecs_irq > 0 && (ir & (IR_RF0N | IR_RF0W))) {
- enable_timer = true;
+ enable_rx_timer = true;
new_interrupts &= ~IR_RF0N;
- } else if (!hrtimer_active(&cdev->irq_timer)) {
- new_interrupts |= IR_RF0N;
}
+ if (cdev->tx_coalesce_usecs_irq > 0 && (ir & (IR_TEFN | IR_TEFW))) {
+ enable_tx_timer = true;
+ new_interrupts &= ~IR_TEFN;
+ }
+ if (!enable_rx_timer && !hrtimer_active(&cdev->irq_timer))
+ new_interrupts |= IR_RF0N;
+ if (!enable_tx_timer && !hrtimer_active(&cdev->irq_timer))
+ new_interrupts |= IR_TEFN;
m_can_interrupt_enable(cdev, new_interrupts);
- if (enable_timer) {
- hrtimer_start(&cdev->irq_timer,
- ns_to_ktime(cdev->rx_coalesce_usecs_irq * NSEC_PER_USEC),
+ if (enable_rx_timer | enable_tx_timer)
+ hrtimer_start(&cdev->irq_timer, cdev->irq_timer_wait,
HRTIMER_MODE_REL);
- }
}
static irqreturn_t m_can_isr(int irq, void *dev_id)
@@ -1165,7 +1171,7 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
netif_wake_queue(dev);
}
} else {
- if (ir & IR_TEFN) {
+ if (ir & (IR_TEFN | IR_TEFW)) {
/* New TX FIFO Element arrived */
if (m_can_echo_tx_event(dev) != 0)
goto out_fail;
@@ -1333,9 +1339,8 @@ static int m_can_chip_config(struct net_device *dev)
}
/* Disable unused interrupts */
- interrupts &= ~(IR_ARA | IR_ELO | IR_DRX | IR_TEFF | IR_TEFW | IR_TFE |
- IR_TCF | IR_HPM | IR_RF1F | IR_RF1W | IR_RF1N |
- IR_RF0F);
+ interrupts &= ~(IR_ARA | IR_ELO | IR_DRX | IR_TEFF | IR_TFE | IR_TCF |
+ IR_HPM | IR_RF1F | IR_RF1W | IR_RF1N | IR_RF0F);
m_can_config_endisable(cdev, true);
@@ -1372,6 +1377,8 @@ static int m_can_chip_config(struct net_device *dev)
} else {
/* Full TX Event FIFO is used */
m_can_write(cdev, M_CAN_TXEFC,
+ FIELD_PREP(TXEFC_EFWM_MASK,
+ cdev->tx_max_coalesced_frames_irq) |
FIELD_PREP(TXEFC_EFS_MASK,
cdev->mcfg[MRAM_TXE].num) |
cdev->mcfg[MRAM_TXE].off);
@@ -85,6 +85,7 @@ struct m_can_classdev {
struct phy *transceiver;
struct hrtimer irq_timer;
+ ktime_t irq_timer_wait;
struct m_can_ops *ops;
@@ -98,6 +99,8 @@ struct m_can_classdev {
u32 active_interrupts;
u32 rx_max_coalesced_frames_irq;
u32 rx_coalesce_usecs_irq;
+ u32 tx_max_coalesced_frames_irq;
+ u32 tx_coalesce_usecs_irq;
struct mram_cfg mcfg[MRAM_CFG_NUM];
};