diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/en_rx.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_rx.c | 74 |
1 files changed, 45 insertions, 29 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 37cc9e5c56be..b89c36dbf5b3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -44,7 +44,7 @@ static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv, struct mlx4_en_rx_desc *rx_desc, - struct skb_frag_struct *skb_frags, + struct page_frag *skb_frags, struct mlx4_en_rx_alloc *ring_alloc, int i) { @@ -61,7 +61,7 @@ static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv, return -ENOMEM; skb_frags[i].page = page_alloc->page; - skb_frags[i].page_offset = page_alloc->offset; + skb_frags[i].offset = page_alloc->offset; page_alloc->page = page; page_alloc->offset = frag_info->frag_align; } else { @@ -69,11 +69,11 @@ static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv, get_page(page); skb_frags[i].page = page; - skb_frags[i].page_offset = page_alloc->offset; + skb_frags[i].offset = page_alloc->offset; page_alloc->offset += frag_info->frag_stride; } dma = pci_map_single(mdev->pdev, page_address(skb_frags[i].page) + - skb_frags[i].page_offset, frag_info->frag_size, + skb_frags[i].offset, frag_info->frag_size, PCI_DMA_FROMDEVICE); rx_desc->data[i].addr = cpu_to_be64(dma); return 0; @@ -135,7 +135,7 @@ static void mlx4_en_init_rx_desc(struct mlx4_en_priv *priv, /* Set size and memtype fields */ for (i = 0; i < priv->num_frags; i++) { - skb_frags[i].size = priv->frag_info[i].frag_size; + skb_frag_size_set(&skb_frags[i], priv->frag_info[i].frag_size); rx_desc->data[i].byte_count = cpu_to_be32(priv->frag_info[i].frag_size); rx_desc->data[i].lkey = cpu_to_be32(priv->mdev->mr.key); @@ -157,8 +157,8 @@ static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv, struct mlx4_en_rx_ring *ring, int index) { struct mlx4_en_rx_desc *rx_desc = ring->buf + (index * ring->stride); - struct skb_frag_struct *skb_frags = ring->rx_info + - (index << priv->log_rx_info); + struct page_frag *skb_frags = ring->rx_info + + (index << priv->log_rx_info); int i; for (i = 0; i < priv->num_frags; i++) @@ -183,7 +183,7 @@ static void mlx4_en_free_rx_desc(struct mlx4_en_priv *priv, int index) { struct mlx4_en_dev *mdev = priv->mdev; - struct skb_frag_struct *skb_frags; + struct page_frag *skb_frags; struct mlx4_en_rx_desc *rx_desc = ring->buf + (index << ring->log_stride); dma_addr_t dma; int nr; @@ -403,11 +403,12 @@ void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv, /* Unmap a completed descriptor and free unused pages */ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv, struct mlx4_en_rx_desc *rx_desc, - struct skb_frag_struct *skb_frags, - struct skb_frag_struct *skb_frags_rx, + struct page_frag *skb_frags, + struct sk_buff *skb, struct mlx4_en_rx_alloc *page_alloc, int length) { + struct skb_frag_struct *skb_frags_rx = skb_shinfo(skb)->frags; struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_frag_info *frag_info; int nr; @@ -420,9 +421,10 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv, break; /* Save page reference in skb */ - skb_frags_rx[nr].page = skb_frags[nr].page; - skb_frags_rx[nr].size = skb_frags[nr].size; - skb_frags_rx[nr].page_offset = skb_frags[nr].page_offset; + __skb_frag_set_page(&skb_frags_rx[nr], skb_frags[nr].page); + skb_frag_size_set(&skb_frags_rx[nr], skb_frags[nr].size); + skb_frags_rx[nr].page_offset = skb_frags[nr].offset; + skb->truesize += frag_info->frag_stride; dma = be64_to_cpu(rx_desc->data[nr].addr); /* Allocate a replacement page */ @@ -430,13 +432,13 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv, goto fail; /* Unmap buffer */ - pci_unmap_single(mdev->pdev, dma, skb_frags_rx[nr].size, + pci_unmap_single(mdev->pdev, dma, skb_frag_size(&skb_frags_rx[nr]), PCI_DMA_FROMDEVICE); } /* Adjust size of last fragment to match actual length */ if (nr > 0) - skb_frags_rx[nr - 1].size = length - - priv->frag_info[nr - 1].frag_prefix_size; + skb_frag_size_set(&skb_frags_rx[nr - 1], + length - priv->frag_info[nr - 1].frag_prefix_size); return nr; fail: @@ -444,7 +446,7 @@ fail: * the descriptor) of this packet; remaining fragments are reused... */ while (nr > 0) { nr--; - put_page(skb_frags_rx[nr].page); + __skb_frag_unref(&skb_frags_rx[nr]); } return 0; } @@ -452,7 +454,7 @@ fail: static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, struct mlx4_en_rx_desc *rx_desc, - struct skb_frag_struct *skb_frags, + struct page_frag *skb_frags, struct mlx4_en_rx_alloc *page_alloc, unsigned int length) { @@ -470,11 +472,10 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, skb->dev = priv->dev; skb_reserve(skb, NET_IP_ALIGN); skb->len = length; - skb->truesize = length + sizeof(struct sk_buff); /* Get pointer to first fragment so we could copy the headers into the * (linear part of the) skb */ - va = page_address(skb_frags[0].page) + skb_frags[0].page_offset; + va = page_address(skb_frags[0].page) + skb_frags[0].offset; if (length <= SMALL_PACKET_SIZE) { /* We are copying all relevant data to the skb - temporarily @@ -490,8 +491,7 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, /* Move relevant fragments to skb */ used_frags = mlx4_en_complete_rx_desc(priv, rx_desc, skb_frags, - skb_shinfo(skb)->frags, - page_alloc, length); + skb, page_alloc, length); if (unlikely(!used_frags)) { kfree_skb(skb); return NULL; @@ -506,7 +506,7 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, skb_shinfo(skb)->frags[0].page_offset += HEADER_COPY_SIZE; /* Adjust size of first fragment */ - skb_shinfo(skb)->frags[0].size -= HEADER_COPY_SIZE; + skb_frag_size_sub(&skb_shinfo(skb)->frags[0], HEADER_COPY_SIZE); skb->data_len = length - HEADER_COPY_SIZE; } return skb; @@ -533,7 +533,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_cqe *cqe; struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring]; - struct skb_frag_struct *skb_frags; + struct page_frag *skb_frags; struct mlx4_en_rx_desc *rx_desc; struct sk_buff *skb; int index; @@ -587,7 +587,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud if (likely(dev->features & NETIF_F_RXCSUM)) { if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) && (cqe->checksum == cpu_to_be16(0xffff))) { - priv->port_stats.rx_chksum_good++; + ring->csum_ok++; /* This packet is eligible for LRO if it is: * - DIX Ethernet (type interpretation) * - TCP/IP (v4) @@ -600,7 +600,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud nr = mlx4_en_complete_rx_desc( priv, rx_desc, - skb_frags, skb_shinfo(gro_skb)->frags, + skb_frags, gro_skb, ring->page_alloc, length); if (!nr) goto next; @@ -608,7 +608,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud skb_shinfo(gro_skb)->nr_frags = nr; gro_skb->len = length; gro_skb->data_len = length; - gro_skb->truesize += length; gro_skb->ip_summed = CHECKSUM_UNNECESSARY; if (cqe->vlan_my_qpn & @@ -618,6 +617,10 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud __vlan_hwaccel_put_tag(gro_skb, vid); } + if (dev->features & NETIF_F_RXHASH) + gro_skb->rxhash = be32_to_cpu(cqe->immed_rss_invalid); + + skb_record_rx_queue(gro_skb, cq->ring); napi_gro_frags(&cq->napi); goto next; @@ -627,11 +630,11 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud ip_summed = CHECKSUM_UNNECESSARY; } else { ip_summed = CHECKSUM_NONE; - priv->port_stats.rx_chksum_none++; + ring->csum_none++; } } else { ip_summed = CHECKSUM_NONE; - priv->port_stats.rx_chksum_none++; + ring->csum_none++; } skb = mlx4_en_rx_skb(priv, rx_desc, skb_frags, @@ -650,6 +653,9 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud skb->protocol = eth_type_trans(skb, dev); skb_record_rx_queue(skb, cq->ring); + if (dev->features & NETIF_F_RXHASH) + skb->rxhash = be32_to_cpu(cqe->immed_rss_invalid); + if (be32_to_cpu(cqe->vlan_my_qpn) & MLX4_CQE_VLAN_PRESENT_MASK) __vlan_hwaccel_put_tag(skb, be16_to_cpu(cqe->sl_vid)); @@ -806,6 +812,10 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn, qpn, ring->cqn, context); context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma); + /* Cancel FCS removal if FW allows */ + if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_FCS_KEEP) + context->param3 |= cpu_to_be32(1 << 29); + err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, context, qp, state); if (err) { mlx4_qp_remove(mdev->dev, qp); @@ -829,6 +839,9 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) int i, qpn; int err = 0; int good_qps = 0; + static const u32 rsskey[10] = { 0xD181C62C, 0xF7F4DB5B, 0x1983A2FC, + 0x943E1ADB, 0xD9389E6B, 0xD1039C2C, 0xA74499AD, + 0x593D56D9, 0xF3253C06, 0x2ADC1FFC}; en_dbg(DRV, priv, "Configuring rss steering\n"); err = mlx4_qp_reserve_range(mdev->dev, priv->rx_ring_num, @@ -866,6 +879,9 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) (rss_map->base_qpn)); rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn); rss_context->flags = rss_mask; + rss_context->hash_fn = 1; + 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; |