Commit 18c5c0a8 authored by Fei Qin's avatar Fei Qin Committed by David S. Miller

nfp: support UDP segmentation offload

The device supports UDP hardware segmentation offload, which helps
improving the performance. Thus, this patch adds support for UDP
segmentation offload from the driver side.
Signed-off-by: default avatarFei Qin <fei.qin@corigine.com>
Signed-off-by: default avatarLouis Peens <louis.peens@corigine.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6e944cc6
...@@ -74,7 +74,7 @@ static void ...@@ -74,7 +74,7 @@ static void
nfp_nfd3_tx_tso(struct nfp_net_r_vector *r_vec, struct nfp_nfd3_tx_buf *txbuf, nfp_nfd3_tx_tso(struct nfp_net_r_vector *r_vec, struct nfp_nfd3_tx_buf *txbuf,
struct nfp_nfd3_tx_desc *txd, struct sk_buff *skb, u32 md_bytes) struct nfp_nfd3_tx_desc *txd, struct sk_buff *skb, u32 md_bytes)
{ {
u32 l3_offset, l4_offset, hdrlen; u32 l3_offset, l4_offset, hdrlen, l4_hdrlen;
u16 mss; u16 mss;
if (!skb_is_gso(skb)) if (!skb_is_gso(skb))
...@@ -83,13 +83,16 @@ nfp_nfd3_tx_tso(struct nfp_net_r_vector *r_vec, struct nfp_nfd3_tx_buf *txbuf, ...@@ -83,13 +83,16 @@ nfp_nfd3_tx_tso(struct nfp_net_r_vector *r_vec, struct nfp_nfd3_tx_buf *txbuf,
if (!skb->encapsulation) { if (!skb->encapsulation) {
l3_offset = skb_network_offset(skb); l3_offset = skb_network_offset(skb);
l4_offset = skb_transport_offset(skb); l4_offset = skb_transport_offset(skb);
hdrlen = skb_tcp_all_headers(skb); l4_hdrlen = (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ?
sizeof(struct udphdr) : tcp_hdrlen(skb);
} else { } else {
l3_offset = skb_inner_network_offset(skb); l3_offset = skb_inner_network_offset(skb);
l4_offset = skb_inner_transport_offset(skb); l4_offset = skb_inner_transport_offset(skb);
hdrlen = skb_inner_tcp_all_headers(skb); l4_hdrlen = (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ?
sizeof(struct udphdr) : inner_tcp_hdrlen(skb);
} }
hdrlen = l4_offset + l4_hdrlen;
txbuf->pkt_cnt = skb_shinfo(skb)->gso_segs; txbuf->pkt_cnt = skb_shinfo(skb)->gso_segs;
txbuf->real_len += hdrlen * (txbuf->pkt_cnt - 1); txbuf->real_len += hdrlen * (txbuf->pkt_cnt - 1);
......
...@@ -40,20 +40,23 @@ static __le64 ...@@ -40,20 +40,23 @@ static __le64
nfp_nfdk_tx_tso(struct nfp_net_r_vector *r_vec, struct nfp_nfdk_tx_buf *txbuf, nfp_nfdk_tx_tso(struct nfp_net_r_vector *r_vec, struct nfp_nfdk_tx_buf *txbuf,
struct sk_buff *skb) struct sk_buff *skb)
{ {
u32 segs, hdrlen, l3_offset, l4_offset; u32 segs, hdrlen, l3_offset, l4_offset, l4_hdrlen;
struct nfp_nfdk_tx_desc txd; struct nfp_nfdk_tx_desc txd;
u16 mss; u16 mss;
if (!skb->encapsulation) { if (!skb->encapsulation) {
l3_offset = skb_network_offset(skb); l3_offset = skb_network_offset(skb);
l4_offset = skb_transport_offset(skb); l4_offset = skb_transport_offset(skb);
hdrlen = skb_tcp_all_headers(skb); l4_hdrlen = (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ?
sizeof(struct udphdr) : tcp_hdrlen(skb);
} else { } else {
l3_offset = skb_inner_network_offset(skb); l3_offset = skb_inner_network_offset(skb);
l4_offset = skb_inner_transport_offset(skb); l4_offset = skb_inner_transport_offset(skb);
hdrlen = skb_inner_tcp_all_headers(skb); l4_hdrlen = (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ?
sizeof(struct udphdr) : inner_tcp_hdrlen(skb);
} }
hdrlen = l4_offset + l4_hdrlen;
segs = skb_shinfo(skb)->gso_segs; segs = skb_shinfo(skb)->gso_segs;
mss = skb_shinfo(skb)->gso_size & NFDK_DESC_TX_MSS_MASK; mss = skb_shinfo(skb)->gso_size & NFDK_DESC_TX_MSS_MASK;
......
...@@ -2116,7 +2116,10 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev, ...@@ -2116,7 +2116,10 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
if (skb_is_gso(skb)) { if (skb_is_gso(skb)) {
u32 hdrlen; u32 hdrlen;
hdrlen = skb_inner_tcp_all_headers(skb); if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
hdrlen = skb_inner_transport_offset(skb) + sizeof(struct udphdr);
else
hdrlen = skb_inner_tcp_all_headers(skb);
/* Assume worst case scenario of having longest possible /* Assume worst case scenario of having longest possible
* metadata prepend - 8B * metadata prepend - 8B
...@@ -2419,7 +2422,7 @@ void nfp_net_info(struct nfp_net *nn) ...@@ -2419,7 +2422,7 @@ void nfp_net_info(struct nfp_net *nn)
nn->fw_ver.extend, nn->fw_ver.class, nn->fw_ver.extend, nn->fw_ver.class,
nn->fw_ver.major, nn->fw_ver.minor, nn->fw_ver.major, nn->fw_ver.minor,
nn->max_mtu); nn->max_mtu);
nn_info(nn, "CAP: %#x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", nn_info(nn, "CAP: %#x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
nn->cap, nn->cap,
nn->cap & NFP_NET_CFG_CTRL_PROMISC ? "PROMISC " : "", nn->cap & NFP_NET_CFG_CTRL_PROMISC ? "PROMISC " : "",
nn->cap & NFP_NET_CFG_CTRL_L2BC ? "L2BCFILT " : "", nn->cap & NFP_NET_CFG_CTRL_L2BC ? "L2BCFILT " : "",
...@@ -2448,6 +2451,7 @@ void nfp_net_info(struct nfp_net *nn) ...@@ -2448,6 +2451,7 @@ void nfp_net_info(struct nfp_net *nn)
"RXCSUM_COMPLETE " : "", "RXCSUM_COMPLETE " : "",
nn->cap & NFP_NET_CFG_CTRL_LIVE_ADDR ? "LIVE_ADDR " : "", nn->cap & NFP_NET_CFG_CTRL_LIVE_ADDR ? "LIVE_ADDR " : "",
nn->cap_w1 & NFP_NET_CFG_CTRL_MCAST_FILTER ? "MULTICAST_FILTER " : "", nn->cap_w1 & NFP_NET_CFG_CTRL_MCAST_FILTER ? "MULTICAST_FILTER " : "",
nn->cap_w1 & NFP_NET_CFG_CTRL_USO ? "USO " : "",
nfp_app_extra_cap(nn->app, nn)); nfp_app_extra_cap(nn->app, nn));
} }
...@@ -2696,6 +2700,8 @@ static void nfp_net_netdev_init(struct nfp_net *nn) ...@@ -2696,6 +2700,8 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
if ((nn->cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) || if ((nn->cap & NFP_NET_CFG_CTRL_LSO && nn->fw_ver.major > 2) ||
nn->cap & NFP_NET_CFG_CTRL_LSO2) { nn->cap & NFP_NET_CFG_CTRL_LSO2) {
netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
if (nn->cap_w1 & NFP_NET_CFG_CTRL_USO)
netdev->hw_features |= NETIF_F_GSO_UDP_L4;
nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_LSO2 ?: nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_LSO2 ?:
NFP_NET_CFG_CTRL_LSO; NFP_NET_CFG_CTRL_LSO;
} }
......
...@@ -270,6 +270,7 @@ ...@@ -270,6 +270,7 @@
#define NFP_NET_CFG_CTRL_MCAST_FILTER (0x1 << 2) /* Multicast Filter */ #define NFP_NET_CFG_CTRL_MCAST_FILTER (0x1 << 2) /* Multicast Filter */
#define NFP_NET_CFG_CTRL_FREELIST_EN (0x1 << 6) /* Freelist enable flag bit */ #define NFP_NET_CFG_CTRL_FREELIST_EN (0x1 << 6) /* Freelist enable flag bit */
#define NFP_NET_CFG_CTRL_FLOW_STEER (0x1 << 8) /* Flow steering */ #define NFP_NET_CFG_CTRL_FLOW_STEER (0x1 << 8) /* Flow steering */
#define NFP_NET_CFG_CTRL_USO (0x1 << 16) /* UDP segmentation offload */
#define NFP_NET_CFG_CAP_WORD1 0x00a4 #define NFP_NET_CFG_CAP_WORD1 0x00a4
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment