Commit 169d00a2 authored by Marc Kleine-Budde's avatar Marc Kleine-Budde

can: mcp251xfd: add TX IRQ coalescing support

This patch adds TX IRQ coalescing support to the driver.

The implemented algorithm is similar to the RX IRQ coalescing support
added in the previous patch.

Link: https://lore.kernel.org/20220313083640.501791-11-mkl@pengutronix.deSigned-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 846990e0
...@@ -71,6 +71,17 @@ mcp251xfd_ring_init_tef(struct mcp251xfd_priv *priv, u16 *base) ...@@ -71,6 +71,17 @@ mcp251xfd_ring_init_tef(struct mcp251xfd_priv *priv, u16 *base)
/* TEF- and TX-FIFO have same number of objects */ /* TEF- and TX-FIFO have same number of objects */
*base = mcp251xfd_get_tef_obj_addr(priv->tx->obj_num); *base = mcp251xfd_get_tef_obj_addr(priv->tx->obj_num);
/* FIFO IRQ enable */
addr = MCP251XFD_REG_TEFCON;
val = MCP251XFD_REG_TEFCON_TEFOVIE | MCP251XFD_REG_TEFCON_TEFNEIE;
len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->irq_enable_buf,
addr, val, val);
tef_ring->irq_enable_xfer.tx_buf = &tef_ring->irq_enable_buf;
tef_ring->irq_enable_xfer.len = len;
spi_message_init_with_transfers(&tef_ring->irq_enable_msg,
&tef_ring->irq_enable_xfer, 1);
/* FIFO increment TEF tail pointer */ /* FIFO increment TEF tail pointer */
addr = MCP251XFD_REG_TEFCON; addr = MCP251XFD_REG_TEFCON;
val = MCP251XFD_REG_TEFCON_UINC; val = MCP251XFD_REG_TEFCON_UINC;
...@@ -94,6 +105,18 @@ mcp251xfd_ring_init_tef(struct mcp251xfd_priv *priv, u16 *base) ...@@ -94,6 +105,18 @@ mcp251xfd_ring_init_tef(struct mcp251xfd_priv *priv, u16 *base)
* message. * message.
*/ */
xfer->cs_change = 0; xfer->cs_change = 0;
if (priv->tx_coalesce_usecs_irq || priv->tx_obj_num_coalesce_irq) {
val = MCP251XFD_REG_TEFCON_UINC |
MCP251XFD_REG_TEFCON_TEFOVIE |
MCP251XFD_REG_TEFCON_TEFHIE;
len = mcp251xfd_cmd_prepare_write_reg(priv,
&tef_ring->uinc_irq_disable_buf,
addr, val, val);
xfer->tx_buf = &tef_ring->uinc_irq_disable_buf;
xfer->len = len;
}
} }
static void static void
...@@ -282,11 +305,29 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv) ...@@ -282,11 +305,29 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
*/ */
priv->regs_status.rxif = BIT(priv->rx[0]->fifo_nr); priv->regs_status.rxif = BIT(priv->rx[0]->fifo_nr);
if (priv->tx_obj_num_coalesce_irq) {
netdev_dbg(priv->ndev,
"FIFO setup: TEF: 0x%03x: %2d*%zu bytes = %4zu bytes (coalesce)\n",
mcp251xfd_get_tef_obj_addr(0),
priv->tx_obj_num_coalesce_irq,
sizeof(struct mcp251xfd_hw_tef_obj),
priv->tx_obj_num_coalesce_irq *
sizeof(struct mcp251xfd_hw_tef_obj));
netdev_dbg(priv->ndev,
" 0x%03x: %2d*%zu bytes = %4zu bytes\n",
mcp251xfd_get_tef_obj_addr(priv->tx_obj_num_coalesce_irq),
priv->tx->obj_num - priv->tx_obj_num_coalesce_irq,
sizeof(struct mcp251xfd_hw_tef_obj),
(priv->tx->obj_num - priv->tx_obj_num_coalesce_irq) *
sizeof(struct mcp251xfd_hw_tef_obj));
} else {
netdev_dbg(priv->ndev, netdev_dbg(priv->ndev,
"FIFO setup: TEF: 0x%03x: %2d*%zu bytes = %4zu bytes\n", "FIFO setup: TEF: 0x%03x: %2d*%zu bytes = %4zu bytes\n",
mcp251xfd_get_tef_obj_addr(0), mcp251xfd_get_tef_obj_addr(0),
priv->tx->obj_num, sizeof(struct mcp251xfd_hw_tef_obj), priv->tx->obj_num, sizeof(struct mcp251xfd_hw_tef_obj),
priv->tx->obj_num * sizeof(struct mcp251xfd_hw_tef_obj)); priv->tx->obj_num * sizeof(struct mcp251xfd_hw_tef_obj));
}
mcp251xfd_for_each_rx_ring(priv, rx_ring, i) { mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
if (rx_ring->nr == 0 && priv->rx_obj_num_coalesce_irq) { if (rx_ring->nr == 0 && priv->rx_obj_num_coalesce_irq) {
...@@ -364,6 +405,20 @@ static enum hrtimer_restart mcp251xfd_rx_irq_timer(struct hrtimer *t) ...@@ -364,6 +405,20 @@ static enum hrtimer_restart mcp251xfd_rx_irq_timer(struct hrtimer *t)
return HRTIMER_NORESTART; return HRTIMER_NORESTART;
} }
static enum hrtimer_restart mcp251xfd_tx_irq_timer(struct hrtimer *t)
{
struct mcp251xfd_priv *priv = container_of(t, struct mcp251xfd_priv,
tx_irq_timer);
struct mcp251xfd_tef_ring *ring = priv->tef;
if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags))
return HRTIMER_NORESTART;
spi_async(priv->spi, &ring->irq_enable_msg);
return HRTIMER_NORESTART;
}
const struct can_ram_config mcp251xfd_ram_config = { const struct can_ram_config mcp251xfd_ram_config = {
.rx = { .rx = {
.size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_rx_obj_can), .size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_rx_obj_can),
...@@ -449,5 +504,8 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv) ...@@ -449,5 +504,8 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
hrtimer_init(&priv->rx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_init(&priv->rx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
priv->rx_irq_timer.function = mcp251xfd_rx_irq_timer; priv->rx_irq_timer.function = mcp251xfd_rx_irq_timer;
hrtimer_init(&priv->tx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
priv->tx_irq_timer.function = mcp251xfd_tx_irq_timer;
return 0; return 0;
} }
...@@ -256,5 +256,11 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv) ...@@ -256,5 +256,11 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
netif_wake_queue(priv->ndev); netif_wake_queue(priv->ndev);
} }
if (priv->tx_coalesce_usecs_irq)
hrtimer_start(&priv->tx_irq_timer,
ns_to_ktime(priv->tx_coalesce_usecs_irq *
NSEC_PER_USEC),
HRTIMER_MODE_REL);
return 0; return 0;
} }
...@@ -518,7 +518,12 @@ struct mcp251xfd_tef_ring { ...@@ -518,7 +518,12 @@ struct mcp251xfd_tef_ring {
/* u8 obj_num equals tx_ring->obj_num */ /* u8 obj_num equals tx_ring->obj_num */
/* u8 obj_size equals sizeof(struct mcp251xfd_hw_tef_obj) */ /* u8 obj_size equals sizeof(struct mcp251xfd_hw_tef_obj) */
union mcp251xfd_write_reg_buf irq_enable_buf;
struct spi_transfer irq_enable_xfer;
struct spi_message irq_enable_msg;
union mcp251xfd_write_reg_buf uinc_buf; union mcp251xfd_write_reg_buf uinc_buf;
union mcp251xfd_write_reg_buf uinc_irq_disable_buf;
struct spi_transfer uinc_xfer[MCP251XFD_TX_OBJ_NUM_MAX]; struct spi_transfer uinc_xfer[MCP251XFD_TX_OBJ_NUM_MAX];
}; };
...@@ -625,9 +630,12 @@ struct mcp251xfd_priv { ...@@ -625,9 +630,12 @@ struct mcp251xfd_priv {
u8 rx_ring_num; u8 rx_ring_num;
u8 rx_obj_num; u8 rx_obj_num;
u8 rx_obj_num_coalesce_irq; u8 rx_obj_num_coalesce_irq;
u8 tx_obj_num_coalesce_irq;
u32 rx_coalesce_usecs_irq; u32 rx_coalesce_usecs_irq;
u32 tx_coalesce_usecs_irq;
struct hrtimer rx_irq_timer; struct hrtimer rx_irq_timer;
struct hrtimer tx_irq_timer;
struct mcp251xfd_ecc ecc; struct mcp251xfd_ecc ecc;
struct mcp251xfd_regs_status regs_status; struct mcp251xfd_regs_status regs_status;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment