diff options
author | Yevgeny Petrilin <yevgenyp@mellanox.co.il> | 2011-11-26 14:55:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-11-27 17:17:04 -0500 |
commit | f0ab34f011d805ce5b1a341409c9c26f0fc8252b (patch) | |
tree | fc376208b33eb22dd3b0d95c495e8299c2c45e00 /drivers/net/ethernet | |
parent | 0d9fdaa9f53cf65a2470e8a7506b59fd88d409e2 (diff) |
net/mlx4_en: using non collapsed CQ on TX
Moving to regular Completion Queue implementation (not collapsed)
Completion for each transmitted packet is written to new entry.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_cq.c | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_tx.c | 67 |
2 files changed, 36 insertions, 38 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c index 227997d775e8..2d1a34267b80 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c | |||
@@ -51,10 +51,7 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv, | |||
51 | int err; | 51 | int err; |
52 | 52 | ||
53 | cq->size = entries; | 53 | cq->size = entries; |
54 | if (mode == RX) | 54 | cq->buf_size = cq->size * sizeof(struct mlx4_cqe); |
55 | cq->buf_size = cq->size * sizeof(struct mlx4_cqe); | ||
56 | else | ||
57 | cq->buf_size = sizeof(struct mlx4_cqe); | ||
58 | 55 | ||
59 | cq->ring = ring; | 56 | cq->ring = ring; |
60 | cq->is_tx = mode; | 57 | cq->is_tx = mode; |
@@ -120,7 +117,7 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, | |||
120 | cq->size = priv->rx_ring[cq->ring].actual_size; | 117 | cq->size = priv->rx_ring[cq->ring].actual_size; |
121 | 118 | ||
122 | err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, &mdev->priv_uar, | 119 | err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, &mdev->priv_uar, |
123 | cq->wqres.db.dma, &cq->mcq, cq->vector, cq->is_tx); | 120 | cq->wqres.db.dma, &cq->mcq, cq->vector, 0); |
124 | if (err) | 121 | if (err) |
125 | return err; | 122 | return err; |
126 | 123 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index d901b4267537..3094f940b928 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c | |||
@@ -307,59 +307,60 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring) | |||
307 | return cnt; | 307 | return cnt; |
308 | } | 308 | } |
309 | 309 | ||
310 | |||
311 | static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq) | 310 | static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq) |
312 | { | 311 | { |
313 | struct mlx4_en_priv *priv = netdev_priv(dev); | 312 | struct mlx4_en_priv *priv = netdev_priv(dev); |
314 | struct mlx4_cq *mcq = &cq->mcq; | 313 | struct mlx4_cq *mcq = &cq->mcq; |
315 | struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring]; | 314 | struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring]; |
316 | struct mlx4_cqe *cqe = cq->buf; | 315 | struct mlx4_cqe *cqe; |
317 | u16 index; | 316 | u16 index; |
318 | u16 new_index; | 317 | u16 new_index, ring_index; |
319 | u32 txbbs_skipped = 0; | 318 | u32 txbbs_skipped = 0; |
320 | u32 cq_last_sav; | 319 | u32 cons_index = mcq->cons_index; |
321 | 320 | int size = cq->size; | |
322 | /* index always points to the first TXBB of the last polled descriptor */ | 321 | u32 size_mask = ring->size_mask; |
323 | index = ring->cons & ring->size_mask; | 322 | struct mlx4_cqe *buf = cq->buf; |
324 | new_index = be16_to_cpu(cqe->wqe_index) & ring->size_mask; | ||
325 | if (index == new_index) | ||
326 | return; | ||
327 | 323 | ||
328 | if (!priv->port_up) | 324 | if (!priv->port_up) |
329 | return; | 325 | return; |
330 | 326 | ||
331 | /* | 327 | index = cons_index & size_mask; |
332 | * We use a two-stage loop: | 328 | cqe = &buf[index]; |
333 | * - the first samples the HW-updated CQE | 329 | ring_index = ring->cons & size_mask; |
334 | * - the second frees TXBBs until the last sample | 330 | |
335 | * This lets us amortize CQE cache misses, while still polling the CQ | 331 | /* Process all completed CQEs */ |
336 | * until is quiescent. | 332 | while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK, |
337 | */ | 333 | cons_index & size)) { |
338 | cq_last_sav = mcq->cons_index; | 334 | /* |
339 | do { | 335 | * make sure we read the CQE after we read the |
336 | * ownership bit | ||
337 | */ | ||
338 | rmb(); | ||
339 | |||
340 | /* Skip over last polled CQE */ | ||
341 | new_index = be16_to_cpu(cqe->wqe_index) & size_mask; | ||
342 | |||
340 | do { | 343 | do { |
341 | /* Skip over last polled CQE */ | ||
342 | index = (index + ring->last_nr_txbb) & ring->size_mask; | ||
343 | txbbs_skipped += ring->last_nr_txbb; | 344 | txbbs_skipped += ring->last_nr_txbb; |
344 | 345 | ring_index = (ring_index + ring->last_nr_txbb) & size_mask; | |
345 | /* Poll next CQE */ | 346 | /* free next descriptor */ |
346 | ring->last_nr_txbb = mlx4_en_free_tx_desc( | 347 | ring->last_nr_txbb = mlx4_en_free_tx_desc( |
347 | priv, ring, index, | 348 | priv, ring, ring_index, |
348 | !!((ring->cons + txbbs_skipped) & | 349 | !!((ring->cons + txbbs_skipped) & |
349 | ring->size)); | 350 | ring->size)); |
350 | ++mcq->cons_index; | 351 | } while (ring_index != new_index); |
351 | 352 | ||
352 | } while (index != new_index); | 353 | ++cons_index; |
354 | index = cons_index & size_mask; | ||
355 | cqe = &buf[index]; | ||
356 | } | ||
353 | 357 | ||
354 | new_index = be16_to_cpu(cqe->wqe_index) & ring->size_mask; | ||
355 | } while (index != new_index); | ||
356 | AVG_PERF_COUNTER(priv->pstats.tx_coal_avg, | ||
357 | (u32) (mcq->cons_index - cq_last_sav)); | ||
358 | 358 | ||
359 | /* | 359 | /* |
360 | * To prevent CQ overflow we first update CQ consumer and only then | 360 | * To prevent CQ overflow we first update CQ consumer and only then |
361 | * the ring consumer. | 361 | * the ring consumer. |
362 | */ | 362 | */ |
363 | mcq->cons_index = cons_index; | ||
363 | mlx4_cq_set_ci(mcq); | 364 | mlx4_cq_set_ci(mcq); |
364 | wmb(); | 365 | wmb(); |
365 | ring->cons += txbbs_skipped; | 366 | ring->cons += txbbs_skipped; |