aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorYevgeny Petrilin <yevgenyp@mellanox.co.il>2011-11-26 14:55:10 -0500
committerDavid S. Miller <davem@davemloft.net>2011-11-27 17:17:04 -0500
commitf0ab34f011d805ce5b1a341409c9c26f0fc8252b (patch)
treefc376208b33eb22dd3b0d95c495e8299c2c45e00 /drivers/net/ethernet
parent0d9fdaa9f53cf65a2470e8a7506b59fd88d409e2 (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.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c67
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
311static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq) 310static 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;