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.de Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
Родитель
846990e0ed
Коммит
169d00a256
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче