Commit 30408a43 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'mlx5e-updates-2018-06-28' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux



Saeed Mahameed says:

====================
mlx5e-updates-2018-06-28

mlx5e netdevice driver updates:

- Boris Pismenny added the support for UDP GSO in the first two patches.
  Impressive performance numbers are included in the commit message,
  @Line rate with ~half of the cpu utilization compared to non offload
  or no GSO at all.

- From Tariq Toukan:
  - Convert large order kzalloc allocations to kvzalloc.
  - Added performance diagnostic statistics to several places in data path.

From Saeed and Eran,
  - Update NIC HW stats on demand only, this is to eliminate the background
    thread needed to update some HW statistics in the driver cache in
    order to report error and drop counters from HW in ndo_get_stats.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c65a6a93 ed56c519
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -14,8 +14,8 @@ mlx5_core-$(CONFIG_MLX5_FPGA) += fpga/cmd.o fpga/core.o fpga/conn.o fpga/sdk.o \
		fpga/ipsec.o fpga/tls.o
		fpga/ipsec.o fpga/tls.o


mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \
mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \
		en_tx.o en_rx.o en_dim.o en_txrx.o en_stats.o vxlan.o \
		en_tx.o en_rx.o en_dim.o en_txrx.o en_accel/rxtx.o en_stats.o  \
		en_arfs.o en_fs_ethtool.o en_selftest.o en/port.o
		vxlan.o en_arfs.o en_fs_ethtool.o en_selftest.o en/port.o


mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o


+0 −1
Original line number Original line Diff line number Diff line
@@ -137,7 +137,6 @@ struct page_pool;
#define MLX5E_MAX_NUM_CHANNELS         (MLX5E_INDIR_RQT_SIZE >> 1)
#define MLX5E_MAX_NUM_CHANNELS         (MLX5E_INDIR_RQT_SIZE >> 1)
#define MLX5E_MAX_NUM_SQS              (MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC)
#define MLX5E_MAX_NUM_SQS              (MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC)
#define MLX5E_TX_CQ_POLL_BUDGET        128
#define MLX5E_TX_CQ_POLL_BUDGET        128
#define MLX5E_UPDATE_STATS_INTERVAL    200 /* msecs */
#define MLX5E_SQ_RECOVER_MIN_INTERVAL  500 /* msecs */
#define MLX5E_SQ_RECOVER_MIN_INTERVAL  500 /* msecs */


#define MLX5E_UMR_WQE_INLINE_SZ \
#define MLX5E_UMR_WQE_INLINE_SZ \
+7 −4
Original line number Original line Diff line number Diff line
@@ -34,12 +34,11 @@
#ifndef __MLX5E_EN_ACCEL_H__
#ifndef __MLX5E_EN_ACCEL_H__
#define __MLX5E_EN_ACCEL_H__
#define __MLX5E_EN_ACCEL_H__


#ifdef CONFIG_MLX5_ACCEL

#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include "en_accel/ipsec_rxtx.h"
#include "en_accel/ipsec_rxtx.h"
#include "en_accel/tls_rxtx.h"
#include "en_accel/tls_rxtx.h"
#include "en_accel/rxtx.h"
#include "en.h"
#include "en.h"


static inline struct sk_buff *mlx5e_accel_handle_tx(struct sk_buff *skb,
static inline struct sk_buff *mlx5e_accel_handle_tx(struct sk_buff *skb,
@@ -64,9 +63,13 @@ static inline struct sk_buff *mlx5e_accel_handle_tx(struct sk_buff *skb,
	}
	}
#endif
#endif


	return skb;
	if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
		skb = mlx5e_udp_gso_handle_tx_skb(dev, sq, skb, wqe, pi);
		if (unlikely(!skb))
			return NULL;
	}
	}


#endif /* CONFIG_MLX5_ACCEL */
	return skb;
}


#endif /* __MLX5E_EN_ACCEL_H__ */
#endif /* __MLX5E_EN_ACCEL_H__ */
+109 −0
Original line number Original line Diff line number Diff line
#include "en_accel/rxtx.h"

static void mlx5e_udp_gso_prepare_last_skb(struct sk_buff *skb,
					   struct sk_buff *nskb,
					   int remaining)
{
	int bytes_needed = remaining, remaining_headlen, remaining_page_offset;
	int headlen = skb_transport_offset(skb) + sizeof(struct udphdr);
	int payload_len = remaining + sizeof(struct udphdr);
	int k = 0, i, j;

	skb_copy_bits(skb, 0, nskb->data, headlen);
	nskb->dev = skb->dev;
	skb_reset_mac_header(nskb);
	skb_set_network_header(nskb, skb_network_offset(skb));
	skb_set_transport_header(nskb, skb_transport_offset(skb));
	skb_set_tail_pointer(nskb, headlen);

	/* How many frags do we need? */
	for (i = skb_shinfo(skb)->nr_frags - 1; i >= 0; i--) {
		bytes_needed -= skb_frag_size(&skb_shinfo(skb)->frags[i]);
		k++;
		if (bytes_needed <= 0)
			break;
	}

	/* Fill the first frag and split it if necessary */
	j = skb_shinfo(skb)->nr_frags - k;
	remaining_page_offset = -bytes_needed;
	skb_fill_page_desc(nskb, 0,
			   skb_shinfo(skb)->frags[j].page.p,
			   skb_shinfo(skb)->frags[j].page_offset + remaining_page_offset,
			   skb_shinfo(skb)->frags[j].size - remaining_page_offset);

	skb_frag_ref(skb, j);

	/* Fill the rest of the frags */
	for (i = 1; i < k; i++) {
		j = skb_shinfo(skb)->nr_frags - k + i;

		skb_fill_page_desc(nskb, i,
				   skb_shinfo(skb)->frags[j].page.p,
				   skb_shinfo(skb)->frags[j].page_offset,
				   skb_shinfo(skb)->frags[j].size);
		skb_frag_ref(skb, j);
	}
	skb_shinfo(nskb)->nr_frags = k;

	remaining_headlen = remaining - skb->data_len;

	/* headlen contains remaining data? */
	if (remaining_headlen > 0)
		skb_copy_bits(skb, skb->len - remaining, nskb->data + headlen,
			      remaining_headlen);
	nskb->len = remaining + headlen;
	nskb->data_len =  payload_len - sizeof(struct udphdr) +
		max_t(int, 0, remaining_headlen);
	nskb->protocol = skb->protocol;
	if (nskb->protocol == htons(ETH_P_IP)) {
		ip_hdr(nskb)->id = htons(ntohs(ip_hdr(nskb)->id) +
					 skb_shinfo(skb)->gso_segs);
		ip_hdr(nskb)->tot_len =
			htons(payload_len + sizeof(struct iphdr));
	} else {
		ipv6_hdr(nskb)->payload_len = htons(payload_len);
	}
	udp_hdr(nskb)->len = htons(payload_len);
	skb_shinfo(nskb)->gso_size = 0;
	nskb->ip_summed = skb->ip_summed;
	nskb->csum_start = skb->csum_start;
	nskb->csum_offset = skb->csum_offset;
	nskb->queue_mapping = skb->queue_mapping;
}

/* might send skbs and update wqe and pi */
struct sk_buff *mlx5e_udp_gso_handle_tx_skb(struct net_device *netdev,
					    struct mlx5e_txqsq *sq,
					    struct sk_buff *skb,
					    struct mlx5e_tx_wqe **wqe,
					    u16 *pi)
{
	int payload_len = skb_shinfo(skb)->gso_size + sizeof(struct udphdr);
	int headlen = skb_transport_offset(skb) + sizeof(struct udphdr);
	int remaining = (skb->len - headlen) % skb_shinfo(skb)->gso_size;
	struct sk_buff *nskb;

	if (skb->protocol == htons(ETH_P_IP))
		ip_hdr(skb)->tot_len = htons(payload_len + sizeof(struct iphdr));
	else
		ipv6_hdr(skb)->payload_len = htons(payload_len);
	udp_hdr(skb)->len = htons(payload_len);
	if (!remaining)
		return skb;

	sq->stats->udp_seg_rem++;
	nskb = alloc_skb(max_t(int, headlen, headlen + remaining - skb->data_len), GFP_ATOMIC);
	if (unlikely(!nskb)) {
		sq->stats->dropped++;
		return NULL;
	}

	mlx5e_udp_gso_prepare_last_skb(skb, nskb, remaining);

	skb_shinfo(skb)->gso_segs--;
	pskb_trim(skb, skb->len - remaining);
	mlx5e_sq_xmit(sq, skb, *wqe, *pi);
	mlx5e_sq_fetch_wqe(sq, wqe, pi);
	return nskb;
}
+14 −0
Original line number Original line Diff line number Diff line

#ifndef __MLX5E_EN_ACCEL_RX_TX_H__
#define __MLX5E_EN_ACCEL_RX_TX_H__

#include <linux/skbuff.h>
#include "en.h"

struct sk_buff *mlx5e_udp_gso_handle_tx_skb(struct net_device *netdev,
					    struct mlx5e_txqsq *sq,
					    struct sk_buff *skb,
					    struct mlx5e_tx_wqe **wqe,
					    u16 *pi);

#endif
Loading