aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mlx4/en_rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/mlx4/en_rx.c')
-rw-r--r--drivers/net/mlx4/en_rx.c123
1 files changed, 49 insertions, 74 deletions
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 8e2fcb7103c3..277215fb9d72 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -42,18 +42,6 @@
42#include "mlx4_en.h" 42#include "mlx4_en.h"
43 43
44 44
45static int mlx4_en_get_frag_header(struct skb_frag_struct *frags, void **mac_hdr,
46 void **ip_hdr, void **tcpudp_hdr,
47 u64 *hdr_flags, void *priv)
48{
49 *mac_hdr = page_address(frags->page) + frags->page_offset;
50 *ip_hdr = *mac_hdr + ETH_HLEN;
51 *tcpudp_hdr = (struct tcphdr *)(*ip_hdr + sizeof(struct iphdr));
52 *hdr_flags = LRO_IPV4 | LRO_TCP;
53
54 return 0;
55}
56
57static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv, 45static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv,
58 struct mlx4_en_rx_desc *rx_desc, 46 struct mlx4_en_rx_desc *rx_desc,
59 struct skb_frag_struct *skb_frags, 47 struct skb_frag_struct *skb_frags,
@@ -251,7 +239,6 @@ reduce_rings:
251 ring->prod--; 239 ring->prod--;
252 mlx4_en_free_rx_desc(priv, ring, ring->actual_size); 240 mlx4_en_free_rx_desc(priv, ring, ring->actual_size);
253 } 241 }
254 ring->size_mask = ring->actual_size - 1;
255 } 242 }
256 243
257 return 0; 244 return 0;
@@ -313,28 +300,8 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
313 } 300 }
314 ring->buf = ring->wqres.buf.direct.buf; 301 ring->buf = ring->wqres.buf.direct.buf;
315 302
316 /* Configure lro mngr */
317 memset(&ring->lro, 0, sizeof(struct net_lro_mgr));
318 ring->lro.dev = priv->dev;
319 ring->lro.features = LRO_F_NAPI;
320 ring->lro.frag_align_pad = NET_IP_ALIGN;
321 ring->lro.ip_summed = CHECKSUM_UNNECESSARY;
322 ring->lro.ip_summed_aggr = CHECKSUM_UNNECESSARY;
323 ring->lro.max_desc = mdev->profile.num_lro;
324 ring->lro.max_aggr = MAX_SKB_FRAGS;
325 ring->lro.lro_arr = kzalloc(mdev->profile.num_lro *
326 sizeof(struct net_lro_desc),
327 GFP_KERNEL);
328 if (!ring->lro.lro_arr) {
329 en_err(priv, "Failed to allocate lro array\n");
330 goto err_map;
331 }
332 ring->lro.get_frag_header = mlx4_en_get_frag_header;
333
334 return 0; 303 return 0;
335 304
336err_map:
337 mlx4_en_unmap_buffer(&ring->wqres.buf);
338err_hwq: 305err_hwq:
339 mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size); 306 mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
340err_ring: 307err_ring:
@@ -378,6 +345,8 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
378 err = mlx4_en_init_allocator(priv, ring); 345 err = mlx4_en_init_allocator(priv, ring);
379 if (err) { 346 if (err) {
380 en_err(priv, "Failed initializing ring allocator\n"); 347 en_err(priv, "Failed initializing ring allocator\n");
348 if (ring->stride <= TXBB_SIZE)
349 ring->buf -= TXBB_SIZE;
381 ring_ind--; 350 ring_ind--;
382 goto err_allocator; 351 goto err_allocator;
383 } 352 }
@@ -389,6 +358,7 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
389 for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) { 358 for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
390 ring = &priv->rx_ring[ring_ind]; 359 ring = &priv->rx_ring[ring_ind];
391 360
361 ring->size_mask = ring->actual_size - 1;
392 mlx4_en_update_rx_prod_db(ring); 362 mlx4_en_update_rx_prod_db(ring);
393 } 363 }
394 364
@@ -401,6 +371,8 @@ err_buffers:
401 ring_ind = priv->rx_ring_num - 1; 371 ring_ind = priv->rx_ring_num - 1;
402err_allocator: 372err_allocator:
403 while (ring_ind >= 0) { 373 while (ring_ind >= 0) {
374 if (priv->rx_ring[ring_ind].stride <= TXBB_SIZE)
375 priv->rx_ring[ring_ind].buf -= TXBB_SIZE;
404 mlx4_en_destroy_allocator(priv, &priv->rx_ring[ring_ind]); 376 mlx4_en_destroy_allocator(priv, &priv->rx_ring[ring_ind]);
405 ring_ind--; 377 ring_ind--;
406 } 378 }
@@ -412,7 +384,6 @@ void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
412{ 384{
413 struct mlx4_en_dev *mdev = priv->mdev; 385 struct mlx4_en_dev *mdev = priv->mdev;
414 386
415 kfree(ring->lro.lro_arr);
416 mlx4_en_unmap_buffer(&ring->wqres.buf); 387 mlx4_en_unmap_buffer(&ring->wqres.buf);
417 mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE); 388 mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE);
418 vfree(ring->rx_info); 389 vfree(ring->rx_info);
@@ -459,7 +430,7 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
459 goto fail; 430 goto fail;
460 431
461 /* Unmap buffer */ 432 /* Unmap buffer */
462 pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size, 433 pci_unmap_single(mdev->pdev, dma, skb_frags_rx[nr].size,
463 PCI_DMA_FROMDEVICE); 434 PCI_DMA_FROMDEVICE);
464 } 435 }
465 /* Adjust size of last fragment to match actual length */ 436 /* Adjust size of last fragment to match actual length */
@@ -541,6 +512,21 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
541 return skb; 512 return skb;
542} 513}
543 514
515static void validate_loopback(struct mlx4_en_priv *priv, struct sk_buff *skb)
516{
517 int i;
518 int offset = ETH_HLEN;
519
520 for (i = 0; i < MLX4_LOOPBACK_TEST_PAYLOAD; i++, offset++) {
521 if (*(skb->data + offset) != (unsigned char) (i & 0xff))
522 goto out_loopback;
523 }
524 /* Loopback found */
525 priv->loopback_ok = 1;
526
527out_loopback:
528 dev_kfree_skb_any(skb);
529}
544 530
545int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget) 531int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget)
546{ 532{
@@ -548,7 +534,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
548 struct mlx4_cqe *cqe; 534 struct mlx4_cqe *cqe;
549 struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring]; 535 struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring];
550 struct skb_frag_struct *skb_frags; 536 struct skb_frag_struct *skb_frags;
551 struct skb_frag_struct lro_frags[MLX4_EN_MAX_RX_FRAGS];
552 struct mlx4_en_rx_desc *rx_desc; 537 struct mlx4_en_rx_desc *rx_desc;
553 struct sk_buff *skb; 538 struct sk_buff *skb;
554 int index; 539 int index;
@@ -599,7 +584,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
599 ring->bytes += length; 584 ring->bytes += length;
600 ring->packets++; 585 ring->packets++;
601 586
602 if (likely(priv->rx_csum)) { 587 if (likely(dev->features & NETIF_F_RXCSUM)) {
603 if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) && 588 if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
604 (cqe->checksum == cpu_to_be16(0xffff))) { 589 (cqe->checksum == cpu_to_be16(0xffff))) {
605 priv->port_stats.rx_chksum_good++; 590 priv->port_stats.rx_chksum_good++;
@@ -608,37 +593,35 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
608 * - TCP/IP (v4) 593 * - TCP/IP (v4)
609 * - without IP options 594 * - without IP options
610 * - not an IP fragment */ 595 * - not an IP fragment */
611 if (mlx4_en_can_lro(cqe->status) && 596 if (dev->features & NETIF_F_GRO) {
612 dev->features & NETIF_F_LRO) { 597 struct sk_buff *gro_skb = napi_get_frags(&cq->napi);
598 if (!gro_skb)
599 goto next;
613 600
614 nr = mlx4_en_complete_rx_desc( 601 nr = mlx4_en_complete_rx_desc(
615 priv, rx_desc, 602 priv, rx_desc,
616 skb_frags, lro_frags, 603 skb_frags, skb_shinfo(gro_skb)->frags,
617 ring->page_alloc, length); 604 ring->page_alloc, length);
618 if (!nr) 605 if (!nr)
619 goto next; 606 goto next;
620 607
608 skb_shinfo(gro_skb)->nr_frags = nr;
609 gro_skb->len = length;
610 gro_skb->data_len = length;
611 gro_skb->truesize += length;
612 gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
613
621 if (priv->vlgrp && (cqe->vlan_my_qpn & 614 if (priv->vlgrp && (cqe->vlan_my_qpn &
622 cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK))) { 615 cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)))
623 lro_vlan_hwaccel_receive_frags( 616 vlan_gro_frags(&cq->napi, priv->vlgrp, be16_to_cpu(cqe->sl_vid));
624 &ring->lro, lro_frags, 617 else
625 length, length, 618 napi_gro_frags(&cq->napi);
626 priv->vlgrp,
627 be16_to_cpu(cqe->sl_vid),
628 NULL, 0);
629 } else
630 lro_receive_frags(&ring->lro,
631 lro_frags,
632 length,
633 length,
634 NULL, 0);
635 619
636 goto next; 620 goto next;
637 } 621 }
638 622
639 /* LRO not possible, complete processing here */ 623 /* LRO not possible, complete processing here */
640 ip_summed = CHECKSUM_UNNECESSARY; 624 ip_summed = CHECKSUM_UNNECESSARY;
641 INC_PERF_COUNTER(priv->pstats.lro_misses);
642 } else { 625 } else {
643 ip_summed = CHECKSUM_NONE; 626 ip_summed = CHECKSUM_NONE;
644 priv->port_stats.rx_chksum_none++; 627 priv->port_stats.rx_chksum_none++;
@@ -655,6 +638,11 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
655 goto next; 638 goto next;
656 } 639 }
657 640
641 if (unlikely(priv->validate_loopback)) {
642 validate_loopback(priv, skb);
643 goto next;
644 }
645
658 skb->ip_summed = ip_summed; 646 skb->ip_summed = ip_summed;
659 skb->protocol = eth_type_trans(skb, dev); 647 skb->protocol = eth_type_trans(skb, dev);
660 skb_record_rx_queue(skb, cq->ring); 648 skb_record_rx_queue(skb, cq->ring);
@@ -674,14 +662,10 @@ next:
674 if (++polled == budget) { 662 if (++polled == budget) {
675 /* We are here because we reached the NAPI budget - 663 /* We are here because we reached the NAPI budget -
676 * flush only pending LRO sessions */ 664 * flush only pending LRO sessions */
677 lro_flush_all(&ring->lro);
678 goto out; 665 goto out;
679 } 666 }
680 } 667 }
681 668
682 /* If CQ is empty flush all LRO sessions unconditionally */
683 lro_flush_all(&ring->lro);
684
685out: 669out:
686 AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled); 670 AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled);
687 mlx4_cq_set_ci(&cq->mcq); 671 mlx4_cq_set_ci(&cq->mcq);
@@ -726,7 +710,7 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
726} 710}
727 711
728 712
729/* Calculate the last offset position that accomodates a full fragment 713/* Calculate the last offset position that accommodates a full fragment
730 * (assuming fagment size = stride-align) */ 714 * (assuming fagment size = stride-align) */
731static int mlx4_en_last_alloc_offset(struct mlx4_en_priv *priv, u16 stride, u16 align) 715static int mlx4_en_last_alloc_offset(struct mlx4_en_priv *priv, u16 stride, u16 align)
732{ 716{
@@ -816,7 +800,7 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
816 qp->event = mlx4_en_sqp_event; 800 qp->event = mlx4_en_sqp_event;
817 801
818 memset(context, 0, sizeof *context); 802 memset(context, 0, sizeof *context);
819 mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 0, 0, 803 mlx4_en_fill_qp_context(priv, ring->actual_size, ring->stride, 0, 0,
820 qpn, ring->cqn, context); 804 qpn, ring->cqn, context);
821 context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma); 805 context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma);
822 806
@@ -839,8 +823,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
839 struct mlx4_qp_context context; 823 struct mlx4_qp_context context;
840 struct mlx4_en_rss_context *rss_context; 824 struct mlx4_en_rss_context *rss_context;
841 void *ptr; 825 void *ptr;
842 int rss_xor = mdev->profile.rss_xor; 826 u8 rss_mask = 0x3f;
843 u8 rss_mask = mdev->profile.rss_mask;
844 int i, qpn; 827 int i, qpn;
845 int err = 0; 828 int err = 0;
846 int good_qps = 0; 829 int good_qps = 0;
@@ -866,16 +849,10 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
866 } 849 }
867 850
868 /* Configure RSS indirection qp */ 851 /* Configure RSS indirection qp */
869 err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &priv->base_qpn);
870 if (err) {
871 en_err(priv, "Failed to reserve range for RSS "
872 "indirection qp\n");
873 goto rss_err;
874 }
875 err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp); 852 err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp);
876 if (err) { 853 if (err) {
877 en_err(priv, "Failed to allocate RSS indirection QP\n"); 854 en_err(priv, "Failed to allocate RSS indirection QP\n");
878 goto reserve_err; 855 goto rss_err;
879 } 856 }
880 rss_map->indir_qp.event = mlx4_en_sqp_event; 857 rss_map->indir_qp.event = mlx4_en_sqp_event;
881 mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn, 858 mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
@@ -886,9 +863,10 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
886 rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 | 863 rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
887 (rss_map->base_qpn)); 864 (rss_map->base_qpn));
888 rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn); 865 rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
889 rss_context->hash_fn = rss_xor & 0x3; 866 rss_context->flags = rss_mask;
890 rss_context->flags = rss_mask << 2;
891 867
868 if (priv->mdev->profile.udp_rss)
869 rss_context->base_qpn_udp = rss_context->default_qpn;
892 err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context, 870 err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context,
893 &rss_map->indir_qp, &rss_map->indir_state); 871 &rss_map->indir_qp, &rss_map->indir_state);
894 if (err) 872 if (err)
@@ -901,8 +879,6 @@ indir_err:
901 MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp); 879 MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
902 mlx4_qp_remove(mdev->dev, &rss_map->indir_qp); 880 mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
903 mlx4_qp_free(mdev->dev, &rss_map->indir_qp); 881 mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
904reserve_err:
905 mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
906rss_err: 882rss_err:
907 for (i = 0; i < good_qps; i++) { 883 for (i = 0; i < good_qps; i++) {
908 mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i], 884 mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
@@ -924,7 +900,6 @@ void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv)
924 MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp); 900 MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
925 mlx4_qp_remove(mdev->dev, &rss_map->indir_qp); 901 mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
926 mlx4_qp_free(mdev->dev, &rss_map->indir_qp); 902 mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
927 mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
928 903
929 for (i = 0; i < priv->rx_ring_num; i++) { 904 for (i = 0; i < priv->rx_ring_num; i++) {
930 mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i], 905 mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],