]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - drivers/net/ethernet/mellanox/mlx4/en_rx.c
mlx4: fix DMA mapping leak when allocation fails
[linux-imx.git] / drivers / net / ethernet / mellanox / mlx4 / en_rx.c
index c2df6c35860317e63a1473e2b69636bedaadc777..d4ad8c226b5115430066a4f41221f7ee41384e58 100644 (file)
@@ -168,8 +168,12 @@ static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
        return 0;
 
 err:
-       while (i--)
+       while (i--) {
+               dma_addr_t dma = be64_to_cpu(rx_desc->data[i].addr);
+               pci_unmap_single(priv->mdev->pdev, dma, skb_frags[i].size,
+                                PCI_DMA_FROMDEVICE);
                put_page(skb_frags[i].page);
+       }
        return -ENOMEM;
 }
 
@@ -380,12 +384,12 @@ err_allocator:
 }
 
 void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
-                            struct mlx4_en_rx_ring *ring)
+                            struct mlx4_en_rx_ring *ring, u32 size, u16 stride)
 {
        struct mlx4_en_dev *mdev = priv->mdev;
 
        mlx4_en_unmap_buffer(&ring->wqres.buf);
-       mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE);
+       mlx4_free_hwq_res(mdev->dev, &ring->wqres, size * stride + TXBB_SIZE);
        vfree(ring->rx_info);
        ring->rx_info = NULL;
 }
@@ -541,6 +545,8 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
        unsigned int length;
        int polled = 0;
        int ip_summed;
+       struct ethhdr *ethh;
+       u64 s_mac;
 
        if (!priv->port_up)
                return 0;
@@ -577,6 +583,19 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                        goto next;
                }
 
+               /* Get pointer to first fragment since we haven't skb yet and
+                * cast it to ethhdr struct */
+               ethh = (struct ethhdr *)(page_address(skb_frags[0].page) +
+                                        skb_frags[0].offset);
+               s_mac = mlx4_en_mac_to_u64(ethh->h_source);
+
+               /* If source MAC is equal to our own MAC and not performing
+                * the selftest or flb disabled - drop the packet */
+               if (s_mac == priv->mac &&
+                       (!(dev->features & NETIF_F_LOOPBACK) ||
+                        !priv->validate_loopback))
+                       goto next;
+
                /*
                 * Packet is OK - process it.
                 */
@@ -837,9 +856,11 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
        struct mlx4_en_dev *mdev = priv->mdev;
        struct mlx4_en_rss_map *rss_map = &priv->rss_map;
        struct mlx4_qp_context context;
-       struct mlx4_en_rss_context *rss_context;
+       struct mlx4_rss_context *rss_context;
+       int rss_rings;
        void *ptr;
-       u8 rss_mask = 0x3f;
+       u8 rss_mask = (MLX4_RSS_IPV4 | MLX4_RSS_TCP_IPV4 | MLX4_RSS_IPV6 |
+                       MLX4_RSS_TCP_IPV6);
        int i, qpn;
        int err = 0;
        int good_qps = 0;
@@ -877,18 +898,26 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
        mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
                                priv->rx_ring[0].cqn, &context);
 
-       ptr = ((void *) &context) + 0x3c;
+       if (!priv->prof->rss_rings || priv->prof->rss_rings > priv->rx_ring_num)
+               rss_rings = priv->rx_ring_num;
+       else
+               rss_rings = priv->prof->rss_rings;
+
+       ptr = ((void *) &context) + offsetof(struct mlx4_qp_context, pri_path)
+                                       + MLX4_RSS_OFFSET_IN_QPC_PRI_PATH;
        rss_context = ptr;
-       rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
+       rss_context->base_qpn = cpu_to_be32(ilog2(rss_rings) << 24 |
                                            (rss_map->base_qpn));
        rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
+       if (priv->mdev->profile.udp_rss) {
+               rss_mask |=  MLX4_RSS_UDP_IPV4 | MLX4_RSS_UDP_IPV6;
+               rss_context->base_qpn_udp = rss_context->default_qpn;
+       }
        rss_context->flags = rss_mask;
-       rss_context->hash_fn = 1;
+       rss_context->hash_fn = MLX4_RSS_HASH_TOP;
        for (i = 0; i < 10; i++)
                rss_context->rss_key[i] = rsskey[i];
 
-       if (priv->mdev->profile.udp_rss)
-               rss_context->base_qpn_udp = rss_context->default_qpn;
        err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context,
                               &rss_map->indir_qp, &rss_map->indir_state);
        if (err)