Commit bd5196b6 authored by David S. Miller's avatar David S. Miller

Merge branch 'hns3-hwgro'

Salil Mehta says:

====================
net: hns3: Add support of hardware GRO to HNS3 Driver

This patch-set adds support of hardware assisted GRO feature to
HNS3 driver on Rev B(=0x21) platform. Current hardware only
supports TCP/IPv{4|6} flows.

Change Log:
V1->V2:
1. Remove redundant print reported by Leon Romanovsky.
   Link: https://lkml.org/lkml/2018/11/13/715
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ba2f55b0 a6d53b97
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#define HNAE3_UNIC_CLIENT_INITED_B 0x4 #define HNAE3_UNIC_CLIENT_INITED_B 0x4
#define HNAE3_ROCE_CLIENT_INITED_B 0x5 #define HNAE3_ROCE_CLIENT_INITED_B 0x5
#define HNAE3_DEV_SUPPORT_FD_B 0x6 #define HNAE3_DEV_SUPPORT_FD_B 0x6
#define HNAE3_DEV_SUPPORT_GRO_B 0x7
#define HNAE3_DEV_SUPPORT_ROCE_DCB_BITS (BIT(HNAE3_DEV_SUPPORT_DCB_B) |\ #define HNAE3_DEV_SUPPORT_ROCE_DCB_BITS (BIT(HNAE3_DEV_SUPPORT_DCB_B) |\
BIT(HNAE3_DEV_SUPPORT_ROCE_B)) BIT(HNAE3_DEV_SUPPORT_ROCE_B))
...@@ -65,6 +66,9 @@ ...@@ -65,6 +66,9 @@
#define hnae3_dev_fd_supported(hdev) \ #define hnae3_dev_fd_supported(hdev) \
hnae3_get_bit((hdev)->ae_dev->flag, HNAE3_DEV_SUPPORT_FD_B) hnae3_get_bit((hdev)->ae_dev->flag, HNAE3_DEV_SUPPORT_FD_B)
#define hnae3_dev_gro_supported(hdev) \
hnae3_get_bit((hdev)->ae_dev->flag, HNAE3_DEV_SUPPORT_GRO_B)
#define ring_ptr_move_fw(ring, p) \ #define ring_ptr_move_fw(ring, p) \
((ring)->p = ((ring)->p + 1) % (ring)->desc_num) ((ring)->p = ((ring)->p + 1) % (ring)->desc_num)
#define ring_ptr_move_bw(ring, p) \ #define ring_ptr_move_bw(ring, p) \
...@@ -301,6 +305,8 @@ struct hnae3_ae_dev { ...@@ -301,6 +305,8 @@ struct hnae3_ae_dev {
* Set vlan filter config of vf * Set vlan filter config of vf
* enable_hw_strip_rxvtag() * enable_hw_strip_rxvtag()
* Enable/disable hardware strip vlan tag of packets received * Enable/disable hardware strip vlan tag of packets received
* set_gro_en
* Enable/disable HW GRO
*/ */
struct hnae3_ae_ops { struct hnae3_ae_ops {
int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev); int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev);
...@@ -445,6 +451,7 @@ struct hnae3_ae_ops { ...@@ -445,6 +451,7 @@ struct hnae3_ae_ops {
bool (*get_hw_reset_stat)(struct hnae3_handle *handle); bool (*get_hw_reset_stat)(struct hnae3_handle *handle);
bool (*ae_dev_resetting)(struct hnae3_handle *handle); bool (*ae_dev_resetting)(struct hnae3_handle *handle);
unsigned long (*ae_dev_reset_cnt)(struct hnae3_handle *handle); unsigned long (*ae_dev_reset_cnt)(struct hnae3_handle *handle);
int (*set_gro_en)(struct hnae3_handle *handle, int enable);
}; };
struct hnae3_dcb_ops { struct hnae3_dcb_ops {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/vermagic.h> #include <linux/vermagic.h>
#include <net/gre.h> #include <net/gre.h>
#include <net/pkt_cls.h> #include <net/pkt_cls.h>
#include <net/tcp.h>
#include <net/vxlan.h> #include <net/vxlan.h>
#include "hnae3.h" #include "hnae3.h"
...@@ -1345,6 +1346,15 @@ static int hns3_nic_set_features(struct net_device *netdev, ...@@ -1345,6 +1346,15 @@ static int hns3_nic_set_features(struct net_device *netdev,
priv->ops.maybe_stop_tx = hns3_nic_maybe_stop_tx; priv->ops.maybe_stop_tx = hns3_nic_maybe_stop_tx;
} }
if (changed & (NETIF_F_GRO_HW) && h->ae_algo->ops->set_gro_en) {
if (features & NETIF_F_GRO_HW)
ret = h->ae_algo->ops->set_gro_en(h, true);
else
ret = h->ae_algo->ops->set_gro_en(h, false);
if (ret)
return ret;
}
if ((changed & NETIF_F_HW_VLAN_CTAG_FILTER) && if ((changed & NETIF_F_HW_VLAN_CTAG_FILTER) &&
h->ae_algo->ops->enable_vlan_filter) { h->ae_algo->ops->enable_vlan_filter) {
if (features & NETIF_F_HW_VLAN_CTAG_FILTER) if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
...@@ -1714,8 +1724,10 @@ static void hns3_disable_sriov(struct pci_dev *pdev) ...@@ -1714,8 +1724,10 @@ static void hns3_disable_sriov(struct pci_dev *pdev)
static void hns3_get_dev_capability(struct pci_dev *pdev, static void hns3_get_dev_capability(struct pci_dev *pdev,
struct hnae3_ae_dev *ae_dev) struct hnae3_ae_dev *ae_dev)
{ {
if (pdev->revision >= 0x21) if (pdev->revision >= 0x21) {
hnae3_set_bit(ae_dev->flag, HNAE3_DEV_SUPPORT_FD_B, 1); hnae3_set_bit(ae_dev->flag, HNAE3_DEV_SUPPORT_FD_B, 1);
hnae3_set_bit(ae_dev->flag, HNAE3_DEV_SUPPORT_GRO_B, 1);
}
} }
/* hns3_probe - Device initialization routine /* hns3_probe - Device initialization routine
...@@ -1927,7 +1939,9 @@ static void hns3_set_default_feature(struct net_device *netdev) ...@@ -1927,7 +1939,9 @@ static void hns3_set_default_feature(struct net_device *netdev)
NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC; NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC;
if (pdev->revision >= 0x21) { if (pdev->revision >= 0x21) {
netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER |
NETIF_F_GRO_HW;
netdev->features |= NETIF_F_GRO_HW;
if (!(h->flags & HNAE3_SUPPORT_VF)) { if (!(h->flags & HNAE3_SUPPORT_VF)) {
netdev->hw_features |= NETIF_F_NTUPLE; netdev->hw_features |= NETIF_F_NTUPLE;
...@@ -2305,6 +2319,12 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, ...@@ -2305,6 +2319,12 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb,
if (!(netdev->features & NETIF_F_RXCSUM)) if (!(netdev->features & NETIF_F_RXCSUM))
return; return;
/* We MUST enable hardware checksum before enabling hardware GRO */
if (skb_shinfo(skb)->gso_size) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
return;
}
/* check if hardware has done checksum */ /* check if hardware has done checksum */
if (!hnae3_get_bit(bd_base_info, HNS3_RXD_L3L4P_B)) if (!hnae3_get_bit(bd_base_info, HNS3_RXD_L3L4P_B))
return; return;
...@@ -2348,6 +2368,9 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, ...@@ -2348,6 +2368,9 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb,
static void hns3_rx_skb(struct hns3_enet_ring *ring, struct sk_buff *skb) static void hns3_rx_skb(struct hns3_enet_ring *ring, struct sk_buff *skb)
{ {
if (skb_has_frag_list(skb))
napi_gro_flush(&ring->tqp_vector->napi, false);
napi_gro_receive(&ring->tqp_vector->napi, skb); napi_gro_receive(&ring->tqp_vector->napi, skb);
} }
...@@ -2381,6 +2404,153 @@ static bool hns3_parse_vlan_tag(struct hns3_enet_ring *ring, ...@@ -2381,6 +2404,153 @@ static bool hns3_parse_vlan_tag(struct hns3_enet_ring *ring,
} }
} }
static int hns3_alloc_skb(struct hns3_enet_ring *ring, int length,
unsigned char *va)
{
#define HNS3_NEED_ADD_FRAG 1
struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_clean];
struct net_device *netdev = ring->tqp->handle->kinfo.netdev;
struct sk_buff *skb;
ring->skb = napi_alloc_skb(&ring->tqp_vector->napi, HNS3_RX_HEAD_SIZE);
skb = ring->skb;
if (unlikely(!skb)) {
netdev_err(netdev, "alloc rx skb fail\n");
u64_stats_update_begin(&ring->syncp);
ring->stats.sw_err_cnt++;
u64_stats_update_end(&ring->syncp);
return -ENOMEM;
}
prefetchw(skb->data);
ring->pending_buf = 1;
ring->frag_num = 0;
ring->tail_skb = NULL;
if (length <= HNS3_RX_HEAD_SIZE) {
memcpy(__skb_put(skb, length), va, ALIGN(length, sizeof(long)));
/* We can reuse buffer as-is, just make sure it is local */
if (likely(page_to_nid(desc_cb->priv) == numa_node_id()))
desc_cb->reuse_flag = 1;
else /* This page cannot be reused so discard it */
put_page(desc_cb->priv);
ring_ptr_move_fw(ring, next_to_clean);
return 0;
}
u64_stats_update_begin(&ring->syncp);
ring->stats.seg_pkt_cnt++;
u64_stats_update_end(&ring->syncp);
ring->pull_len = eth_get_headlen(va, HNS3_RX_HEAD_SIZE);
__skb_put(skb, ring->pull_len);
hns3_nic_reuse_page(skb, ring->frag_num++, ring, ring->pull_len,
desc_cb);
ring_ptr_move_fw(ring, next_to_clean);
return HNS3_NEED_ADD_FRAG;
}
static int hns3_add_frag(struct hns3_enet_ring *ring, struct hns3_desc *desc,
struct sk_buff **out_skb, bool pending)
{
struct sk_buff *skb = *out_skb;
struct sk_buff *head_skb = *out_skb;
struct sk_buff *new_skb;
struct hns3_desc_cb *desc_cb;
struct hns3_desc *pre_desc;
u32 bd_base_info;
int pre_bd;
/* if there is pending bd, the SW param next_to_clean has moved
* to next and the next is NULL
*/
if (pending) {
pre_bd = (ring->next_to_clean - 1 + ring->desc_num) %
ring->desc_num;
pre_desc = &ring->desc[pre_bd];
bd_base_info = le32_to_cpu(pre_desc->rx.bd_base_info);
} else {
bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
}
while (!hnae3_get_bit(bd_base_info, HNS3_RXD_FE_B)) {
desc = &ring->desc[ring->next_to_clean];
desc_cb = &ring->desc_cb[ring->next_to_clean];
bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
if (!hnae3_get_bit(bd_base_info, HNS3_RXD_VLD_B))
return -ENXIO;
if (unlikely(ring->frag_num >= MAX_SKB_FRAGS)) {
new_skb = napi_alloc_skb(&ring->tqp_vector->napi,
HNS3_RX_HEAD_SIZE);
if (unlikely(!new_skb)) {
netdev_err(ring->tqp->handle->kinfo.netdev,
"alloc rx skb frag fail\n");
return -ENXIO;
}
ring->frag_num = 0;
if (ring->tail_skb) {
ring->tail_skb->next = new_skb;
ring->tail_skb = new_skb;
} else {
skb_shinfo(skb)->frag_list = new_skb;
ring->tail_skb = new_skb;
}
}
if (ring->tail_skb) {
head_skb->truesize += hnae3_buf_size(ring);
head_skb->data_len += le16_to_cpu(desc->rx.size);
head_skb->len += le16_to_cpu(desc->rx.size);
skb = ring->tail_skb;
}
hns3_nic_reuse_page(skb, ring->frag_num++, ring, 0, desc_cb);
ring_ptr_move_fw(ring, next_to_clean);
ring->pending_buf++;
}
return 0;
}
static void hns3_set_gro_param(struct sk_buff *skb, u32 l234info,
u32 bd_base_info)
{
u16 gro_count;
u32 l3_type;
gro_count = hnae3_get_field(l234info, HNS3_RXD_GRO_COUNT_M,
HNS3_RXD_GRO_COUNT_S);
/* if there is no HW GRO, do not set gro params */
if (!gro_count)
return;
/* tcp_gro_complete() will copy NAPI_GRO_CB(skb)->count
* to skb_shinfo(skb)->gso_segs
*/
NAPI_GRO_CB(skb)->count = gro_count;
l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M,
HNS3_RXD_L3ID_S);
if (l3_type == HNS3_L3_TYPE_IPV4)
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
else if (l3_type == HNS3_L3_TYPE_IPV6)
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
else
return;
skb_shinfo(skb)->gso_size = hnae3_get_field(bd_base_info,
HNS3_RXD_GRO_SIZE_M,
HNS3_RXD_GRO_SIZE_S);
if (skb_shinfo(skb)->gso_size)
tcp_gro_complete(skb);
}
static void hns3_set_rx_skb_rss_type(struct hns3_enet_ring *ring, static void hns3_set_rx_skb_rss_type(struct hns3_enet_ring *ring,
struct sk_buff *skb) struct sk_buff *skb)
{ {
...@@ -2397,18 +2567,16 @@ static void hns3_set_rx_skb_rss_type(struct hns3_enet_ring *ring, ...@@ -2397,18 +2567,16 @@ static void hns3_set_rx_skb_rss_type(struct hns3_enet_ring *ring,
} }
static int hns3_handle_rx_bd(struct hns3_enet_ring *ring, static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
struct sk_buff **out_skb, int *out_bnum) struct sk_buff **out_skb)
{ {
struct net_device *netdev = ring->tqp->handle->kinfo.netdev; struct net_device *netdev = ring->tqp->handle->kinfo.netdev;
struct sk_buff *skb = ring->skb;
struct hns3_desc_cb *desc_cb; struct hns3_desc_cb *desc_cb;
struct hns3_desc *desc; struct hns3_desc *desc;
struct sk_buff *skb;
unsigned char *va;
u32 bd_base_info; u32 bd_base_info;
int pull_len;
u32 l234info; u32 l234info;
int length; int length;
int bnum; int ret;
desc = &ring->desc[ring->next_to_clean]; desc = &ring->desc[ring->next_to_clean];
desc_cb = &ring->desc_cb[ring->next_to_clean]; desc_cb = &ring->desc_cb[ring->next_to_clean];
...@@ -2420,9 +2588,10 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring, ...@@ -2420,9 +2588,10 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
/* Check valid BD */ /* Check valid BD */
if (unlikely(!hnae3_get_bit(bd_base_info, HNS3_RXD_VLD_B))) if (unlikely(!hnae3_get_bit(bd_base_info, HNS3_RXD_VLD_B)))
return -EFAULT; return -ENXIO;
va = (unsigned char *)desc_cb->buf + desc_cb->page_offset; if (!skb)
ring->va = (unsigned char *)desc_cb->buf + desc_cb->page_offset;
/* Prefetch first cache line of first page /* Prefetch first cache line of first page
* Idea is to cache few bytes of the header of the packet. Our L1 Cache * Idea is to cache few bytes of the header of the packet. Our L1 Cache
...@@ -2431,62 +2600,42 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring, ...@@ -2431,62 +2600,42 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
* lines. In such a case, single fetch would suffice to cache in the * lines. In such a case, single fetch would suffice to cache in the
* relevant part of the header. * relevant part of the header.
*/ */
prefetch(va); prefetch(ring->va);
#if L1_CACHE_BYTES < 128 #if L1_CACHE_BYTES < 128
prefetch(va + L1_CACHE_BYTES); prefetch(ring->va + L1_CACHE_BYTES);
#endif #endif
skb = *out_skb = napi_alloc_skb(&ring->tqp_vector->napi, if (!skb) {
HNS3_RX_HEAD_SIZE); ret = hns3_alloc_skb(ring, length, ring->va);
if (unlikely(!skb)) { *out_skb = skb = ring->skb;
netdev_err(netdev, "alloc rx skb fail\n");
u64_stats_update_begin(&ring->syncp);
ring->stats.sw_err_cnt++;
u64_stats_update_end(&ring->syncp);
return -ENOMEM;
}
prefetchw(skb->data);
bnum = 1;
if (length <= HNS3_RX_HEAD_SIZE) {
memcpy(__skb_put(skb, length), va, ALIGN(length, sizeof(long)));
/* We can reuse buffer as-is, just make sure it is local */ if (ret < 0) /* alloc buffer fail */
if (likely(page_to_nid(desc_cb->priv) == numa_node_id())) return ret;
desc_cb->reuse_flag = 1; if (ret > 0) { /* need add frag */
else /* This page cannot be reused so discard it */ ret = hns3_add_frag(ring, desc, &skb, false);
put_page(desc_cb->priv); if (ret)
return ret;
ring_ptr_move_fw(ring, next_to_clean); /* As the head data may be changed when GRO enable, copy
* the head data in after other data rx completed
*/
memcpy(skb->data, ring->va,
ALIGN(ring->pull_len, sizeof(long)));
}
} else { } else {
u64_stats_update_begin(&ring->syncp); ret = hns3_add_frag(ring, desc, &skb, true);
ring->stats.seg_pkt_cnt++; if (ret)
u64_stats_update_end(&ring->syncp); return ret;
pull_len = eth_get_headlen(va, HNS3_RX_HEAD_SIZE);
memcpy(__skb_put(skb, pull_len), va,
ALIGN(pull_len, sizeof(long)));
hns3_nic_reuse_page(skb, 0, ring, pull_len, desc_cb);
ring_ptr_move_fw(ring, next_to_clean);
while (!hnae3_get_bit(bd_base_info, HNS3_RXD_FE_B)) { /* As the head data may be changed when GRO enable, copy
desc = &ring->desc[ring->next_to_clean]; * the head data in after other data rx completed
desc_cb = &ring->desc_cb[ring->next_to_clean]; */
bd_base_info = le32_to_cpu(desc->rx.bd_base_info); memcpy(skb->data, ring->va,
hns3_nic_reuse_page(skb, bnum, ring, 0, desc_cb); ALIGN(ring->pull_len, sizeof(long)));
ring_ptr_move_fw(ring, next_to_clean);
bnum++;
}
} }
*out_bnum = bnum;
l234info = le32_to_cpu(desc->rx.l234_info); l234info = le32_to_cpu(desc->rx.l234_info);
bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
/* Based on hw strategy, the tag offloaded will be stored at /* Based on hw strategy, the tag offloaded will be stored at
* ot_vlan_tag in two layer tag case, and stored at vlan_tag * ot_vlan_tag in two layer tag case, and stored at vlan_tag
...@@ -2536,7 +2685,11 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring, ...@@ -2536,7 +2685,11 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
ring->tqp_vector->rx_group.total_bytes += skb->len; ring->tqp_vector->rx_group.total_bytes += skb->len;
/* This is needed in order to enable forwarding support */
hns3_set_gro_param(skb, l234info, bd_base_info);
hns3_rx_checksum(ring, skb, desc); hns3_rx_checksum(ring, skb, desc);
*out_skb = skb;
hns3_set_rx_skb_rss_type(ring, skb); hns3_set_rx_skb_rss_type(ring, skb);
return 0; return 0;
...@@ -2549,9 +2702,9 @@ int hns3_clean_rx_ring( ...@@ -2549,9 +2702,9 @@ int hns3_clean_rx_ring(
#define RCB_NOF_ALLOC_RX_BUFF_ONCE 16 #define RCB_NOF_ALLOC_RX_BUFF_ONCE 16
struct net_device *netdev = ring->tqp->handle->kinfo.netdev; struct net_device *netdev = ring->tqp->handle->kinfo.netdev;
int recv_pkts, recv_bds, clean_count, err; int recv_pkts, recv_bds, clean_count, err;
int unused_count = hns3_desc_unused(ring); int unused_count = hns3_desc_unused(ring) - ring->pending_buf;
struct sk_buff *skb = NULL; struct sk_buff *skb = ring->skb;
int num, bnum = 0; int num;
num = readl_relaxed(ring->tqp->io_base + HNS3_RING_RX_RING_FBDNUM_REG); num = readl_relaxed(ring->tqp->io_base + HNS3_RING_RX_RING_FBDNUM_REG);
rmb(); /* Make sure num taken effect before the other data is touched */ rmb(); /* Make sure num taken effect before the other data is touched */
...@@ -2565,24 +2718,32 @@ int hns3_clean_rx_ring( ...@@ -2565,24 +2718,32 @@ int hns3_clean_rx_ring(
hns3_nic_alloc_rx_buffers(ring, hns3_nic_alloc_rx_buffers(ring,
clean_count + unused_count); clean_count + unused_count);
clean_count = 0; clean_count = 0;
unused_count = hns3_desc_unused(ring); unused_count = hns3_desc_unused(ring) -
ring->pending_buf;
} }
/* Poll one pkt */ /* Poll one pkt */
err = hns3_handle_rx_bd(ring, &skb, &bnum); err = hns3_handle_rx_bd(ring, &skb);
if (unlikely(!skb)) /* This fault cannot be repaired */ if (unlikely(!skb)) /* This fault cannot be repaired */
goto out; goto out;
recv_bds += bnum; if (err == -ENXIO) { /* Do not get FE for the packet */
clean_count += bnum; goto out;
if (unlikely(err)) { /* Do jump the err */ } else if (unlikely(err)) { /* Do jump the err */
recv_pkts++; recv_bds += ring->pending_buf;
clean_count += ring->pending_buf;
ring->skb = NULL;
ring->pending_buf = 0;
continue; continue;
} }
/* Do update ip stack process */ /* Do update ip stack process */
skb->protocol = eth_type_trans(skb, netdev); skb->protocol = eth_type_trans(skb, netdev);
rx_fn(ring, skb); rx_fn(ring, skb);
recv_bds += ring->pending_buf;
clean_count += ring->pending_buf;
ring->skb = NULL;
ring->pending_buf = 0;
recv_pkts++; recv_pkts++;
} }
......
...@@ -109,6 +109,10 @@ enum hns3_nic_state { ...@@ -109,6 +109,10 @@ enum hns3_nic_state {
#define HNS3_RXD_DOI_B 21 #define HNS3_RXD_DOI_B 21
#define HNS3_RXD_OL3E_B 22 #define HNS3_RXD_OL3E_B 22
#define HNS3_RXD_OL4E_B 23 #define HNS3_RXD_OL4E_B 23
#define HNS3_RXD_GRO_COUNT_S 24
#define HNS3_RXD_GRO_COUNT_M (0x3f << HNS3_RXD_GRO_COUNT_S)
#define HNS3_RXD_GRO_FIXID_B 30
#define HNS3_RXD_GRO_ECN_B 31
#define HNS3_RXD_ODMAC_S 0 #define HNS3_RXD_ODMAC_S 0
#define HNS3_RXD_ODMAC_M (0x3 << HNS3_RXD_ODMAC_S) #define HNS3_RXD_ODMAC_M (0x3 << HNS3_RXD_ODMAC_S)
...@@ -135,9 +139,8 @@ enum hns3_nic_state { ...@@ -135,9 +139,8 @@ enum hns3_nic_state {
#define HNS3_RXD_TSIND_S 12 #define HNS3_RXD_TSIND_S 12
#define HNS3_RXD_TSIND_M (0x7 << HNS3_RXD_TSIND_S) #define HNS3_RXD_TSIND_M (0x7 << HNS3_RXD_TSIND_S)
#define HNS3_RXD_LKBK_B 15 #define HNS3_RXD_LKBK_B 15
#define HNS3_RXD_HDL_S 16 #define HNS3_RXD_GRO_SIZE_S 16
#define HNS3_RXD_HDL_M (0x7ff << HNS3_RXD_HDL_S) #define HNS3_RXD_GRO_SIZE_M (0x3ff << HNS3_RXD_GRO_SIZE_S)
#define HNS3_RXD_HSIND_B 31
#define HNS3_TXD_L3T_S 0 #define HNS3_TXD_L3T_S 0
#define HNS3_TXD_L3T_M (0x3 << HNS3_TXD_L3T_S) #define HNS3_TXD_L3T_M (0x3 << HNS3_TXD_L3T_S)
...@@ -401,11 +404,19 @@ struct hns3_enet_ring { ...@@ -401,11 +404,19 @@ struct hns3_enet_ring {
*/ */
int next_to_clean; int next_to_clean;
int pull_len; /* head length for current packet */
u32 frag_num;
unsigned char *va; /* first buffer address for current packet */
u32 flag; /* ring attribute */ u32 flag; /* ring attribute */
int irq_init_flag; int irq_init_flag;
int numa_node; int numa_node;
cpumask_t affinity_mask; cpumask_t affinity_mask;
int pending_buf;
struct sk_buff *skb;
struct sk_buff *tail_skb;
}; };
struct hns_queue; struct hns_queue;
......
...@@ -152,6 +152,7 @@ enum hclge_opcode_type { ...@@ -152,6 +152,7 @@ enum hclge_opcode_type {
/* TSO command */ /* TSO command */
HCLGE_OPC_TSO_GENERIC_CONFIG = 0x0C01, HCLGE_OPC_TSO_GENERIC_CONFIG = 0x0C01,
HCLGE_OPC_GRO_GENERIC_CONFIG = 0x0C10,
/* RSS commands */ /* RSS commands */
HCLGE_OPC_RSS_GENERIC_CONFIG = 0x0D01, HCLGE_OPC_RSS_GENERIC_CONFIG = 0x0D01,
...@@ -758,6 +759,12 @@ struct hclge_cfg_tso_status_cmd { ...@@ -758,6 +759,12 @@ struct hclge_cfg_tso_status_cmd {
u8 rsv[20]; u8 rsv[20];
}; };
#define HCLGE_GRO_EN_B 0
struct hclge_cfg_gro_status_cmd {
__le16 gro_en;
u8 rsv[22];
};
#define HCLGE_TSO_MSS_MIN 256 #define HCLGE_TSO_MSS_MIN 256
#define HCLGE_TSO_MSS_MAX 9668 #define HCLGE_TSO_MSS_MAX 9668
......
...@@ -921,6 +921,28 @@ static int hclge_config_tso(struct hclge_dev *hdev, int tso_mss_min, ...@@ -921,6 +921,28 @@ static int hclge_config_tso(struct hclge_dev *hdev, int tso_mss_min,
return hclge_cmd_send(&hdev->hw, &desc, 1); return hclge_cmd_send(&hdev->hw, &desc, 1);
} }
static int hclge_config_gro(struct hclge_dev *hdev, bool en)
{
struct hclge_cfg_gro_status_cmd *req;
struct hclge_desc desc;
int ret;
if (!hnae3_dev_gro_supported(hdev))
return 0;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_GRO_GENERIC_CONFIG, false);
req = (struct hclge_cfg_gro_status_cmd *)desc.data;
req->gro_en = cpu_to_le16(en ? 1 : 0);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret)
dev_err(&hdev->pdev->dev,
"GRO hardware config cmd failed, ret = %d\n", ret);
return ret;
}
static int hclge_alloc_tqps(struct hclge_dev *hdev) static int hclge_alloc_tqps(struct hclge_dev *hdev)
{ {
struct hclge_tqp *tqp; struct hclge_tqp *tqp;
...@@ -7090,6 +7112,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) ...@@ -7090,6 +7112,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
goto err_mdiobus_unreg; goto err_mdiobus_unreg;
} }
ret = hclge_config_gro(hdev, true);
if (ret)
goto err_mdiobus_unreg;
ret = hclge_init_vlan_config(hdev); ret = hclge_init_vlan_config(hdev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "VLAN init fail, ret =%d\n", ret); dev_err(&pdev->dev, "VLAN init fail, ret =%d\n", ret);
...@@ -7221,6 +7247,10 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev) ...@@ -7221,6 +7247,10 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev)
return ret; return ret;
} }
ret = hclge_config_gro(hdev, true);
if (ret)
return ret;
ret = hclge_init_vlan_config(hdev); ret = hclge_init_vlan_config(hdev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "VLAN init fail, ret =%d\n", ret); dev_err(&pdev->dev, "VLAN init fail, ret =%d\n", ret);
...@@ -7637,6 +7667,14 @@ static void hclge_get_link_mode(struct hnae3_handle *handle, ...@@ -7637,6 +7667,14 @@ static void hclge_get_link_mode(struct hnae3_handle *handle,
} }
} }
static int hclge_gro_en(struct hnae3_handle *handle, int enable)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
return hclge_config_gro(hdev, enable);
}
static const struct hnae3_ae_ops hclge_ops = { static const struct hnae3_ae_ops hclge_ops = {
.init_ae_dev = hclge_init_ae_dev, .init_ae_dev = hclge_init_ae_dev,
.uninit_ae_dev = hclge_uninit_ae_dev, .uninit_ae_dev = hclge_uninit_ae_dev,
...@@ -7708,6 +7746,7 @@ static const struct hnae3_ae_ops hclge_ops = { ...@@ -7708,6 +7746,7 @@ static const struct hnae3_ae_ops hclge_ops = {
.get_hw_reset_stat = hclge_get_hw_reset_stat, .get_hw_reset_stat = hclge_get_hw_reset_stat,
.ae_dev_resetting = hclge_ae_dev_resetting, .ae_dev_resetting = hclge_ae_dev_resetting,
.ae_dev_reset_cnt = hclge_ae_dev_reset_cnt, .ae_dev_reset_cnt = hclge_ae_dev_reset_cnt,
.set_gro_en = hclge_gro_en,
}; };
static struct hnae3_ae_algo ae_algo = { static struct hnae3_ae_algo ae_algo = {
......
...@@ -87,6 +87,8 @@ enum hclgevf_opcode_type { ...@@ -87,6 +87,8 @@ enum hclgevf_opcode_type {
HCLGEVF_OPC_QUERY_TX_STATUS = 0x0B03, HCLGEVF_OPC_QUERY_TX_STATUS = 0x0B03,
HCLGEVF_OPC_QUERY_RX_STATUS = 0x0B13, HCLGEVF_OPC_QUERY_RX_STATUS = 0x0B13,
HCLGEVF_OPC_CFG_COM_TQP_QUEUE = 0x0B20, HCLGEVF_OPC_CFG_COM_TQP_QUEUE = 0x0B20,
/* GRO command */
HCLGEVF_OPC_GRO_GENERIC_CONFIG = 0x0C10,
/* RSS cmd */ /* RSS cmd */
HCLGEVF_OPC_RSS_GENERIC_CONFIG = 0x0D01, HCLGEVF_OPC_RSS_GENERIC_CONFIG = 0x0D01,
HCLGEVF_OPC_RSS_INPUT_TUPLE = 0x0D02, HCLGEVF_OPC_RSS_INPUT_TUPLE = 0x0D02,
...@@ -149,6 +151,12 @@ struct hclgevf_query_res_cmd { ...@@ -149,6 +151,12 @@ struct hclgevf_query_res_cmd {
__le16 rsv[7]; __le16 rsv[7];
}; };
#define HCLGEVF_GRO_EN_B 0
struct hclgevf_cfg_gro_status_cmd {
__le16 gro_en;
u8 rsv[22];
};
#define HCLGEVF_RSS_DEFAULT_OUTPORT_B 4 #define HCLGEVF_RSS_DEFAULT_OUTPORT_B 4
#define HCLGEVF_RSS_HASH_KEY_OFFSET_B 4 #define HCLGEVF_RSS_HASH_KEY_OFFSET_B 4
#define HCLGEVF_RSS_HASH_KEY_NUM 16 #define HCLGEVF_RSS_HASH_KEY_NUM 16
......
...@@ -1655,6 +1655,29 @@ static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev) ...@@ -1655,6 +1655,29 @@ static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev)
return 0; return 0;
} }
static int hclgevf_config_gro(struct hclgevf_dev *hdev, bool en)
{
struct hclgevf_cfg_gro_status_cmd *req;
struct hclgevf_desc desc;
int ret;
if (!hnae3_dev_gro_supported(hdev))
return 0;
hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_GRO_GENERIC_CONFIG,
false);
req = (struct hclgevf_cfg_gro_status_cmd *)desc.data;
req->gro_en = cpu_to_le16(en ? 1 : 0);
ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
if (ret)
dev_err(&hdev->pdev->dev,
"VF GRO hardware config cmd failed, ret = %d.\n", ret);
return ret;
}
static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev)
{ {
struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
...@@ -2122,6 +2145,10 @@ static int hclgevf_reset_hdev(struct hclgevf_dev *hdev) ...@@ -2122,6 +2145,10 @@ static int hclgevf_reset_hdev(struct hclgevf_dev *hdev)
return ret; return ret;
} }
ret = hclgevf_config_gro(hdev, true);
if (ret)
return ret;
ret = hclgevf_init_vlan_config(hdev); ret = hclgevf_init_vlan_config(hdev);
if (ret) { if (ret) {
dev_err(&hdev->pdev->dev, dev_err(&hdev->pdev->dev,
...@@ -2199,6 +2226,10 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) ...@@ -2199,6 +2226,10 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
goto err_config; goto err_config;
} }
ret = hclgevf_config_gro(hdev, true);
if (ret)
goto err_config;
/* Initialize RSS for this VF */ /* Initialize RSS for this VF */
ret = hclgevf_rss_init_hw(hdev); ret = hclgevf_rss_init_hw(hdev);
if (ret) { if (ret) {
...@@ -2337,6 +2368,13 @@ void hclgevf_update_speed_duplex(struct hclgevf_dev *hdev, u32 speed, ...@@ -2337,6 +2368,13 @@ void hclgevf_update_speed_duplex(struct hclgevf_dev *hdev, u32 speed,
hdev->hw.mac.duplex = duplex; hdev->hw.mac.duplex = duplex;
} }
static int hclgevf_gro_en(struct hnae3_handle *handle, int enable)
{
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
return hclgevf_config_gro(hdev, enable);
}
static void hclgevf_get_media_type(struct hnae3_handle *handle, static void hclgevf_get_media_type(struct hnae3_handle *handle,
u8 *media_type) u8 *media_type)
{ {
...@@ -2411,6 +2449,7 @@ static const struct hnae3_ae_ops hclgevf_ops = { ...@@ -2411,6 +2449,7 @@ static const struct hnae3_ae_ops hclgevf_ops = {
.get_hw_reset_stat = hclgevf_get_hw_reset_stat, .get_hw_reset_stat = hclgevf_get_hw_reset_stat,
.ae_dev_resetting = hclgevf_ae_dev_resetting, .ae_dev_resetting = hclgevf_ae_dev_resetting,
.ae_dev_reset_cnt = hclgevf_ae_dev_reset_cnt, .ae_dev_reset_cnt = hclgevf_ae_dev_reset_cnt,
.set_gro_en = hclgevf_gro_en,
}; };
static struct hnae3_ae_algo ae_algovf = { static struct hnae3_ae_algo ae_algovf = {
......
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