diff options
Diffstat (limited to 'drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c')
-rw-r--r-- | drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c index 63f2526464b3..d09f7fbf2ba7 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c @@ -19,7 +19,7 @@ static inline int mcp251xfd_rx_head_get_from_chip(const struct mcp251xfd_priv *priv, const struct mcp251xfd_rx_ring *ring, - u8 *rx_head) + u8 *rx_head, bool *fifo_empty) { u32 fifo_sta; int err; @@ -30,6 +30,7 @@ mcp251xfd_rx_head_get_from_chip(const struct mcp251xfd_priv *priv, return err; *rx_head = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta); + *fifo_empty = !(fifo_sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF); return 0; } @@ -84,10 +85,12 @@ mcp251xfd_rx_ring_update(const struct mcp251xfd_priv *priv, { u32 new_head; u8 chip_rx_head; + bool fifo_empty; int err; - err = mcp251xfd_rx_head_get_from_chip(priv, ring, &chip_rx_head); - if (err) + err = mcp251xfd_rx_head_get_from_chip(priv, ring, &chip_rx_head, + &fifo_empty); + if (err || fifo_empty) return err; /* chip_rx_head, is the next RX-Object filled by the HW. @@ -251,10 +254,23 @@ int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv) int err, n; mcp251xfd_for_each_rx_ring(priv, ring, n) { + /* - if RX IRQ coalescing is active always handle ring 0 + * - only handle rings if RX IRQ is active + */ + if ((ring->nr > 0 || !priv->rx_obj_num_coalesce_irq) && + !(priv->regs_status.rxif & BIT(ring->fifo_nr))) + continue; + err = mcp251xfd_handle_rxif_ring(priv, ring); if (err) return err; } + if (priv->rx_coalesce_usecs_irq) + hrtimer_start(&priv->rx_irq_timer, + ns_to_ktime(priv->rx_coalesce_usecs_irq * + NSEC_PER_USEC), + HRTIMER_MODE_REL); + return 0; } |