Skip to content

Commit

Permalink
can: mcp251xfd: add TX IRQ coalescing support
Browse files Browse the repository at this point in the history
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.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
  • Loading branch information
Marc Kleine-Budde committed Mar 13, 2022
1 parent 846990e commit 169d00a
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 5 deletions.
68 changes: 63 additions & 5 deletions drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@ mcp251xfd_ring_init_tef(struct mcp251xfd_priv *priv, u16 *base)
/* TEF- and TX-FIFO have same number of objects */
*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 */
addr = MCP251XFD_REG_TEFCON;
val = MCP251XFD_REG_TEFCON_UINC;
Expand All @@ -94,6 +105,18 @@ mcp251xfd_ring_init_tef(struct mcp251xfd_priv *priv, u16 *base)
* message.
*/
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
Expand Down Expand Up @@ -282,11 +305,29 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
*/
priv->regs_status.rxif = BIT(priv->rx[0]->fifo_nr);

netdev_dbg(priv->ndev,
"FIFO setup: TEF: 0x%03x: %2d*%zu bytes = %4zu bytes\n",
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));
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,
"FIFO setup: TEF: 0x%03x: %2d*%zu bytes = %4zu bytes\n",
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));
}

mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
if (rx_ring->nr == 0 && priv->rx_obj_num_coalesce_irq) {
Expand Down Expand Up @@ -364,6 +405,20 @@ static enum hrtimer_restart mcp251xfd_rx_irq_timer(struct hrtimer *t)
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 = {
.rx = {
.size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_rx_obj_can),
Expand Down Expand Up @@ -449,5 +504,8 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
hrtimer_init(&priv->rx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
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;
}
6 changes: 6 additions & 0 deletions drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,5 +256,11 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
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;
}
8 changes: 8 additions & 0 deletions drivers/net/can/spi/mcp251xfd/mcp251xfd.h
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,12 @@ struct mcp251xfd_tef_ring {
/* u8 obj_num equals tx_ring->obj_num */
/* 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_irq_disable_buf;
struct spi_transfer uinc_xfer[MCP251XFD_TX_OBJ_NUM_MAX];
};

Expand Down Expand Up @@ -625,9 +630,12 @@ struct mcp251xfd_priv {
u8 rx_ring_num;
u8 rx_obj_num;
u8 rx_obj_num_coalesce_irq;
u8 tx_obj_num_coalesce_irq;

u32 rx_coalesce_usecs_irq;
u32 tx_coalesce_usecs_irq;
struct hrtimer rx_irq_timer;
struct hrtimer tx_irq_timer;

struct mcp251xfd_ecc ecc;
struct mcp251xfd_regs_status regs_status;
Expand Down

0 comments on commit 169d00a

Please sign in to comment.