diff options
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_rx.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index bcbb80ff86a7..1a92cd719e19 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -142,16 +142,17 @@ static void mlx4_en_free_frag(struct mlx4_en_priv *priv, struct mlx4_en_rx_alloc *frags, int i) { - const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; - u32 next_frag_end = frags[i].page_offset + 2 * frag_info->frag_stride; - - - if (next_frag_end > frags[i].page_size) - dma_unmap_page(priv->ddev, frags[i].dma, frags[i].page_size, - frag_info->dma_dir); + if (frags[i].page) { + const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; + u32 next_frag_end = frags[i].page_offset + + 2 * frag_info->frag_stride; - if (frags[i].page) + if (next_frag_end > frags[i].page_size) { + dma_unmap_page(priv->ddev, frags[i].dma, + frags[i].page_size, frag_info->dma_dir); + } put_page(frags[i].page); + } } static int mlx4_en_init_allocator(struct mlx4_en_priv *priv, @@ -586,21 +587,28 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv, int length) { struct skb_frag_struct *skb_frags_rx = skb_shinfo(skb)->frags; - struct mlx4_en_frag_info *frag_info; int nr; dma_addr_t dma; /* Collect used fragments while replacing them in the HW descriptors */ for (nr = 0; nr < priv->num_frags; nr++) { - frag_info = &priv->frag_info[nr]; + struct mlx4_en_frag_info *frag_info = &priv->frag_info[nr]; + u32 next_frag_end = frags[nr].page_offset + + 2 * frag_info->frag_stride; + if (length <= frag_info->frag_prefix_size) break; if (unlikely(!frags[nr].page)) goto fail; dma = be64_to_cpu(rx_desc->data[nr].addr); - dma_sync_single_for_cpu(priv->ddev, dma, frag_info->frag_size, - DMA_FROM_DEVICE); + if (next_frag_end > frags[nr].page_size) + dma_unmap_page(priv->ddev, frags[nr].dma, + frags[nr].page_size, frag_info->dma_dir); + else + dma_sync_single_for_cpu(priv->ddev, dma, + frag_info->frag_size, + DMA_FROM_DEVICE); /* Save page reference in skb */ __skb_frag_set_page(&skb_frags_rx[nr], frags[nr].page); |