diff options
author | Eric Dumazet <edumazet@google.com> | 2017-02-10 15:27:58 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-02-17 18:55:22 +0300 |
commit | 01f0f4253469e1b1e80bc84ae64728c294534836 (patch) | |
tree | 04d19fb652370947799509fce5e87668e5835c98 /drivers/net/ethernet/mellanox/mlx4/cq.c | |
parent | 99d5ceeea5120dd3ac2f879f4083697b70a1c89f (diff) | |
download | linux-01f0f4253469e1b1e80bc84ae64728c294534836.tar.xz |
mlx4: do not fire tasklet unless necessary
All rx and rx netdev interrupts are handled by respectively
by mlx4_en_rx_irq() and mlx4_en_tx_irq() which simply schedule a NAPI.
But mlx4_eq_int() also fires a tasklet to service all items that were
queued via mlx4_add_cq_to_tasklet(), but this handler was not called
unless user cqe was handled.
This is very confusing, as "mpstat -I SCPU ..." show huge number of
tasklet invocations.
This patch saves this overhead, by carefully firing the tasklet directly
from mlx4_add_cq_to_tasklet(), removing four atomic operations per IRQ.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Tariq Toukan <tariqt@mellanox.com>
Cc: Saeed Mahameed <saeedm@mellanox.com>
Acked-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/cq.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/cq.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c index 6b8635378f1f..fa6d2354a0e9 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/cq.c @@ -81,8 +81,9 @@ void mlx4_cq_tasklet_cb(unsigned long data) static void mlx4_add_cq_to_tasklet(struct mlx4_cq *cq) { - unsigned long flags; struct mlx4_eq_tasklet *tasklet_ctx = cq->tasklet_ctx.priv; + unsigned long flags; + bool kick; spin_lock_irqsave(&tasklet_ctx->lock, flags); /* When migrating CQs between EQs will be implemented, please note @@ -92,7 +93,10 @@ static void mlx4_add_cq_to_tasklet(struct mlx4_cq *cq) */ if (list_empty_careful(&cq->tasklet_ctx.list)) { atomic_inc(&cq->refcount); + kick = list_empty(&tasklet_ctx->list); list_add_tail(&cq->tasklet_ctx.list, &tasklet_ctx->list); + if (kick) + tasklet_schedule(&tasklet_ctx->task); } spin_unlock_irqrestore(&tasklet_ctx->lock, flags); } |