Skip to content

Commit 30408a4

Browse files
committed
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: David S. Miller <[email protected]>
2 parents c65a6a9 + ed56c51 commit 30408a4

File tree

13 files changed

+252
-48
lines changed

13 files changed

+252
-48
lines changed

drivers/net/ethernet/mellanox/mlx5/core/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ mlx5_core-$(CONFIG_MLX5_FPGA) += fpga/cmd.o fpga/core.o fpga/conn.o fpga/sdk.o \
1414
fpga/ipsec.o fpga/tls.o
1515

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

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

drivers/net/ethernet/mellanox/mlx5/core/en.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ struct page_pool;
137137
#define MLX5E_MAX_NUM_CHANNELS (MLX5E_INDIR_RQT_SIZE >> 1)
138138
#define MLX5E_MAX_NUM_SQS (MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC)
139139
#define MLX5E_TX_CQ_POLL_BUDGET 128
140-
#define MLX5E_UPDATE_STATS_INTERVAL 200 /* msecs */
141140
#define MLX5E_SQ_RECOVER_MIN_INTERVAL 500 /* msecs */
142141

143142
#define MLX5E_UMR_WQE_INLINE_SZ \

drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,11 @@
3434
#ifndef __MLX5E_EN_ACCEL_H__
3535
#define __MLX5E_EN_ACCEL_H__
3636

37-
#ifdef CONFIG_MLX5_ACCEL
38-
3937
#include <linux/skbuff.h>
4038
#include <linux/netdevice.h>
4139
#include "en_accel/ipsec_rxtx.h"
4240
#include "en_accel/tls_rxtx.h"
41+
#include "en_accel/rxtx.h"
4342
#include "en.h"
4443

4544
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,
6463
}
6564
#endif
6665

66+
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
67+
skb = mlx5e_udp_gso_handle_tx_skb(dev, sq, skb, wqe, pi);
68+
if (unlikely(!skb))
69+
return NULL;
70+
}
71+
6772
return skb;
6873
}
6974

70-
#endif /* CONFIG_MLX5_ACCEL */
71-
7275
#endif /* __MLX5E_EN_ACCEL_H__ */
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#include "en_accel/rxtx.h"
2+
3+
static void mlx5e_udp_gso_prepare_last_skb(struct sk_buff *skb,
4+
struct sk_buff *nskb,
5+
int remaining)
6+
{
7+
int bytes_needed = remaining, remaining_headlen, remaining_page_offset;
8+
int headlen = skb_transport_offset(skb) + sizeof(struct udphdr);
9+
int payload_len = remaining + sizeof(struct udphdr);
10+
int k = 0, i, j;
11+
12+
skb_copy_bits(skb, 0, nskb->data, headlen);
13+
nskb->dev = skb->dev;
14+
skb_reset_mac_header(nskb);
15+
skb_set_network_header(nskb, skb_network_offset(skb));
16+
skb_set_transport_header(nskb, skb_transport_offset(skb));
17+
skb_set_tail_pointer(nskb, headlen);
18+
19+
/* How many frags do we need? */
20+
for (i = skb_shinfo(skb)->nr_frags - 1; i >= 0; i--) {
21+
bytes_needed -= skb_frag_size(&skb_shinfo(skb)->frags[i]);
22+
k++;
23+
if (bytes_needed <= 0)
24+
break;
25+
}
26+
27+
/* Fill the first frag and split it if necessary */
28+
j = skb_shinfo(skb)->nr_frags - k;
29+
remaining_page_offset = -bytes_needed;
30+
skb_fill_page_desc(nskb, 0,
31+
skb_shinfo(skb)->frags[j].page.p,
32+
skb_shinfo(skb)->frags[j].page_offset + remaining_page_offset,
33+
skb_shinfo(skb)->frags[j].size - remaining_page_offset);
34+
35+
skb_frag_ref(skb, j);
36+
37+
/* Fill the rest of the frags */
38+
for (i = 1; i < k; i++) {
39+
j = skb_shinfo(skb)->nr_frags - k + i;
40+
41+
skb_fill_page_desc(nskb, i,
42+
skb_shinfo(skb)->frags[j].page.p,
43+
skb_shinfo(skb)->frags[j].page_offset,
44+
skb_shinfo(skb)->frags[j].size);
45+
skb_frag_ref(skb, j);
46+
}
47+
skb_shinfo(nskb)->nr_frags = k;
48+
49+
remaining_headlen = remaining - skb->data_len;
50+
51+
/* headlen contains remaining data? */
52+
if (remaining_headlen > 0)
53+
skb_copy_bits(skb, skb->len - remaining, nskb->data + headlen,
54+
remaining_headlen);
55+
nskb->len = remaining + headlen;
56+
nskb->data_len = payload_len - sizeof(struct udphdr) +
57+
max_t(int, 0, remaining_headlen);
58+
nskb->protocol = skb->protocol;
59+
if (nskb->protocol == htons(ETH_P_IP)) {
60+
ip_hdr(nskb)->id = htons(ntohs(ip_hdr(nskb)->id) +
61+
skb_shinfo(skb)->gso_segs);
62+
ip_hdr(nskb)->tot_len =
63+
htons(payload_len + sizeof(struct iphdr));
64+
} else {
65+
ipv6_hdr(nskb)->payload_len = htons(payload_len);
66+
}
67+
udp_hdr(nskb)->len = htons(payload_len);
68+
skb_shinfo(nskb)->gso_size = 0;
69+
nskb->ip_summed = skb->ip_summed;
70+
nskb->csum_start = skb->csum_start;
71+
nskb->csum_offset = skb->csum_offset;
72+
nskb->queue_mapping = skb->queue_mapping;
73+
}
74+
75+
/* might send skbs and update wqe and pi */
76+
struct sk_buff *mlx5e_udp_gso_handle_tx_skb(struct net_device *netdev,
77+
struct mlx5e_txqsq *sq,
78+
struct sk_buff *skb,
79+
struct mlx5e_tx_wqe **wqe,
80+
u16 *pi)
81+
{
82+
int payload_len = skb_shinfo(skb)->gso_size + sizeof(struct udphdr);
83+
int headlen = skb_transport_offset(skb) + sizeof(struct udphdr);
84+
int remaining = (skb->len - headlen) % skb_shinfo(skb)->gso_size;
85+
struct sk_buff *nskb;
86+
87+
if (skb->protocol == htons(ETH_P_IP))
88+
ip_hdr(skb)->tot_len = htons(payload_len + sizeof(struct iphdr));
89+
else
90+
ipv6_hdr(skb)->payload_len = htons(payload_len);
91+
udp_hdr(skb)->len = htons(payload_len);
92+
if (!remaining)
93+
return skb;
94+
95+
sq->stats->udp_seg_rem++;
96+
nskb = alloc_skb(max_t(int, headlen, headlen + remaining - skb->data_len), GFP_ATOMIC);
97+
if (unlikely(!nskb)) {
98+
sq->stats->dropped++;
99+
return NULL;
100+
}
101+
102+
mlx5e_udp_gso_prepare_last_skb(skb, nskb, remaining);
103+
104+
skb_shinfo(skb)->gso_segs--;
105+
pskb_trim(skb, skb->len - remaining);
106+
mlx5e_sq_xmit(sq, skb, *wqe, *pi);
107+
mlx5e_sq_fetch_wqe(sq, wqe, pi);
108+
return nskb;
109+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
#ifndef __MLX5E_EN_ACCEL_RX_TX_H__
3+
#define __MLX5E_EN_ACCEL_RX_TX_H__
4+
5+
#include <linux/skbuff.h>
6+
#include "en.h"
7+
8+
struct sk_buff *mlx5e_udp_gso_handle_tx_skb(struct net_device *netdev,
9+
struct mlx5e_txqsq *sq,
10+
struct sk_buff *skb,
11+
struct mlx5e_tx_wqe **wqe,
12+
u16 *pi);
13+
14+
#endif

drivers/net/ethernet/mellanox/mlx5/core/en_main.c

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -270,12 +270,9 @@ void mlx5e_update_stats_work(struct work_struct *work)
270270
struct delayed_work *dwork = to_delayed_work(work);
271271
struct mlx5e_priv *priv = container_of(dwork, struct mlx5e_priv,
272272
update_stats_work);
273+
273274
mutex_lock(&priv->state_lock);
274-
if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
275-
priv->profile->update_stats(priv);
276-
queue_delayed_work(priv->wq, dwork,
277-
msecs_to_jiffies(MLX5E_UPDATE_STATS_INTERVAL));
278-
}
275+
priv->profile->update_stats(priv);
279276
mutex_unlock(&priv->state_lock);
280277
}
281278

@@ -352,8 +349,8 @@ static int mlx5e_rq_alloc_mpwqe_info(struct mlx5e_rq *rq,
352349
{
353350
int wq_sz = mlx5_wq_ll_get_size(&rq->mpwqe.wq);
354351

355-
rq->mpwqe.info = kcalloc_node(wq_sz, sizeof(*rq->mpwqe.info),
356-
GFP_KERNEL, cpu_to_node(c->cpu));
352+
rq->mpwqe.info = kvzalloc_node(wq_sz * sizeof(*rq->mpwqe.info),
353+
GFP_KERNEL, cpu_to_node(c->cpu));
357354
if (!rq->mpwqe.info)
358355
return -ENOMEM;
359356

@@ -670,7 +667,7 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
670667
err_free:
671668
switch (rq->wq_type) {
672669
case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
673-
kfree(rq->mpwqe.info);
670+
kvfree(rq->mpwqe.info);
674671
mlx5_core_destroy_mkey(mdev, &rq->umr_mkey);
675672
break;
676673
default: /* MLX5_WQ_TYPE_CYCLIC */
@@ -702,7 +699,7 @@ static void mlx5e_free_rq(struct mlx5e_rq *rq)
702699

703700
switch (rq->wq_type) {
704701
case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
705-
kfree(rq->mpwqe.info);
702+
kvfree(rq->mpwqe.info);
706703
mlx5_core_destroy_mkey(rq->mdev, &rq->umr_mkey);
707704
break;
708705
default: /* MLX5_WQ_TYPE_CYCLIC */
@@ -965,15 +962,15 @@ static void mlx5e_close_rq(struct mlx5e_rq *rq)
965962

966963
static void mlx5e_free_xdpsq_db(struct mlx5e_xdpsq *sq)
967964
{
968-
kfree(sq->db.di);
965+
kvfree(sq->db.di);
969966
}
970967

971968
static int mlx5e_alloc_xdpsq_db(struct mlx5e_xdpsq *sq, int numa)
972969
{
973970
int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
974971

975-
sq->db.di = kcalloc_node(wq_sz, sizeof(*sq->db.di),
976-
GFP_KERNEL, numa);
972+
sq->db.di = kvzalloc_node(sizeof(*sq->db.di) * wq_sz,
973+
GFP_KERNEL, numa);
977974
if (!sq->db.di) {
978975
mlx5e_free_xdpsq_db(sq);
979976
return -ENOMEM;
@@ -1024,15 +1021,15 @@ static void mlx5e_free_xdpsq(struct mlx5e_xdpsq *sq)
10241021

10251022
static void mlx5e_free_icosq_db(struct mlx5e_icosq *sq)
10261023
{
1027-
kfree(sq->db.ico_wqe);
1024+
kvfree(sq->db.ico_wqe);
10281025
}
10291026

10301027
static int mlx5e_alloc_icosq_db(struct mlx5e_icosq *sq, int numa)
10311028
{
10321029
u8 wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
10331030

1034-
sq->db.ico_wqe = kcalloc_node(wq_sz, sizeof(*sq->db.ico_wqe),
1035-
GFP_KERNEL, numa);
1031+
sq->db.ico_wqe = kvzalloc_node(sizeof(*sq->db.ico_wqe) * wq_sz,
1032+
GFP_KERNEL, numa);
10361033
if (!sq->db.ico_wqe)
10371034
return -ENOMEM;
10381035

@@ -1077,19 +1074,19 @@ static void mlx5e_free_icosq(struct mlx5e_icosq *sq)
10771074

10781075
static void mlx5e_free_txqsq_db(struct mlx5e_txqsq *sq)
10791076
{
1080-
kfree(sq->db.wqe_info);
1081-
kfree(sq->db.dma_fifo);
1077+
kvfree(sq->db.wqe_info);
1078+
kvfree(sq->db.dma_fifo);
10821079
}
10831080

10841081
static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa)
10851082
{
10861083
int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
10871084
int df_sz = wq_sz * MLX5_SEND_WQEBB_NUM_DS;
10881085

1089-
sq->db.dma_fifo = kcalloc_node(df_sz, sizeof(*sq->db.dma_fifo),
1090-
GFP_KERNEL, numa);
1091-
sq->db.wqe_info = kcalloc_node(wq_sz, sizeof(*sq->db.wqe_info),
1092-
GFP_KERNEL, numa);
1086+
sq->db.dma_fifo = kvzalloc_node(df_sz * sizeof(*sq->db.dma_fifo),
1087+
GFP_KERNEL, numa);
1088+
sq->db.wqe_info = kvzalloc_node(wq_sz * sizeof(*sq->db.wqe_info),
1089+
GFP_KERNEL, numa);
10931090
if (!sq->db.dma_fifo || !sq->db.wqe_info) {
10941091
mlx5e_free_txqsq_db(sq);
10951092
return -ENOMEM;
@@ -1893,7 +1890,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
18931890
int err;
18941891
int eqn;
18951892

1896-
c = kzalloc_node(sizeof(*c), GFP_KERNEL, cpu_to_node(cpu));
1893+
c = kvzalloc_node(sizeof(*c), GFP_KERNEL, cpu_to_node(cpu));
18971894
if (!c)
18981895
return -ENOMEM;
18991896

@@ -1979,7 +1976,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
19791976

19801977
err_napi_del:
19811978
netif_napi_del(&c->napi);
1982-
kfree(c);
1979+
kvfree(c);
19831980

19841981
return err;
19851982
}
@@ -2018,7 +2015,7 @@ static void mlx5e_close_channel(struct mlx5e_channel *c)
20182015
mlx5e_close_cq(&c->icosq.cq);
20192016
netif_napi_del(&c->napi);
20202017

2021-
kfree(c);
2018+
kvfree(c);
20222019
}
20232020

20242021
#define DEFAULT_FRAG_SIZE (2048)
@@ -2276,7 +2273,7 @@ int mlx5e_open_channels(struct mlx5e_priv *priv,
22762273
chs->num = chs->params.num_channels;
22772274

22782275
chs->c = kcalloc(chs->num, sizeof(struct mlx5e_channel *), GFP_KERNEL);
2279-
cparam = kzalloc(sizeof(struct mlx5e_channel_param), GFP_KERNEL);
2276+
cparam = kvzalloc(sizeof(struct mlx5e_channel_param), GFP_KERNEL);
22802277
if (!chs->c || !cparam)
22812278
goto err_free;
22822279

@@ -2287,7 +2284,7 @@ int mlx5e_open_channels(struct mlx5e_priv *priv,
22872284
goto err_close_channels;
22882285
}
22892286

2290-
kfree(cparam);
2287+
kvfree(cparam);
22912288
return 0;
22922289

22932290
err_close_channels:
@@ -2296,7 +2293,7 @@ int mlx5e_open_channels(struct mlx5e_priv *priv,
22962293

22972294
err_free:
22982295
kfree(chs->c);
2299-
kfree(cparam);
2296+
kvfree(cparam);
23002297
chs->num = 0;
23012298
return err;
23022299
}
@@ -3405,6 +3402,9 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
34053402
struct mlx5e_vport_stats *vstats = &priv->stats.vport;
34063403
struct mlx5e_pport_stats *pstats = &priv->stats.pport;
34073404

3405+
/* update HW stats in background for next time */
3406+
queue_delayed_work(priv->wq, &priv->update_stats_work, 0);
3407+
34083408
if (mlx5e_is_uplink_rep(priv)) {
34093409
stats->rx_packets = PPORT_802_3_GET(pstats, a_frames_received_ok);
34103410
stats->rx_bytes = PPORT_802_3_GET(pstats, a_octets_received_ok);
@@ -4592,6 +4592,9 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
45924592
netdev->features |= NETIF_F_HIGHDMA;
45934593
netdev->features |= NETIF_F_HW_VLAN_STAG_FILTER;
45944594

4595+
netdev->features |= NETIF_F_GSO_UDP_L4;
4596+
netdev->hw_features |= NETIF_F_GSO_UDP_L4;
4597+
45954598
netdev->priv_flags |= IFF_UNICAST_FLT;
45964599

45974600
mlx5e_set_netdev_dev_addr(netdev);

drivers/net/ethernet/mellanox/mlx5/core/en_rep.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,9 @@ mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
893893
{
894894
struct mlx5e_priv *priv = netdev_priv(dev);
895895

896+
/* update HW stats in background for next time */
897+
queue_delayed_work(priv->wq, &priv->update_stats_work, 0);
898+
896899
memcpy(stats, &priv->stats.vf_vport, sizeof(*stats));
897900
}
898901

0 commit comments

Comments
 (0)