18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci// Copyright (c) 2016-2017 Hisilicon Limited.
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
58c2ecf20Sopenharmony_ci#include <linux/etherdevice.h>
68c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
78c2ecf20Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
88c2ecf20Sopenharmony_ci#include <linux/cpu_rmap.h>
98c2ecf20Sopenharmony_ci#endif
108c2ecf20Sopenharmony_ci#include <linux/if_vlan.h>
118c2ecf20Sopenharmony_ci#include <linux/irq.h>
128c2ecf20Sopenharmony_ci#include <linux/ip.h>
138c2ecf20Sopenharmony_ci#include <linux/ipv6.h>
148c2ecf20Sopenharmony_ci#include <linux/module.h>
158c2ecf20Sopenharmony_ci#include <linux/pci.h>
168c2ecf20Sopenharmony_ci#include <linux/aer.h>
178c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
188c2ecf20Sopenharmony_ci#include <linux/sctp.h>
198c2ecf20Sopenharmony_ci#include <net/gre.h>
208c2ecf20Sopenharmony_ci#include <net/ip6_checksum.h>
218c2ecf20Sopenharmony_ci#include <net/pkt_cls.h>
228c2ecf20Sopenharmony_ci#include <net/tcp.h>
238c2ecf20Sopenharmony_ci#include <net/vxlan.h>
248c2ecf20Sopenharmony_ci#include <net/geneve.h>
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#include "hnae3.h"
278c2ecf20Sopenharmony_ci#include "hns3_enet.h"
288c2ecf20Sopenharmony_ci/* All hns3 tracepoints are defined by the include below, which
298c2ecf20Sopenharmony_ci * must be included exactly once across the whole kernel with
308c2ecf20Sopenharmony_ci * CREATE_TRACE_POINTS defined
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_ci#define CREATE_TRACE_POINTS
338c2ecf20Sopenharmony_ci#include "hns3_trace.h"
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define hns3_set_field(origin, shift, val)	((origin) |= ((val) << (shift)))
368c2ecf20Sopenharmony_ci#define hns3_tx_bd_count(S)	DIV_ROUND_UP(S, HNS3_MAX_BD_SIZE)
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define hns3_rl_err(fmt, ...)						\
398c2ecf20Sopenharmony_ci	do {								\
408c2ecf20Sopenharmony_ci		if (net_ratelimit())					\
418c2ecf20Sopenharmony_ci			netdev_err(fmt, ##__VA_ARGS__);			\
428c2ecf20Sopenharmony_ci	} while (0)
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic void hns3_clear_all_ring(struct hnae3_handle *h, bool force);
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic const char hns3_driver_name[] = "hns3";
478c2ecf20Sopenharmony_cistatic const char hns3_driver_string[] =
488c2ecf20Sopenharmony_ci			"Hisilicon Ethernet Network Driver for Hip08 Family";
498c2ecf20Sopenharmony_cistatic const char hns3_copyright[] = "Copyright (c) 2017 Huawei Corporation.";
508c2ecf20Sopenharmony_cistatic struct hnae3_client client;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic int debug = -1;
538c2ecf20Sopenharmony_cimodule_param(debug, int, 0);
548c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, " Network interface message level setting");
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#define DEFAULT_MSG_LEVEL (NETIF_MSG_PROBE | NETIF_MSG_LINK | \
578c2ecf20Sopenharmony_ci			   NETIF_MSG_IFDOWN | NETIF_MSG_IFUP)
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#define HNS3_INNER_VLAN_TAG	1
608c2ecf20Sopenharmony_ci#define HNS3_OUTER_VLAN_TAG	2
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#define HNS3_MIN_TX_LEN		33U
638c2ecf20Sopenharmony_ci#define HNS3_MIN_TUN_PKT_LEN	65U
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci/* hns3_pci_tbl - PCI Device ID Table
668c2ecf20Sopenharmony_ci *
678c2ecf20Sopenharmony_ci * Last entry must be all 0s
688c2ecf20Sopenharmony_ci *
698c2ecf20Sopenharmony_ci * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
708c2ecf20Sopenharmony_ci *   Class, Class Mask, private data (not used) }
718c2ecf20Sopenharmony_ci */
728c2ecf20Sopenharmony_cistatic const struct pci_device_id hns3_pci_tbl[] = {
738c2ecf20Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_GE), 0},
748c2ecf20Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE), 0},
758c2ecf20Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA),
768c2ecf20Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
778c2ecf20Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA_MACSEC),
788c2ecf20Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
798c2ecf20Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA),
808c2ecf20Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
818c2ecf20Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA_MACSEC),
828c2ecf20Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
838c2ecf20Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_MACSEC),
848c2ecf20Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
858c2ecf20Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_200G_RDMA),
868c2ecf20Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
878c2ecf20Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_VF), 0},
888c2ecf20Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_RDMA_DCB_PFC_VF),
898c2ecf20Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
908c2ecf20Sopenharmony_ci	/* required last entry */
918c2ecf20Sopenharmony_ci	{0, }
928c2ecf20Sopenharmony_ci};
938c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, hns3_pci_tbl);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic irqreturn_t hns3_irq_handle(int irq, void *vector)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector = vector;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	napi_schedule_irqoff(&tqp_vector->napi);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic void hns3_nic_uninit_irq(struct hns3_nic_priv *priv)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vectors;
1078c2ecf20Sopenharmony_ci	unsigned int i;
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
1108c2ecf20Sopenharmony_ci		tqp_vectors = &priv->tqp_vector[i];
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci		if (tqp_vectors->irq_init_flag != HNS3_VECTOR_INITED)
1138c2ecf20Sopenharmony_ci			continue;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci		/* clear the affinity mask */
1168c2ecf20Sopenharmony_ci		irq_set_affinity_hint(tqp_vectors->vector_irq, NULL);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci		/* release the irq resource */
1198c2ecf20Sopenharmony_ci		free_irq(tqp_vectors->vector_irq, tqp_vectors);
1208c2ecf20Sopenharmony_ci		tqp_vectors->irq_init_flag = HNS3_VECTOR_NOT_INITED;
1218c2ecf20Sopenharmony_ci	}
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistatic int hns3_nic_init_irq(struct hns3_nic_priv *priv)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vectors;
1278c2ecf20Sopenharmony_ci	int txrx_int_idx = 0;
1288c2ecf20Sopenharmony_ci	int rx_int_idx = 0;
1298c2ecf20Sopenharmony_ci	int tx_int_idx = 0;
1308c2ecf20Sopenharmony_ci	unsigned int i;
1318c2ecf20Sopenharmony_ci	int ret;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
1348c2ecf20Sopenharmony_ci		tqp_vectors = &priv->tqp_vector[i];
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci		if (tqp_vectors->irq_init_flag == HNS3_VECTOR_INITED)
1378c2ecf20Sopenharmony_ci			continue;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci		if (tqp_vectors->tx_group.ring && tqp_vectors->rx_group.ring) {
1408c2ecf20Sopenharmony_ci			snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN,
1418c2ecf20Sopenharmony_ci				 "%s-%s-%s-%d", hns3_driver_name,
1428c2ecf20Sopenharmony_ci				 pci_name(priv->ae_handle->pdev),
1438c2ecf20Sopenharmony_ci				 "TxRx", txrx_int_idx++);
1448c2ecf20Sopenharmony_ci			txrx_int_idx++;
1458c2ecf20Sopenharmony_ci		} else if (tqp_vectors->rx_group.ring) {
1468c2ecf20Sopenharmony_ci			snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN,
1478c2ecf20Sopenharmony_ci				 "%s-%s-%s-%d", hns3_driver_name,
1488c2ecf20Sopenharmony_ci				 pci_name(priv->ae_handle->pdev),
1498c2ecf20Sopenharmony_ci				 "Rx", rx_int_idx++);
1508c2ecf20Sopenharmony_ci		} else if (tqp_vectors->tx_group.ring) {
1518c2ecf20Sopenharmony_ci			snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN,
1528c2ecf20Sopenharmony_ci				 "%s-%s-%s-%d", hns3_driver_name,
1538c2ecf20Sopenharmony_ci				 pci_name(priv->ae_handle->pdev),
1548c2ecf20Sopenharmony_ci				 "Tx", tx_int_idx++);
1558c2ecf20Sopenharmony_ci		} else {
1568c2ecf20Sopenharmony_ci			/* Skip this unused q_vector */
1578c2ecf20Sopenharmony_ci			continue;
1588c2ecf20Sopenharmony_ci		}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci		tqp_vectors->name[HNAE3_INT_NAME_LEN - 1] = '\0';
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci		irq_set_status_flags(tqp_vectors->vector_irq, IRQ_NOAUTOEN);
1638c2ecf20Sopenharmony_ci		ret = request_irq(tqp_vectors->vector_irq, hns3_irq_handle, 0,
1648c2ecf20Sopenharmony_ci				  tqp_vectors->name, tqp_vectors);
1658c2ecf20Sopenharmony_ci		if (ret) {
1668c2ecf20Sopenharmony_ci			netdev_err(priv->netdev, "request irq(%d) fail\n",
1678c2ecf20Sopenharmony_ci				   tqp_vectors->vector_irq);
1688c2ecf20Sopenharmony_ci			hns3_nic_uninit_irq(priv);
1698c2ecf20Sopenharmony_ci			return ret;
1708c2ecf20Sopenharmony_ci		}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci		irq_set_affinity_hint(tqp_vectors->vector_irq,
1738c2ecf20Sopenharmony_ci				      &tqp_vectors->affinity_mask);
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci		tqp_vectors->irq_init_flag = HNS3_VECTOR_INITED;
1768c2ecf20Sopenharmony_ci	}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	return 0;
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cistatic void hns3_mask_vector_irq(struct hns3_enet_tqp_vector *tqp_vector,
1828c2ecf20Sopenharmony_ci				 u32 mask_en)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	writel(mask_en, tqp_vector->mask_addr);
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic void hns3_vector_enable(struct hns3_enet_tqp_vector *tqp_vector)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	napi_enable(&tqp_vector->napi);
1908c2ecf20Sopenharmony_ci	enable_irq(tqp_vector->vector_irq);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	/* enable vector */
1938c2ecf20Sopenharmony_ci	hns3_mask_vector_irq(tqp_vector, 1);
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cistatic void hns3_vector_disable(struct hns3_enet_tqp_vector *tqp_vector)
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	/* disable vector */
1998c2ecf20Sopenharmony_ci	hns3_mask_vector_irq(tqp_vector, 0);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	disable_irq(tqp_vector->vector_irq);
2028c2ecf20Sopenharmony_ci	napi_disable(&tqp_vector->napi);
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_civoid hns3_set_vector_coalesce_rl(struct hns3_enet_tqp_vector *tqp_vector,
2068c2ecf20Sopenharmony_ci				 u32 rl_value)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	u32 rl_reg = hns3_rl_usec_to_reg(rl_value);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	/* this defines the configuration for RL (Interrupt Rate Limiter).
2118c2ecf20Sopenharmony_ci	 * Rl defines rate of interrupts i.e. number of interrupts-per-second
2128c2ecf20Sopenharmony_ci	 * GL and RL(Rate Limiter) are 2 ways to acheive interrupt coalescing
2138c2ecf20Sopenharmony_ci	 */
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	if (rl_reg > 0 && !tqp_vector->tx_group.coal.gl_adapt_enable &&
2168c2ecf20Sopenharmony_ci	    !tqp_vector->rx_group.coal.gl_adapt_enable)
2178c2ecf20Sopenharmony_ci		/* According to the hardware, the range of rl_reg is
2188c2ecf20Sopenharmony_ci		 * 0-59 and the unit is 4.
2198c2ecf20Sopenharmony_ci		 */
2208c2ecf20Sopenharmony_ci		rl_reg |=  HNS3_INT_RL_ENABLE_MASK;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	writel(rl_reg, tqp_vector->mask_addr + HNS3_VECTOR_RL_OFFSET);
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_civoid hns3_set_vector_coalesce_rx_gl(struct hns3_enet_tqp_vector *tqp_vector,
2268c2ecf20Sopenharmony_ci				    u32 gl_value)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	u32 rx_gl_reg = hns3_gl_usec_to_reg(gl_value);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	writel(rx_gl_reg, tqp_vector->mask_addr + HNS3_VECTOR_GL0_OFFSET);
2318c2ecf20Sopenharmony_ci}
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_civoid hns3_set_vector_coalesce_tx_gl(struct hns3_enet_tqp_vector *tqp_vector,
2348c2ecf20Sopenharmony_ci				    u32 gl_value)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	u32 tx_gl_reg = hns3_gl_usec_to_reg(gl_value);
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	writel(tx_gl_reg, tqp_vector->mask_addr + HNS3_VECTOR_GL1_OFFSET);
2398c2ecf20Sopenharmony_ci}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_cistatic void hns3_vector_gl_rl_init(struct hns3_enet_tqp_vector *tqp_vector,
2428c2ecf20Sopenharmony_ci				   struct hns3_nic_priv *priv)
2438c2ecf20Sopenharmony_ci{
2448c2ecf20Sopenharmony_ci	/* initialize the configuration for interrupt coalescing.
2458c2ecf20Sopenharmony_ci	 * 1. GL (Interrupt Gap Limiter)
2468c2ecf20Sopenharmony_ci	 * 2. RL (Interrupt Rate Limiter)
2478c2ecf20Sopenharmony_ci	 *
2488c2ecf20Sopenharmony_ci	 * Default: enable interrupt coalescing self-adaptive and GL
2498c2ecf20Sopenharmony_ci	 */
2508c2ecf20Sopenharmony_ci	tqp_vector->tx_group.coal.gl_adapt_enable = 1;
2518c2ecf20Sopenharmony_ci	tqp_vector->rx_group.coal.gl_adapt_enable = 1;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	tqp_vector->tx_group.coal.int_gl = HNS3_INT_GL_50K;
2548c2ecf20Sopenharmony_ci	tqp_vector->rx_group.coal.int_gl = HNS3_INT_GL_50K;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	tqp_vector->rx_group.coal.flow_level = HNS3_FLOW_LOW;
2578c2ecf20Sopenharmony_ci	tqp_vector->tx_group.coal.flow_level = HNS3_FLOW_LOW;
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cistatic void hns3_vector_gl_rl_init_hw(struct hns3_enet_tqp_vector *tqp_vector,
2618c2ecf20Sopenharmony_ci				      struct hns3_nic_priv *priv)
2628c2ecf20Sopenharmony_ci{
2638c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	hns3_set_vector_coalesce_tx_gl(tqp_vector,
2668c2ecf20Sopenharmony_ci				       tqp_vector->tx_group.coal.int_gl);
2678c2ecf20Sopenharmony_ci	hns3_set_vector_coalesce_rx_gl(tqp_vector,
2688c2ecf20Sopenharmony_ci				       tqp_vector->rx_group.coal.int_gl);
2698c2ecf20Sopenharmony_ci	hns3_set_vector_coalesce_rl(tqp_vector, h->kinfo.int_rl_setting);
2708c2ecf20Sopenharmony_ci}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_cistatic int hns3_nic_set_real_num_queue(struct net_device *netdev)
2738c2ecf20Sopenharmony_ci{
2748c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
2758c2ecf20Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &h->kinfo;
2768c2ecf20Sopenharmony_ci	unsigned int queue_size = kinfo->rss_size * kinfo->num_tc;
2778c2ecf20Sopenharmony_ci	int i, ret;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	if (kinfo->num_tc <= 1) {
2808c2ecf20Sopenharmony_ci		netdev_reset_tc(netdev);
2818c2ecf20Sopenharmony_ci	} else {
2828c2ecf20Sopenharmony_ci		ret = netdev_set_num_tc(netdev, kinfo->num_tc);
2838c2ecf20Sopenharmony_ci		if (ret) {
2848c2ecf20Sopenharmony_ci			netdev_err(netdev,
2858c2ecf20Sopenharmony_ci				   "netdev_set_num_tc fail, ret=%d!\n", ret);
2868c2ecf20Sopenharmony_ci			return ret;
2878c2ecf20Sopenharmony_ci		}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci		for (i = 0; i < HNAE3_MAX_TC; i++) {
2908c2ecf20Sopenharmony_ci			if (!kinfo->tc_info[i].enable)
2918c2ecf20Sopenharmony_ci				continue;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci			netdev_set_tc_queue(netdev,
2948c2ecf20Sopenharmony_ci					    kinfo->tc_info[i].tc,
2958c2ecf20Sopenharmony_ci					    kinfo->tc_info[i].tqp_count,
2968c2ecf20Sopenharmony_ci					    kinfo->tc_info[i].tqp_offset);
2978c2ecf20Sopenharmony_ci		}
2988c2ecf20Sopenharmony_ci	}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	ret = netif_set_real_num_tx_queues(netdev, queue_size);
3018c2ecf20Sopenharmony_ci	if (ret) {
3028c2ecf20Sopenharmony_ci		netdev_err(netdev,
3038c2ecf20Sopenharmony_ci			   "netif_set_real_num_tx_queues fail, ret=%d!\n", ret);
3048c2ecf20Sopenharmony_ci		return ret;
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	ret = netif_set_real_num_rx_queues(netdev, queue_size);
3088c2ecf20Sopenharmony_ci	if (ret) {
3098c2ecf20Sopenharmony_ci		netdev_err(netdev,
3108c2ecf20Sopenharmony_ci			   "netif_set_real_num_rx_queues fail, ret=%d!\n", ret);
3118c2ecf20Sopenharmony_ci		return ret;
3128c2ecf20Sopenharmony_ci	}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	return 0;
3158c2ecf20Sopenharmony_ci}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic u16 hns3_get_max_available_channels(struct hnae3_handle *h)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	u16 alloc_tqps, max_rss_size, rss_size;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	h->ae_algo->ops->get_tqps_and_rss_info(h, &alloc_tqps, &max_rss_size);
3228c2ecf20Sopenharmony_ci	rss_size = alloc_tqps / h->kinfo.num_tc;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	return min_t(u16, rss_size, max_rss_size);
3258c2ecf20Sopenharmony_ci}
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_cistatic void hns3_tqp_enable(struct hnae3_queue *tqp)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	u32 rcb_reg;
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	rcb_reg = hns3_read_dev(tqp, HNS3_RING_EN_REG);
3328c2ecf20Sopenharmony_ci	rcb_reg |= BIT(HNS3_RING_EN_B);
3338c2ecf20Sopenharmony_ci	hns3_write_dev(tqp, HNS3_RING_EN_REG, rcb_reg);
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_cistatic void hns3_tqp_disable(struct hnae3_queue *tqp)
3378c2ecf20Sopenharmony_ci{
3388c2ecf20Sopenharmony_ci	u32 rcb_reg;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	rcb_reg = hns3_read_dev(tqp, HNS3_RING_EN_REG);
3418c2ecf20Sopenharmony_ci	rcb_reg &= ~BIT(HNS3_RING_EN_B);
3428c2ecf20Sopenharmony_ci	hns3_write_dev(tqp, HNS3_RING_EN_REG, rcb_reg);
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic void hns3_free_rx_cpu_rmap(struct net_device *netdev)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
3488c2ecf20Sopenharmony_ci	free_irq_cpu_rmap(netdev->rx_cpu_rmap);
3498c2ecf20Sopenharmony_ci	netdev->rx_cpu_rmap = NULL;
3508c2ecf20Sopenharmony_ci#endif
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_cistatic int hns3_set_rx_cpu_rmap(struct net_device *netdev)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
3568c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
3578c2ecf20Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector;
3588c2ecf20Sopenharmony_ci	int i, ret;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	if (!netdev->rx_cpu_rmap) {
3618c2ecf20Sopenharmony_ci		netdev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->vector_num);
3628c2ecf20Sopenharmony_ci		if (!netdev->rx_cpu_rmap)
3638c2ecf20Sopenharmony_ci			return -ENOMEM;
3648c2ecf20Sopenharmony_ci	}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
3678c2ecf20Sopenharmony_ci		tqp_vector = &priv->tqp_vector[i];
3688c2ecf20Sopenharmony_ci		ret = irq_cpu_rmap_add(netdev->rx_cpu_rmap,
3698c2ecf20Sopenharmony_ci				       tqp_vector->vector_irq);
3708c2ecf20Sopenharmony_ci		if (ret) {
3718c2ecf20Sopenharmony_ci			hns3_free_rx_cpu_rmap(netdev);
3728c2ecf20Sopenharmony_ci			return ret;
3738c2ecf20Sopenharmony_ci		}
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci#endif
3768c2ecf20Sopenharmony_ci	return 0;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistatic int hns3_nic_net_up(struct net_device *netdev)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
3828c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
3838c2ecf20Sopenharmony_ci	int i, j;
3848c2ecf20Sopenharmony_ci	int ret;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	ret = hns3_nic_reset_all_ring(h);
3878c2ecf20Sopenharmony_ci	if (ret)
3888c2ecf20Sopenharmony_ci		return ret;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	clear_bit(HNS3_NIC_STATE_DOWN, &priv->state);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	/* enable the vectors */
3938c2ecf20Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++)
3948c2ecf20Sopenharmony_ci		hns3_vector_enable(&priv->tqp_vector[i]);
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	/* enable rcb */
3978c2ecf20Sopenharmony_ci	for (j = 0; j < h->kinfo.num_tqps; j++)
3988c2ecf20Sopenharmony_ci		hns3_tqp_enable(h->kinfo.tqp[j]);
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	/* start the ae_dev */
4018c2ecf20Sopenharmony_ci	ret = h->ae_algo->ops->start ? h->ae_algo->ops->start(h) : 0;
4028c2ecf20Sopenharmony_ci	if (ret) {
4038c2ecf20Sopenharmony_ci		set_bit(HNS3_NIC_STATE_DOWN, &priv->state);
4048c2ecf20Sopenharmony_ci		while (j--)
4058c2ecf20Sopenharmony_ci			hns3_tqp_disable(h->kinfo.tqp[j]);
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci		for (j = i - 1; j >= 0; j--)
4088c2ecf20Sopenharmony_ci			hns3_vector_disable(&priv->tqp_vector[j]);
4098c2ecf20Sopenharmony_ci	}
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	return ret;
4128c2ecf20Sopenharmony_ci}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cistatic void hns3_config_xps(struct hns3_nic_priv *priv)
4158c2ecf20Sopenharmony_ci{
4168c2ecf20Sopenharmony_ci	int i;
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
4198c2ecf20Sopenharmony_ci		struct hns3_enet_tqp_vector *tqp_vector = &priv->tqp_vector[i];
4208c2ecf20Sopenharmony_ci		struct hns3_enet_ring *ring = tqp_vector->tx_group.ring;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci		while (ring) {
4238c2ecf20Sopenharmony_ci			int ret;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci			ret = netif_set_xps_queue(priv->netdev,
4268c2ecf20Sopenharmony_ci						  &tqp_vector->affinity_mask,
4278c2ecf20Sopenharmony_ci						  ring->tqp->tqp_index);
4288c2ecf20Sopenharmony_ci			if (ret)
4298c2ecf20Sopenharmony_ci				netdev_warn(priv->netdev,
4308c2ecf20Sopenharmony_ci					    "set xps queue failed: %d", ret);
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci			ring = ring->next;
4338c2ecf20Sopenharmony_ci		}
4348c2ecf20Sopenharmony_ci	}
4358c2ecf20Sopenharmony_ci}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_cistatic int hns3_nic_net_open(struct net_device *netdev)
4388c2ecf20Sopenharmony_ci{
4398c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
4408c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
4418c2ecf20Sopenharmony_ci	struct hnae3_knic_private_info *kinfo;
4428c2ecf20Sopenharmony_ci	int i, ret;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	if (hns3_nic_resetting(netdev))
4458c2ecf20Sopenharmony_ci		return -EBUSY;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) {
4488c2ecf20Sopenharmony_ci		netdev_warn(netdev, "net open repeatedly!\n");
4498c2ecf20Sopenharmony_ci		return 0;
4508c2ecf20Sopenharmony_ci	}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	netif_carrier_off(netdev);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	ret = hns3_nic_set_real_num_queue(netdev);
4558c2ecf20Sopenharmony_ci	if (ret)
4568c2ecf20Sopenharmony_ci		return ret;
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	ret = hns3_nic_net_up(netdev);
4598c2ecf20Sopenharmony_ci	if (ret) {
4608c2ecf20Sopenharmony_ci		netdev_err(netdev, "net up fail, ret=%d!\n", ret);
4618c2ecf20Sopenharmony_ci		return ret;
4628c2ecf20Sopenharmony_ci	}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	kinfo = &h->kinfo;
4658c2ecf20Sopenharmony_ci	for (i = 0; i < HNAE3_MAX_USER_PRIO; i++)
4668c2ecf20Sopenharmony_ci		netdev_set_prio_tc_map(netdev, i, kinfo->prio_tc[i]);
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->set_timer_task)
4698c2ecf20Sopenharmony_ci		h->ae_algo->ops->set_timer_task(priv->ae_handle, true);
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	hns3_config_xps(priv);
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	netif_dbg(h, drv, netdev, "net open\n");
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	return 0;
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_cistatic void hns3_reset_tx_queue(struct hnae3_handle *h)
4798c2ecf20Sopenharmony_ci{
4808c2ecf20Sopenharmony_ci	struct net_device *ndev = h->kinfo.netdev;
4818c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
4828c2ecf20Sopenharmony_ci	struct netdev_queue *dev_queue;
4838c2ecf20Sopenharmony_ci	u32 i;
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++) {
4868c2ecf20Sopenharmony_ci		dev_queue = netdev_get_tx_queue(ndev,
4878c2ecf20Sopenharmony_ci						priv->ring[i].queue_index);
4888c2ecf20Sopenharmony_ci		netdev_tx_reset_queue(dev_queue);
4898c2ecf20Sopenharmony_ci	}
4908c2ecf20Sopenharmony_ci}
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_cistatic void hns3_nic_net_down(struct net_device *netdev)
4938c2ecf20Sopenharmony_ci{
4948c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
4958c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
4968c2ecf20Sopenharmony_ci	const struct hnae3_ae_ops *ops;
4978c2ecf20Sopenharmony_ci	int i;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	/* disable vectors */
5008c2ecf20Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++)
5018c2ecf20Sopenharmony_ci		hns3_vector_disable(&priv->tqp_vector[i]);
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	/* disable rcb */
5048c2ecf20Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++)
5058c2ecf20Sopenharmony_ci		hns3_tqp_disable(h->kinfo.tqp[i]);
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	/* stop ae_dev */
5088c2ecf20Sopenharmony_ci	ops = priv->ae_handle->ae_algo->ops;
5098c2ecf20Sopenharmony_ci	if (ops->stop)
5108c2ecf20Sopenharmony_ci		ops->stop(priv->ae_handle);
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	/* delay ring buffer clearing to hns3_reset_notify_uninit_enet
5138c2ecf20Sopenharmony_ci	 * during reset process, because driver may not be able
5148c2ecf20Sopenharmony_ci	 * to disable the ring through firmware when downing the netdev.
5158c2ecf20Sopenharmony_ci	 */
5168c2ecf20Sopenharmony_ci	if (!hns3_nic_resetting(netdev))
5178c2ecf20Sopenharmony_ci		hns3_clear_all_ring(priv->ae_handle, false);
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	hns3_reset_tx_queue(priv->ae_handle);
5208c2ecf20Sopenharmony_ci}
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_cistatic int hns3_nic_net_stop(struct net_device *netdev)
5238c2ecf20Sopenharmony_ci{
5248c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
5258c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state))
5288c2ecf20Sopenharmony_ci		return 0;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	netif_dbg(h, drv, netdev, "net stop\n");
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->set_timer_task)
5338c2ecf20Sopenharmony_ci		h->ae_algo->ops->set_timer_task(priv->ae_handle, false);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	netif_carrier_off(netdev);
5368c2ecf20Sopenharmony_ci	netif_tx_disable(netdev);
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	hns3_nic_net_down(netdev);
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	return 0;
5418c2ecf20Sopenharmony_ci}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_cistatic int hns3_nic_uc_sync(struct net_device *netdev,
5448c2ecf20Sopenharmony_ci			    const unsigned char *addr)
5458c2ecf20Sopenharmony_ci{
5468c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->add_uc_addr)
5498c2ecf20Sopenharmony_ci		return h->ae_algo->ops->add_uc_addr(h, addr);
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	return 0;
5528c2ecf20Sopenharmony_ci}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_cistatic int hns3_nic_uc_unsync(struct net_device *netdev,
5558c2ecf20Sopenharmony_ci			      const unsigned char *addr)
5568c2ecf20Sopenharmony_ci{
5578c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci	/* need ignore the request of removing device address, because
5608c2ecf20Sopenharmony_ci	 * we store the device address and other addresses of uc list
5618c2ecf20Sopenharmony_ci	 * in the function's mac filter list.
5628c2ecf20Sopenharmony_ci	 */
5638c2ecf20Sopenharmony_ci	if (ether_addr_equal(addr, netdev->dev_addr))
5648c2ecf20Sopenharmony_ci		return 0;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->rm_uc_addr)
5678c2ecf20Sopenharmony_ci		return h->ae_algo->ops->rm_uc_addr(h, addr);
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	return 0;
5708c2ecf20Sopenharmony_ci}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_cistatic int hns3_nic_mc_sync(struct net_device *netdev,
5738c2ecf20Sopenharmony_ci			    const unsigned char *addr)
5748c2ecf20Sopenharmony_ci{
5758c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->add_mc_addr)
5788c2ecf20Sopenharmony_ci		return h->ae_algo->ops->add_mc_addr(h, addr);
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	return 0;
5818c2ecf20Sopenharmony_ci}
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_cistatic int hns3_nic_mc_unsync(struct net_device *netdev,
5848c2ecf20Sopenharmony_ci			      const unsigned char *addr)
5858c2ecf20Sopenharmony_ci{
5868c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->rm_mc_addr)
5898c2ecf20Sopenharmony_ci		return h->ae_algo->ops->rm_mc_addr(h, addr);
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	return 0;
5928c2ecf20Sopenharmony_ci}
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_cistatic u8 hns3_get_netdev_flags(struct net_device *netdev)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	u8 flags = 0;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	if (netdev->flags & IFF_PROMISC) {
5998c2ecf20Sopenharmony_ci		flags = HNAE3_USER_UPE | HNAE3_USER_MPE | HNAE3_BPE;
6008c2ecf20Sopenharmony_ci	} else {
6018c2ecf20Sopenharmony_ci		flags |= HNAE3_VLAN_FLTR;
6028c2ecf20Sopenharmony_ci		if (netdev->flags & IFF_ALLMULTI)
6038c2ecf20Sopenharmony_ci			flags |= HNAE3_USER_MPE;
6048c2ecf20Sopenharmony_ci	}
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	return flags;
6078c2ecf20Sopenharmony_ci}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_cistatic void hns3_nic_set_rx_mode(struct net_device *netdev)
6108c2ecf20Sopenharmony_ci{
6118c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
6128c2ecf20Sopenharmony_ci	u8 new_flags;
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	new_flags = hns3_get_netdev_flags(netdev);
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	__dev_uc_sync(netdev, hns3_nic_uc_sync, hns3_nic_uc_unsync);
6178c2ecf20Sopenharmony_ci	__dev_mc_sync(netdev, hns3_nic_mc_sync, hns3_nic_mc_unsync);
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	/* User mode Promisc mode enable and vlan filtering is disabled to
6208c2ecf20Sopenharmony_ci	 * let all packets in.
6218c2ecf20Sopenharmony_ci	 */
6228c2ecf20Sopenharmony_ci	h->netdev_flags = new_flags;
6238c2ecf20Sopenharmony_ci	hns3_request_update_promisc_mode(h);
6248c2ecf20Sopenharmony_ci}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_civoid hns3_request_update_promisc_mode(struct hnae3_handle *handle)
6278c2ecf20Sopenharmony_ci{
6288c2ecf20Sopenharmony_ci	const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	if (ops->request_update_promisc_mode)
6318c2ecf20Sopenharmony_ci		ops->request_update_promisc_mode(handle);
6328c2ecf20Sopenharmony_ci}
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_civoid hns3_enable_vlan_filter(struct net_device *netdev, bool enable)
6358c2ecf20Sopenharmony_ci{
6368c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
6378c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
6388c2ecf20Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev);
6398c2ecf20Sopenharmony_ci	bool last_state;
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2 &&
6428c2ecf20Sopenharmony_ci	    h->ae_algo->ops->enable_vlan_filter) {
6438c2ecf20Sopenharmony_ci		last_state = h->netdev_flags & HNAE3_VLAN_FLTR ? true : false;
6448c2ecf20Sopenharmony_ci		if (enable != last_state) {
6458c2ecf20Sopenharmony_ci			netdev_info(netdev,
6468c2ecf20Sopenharmony_ci				    "%s vlan filter\n",
6478c2ecf20Sopenharmony_ci				    enable ? "enable" : "disable");
6488c2ecf20Sopenharmony_ci			h->ae_algo->ops->enable_vlan_filter(h, enable);
6498c2ecf20Sopenharmony_ci		}
6508c2ecf20Sopenharmony_ci	}
6518c2ecf20Sopenharmony_ci}
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_cistatic int hns3_set_tso(struct sk_buff *skb, u32 *paylen,
6548c2ecf20Sopenharmony_ci			u16 *mss, u32 *type_cs_vlan_tso)
6558c2ecf20Sopenharmony_ci{
6568c2ecf20Sopenharmony_ci	u32 l4_offset, hdr_len;
6578c2ecf20Sopenharmony_ci	union l3_hdr_info l3;
6588c2ecf20Sopenharmony_ci	union l4_hdr_info l4;
6598c2ecf20Sopenharmony_ci	u32 l4_paylen;
6608c2ecf20Sopenharmony_ci	int ret;
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	if (!skb_is_gso(skb))
6638c2ecf20Sopenharmony_ci		return 0;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	ret = skb_cow_head(skb, 0);
6668c2ecf20Sopenharmony_ci	if (unlikely(ret < 0))
6678c2ecf20Sopenharmony_ci		return ret;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	l3.hdr = skb_network_header(skb);
6708c2ecf20Sopenharmony_ci	l4.hdr = skb_transport_header(skb);
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	/* Software should clear the IPv4's checksum field when tso is
6738c2ecf20Sopenharmony_ci	 * needed.
6748c2ecf20Sopenharmony_ci	 */
6758c2ecf20Sopenharmony_ci	if (l3.v4->version == 4)
6768c2ecf20Sopenharmony_ci		l3.v4->check = 0;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	/* tunnel packet */
6798c2ecf20Sopenharmony_ci	if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
6808c2ecf20Sopenharmony_ci					 SKB_GSO_GRE_CSUM |
6818c2ecf20Sopenharmony_ci					 SKB_GSO_UDP_TUNNEL |
6828c2ecf20Sopenharmony_ci					 SKB_GSO_UDP_TUNNEL_CSUM)) {
6838c2ecf20Sopenharmony_ci		if ((!(skb_shinfo(skb)->gso_type &
6848c2ecf20Sopenharmony_ci		    SKB_GSO_PARTIAL)) &&
6858c2ecf20Sopenharmony_ci		    (skb_shinfo(skb)->gso_type &
6868c2ecf20Sopenharmony_ci		    SKB_GSO_UDP_TUNNEL_CSUM)) {
6878c2ecf20Sopenharmony_ci			/* Software should clear the udp's checksum
6888c2ecf20Sopenharmony_ci			 * field when tso is needed.
6898c2ecf20Sopenharmony_ci			 */
6908c2ecf20Sopenharmony_ci			l4.udp->check = 0;
6918c2ecf20Sopenharmony_ci		}
6928c2ecf20Sopenharmony_ci		/* reset l3&l4 pointers from outer to inner headers */
6938c2ecf20Sopenharmony_ci		l3.hdr = skb_inner_network_header(skb);
6948c2ecf20Sopenharmony_ci		l4.hdr = skb_inner_transport_header(skb);
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci		/* Software should clear the IPv4's checksum field when
6978c2ecf20Sopenharmony_ci		 * tso is needed.
6988c2ecf20Sopenharmony_ci		 */
6998c2ecf20Sopenharmony_ci		if (l3.v4->version == 4)
7008c2ecf20Sopenharmony_ci			l3.v4->check = 0;
7018c2ecf20Sopenharmony_ci	}
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	/* normal or tunnel packet */
7048c2ecf20Sopenharmony_ci	l4_offset = l4.hdr - skb->data;
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	/* remove payload length from inner pseudo checksum when tso */
7078c2ecf20Sopenharmony_ci	l4_paylen = skb->len - l4_offset;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
7108c2ecf20Sopenharmony_ci		hdr_len = sizeof(*l4.udp) + l4_offset;
7118c2ecf20Sopenharmony_ci		csum_replace_by_diff(&l4.udp->check,
7128c2ecf20Sopenharmony_ci				     (__force __wsum)htonl(l4_paylen));
7138c2ecf20Sopenharmony_ci	} else {
7148c2ecf20Sopenharmony_ci		hdr_len = (l4.tcp->doff << 2) + l4_offset;
7158c2ecf20Sopenharmony_ci		csum_replace_by_diff(&l4.tcp->check,
7168c2ecf20Sopenharmony_ci				     (__force __wsum)htonl(l4_paylen));
7178c2ecf20Sopenharmony_ci	}
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	/* find the txbd field values */
7208c2ecf20Sopenharmony_ci	*paylen = skb->len - hdr_len;
7218c2ecf20Sopenharmony_ci	hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_TSO_B, 1);
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	/* get MSS for TSO */
7248c2ecf20Sopenharmony_ci	*mss = skb_shinfo(skb)->gso_size;
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	trace_hns3_tso(skb);
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	return 0;
7298c2ecf20Sopenharmony_ci}
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_cistatic int hns3_get_l4_protocol(struct sk_buff *skb, u8 *ol4_proto,
7328c2ecf20Sopenharmony_ci				u8 *il4_proto)
7338c2ecf20Sopenharmony_ci{
7348c2ecf20Sopenharmony_ci	union l3_hdr_info l3;
7358c2ecf20Sopenharmony_ci	unsigned char *l4_hdr;
7368c2ecf20Sopenharmony_ci	unsigned char *exthdr;
7378c2ecf20Sopenharmony_ci	u8 l4_proto_tmp;
7388c2ecf20Sopenharmony_ci	__be16 frag_off;
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	/* find outer header point */
7418c2ecf20Sopenharmony_ci	l3.hdr = skb_network_header(skb);
7428c2ecf20Sopenharmony_ci	l4_hdr = skb_transport_header(skb);
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	if (skb->protocol == htons(ETH_P_IPV6)) {
7458c2ecf20Sopenharmony_ci		exthdr = l3.hdr + sizeof(*l3.v6);
7468c2ecf20Sopenharmony_ci		l4_proto_tmp = l3.v6->nexthdr;
7478c2ecf20Sopenharmony_ci		if (l4_hdr != exthdr)
7488c2ecf20Sopenharmony_ci			ipv6_skip_exthdr(skb, exthdr - skb->data,
7498c2ecf20Sopenharmony_ci					 &l4_proto_tmp, &frag_off);
7508c2ecf20Sopenharmony_ci	} else if (skb->protocol == htons(ETH_P_IP)) {
7518c2ecf20Sopenharmony_ci		l4_proto_tmp = l3.v4->protocol;
7528c2ecf20Sopenharmony_ci	} else {
7538c2ecf20Sopenharmony_ci		return -EINVAL;
7548c2ecf20Sopenharmony_ci	}
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	*ol4_proto = l4_proto_tmp;
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	/* tunnel packet */
7598c2ecf20Sopenharmony_ci	if (!skb->encapsulation) {
7608c2ecf20Sopenharmony_ci		*il4_proto = 0;
7618c2ecf20Sopenharmony_ci		return 0;
7628c2ecf20Sopenharmony_ci	}
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	/* find inner header point */
7658c2ecf20Sopenharmony_ci	l3.hdr = skb_inner_network_header(skb);
7668c2ecf20Sopenharmony_ci	l4_hdr = skb_inner_transport_header(skb);
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	if (l3.v6->version == 6) {
7698c2ecf20Sopenharmony_ci		exthdr = l3.hdr + sizeof(*l3.v6);
7708c2ecf20Sopenharmony_ci		l4_proto_tmp = l3.v6->nexthdr;
7718c2ecf20Sopenharmony_ci		if (l4_hdr != exthdr)
7728c2ecf20Sopenharmony_ci			ipv6_skip_exthdr(skb, exthdr - skb->data,
7738c2ecf20Sopenharmony_ci					 &l4_proto_tmp, &frag_off);
7748c2ecf20Sopenharmony_ci	} else if (l3.v4->version == 4) {
7758c2ecf20Sopenharmony_ci		l4_proto_tmp = l3.v4->protocol;
7768c2ecf20Sopenharmony_ci	}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	*il4_proto = l4_proto_tmp;
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	return 0;
7818c2ecf20Sopenharmony_ci}
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci/* when skb->encapsulation is 0, skb->ip_summed is CHECKSUM_PARTIAL
7848c2ecf20Sopenharmony_ci * and it is udp packet, which has a dest port as the IANA assigned.
7858c2ecf20Sopenharmony_ci * the hardware is expected to do the checksum offload, but the
7868c2ecf20Sopenharmony_ci * hardware will not do the checksum offload when udp dest port is
7878c2ecf20Sopenharmony_ci * 4789, 4790 or 6081.
7888c2ecf20Sopenharmony_ci */
7898c2ecf20Sopenharmony_cistatic bool hns3_tunnel_csum_bug(struct sk_buff *skb)
7908c2ecf20Sopenharmony_ci{
7918c2ecf20Sopenharmony_ci	union l4_hdr_info l4;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	l4.hdr = skb_transport_header(skb);
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	if (!(!skb->encapsulation &&
7968c2ecf20Sopenharmony_ci	      (l4.udp->dest == htons(IANA_VXLAN_UDP_PORT) ||
7978c2ecf20Sopenharmony_ci	      l4.udp->dest == htons(GENEVE_UDP_PORT) ||
7988c2ecf20Sopenharmony_ci	      l4.udp->dest == htons(4790))))
7998c2ecf20Sopenharmony_ci		return false;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	return true;
8028c2ecf20Sopenharmony_ci}
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_cistatic void hns3_set_outer_l2l3l4(struct sk_buff *skb, u8 ol4_proto,
8058c2ecf20Sopenharmony_ci				  u32 *ol_type_vlan_len_msec)
8068c2ecf20Sopenharmony_ci{
8078c2ecf20Sopenharmony_ci	u32 l2_len, l3_len, l4_len;
8088c2ecf20Sopenharmony_ci	unsigned char *il2_hdr;
8098c2ecf20Sopenharmony_ci	union l3_hdr_info l3;
8108c2ecf20Sopenharmony_ci	union l4_hdr_info l4;
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	l3.hdr = skb_network_header(skb);
8138c2ecf20Sopenharmony_ci	l4.hdr = skb_transport_header(skb);
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	/* compute OL2 header size, defined in 2 Bytes */
8168c2ecf20Sopenharmony_ci	l2_len = l3.hdr - skb->data;
8178c2ecf20Sopenharmony_ci	hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_L2LEN_S, l2_len >> 1);
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	/* compute OL3 header size, defined in 4 Bytes */
8208c2ecf20Sopenharmony_ci	l3_len = l4.hdr - l3.hdr;
8218c2ecf20Sopenharmony_ci	hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_L3LEN_S, l3_len >> 2);
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	il2_hdr = skb_inner_mac_header(skb);
8248c2ecf20Sopenharmony_ci	/* compute OL4 header size, defined in 4 Bytes */
8258c2ecf20Sopenharmony_ci	l4_len = il2_hdr - l4.hdr;
8268c2ecf20Sopenharmony_ci	hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_L4LEN_S, l4_len >> 2);
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	/* define outer network header type */
8298c2ecf20Sopenharmony_ci	if (skb->protocol == htons(ETH_P_IP)) {
8308c2ecf20Sopenharmony_ci		if (skb_is_gso(skb))
8318c2ecf20Sopenharmony_ci			hns3_set_field(*ol_type_vlan_len_msec,
8328c2ecf20Sopenharmony_ci				       HNS3_TXD_OL3T_S,
8338c2ecf20Sopenharmony_ci				       HNS3_OL3T_IPV4_CSUM);
8348c2ecf20Sopenharmony_ci		else
8358c2ecf20Sopenharmony_ci			hns3_set_field(*ol_type_vlan_len_msec,
8368c2ecf20Sopenharmony_ci				       HNS3_TXD_OL3T_S,
8378c2ecf20Sopenharmony_ci				       HNS3_OL3T_IPV4_NO_CSUM);
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	} else if (skb->protocol == htons(ETH_P_IPV6)) {
8408c2ecf20Sopenharmony_ci		hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_OL3T_S,
8418c2ecf20Sopenharmony_ci			       HNS3_OL3T_IPV6);
8428c2ecf20Sopenharmony_ci	}
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	if (ol4_proto == IPPROTO_UDP)
8458c2ecf20Sopenharmony_ci		hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_TUNTYPE_S,
8468c2ecf20Sopenharmony_ci			       HNS3_TUN_MAC_IN_UDP);
8478c2ecf20Sopenharmony_ci	else if (ol4_proto == IPPROTO_GRE)
8488c2ecf20Sopenharmony_ci		hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_TUNTYPE_S,
8498c2ecf20Sopenharmony_ci			       HNS3_TUN_NVGRE);
8508c2ecf20Sopenharmony_ci}
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_cistatic int hns3_set_l2l3l4(struct sk_buff *skb, u8 ol4_proto,
8538c2ecf20Sopenharmony_ci			   u8 il4_proto, u32 *type_cs_vlan_tso,
8548c2ecf20Sopenharmony_ci			   u32 *ol_type_vlan_len_msec)
8558c2ecf20Sopenharmony_ci{
8568c2ecf20Sopenharmony_ci	unsigned char *l2_hdr = skb->data;
8578c2ecf20Sopenharmony_ci	u32 l4_proto = ol4_proto;
8588c2ecf20Sopenharmony_ci	union l4_hdr_info l4;
8598c2ecf20Sopenharmony_ci	union l3_hdr_info l3;
8608c2ecf20Sopenharmony_ci	u32 l2_len, l3_len;
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	l4.hdr = skb_transport_header(skb);
8638c2ecf20Sopenharmony_ci	l3.hdr = skb_network_header(skb);
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	/* handle encapsulation skb */
8668c2ecf20Sopenharmony_ci	if (skb->encapsulation) {
8678c2ecf20Sopenharmony_ci		/* If this is a not UDP/GRE encapsulation skb */
8688c2ecf20Sopenharmony_ci		if (!(ol4_proto == IPPROTO_UDP || ol4_proto == IPPROTO_GRE)) {
8698c2ecf20Sopenharmony_ci			/* drop the skb tunnel packet if hardware don't support,
8708c2ecf20Sopenharmony_ci			 * because hardware can't calculate csum when TSO.
8718c2ecf20Sopenharmony_ci			 */
8728c2ecf20Sopenharmony_ci			if (skb_is_gso(skb))
8738c2ecf20Sopenharmony_ci				return -EDOM;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci			/* the stack computes the IP header already,
8768c2ecf20Sopenharmony_ci			 * driver calculate l4 checksum when not TSO.
8778c2ecf20Sopenharmony_ci			 */
8788c2ecf20Sopenharmony_ci			return skb_checksum_help(skb);
8798c2ecf20Sopenharmony_ci		}
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci		hns3_set_outer_l2l3l4(skb, ol4_proto, ol_type_vlan_len_msec);
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci		/* switch to inner header */
8848c2ecf20Sopenharmony_ci		l2_hdr = skb_inner_mac_header(skb);
8858c2ecf20Sopenharmony_ci		l3.hdr = skb_inner_network_header(skb);
8868c2ecf20Sopenharmony_ci		l4.hdr = skb_inner_transport_header(skb);
8878c2ecf20Sopenharmony_ci		l4_proto = il4_proto;
8888c2ecf20Sopenharmony_ci	}
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	if (l3.v4->version == 4) {
8918c2ecf20Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_S,
8928c2ecf20Sopenharmony_ci			       HNS3_L3T_IPV4);
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_ci		/* the stack computes the IP header already, the only time we
8958c2ecf20Sopenharmony_ci		 * need the hardware to recompute it is in the case of TSO.
8968c2ecf20Sopenharmony_ci		 */
8978c2ecf20Sopenharmony_ci		if (skb_is_gso(skb))
8988c2ecf20Sopenharmony_ci			hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3CS_B, 1);
8998c2ecf20Sopenharmony_ci	} else if (l3.v6->version == 6) {
9008c2ecf20Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_S,
9018c2ecf20Sopenharmony_ci			       HNS3_L3T_IPV6);
9028c2ecf20Sopenharmony_ci	}
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci	/* compute inner(/normal) L2 header size, defined in 2 Bytes */
9058c2ecf20Sopenharmony_ci	l2_len = l3.hdr - l2_hdr;
9068c2ecf20Sopenharmony_ci	hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L2LEN_S, l2_len >> 1);
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	/* compute inner(/normal) L3 header size, defined in 4 Bytes */
9098c2ecf20Sopenharmony_ci	l3_len = l4.hdr - l3.hdr;
9108c2ecf20Sopenharmony_ci	hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3LEN_S, l3_len >> 2);
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci	/* compute inner(/normal) L4 header size, defined in 4 Bytes */
9138c2ecf20Sopenharmony_ci	switch (l4_proto) {
9148c2ecf20Sopenharmony_ci	case IPPROTO_TCP:
9158c2ecf20Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
9168c2ecf20Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S,
9178c2ecf20Sopenharmony_ci			       HNS3_L4T_TCP);
9188c2ecf20Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_S,
9198c2ecf20Sopenharmony_ci			       l4.tcp->doff);
9208c2ecf20Sopenharmony_ci		break;
9218c2ecf20Sopenharmony_ci	case IPPROTO_UDP:
9228c2ecf20Sopenharmony_ci		if (hns3_tunnel_csum_bug(skb)) {
9238c2ecf20Sopenharmony_ci			int ret = skb_put_padto(skb, HNS3_MIN_TUN_PKT_LEN);
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci			return ret ? ret : skb_checksum_help(skb);
9268c2ecf20Sopenharmony_ci		}
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
9298c2ecf20Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S,
9308c2ecf20Sopenharmony_ci			       HNS3_L4T_UDP);
9318c2ecf20Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_S,
9328c2ecf20Sopenharmony_ci			       (sizeof(struct udphdr) >> 2));
9338c2ecf20Sopenharmony_ci		break;
9348c2ecf20Sopenharmony_ci	case IPPROTO_SCTP:
9358c2ecf20Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
9368c2ecf20Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S,
9378c2ecf20Sopenharmony_ci			       HNS3_L4T_SCTP);
9388c2ecf20Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_S,
9398c2ecf20Sopenharmony_ci			       (sizeof(struct sctphdr) >> 2));
9408c2ecf20Sopenharmony_ci		break;
9418c2ecf20Sopenharmony_ci	default:
9428c2ecf20Sopenharmony_ci		/* drop the skb tunnel packet if hardware don't support,
9438c2ecf20Sopenharmony_ci		 * because hardware can't calculate csum when TSO.
9448c2ecf20Sopenharmony_ci		 */
9458c2ecf20Sopenharmony_ci		if (skb_is_gso(skb))
9468c2ecf20Sopenharmony_ci			return -EDOM;
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci		/* the stack computes the IP header already,
9498c2ecf20Sopenharmony_ci		 * driver calculate l4 checksum when not TSO.
9508c2ecf20Sopenharmony_ci		 */
9518c2ecf20Sopenharmony_ci		return skb_checksum_help(skb);
9528c2ecf20Sopenharmony_ci	}
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci	return 0;
9558c2ecf20Sopenharmony_ci}
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_cistatic int hns3_handle_vtags(struct hns3_enet_ring *tx_ring,
9588c2ecf20Sopenharmony_ci			     struct sk_buff *skb)
9598c2ecf20Sopenharmony_ci{
9608c2ecf20Sopenharmony_ci	struct hnae3_handle *handle = tx_ring->tqp->handle;
9618c2ecf20Sopenharmony_ci	struct vlan_ethhdr *vhdr;
9628c2ecf20Sopenharmony_ci	int rc;
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci	if (!(skb->protocol == htons(ETH_P_8021Q) ||
9658c2ecf20Sopenharmony_ci	      skb_vlan_tag_present(skb)))
9668c2ecf20Sopenharmony_ci		return 0;
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	/* Since HW limitation, if port based insert VLAN enabled, only one VLAN
9698c2ecf20Sopenharmony_ci	 * header is allowed in skb, otherwise it will cause RAS error.
9708c2ecf20Sopenharmony_ci	 */
9718c2ecf20Sopenharmony_ci	if (unlikely(skb_vlan_tagged_multi(skb) &&
9728c2ecf20Sopenharmony_ci		     handle->port_base_vlan_state ==
9738c2ecf20Sopenharmony_ci		     HNAE3_PORT_BASE_VLAN_ENABLE))
9748c2ecf20Sopenharmony_ci		return -EINVAL;
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	if (skb->protocol == htons(ETH_P_8021Q) &&
9778c2ecf20Sopenharmony_ci	    !(handle->kinfo.netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) {
9788c2ecf20Sopenharmony_ci		/* When HW VLAN acceleration is turned off, and the stack
9798c2ecf20Sopenharmony_ci		 * sets the protocol to 802.1q, the driver just need to
9808c2ecf20Sopenharmony_ci		 * set the protocol to the encapsulated ethertype.
9818c2ecf20Sopenharmony_ci		 */
9828c2ecf20Sopenharmony_ci		skb->protocol = vlan_get_protocol(skb);
9838c2ecf20Sopenharmony_ci		return 0;
9848c2ecf20Sopenharmony_ci	}
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	if (skb_vlan_tag_present(skb)) {
9878c2ecf20Sopenharmony_ci		/* Based on hw strategy, use out_vtag in two layer tag case,
9888c2ecf20Sopenharmony_ci		 * and use inner_vtag in one tag case.
9898c2ecf20Sopenharmony_ci		 */
9908c2ecf20Sopenharmony_ci		if (skb->protocol == htons(ETH_P_8021Q) &&
9918c2ecf20Sopenharmony_ci		    handle->port_base_vlan_state ==
9928c2ecf20Sopenharmony_ci		    HNAE3_PORT_BASE_VLAN_DISABLE)
9938c2ecf20Sopenharmony_ci			rc = HNS3_OUTER_VLAN_TAG;
9948c2ecf20Sopenharmony_ci		else
9958c2ecf20Sopenharmony_ci			rc = HNS3_INNER_VLAN_TAG;
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci		skb->protocol = vlan_get_protocol(skb);
9988c2ecf20Sopenharmony_ci		return rc;
9998c2ecf20Sopenharmony_ci	}
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	rc = skb_cow_head(skb, 0);
10028c2ecf20Sopenharmony_ci	if (unlikely(rc < 0))
10038c2ecf20Sopenharmony_ci		return rc;
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	vhdr = skb_vlan_eth_hdr(skb);
10068c2ecf20Sopenharmony_ci	vhdr->h_vlan_TCI |= cpu_to_be16((skb->priority << VLAN_PRIO_SHIFT)
10078c2ecf20Sopenharmony_ci					 & VLAN_PRIO_MASK);
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci	skb->protocol = vlan_get_protocol(skb);
10108c2ecf20Sopenharmony_ci	return 0;
10118c2ecf20Sopenharmony_ci}
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_cistatic int hns3_fill_skb_desc(struct hns3_enet_ring *ring,
10148c2ecf20Sopenharmony_ci			      struct sk_buff *skb, struct hns3_desc *desc)
10158c2ecf20Sopenharmony_ci{
10168c2ecf20Sopenharmony_ci	u32 ol_type_vlan_len_msec = 0;
10178c2ecf20Sopenharmony_ci	u32 type_cs_vlan_tso = 0;
10188c2ecf20Sopenharmony_ci	u32 paylen = skb->len;
10198c2ecf20Sopenharmony_ci	u16 inner_vtag = 0;
10208c2ecf20Sopenharmony_ci	u16 out_vtag = 0;
10218c2ecf20Sopenharmony_ci	u16 mss = 0;
10228c2ecf20Sopenharmony_ci	int ret;
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	ret = hns3_handle_vtags(ring, skb);
10258c2ecf20Sopenharmony_ci	if (unlikely(ret < 0)) {
10268c2ecf20Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
10278c2ecf20Sopenharmony_ci		ring->stats.tx_vlan_err++;
10288c2ecf20Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
10298c2ecf20Sopenharmony_ci		return ret;
10308c2ecf20Sopenharmony_ci	} else if (ret == HNS3_INNER_VLAN_TAG) {
10318c2ecf20Sopenharmony_ci		inner_vtag = skb_vlan_tag_get(skb);
10328c2ecf20Sopenharmony_ci		inner_vtag |= (skb->priority << VLAN_PRIO_SHIFT) &
10338c2ecf20Sopenharmony_ci				VLAN_PRIO_MASK;
10348c2ecf20Sopenharmony_ci		hns3_set_field(type_cs_vlan_tso, HNS3_TXD_VLAN_B, 1);
10358c2ecf20Sopenharmony_ci	} else if (ret == HNS3_OUTER_VLAN_TAG) {
10368c2ecf20Sopenharmony_ci		out_vtag = skb_vlan_tag_get(skb);
10378c2ecf20Sopenharmony_ci		out_vtag |= (skb->priority << VLAN_PRIO_SHIFT) &
10388c2ecf20Sopenharmony_ci				VLAN_PRIO_MASK;
10398c2ecf20Sopenharmony_ci		hns3_set_field(ol_type_vlan_len_msec, HNS3_TXD_OVLAN_B,
10408c2ecf20Sopenharmony_ci			       1);
10418c2ecf20Sopenharmony_ci	}
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	if (skb->ip_summed == CHECKSUM_PARTIAL) {
10448c2ecf20Sopenharmony_ci		u8 ol4_proto, il4_proto;
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci		skb_reset_mac_len(skb);
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci		ret = hns3_get_l4_protocol(skb, &ol4_proto, &il4_proto);
10498c2ecf20Sopenharmony_ci		if (unlikely(ret < 0)) {
10508c2ecf20Sopenharmony_ci			u64_stats_update_begin(&ring->syncp);
10518c2ecf20Sopenharmony_ci			ring->stats.tx_l4_proto_err++;
10528c2ecf20Sopenharmony_ci			u64_stats_update_end(&ring->syncp);
10538c2ecf20Sopenharmony_ci			return ret;
10548c2ecf20Sopenharmony_ci		}
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci		ret = hns3_set_l2l3l4(skb, ol4_proto, il4_proto,
10578c2ecf20Sopenharmony_ci				      &type_cs_vlan_tso,
10588c2ecf20Sopenharmony_ci				      &ol_type_vlan_len_msec);
10598c2ecf20Sopenharmony_ci		if (unlikely(ret < 0)) {
10608c2ecf20Sopenharmony_ci			u64_stats_update_begin(&ring->syncp);
10618c2ecf20Sopenharmony_ci			ring->stats.tx_l2l3l4_err++;
10628c2ecf20Sopenharmony_ci			u64_stats_update_end(&ring->syncp);
10638c2ecf20Sopenharmony_ci			return ret;
10648c2ecf20Sopenharmony_ci		}
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci		ret = hns3_set_tso(skb, &paylen, &mss,
10678c2ecf20Sopenharmony_ci				   &type_cs_vlan_tso);
10688c2ecf20Sopenharmony_ci		if (unlikely(ret < 0)) {
10698c2ecf20Sopenharmony_ci			u64_stats_update_begin(&ring->syncp);
10708c2ecf20Sopenharmony_ci			ring->stats.tx_tso_err++;
10718c2ecf20Sopenharmony_ci			u64_stats_update_end(&ring->syncp);
10728c2ecf20Sopenharmony_ci			return ret;
10738c2ecf20Sopenharmony_ci		}
10748c2ecf20Sopenharmony_ci	}
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	/* Set txbd */
10778c2ecf20Sopenharmony_ci	desc->tx.ol_type_vlan_len_msec =
10788c2ecf20Sopenharmony_ci		cpu_to_le32(ol_type_vlan_len_msec);
10798c2ecf20Sopenharmony_ci	desc->tx.type_cs_vlan_tso_len = cpu_to_le32(type_cs_vlan_tso);
10808c2ecf20Sopenharmony_ci	desc->tx.paylen = cpu_to_le32(paylen);
10818c2ecf20Sopenharmony_ci	desc->tx.mss = cpu_to_le16(mss);
10828c2ecf20Sopenharmony_ci	desc->tx.vlan_tag = cpu_to_le16(inner_vtag);
10838c2ecf20Sopenharmony_ci	desc->tx.outer_vlan_tag = cpu_to_le16(out_vtag);
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci	return 0;
10868c2ecf20Sopenharmony_ci}
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_cistatic int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
10898c2ecf20Sopenharmony_ci			  unsigned int size, enum hns_desc_type type)
10908c2ecf20Sopenharmony_ci{
10918c2ecf20Sopenharmony_ci#define HNS3_LIKELY_BD_NUM	1
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use];
10948c2ecf20Sopenharmony_ci	struct hns3_desc *desc = &ring->desc[ring->next_to_use];
10958c2ecf20Sopenharmony_ci	struct device *dev = ring_to_dev(ring);
10968c2ecf20Sopenharmony_ci	skb_frag_t *frag;
10978c2ecf20Sopenharmony_ci	unsigned int frag_buf_num;
10988c2ecf20Sopenharmony_ci	int k, sizeoflast;
10998c2ecf20Sopenharmony_ci	dma_addr_t dma;
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	if (type == DESC_TYPE_FRAGLIST_SKB ||
11028c2ecf20Sopenharmony_ci	    type == DESC_TYPE_SKB) {
11038c2ecf20Sopenharmony_ci		struct sk_buff *skb = (struct sk_buff *)priv;
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci		dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE);
11068c2ecf20Sopenharmony_ci	} else {
11078c2ecf20Sopenharmony_ci		frag = (skb_frag_t *)priv;
11088c2ecf20Sopenharmony_ci		dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE);
11098c2ecf20Sopenharmony_ci	}
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci	if (unlikely(dma_mapping_error(dev, dma))) {
11128c2ecf20Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
11138c2ecf20Sopenharmony_ci		ring->stats.sw_err_cnt++;
11148c2ecf20Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
11158c2ecf20Sopenharmony_ci		return -ENOMEM;
11168c2ecf20Sopenharmony_ci	}
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci	desc_cb->priv = priv;
11198c2ecf20Sopenharmony_ci	desc_cb->length = size;
11208c2ecf20Sopenharmony_ci	desc_cb->dma = dma;
11218c2ecf20Sopenharmony_ci	desc_cb->type = type;
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	if (likely(size <= HNS3_MAX_BD_SIZE)) {
11248c2ecf20Sopenharmony_ci		desc->addr = cpu_to_le64(dma);
11258c2ecf20Sopenharmony_ci		desc->tx.send_size = cpu_to_le16(size);
11268c2ecf20Sopenharmony_ci		desc->tx.bdtp_fe_sc_vld_ra_ri =
11278c2ecf20Sopenharmony_ci			cpu_to_le16(BIT(HNS3_TXD_VLD_B));
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci		trace_hns3_tx_desc(ring, ring->next_to_use);
11308c2ecf20Sopenharmony_ci		ring_ptr_move_fw(ring, next_to_use);
11318c2ecf20Sopenharmony_ci		return HNS3_LIKELY_BD_NUM;
11328c2ecf20Sopenharmony_ci	}
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	frag_buf_num = hns3_tx_bd_count(size);
11358c2ecf20Sopenharmony_ci	sizeoflast = size % HNS3_MAX_BD_SIZE;
11368c2ecf20Sopenharmony_ci	sizeoflast = sizeoflast ? sizeoflast : HNS3_MAX_BD_SIZE;
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci	/* When frag size is bigger than hardware limit, split this frag */
11398c2ecf20Sopenharmony_ci	for (k = 0; k < frag_buf_num; k++) {
11408c2ecf20Sopenharmony_ci		/* now, fill the descriptor */
11418c2ecf20Sopenharmony_ci		desc->addr = cpu_to_le64(dma + HNS3_MAX_BD_SIZE * k);
11428c2ecf20Sopenharmony_ci		desc->tx.send_size = cpu_to_le16((k == frag_buf_num - 1) ?
11438c2ecf20Sopenharmony_ci				     (u16)sizeoflast : (u16)HNS3_MAX_BD_SIZE);
11448c2ecf20Sopenharmony_ci		desc->tx.bdtp_fe_sc_vld_ra_ri =
11458c2ecf20Sopenharmony_ci				cpu_to_le16(BIT(HNS3_TXD_VLD_B));
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci		trace_hns3_tx_desc(ring, ring->next_to_use);
11488c2ecf20Sopenharmony_ci		/* move ring pointer to next */
11498c2ecf20Sopenharmony_ci		ring_ptr_move_fw(ring, next_to_use);
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci		desc = &ring->desc[ring->next_to_use];
11528c2ecf20Sopenharmony_ci	}
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_ci	return frag_buf_num;
11558c2ecf20Sopenharmony_ci}
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_cistatic unsigned int hns3_skb_bd_num(struct sk_buff *skb, unsigned int *bd_size,
11588c2ecf20Sopenharmony_ci				    unsigned int bd_num)
11598c2ecf20Sopenharmony_ci{
11608c2ecf20Sopenharmony_ci	unsigned int size;
11618c2ecf20Sopenharmony_ci	int i;
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	size = skb_headlen(skb);
11648c2ecf20Sopenharmony_ci	while (size > HNS3_MAX_BD_SIZE) {
11658c2ecf20Sopenharmony_ci		bd_size[bd_num++] = HNS3_MAX_BD_SIZE;
11668c2ecf20Sopenharmony_ci		size -= HNS3_MAX_BD_SIZE;
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci		if (bd_num > HNS3_MAX_TSO_BD_NUM)
11698c2ecf20Sopenharmony_ci			return bd_num;
11708c2ecf20Sopenharmony_ci	}
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci	if (size) {
11738c2ecf20Sopenharmony_ci		bd_size[bd_num++] = size;
11748c2ecf20Sopenharmony_ci		if (bd_num > HNS3_MAX_TSO_BD_NUM)
11758c2ecf20Sopenharmony_ci			return bd_num;
11768c2ecf20Sopenharmony_ci	}
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
11798c2ecf20Sopenharmony_ci		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
11808c2ecf20Sopenharmony_ci		size = skb_frag_size(frag);
11818c2ecf20Sopenharmony_ci		if (!size)
11828c2ecf20Sopenharmony_ci			continue;
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci		while (size > HNS3_MAX_BD_SIZE) {
11858c2ecf20Sopenharmony_ci			bd_size[bd_num++] = HNS3_MAX_BD_SIZE;
11868c2ecf20Sopenharmony_ci			size -= HNS3_MAX_BD_SIZE;
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci			if (bd_num > HNS3_MAX_TSO_BD_NUM)
11898c2ecf20Sopenharmony_ci				return bd_num;
11908c2ecf20Sopenharmony_ci		}
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci		bd_size[bd_num++] = size;
11938c2ecf20Sopenharmony_ci		if (bd_num > HNS3_MAX_TSO_BD_NUM)
11948c2ecf20Sopenharmony_ci			return bd_num;
11958c2ecf20Sopenharmony_ci	}
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci	return bd_num;
11988c2ecf20Sopenharmony_ci}
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_cistatic unsigned int hns3_tx_bd_num(struct sk_buff *skb, unsigned int *bd_size,
12018c2ecf20Sopenharmony_ci				   u8 max_non_tso_bd_num, unsigned int bd_num,
12028c2ecf20Sopenharmony_ci				   unsigned int recursion_level)
12038c2ecf20Sopenharmony_ci{
12048c2ecf20Sopenharmony_ci#define HNS3_MAX_RECURSION_LEVEL	24
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	struct sk_buff *frag_skb;
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	/* If the total len is within the max bd limit */
12098c2ecf20Sopenharmony_ci	if (likely(skb->len <= HNS3_MAX_BD_SIZE && !recursion_level &&
12108c2ecf20Sopenharmony_ci		   !skb_has_frag_list(skb) &&
12118c2ecf20Sopenharmony_ci		   skb_shinfo(skb)->nr_frags < max_non_tso_bd_num))
12128c2ecf20Sopenharmony_ci		return skb_shinfo(skb)->nr_frags + 1U;
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	if (unlikely(recursion_level >= HNS3_MAX_RECURSION_LEVEL))
12158c2ecf20Sopenharmony_ci		return UINT_MAX;
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	bd_num = hns3_skb_bd_num(skb, bd_size, bd_num);
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	if (!skb_has_frag_list(skb) || bd_num > HNS3_MAX_TSO_BD_NUM)
12208c2ecf20Sopenharmony_ci		return bd_num;
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	skb_walk_frags(skb, frag_skb) {
12238c2ecf20Sopenharmony_ci		bd_num = hns3_tx_bd_num(frag_skb, bd_size, max_non_tso_bd_num,
12248c2ecf20Sopenharmony_ci					bd_num, recursion_level + 1);
12258c2ecf20Sopenharmony_ci		if (bd_num > HNS3_MAX_TSO_BD_NUM)
12268c2ecf20Sopenharmony_ci			return bd_num;
12278c2ecf20Sopenharmony_ci	}
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci	return bd_num;
12308c2ecf20Sopenharmony_ci}
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_cistatic unsigned int hns3_gso_hdr_len(struct sk_buff *skb)
12338c2ecf20Sopenharmony_ci{
12348c2ecf20Sopenharmony_ci	if (!skb->encapsulation)
12358c2ecf20Sopenharmony_ci		return skb_transport_offset(skb) + tcp_hdrlen(skb);
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci	return skb_inner_transport_offset(skb) + inner_tcp_hdrlen(skb);
12388c2ecf20Sopenharmony_ci}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ci/* HW need every continuous max_non_tso_bd_num buffer data to be larger
12418c2ecf20Sopenharmony_ci * than MSS, we simplify it by ensuring skb_headlen + the first continuous
12428c2ecf20Sopenharmony_ci * max_non_tso_bd_num - 1 frags to be larger than gso header len + mss,
12438c2ecf20Sopenharmony_ci * and the remaining continuous max_non_tso_bd_num - 1 frags to be larger
12448c2ecf20Sopenharmony_ci * than MSS except the last max_non_tso_bd_num - 1 frags.
12458c2ecf20Sopenharmony_ci */
12468c2ecf20Sopenharmony_cistatic bool hns3_skb_need_linearized(struct sk_buff *skb, unsigned int *bd_size,
12478c2ecf20Sopenharmony_ci				     unsigned int bd_num, u8 max_non_tso_bd_num)
12488c2ecf20Sopenharmony_ci{
12498c2ecf20Sopenharmony_ci	unsigned int tot_len = 0;
12508c2ecf20Sopenharmony_ci	int i;
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	for (i = 0; i < max_non_tso_bd_num - 1U; i++)
12538c2ecf20Sopenharmony_ci		tot_len += bd_size[i];
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	/* ensure the first max_non_tso_bd_num frags is greater than
12568c2ecf20Sopenharmony_ci	 * mss + header
12578c2ecf20Sopenharmony_ci	 */
12588c2ecf20Sopenharmony_ci	if (tot_len + bd_size[max_non_tso_bd_num - 1U] <
12598c2ecf20Sopenharmony_ci	    skb_shinfo(skb)->gso_size + hns3_gso_hdr_len(skb))
12608c2ecf20Sopenharmony_ci		return true;
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ci	/* ensure every continuous max_non_tso_bd_num - 1 buffer is greater
12638c2ecf20Sopenharmony_ci	 * than mss except the last one.
12648c2ecf20Sopenharmony_ci	 */
12658c2ecf20Sopenharmony_ci	for (i = 0; i < bd_num - max_non_tso_bd_num; i++) {
12668c2ecf20Sopenharmony_ci		tot_len -= bd_size[i];
12678c2ecf20Sopenharmony_ci		tot_len += bd_size[i + max_non_tso_bd_num - 1U];
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci		if (tot_len < skb_shinfo(skb)->gso_size)
12708c2ecf20Sopenharmony_ci			return true;
12718c2ecf20Sopenharmony_ci	}
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	return false;
12748c2ecf20Sopenharmony_ci}
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_civoid hns3_shinfo_pack(struct skb_shared_info *shinfo, __u32 *size)
12778c2ecf20Sopenharmony_ci{
12788c2ecf20Sopenharmony_ci	int i;
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_SKB_FRAGS; i++)
12818c2ecf20Sopenharmony_ci		size[i] = skb_frag_size(&shinfo->frags[i]);
12828c2ecf20Sopenharmony_ci}
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_cistatic int hns3_skb_linearize(struct hns3_enet_ring *ring,
12858c2ecf20Sopenharmony_ci			      struct sk_buff *skb,
12868c2ecf20Sopenharmony_ci			      unsigned int bd_num)
12878c2ecf20Sopenharmony_ci{
12888c2ecf20Sopenharmony_ci	/* 'bd_num == UINT_MAX' means the skb' fraglist has a
12898c2ecf20Sopenharmony_ci	 * recursion level of over HNS3_MAX_RECURSION_LEVEL.
12908c2ecf20Sopenharmony_ci	 */
12918c2ecf20Sopenharmony_ci	if (bd_num == UINT_MAX) {
12928c2ecf20Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
12938c2ecf20Sopenharmony_ci		ring->stats.over_max_recursion++;
12948c2ecf20Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
12958c2ecf20Sopenharmony_ci		return -ENOMEM;
12968c2ecf20Sopenharmony_ci	}
12978c2ecf20Sopenharmony_ci
12988c2ecf20Sopenharmony_ci	/* The skb->len has exceeded the hw limitation, linearization
12998c2ecf20Sopenharmony_ci	 * will not help.
13008c2ecf20Sopenharmony_ci	 */
13018c2ecf20Sopenharmony_ci	if (skb->len > HNS3_MAX_TSO_SIZE ||
13028c2ecf20Sopenharmony_ci	    (!skb_is_gso(skb) && skb->len > HNS3_MAX_NON_TSO_SIZE)) {
13038c2ecf20Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
13048c2ecf20Sopenharmony_ci		ring->stats.hw_limitation++;
13058c2ecf20Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
13068c2ecf20Sopenharmony_ci		return -ENOMEM;
13078c2ecf20Sopenharmony_ci	}
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci	if (__skb_linearize(skb)) {
13108c2ecf20Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
13118c2ecf20Sopenharmony_ci		ring->stats.sw_err_cnt++;
13128c2ecf20Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
13138c2ecf20Sopenharmony_ci		return -ENOMEM;
13148c2ecf20Sopenharmony_ci	}
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci	return 0;
13178c2ecf20Sopenharmony_ci}
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_cistatic int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring,
13208c2ecf20Sopenharmony_ci				  struct net_device *netdev,
13218c2ecf20Sopenharmony_ci				  struct sk_buff *skb)
13228c2ecf20Sopenharmony_ci{
13238c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
13248c2ecf20Sopenharmony_ci	u8 max_non_tso_bd_num = priv->max_non_tso_bd_num;
13258c2ecf20Sopenharmony_ci	unsigned int bd_size[HNS3_MAX_TSO_BD_NUM + 1U];
13268c2ecf20Sopenharmony_ci	unsigned int bd_num;
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci	bd_num = hns3_tx_bd_num(skb, bd_size, max_non_tso_bd_num, 0, 0);
13298c2ecf20Sopenharmony_ci	if (unlikely(bd_num > max_non_tso_bd_num)) {
13308c2ecf20Sopenharmony_ci		if (bd_num <= HNS3_MAX_TSO_BD_NUM && skb_is_gso(skb) &&
13318c2ecf20Sopenharmony_ci		    !hns3_skb_need_linearized(skb, bd_size, bd_num,
13328c2ecf20Sopenharmony_ci					      max_non_tso_bd_num)) {
13338c2ecf20Sopenharmony_ci			trace_hns3_over_max_bd(skb);
13348c2ecf20Sopenharmony_ci			goto out;
13358c2ecf20Sopenharmony_ci		}
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci		if (hns3_skb_linearize(ring, skb, bd_num))
13388c2ecf20Sopenharmony_ci			return -ENOMEM;
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci		bd_num = hns3_tx_bd_count(skb->len);
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
13438c2ecf20Sopenharmony_ci		ring->stats.tx_copy++;
13448c2ecf20Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
13458c2ecf20Sopenharmony_ci	}
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ciout:
13488c2ecf20Sopenharmony_ci	if (likely(ring_space(ring) >= bd_num))
13498c2ecf20Sopenharmony_ci		return bd_num;
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci	netif_stop_subqueue(netdev, ring->queue_index);
13528c2ecf20Sopenharmony_ci	smp_mb(); /* Memory barrier before checking ring_space */
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci	/* Start queue in case hns3_clean_tx_ring has just made room
13558c2ecf20Sopenharmony_ci	 * available and has not seen the queue stopped state performed
13568c2ecf20Sopenharmony_ci	 * by netif_stop_subqueue above.
13578c2ecf20Sopenharmony_ci	 */
13588c2ecf20Sopenharmony_ci	if (ring_space(ring) >= bd_num && netif_carrier_ok(netdev) &&
13598c2ecf20Sopenharmony_ci	    !test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) {
13608c2ecf20Sopenharmony_ci		netif_start_subqueue(netdev, ring->queue_index);
13618c2ecf20Sopenharmony_ci		return bd_num;
13628c2ecf20Sopenharmony_ci	}
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci	u64_stats_update_begin(&ring->syncp);
13658c2ecf20Sopenharmony_ci	ring->stats.tx_busy++;
13668c2ecf20Sopenharmony_ci	u64_stats_update_end(&ring->syncp);
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci	return -EBUSY;
13698c2ecf20Sopenharmony_ci}
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_cistatic void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig)
13728c2ecf20Sopenharmony_ci{
13738c2ecf20Sopenharmony_ci	struct device *dev = ring_to_dev(ring);
13748c2ecf20Sopenharmony_ci	unsigned int i;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	for (i = 0; i < ring->desc_num; i++) {
13778c2ecf20Sopenharmony_ci		struct hns3_desc *desc = &ring->desc[ring->next_to_use];
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci		memset(desc, 0, sizeof(*desc));
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci		/* check if this is where we started */
13828c2ecf20Sopenharmony_ci		if (ring->next_to_use == next_to_use_orig)
13838c2ecf20Sopenharmony_ci			break;
13848c2ecf20Sopenharmony_ci
13858c2ecf20Sopenharmony_ci		/* rollback one */
13868c2ecf20Sopenharmony_ci		ring_ptr_move_bw(ring, next_to_use);
13878c2ecf20Sopenharmony_ci
13888c2ecf20Sopenharmony_ci		if (!ring->desc_cb[ring->next_to_use].dma)
13898c2ecf20Sopenharmony_ci			continue;
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci		/* unmap the descriptor dma address */
13928c2ecf20Sopenharmony_ci		if (ring->desc_cb[ring->next_to_use].type == DESC_TYPE_SKB ||
13938c2ecf20Sopenharmony_ci		    ring->desc_cb[ring->next_to_use].type ==
13948c2ecf20Sopenharmony_ci		    DESC_TYPE_FRAGLIST_SKB)
13958c2ecf20Sopenharmony_ci			dma_unmap_single(dev,
13968c2ecf20Sopenharmony_ci					 ring->desc_cb[ring->next_to_use].dma,
13978c2ecf20Sopenharmony_ci					ring->desc_cb[ring->next_to_use].length,
13988c2ecf20Sopenharmony_ci					DMA_TO_DEVICE);
13998c2ecf20Sopenharmony_ci		else if (ring->desc_cb[ring->next_to_use].length)
14008c2ecf20Sopenharmony_ci			dma_unmap_page(dev,
14018c2ecf20Sopenharmony_ci				       ring->desc_cb[ring->next_to_use].dma,
14028c2ecf20Sopenharmony_ci				       ring->desc_cb[ring->next_to_use].length,
14038c2ecf20Sopenharmony_ci				       DMA_TO_DEVICE);
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci		ring->desc_cb[ring->next_to_use].length = 0;
14068c2ecf20Sopenharmony_ci		ring->desc_cb[ring->next_to_use].dma = 0;
14078c2ecf20Sopenharmony_ci		ring->desc_cb[ring->next_to_use].type = DESC_TYPE_UNKNOWN;
14088c2ecf20Sopenharmony_ci	}
14098c2ecf20Sopenharmony_ci}
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_cistatic int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring,
14128c2ecf20Sopenharmony_ci				 struct sk_buff *skb, enum hns_desc_type type)
14138c2ecf20Sopenharmony_ci{
14148c2ecf20Sopenharmony_ci	unsigned int size = skb_headlen(skb);
14158c2ecf20Sopenharmony_ci	struct sk_buff *frag_skb;
14168c2ecf20Sopenharmony_ci	int i, ret, bd_num = 0;
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci	if (size) {
14198c2ecf20Sopenharmony_ci		ret = hns3_fill_desc(ring, skb, size, type);
14208c2ecf20Sopenharmony_ci		if (unlikely(ret < 0))
14218c2ecf20Sopenharmony_ci			return ret;
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_ci		bd_num += ret;
14248c2ecf20Sopenharmony_ci	}
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
14278c2ecf20Sopenharmony_ci		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci		size = skb_frag_size(frag);
14308c2ecf20Sopenharmony_ci		if (!size)
14318c2ecf20Sopenharmony_ci			continue;
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_ci		ret = hns3_fill_desc(ring, frag, size, DESC_TYPE_PAGE);
14348c2ecf20Sopenharmony_ci		if (unlikely(ret < 0))
14358c2ecf20Sopenharmony_ci			return ret;
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_ci		bd_num += ret;
14388c2ecf20Sopenharmony_ci	}
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	skb_walk_frags(skb, frag_skb) {
14418c2ecf20Sopenharmony_ci		ret = hns3_fill_skb_to_desc(ring, frag_skb,
14428c2ecf20Sopenharmony_ci					    DESC_TYPE_FRAGLIST_SKB);
14438c2ecf20Sopenharmony_ci		if (unlikely(ret < 0))
14448c2ecf20Sopenharmony_ci			return ret;
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci		bd_num += ret;
14478c2ecf20Sopenharmony_ci	}
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci	return bd_num;
14508c2ecf20Sopenharmony_ci}
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_cistatic void hns3_tx_doorbell(struct hns3_enet_ring *ring, int num,
14538c2ecf20Sopenharmony_ci			     bool doorbell)
14548c2ecf20Sopenharmony_ci{
14558c2ecf20Sopenharmony_ci	ring->pending_buf += num;
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci	if (!doorbell) {
14588c2ecf20Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
14598c2ecf20Sopenharmony_ci		ring->stats.tx_more++;
14608c2ecf20Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
14618c2ecf20Sopenharmony_ci		return;
14628c2ecf20Sopenharmony_ci	}
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci	if (!ring->pending_buf)
14658c2ecf20Sopenharmony_ci		return;
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ci	writel(ring->pending_buf,
14688c2ecf20Sopenharmony_ci	       ring->tqp->io_base + HNS3_RING_TX_RING_TAIL_REG);
14698c2ecf20Sopenharmony_ci	ring->pending_buf = 0;
14708c2ecf20Sopenharmony_ci	WRITE_ONCE(ring->last_to_use, ring->next_to_use);
14718c2ecf20Sopenharmony_ci}
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_cinetdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
14748c2ecf20Sopenharmony_ci{
14758c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
14768c2ecf20Sopenharmony_ci	struct hns3_enet_ring *ring = &priv->ring[skb->queue_mapping];
14778c2ecf20Sopenharmony_ci	struct netdev_queue *dev_queue;
14788c2ecf20Sopenharmony_ci	int pre_ntu, next_to_use_head;
14798c2ecf20Sopenharmony_ci	bool doorbell;
14808c2ecf20Sopenharmony_ci	int ret;
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	/* Hardware can only handle short frames above 32 bytes */
14838c2ecf20Sopenharmony_ci	if (skb_put_padto(skb, HNS3_MIN_TX_LEN)) {
14848c2ecf20Sopenharmony_ci		hns3_tx_doorbell(ring, 0, !netdev_xmit_more());
14858c2ecf20Sopenharmony_ci		return NETDEV_TX_OK;
14868c2ecf20Sopenharmony_ci	}
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci	/* Prefetch the data used later */
14898c2ecf20Sopenharmony_ci	prefetch(skb->data);
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci	ret = hns3_nic_maybe_stop_tx(ring, netdev, skb);
14928c2ecf20Sopenharmony_ci	if (unlikely(ret <= 0)) {
14938c2ecf20Sopenharmony_ci		if (ret == -EBUSY) {
14948c2ecf20Sopenharmony_ci			hns3_tx_doorbell(ring, 0, true);
14958c2ecf20Sopenharmony_ci			return NETDEV_TX_BUSY;
14968c2ecf20Sopenharmony_ci		}
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_ci		hns3_rl_err(netdev, "xmit error: %d!\n", ret);
14998c2ecf20Sopenharmony_ci		goto out_err_tx_ok;
15008c2ecf20Sopenharmony_ci	}
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_ci	next_to_use_head = ring->next_to_use;
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	ret = hns3_fill_skb_desc(ring, skb, &ring->desc[ring->next_to_use]);
15058c2ecf20Sopenharmony_ci	if (unlikely(ret < 0))
15068c2ecf20Sopenharmony_ci		goto fill_err;
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci	/* 'ret < 0' means filling error, 'ret == 0' means skb->len is
15098c2ecf20Sopenharmony_ci	 * zero, which is unlikely, and 'ret > 0' means how many tx desc
15108c2ecf20Sopenharmony_ci	 * need to be notified to the hw.
15118c2ecf20Sopenharmony_ci	 */
15128c2ecf20Sopenharmony_ci	ret = hns3_fill_skb_to_desc(ring, skb, DESC_TYPE_SKB);
15138c2ecf20Sopenharmony_ci	if (unlikely(ret <= 0))
15148c2ecf20Sopenharmony_ci		goto fill_err;
15158c2ecf20Sopenharmony_ci
15168c2ecf20Sopenharmony_ci	pre_ntu = ring->next_to_use ? (ring->next_to_use - 1) :
15178c2ecf20Sopenharmony_ci					(ring->desc_num - 1);
15188c2ecf20Sopenharmony_ci	ring->desc[pre_ntu].tx.bdtp_fe_sc_vld_ra_ri |=
15198c2ecf20Sopenharmony_ci				cpu_to_le16(BIT(HNS3_TXD_FE_B));
15208c2ecf20Sopenharmony_ci	trace_hns3_tx_desc(ring, pre_ntu);
15218c2ecf20Sopenharmony_ci
15228c2ecf20Sopenharmony_ci	/* Complete translate all packets */
15238c2ecf20Sopenharmony_ci	dev_queue = netdev_get_tx_queue(netdev, ring->queue_index);
15248c2ecf20Sopenharmony_ci	doorbell = __netdev_tx_sent_queue(dev_queue, skb->len,
15258c2ecf20Sopenharmony_ci					  netdev_xmit_more());
15268c2ecf20Sopenharmony_ci	hns3_tx_doorbell(ring, ret, doorbell);
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_ci	return NETDEV_TX_OK;
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_cifill_err:
15318c2ecf20Sopenharmony_ci	hns3_clear_desc(ring, next_to_use_head);
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_ciout_err_tx_ok:
15348c2ecf20Sopenharmony_ci	dev_kfree_skb_any(skb);
15358c2ecf20Sopenharmony_ci	hns3_tx_doorbell(ring, 0, !netdev_xmit_more());
15368c2ecf20Sopenharmony_ci	return NETDEV_TX_OK;
15378c2ecf20Sopenharmony_ci}
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_cistatic int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p)
15408c2ecf20Sopenharmony_ci{
15418c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
15428c2ecf20Sopenharmony_ci	struct sockaddr *mac_addr = p;
15438c2ecf20Sopenharmony_ci	int ret;
15448c2ecf20Sopenharmony_ci
15458c2ecf20Sopenharmony_ci	if (!mac_addr || !is_valid_ether_addr((const u8 *)mac_addr->sa_data))
15468c2ecf20Sopenharmony_ci		return -EADDRNOTAVAIL;
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	if (ether_addr_equal(netdev->dev_addr, mac_addr->sa_data)) {
15498c2ecf20Sopenharmony_ci		netdev_info(netdev, "already using mac address %pM\n",
15508c2ecf20Sopenharmony_ci			    mac_addr->sa_data);
15518c2ecf20Sopenharmony_ci		return 0;
15528c2ecf20Sopenharmony_ci	}
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	/* For VF device, if there is a perm_addr, then the user will not
15558c2ecf20Sopenharmony_ci	 * be allowed to change the address.
15568c2ecf20Sopenharmony_ci	 */
15578c2ecf20Sopenharmony_ci	if (!hns3_is_phys_func(h->pdev) &&
15588c2ecf20Sopenharmony_ci	    !is_zero_ether_addr(netdev->perm_addr)) {
15598c2ecf20Sopenharmony_ci		netdev_err(netdev, "has permanent MAC %pM, user MAC %pM not allow\n",
15608c2ecf20Sopenharmony_ci			   netdev->perm_addr, mac_addr->sa_data);
15618c2ecf20Sopenharmony_ci		return -EPERM;
15628c2ecf20Sopenharmony_ci	}
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci	ret = h->ae_algo->ops->set_mac_addr(h, mac_addr->sa_data, false);
15658c2ecf20Sopenharmony_ci	if (ret) {
15668c2ecf20Sopenharmony_ci		netdev_err(netdev, "set_mac_address fail, ret=%d!\n", ret);
15678c2ecf20Sopenharmony_ci		return ret;
15688c2ecf20Sopenharmony_ci	}
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci	ether_addr_copy(netdev->dev_addr, mac_addr->sa_data);
15718c2ecf20Sopenharmony_ci
15728c2ecf20Sopenharmony_ci	return 0;
15738c2ecf20Sopenharmony_ci}
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_cistatic int hns3_nic_do_ioctl(struct net_device *netdev,
15768c2ecf20Sopenharmony_ci			     struct ifreq *ifr, int cmd)
15778c2ecf20Sopenharmony_ci{
15788c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
15798c2ecf20Sopenharmony_ci
15808c2ecf20Sopenharmony_ci	if (!netif_running(netdev))
15818c2ecf20Sopenharmony_ci		return -EINVAL;
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci	if (!h->ae_algo->ops->do_ioctl)
15848c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	return h->ae_algo->ops->do_ioctl(h, ifr, cmd);
15878c2ecf20Sopenharmony_ci}
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_cistatic int hns3_nic_set_features(struct net_device *netdev,
15908c2ecf20Sopenharmony_ci				 netdev_features_t features)
15918c2ecf20Sopenharmony_ci{
15928c2ecf20Sopenharmony_ci	netdev_features_t changed = netdev->features ^ features;
15938c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
15948c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
15958c2ecf20Sopenharmony_ci	bool enable;
15968c2ecf20Sopenharmony_ci	int ret;
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci	if (changed & (NETIF_F_GRO_HW) && h->ae_algo->ops->set_gro_en) {
15998c2ecf20Sopenharmony_ci		enable = !!(features & NETIF_F_GRO_HW);
16008c2ecf20Sopenharmony_ci		ret = h->ae_algo->ops->set_gro_en(h, enable);
16018c2ecf20Sopenharmony_ci		if (ret)
16028c2ecf20Sopenharmony_ci			return ret;
16038c2ecf20Sopenharmony_ci	}
16048c2ecf20Sopenharmony_ci
16058c2ecf20Sopenharmony_ci	if ((changed & NETIF_F_HW_VLAN_CTAG_RX) &&
16068c2ecf20Sopenharmony_ci	    h->ae_algo->ops->enable_hw_strip_rxvtag) {
16078c2ecf20Sopenharmony_ci		enable = !!(features & NETIF_F_HW_VLAN_CTAG_RX);
16088c2ecf20Sopenharmony_ci		ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, enable);
16098c2ecf20Sopenharmony_ci		if (ret)
16108c2ecf20Sopenharmony_ci			return ret;
16118c2ecf20Sopenharmony_ci	}
16128c2ecf20Sopenharmony_ci
16138c2ecf20Sopenharmony_ci	if ((changed & NETIF_F_NTUPLE) && h->ae_algo->ops->enable_fd) {
16148c2ecf20Sopenharmony_ci		enable = !!(features & NETIF_F_NTUPLE);
16158c2ecf20Sopenharmony_ci		h->ae_algo->ops->enable_fd(h, enable);
16168c2ecf20Sopenharmony_ci	}
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci	netdev->features = features;
16198c2ecf20Sopenharmony_ci	return 0;
16208c2ecf20Sopenharmony_ci}
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_cistatic netdev_features_t hns3_features_check(struct sk_buff *skb,
16238c2ecf20Sopenharmony_ci					     struct net_device *dev,
16248c2ecf20Sopenharmony_ci					     netdev_features_t features)
16258c2ecf20Sopenharmony_ci{
16268c2ecf20Sopenharmony_ci#define HNS3_MAX_HDR_LEN	480U
16278c2ecf20Sopenharmony_ci#define HNS3_MAX_L4_HDR_LEN	60U
16288c2ecf20Sopenharmony_ci
16298c2ecf20Sopenharmony_ci	size_t len;
16308c2ecf20Sopenharmony_ci
16318c2ecf20Sopenharmony_ci	if (skb->ip_summed != CHECKSUM_PARTIAL)
16328c2ecf20Sopenharmony_ci		return features;
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_ci	if (skb->encapsulation)
16358c2ecf20Sopenharmony_ci		len = skb_inner_transport_header(skb) - skb->data;
16368c2ecf20Sopenharmony_ci	else
16378c2ecf20Sopenharmony_ci		len = skb_transport_header(skb) - skb->data;
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci	/* Assume L4 is 60 byte as TCP is the only protocol with a
16408c2ecf20Sopenharmony_ci	 * a flexible value, and it's max len is 60 bytes.
16418c2ecf20Sopenharmony_ci	 */
16428c2ecf20Sopenharmony_ci	len += HNS3_MAX_L4_HDR_LEN;
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_ci	/* Hardware only supports checksum on the skb with a max header
16458c2ecf20Sopenharmony_ci	 * len of 480 bytes.
16468c2ecf20Sopenharmony_ci	 */
16478c2ecf20Sopenharmony_ci	if (len > HNS3_MAX_HDR_LEN)
16488c2ecf20Sopenharmony_ci		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ci	return features;
16518c2ecf20Sopenharmony_ci}
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_cistatic void hns3_nic_get_stats64(struct net_device *netdev,
16548c2ecf20Sopenharmony_ci				 struct rtnl_link_stats64 *stats)
16558c2ecf20Sopenharmony_ci{
16568c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
16578c2ecf20Sopenharmony_ci	int queue_num = priv->ae_handle->kinfo.num_tqps;
16588c2ecf20Sopenharmony_ci	struct hnae3_handle *handle = priv->ae_handle;
16598c2ecf20Sopenharmony_ci	struct hns3_enet_ring *ring;
16608c2ecf20Sopenharmony_ci	u64 rx_length_errors = 0;
16618c2ecf20Sopenharmony_ci	u64 rx_crc_errors = 0;
16628c2ecf20Sopenharmony_ci	u64 rx_multicast = 0;
16638c2ecf20Sopenharmony_ci	unsigned int start;
16648c2ecf20Sopenharmony_ci	u64 tx_errors = 0;
16658c2ecf20Sopenharmony_ci	u64 rx_errors = 0;
16668c2ecf20Sopenharmony_ci	unsigned int idx;
16678c2ecf20Sopenharmony_ci	u64 tx_bytes = 0;
16688c2ecf20Sopenharmony_ci	u64 rx_bytes = 0;
16698c2ecf20Sopenharmony_ci	u64 tx_pkts = 0;
16708c2ecf20Sopenharmony_ci	u64 rx_pkts = 0;
16718c2ecf20Sopenharmony_ci	u64 tx_drop = 0;
16728c2ecf20Sopenharmony_ci	u64 rx_drop = 0;
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci	if (test_bit(HNS3_NIC_STATE_DOWN, &priv->state))
16758c2ecf20Sopenharmony_ci		return;
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci	handle->ae_algo->ops->update_stats(handle, &netdev->stats);
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ci	for (idx = 0; idx < queue_num; idx++) {
16808c2ecf20Sopenharmony_ci		/* fetch the tx stats */
16818c2ecf20Sopenharmony_ci		ring = &priv->ring[idx];
16828c2ecf20Sopenharmony_ci		do {
16838c2ecf20Sopenharmony_ci			start = u64_stats_fetch_begin_irq(&ring->syncp);
16848c2ecf20Sopenharmony_ci			tx_bytes += ring->stats.tx_bytes;
16858c2ecf20Sopenharmony_ci			tx_pkts += ring->stats.tx_pkts;
16868c2ecf20Sopenharmony_ci			tx_drop += ring->stats.sw_err_cnt;
16878c2ecf20Sopenharmony_ci			tx_drop += ring->stats.tx_vlan_err;
16888c2ecf20Sopenharmony_ci			tx_drop += ring->stats.tx_l4_proto_err;
16898c2ecf20Sopenharmony_ci			tx_drop += ring->stats.tx_l2l3l4_err;
16908c2ecf20Sopenharmony_ci			tx_drop += ring->stats.tx_tso_err;
16918c2ecf20Sopenharmony_ci			tx_drop += ring->stats.over_max_recursion;
16928c2ecf20Sopenharmony_ci			tx_drop += ring->stats.hw_limitation;
16938c2ecf20Sopenharmony_ci			tx_errors += ring->stats.sw_err_cnt;
16948c2ecf20Sopenharmony_ci			tx_errors += ring->stats.tx_vlan_err;
16958c2ecf20Sopenharmony_ci			tx_errors += ring->stats.tx_l4_proto_err;
16968c2ecf20Sopenharmony_ci			tx_errors += ring->stats.tx_l2l3l4_err;
16978c2ecf20Sopenharmony_ci			tx_errors += ring->stats.tx_tso_err;
16988c2ecf20Sopenharmony_ci			tx_errors += ring->stats.over_max_recursion;
16998c2ecf20Sopenharmony_ci			tx_errors += ring->stats.hw_limitation;
17008c2ecf20Sopenharmony_ci		} while (u64_stats_fetch_retry_irq(&ring->syncp, start));
17018c2ecf20Sopenharmony_ci
17028c2ecf20Sopenharmony_ci		/* fetch the rx stats */
17038c2ecf20Sopenharmony_ci		ring = &priv->ring[idx + queue_num];
17048c2ecf20Sopenharmony_ci		do {
17058c2ecf20Sopenharmony_ci			start = u64_stats_fetch_begin_irq(&ring->syncp);
17068c2ecf20Sopenharmony_ci			rx_bytes += ring->stats.rx_bytes;
17078c2ecf20Sopenharmony_ci			rx_pkts += ring->stats.rx_pkts;
17088c2ecf20Sopenharmony_ci			rx_drop += ring->stats.l2_err;
17098c2ecf20Sopenharmony_ci			rx_errors += ring->stats.l2_err;
17108c2ecf20Sopenharmony_ci			rx_errors += ring->stats.l3l4_csum_err;
17118c2ecf20Sopenharmony_ci			rx_crc_errors += ring->stats.l2_err;
17128c2ecf20Sopenharmony_ci			rx_multicast += ring->stats.rx_multicast;
17138c2ecf20Sopenharmony_ci			rx_length_errors += ring->stats.err_pkt_len;
17148c2ecf20Sopenharmony_ci		} while (u64_stats_fetch_retry_irq(&ring->syncp, start));
17158c2ecf20Sopenharmony_ci	}
17168c2ecf20Sopenharmony_ci
17178c2ecf20Sopenharmony_ci	stats->tx_bytes = tx_bytes;
17188c2ecf20Sopenharmony_ci	stats->tx_packets = tx_pkts;
17198c2ecf20Sopenharmony_ci	stats->rx_bytes = rx_bytes;
17208c2ecf20Sopenharmony_ci	stats->rx_packets = rx_pkts;
17218c2ecf20Sopenharmony_ci
17228c2ecf20Sopenharmony_ci	stats->rx_errors = rx_errors;
17238c2ecf20Sopenharmony_ci	stats->multicast = rx_multicast;
17248c2ecf20Sopenharmony_ci	stats->rx_length_errors = rx_length_errors;
17258c2ecf20Sopenharmony_ci	stats->rx_crc_errors = rx_crc_errors;
17268c2ecf20Sopenharmony_ci	stats->rx_missed_errors = netdev->stats.rx_missed_errors;
17278c2ecf20Sopenharmony_ci
17288c2ecf20Sopenharmony_ci	stats->tx_errors = tx_errors;
17298c2ecf20Sopenharmony_ci	stats->rx_dropped = rx_drop;
17308c2ecf20Sopenharmony_ci	stats->tx_dropped = tx_drop;
17318c2ecf20Sopenharmony_ci	stats->collisions = netdev->stats.collisions;
17328c2ecf20Sopenharmony_ci	stats->rx_over_errors = netdev->stats.rx_over_errors;
17338c2ecf20Sopenharmony_ci	stats->rx_frame_errors = netdev->stats.rx_frame_errors;
17348c2ecf20Sopenharmony_ci	stats->rx_fifo_errors = netdev->stats.rx_fifo_errors;
17358c2ecf20Sopenharmony_ci	stats->tx_aborted_errors = netdev->stats.tx_aborted_errors;
17368c2ecf20Sopenharmony_ci	stats->tx_carrier_errors = netdev->stats.tx_carrier_errors;
17378c2ecf20Sopenharmony_ci	stats->tx_fifo_errors = netdev->stats.tx_fifo_errors;
17388c2ecf20Sopenharmony_ci	stats->tx_heartbeat_errors = netdev->stats.tx_heartbeat_errors;
17398c2ecf20Sopenharmony_ci	stats->tx_window_errors = netdev->stats.tx_window_errors;
17408c2ecf20Sopenharmony_ci	stats->rx_compressed = netdev->stats.rx_compressed;
17418c2ecf20Sopenharmony_ci	stats->tx_compressed = netdev->stats.tx_compressed;
17428c2ecf20Sopenharmony_ci}
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_cistatic int hns3_setup_tc(struct net_device *netdev, void *type_data)
17458c2ecf20Sopenharmony_ci{
17468c2ecf20Sopenharmony_ci	struct tc_mqprio_qopt_offload *mqprio_qopt = type_data;
17478c2ecf20Sopenharmony_ci	u8 *prio_tc = mqprio_qopt->qopt.prio_tc_map;
17488c2ecf20Sopenharmony_ci	struct hnae3_knic_private_info *kinfo;
17498c2ecf20Sopenharmony_ci	u8 tc = mqprio_qopt->qopt.num_tc;
17508c2ecf20Sopenharmony_ci	u16 mode = mqprio_qopt->mode;
17518c2ecf20Sopenharmony_ci	u8 hw = mqprio_qopt->qopt.hw;
17528c2ecf20Sopenharmony_ci	struct hnae3_handle *h;
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_ci	if (!((hw == TC_MQPRIO_HW_OFFLOAD_TCS &&
17558c2ecf20Sopenharmony_ci	       mode == TC_MQPRIO_MODE_CHANNEL) || (!hw && tc == 0)))
17568c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
17578c2ecf20Sopenharmony_ci
17588c2ecf20Sopenharmony_ci	if (tc > HNAE3_MAX_TC)
17598c2ecf20Sopenharmony_ci		return -EINVAL;
17608c2ecf20Sopenharmony_ci
17618c2ecf20Sopenharmony_ci	if (!netdev)
17628c2ecf20Sopenharmony_ci		return -EINVAL;
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_ci	h = hns3_get_handle(netdev);
17658c2ecf20Sopenharmony_ci	kinfo = &h->kinfo;
17668c2ecf20Sopenharmony_ci
17678c2ecf20Sopenharmony_ci	netif_dbg(h, drv, netdev, "setup tc: num_tc=%u\n", tc);
17688c2ecf20Sopenharmony_ci
17698c2ecf20Sopenharmony_ci	return (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ?
17708c2ecf20Sopenharmony_ci		kinfo->dcb_ops->setup_tc(h, tc ? tc : 1, prio_tc) : -EOPNOTSUPP;
17718c2ecf20Sopenharmony_ci}
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_cistatic int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type,
17748c2ecf20Sopenharmony_ci			     void *type_data)
17758c2ecf20Sopenharmony_ci{
17768c2ecf20Sopenharmony_ci	if (type != TC_SETUP_QDISC_MQPRIO)
17778c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
17788c2ecf20Sopenharmony_ci
17798c2ecf20Sopenharmony_ci	return hns3_setup_tc(dev, type_data);
17808c2ecf20Sopenharmony_ci}
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_cistatic int hns3_vlan_rx_add_vid(struct net_device *netdev,
17838c2ecf20Sopenharmony_ci				__be16 proto, u16 vid)
17848c2ecf20Sopenharmony_ci{
17858c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
17868c2ecf20Sopenharmony_ci	int ret = -EIO;
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->set_vlan_filter)
17898c2ecf20Sopenharmony_ci		ret = h->ae_algo->ops->set_vlan_filter(h, proto, vid, false);
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ci	return ret;
17928c2ecf20Sopenharmony_ci}
17938c2ecf20Sopenharmony_ci
17948c2ecf20Sopenharmony_cistatic int hns3_vlan_rx_kill_vid(struct net_device *netdev,
17958c2ecf20Sopenharmony_ci				 __be16 proto, u16 vid)
17968c2ecf20Sopenharmony_ci{
17978c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
17988c2ecf20Sopenharmony_ci	int ret = -EIO;
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->set_vlan_filter)
18018c2ecf20Sopenharmony_ci		ret = h->ae_algo->ops->set_vlan_filter(h, proto, vid, true);
18028c2ecf20Sopenharmony_ci
18038c2ecf20Sopenharmony_ci	return ret;
18048c2ecf20Sopenharmony_ci}
18058c2ecf20Sopenharmony_ci
18068c2ecf20Sopenharmony_cistatic int hns3_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
18078c2ecf20Sopenharmony_ci				u8 qos, __be16 vlan_proto)
18088c2ecf20Sopenharmony_ci{
18098c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
18108c2ecf20Sopenharmony_ci	int ret = -EIO;
18118c2ecf20Sopenharmony_ci
18128c2ecf20Sopenharmony_ci	netif_dbg(h, drv, netdev,
18138c2ecf20Sopenharmony_ci		  "set vf vlan: vf=%d, vlan=%u, qos=%u, vlan_proto=0x%x\n",
18148c2ecf20Sopenharmony_ci		  vf, vlan, qos, ntohs(vlan_proto));
18158c2ecf20Sopenharmony_ci
18168c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->set_vf_vlan_filter)
18178c2ecf20Sopenharmony_ci		ret = h->ae_algo->ops->set_vf_vlan_filter(h, vf, vlan,
18188c2ecf20Sopenharmony_ci							  qos, vlan_proto);
18198c2ecf20Sopenharmony_ci
18208c2ecf20Sopenharmony_ci	return ret;
18218c2ecf20Sopenharmony_ci}
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_cistatic int hns3_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable)
18248c2ecf20Sopenharmony_ci{
18258c2ecf20Sopenharmony_ci	struct hnae3_handle *handle = hns3_get_handle(netdev);
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ci	if (hns3_nic_resetting(netdev))
18288c2ecf20Sopenharmony_ci		return -EBUSY;
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_ci	if (!handle->ae_algo->ops->set_vf_spoofchk)
18318c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_ci	return handle->ae_algo->ops->set_vf_spoofchk(handle, vf, enable);
18348c2ecf20Sopenharmony_ci}
18358c2ecf20Sopenharmony_ci
18368c2ecf20Sopenharmony_cistatic int hns3_set_vf_trust(struct net_device *netdev, int vf, bool enable)
18378c2ecf20Sopenharmony_ci{
18388c2ecf20Sopenharmony_ci	struct hnae3_handle *handle = hns3_get_handle(netdev);
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci	if (!handle->ae_algo->ops->set_vf_trust)
18418c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
18428c2ecf20Sopenharmony_ci
18438c2ecf20Sopenharmony_ci	return handle->ae_algo->ops->set_vf_trust(handle, vf, enable);
18448c2ecf20Sopenharmony_ci}
18458c2ecf20Sopenharmony_ci
18468c2ecf20Sopenharmony_cistatic int hns3_nic_change_mtu(struct net_device *netdev, int new_mtu)
18478c2ecf20Sopenharmony_ci{
18488c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
18498c2ecf20Sopenharmony_ci	int ret;
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ci	if (hns3_nic_resetting(netdev))
18528c2ecf20Sopenharmony_ci		return -EBUSY;
18538c2ecf20Sopenharmony_ci
18548c2ecf20Sopenharmony_ci	if (!h->ae_algo->ops->set_mtu)
18558c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_ci	netif_dbg(h, drv, netdev,
18588c2ecf20Sopenharmony_ci		  "change mtu from %u to %d\n", netdev->mtu, new_mtu);
18598c2ecf20Sopenharmony_ci
18608c2ecf20Sopenharmony_ci	ret = h->ae_algo->ops->set_mtu(h, new_mtu);
18618c2ecf20Sopenharmony_ci	if (ret)
18628c2ecf20Sopenharmony_ci		netdev_err(netdev, "failed to change MTU in hardware %d\n",
18638c2ecf20Sopenharmony_ci			   ret);
18648c2ecf20Sopenharmony_ci	else
18658c2ecf20Sopenharmony_ci		netdev->mtu = new_mtu;
18668c2ecf20Sopenharmony_ci
18678c2ecf20Sopenharmony_ci	return ret;
18688c2ecf20Sopenharmony_ci}
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_cistatic bool hns3_get_tx_timeo_queue_info(struct net_device *ndev)
18718c2ecf20Sopenharmony_ci{
18728c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
18738c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(ndev);
18748c2ecf20Sopenharmony_ci	struct hns3_enet_ring *tx_ring;
18758c2ecf20Sopenharmony_ci	struct napi_struct *napi;
18768c2ecf20Sopenharmony_ci	int timeout_queue = 0;
18778c2ecf20Sopenharmony_ci	int hw_head, hw_tail;
18788c2ecf20Sopenharmony_ci	int fbd_num, fbd_oft;
18798c2ecf20Sopenharmony_ci	int ebd_num, ebd_oft;
18808c2ecf20Sopenharmony_ci	int bd_num, bd_err;
18818c2ecf20Sopenharmony_ci	int ring_en, tc;
18828c2ecf20Sopenharmony_ci	int i;
18838c2ecf20Sopenharmony_ci
18848c2ecf20Sopenharmony_ci	/* Find the stopped queue the same way the stack does */
18858c2ecf20Sopenharmony_ci	for (i = 0; i < ndev->num_tx_queues; i++) {
18868c2ecf20Sopenharmony_ci		struct netdev_queue *q;
18878c2ecf20Sopenharmony_ci		unsigned long trans_start;
18888c2ecf20Sopenharmony_ci
18898c2ecf20Sopenharmony_ci		q = netdev_get_tx_queue(ndev, i);
18908c2ecf20Sopenharmony_ci		trans_start = q->trans_start;
18918c2ecf20Sopenharmony_ci		if (netif_xmit_stopped(q) &&
18928c2ecf20Sopenharmony_ci		    time_after(jiffies,
18938c2ecf20Sopenharmony_ci			       (trans_start + ndev->watchdog_timeo))) {
18948c2ecf20Sopenharmony_ci			timeout_queue = i;
18958c2ecf20Sopenharmony_ci			netdev_info(ndev, "queue state: 0x%lx, delta msecs: %u\n",
18968c2ecf20Sopenharmony_ci				    q->state,
18978c2ecf20Sopenharmony_ci				    jiffies_to_msecs(jiffies - trans_start));
18988c2ecf20Sopenharmony_ci			break;
18998c2ecf20Sopenharmony_ci		}
19008c2ecf20Sopenharmony_ci	}
19018c2ecf20Sopenharmony_ci
19028c2ecf20Sopenharmony_ci	if (i == ndev->num_tx_queues) {
19038c2ecf20Sopenharmony_ci		netdev_info(ndev,
19048c2ecf20Sopenharmony_ci			    "no netdev TX timeout queue found, timeout count: %llu\n",
19058c2ecf20Sopenharmony_ci			    priv->tx_timeout_count);
19068c2ecf20Sopenharmony_ci		return false;
19078c2ecf20Sopenharmony_ci	}
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_ci	priv->tx_timeout_count++;
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	tx_ring = &priv->ring[timeout_queue];
19128c2ecf20Sopenharmony_ci	napi = &tx_ring->tqp_vector->napi;
19138c2ecf20Sopenharmony_ci
19148c2ecf20Sopenharmony_ci	netdev_info(ndev,
19158c2ecf20Sopenharmony_ci		    "tx_timeout count: %llu, queue id: %d, SW_NTU: 0x%x, SW_NTC: 0x%x, napi state: %lu\n",
19168c2ecf20Sopenharmony_ci		    priv->tx_timeout_count, timeout_queue, tx_ring->next_to_use,
19178c2ecf20Sopenharmony_ci		    tx_ring->next_to_clean, napi->state);
19188c2ecf20Sopenharmony_ci
19198c2ecf20Sopenharmony_ci	netdev_info(ndev,
19208c2ecf20Sopenharmony_ci		    "tx_pkts: %llu, tx_bytes: %llu, sw_err_cnt: %llu, tx_pending: %d\n",
19218c2ecf20Sopenharmony_ci		    tx_ring->stats.tx_pkts, tx_ring->stats.tx_bytes,
19228c2ecf20Sopenharmony_ci		    tx_ring->stats.sw_err_cnt, tx_ring->pending_buf);
19238c2ecf20Sopenharmony_ci
19248c2ecf20Sopenharmony_ci	netdev_info(ndev,
19258c2ecf20Sopenharmony_ci		    "seg_pkt_cnt: %llu, tx_more: %llu, restart_queue: %llu, tx_busy: %llu\n",
19268c2ecf20Sopenharmony_ci		    tx_ring->stats.seg_pkt_cnt, tx_ring->stats.tx_more,
19278c2ecf20Sopenharmony_ci		    tx_ring->stats.restart_queue, tx_ring->stats.tx_busy);
19288c2ecf20Sopenharmony_ci
19298c2ecf20Sopenharmony_ci	/* When mac received many pause frames continuous, it's unable to send
19308c2ecf20Sopenharmony_ci	 * packets, which may cause tx timeout
19318c2ecf20Sopenharmony_ci	 */
19328c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->get_mac_stats) {
19338c2ecf20Sopenharmony_ci		struct hns3_mac_stats mac_stats;
19348c2ecf20Sopenharmony_ci
19358c2ecf20Sopenharmony_ci		h->ae_algo->ops->get_mac_stats(h, &mac_stats);
19368c2ecf20Sopenharmony_ci		netdev_info(ndev, "tx_pause_cnt: %llu, rx_pause_cnt: %llu\n",
19378c2ecf20Sopenharmony_ci			    mac_stats.tx_pause_cnt, mac_stats.rx_pause_cnt);
19388c2ecf20Sopenharmony_ci	}
19398c2ecf20Sopenharmony_ci
19408c2ecf20Sopenharmony_ci	hw_head = readl_relaxed(tx_ring->tqp->io_base +
19418c2ecf20Sopenharmony_ci				HNS3_RING_TX_RING_HEAD_REG);
19428c2ecf20Sopenharmony_ci	hw_tail = readl_relaxed(tx_ring->tqp->io_base +
19438c2ecf20Sopenharmony_ci				HNS3_RING_TX_RING_TAIL_REG);
19448c2ecf20Sopenharmony_ci	fbd_num = readl_relaxed(tx_ring->tqp->io_base +
19458c2ecf20Sopenharmony_ci				HNS3_RING_TX_RING_FBDNUM_REG);
19468c2ecf20Sopenharmony_ci	fbd_oft = readl_relaxed(tx_ring->tqp->io_base +
19478c2ecf20Sopenharmony_ci				HNS3_RING_TX_RING_OFFSET_REG);
19488c2ecf20Sopenharmony_ci	ebd_num = readl_relaxed(tx_ring->tqp->io_base +
19498c2ecf20Sopenharmony_ci				HNS3_RING_TX_RING_EBDNUM_REG);
19508c2ecf20Sopenharmony_ci	ebd_oft = readl_relaxed(tx_ring->tqp->io_base +
19518c2ecf20Sopenharmony_ci				HNS3_RING_TX_RING_EBD_OFFSET_REG);
19528c2ecf20Sopenharmony_ci	bd_num = readl_relaxed(tx_ring->tqp->io_base +
19538c2ecf20Sopenharmony_ci			       HNS3_RING_TX_RING_BD_NUM_REG);
19548c2ecf20Sopenharmony_ci	bd_err = readl_relaxed(tx_ring->tqp->io_base +
19558c2ecf20Sopenharmony_ci			       HNS3_RING_TX_RING_BD_ERR_REG);
19568c2ecf20Sopenharmony_ci	ring_en = readl_relaxed(tx_ring->tqp->io_base + HNS3_RING_EN_REG);
19578c2ecf20Sopenharmony_ci	tc = readl_relaxed(tx_ring->tqp->io_base + HNS3_RING_TX_RING_TC_REG);
19588c2ecf20Sopenharmony_ci
19598c2ecf20Sopenharmony_ci	netdev_info(ndev,
19608c2ecf20Sopenharmony_ci		    "BD_NUM: 0x%x HW_HEAD: 0x%x, HW_TAIL: 0x%x, BD_ERR: 0x%x, INT: 0x%x\n",
19618c2ecf20Sopenharmony_ci		    bd_num, hw_head, hw_tail, bd_err,
19628c2ecf20Sopenharmony_ci		    readl(tx_ring->tqp_vector->mask_addr));
19638c2ecf20Sopenharmony_ci	netdev_info(ndev,
19648c2ecf20Sopenharmony_ci		    "RING_EN: 0x%x, TC: 0x%x, FBD_NUM: 0x%x FBD_OFT: 0x%x, EBD_NUM: 0x%x, EBD_OFT: 0x%x\n",
19658c2ecf20Sopenharmony_ci		    ring_en, tc, fbd_num, fbd_oft, ebd_num, ebd_oft);
19668c2ecf20Sopenharmony_ci
19678c2ecf20Sopenharmony_ci	return true;
19688c2ecf20Sopenharmony_ci}
19698c2ecf20Sopenharmony_ci
19708c2ecf20Sopenharmony_cistatic void hns3_nic_net_timeout(struct net_device *ndev, unsigned int txqueue)
19718c2ecf20Sopenharmony_ci{
19728c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
19738c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
19748c2ecf20Sopenharmony_ci
19758c2ecf20Sopenharmony_ci	if (!hns3_get_tx_timeo_queue_info(ndev))
19768c2ecf20Sopenharmony_ci		return;
19778c2ecf20Sopenharmony_ci
19788c2ecf20Sopenharmony_ci	/* request the reset, and let the hclge to determine
19798c2ecf20Sopenharmony_ci	 * which reset level should be done
19808c2ecf20Sopenharmony_ci	 */
19818c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->reset_event)
19828c2ecf20Sopenharmony_ci		h->ae_algo->ops->reset_event(h->pdev, h);
19838c2ecf20Sopenharmony_ci}
19848c2ecf20Sopenharmony_ci
19858c2ecf20Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
19868c2ecf20Sopenharmony_cistatic int hns3_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
19878c2ecf20Sopenharmony_ci			      u16 rxq_index, u32 flow_id)
19888c2ecf20Sopenharmony_ci{
19898c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(dev);
19908c2ecf20Sopenharmony_ci	struct flow_keys fkeys;
19918c2ecf20Sopenharmony_ci
19928c2ecf20Sopenharmony_ci	if (!h->ae_algo->ops->add_arfs_entry)
19938c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ci	if (skb->encapsulation)
19968c2ecf20Sopenharmony_ci		return -EPROTONOSUPPORT;
19978c2ecf20Sopenharmony_ci
19988c2ecf20Sopenharmony_ci	if (!skb_flow_dissect_flow_keys(skb, &fkeys, 0))
19998c2ecf20Sopenharmony_ci		return -EPROTONOSUPPORT;
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_ci	if ((fkeys.basic.n_proto != htons(ETH_P_IP) &&
20028c2ecf20Sopenharmony_ci	     fkeys.basic.n_proto != htons(ETH_P_IPV6)) ||
20038c2ecf20Sopenharmony_ci	    (fkeys.basic.ip_proto != IPPROTO_TCP &&
20048c2ecf20Sopenharmony_ci	     fkeys.basic.ip_proto != IPPROTO_UDP))
20058c2ecf20Sopenharmony_ci		return -EPROTONOSUPPORT;
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	return h->ae_algo->ops->add_arfs_entry(h, rxq_index, flow_id, &fkeys);
20088c2ecf20Sopenharmony_ci}
20098c2ecf20Sopenharmony_ci#endif
20108c2ecf20Sopenharmony_ci
20118c2ecf20Sopenharmony_cistatic int hns3_nic_get_vf_config(struct net_device *ndev, int vf,
20128c2ecf20Sopenharmony_ci				  struct ifla_vf_info *ivf)
20138c2ecf20Sopenharmony_ci{
20148c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(ndev);
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci	if (!h->ae_algo->ops->get_vf_config)
20178c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
20188c2ecf20Sopenharmony_ci
20198c2ecf20Sopenharmony_ci	return h->ae_algo->ops->get_vf_config(h, vf, ivf);
20208c2ecf20Sopenharmony_ci}
20218c2ecf20Sopenharmony_ci
20228c2ecf20Sopenharmony_cistatic int hns3_nic_set_vf_link_state(struct net_device *ndev, int vf,
20238c2ecf20Sopenharmony_ci				      int link_state)
20248c2ecf20Sopenharmony_ci{
20258c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(ndev);
20268c2ecf20Sopenharmony_ci
20278c2ecf20Sopenharmony_ci	if (!h->ae_algo->ops->set_vf_link_state)
20288c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
20298c2ecf20Sopenharmony_ci
20308c2ecf20Sopenharmony_ci	return h->ae_algo->ops->set_vf_link_state(h, vf, link_state);
20318c2ecf20Sopenharmony_ci}
20328c2ecf20Sopenharmony_ci
20338c2ecf20Sopenharmony_cistatic int hns3_nic_set_vf_rate(struct net_device *ndev, int vf,
20348c2ecf20Sopenharmony_ci				int min_tx_rate, int max_tx_rate)
20358c2ecf20Sopenharmony_ci{
20368c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(ndev);
20378c2ecf20Sopenharmony_ci
20388c2ecf20Sopenharmony_ci	if (!h->ae_algo->ops->set_vf_rate)
20398c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
20408c2ecf20Sopenharmony_ci
20418c2ecf20Sopenharmony_ci	return h->ae_algo->ops->set_vf_rate(h, vf, min_tx_rate, max_tx_rate,
20428c2ecf20Sopenharmony_ci					    false);
20438c2ecf20Sopenharmony_ci}
20448c2ecf20Sopenharmony_ci
20458c2ecf20Sopenharmony_cistatic int hns3_nic_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
20468c2ecf20Sopenharmony_ci{
20478c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
20488c2ecf20Sopenharmony_ci
20498c2ecf20Sopenharmony_ci	if (!h->ae_algo->ops->set_vf_mac)
20508c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci	if (is_multicast_ether_addr(mac)) {
20538c2ecf20Sopenharmony_ci		netdev_err(netdev,
20548c2ecf20Sopenharmony_ci			   "Invalid MAC:%pM specified. Could not set MAC\n",
20558c2ecf20Sopenharmony_ci			   mac);
20568c2ecf20Sopenharmony_ci		return -EINVAL;
20578c2ecf20Sopenharmony_ci	}
20588c2ecf20Sopenharmony_ci
20598c2ecf20Sopenharmony_ci	return h->ae_algo->ops->set_vf_mac(h, vf_id, mac);
20608c2ecf20Sopenharmony_ci}
20618c2ecf20Sopenharmony_ci
20628c2ecf20Sopenharmony_cistatic const struct net_device_ops hns3_nic_netdev_ops = {
20638c2ecf20Sopenharmony_ci	.ndo_open		= hns3_nic_net_open,
20648c2ecf20Sopenharmony_ci	.ndo_stop		= hns3_nic_net_stop,
20658c2ecf20Sopenharmony_ci	.ndo_start_xmit		= hns3_nic_net_xmit,
20668c2ecf20Sopenharmony_ci	.ndo_tx_timeout		= hns3_nic_net_timeout,
20678c2ecf20Sopenharmony_ci	.ndo_set_mac_address	= hns3_nic_net_set_mac_address,
20688c2ecf20Sopenharmony_ci	.ndo_do_ioctl		= hns3_nic_do_ioctl,
20698c2ecf20Sopenharmony_ci	.ndo_change_mtu		= hns3_nic_change_mtu,
20708c2ecf20Sopenharmony_ci	.ndo_set_features	= hns3_nic_set_features,
20718c2ecf20Sopenharmony_ci	.ndo_features_check	= hns3_features_check,
20728c2ecf20Sopenharmony_ci	.ndo_get_stats64	= hns3_nic_get_stats64,
20738c2ecf20Sopenharmony_ci	.ndo_setup_tc		= hns3_nic_setup_tc,
20748c2ecf20Sopenharmony_ci	.ndo_set_rx_mode	= hns3_nic_set_rx_mode,
20758c2ecf20Sopenharmony_ci	.ndo_vlan_rx_add_vid	= hns3_vlan_rx_add_vid,
20768c2ecf20Sopenharmony_ci	.ndo_vlan_rx_kill_vid	= hns3_vlan_rx_kill_vid,
20778c2ecf20Sopenharmony_ci	.ndo_set_vf_vlan	= hns3_ndo_set_vf_vlan,
20788c2ecf20Sopenharmony_ci	.ndo_set_vf_spoofchk	= hns3_set_vf_spoofchk,
20798c2ecf20Sopenharmony_ci	.ndo_set_vf_trust	= hns3_set_vf_trust,
20808c2ecf20Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
20818c2ecf20Sopenharmony_ci	.ndo_rx_flow_steer	= hns3_rx_flow_steer,
20828c2ecf20Sopenharmony_ci#endif
20838c2ecf20Sopenharmony_ci	.ndo_get_vf_config	= hns3_nic_get_vf_config,
20848c2ecf20Sopenharmony_ci	.ndo_set_vf_link_state	= hns3_nic_set_vf_link_state,
20858c2ecf20Sopenharmony_ci	.ndo_set_vf_rate	= hns3_nic_set_vf_rate,
20868c2ecf20Sopenharmony_ci	.ndo_set_vf_mac		= hns3_nic_set_vf_mac,
20878c2ecf20Sopenharmony_ci};
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_cibool hns3_is_phys_func(struct pci_dev *pdev)
20908c2ecf20Sopenharmony_ci{
20918c2ecf20Sopenharmony_ci	u32 dev_id = pdev->device;
20928c2ecf20Sopenharmony_ci
20938c2ecf20Sopenharmony_ci	switch (dev_id) {
20948c2ecf20Sopenharmony_ci	case HNAE3_DEV_ID_GE:
20958c2ecf20Sopenharmony_ci	case HNAE3_DEV_ID_25GE:
20968c2ecf20Sopenharmony_ci	case HNAE3_DEV_ID_25GE_RDMA:
20978c2ecf20Sopenharmony_ci	case HNAE3_DEV_ID_25GE_RDMA_MACSEC:
20988c2ecf20Sopenharmony_ci	case HNAE3_DEV_ID_50GE_RDMA:
20998c2ecf20Sopenharmony_ci	case HNAE3_DEV_ID_50GE_RDMA_MACSEC:
21008c2ecf20Sopenharmony_ci	case HNAE3_DEV_ID_100G_RDMA_MACSEC:
21018c2ecf20Sopenharmony_ci	case HNAE3_DEV_ID_200G_RDMA:
21028c2ecf20Sopenharmony_ci		return true;
21038c2ecf20Sopenharmony_ci	case HNAE3_DEV_ID_VF:
21048c2ecf20Sopenharmony_ci	case HNAE3_DEV_ID_RDMA_DCB_PFC_VF:
21058c2ecf20Sopenharmony_ci		return false;
21068c2ecf20Sopenharmony_ci	default:
21078c2ecf20Sopenharmony_ci		dev_warn(&pdev->dev, "un-recognized pci device-id %u",
21088c2ecf20Sopenharmony_ci			 dev_id);
21098c2ecf20Sopenharmony_ci	}
21108c2ecf20Sopenharmony_ci
21118c2ecf20Sopenharmony_ci	return false;
21128c2ecf20Sopenharmony_ci}
21138c2ecf20Sopenharmony_ci
21148c2ecf20Sopenharmony_cistatic void hns3_disable_sriov(struct pci_dev *pdev)
21158c2ecf20Sopenharmony_ci{
21168c2ecf20Sopenharmony_ci	/* If our VFs are assigned we cannot shut down SR-IOV
21178c2ecf20Sopenharmony_ci	 * without causing issues, so just leave the hardware
21188c2ecf20Sopenharmony_ci	 * available but disabled
21198c2ecf20Sopenharmony_ci	 */
21208c2ecf20Sopenharmony_ci	if (pci_vfs_assigned(pdev)) {
21218c2ecf20Sopenharmony_ci		dev_warn(&pdev->dev,
21228c2ecf20Sopenharmony_ci			 "disabling driver while VFs are assigned\n");
21238c2ecf20Sopenharmony_ci		return;
21248c2ecf20Sopenharmony_ci	}
21258c2ecf20Sopenharmony_ci
21268c2ecf20Sopenharmony_ci	pci_disable_sriov(pdev);
21278c2ecf20Sopenharmony_ci}
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_ci/* hns3_probe - Device initialization routine
21308c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
21318c2ecf20Sopenharmony_ci * @ent: entry in hns3_pci_tbl
21328c2ecf20Sopenharmony_ci *
21338c2ecf20Sopenharmony_ci * hns3_probe initializes a PF identified by a pci_dev structure.
21348c2ecf20Sopenharmony_ci * The OS initialization, configuring of the PF private structure,
21358c2ecf20Sopenharmony_ci * and a hardware reset occur.
21368c2ecf20Sopenharmony_ci *
21378c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
21388c2ecf20Sopenharmony_ci */
21398c2ecf20Sopenharmony_cistatic int hns3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
21408c2ecf20Sopenharmony_ci{
21418c2ecf20Sopenharmony_ci	struct hnae3_ae_dev *ae_dev;
21428c2ecf20Sopenharmony_ci	int ret;
21438c2ecf20Sopenharmony_ci
21448c2ecf20Sopenharmony_ci	ae_dev = devm_kzalloc(&pdev->dev, sizeof(*ae_dev), GFP_KERNEL);
21458c2ecf20Sopenharmony_ci	if (!ae_dev)
21468c2ecf20Sopenharmony_ci		return -ENOMEM;
21478c2ecf20Sopenharmony_ci
21488c2ecf20Sopenharmony_ci	ae_dev->pdev = pdev;
21498c2ecf20Sopenharmony_ci	ae_dev->flag = ent->driver_data;
21508c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, ae_dev);
21518c2ecf20Sopenharmony_ci
21528c2ecf20Sopenharmony_ci	ret = hnae3_register_ae_dev(ae_dev);
21538c2ecf20Sopenharmony_ci	if (ret)
21548c2ecf20Sopenharmony_ci		pci_set_drvdata(pdev, NULL);
21558c2ecf20Sopenharmony_ci
21568c2ecf20Sopenharmony_ci	return ret;
21578c2ecf20Sopenharmony_ci}
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_ci/* hns3_remove - Device removal routine
21608c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
21618c2ecf20Sopenharmony_ci */
21628c2ecf20Sopenharmony_cistatic void hns3_remove(struct pci_dev *pdev)
21638c2ecf20Sopenharmony_ci{
21648c2ecf20Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
21658c2ecf20Sopenharmony_ci
21668c2ecf20Sopenharmony_ci	if (hns3_is_phys_func(pdev) && IS_ENABLED(CONFIG_PCI_IOV))
21678c2ecf20Sopenharmony_ci		hns3_disable_sriov(pdev);
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_ci	hnae3_unregister_ae_dev(ae_dev);
21708c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, NULL);
21718c2ecf20Sopenharmony_ci}
21728c2ecf20Sopenharmony_ci
21738c2ecf20Sopenharmony_ci/**
21748c2ecf20Sopenharmony_ci * hns3_pci_sriov_configure
21758c2ecf20Sopenharmony_ci * @pdev: pointer to a pci_dev structure
21768c2ecf20Sopenharmony_ci * @num_vfs: number of VFs to allocate
21778c2ecf20Sopenharmony_ci *
21788c2ecf20Sopenharmony_ci * Enable or change the number of VFs. Called when the user updates the number
21798c2ecf20Sopenharmony_ci * of VFs in sysfs.
21808c2ecf20Sopenharmony_ci **/
21818c2ecf20Sopenharmony_cistatic int hns3_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
21828c2ecf20Sopenharmony_ci{
21838c2ecf20Sopenharmony_ci	int ret;
21848c2ecf20Sopenharmony_ci
21858c2ecf20Sopenharmony_ci	if (!(hns3_is_phys_func(pdev) && IS_ENABLED(CONFIG_PCI_IOV))) {
21868c2ecf20Sopenharmony_ci		dev_warn(&pdev->dev, "Can not config SRIOV\n");
21878c2ecf20Sopenharmony_ci		return -EINVAL;
21888c2ecf20Sopenharmony_ci	}
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ci	if (num_vfs) {
21918c2ecf20Sopenharmony_ci		ret = pci_enable_sriov(pdev, num_vfs);
21928c2ecf20Sopenharmony_ci		if (ret)
21938c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "SRIOV enable failed %d\n", ret);
21948c2ecf20Sopenharmony_ci		else
21958c2ecf20Sopenharmony_ci			return num_vfs;
21968c2ecf20Sopenharmony_ci	} else if (!pci_vfs_assigned(pdev)) {
21978c2ecf20Sopenharmony_ci		pci_disable_sriov(pdev);
21988c2ecf20Sopenharmony_ci	} else {
21998c2ecf20Sopenharmony_ci		dev_warn(&pdev->dev,
22008c2ecf20Sopenharmony_ci			 "Unable to free VFs because some are assigned to VMs.\n");
22018c2ecf20Sopenharmony_ci	}
22028c2ecf20Sopenharmony_ci
22038c2ecf20Sopenharmony_ci	return 0;
22048c2ecf20Sopenharmony_ci}
22058c2ecf20Sopenharmony_ci
22068c2ecf20Sopenharmony_cistatic void hns3_shutdown(struct pci_dev *pdev)
22078c2ecf20Sopenharmony_ci{
22088c2ecf20Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_ci	hnae3_unregister_ae_dev(ae_dev);
22118c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, NULL);
22128c2ecf20Sopenharmony_ci
22138c2ecf20Sopenharmony_ci	if (system_state == SYSTEM_POWER_OFF)
22148c2ecf20Sopenharmony_ci		pci_set_power_state(pdev, PCI_D3hot);
22158c2ecf20Sopenharmony_ci}
22168c2ecf20Sopenharmony_ci
22178c2ecf20Sopenharmony_cistatic pci_ers_result_t hns3_error_detected(struct pci_dev *pdev,
22188c2ecf20Sopenharmony_ci					    pci_channel_state_t state)
22198c2ecf20Sopenharmony_ci{
22208c2ecf20Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
22218c2ecf20Sopenharmony_ci	pci_ers_result_t ret;
22228c2ecf20Sopenharmony_ci
22238c2ecf20Sopenharmony_ci	dev_info(&pdev->dev, "PCI error detected, state(=%d)!!\n", state);
22248c2ecf20Sopenharmony_ci
22258c2ecf20Sopenharmony_ci	if (state == pci_channel_io_perm_failure)
22268c2ecf20Sopenharmony_ci		return PCI_ERS_RESULT_DISCONNECT;
22278c2ecf20Sopenharmony_ci
22288c2ecf20Sopenharmony_ci	if (!ae_dev || !ae_dev->ops) {
22298c2ecf20Sopenharmony_ci		dev_err(&pdev->dev,
22308c2ecf20Sopenharmony_ci			"Can't recover - error happened before device initialized\n");
22318c2ecf20Sopenharmony_ci		return PCI_ERS_RESULT_NONE;
22328c2ecf20Sopenharmony_ci	}
22338c2ecf20Sopenharmony_ci
22348c2ecf20Sopenharmony_ci	if (ae_dev->ops->handle_hw_ras_error)
22358c2ecf20Sopenharmony_ci		ret = ae_dev->ops->handle_hw_ras_error(ae_dev);
22368c2ecf20Sopenharmony_ci	else
22378c2ecf20Sopenharmony_ci		return PCI_ERS_RESULT_NONE;
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ci	return ret;
22408c2ecf20Sopenharmony_ci}
22418c2ecf20Sopenharmony_ci
22428c2ecf20Sopenharmony_cistatic pci_ers_result_t hns3_slot_reset(struct pci_dev *pdev)
22438c2ecf20Sopenharmony_ci{
22448c2ecf20Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
22458c2ecf20Sopenharmony_ci	const struct hnae3_ae_ops *ops;
22468c2ecf20Sopenharmony_ci	enum hnae3_reset_type reset_type;
22478c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
22488c2ecf20Sopenharmony_ci
22498c2ecf20Sopenharmony_ci	if (!ae_dev || !ae_dev->ops)
22508c2ecf20Sopenharmony_ci		return PCI_ERS_RESULT_NONE;
22518c2ecf20Sopenharmony_ci
22528c2ecf20Sopenharmony_ci	ops = ae_dev->ops;
22538c2ecf20Sopenharmony_ci	/* request the reset */
22548c2ecf20Sopenharmony_ci	if (ops->reset_event && ops->get_reset_level &&
22558c2ecf20Sopenharmony_ci	    ops->set_default_reset_request) {
22568c2ecf20Sopenharmony_ci		if (ae_dev->hw_err_reset_req) {
22578c2ecf20Sopenharmony_ci			reset_type = ops->get_reset_level(ae_dev,
22588c2ecf20Sopenharmony_ci						&ae_dev->hw_err_reset_req);
22598c2ecf20Sopenharmony_ci			ops->set_default_reset_request(ae_dev, reset_type);
22608c2ecf20Sopenharmony_ci			dev_info(dev, "requesting reset due to PCI error\n");
22618c2ecf20Sopenharmony_ci			ops->reset_event(pdev, NULL);
22628c2ecf20Sopenharmony_ci		}
22638c2ecf20Sopenharmony_ci
22648c2ecf20Sopenharmony_ci		return PCI_ERS_RESULT_RECOVERED;
22658c2ecf20Sopenharmony_ci	}
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_ci	return PCI_ERS_RESULT_DISCONNECT;
22688c2ecf20Sopenharmony_ci}
22698c2ecf20Sopenharmony_ci
22708c2ecf20Sopenharmony_cistatic void hns3_reset_prepare(struct pci_dev *pdev)
22718c2ecf20Sopenharmony_ci{
22728c2ecf20Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
22738c2ecf20Sopenharmony_ci
22748c2ecf20Sopenharmony_ci	dev_info(&pdev->dev, "FLR prepare\n");
22758c2ecf20Sopenharmony_ci	if (ae_dev && ae_dev->ops && ae_dev->ops->flr_prepare)
22768c2ecf20Sopenharmony_ci		ae_dev->ops->flr_prepare(ae_dev);
22778c2ecf20Sopenharmony_ci}
22788c2ecf20Sopenharmony_ci
22798c2ecf20Sopenharmony_cistatic void hns3_reset_done(struct pci_dev *pdev)
22808c2ecf20Sopenharmony_ci{
22818c2ecf20Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
22828c2ecf20Sopenharmony_ci
22838c2ecf20Sopenharmony_ci	dev_info(&pdev->dev, "FLR done\n");
22848c2ecf20Sopenharmony_ci	if (ae_dev && ae_dev->ops && ae_dev->ops->flr_done)
22858c2ecf20Sopenharmony_ci		ae_dev->ops->flr_done(ae_dev);
22868c2ecf20Sopenharmony_ci}
22878c2ecf20Sopenharmony_ci
22888c2ecf20Sopenharmony_cistatic const struct pci_error_handlers hns3_err_handler = {
22898c2ecf20Sopenharmony_ci	.error_detected = hns3_error_detected,
22908c2ecf20Sopenharmony_ci	.slot_reset     = hns3_slot_reset,
22918c2ecf20Sopenharmony_ci	.reset_prepare	= hns3_reset_prepare,
22928c2ecf20Sopenharmony_ci	.reset_done	= hns3_reset_done,
22938c2ecf20Sopenharmony_ci};
22948c2ecf20Sopenharmony_ci
22958c2ecf20Sopenharmony_cistatic struct pci_driver hns3_driver = {
22968c2ecf20Sopenharmony_ci	.name     = hns3_driver_name,
22978c2ecf20Sopenharmony_ci	.id_table = hns3_pci_tbl,
22988c2ecf20Sopenharmony_ci	.probe    = hns3_probe,
22998c2ecf20Sopenharmony_ci	.remove   = hns3_remove,
23008c2ecf20Sopenharmony_ci	.shutdown = hns3_shutdown,
23018c2ecf20Sopenharmony_ci	.sriov_configure = hns3_pci_sriov_configure,
23028c2ecf20Sopenharmony_ci	.err_handler    = &hns3_err_handler,
23038c2ecf20Sopenharmony_ci};
23048c2ecf20Sopenharmony_ci
23058c2ecf20Sopenharmony_ci/* set default feature to hns3 */
23068c2ecf20Sopenharmony_cistatic void hns3_set_default_feature(struct net_device *netdev)
23078c2ecf20Sopenharmony_ci{
23088c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
23098c2ecf20Sopenharmony_ci	struct pci_dev *pdev = h->pdev;
23108c2ecf20Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
23118c2ecf20Sopenharmony_ci
23128c2ecf20Sopenharmony_ci	netdev->priv_flags |= IFF_UNICAST_FLT;
23138c2ecf20Sopenharmony_ci
23148c2ecf20Sopenharmony_ci	netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
23158c2ecf20Sopenharmony_ci		NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
23168c2ecf20Sopenharmony_ci		NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE |
23178c2ecf20Sopenharmony_ci		NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
23188c2ecf20Sopenharmony_ci		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC |
23198c2ecf20Sopenharmony_ci		NETIF_F_TSO_MANGLEID | NETIF_F_FRAGLIST;
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ci	netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
23228c2ecf20Sopenharmony_ci
23238c2ecf20Sopenharmony_ci	netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
23248c2ecf20Sopenharmony_ci		NETIF_F_HW_VLAN_CTAG_FILTER |
23258c2ecf20Sopenharmony_ci		NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
23268c2ecf20Sopenharmony_ci		NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
23278c2ecf20Sopenharmony_ci		NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE |
23288c2ecf20Sopenharmony_ci		NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
23298c2ecf20Sopenharmony_ci		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC |
23308c2ecf20Sopenharmony_ci		NETIF_F_FRAGLIST;
23318c2ecf20Sopenharmony_ci
23328c2ecf20Sopenharmony_ci	netdev->vlan_features |=
23338c2ecf20Sopenharmony_ci		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |
23348c2ecf20Sopenharmony_ci		NETIF_F_SG | NETIF_F_GSO | NETIF_F_GRO |
23358c2ecf20Sopenharmony_ci		NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE |
23368c2ecf20Sopenharmony_ci		NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
23378c2ecf20Sopenharmony_ci		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC |
23388c2ecf20Sopenharmony_ci		NETIF_F_FRAGLIST;
23398c2ecf20Sopenharmony_ci
23408c2ecf20Sopenharmony_ci	netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
23418c2ecf20Sopenharmony_ci		NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
23428c2ecf20Sopenharmony_ci		NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
23438c2ecf20Sopenharmony_ci		NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE |
23448c2ecf20Sopenharmony_ci		NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
23458c2ecf20Sopenharmony_ci		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC |
23468c2ecf20Sopenharmony_ci		NETIF_F_FRAGLIST;
23478c2ecf20Sopenharmony_ci
23488c2ecf20Sopenharmony_ci	if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
23498c2ecf20Sopenharmony_ci		netdev->hw_features |= NETIF_F_GRO_HW;
23508c2ecf20Sopenharmony_ci		netdev->features |= NETIF_F_GRO_HW;
23518c2ecf20Sopenharmony_ci
23528c2ecf20Sopenharmony_ci		if (!(h->flags & HNAE3_SUPPORT_VF)) {
23538c2ecf20Sopenharmony_ci			netdev->hw_features |= NETIF_F_NTUPLE;
23548c2ecf20Sopenharmony_ci			netdev->features |= NETIF_F_NTUPLE;
23558c2ecf20Sopenharmony_ci		}
23568c2ecf20Sopenharmony_ci	}
23578c2ecf20Sopenharmony_ci
23588c2ecf20Sopenharmony_ci	if (test_bit(HNAE3_DEV_SUPPORT_UDP_GSO_B, ae_dev->caps)) {
23598c2ecf20Sopenharmony_ci		netdev->hw_features |= NETIF_F_GSO_UDP_L4;
23608c2ecf20Sopenharmony_ci		netdev->features |= NETIF_F_GSO_UDP_L4;
23618c2ecf20Sopenharmony_ci		netdev->vlan_features |= NETIF_F_GSO_UDP_L4;
23628c2ecf20Sopenharmony_ci		netdev->hw_enc_features |= NETIF_F_GSO_UDP_L4;
23638c2ecf20Sopenharmony_ci	}
23648c2ecf20Sopenharmony_ci}
23658c2ecf20Sopenharmony_ci
23668c2ecf20Sopenharmony_cistatic int hns3_alloc_buffer(struct hns3_enet_ring *ring,
23678c2ecf20Sopenharmony_ci			     struct hns3_desc_cb *cb)
23688c2ecf20Sopenharmony_ci{
23698c2ecf20Sopenharmony_ci	unsigned int order = hns3_page_order(ring);
23708c2ecf20Sopenharmony_ci	struct page *p;
23718c2ecf20Sopenharmony_ci
23728c2ecf20Sopenharmony_ci	p = dev_alloc_pages(order);
23738c2ecf20Sopenharmony_ci	if (!p)
23748c2ecf20Sopenharmony_ci		return -ENOMEM;
23758c2ecf20Sopenharmony_ci
23768c2ecf20Sopenharmony_ci	cb->priv = p;
23778c2ecf20Sopenharmony_ci	cb->page_offset = 0;
23788c2ecf20Sopenharmony_ci	cb->reuse_flag = 0;
23798c2ecf20Sopenharmony_ci	cb->buf  = page_address(p);
23808c2ecf20Sopenharmony_ci	cb->length = hns3_page_size(ring);
23818c2ecf20Sopenharmony_ci	cb->type = DESC_TYPE_PAGE;
23828c2ecf20Sopenharmony_ci	page_ref_add(p, USHRT_MAX - 1);
23838c2ecf20Sopenharmony_ci	cb->pagecnt_bias = USHRT_MAX;
23848c2ecf20Sopenharmony_ci
23858c2ecf20Sopenharmony_ci	return 0;
23868c2ecf20Sopenharmony_ci}
23878c2ecf20Sopenharmony_ci
23888c2ecf20Sopenharmony_cistatic void hns3_free_buffer(struct hns3_enet_ring *ring,
23898c2ecf20Sopenharmony_ci			     struct hns3_desc_cb *cb, int budget)
23908c2ecf20Sopenharmony_ci{
23918c2ecf20Sopenharmony_ci	if (cb->type == DESC_TYPE_SKB)
23928c2ecf20Sopenharmony_ci		napi_consume_skb(cb->priv, budget);
23938c2ecf20Sopenharmony_ci	else if (!HNAE3_IS_TX_RING(ring) && cb->pagecnt_bias)
23948c2ecf20Sopenharmony_ci		__page_frag_cache_drain(cb->priv, cb->pagecnt_bias);
23958c2ecf20Sopenharmony_ci	memset(cb, 0, sizeof(*cb));
23968c2ecf20Sopenharmony_ci}
23978c2ecf20Sopenharmony_ci
23988c2ecf20Sopenharmony_cistatic int hns3_map_buffer(struct hns3_enet_ring *ring, struct hns3_desc_cb *cb)
23998c2ecf20Sopenharmony_ci{
24008c2ecf20Sopenharmony_ci	cb->dma = dma_map_page(ring_to_dev(ring), cb->priv, 0,
24018c2ecf20Sopenharmony_ci			       cb->length, ring_to_dma_dir(ring));
24028c2ecf20Sopenharmony_ci
24038c2ecf20Sopenharmony_ci	if (unlikely(dma_mapping_error(ring_to_dev(ring), cb->dma)))
24048c2ecf20Sopenharmony_ci		return -EIO;
24058c2ecf20Sopenharmony_ci
24068c2ecf20Sopenharmony_ci	return 0;
24078c2ecf20Sopenharmony_ci}
24088c2ecf20Sopenharmony_ci
24098c2ecf20Sopenharmony_cistatic void hns3_unmap_buffer(struct hns3_enet_ring *ring,
24108c2ecf20Sopenharmony_ci			      struct hns3_desc_cb *cb)
24118c2ecf20Sopenharmony_ci{
24128c2ecf20Sopenharmony_ci	if (cb->type == DESC_TYPE_SKB || cb->type == DESC_TYPE_FRAGLIST_SKB)
24138c2ecf20Sopenharmony_ci		dma_unmap_single(ring_to_dev(ring), cb->dma, cb->length,
24148c2ecf20Sopenharmony_ci				 ring_to_dma_dir(ring));
24158c2ecf20Sopenharmony_ci	else if (cb->length)
24168c2ecf20Sopenharmony_ci		dma_unmap_page(ring_to_dev(ring), cb->dma, cb->length,
24178c2ecf20Sopenharmony_ci			       ring_to_dma_dir(ring));
24188c2ecf20Sopenharmony_ci}
24198c2ecf20Sopenharmony_ci
24208c2ecf20Sopenharmony_cistatic void hns3_buffer_detach(struct hns3_enet_ring *ring, int i)
24218c2ecf20Sopenharmony_ci{
24228c2ecf20Sopenharmony_ci	hns3_unmap_buffer(ring, &ring->desc_cb[i]);
24238c2ecf20Sopenharmony_ci	ring->desc[i].addr = 0;
24248c2ecf20Sopenharmony_ci	ring->desc_cb[i].refill = 0;
24258c2ecf20Sopenharmony_ci}
24268c2ecf20Sopenharmony_ci
24278c2ecf20Sopenharmony_cistatic void hns3_free_buffer_detach(struct hns3_enet_ring *ring, int i,
24288c2ecf20Sopenharmony_ci				    int budget)
24298c2ecf20Sopenharmony_ci{
24308c2ecf20Sopenharmony_ci	struct hns3_desc_cb *cb = &ring->desc_cb[i];
24318c2ecf20Sopenharmony_ci
24328c2ecf20Sopenharmony_ci	if (!ring->desc_cb[i].dma)
24338c2ecf20Sopenharmony_ci		return;
24348c2ecf20Sopenharmony_ci
24358c2ecf20Sopenharmony_ci	hns3_buffer_detach(ring, i);
24368c2ecf20Sopenharmony_ci	hns3_free_buffer(ring, cb, budget);
24378c2ecf20Sopenharmony_ci}
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_cistatic void hns3_free_buffers(struct hns3_enet_ring *ring)
24408c2ecf20Sopenharmony_ci{
24418c2ecf20Sopenharmony_ci	int i;
24428c2ecf20Sopenharmony_ci
24438c2ecf20Sopenharmony_ci	for (i = 0; i < ring->desc_num; i++)
24448c2ecf20Sopenharmony_ci		hns3_free_buffer_detach(ring, i, 0);
24458c2ecf20Sopenharmony_ci}
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_ci/* free desc along with its attached buffer */
24488c2ecf20Sopenharmony_cistatic void hns3_free_desc(struct hns3_enet_ring *ring)
24498c2ecf20Sopenharmony_ci{
24508c2ecf20Sopenharmony_ci	int size = ring->desc_num * sizeof(ring->desc[0]);
24518c2ecf20Sopenharmony_ci
24528c2ecf20Sopenharmony_ci	hns3_free_buffers(ring);
24538c2ecf20Sopenharmony_ci
24548c2ecf20Sopenharmony_ci	if (ring->desc) {
24558c2ecf20Sopenharmony_ci		dma_free_coherent(ring_to_dev(ring), size,
24568c2ecf20Sopenharmony_ci				  ring->desc, ring->desc_dma_addr);
24578c2ecf20Sopenharmony_ci		ring->desc = NULL;
24588c2ecf20Sopenharmony_ci	}
24598c2ecf20Sopenharmony_ci}
24608c2ecf20Sopenharmony_ci
24618c2ecf20Sopenharmony_cistatic int hns3_alloc_desc(struct hns3_enet_ring *ring)
24628c2ecf20Sopenharmony_ci{
24638c2ecf20Sopenharmony_ci	int size = ring->desc_num * sizeof(ring->desc[0]);
24648c2ecf20Sopenharmony_ci
24658c2ecf20Sopenharmony_ci	ring->desc = dma_alloc_coherent(ring_to_dev(ring), size,
24668c2ecf20Sopenharmony_ci					&ring->desc_dma_addr, GFP_KERNEL);
24678c2ecf20Sopenharmony_ci	if (!ring->desc)
24688c2ecf20Sopenharmony_ci		return -ENOMEM;
24698c2ecf20Sopenharmony_ci
24708c2ecf20Sopenharmony_ci	return 0;
24718c2ecf20Sopenharmony_ci}
24728c2ecf20Sopenharmony_ci
24738c2ecf20Sopenharmony_cistatic int hns3_alloc_and_map_buffer(struct hns3_enet_ring *ring,
24748c2ecf20Sopenharmony_ci				   struct hns3_desc_cb *cb)
24758c2ecf20Sopenharmony_ci{
24768c2ecf20Sopenharmony_ci	int ret;
24778c2ecf20Sopenharmony_ci
24788c2ecf20Sopenharmony_ci	ret = hns3_alloc_buffer(ring, cb);
24798c2ecf20Sopenharmony_ci	if (ret)
24808c2ecf20Sopenharmony_ci		goto out;
24818c2ecf20Sopenharmony_ci
24828c2ecf20Sopenharmony_ci	ret = hns3_map_buffer(ring, cb);
24838c2ecf20Sopenharmony_ci	if (ret)
24848c2ecf20Sopenharmony_ci		goto out_with_buf;
24858c2ecf20Sopenharmony_ci
24868c2ecf20Sopenharmony_ci	return 0;
24878c2ecf20Sopenharmony_ci
24888c2ecf20Sopenharmony_ciout_with_buf:
24898c2ecf20Sopenharmony_ci	hns3_free_buffer(ring, cb, 0);
24908c2ecf20Sopenharmony_ciout:
24918c2ecf20Sopenharmony_ci	return ret;
24928c2ecf20Sopenharmony_ci}
24938c2ecf20Sopenharmony_ci
24948c2ecf20Sopenharmony_cistatic int hns3_alloc_and_attach_buffer(struct hns3_enet_ring *ring, int i)
24958c2ecf20Sopenharmony_ci{
24968c2ecf20Sopenharmony_ci	int ret = hns3_alloc_and_map_buffer(ring, &ring->desc_cb[i]);
24978c2ecf20Sopenharmony_ci
24988c2ecf20Sopenharmony_ci	if (ret)
24998c2ecf20Sopenharmony_ci		return ret;
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_ci	ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma);
25028c2ecf20Sopenharmony_ci	ring->desc_cb[i].refill = 1;
25038c2ecf20Sopenharmony_ci
25048c2ecf20Sopenharmony_ci	return 0;
25058c2ecf20Sopenharmony_ci}
25068c2ecf20Sopenharmony_ci
25078c2ecf20Sopenharmony_ci/* Allocate memory for raw pkg, and map with dma */
25088c2ecf20Sopenharmony_cistatic int hns3_alloc_ring_buffers(struct hns3_enet_ring *ring)
25098c2ecf20Sopenharmony_ci{
25108c2ecf20Sopenharmony_ci	int i, j, ret;
25118c2ecf20Sopenharmony_ci
25128c2ecf20Sopenharmony_ci	for (i = 0; i < ring->desc_num; i++) {
25138c2ecf20Sopenharmony_ci		ret = hns3_alloc_and_attach_buffer(ring, i);
25148c2ecf20Sopenharmony_ci		if (ret)
25158c2ecf20Sopenharmony_ci			goto out_buffer_fail;
25168c2ecf20Sopenharmony_ci	}
25178c2ecf20Sopenharmony_ci
25188c2ecf20Sopenharmony_ci	return 0;
25198c2ecf20Sopenharmony_ci
25208c2ecf20Sopenharmony_ciout_buffer_fail:
25218c2ecf20Sopenharmony_ci	for (j = i - 1; j >= 0; j--)
25228c2ecf20Sopenharmony_ci		hns3_free_buffer_detach(ring, j, 0);
25238c2ecf20Sopenharmony_ci	return ret;
25248c2ecf20Sopenharmony_ci}
25258c2ecf20Sopenharmony_ci
25268c2ecf20Sopenharmony_ci/* detach a in-used buffer and replace with a reserved one */
25278c2ecf20Sopenharmony_cistatic void hns3_replace_buffer(struct hns3_enet_ring *ring, int i,
25288c2ecf20Sopenharmony_ci				struct hns3_desc_cb *res_cb)
25298c2ecf20Sopenharmony_ci{
25308c2ecf20Sopenharmony_ci	hns3_unmap_buffer(ring, &ring->desc_cb[i]);
25318c2ecf20Sopenharmony_ci	ring->desc_cb[i] = *res_cb;
25328c2ecf20Sopenharmony_ci	ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma);
25338c2ecf20Sopenharmony_ci	ring->desc_cb[i].refill = 1;
25348c2ecf20Sopenharmony_ci	ring->desc[i].rx.bd_base_info = 0;
25358c2ecf20Sopenharmony_ci}
25368c2ecf20Sopenharmony_ci
25378c2ecf20Sopenharmony_cistatic void hns3_reuse_buffer(struct hns3_enet_ring *ring, int i)
25388c2ecf20Sopenharmony_ci{
25398c2ecf20Sopenharmony_ci	ring->desc_cb[i].reuse_flag = 0;
25408c2ecf20Sopenharmony_ci	ring->desc_cb[i].refill = 1;
25418c2ecf20Sopenharmony_ci	ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma +
25428c2ecf20Sopenharmony_ci					 ring->desc_cb[i].page_offset);
25438c2ecf20Sopenharmony_ci	ring->desc[i].rx.bd_base_info = 0;
25448c2ecf20Sopenharmony_ci
25458c2ecf20Sopenharmony_ci	dma_sync_single_for_device(ring_to_dev(ring),
25468c2ecf20Sopenharmony_ci			ring->desc_cb[i].dma + ring->desc_cb[i].page_offset,
25478c2ecf20Sopenharmony_ci			hns3_buf_size(ring),
25488c2ecf20Sopenharmony_ci			DMA_FROM_DEVICE);
25498c2ecf20Sopenharmony_ci}
25508c2ecf20Sopenharmony_ci
25518c2ecf20Sopenharmony_cistatic bool hns3_nic_reclaim_desc(struct hns3_enet_ring *ring,
25528c2ecf20Sopenharmony_ci				  int *bytes, int *pkts, int budget)
25538c2ecf20Sopenharmony_ci{
25548c2ecf20Sopenharmony_ci	/* pair with ring->last_to_use update in hns3_tx_doorbell(),
25558c2ecf20Sopenharmony_ci	 * smp_store_release() is not used in hns3_tx_doorbell() because
25568c2ecf20Sopenharmony_ci	 * the doorbell operation already have the needed barrier operation.
25578c2ecf20Sopenharmony_ci	 */
25588c2ecf20Sopenharmony_ci	int ltu = smp_load_acquire(&ring->last_to_use);
25598c2ecf20Sopenharmony_ci	int ntc = ring->next_to_clean;
25608c2ecf20Sopenharmony_ci	struct hns3_desc_cb *desc_cb;
25618c2ecf20Sopenharmony_ci	bool reclaimed = false;
25628c2ecf20Sopenharmony_ci	struct hns3_desc *desc;
25638c2ecf20Sopenharmony_ci
25648c2ecf20Sopenharmony_ci	while (ltu != ntc) {
25658c2ecf20Sopenharmony_ci		desc = &ring->desc[ntc];
25668c2ecf20Sopenharmony_ci
25678c2ecf20Sopenharmony_ci		if (le16_to_cpu(desc->tx.bdtp_fe_sc_vld_ra_ri) &
25688c2ecf20Sopenharmony_ci				BIT(HNS3_TXD_VLD_B))
25698c2ecf20Sopenharmony_ci			break;
25708c2ecf20Sopenharmony_ci
25718c2ecf20Sopenharmony_ci		desc_cb = &ring->desc_cb[ntc];
25728c2ecf20Sopenharmony_ci		(*pkts) += (desc_cb->type == DESC_TYPE_SKB);
25738c2ecf20Sopenharmony_ci		(*bytes) += desc_cb->length;
25748c2ecf20Sopenharmony_ci		/* desc_cb will be cleaned, after hnae3_free_buffer_detach */
25758c2ecf20Sopenharmony_ci		hns3_free_buffer_detach(ring, ntc, budget);
25768c2ecf20Sopenharmony_ci
25778c2ecf20Sopenharmony_ci		if (++ntc == ring->desc_num)
25788c2ecf20Sopenharmony_ci			ntc = 0;
25798c2ecf20Sopenharmony_ci
25808c2ecf20Sopenharmony_ci		/* Issue prefetch for next Tx descriptor */
25818c2ecf20Sopenharmony_ci		prefetch(&ring->desc_cb[ntc]);
25828c2ecf20Sopenharmony_ci		reclaimed = true;
25838c2ecf20Sopenharmony_ci	}
25848c2ecf20Sopenharmony_ci
25858c2ecf20Sopenharmony_ci	if (unlikely(!reclaimed))
25868c2ecf20Sopenharmony_ci		return false;
25878c2ecf20Sopenharmony_ci
25888c2ecf20Sopenharmony_ci	/* This smp_store_release() pairs with smp_load_acquire() in
25898c2ecf20Sopenharmony_ci	 * ring_space called by hns3_nic_net_xmit.
25908c2ecf20Sopenharmony_ci	 */
25918c2ecf20Sopenharmony_ci	smp_store_release(&ring->next_to_clean, ntc);
25928c2ecf20Sopenharmony_ci	return true;
25938c2ecf20Sopenharmony_ci}
25948c2ecf20Sopenharmony_ci
25958c2ecf20Sopenharmony_civoid hns3_clean_tx_ring(struct hns3_enet_ring *ring, int budget)
25968c2ecf20Sopenharmony_ci{
25978c2ecf20Sopenharmony_ci	struct net_device *netdev = ring_to_netdev(ring);
25988c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
25998c2ecf20Sopenharmony_ci	struct netdev_queue *dev_queue;
26008c2ecf20Sopenharmony_ci	int bytes, pkts;
26018c2ecf20Sopenharmony_ci
26028c2ecf20Sopenharmony_ci	bytes = 0;
26038c2ecf20Sopenharmony_ci	pkts = 0;
26048c2ecf20Sopenharmony_ci
26058c2ecf20Sopenharmony_ci	if (unlikely(!hns3_nic_reclaim_desc(ring, &bytes, &pkts, budget)))
26068c2ecf20Sopenharmony_ci		return;
26078c2ecf20Sopenharmony_ci
26088c2ecf20Sopenharmony_ci	ring->tqp_vector->tx_group.total_bytes += bytes;
26098c2ecf20Sopenharmony_ci	ring->tqp_vector->tx_group.total_packets += pkts;
26108c2ecf20Sopenharmony_ci
26118c2ecf20Sopenharmony_ci	u64_stats_update_begin(&ring->syncp);
26128c2ecf20Sopenharmony_ci	ring->stats.tx_bytes += bytes;
26138c2ecf20Sopenharmony_ci	ring->stats.tx_pkts += pkts;
26148c2ecf20Sopenharmony_ci	u64_stats_update_end(&ring->syncp);
26158c2ecf20Sopenharmony_ci
26168c2ecf20Sopenharmony_ci	dev_queue = netdev_get_tx_queue(netdev, ring->tqp->tqp_index);
26178c2ecf20Sopenharmony_ci	netdev_tx_completed_queue(dev_queue, pkts, bytes);
26188c2ecf20Sopenharmony_ci
26198c2ecf20Sopenharmony_ci	if (unlikely(netif_carrier_ok(netdev) &&
26208c2ecf20Sopenharmony_ci		     ring_space(ring) > HNS3_MAX_TSO_BD_NUM)) {
26218c2ecf20Sopenharmony_ci		/* Make sure that anybody stopping the queue after this
26228c2ecf20Sopenharmony_ci		 * sees the new next_to_clean.
26238c2ecf20Sopenharmony_ci		 */
26248c2ecf20Sopenharmony_ci		smp_mb();
26258c2ecf20Sopenharmony_ci		if (netif_tx_queue_stopped(dev_queue) &&
26268c2ecf20Sopenharmony_ci		    !test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) {
26278c2ecf20Sopenharmony_ci			netif_tx_wake_queue(dev_queue);
26288c2ecf20Sopenharmony_ci			ring->stats.restart_queue++;
26298c2ecf20Sopenharmony_ci		}
26308c2ecf20Sopenharmony_ci	}
26318c2ecf20Sopenharmony_ci}
26328c2ecf20Sopenharmony_ci
26338c2ecf20Sopenharmony_cistatic int hns3_desc_unused(struct hns3_enet_ring *ring)
26348c2ecf20Sopenharmony_ci{
26358c2ecf20Sopenharmony_ci	int ntc = ring->next_to_clean;
26368c2ecf20Sopenharmony_ci	int ntu = ring->next_to_use;
26378c2ecf20Sopenharmony_ci
26388c2ecf20Sopenharmony_ci	if (unlikely(ntc == ntu && !ring->desc_cb[ntc].refill))
26398c2ecf20Sopenharmony_ci		return ring->desc_num;
26408c2ecf20Sopenharmony_ci
26418c2ecf20Sopenharmony_ci	return ((ntc >= ntu) ? 0 : ring->desc_num) + ntc - ntu;
26428c2ecf20Sopenharmony_ci}
26438c2ecf20Sopenharmony_ci
26448c2ecf20Sopenharmony_ci/* Return true if there is any allocation failure */
26458c2ecf20Sopenharmony_cistatic bool hns3_nic_alloc_rx_buffers(struct hns3_enet_ring *ring,
26468c2ecf20Sopenharmony_ci				      int cleand_count)
26478c2ecf20Sopenharmony_ci{
26488c2ecf20Sopenharmony_ci	struct hns3_desc_cb *desc_cb;
26498c2ecf20Sopenharmony_ci	struct hns3_desc_cb res_cbs;
26508c2ecf20Sopenharmony_ci	int i, ret;
26518c2ecf20Sopenharmony_ci
26528c2ecf20Sopenharmony_ci	for (i = 0; i < cleand_count; i++) {
26538c2ecf20Sopenharmony_ci		desc_cb = &ring->desc_cb[ring->next_to_use];
26548c2ecf20Sopenharmony_ci		if (desc_cb->reuse_flag) {
26558c2ecf20Sopenharmony_ci			u64_stats_update_begin(&ring->syncp);
26568c2ecf20Sopenharmony_ci			ring->stats.reuse_pg_cnt++;
26578c2ecf20Sopenharmony_ci			u64_stats_update_end(&ring->syncp);
26588c2ecf20Sopenharmony_ci
26598c2ecf20Sopenharmony_ci			hns3_reuse_buffer(ring, ring->next_to_use);
26608c2ecf20Sopenharmony_ci		} else {
26618c2ecf20Sopenharmony_ci			ret = hns3_alloc_and_map_buffer(ring, &res_cbs);
26628c2ecf20Sopenharmony_ci			if (ret) {
26638c2ecf20Sopenharmony_ci				u64_stats_update_begin(&ring->syncp);
26648c2ecf20Sopenharmony_ci				ring->stats.sw_err_cnt++;
26658c2ecf20Sopenharmony_ci				u64_stats_update_end(&ring->syncp);
26668c2ecf20Sopenharmony_ci
26678c2ecf20Sopenharmony_ci				hns3_rl_err(ring_to_netdev(ring),
26688c2ecf20Sopenharmony_ci					    "alloc rx buffer failed: %d\n",
26698c2ecf20Sopenharmony_ci					    ret);
26708c2ecf20Sopenharmony_ci
26718c2ecf20Sopenharmony_ci				writel(i, ring->tqp->io_base +
26728c2ecf20Sopenharmony_ci				       HNS3_RING_RX_RING_HEAD_REG);
26738c2ecf20Sopenharmony_ci				return true;
26748c2ecf20Sopenharmony_ci			}
26758c2ecf20Sopenharmony_ci			hns3_replace_buffer(ring, ring->next_to_use, &res_cbs);
26768c2ecf20Sopenharmony_ci
26778c2ecf20Sopenharmony_ci			u64_stats_update_begin(&ring->syncp);
26788c2ecf20Sopenharmony_ci			ring->stats.non_reuse_pg++;
26798c2ecf20Sopenharmony_ci			u64_stats_update_end(&ring->syncp);
26808c2ecf20Sopenharmony_ci		}
26818c2ecf20Sopenharmony_ci
26828c2ecf20Sopenharmony_ci		ring_ptr_move_fw(ring, next_to_use);
26838c2ecf20Sopenharmony_ci	}
26848c2ecf20Sopenharmony_ci
26858c2ecf20Sopenharmony_ci	writel(i, ring->tqp->io_base + HNS3_RING_RX_RING_HEAD_REG);
26868c2ecf20Sopenharmony_ci	return false;
26878c2ecf20Sopenharmony_ci}
26888c2ecf20Sopenharmony_ci
26898c2ecf20Sopenharmony_cistatic bool hns3_page_is_reusable(struct page *page)
26908c2ecf20Sopenharmony_ci{
26918c2ecf20Sopenharmony_ci	return page_to_nid(page) == numa_mem_id() &&
26928c2ecf20Sopenharmony_ci		!page_is_pfmemalloc(page);
26938c2ecf20Sopenharmony_ci}
26948c2ecf20Sopenharmony_ci
26958c2ecf20Sopenharmony_cistatic bool hns3_can_reuse_page(struct hns3_desc_cb *cb)
26968c2ecf20Sopenharmony_ci{
26978c2ecf20Sopenharmony_ci	return (page_count(cb->priv) - cb->pagecnt_bias) == 1;
26988c2ecf20Sopenharmony_ci}
26998c2ecf20Sopenharmony_ci
27008c2ecf20Sopenharmony_cistatic void hns3_nic_reuse_page(struct sk_buff *skb, int i,
27018c2ecf20Sopenharmony_ci				struct hns3_enet_ring *ring, int pull_len,
27028c2ecf20Sopenharmony_ci				struct hns3_desc_cb *desc_cb)
27038c2ecf20Sopenharmony_ci{
27048c2ecf20Sopenharmony_ci	struct hns3_desc *desc = &ring->desc[ring->next_to_clean];
27058c2ecf20Sopenharmony_ci	int size = le16_to_cpu(desc->rx.size);
27068c2ecf20Sopenharmony_ci	u32 truesize = hns3_buf_size(ring);
27078c2ecf20Sopenharmony_ci
27088c2ecf20Sopenharmony_ci	desc_cb->pagecnt_bias--;
27098c2ecf20Sopenharmony_ci	skb_add_rx_frag(skb, i, desc_cb->priv, desc_cb->page_offset + pull_len,
27108c2ecf20Sopenharmony_ci			size - pull_len, truesize);
27118c2ecf20Sopenharmony_ci
27128c2ecf20Sopenharmony_ci	/* Avoid re-using remote pages, or the stack is still using the page
27138c2ecf20Sopenharmony_ci	 * when page_offset rollback to zero, flag default unreuse
27148c2ecf20Sopenharmony_ci	 */
27158c2ecf20Sopenharmony_ci	if (unlikely(!hns3_page_is_reusable(desc_cb->priv)) ||
27168c2ecf20Sopenharmony_ci	    (!desc_cb->page_offset && !hns3_can_reuse_page(desc_cb))) {
27178c2ecf20Sopenharmony_ci		__page_frag_cache_drain(desc_cb->priv, desc_cb->pagecnt_bias);
27188c2ecf20Sopenharmony_ci		return;
27198c2ecf20Sopenharmony_ci	}
27208c2ecf20Sopenharmony_ci
27218c2ecf20Sopenharmony_ci	/* Move offset up to the next cache line */
27228c2ecf20Sopenharmony_ci	desc_cb->page_offset += truesize;
27238c2ecf20Sopenharmony_ci
27248c2ecf20Sopenharmony_ci	if (desc_cb->page_offset + truesize <= hns3_page_size(ring)) {
27258c2ecf20Sopenharmony_ci		desc_cb->reuse_flag = 1;
27268c2ecf20Sopenharmony_ci	} else if (hns3_can_reuse_page(desc_cb)) {
27278c2ecf20Sopenharmony_ci		desc_cb->reuse_flag = 1;
27288c2ecf20Sopenharmony_ci		desc_cb->page_offset = 0;
27298c2ecf20Sopenharmony_ci	} else if (desc_cb->pagecnt_bias) {
27308c2ecf20Sopenharmony_ci		__page_frag_cache_drain(desc_cb->priv, desc_cb->pagecnt_bias);
27318c2ecf20Sopenharmony_ci		return;
27328c2ecf20Sopenharmony_ci	}
27338c2ecf20Sopenharmony_ci
27348c2ecf20Sopenharmony_ci	if (unlikely(!desc_cb->pagecnt_bias)) {
27358c2ecf20Sopenharmony_ci		page_ref_add(desc_cb->priv, USHRT_MAX);
27368c2ecf20Sopenharmony_ci		desc_cb->pagecnt_bias = USHRT_MAX;
27378c2ecf20Sopenharmony_ci	}
27388c2ecf20Sopenharmony_ci}
27398c2ecf20Sopenharmony_ci
27408c2ecf20Sopenharmony_cistatic int hns3_gro_complete(struct sk_buff *skb, u32 l234info)
27418c2ecf20Sopenharmony_ci{
27428c2ecf20Sopenharmony_ci	__be16 type = skb->protocol;
27438c2ecf20Sopenharmony_ci	struct tcphdr *th;
27448c2ecf20Sopenharmony_ci	int depth = 0;
27458c2ecf20Sopenharmony_ci
27468c2ecf20Sopenharmony_ci	while (eth_type_vlan(type)) {
27478c2ecf20Sopenharmony_ci		struct vlan_hdr *vh;
27488c2ecf20Sopenharmony_ci
27498c2ecf20Sopenharmony_ci		if ((depth + VLAN_HLEN) > skb_headlen(skb))
27508c2ecf20Sopenharmony_ci			return -EFAULT;
27518c2ecf20Sopenharmony_ci
27528c2ecf20Sopenharmony_ci		vh = (struct vlan_hdr *)(skb->data + depth);
27538c2ecf20Sopenharmony_ci		type = vh->h_vlan_encapsulated_proto;
27548c2ecf20Sopenharmony_ci		depth += VLAN_HLEN;
27558c2ecf20Sopenharmony_ci	}
27568c2ecf20Sopenharmony_ci
27578c2ecf20Sopenharmony_ci	skb_set_network_header(skb, depth);
27588c2ecf20Sopenharmony_ci
27598c2ecf20Sopenharmony_ci	if (type == htons(ETH_P_IP)) {
27608c2ecf20Sopenharmony_ci		const struct iphdr *iph = ip_hdr(skb);
27618c2ecf20Sopenharmony_ci
27628c2ecf20Sopenharmony_ci		depth += sizeof(struct iphdr);
27638c2ecf20Sopenharmony_ci		skb_set_transport_header(skb, depth);
27648c2ecf20Sopenharmony_ci		th = tcp_hdr(skb);
27658c2ecf20Sopenharmony_ci		th->check = ~tcp_v4_check(skb->len - depth, iph->saddr,
27668c2ecf20Sopenharmony_ci					  iph->daddr, 0);
27678c2ecf20Sopenharmony_ci	} else if (type == htons(ETH_P_IPV6)) {
27688c2ecf20Sopenharmony_ci		const struct ipv6hdr *iph = ipv6_hdr(skb);
27698c2ecf20Sopenharmony_ci
27708c2ecf20Sopenharmony_ci		depth += sizeof(struct ipv6hdr);
27718c2ecf20Sopenharmony_ci		skb_set_transport_header(skb, depth);
27728c2ecf20Sopenharmony_ci		th = tcp_hdr(skb);
27738c2ecf20Sopenharmony_ci		th->check = ~tcp_v6_check(skb->len - depth, &iph->saddr,
27748c2ecf20Sopenharmony_ci					  &iph->daddr, 0);
27758c2ecf20Sopenharmony_ci	} else {
27768c2ecf20Sopenharmony_ci		hns3_rl_err(skb->dev,
27778c2ecf20Sopenharmony_ci			    "Error: FW GRO supports only IPv4/IPv6, not 0x%04x, depth: %d\n",
27788c2ecf20Sopenharmony_ci			    be16_to_cpu(type), depth);
27798c2ecf20Sopenharmony_ci		return -EFAULT;
27808c2ecf20Sopenharmony_ci	}
27818c2ecf20Sopenharmony_ci
27828c2ecf20Sopenharmony_ci	skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count;
27838c2ecf20Sopenharmony_ci	if (th->cwr)
27848c2ecf20Sopenharmony_ci		skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
27858c2ecf20Sopenharmony_ci
27868c2ecf20Sopenharmony_ci	if (l234info & BIT(HNS3_RXD_GRO_FIXID_B))
27878c2ecf20Sopenharmony_ci		skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_FIXEDID;
27888c2ecf20Sopenharmony_ci
27898c2ecf20Sopenharmony_ci	skb->csum_start = (unsigned char *)th - skb->head;
27908c2ecf20Sopenharmony_ci	skb->csum_offset = offsetof(struct tcphdr, check);
27918c2ecf20Sopenharmony_ci	skb->ip_summed = CHECKSUM_PARTIAL;
27928c2ecf20Sopenharmony_ci
27938c2ecf20Sopenharmony_ci	trace_hns3_gro(skb);
27948c2ecf20Sopenharmony_ci
27958c2ecf20Sopenharmony_ci	return 0;
27968c2ecf20Sopenharmony_ci}
27978c2ecf20Sopenharmony_ci
27988c2ecf20Sopenharmony_cistatic void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb,
27998c2ecf20Sopenharmony_ci			     u32 l234info, u32 bd_base_info, u32 ol_info)
28008c2ecf20Sopenharmony_ci{
28018c2ecf20Sopenharmony_ci	struct net_device *netdev = ring_to_netdev(ring);
28028c2ecf20Sopenharmony_ci	int l3_type, l4_type;
28038c2ecf20Sopenharmony_ci	int ol4_type;
28048c2ecf20Sopenharmony_ci
28058c2ecf20Sopenharmony_ci	skb->ip_summed = CHECKSUM_NONE;
28068c2ecf20Sopenharmony_ci
28078c2ecf20Sopenharmony_ci	skb_checksum_none_assert(skb);
28088c2ecf20Sopenharmony_ci
28098c2ecf20Sopenharmony_ci	if (!(netdev->features & NETIF_F_RXCSUM))
28108c2ecf20Sopenharmony_ci		return;
28118c2ecf20Sopenharmony_ci
28128c2ecf20Sopenharmony_ci	/* check if hardware has done checksum */
28138c2ecf20Sopenharmony_ci	if (!(bd_base_info & BIT(HNS3_RXD_L3L4P_B)))
28148c2ecf20Sopenharmony_ci		return;
28158c2ecf20Sopenharmony_ci
28168c2ecf20Sopenharmony_ci	if (unlikely(l234info & (BIT(HNS3_RXD_L3E_B) | BIT(HNS3_RXD_L4E_B) |
28178c2ecf20Sopenharmony_ci				 BIT(HNS3_RXD_OL3E_B) |
28188c2ecf20Sopenharmony_ci				 BIT(HNS3_RXD_OL4E_B)))) {
28198c2ecf20Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
28208c2ecf20Sopenharmony_ci		ring->stats.l3l4_csum_err++;
28218c2ecf20Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
28228c2ecf20Sopenharmony_ci
28238c2ecf20Sopenharmony_ci		return;
28248c2ecf20Sopenharmony_ci	}
28258c2ecf20Sopenharmony_ci
28268c2ecf20Sopenharmony_ci	ol4_type = hnae3_get_field(ol_info, HNS3_RXD_OL4ID_M,
28278c2ecf20Sopenharmony_ci				   HNS3_RXD_OL4ID_S);
28288c2ecf20Sopenharmony_ci	switch (ol4_type) {
28298c2ecf20Sopenharmony_ci	case HNS3_OL4_TYPE_MAC_IN_UDP:
28308c2ecf20Sopenharmony_ci	case HNS3_OL4_TYPE_NVGRE:
28318c2ecf20Sopenharmony_ci		skb->csum_level = 1;
28328c2ecf20Sopenharmony_ci		fallthrough;
28338c2ecf20Sopenharmony_ci	case HNS3_OL4_TYPE_NO_TUN:
28348c2ecf20Sopenharmony_ci		l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M,
28358c2ecf20Sopenharmony_ci					  HNS3_RXD_L3ID_S);
28368c2ecf20Sopenharmony_ci		l4_type = hnae3_get_field(l234info, HNS3_RXD_L4ID_M,
28378c2ecf20Sopenharmony_ci					  HNS3_RXD_L4ID_S);
28388c2ecf20Sopenharmony_ci
28398c2ecf20Sopenharmony_ci		/* Can checksum ipv4 or ipv6 + UDP/TCP/SCTP packets */
28408c2ecf20Sopenharmony_ci		if ((l3_type == HNS3_L3_TYPE_IPV4 ||
28418c2ecf20Sopenharmony_ci		     l3_type == HNS3_L3_TYPE_IPV6) &&
28428c2ecf20Sopenharmony_ci		    (l4_type == HNS3_L4_TYPE_UDP ||
28438c2ecf20Sopenharmony_ci		     l4_type == HNS3_L4_TYPE_TCP ||
28448c2ecf20Sopenharmony_ci		     l4_type == HNS3_L4_TYPE_SCTP))
28458c2ecf20Sopenharmony_ci			skb->ip_summed = CHECKSUM_UNNECESSARY;
28468c2ecf20Sopenharmony_ci		break;
28478c2ecf20Sopenharmony_ci	default:
28488c2ecf20Sopenharmony_ci		break;
28498c2ecf20Sopenharmony_ci	}
28508c2ecf20Sopenharmony_ci}
28518c2ecf20Sopenharmony_ci
28528c2ecf20Sopenharmony_cistatic void hns3_rx_skb(struct hns3_enet_ring *ring, struct sk_buff *skb)
28538c2ecf20Sopenharmony_ci{
28548c2ecf20Sopenharmony_ci	if (skb_has_frag_list(skb))
28558c2ecf20Sopenharmony_ci		napi_gro_flush(&ring->tqp_vector->napi, false);
28568c2ecf20Sopenharmony_ci
28578c2ecf20Sopenharmony_ci	napi_gro_receive(&ring->tqp_vector->napi, skb);
28588c2ecf20Sopenharmony_ci}
28598c2ecf20Sopenharmony_ci
28608c2ecf20Sopenharmony_cistatic bool hns3_parse_vlan_tag(struct hns3_enet_ring *ring,
28618c2ecf20Sopenharmony_ci				struct hns3_desc *desc, u32 l234info,
28628c2ecf20Sopenharmony_ci				u16 *vlan_tag)
28638c2ecf20Sopenharmony_ci{
28648c2ecf20Sopenharmony_ci	struct hnae3_handle *handle = ring->tqp->handle;
28658c2ecf20Sopenharmony_ci	struct pci_dev *pdev = ring->tqp->handle->pdev;
28668c2ecf20Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
28678c2ecf20Sopenharmony_ci
28688c2ecf20Sopenharmony_ci	if (unlikely(ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)) {
28698c2ecf20Sopenharmony_ci		*vlan_tag = le16_to_cpu(desc->rx.ot_vlan_tag);
28708c2ecf20Sopenharmony_ci		if (!(*vlan_tag & VLAN_VID_MASK))
28718c2ecf20Sopenharmony_ci			*vlan_tag = le16_to_cpu(desc->rx.vlan_tag);
28728c2ecf20Sopenharmony_ci
28738c2ecf20Sopenharmony_ci		return (*vlan_tag != 0);
28748c2ecf20Sopenharmony_ci	}
28758c2ecf20Sopenharmony_ci
28768c2ecf20Sopenharmony_ci#define HNS3_STRP_OUTER_VLAN	0x1
28778c2ecf20Sopenharmony_ci#define HNS3_STRP_INNER_VLAN	0x2
28788c2ecf20Sopenharmony_ci#define HNS3_STRP_BOTH		0x3
28798c2ecf20Sopenharmony_ci
28808c2ecf20Sopenharmony_ci	/* Hardware always insert VLAN tag into RX descriptor when
28818c2ecf20Sopenharmony_ci	 * remove the tag from packet, driver needs to determine
28828c2ecf20Sopenharmony_ci	 * reporting which tag to stack.
28838c2ecf20Sopenharmony_ci	 */
28848c2ecf20Sopenharmony_ci	switch (hnae3_get_field(l234info, HNS3_RXD_STRP_TAGP_M,
28858c2ecf20Sopenharmony_ci				HNS3_RXD_STRP_TAGP_S)) {
28868c2ecf20Sopenharmony_ci	case HNS3_STRP_OUTER_VLAN:
28878c2ecf20Sopenharmony_ci		if (handle->port_base_vlan_state !=
28888c2ecf20Sopenharmony_ci				HNAE3_PORT_BASE_VLAN_DISABLE)
28898c2ecf20Sopenharmony_ci			return false;
28908c2ecf20Sopenharmony_ci
28918c2ecf20Sopenharmony_ci		*vlan_tag = le16_to_cpu(desc->rx.ot_vlan_tag);
28928c2ecf20Sopenharmony_ci		return true;
28938c2ecf20Sopenharmony_ci	case HNS3_STRP_INNER_VLAN:
28948c2ecf20Sopenharmony_ci		if (handle->port_base_vlan_state !=
28958c2ecf20Sopenharmony_ci				HNAE3_PORT_BASE_VLAN_DISABLE)
28968c2ecf20Sopenharmony_ci			return false;
28978c2ecf20Sopenharmony_ci
28988c2ecf20Sopenharmony_ci		*vlan_tag = le16_to_cpu(desc->rx.vlan_tag);
28998c2ecf20Sopenharmony_ci		return true;
29008c2ecf20Sopenharmony_ci	case HNS3_STRP_BOTH:
29018c2ecf20Sopenharmony_ci		if (handle->port_base_vlan_state ==
29028c2ecf20Sopenharmony_ci				HNAE3_PORT_BASE_VLAN_DISABLE)
29038c2ecf20Sopenharmony_ci			*vlan_tag = le16_to_cpu(desc->rx.ot_vlan_tag);
29048c2ecf20Sopenharmony_ci		else
29058c2ecf20Sopenharmony_ci			*vlan_tag = le16_to_cpu(desc->rx.vlan_tag);
29068c2ecf20Sopenharmony_ci
29078c2ecf20Sopenharmony_ci		return true;
29088c2ecf20Sopenharmony_ci	default:
29098c2ecf20Sopenharmony_ci		return false;
29108c2ecf20Sopenharmony_ci	}
29118c2ecf20Sopenharmony_ci}
29128c2ecf20Sopenharmony_ci
29138c2ecf20Sopenharmony_cistatic void hns3_rx_ring_move_fw(struct hns3_enet_ring *ring)
29148c2ecf20Sopenharmony_ci{
29158c2ecf20Sopenharmony_ci	ring->desc[ring->next_to_clean].rx.bd_base_info &=
29168c2ecf20Sopenharmony_ci		cpu_to_le32(~BIT(HNS3_RXD_VLD_B));
29178c2ecf20Sopenharmony_ci	ring->desc_cb[ring->next_to_clean].refill = 0;
29188c2ecf20Sopenharmony_ci	ring->next_to_clean += 1;
29198c2ecf20Sopenharmony_ci
29208c2ecf20Sopenharmony_ci	if (unlikely(ring->next_to_clean == ring->desc_num))
29218c2ecf20Sopenharmony_ci		ring->next_to_clean = 0;
29228c2ecf20Sopenharmony_ci}
29238c2ecf20Sopenharmony_ci
29248c2ecf20Sopenharmony_cistatic int hns3_alloc_skb(struct hns3_enet_ring *ring, unsigned int length,
29258c2ecf20Sopenharmony_ci			  unsigned char *va)
29268c2ecf20Sopenharmony_ci{
29278c2ecf20Sopenharmony_ci	struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_clean];
29288c2ecf20Sopenharmony_ci	struct net_device *netdev = ring_to_netdev(ring);
29298c2ecf20Sopenharmony_ci	struct sk_buff *skb;
29308c2ecf20Sopenharmony_ci
29318c2ecf20Sopenharmony_ci	ring->skb = napi_alloc_skb(&ring->tqp_vector->napi, HNS3_RX_HEAD_SIZE);
29328c2ecf20Sopenharmony_ci	skb = ring->skb;
29338c2ecf20Sopenharmony_ci	if (unlikely(!skb)) {
29348c2ecf20Sopenharmony_ci		hns3_rl_err(netdev, "alloc rx skb fail\n");
29358c2ecf20Sopenharmony_ci
29368c2ecf20Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
29378c2ecf20Sopenharmony_ci		ring->stats.sw_err_cnt++;
29388c2ecf20Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
29398c2ecf20Sopenharmony_ci
29408c2ecf20Sopenharmony_ci		return -ENOMEM;
29418c2ecf20Sopenharmony_ci	}
29428c2ecf20Sopenharmony_ci
29438c2ecf20Sopenharmony_ci	trace_hns3_rx_desc(ring);
29448c2ecf20Sopenharmony_ci	prefetchw(skb->data);
29458c2ecf20Sopenharmony_ci
29468c2ecf20Sopenharmony_ci	ring->pending_buf = 1;
29478c2ecf20Sopenharmony_ci	ring->frag_num = 0;
29488c2ecf20Sopenharmony_ci	ring->tail_skb = NULL;
29498c2ecf20Sopenharmony_ci	if (length <= HNS3_RX_HEAD_SIZE) {
29508c2ecf20Sopenharmony_ci		memcpy(__skb_put(skb, length), va, ALIGN(length, sizeof(long)));
29518c2ecf20Sopenharmony_ci
29528c2ecf20Sopenharmony_ci		/* We can reuse buffer as-is, just make sure it is local */
29538c2ecf20Sopenharmony_ci		if (likely(hns3_page_is_reusable(desc_cb->priv)))
29548c2ecf20Sopenharmony_ci			desc_cb->reuse_flag = 1;
29558c2ecf20Sopenharmony_ci		else /* This page cannot be reused so discard it */
29568c2ecf20Sopenharmony_ci			__page_frag_cache_drain(desc_cb->priv,
29578c2ecf20Sopenharmony_ci						desc_cb->pagecnt_bias);
29588c2ecf20Sopenharmony_ci
29598c2ecf20Sopenharmony_ci		hns3_rx_ring_move_fw(ring);
29608c2ecf20Sopenharmony_ci		return 0;
29618c2ecf20Sopenharmony_ci	}
29628c2ecf20Sopenharmony_ci	u64_stats_update_begin(&ring->syncp);
29638c2ecf20Sopenharmony_ci	ring->stats.seg_pkt_cnt++;
29648c2ecf20Sopenharmony_ci	u64_stats_update_end(&ring->syncp);
29658c2ecf20Sopenharmony_ci
29668c2ecf20Sopenharmony_ci	ring->pull_len = eth_get_headlen(netdev, va, HNS3_RX_HEAD_SIZE);
29678c2ecf20Sopenharmony_ci	__skb_put(skb, ring->pull_len);
29688c2ecf20Sopenharmony_ci	hns3_nic_reuse_page(skb, ring->frag_num++, ring, ring->pull_len,
29698c2ecf20Sopenharmony_ci			    desc_cb);
29708c2ecf20Sopenharmony_ci	hns3_rx_ring_move_fw(ring);
29718c2ecf20Sopenharmony_ci
29728c2ecf20Sopenharmony_ci	return 0;
29738c2ecf20Sopenharmony_ci}
29748c2ecf20Sopenharmony_ci
29758c2ecf20Sopenharmony_cistatic int hns3_add_frag(struct hns3_enet_ring *ring)
29768c2ecf20Sopenharmony_ci{
29778c2ecf20Sopenharmony_ci	struct sk_buff *skb = ring->skb;
29788c2ecf20Sopenharmony_ci	struct sk_buff *head_skb = skb;
29798c2ecf20Sopenharmony_ci	struct sk_buff *new_skb;
29808c2ecf20Sopenharmony_ci	struct hns3_desc_cb *desc_cb;
29818c2ecf20Sopenharmony_ci	struct hns3_desc *desc;
29828c2ecf20Sopenharmony_ci	u32 bd_base_info;
29838c2ecf20Sopenharmony_ci
29848c2ecf20Sopenharmony_ci	do {
29858c2ecf20Sopenharmony_ci		desc = &ring->desc[ring->next_to_clean];
29868c2ecf20Sopenharmony_ci		desc_cb = &ring->desc_cb[ring->next_to_clean];
29878c2ecf20Sopenharmony_ci		bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
29888c2ecf20Sopenharmony_ci		/* make sure HW write desc complete */
29898c2ecf20Sopenharmony_ci		dma_rmb();
29908c2ecf20Sopenharmony_ci		if (!(bd_base_info & BIT(HNS3_RXD_VLD_B)))
29918c2ecf20Sopenharmony_ci			return -ENXIO;
29928c2ecf20Sopenharmony_ci
29938c2ecf20Sopenharmony_ci		if (unlikely(ring->frag_num >= MAX_SKB_FRAGS)) {
29948c2ecf20Sopenharmony_ci			new_skb = napi_alloc_skb(&ring->tqp_vector->napi, 0);
29958c2ecf20Sopenharmony_ci			if (unlikely(!new_skb)) {
29968c2ecf20Sopenharmony_ci				hns3_rl_err(ring_to_netdev(ring),
29978c2ecf20Sopenharmony_ci					    "alloc rx fraglist skb fail\n");
29988c2ecf20Sopenharmony_ci				return -ENXIO;
29998c2ecf20Sopenharmony_ci			}
30008c2ecf20Sopenharmony_ci			ring->frag_num = 0;
30018c2ecf20Sopenharmony_ci
30028c2ecf20Sopenharmony_ci			if (ring->tail_skb) {
30038c2ecf20Sopenharmony_ci				ring->tail_skb->next = new_skb;
30048c2ecf20Sopenharmony_ci				ring->tail_skb = new_skb;
30058c2ecf20Sopenharmony_ci			} else {
30068c2ecf20Sopenharmony_ci				skb_shinfo(skb)->frag_list = new_skb;
30078c2ecf20Sopenharmony_ci				ring->tail_skb = new_skb;
30088c2ecf20Sopenharmony_ci			}
30098c2ecf20Sopenharmony_ci		}
30108c2ecf20Sopenharmony_ci
30118c2ecf20Sopenharmony_ci		if (ring->tail_skb) {
30128c2ecf20Sopenharmony_ci			head_skb->truesize += hns3_buf_size(ring);
30138c2ecf20Sopenharmony_ci			head_skb->data_len += le16_to_cpu(desc->rx.size);
30148c2ecf20Sopenharmony_ci			head_skb->len += le16_to_cpu(desc->rx.size);
30158c2ecf20Sopenharmony_ci			skb = ring->tail_skb;
30168c2ecf20Sopenharmony_ci		}
30178c2ecf20Sopenharmony_ci
30188c2ecf20Sopenharmony_ci		dma_sync_single_for_cpu(ring_to_dev(ring),
30198c2ecf20Sopenharmony_ci				desc_cb->dma + desc_cb->page_offset,
30208c2ecf20Sopenharmony_ci				hns3_buf_size(ring),
30218c2ecf20Sopenharmony_ci				DMA_FROM_DEVICE);
30228c2ecf20Sopenharmony_ci
30238c2ecf20Sopenharmony_ci		hns3_nic_reuse_page(skb, ring->frag_num++, ring, 0, desc_cb);
30248c2ecf20Sopenharmony_ci		trace_hns3_rx_desc(ring);
30258c2ecf20Sopenharmony_ci		hns3_rx_ring_move_fw(ring);
30268c2ecf20Sopenharmony_ci		ring->pending_buf++;
30278c2ecf20Sopenharmony_ci	} while (!(bd_base_info & BIT(HNS3_RXD_FE_B)));
30288c2ecf20Sopenharmony_ci
30298c2ecf20Sopenharmony_ci	return 0;
30308c2ecf20Sopenharmony_ci}
30318c2ecf20Sopenharmony_ci
30328c2ecf20Sopenharmony_cistatic int hns3_set_gro_and_checksum(struct hns3_enet_ring *ring,
30338c2ecf20Sopenharmony_ci				     struct sk_buff *skb, u32 l234info,
30348c2ecf20Sopenharmony_ci				     u32 bd_base_info, u32 ol_info)
30358c2ecf20Sopenharmony_ci{
30368c2ecf20Sopenharmony_ci	u32 l3_type;
30378c2ecf20Sopenharmony_ci
30388c2ecf20Sopenharmony_ci	skb_shinfo(skb)->gso_size = hnae3_get_field(bd_base_info,
30398c2ecf20Sopenharmony_ci						    HNS3_RXD_GRO_SIZE_M,
30408c2ecf20Sopenharmony_ci						    HNS3_RXD_GRO_SIZE_S);
30418c2ecf20Sopenharmony_ci	/* if there is no HW GRO, do not set gro params */
30428c2ecf20Sopenharmony_ci	if (!skb_shinfo(skb)->gso_size) {
30438c2ecf20Sopenharmony_ci		hns3_rx_checksum(ring, skb, l234info, bd_base_info, ol_info);
30448c2ecf20Sopenharmony_ci		return 0;
30458c2ecf20Sopenharmony_ci	}
30468c2ecf20Sopenharmony_ci
30478c2ecf20Sopenharmony_ci	NAPI_GRO_CB(skb)->count = hnae3_get_field(l234info,
30488c2ecf20Sopenharmony_ci						  HNS3_RXD_GRO_COUNT_M,
30498c2ecf20Sopenharmony_ci						  HNS3_RXD_GRO_COUNT_S);
30508c2ecf20Sopenharmony_ci
30518c2ecf20Sopenharmony_ci	l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M, HNS3_RXD_L3ID_S);
30528c2ecf20Sopenharmony_ci	if (l3_type == HNS3_L3_TYPE_IPV4)
30538c2ecf20Sopenharmony_ci		skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
30548c2ecf20Sopenharmony_ci	else if (l3_type == HNS3_L3_TYPE_IPV6)
30558c2ecf20Sopenharmony_ci		skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
30568c2ecf20Sopenharmony_ci	else
30578c2ecf20Sopenharmony_ci		return -EFAULT;
30588c2ecf20Sopenharmony_ci
30598c2ecf20Sopenharmony_ci	return  hns3_gro_complete(skb, l234info);
30608c2ecf20Sopenharmony_ci}
30618c2ecf20Sopenharmony_ci
30628c2ecf20Sopenharmony_cistatic void hns3_set_rx_skb_rss_type(struct hns3_enet_ring *ring,
30638c2ecf20Sopenharmony_ci				     struct sk_buff *skb, u32 rss_hash)
30648c2ecf20Sopenharmony_ci{
30658c2ecf20Sopenharmony_ci	struct hnae3_handle *handle = ring->tqp->handle;
30668c2ecf20Sopenharmony_ci	enum pkt_hash_types rss_type;
30678c2ecf20Sopenharmony_ci
30688c2ecf20Sopenharmony_ci	if (rss_hash)
30698c2ecf20Sopenharmony_ci		rss_type = handle->kinfo.rss_type;
30708c2ecf20Sopenharmony_ci	else
30718c2ecf20Sopenharmony_ci		rss_type = PKT_HASH_TYPE_NONE;
30728c2ecf20Sopenharmony_ci
30738c2ecf20Sopenharmony_ci	skb_set_hash(skb, rss_hash, rss_type);
30748c2ecf20Sopenharmony_ci}
30758c2ecf20Sopenharmony_ci
30768c2ecf20Sopenharmony_cistatic int hns3_handle_bdinfo(struct hns3_enet_ring *ring, struct sk_buff *skb)
30778c2ecf20Sopenharmony_ci{
30788c2ecf20Sopenharmony_ci	struct net_device *netdev = ring_to_netdev(ring);
30798c2ecf20Sopenharmony_ci	enum hns3_pkt_l2t_type l2_frame_type;
30808c2ecf20Sopenharmony_ci	u32 bd_base_info, l234info, ol_info;
30818c2ecf20Sopenharmony_ci	struct hns3_desc *desc;
30828c2ecf20Sopenharmony_ci	unsigned int len;
30838c2ecf20Sopenharmony_ci	int pre_ntc, ret;
30848c2ecf20Sopenharmony_ci
30858c2ecf20Sopenharmony_ci	/* bdinfo handled below is only valid on the last BD of the
30868c2ecf20Sopenharmony_ci	 * current packet, and ring->next_to_clean indicates the first
30878c2ecf20Sopenharmony_ci	 * descriptor of next packet, so need - 1 below.
30888c2ecf20Sopenharmony_ci	 */
30898c2ecf20Sopenharmony_ci	pre_ntc = ring->next_to_clean ? (ring->next_to_clean - 1) :
30908c2ecf20Sopenharmony_ci					(ring->desc_num - 1);
30918c2ecf20Sopenharmony_ci	desc = &ring->desc[pre_ntc];
30928c2ecf20Sopenharmony_ci	bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
30938c2ecf20Sopenharmony_ci	l234info = le32_to_cpu(desc->rx.l234_info);
30948c2ecf20Sopenharmony_ci	ol_info = le32_to_cpu(desc->rx.ol_info);
30958c2ecf20Sopenharmony_ci
30968c2ecf20Sopenharmony_ci	/* Based on hw strategy, the tag offloaded will be stored at
30978c2ecf20Sopenharmony_ci	 * ot_vlan_tag in two layer tag case, and stored at vlan_tag
30988c2ecf20Sopenharmony_ci	 * in one layer tag case.
30998c2ecf20Sopenharmony_ci	 */
31008c2ecf20Sopenharmony_ci	if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
31018c2ecf20Sopenharmony_ci		u16 vlan_tag;
31028c2ecf20Sopenharmony_ci
31038c2ecf20Sopenharmony_ci		if (hns3_parse_vlan_tag(ring, desc, l234info, &vlan_tag))
31048c2ecf20Sopenharmony_ci			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
31058c2ecf20Sopenharmony_ci					       vlan_tag);
31068c2ecf20Sopenharmony_ci	}
31078c2ecf20Sopenharmony_ci
31088c2ecf20Sopenharmony_ci	if (unlikely(!desc->rx.pkt_len || (l234info & (BIT(HNS3_RXD_TRUNCAT_B) |
31098c2ecf20Sopenharmony_ci				  BIT(HNS3_RXD_L2E_B))))) {
31108c2ecf20Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
31118c2ecf20Sopenharmony_ci		if (l234info & BIT(HNS3_RXD_L2E_B))
31128c2ecf20Sopenharmony_ci			ring->stats.l2_err++;
31138c2ecf20Sopenharmony_ci		else
31148c2ecf20Sopenharmony_ci			ring->stats.err_pkt_len++;
31158c2ecf20Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
31168c2ecf20Sopenharmony_ci
31178c2ecf20Sopenharmony_ci		return -EFAULT;
31188c2ecf20Sopenharmony_ci	}
31198c2ecf20Sopenharmony_ci
31208c2ecf20Sopenharmony_ci	len = skb->len;
31218c2ecf20Sopenharmony_ci
31228c2ecf20Sopenharmony_ci	/* Do update ip stack process */
31238c2ecf20Sopenharmony_ci	skb->protocol = eth_type_trans(skb, netdev);
31248c2ecf20Sopenharmony_ci
31258c2ecf20Sopenharmony_ci	/* This is needed in order to enable forwarding support */
31268c2ecf20Sopenharmony_ci	ret = hns3_set_gro_and_checksum(ring, skb, l234info,
31278c2ecf20Sopenharmony_ci					bd_base_info, ol_info);
31288c2ecf20Sopenharmony_ci	if (unlikely(ret)) {
31298c2ecf20Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
31308c2ecf20Sopenharmony_ci		ring->stats.rx_err_cnt++;
31318c2ecf20Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
31328c2ecf20Sopenharmony_ci		return ret;
31338c2ecf20Sopenharmony_ci	}
31348c2ecf20Sopenharmony_ci
31358c2ecf20Sopenharmony_ci	l2_frame_type = hnae3_get_field(l234info, HNS3_RXD_DMAC_M,
31368c2ecf20Sopenharmony_ci					HNS3_RXD_DMAC_S);
31378c2ecf20Sopenharmony_ci
31388c2ecf20Sopenharmony_ci	u64_stats_update_begin(&ring->syncp);
31398c2ecf20Sopenharmony_ci	ring->stats.rx_pkts++;
31408c2ecf20Sopenharmony_ci	ring->stats.rx_bytes += len;
31418c2ecf20Sopenharmony_ci
31428c2ecf20Sopenharmony_ci	if (l2_frame_type == HNS3_L2_TYPE_MULTICAST)
31438c2ecf20Sopenharmony_ci		ring->stats.rx_multicast++;
31448c2ecf20Sopenharmony_ci
31458c2ecf20Sopenharmony_ci	u64_stats_update_end(&ring->syncp);
31468c2ecf20Sopenharmony_ci
31478c2ecf20Sopenharmony_ci	ring->tqp_vector->rx_group.total_bytes += len;
31488c2ecf20Sopenharmony_ci
31498c2ecf20Sopenharmony_ci	hns3_set_rx_skb_rss_type(ring, skb, le32_to_cpu(desc->rx.rss_hash));
31508c2ecf20Sopenharmony_ci	return 0;
31518c2ecf20Sopenharmony_ci}
31528c2ecf20Sopenharmony_ci
31538c2ecf20Sopenharmony_cistatic int hns3_handle_rx_bd(struct hns3_enet_ring *ring)
31548c2ecf20Sopenharmony_ci{
31558c2ecf20Sopenharmony_ci	struct sk_buff *skb = ring->skb;
31568c2ecf20Sopenharmony_ci	struct hns3_desc_cb *desc_cb;
31578c2ecf20Sopenharmony_ci	struct hns3_desc *desc;
31588c2ecf20Sopenharmony_ci	unsigned int length;
31598c2ecf20Sopenharmony_ci	u32 bd_base_info;
31608c2ecf20Sopenharmony_ci	int ret;
31618c2ecf20Sopenharmony_ci
31628c2ecf20Sopenharmony_ci	desc = &ring->desc[ring->next_to_clean];
31638c2ecf20Sopenharmony_ci	desc_cb = &ring->desc_cb[ring->next_to_clean];
31648c2ecf20Sopenharmony_ci
31658c2ecf20Sopenharmony_ci	prefetch(desc);
31668c2ecf20Sopenharmony_ci
31678c2ecf20Sopenharmony_ci	if (!skb) {
31688c2ecf20Sopenharmony_ci		bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
31698c2ecf20Sopenharmony_ci
31708c2ecf20Sopenharmony_ci		/* Check valid BD */
31718c2ecf20Sopenharmony_ci		if (unlikely(!(bd_base_info & BIT(HNS3_RXD_VLD_B))))
31728c2ecf20Sopenharmony_ci			return -ENXIO;
31738c2ecf20Sopenharmony_ci
31748c2ecf20Sopenharmony_ci		dma_rmb();
31758c2ecf20Sopenharmony_ci		length = le16_to_cpu(desc->rx.size);
31768c2ecf20Sopenharmony_ci
31778c2ecf20Sopenharmony_ci		ring->va = desc_cb->buf + desc_cb->page_offset;
31788c2ecf20Sopenharmony_ci
31798c2ecf20Sopenharmony_ci		dma_sync_single_for_cpu(ring_to_dev(ring),
31808c2ecf20Sopenharmony_ci				desc_cb->dma + desc_cb->page_offset,
31818c2ecf20Sopenharmony_ci				hns3_buf_size(ring),
31828c2ecf20Sopenharmony_ci				DMA_FROM_DEVICE);
31838c2ecf20Sopenharmony_ci
31848c2ecf20Sopenharmony_ci		/* Prefetch first cache line of first page.
31858c2ecf20Sopenharmony_ci		 * Idea is to cache few bytes of the header of the packet.
31868c2ecf20Sopenharmony_ci		 * Our L1 Cache line size is 64B so need to prefetch twice to make
31878c2ecf20Sopenharmony_ci		 * it 128B. But in actual we can have greater size of caches with
31888c2ecf20Sopenharmony_ci		 * 128B Level 1 cache lines. In such a case, single fetch would
31898c2ecf20Sopenharmony_ci		 * suffice to cache in the relevant part of the header.
31908c2ecf20Sopenharmony_ci		 */
31918c2ecf20Sopenharmony_ci		net_prefetch(ring->va);
31928c2ecf20Sopenharmony_ci
31938c2ecf20Sopenharmony_ci		ret = hns3_alloc_skb(ring, length, ring->va);
31948c2ecf20Sopenharmony_ci		skb = ring->skb;
31958c2ecf20Sopenharmony_ci
31968c2ecf20Sopenharmony_ci		if (ret < 0) /* alloc buffer fail */
31978c2ecf20Sopenharmony_ci			return ret;
31988c2ecf20Sopenharmony_ci		if (!(bd_base_info & BIT(HNS3_RXD_FE_B))) { /* need add frag */
31998c2ecf20Sopenharmony_ci			ret = hns3_add_frag(ring);
32008c2ecf20Sopenharmony_ci			if (ret)
32018c2ecf20Sopenharmony_ci				return ret;
32028c2ecf20Sopenharmony_ci		}
32038c2ecf20Sopenharmony_ci	} else {
32048c2ecf20Sopenharmony_ci		ret = hns3_add_frag(ring);
32058c2ecf20Sopenharmony_ci		if (ret)
32068c2ecf20Sopenharmony_ci			return ret;
32078c2ecf20Sopenharmony_ci	}
32088c2ecf20Sopenharmony_ci
32098c2ecf20Sopenharmony_ci	/* As the head data may be changed when GRO enable, copy
32108c2ecf20Sopenharmony_ci	 * the head data in after other data rx completed
32118c2ecf20Sopenharmony_ci	 */
32128c2ecf20Sopenharmony_ci	if (skb->len > HNS3_RX_HEAD_SIZE)
32138c2ecf20Sopenharmony_ci		memcpy(skb->data, ring->va,
32148c2ecf20Sopenharmony_ci		       ALIGN(ring->pull_len, sizeof(long)));
32158c2ecf20Sopenharmony_ci
32168c2ecf20Sopenharmony_ci	ret = hns3_handle_bdinfo(ring, skb);
32178c2ecf20Sopenharmony_ci	if (unlikely(ret)) {
32188c2ecf20Sopenharmony_ci		dev_kfree_skb_any(skb);
32198c2ecf20Sopenharmony_ci		return ret;
32208c2ecf20Sopenharmony_ci	}
32218c2ecf20Sopenharmony_ci
32228c2ecf20Sopenharmony_ci	skb_record_rx_queue(skb, ring->tqp->tqp_index);
32238c2ecf20Sopenharmony_ci	return 0;
32248c2ecf20Sopenharmony_ci}
32258c2ecf20Sopenharmony_ci
32268c2ecf20Sopenharmony_ciint hns3_clean_rx_ring(struct hns3_enet_ring *ring, int budget,
32278c2ecf20Sopenharmony_ci		       void (*rx_fn)(struct hns3_enet_ring *, struct sk_buff *))
32288c2ecf20Sopenharmony_ci{
32298c2ecf20Sopenharmony_ci#define RCB_NOF_ALLOC_RX_BUFF_ONCE 16
32308c2ecf20Sopenharmony_ci	int unused_count = hns3_desc_unused(ring);
32318c2ecf20Sopenharmony_ci	bool failure = false;
32328c2ecf20Sopenharmony_ci	int recv_pkts = 0;
32338c2ecf20Sopenharmony_ci	int err;
32348c2ecf20Sopenharmony_ci
32358c2ecf20Sopenharmony_ci	unused_count -= ring->pending_buf;
32368c2ecf20Sopenharmony_ci
32378c2ecf20Sopenharmony_ci	while (recv_pkts < budget) {
32388c2ecf20Sopenharmony_ci		/* Reuse or realloc buffers */
32398c2ecf20Sopenharmony_ci		if (unused_count >= RCB_NOF_ALLOC_RX_BUFF_ONCE) {
32408c2ecf20Sopenharmony_ci			failure = failure ||
32418c2ecf20Sopenharmony_ci				hns3_nic_alloc_rx_buffers(ring, unused_count);
32428c2ecf20Sopenharmony_ci			unused_count = 0;
32438c2ecf20Sopenharmony_ci		}
32448c2ecf20Sopenharmony_ci
32458c2ecf20Sopenharmony_ci		/* Poll one pkt */
32468c2ecf20Sopenharmony_ci		err = hns3_handle_rx_bd(ring);
32478c2ecf20Sopenharmony_ci		/* Do not get FE for the packet or failed to alloc skb */
32488c2ecf20Sopenharmony_ci		if (unlikely(!ring->skb || err == -ENXIO)) {
32498c2ecf20Sopenharmony_ci			goto out;
32508c2ecf20Sopenharmony_ci		} else if (likely(!err)) {
32518c2ecf20Sopenharmony_ci			rx_fn(ring, ring->skb);
32528c2ecf20Sopenharmony_ci			recv_pkts++;
32538c2ecf20Sopenharmony_ci		}
32548c2ecf20Sopenharmony_ci
32558c2ecf20Sopenharmony_ci		unused_count += ring->pending_buf;
32568c2ecf20Sopenharmony_ci		ring->skb = NULL;
32578c2ecf20Sopenharmony_ci		ring->pending_buf = 0;
32588c2ecf20Sopenharmony_ci	}
32598c2ecf20Sopenharmony_ci
32608c2ecf20Sopenharmony_ciout:
32618c2ecf20Sopenharmony_ci	return failure ? budget : recv_pkts;
32628c2ecf20Sopenharmony_ci}
32638c2ecf20Sopenharmony_ci
32648c2ecf20Sopenharmony_cistatic bool hns3_get_new_flow_lvl(struct hns3_enet_ring_group *ring_group)
32658c2ecf20Sopenharmony_ci{
32668c2ecf20Sopenharmony_ci#define HNS3_RX_LOW_BYTE_RATE 10000
32678c2ecf20Sopenharmony_ci#define HNS3_RX_MID_BYTE_RATE 20000
32688c2ecf20Sopenharmony_ci#define HNS3_RX_ULTRA_PACKET_RATE 40
32698c2ecf20Sopenharmony_ci
32708c2ecf20Sopenharmony_ci	enum hns3_flow_level_range new_flow_level;
32718c2ecf20Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector;
32728c2ecf20Sopenharmony_ci	int packets_per_msecs, bytes_per_msecs;
32738c2ecf20Sopenharmony_ci	u32 time_passed_ms;
32748c2ecf20Sopenharmony_ci
32758c2ecf20Sopenharmony_ci	tqp_vector = ring_group->ring->tqp_vector;
32768c2ecf20Sopenharmony_ci	time_passed_ms =
32778c2ecf20Sopenharmony_ci		jiffies_to_msecs(jiffies - tqp_vector->last_jiffies);
32788c2ecf20Sopenharmony_ci	if (!time_passed_ms)
32798c2ecf20Sopenharmony_ci		return false;
32808c2ecf20Sopenharmony_ci
32818c2ecf20Sopenharmony_ci	do_div(ring_group->total_packets, time_passed_ms);
32828c2ecf20Sopenharmony_ci	packets_per_msecs = ring_group->total_packets;
32838c2ecf20Sopenharmony_ci
32848c2ecf20Sopenharmony_ci	do_div(ring_group->total_bytes, time_passed_ms);
32858c2ecf20Sopenharmony_ci	bytes_per_msecs = ring_group->total_bytes;
32868c2ecf20Sopenharmony_ci
32878c2ecf20Sopenharmony_ci	new_flow_level = ring_group->coal.flow_level;
32888c2ecf20Sopenharmony_ci
32898c2ecf20Sopenharmony_ci	/* Simple throttlerate management
32908c2ecf20Sopenharmony_ci	 * 0-10MB/s   lower     (50000 ints/s)
32918c2ecf20Sopenharmony_ci	 * 10-20MB/s   middle    (20000 ints/s)
32928c2ecf20Sopenharmony_ci	 * 20-1249MB/s high      (18000 ints/s)
32938c2ecf20Sopenharmony_ci	 * > 40000pps  ultra     (8000 ints/s)
32948c2ecf20Sopenharmony_ci	 */
32958c2ecf20Sopenharmony_ci	switch (new_flow_level) {
32968c2ecf20Sopenharmony_ci	case HNS3_FLOW_LOW:
32978c2ecf20Sopenharmony_ci		if (bytes_per_msecs > HNS3_RX_LOW_BYTE_RATE)
32988c2ecf20Sopenharmony_ci			new_flow_level = HNS3_FLOW_MID;
32998c2ecf20Sopenharmony_ci		break;
33008c2ecf20Sopenharmony_ci	case HNS3_FLOW_MID:
33018c2ecf20Sopenharmony_ci		if (bytes_per_msecs > HNS3_RX_MID_BYTE_RATE)
33028c2ecf20Sopenharmony_ci			new_flow_level = HNS3_FLOW_HIGH;
33038c2ecf20Sopenharmony_ci		else if (bytes_per_msecs <= HNS3_RX_LOW_BYTE_RATE)
33048c2ecf20Sopenharmony_ci			new_flow_level = HNS3_FLOW_LOW;
33058c2ecf20Sopenharmony_ci		break;
33068c2ecf20Sopenharmony_ci	case HNS3_FLOW_HIGH:
33078c2ecf20Sopenharmony_ci	case HNS3_FLOW_ULTRA:
33088c2ecf20Sopenharmony_ci	default:
33098c2ecf20Sopenharmony_ci		if (bytes_per_msecs <= HNS3_RX_MID_BYTE_RATE)
33108c2ecf20Sopenharmony_ci			new_flow_level = HNS3_FLOW_MID;
33118c2ecf20Sopenharmony_ci		break;
33128c2ecf20Sopenharmony_ci	}
33138c2ecf20Sopenharmony_ci
33148c2ecf20Sopenharmony_ci	if (packets_per_msecs > HNS3_RX_ULTRA_PACKET_RATE &&
33158c2ecf20Sopenharmony_ci	    &tqp_vector->rx_group == ring_group)
33168c2ecf20Sopenharmony_ci		new_flow_level = HNS3_FLOW_ULTRA;
33178c2ecf20Sopenharmony_ci
33188c2ecf20Sopenharmony_ci	ring_group->total_bytes = 0;
33198c2ecf20Sopenharmony_ci	ring_group->total_packets = 0;
33208c2ecf20Sopenharmony_ci	ring_group->coal.flow_level = new_flow_level;
33218c2ecf20Sopenharmony_ci
33228c2ecf20Sopenharmony_ci	return true;
33238c2ecf20Sopenharmony_ci}
33248c2ecf20Sopenharmony_ci
33258c2ecf20Sopenharmony_cistatic bool hns3_get_new_int_gl(struct hns3_enet_ring_group *ring_group)
33268c2ecf20Sopenharmony_ci{
33278c2ecf20Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector;
33288c2ecf20Sopenharmony_ci	u16 new_int_gl;
33298c2ecf20Sopenharmony_ci
33308c2ecf20Sopenharmony_ci	if (!ring_group->ring)
33318c2ecf20Sopenharmony_ci		return false;
33328c2ecf20Sopenharmony_ci
33338c2ecf20Sopenharmony_ci	tqp_vector = ring_group->ring->tqp_vector;
33348c2ecf20Sopenharmony_ci	if (!tqp_vector->last_jiffies)
33358c2ecf20Sopenharmony_ci		return false;
33368c2ecf20Sopenharmony_ci
33378c2ecf20Sopenharmony_ci	if (ring_group->total_packets == 0) {
33388c2ecf20Sopenharmony_ci		ring_group->coal.int_gl = HNS3_INT_GL_50K;
33398c2ecf20Sopenharmony_ci		ring_group->coal.flow_level = HNS3_FLOW_LOW;
33408c2ecf20Sopenharmony_ci		return true;
33418c2ecf20Sopenharmony_ci	}
33428c2ecf20Sopenharmony_ci
33438c2ecf20Sopenharmony_ci	if (!hns3_get_new_flow_lvl(ring_group))
33448c2ecf20Sopenharmony_ci		return false;
33458c2ecf20Sopenharmony_ci
33468c2ecf20Sopenharmony_ci	new_int_gl = ring_group->coal.int_gl;
33478c2ecf20Sopenharmony_ci	switch (ring_group->coal.flow_level) {
33488c2ecf20Sopenharmony_ci	case HNS3_FLOW_LOW:
33498c2ecf20Sopenharmony_ci		new_int_gl = HNS3_INT_GL_50K;
33508c2ecf20Sopenharmony_ci		break;
33518c2ecf20Sopenharmony_ci	case HNS3_FLOW_MID:
33528c2ecf20Sopenharmony_ci		new_int_gl = HNS3_INT_GL_20K;
33538c2ecf20Sopenharmony_ci		break;
33548c2ecf20Sopenharmony_ci	case HNS3_FLOW_HIGH:
33558c2ecf20Sopenharmony_ci		new_int_gl = HNS3_INT_GL_18K;
33568c2ecf20Sopenharmony_ci		break;
33578c2ecf20Sopenharmony_ci	case HNS3_FLOW_ULTRA:
33588c2ecf20Sopenharmony_ci		new_int_gl = HNS3_INT_GL_8K;
33598c2ecf20Sopenharmony_ci		break;
33608c2ecf20Sopenharmony_ci	default:
33618c2ecf20Sopenharmony_ci		break;
33628c2ecf20Sopenharmony_ci	}
33638c2ecf20Sopenharmony_ci
33648c2ecf20Sopenharmony_ci	if (new_int_gl != ring_group->coal.int_gl) {
33658c2ecf20Sopenharmony_ci		ring_group->coal.int_gl = new_int_gl;
33668c2ecf20Sopenharmony_ci		return true;
33678c2ecf20Sopenharmony_ci	}
33688c2ecf20Sopenharmony_ci	return false;
33698c2ecf20Sopenharmony_ci}
33708c2ecf20Sopenharmony_ci
33718c2ecf20Sopenharmony_cistatic void hns3_update_new_int_gl(struct hns3_enet_tqp_vector *tqp_vector)
33728c2ecf20Sopenharmony_ci{
33738c2ecf20Sopenharmony_ci	struct hns3_enet_ring_group *rx_group = &tqp_vector->rx_group;
33748c2ecf20Sopenharmony_ci	struct hns3_enet_ring_group *tx_group = &tqp_vector->tx_group;
33758c2ecf20Sopenharmony_ci	bool rx_update, tx_update;
33768c2ecf20Sopenharmony_ci
33778c2ecf20Sopenharmony_ci	/* update param every 1000ms */
33788c2ecf20Sopenharmony_ci	if (time_before(jiffies,
33798c2ecf20Sopenharmony_ci			tqp_vector->last_jiffies + msecs_to_jiffies(1000)))
33808c2ecf20Sopenharmony_ci		return;
33818c2ecf20Sopenharmony_ci
33828c2ecf20Sopenharmony_ci	if (rx_group->coal.gl_adapt_enable) {
33838c2ecf20Sopenharmony_ci		rx_update = hns3_get_new_int_gl(rx_group);
33848c2ecf20Sopenharmony_ci		if (rx_update)
33858c2ecf20Sopenharmony_ci			hns3_set_vector_coalesce_rx_gl(tqp_vector,
33868c2ecf20Sopenharmony_ci						       rx_group->coal.int_gl);
33878c2ecf20Sopenharmony_ci	}
33888c2ecf20Sopenharmony_ci
33898c2ecf20Sopenharmony_ci	if (tx_group->coal.gl_adapt_enable) {
33908c2ecf20Sopenharmony_ci		tx_update = hns3_get_new_int_gl(tx_group);
33918c2ecf20Sopenharmony_ci		if (tx_update)
33928c2ecf20Sopenharmony_ci			hns3_set_vector_coalesce_tx_gl(tqp_vector,
33938c2ecf20Sopenharmony_ci						       tx_group->coal.int_gl);
33948c2ecf20Sopenharmony_ci	}
33958c2ecf20Sopenharmony_ci
33968c2ecf20Sopenharmony_ci	tqp_vector->last_jiffies = jiffies;
33978c2ecf20Sopenharmony_ci}
33988c2ecf20Sopenharmony_ci
33998c2ecf20Sopenharmony_cistatic int hns3_nic_common_poll(struct napi_struct *napi, int budget)
34008c2ecf20Sopenharmony_ci{
34018c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(napi->dev);
34028c2ecf20Sopenharmony_ci	struct hns3_enet_ring *ring;
34038c2ecf20Sopenharmony_ci	int rx_pkt_total = 0;
34048c2ecf20Sopenharmony_ci
34058c2ecf20Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector =
34068c2ecf20Sopenharmony_ci		container_of(napi, struct hns3_enet_tqp_vector, napi);
34078c2ecf20Sopenharmony_ci	bool clean_complete = true;
34088c2ecf20Sopenharmony_ci	int rx_budget = budget;
34098c2ecf20Sopenharmony_ci
34108c2ecf20Sopenharmony_ci	if (unlikely(test_bit(HNS3_NIC_STATE_DOWN, &priv->state))) {
34118c2ecf20Sopenharmony_ci		napi_complete(napi);
34128c2ecf20Sopenharmony_ci		return 0;
34138c2ecf20Sopenharmony_ci	}
34148c2ecf20Sopenharmony_ci
34158c2ecf20Sopenharmony_ci	/* Since the actual Tx work is minimal, we can give the Tx a larger
34168c2ecf20Sopenharmony_ci	 * budget and be more aggressive about cleaning up the Tx descriptors.
34178c2ecf20Sopenharmony_ci	 */
34188c2ecf20Sopenharmony_ci	hns3_for_each_ring(ring, tqp_vector->tx_group)
34198c2ecf20Sopenharmony_ci		hns3_clean_tx_ring(ring, budget);
34208c2ecf20Sopenharmony_ci
34218c2ecf20Sopenharmony_ci	/* make sure rx ring budget not smaller than 1 */
34228c2ecf20Sopenharmony_ci	if (tqp_vector->num_tqps > 1)
34238c2ecf20Sopenharmony_ci		rx_budget = max(budget / tqp_vector->num_tqps, 1);
34248c2ecf20Sopenharmony_ci
34258c2ecf20Sopenharmony_ci	hns3_for_each_ring(ring, tqp_vector->rx_group) {
34268c2ecf20Sopenharmony_ci		int rx_cleaned = hns3_clean_rx_ring(ring, rx_budget,
34278c2ecf20Sopenharmony_ci						    hns3_rx_skb);
34288c2ecf20Sopenharmony_ci
34298c2ecf20Sopenharmony_ci		if (rx_cleaned >= rx_budget)
34308c2ecf20Sopenharmony_ci			clean_complete = false;
34318c2ecf20Sopenharmony_ci
34328c2ecf20Sopenharmony_ci		rx_pkt_total += rx_cleaned;
34338c2ecf20Sopenharmony_ci	}
34348c2ecf20Sopenharmony_ci
34358c2ecf20Sopenharmony_ci	tqp_vector->rx_group.total_packets += rx_pkt_total;
34368c2ecf20Sopenharmony_ci
34378c2ecf20Sopenharmony_ci	if (!clean_complete)
34388c2ecf20Sopenharmony_ci		return budget;
34398c2ecf20Sopenharmony_ci
34408c2ecf20Sopenharmony_ci	if (napi_complete(napi) &&
34418c2ecf20Sopenharmony_ci	    likely(!test_bit(HNS3_NIC_STATE_DOWN, &priv->state))) {
34428c2ecf20Sopenharmony_ci		hns3_update_new_int_gl(tqp_vector);
34438c2ecf20Sopenharmony_ci		hns3_mask_vector_irq(tqp_vector, 1);
34448c2ecf20Sopenharmony_ci	}
34458c2ecf20Sopenharmony_ci
34468c2ecf20Sopenharmony_ci	return rx_pkt_total;
34478c2ecf20Sopenharmony_ci}
34488c2ecf20Sopenharmony_ci
34498c2ecf20Sopenharmony_cistatic int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
34508c2ecf20Sopenharmony_ci				      struct hnae3_ring_chain_node *head)
34518c2ecf20Sopenharmony_ci{
34528c2ecf20Sopenharmony_ci	struct pci_dev *pdev = tqp_vector->handle->pdev;
34538c2ecf20Sopenharmony_ci	struct hnae3_ring_chain_node *cur_chain = head;
34548c2ecf20Sopenharmony_ci	struct hnae3_ring_chain_node *chain;
34558c2ecf20Sopenharmony_ci	struct hns3_enet_ring *tx_ring;
34568c2ecf20Sopenharmony_ci	struct hns3_enet_ring *rx_ring;
34578c2ecf20Sopenharmony_ci
34588c2ecf20Sopenharmony_ci	tx_ring = tqp_vector->tx_group.ring;
34598c2ecf20Sopenharmony_ci	if (tx_ring) {
34608c2ecf20Sopenharmony_ci		cur_chain->tqp_index = tx_ring->tqp->tqp_index;
34618c2ecf20Sopenharmony_ci		hnae3_set_bit(cur_chain->flag, HNAE3_RING_TYPE_B,
34628c2ecf20Sopenharmony_ci			      HNAE3_RING_TYPE_TX);
34638c2ecf20Sopenharmony_ci		hnae3_set_field(cur_chain->int_gl_idx, HNAE3_RING_GL_IDX_M,
34648c2ecf20Sopenharmony_ci				HNAE3_RING_GL_IDX_S, HNAE3_RING_GL_TX);
34658c2ecf20Sopenharmony_ci
34668c2ecf20Sopenharmony_ci		cur_chain->next = NULL;
34678c2ecf20Sopenharmony_ci
34688c2ecf20Sopenharmony_ci		while (tx_ring->next) {
34698c2ecf20Sopenharmony_ci			tx_ring = tx_ring->next;
34708c2ecf20Sopenharmony_ci
34718c2ecf20Sopenharmony_ci			chain = devm_kzalloc(&pdev->dev, sizeof(*chain),
34728c2ecf20Sopenharmony_ci					     GFP_KERNEL);
34738c2ecf20Sopenharmony_ci			if (!chain)
34748c2ecf20Sopenharmony_ci				goto err_free_chain;
34758c2ecf20Sopenharmony_ci
34768c2ecf20Sopenharmony_ci			cur_chain->next = chain;
34778c2ecf20Sopenharmony_ci			chain->tqp_index = tx_ring->tqp->tqp_index;
34788c2ecf20Sopenharmony_ci			hnae3_set_bit(chain->flag, HNAE3_RING_TYPE_B,
34798c2ecf20Sopenharmony_ci				      HNAE3_RING_TYPE_TX);
34808c2ecf20Sopenharmony_ci			hnae3_set_field(chain->int_gl_idx,
34818c2ecf20Sopenharmony_ci					HNAE3_RING_GL_IDX_M,
34828c2ecf20Sopenharmony_ci					HNAE3_RING_GL_IDX_S,
34838c2ecf20Sopenharmony_ci					HNAE3_RING_GL_TX);
34848c2ecf20Sopenharmony_ci
34858c2ecf20Sopenharmony_ci			cur_chain = chain;
34868c2ecf20Sopenharmony_ci		}
34878c2ecf20Sopenharmony_ci	}
34888c2ecf20Sopenharmony_ci
34898c2ecf20Sopenharmony_ci	rx_ring = tqp_vector->rx_group.ring;
34908c2ecf20Sopenharmony_ci	if (!tx_ring && rx_ring) {
34918c2ecf20Sopenharmony_ci		cur_chain->next = NULL;
34928c2ecf20Sopenharmony_ci		cur_chain->tqp_index = rx_ring->tqp->tqp_index;
34938c2ecf20Sopenharmony_ci		hnae3_set_bit(cur_chain->flag, HNAE3_RING_TYPE_B,
34948c2ecf20Sopenharmony_ci			      HNAE3_RING_TYPE_RX);
34958c2ecf20Sopenharmony_ci		hnae3_set_field(cur_chain->int_gl_idx, HNAE3_RING_GL_IDX_M,
34968c2ecf20Sopenharmony_ci				HNAE3_RING_GL_IDX_S, HNAE3_RING_GL_RX);
34978c2ecf20Sopenharmony_ci
34988c2ecf20Sopenharmony_ci		rx_ring = rx_ring->next;
34998c2ecf20Sopenharmony_ci	}
35008c2ecf20Sopenharmony_ci
35018c2ecf20Sopenharmony_ci	while (rx_ring) {
35028c2ecf20Sopenharmony_ci		chain = devm_kzalloc(&pdev->dev, sizeof(*chain), GFP_KERNEL);
35038c2ecf20Sopenharmony_ci		if (!chain)
35048c2ecf20Sopenharmony_ci			goto err_free_chain;
35058c2ecf20Sopenharmony_ci
35068c2ecf20Sopenharmony_ci		cur_chain->next = chain;
35078c2ecf20Sopenharmony_ci		chain->tqp_index = rx_ring->tqp->tqp_index;
35088c2ecf20Sopenharmony_ci		hnae3_set_bit(chain->flag, HNAE3_RING_TYPE_B,
35098c2ecf20Sopenharmony_ci			      HNAE3_RING_TYPE_RX);
35108c2ecf20Sopenharmony_ci		hnae3_set_field(chain->int_gl_idx, HNAE3_RING_GL_IDX_M,
35118c2ecf20Sopenharmony_ci				HNAE3_RING_GL_IDX_S, HNAE3_RING_GL_RX);
35128c2ecf20Sopenharmony_ci
35138c2ecf20Sopenharmony_ci		cur_chain = chain;
35148c2ecf20Sopenharmony_ci
35158c2ecf20Sopenharmony_ci		rx_ring = rx_ring->next;
35168c2ecf20Sopenharmony_ci	}
35178c2ecf20Sopenharmony_ci
35188c2ecf20Sopenharmony_ci	return 0;
35198c2ecf20Sopenharmony_ci
35208c2ecf20Sopenharmony_cierr_free_chain:
35218c2ecf20Sopenharmony_ci	cur_chain = head->next;
35228c2ecf20Sopenharmony_ci	while (cur_chain) {
35238c2ecf20Sopenharmony_ci		chain = cur_chain->next;
35248c2ecf20Sopenharmony_ci		devm_kfree(&pdev->dev, cur_chain);
35258c2ecf20Sopenharmony_ci		cur_chain = chain;
35268c2ecf20Sopenharmony_ci	}
35278c2ecf20Sopenharmony_ci	head->next = NULL;
35288c2ecf20Sopenharmony_ci
35298c2ecf20Sopenharmony_ci	return -ENOMEM;
35308c2ecf20Sopenharmony_ci}
35318c2ecf20Sopenharmony_ci
35328c2ecf20Sopenharmony_cistatic void hns3_free_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
35338c2ecf20Sopenharmony_ci					struct hnae3_ring_chain_node *head)
35348c2ecf20Sopenharmony_ci{
35358c2ecf20Sopenharmony_ci	struct pci_dev *pdev = tqp_vector->handle->pdev;
35368c2ecf20Sopenharmony_ci	struct hnae3_ring_chain_node *chain_tmp, *chain;
35378c2ecf20Sopenharmony_ci
35388c2ecf20Sopenharmony_ci	chain = head->next;
35398c2ecf20Sopenharmony_ci
35408c2ecf20Sopenharmony_ci	while (chain) {
35418c2ecf20Sopenharmony_ci		chain_tmp = chain->next;
35428c2ecf20Sopenharmony_ci		devm_kfree(&pdev->dev, chain);
35438c2ecf20Sopenharmony_ci		chain = chain_tmp;
35448c2ecf20Sopenharmony_ci	}
35458c2ecf20Sopenharmony_ci}
35468c2ecf20Sopenharmony_ci
35478c2ecf20Sopenharmony_cistatic void hns3_add_ring_to_group(struct hns3_enet_ring_group *group,
35488c2ecf20Sopenharmony_ci				   struct hns3_enet_ring *ring)
35498c2ecf20Sopenharmony_ci{
35508c2ecf20Sopenharmony_ci	ring->next = group->ring;
35518c2ecf20Sopenharmony_ci	group->ring = ring;
35528c2ecf20Sopenharmony_ci
35538c2ecf20Sopenharmony_ci	group->count++;
35548c2ecf20Sopenharmony_ci}
35558c2ecf20Sopenharmony_ci
35568c2ecf20Sopenharmony_cistatic void hns3_nic_set_cpumask(struct hns3_nic_priv *priv)
35578c2ecf20Sopenharmony_ci{
35588c2ecf20Sopenharmony_ci	struct pci_dev *pdev = priv->ae_handle->pdev;
35598c2ecf20Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector;
35608c2ecf20Sopenharmony_ci	int num_vectors = priv->vector_num;
35618c2ecf20Sopenharmony_ci	int numa_node;
35628c2ecf20Sopenharmony_ci	int vector_i;
35638c2ecf20Sopenharmony_ci
35648c2ecf20Sopenharmony_ci	numa_node = dev_to_node(&pdev->dev);
35658c2ecf20Sopenharmony_ci
35668c2ecf20Sopenharmony_ci	for (vector_i = 0; vector_i < num_vectors; vector_i++) {
35678c2ecf20Sopenharmony_ci		tqp_vector = &priv->tqp_vector[vector_i];
35688c2ecf20Sopenharmony_ci		cpumask_set_cpu(cpumask_local_spread(vector_i, numa_node),
35698c2ecf20Sopenharmony_ci				&tqp_vector->affinity_mask);
35708c2ecf20Sopenharmony_ci	}
35718c2ecf20Sopenharmony_ci}
35728c2ecf20Sopenharmony_ci
35738c2ecf20Sopenharmony_cistatic int hns3_nic_init_vector_data(struct hns3_nic_priv *priv)
35748c2ecf20Sopenharmony_ci{
35758c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
35768c2ecf20Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector;
35778c2ecf20Sopenharmony_ci	int ret;
35788c2ecf20Sopenharmony_ci	int i;
35798c2ecf20Sopenharmony_ci
35808c2ecf20Sopenharmony_ci	hns3_nic_set_cpumask(priv);
35818c2ecf20Sopenharmony_ci
35828c2ecf20Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
35838c2ecf20Sopenharmony_ci		tqp_vector = &priv->tqp_vector[i];
35848c2ecf20Sopenharmony_ci		hns3_vector_gl_rl_init_hw(tqp_vector, priv);
35858c2ecf20Sopenharmony_ci		tqp_vector->num_tqps = 0;
35868c2ecf20Sopenharmony_ci	}
35878c2ecf20Sopenharmony_ci
35888c2ecf20Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++) {
35898c2ecf20Sopenharmony_ci		u16 vector_i = i % priv->vector_num;
35908c2ecf20Sopenharmony_ci		u16 tqp_num = h->kinfo.num_tqps;
35918c2ecf20Sopenharmony_ci
35928c2ecf20Sopenharmony_ci		tqp_vector = &priv->tqp_vector[vector_i];
35938c2ecf20Sopenharmony_ci
35948c2ecf20Sopenharmony_ci		hns3_add_ring_to_group(&tqp_vector->tx_group,
35958c2ecf20Sopenharmony_ci				       &priv->ring[i]);
35968c2ecf20Sopenharmony_ci
35978c2ecf20Sopenharmony_ci		hns3_add_ring_to_group(&tqp_vector->rx_group,
35988c2ecf20Sopenharmony_ci				       &priv->ring[i + tqp_num]);
35998c2ecf20Sopenharmony_ci
36008c2ecf20Sopenharmony_ci		priv->ring[i].tqp_vector = tqp_vector;
36018c2ecf20Sopenharmony_ci		priv->ring[i + tqp_num].tqp_vector = tqp_vector;
36028c2ecf20Sopenharmony_ci		tqp_vector->num_tqps++;
36038c2ecf20Sopenharmony_ci	}
36048c2ecf20Sopenharmony_ci
36058c2ecf20Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
36068c2ecf20Sopenharmony_ci		struct hnae3_ring_chain_node vector_ring_chain;
36078c2ecf20Sopenharmony_ci
36088c2ecf20Sopenharmony_ci		tqp_vector = &priv->tqp_vector[i];
36098c2ecf20Sopenharmony_ci
36108c2ecf20Sopenharmony_ci		tqp_vector->rx_group.total_bytes = 0;
36118c2ecf20Sopenharmony_ci		tqp_vector->rx_group.total_packets = 0;
36128c2ecf20Sopenharmony_ci		tqp_vector->tx_group.total_bytes = 0;
36138c2ecf20Sopenharmony_ci		tqp_vector->tx_group.total_packets = 0;
36148c2ecf20Sopenharmony_ci		tqp_vector->handle = h;
36158c2ecf20Sopenharmony_ci
36168c2ecf20Sopenharmony_ci		ret = hns3_get_vector_ring_chain(tqp_vector,
36178c2ecf20Sopenharmony_ci						 &vector_ring_chain);
36188c2ecf20Sopenharmony_ci		if (ret)
36198c2ecf20Sopenharmony_ci			goto map_ring_fail;
36208c2ecf20Sopenharmony_ci
36218c2ecf20Sopenharmony_ci		ret = h->ae_algo->ops->map_ring_to_vector(h,
36228c2ecf20Sopenharmony_ci			tqp_vector->vector_irq, &vector_ring_chain);
36238c2ecf20Sopenharmony_ci
36248c2ecf20Sopenharmony_ci		hns3_free_vector_ring_chain(tqp_vector, &vector_ring_chain);
36258c2ecf20Sopenharmony_ci
36268c2ecf20Sopenharmony_ci		if (ret)
36278c2ecf20Sopenharmony_ci			goto map_ring_fail;
36288c2ecf20Sopenharmony_ci
36298c2ecf20Sopenharmony_ci		netif_napi_add(priv->netdev, &tqp_vector->napi,
36308c2ecf20Sopenharmony_ci			       hns3_nic_common_poll, NAPI_POLL_WEIGHT);
36318c2ecf20Sopenharmony_ci	}
36328c2ecf20Sopenharmony_ci
36338c2ecf20Sopenharmony_ci	return 0;
36348c2ecf20Sopenharmony_ci
36358c2ecf20Sopenharmony_cimap_ring_fail:
36368c2ecf20Sopenharmony_ci	while (i--)
36378c2ecf20Sopenharmony_ci		netif_napi_del(&priv->tqp_vector[i].napi);
36388c2ecf20Sopenharmony_ci
36398c2ecf20Sopenharmony_ci	return ret;
36408c2ecf20Sopenharmony_ci}
36418c2ecf20Sopenharmony_ci
36428c2ecf20Sopenharmony_cistatic int hns3_nic_alloc_vector_data(struct hns3_nic_priv *priv)
36438c2ecf20Sopenharmony_ci{
36448c2ecf20Sopenharmony_ci#define HNS3_VECTOR_PF_MAX_NUM		64
36458c2ecf20Sopenharmony_ci
36468c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
36478c2ecf20Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector;
36488c2ecf20Sopenharmony_ci	struct hnae3_vector_info *vector;
36498c2ecf20Sopenharmony_ci	struct pci_dev *pdev = h->pdev;
36508c2ecf20Sopenharmony_ci	u16 tqp_num = h->kinfo.num_tqps;
36518c2ecf20Sopenharmony_ci	u16 vector_num;
36528c2ecf20Sopenharmony_ci	int ret = 0;
36538c2ecf20Sopenharmony_ci	u16 i;
36548c2ecf20Sopenharmony_ci
36558c2ecf20Sopenharmony_ci	/* RSS size, cpu online and vector_num should be the same */
36568c2ecf20Sopenharmony_ci	/* Should consider 2p/4p later */
36578c2ecf20Sopenharmony_ci	vector_num = min_t(u16, num_online_cpus(), tqp_num);
36588c2ecf20Sopenharmony_ci	vector_num = min_t(u16, vector_num, HNS3_VECTOR_PF_MAX_NUM);
36598c2ecf20Sopenharmony_ci
36608c2ecf20Sopenharmony_ci	vector = devm_kcalloc(&pdev->dev, vector_num, sizeof(*vector),
36618c2ecf20Sopenharmony_ci			      GFP_KERNEL);
36628c2ecf20Sopenharmony_ci	if (!vector)
36638c2ecf20Sopenharmony_ci		return -ENOMEM;
36648c2ecf20Sopenharmony_ci
36658c2ecf20Sopenharmony_ci	/* save the actual available vector number */
36668c2ecf20Sopenharmony_ci	vector_num = h->ae_algo->ops->get_vector(h, vector_num, vector);
36678c2ecf20Sopenharmony_ci
36688c2ecf20Sopenharmony_ci	priv->vector_num = vector_num;
36698c2ecf20Sopenharmony_ci	priv->tqp_vector = (struct hns3_enet_tqp_vector *)
36708c2ecf20Sopenharmony_ci		devm_kcalloc(&pdev->dev, vector_num, sizeof(*priv->tqp_vector),
36718c2ecf20Sopenharmony_ci			     GFP_KERNEL);
36728c2ecf20Sopenharmony_ci	if (!priv->tqp_vector) {
36738c2ecf20Sopenharmony_ci		ret = -ENOMEM;
36748c2ecf20Sopenharmony_ci		goto out;
36758c2ecf20Sopenharmony_ci	}
36768c2ecf20Sopenharmony_ci
36778c2ecf20Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
36788c2ecf20Sopenharmony_ci		tqp_vector = &priv->tqp_vector[i];
36798c2ecf20Sopenharmony_ci		tqp_vector->idx = i;
36808c2ecf20Sopenharmony_ci		tqp_vector->mask_addr = vector[i].io_addr;
36818c2ecf20Sopenharmony_ci		tqp_vector->vector_irq = vector[i].vector;
36828c2ecf20Sopenharmony_ci		hns3_vector_gl_rl_init(tqp_vector, priv);
36838c2ecf20Sopenharmony_ci	}
36848c2ecf20Sopenharmony_ci
36858c2ecf20Sopenharmony_ciout:
36868c2ecf20Sopenharmony_ci	devm_kfree(&pdev->dev, vector);
36878c2ecf20Sopenharmony_ci	return ret;
36888c2ecf20Sopenharmony_ci}
36898c2ecf20Sopenharmony_ci
36908c2ecf20Sopenharmony_cistatic void hns3_clear_ring_group(struct hns3_enet_ring_group *group)
36918c2ecf20Sopenharmony_ci{
36928c2ecf20Sopenharmony_ci	group->ring = NULL;
36938c2ecf20Sopenharmony_ci	group->count = 0;
36948c2ecf20Sopenharmony_ci}
36958c2ecf20Sopenharmony_ci
36968c2ecf20Sopenharmony_cistatic void hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv)
36978c2ecf20Sopenharmony_ci{
36988c2ecf20Sopenharmony_ci	struct hnae3_ring_chain_node vector_ring_chain;
36998c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
37008c2ecf20Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector;
37018c2ecf20Sopenharmony_ci	int i;
37028c2ecf20Sopenharmony_ci
37038c2ecf20Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
37048c2ecf20Sopenharmony_ci		tqp_vector = &priv->tqp_vector[i];
37058c2ecf20Sopenharmony_ci
37068c2ecf20Sopenharmony_ci		if (!tqp_vector->rx_group.ring && !tqp_vector->tx_group.ring)
37078c2ecf20Sopenharmony_ci			continue;
37088c2ecf20Sopenharmony_ci
37098c2ecf20Sopenharmony_ci		/* Since the mapping can be overwritten, when fail to get the
37108c2ecf20Sopenharmony_ci		 * chain between vector and ring, we should go on to deal with
37118c2ecf20Sopenharmony_ci		 * the remaining options.
37128c2ecf20Sopenharmony_ci		 */
37138c2ecf20Sopenharmony_ci		if (hns3_get_vector_ring_chain(tqp_vector, &vector_ring_chain))
37148c2ecf20Sopenharmony_ci			dev_warn(priv->dev, "failed to get ring chain\n");
37158c2ecf20Sopenharmony_ci
37168c2ecf20Sopenharmony_ci		h->ae_algo->ops->unmap_ring_from_vector(h,
37178c2ecf20Sopenharmony_ci			tqp_vector->vector_irq, &vector_ring_chain);
37188c2ecf20Sopenharmony_ci
37198c2ecf20Sopenharmony_ci		hns3_free_vector_ring_chain(tqp_vector, &vector_ring_chain);
37208c2ecf20Sopenharmony_ci
37218c2ecf20Sopenharmony_ci		hns3_clear_ring_group(&tqp_vector->rx_group);
37228c2ecf20Sopenharmony_ci		hns3_clear_ring_group(&tqp_vector->tx_group);
37238c2ecf20Sopenharmony_ci		netif_napi_del(&priv->tqp_vector[i].napi);
37248c2ecf20Sopenharmony_ci	}
37258c2ecf20Sopenharmony_ci}
37268c2ecf20Sopenharmony_ci
37278c2ecf20Sopenharmony_cistatic void hns3_nic_dealloc_vector_data(struct hns3_nic_priv *priv)
37288c2ecf20Sopenharmony_ci{
37298c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
37308c2ecf20Sopenharmony_ci	struct pci_dev *pdev = h->pdev;
37318c2ecf20Sopenharmony_ci	int i, ret;
37328c2ecf20Sopenharmony_ci
37338c2ecf20Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
37348c2ecf20Sopenharmony_ci		struct hns3_enet_tqp_vector *tqp_vector;
37358c2ecf20Sopenharmony_ci
37368c2ecf20Sopenharmony_ci		tqp_vector = &priv->tqp_vector[i];
37378c2ecf20Sopenharmony_ci		ret = h->ae_algo->ops->put_vector(h, tqp_vector->vector_irq);
37388c2ecf20Sopenharmony_ci		if (ret)
37398c2ecf20Sopenharmony_ci			return;
37408c2ecf20Sopenharmony_ci	}
37418c2ecf20Sopenharmony_ci
37428c2ecf20Sopenharmony_ci	devm_kfree(&pdev->dev, priv->tqp_vector);
37438c2ecf20Sopenharmony_ci}
37448c2ecf20Sopenharmony_ci
37458c2ecf20Sopenharmony_cistatic void hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv,
37468c2ecf20Sopenharmony_ci			      unsigned int ring_type)
37478c2ecf20Sopenharmony_ci{
37488c2ecf20Sopenharmony_ci	int queue_num = priv->ae_handle->kinfo.num_tqps;
37498c2ecf20Sopenharmony_ci	struct hns3_enet_ring *ring;
37508c2ecf20Sopenharmony_ci	int desc_num;
37518c2ecf20Sopenharmony_ci
37528c2ecf20Sopenharmony_ci	if (ring_type == HNAE3_RING_TYPE_TX) {
37538c2ecf20Sopenharmony_ci		ring = &priv->ring[q->tqp_index];
37548c2ecf20Sopenharmony_ci		desc_num = priv->ae_handle->kinfo.num_tx_desc;
37558c2ecf20Sopenharmony_ci		ring->queue_index = q->tqp_index;
37568c2ecf20Sopenharmony_ci	} else {
37578c2ecf20Sopenharmony_ci		ring = &priv->ring[q->tqp_index + queue_num];
37588c2ecf20Sopenharmony_ci		desc_num = priv->ae_handle->kinfo.num_rx_desc;
37598c2ecf20Sopenharmony_ci		ring->queue_index = q->tqp_index;
37608c2ecf20Sopenharmony_ci	}
37618c2ecf20Sopenharmony_ci
37628c2ecf20Sopenharmony_ci	hnae3_set_bit(ring->flag, HNAE3_RING_TYPE_B, ring_type);
37638c2ecf20Sopenharmony_ci
37648c2ecf20Sopenharmony_ci	ring->tqp = q;
37658c2ecf20Sopenharmony_ci	ring->desc = NULL;
37668c2ecf20Sopenharmony_ci	ring->desc_cb = NULL;
37678c2ecf20Sopenharmony_ci	ring->dev = priv->dev;
37688c2ecf20Sopenharmony_ci	ring->desc_dma_addr = 0;
37698c2ecf20Sopenharmony_ci	ring->buf_size = q->buf_size;
37708c2ecf20Sopenharmony_ci	ring->desc_num = desc_num;
37718c2ecf20Sopenharmony_ci	ring->next_to_use = 0;
37728c2ecf20Sopenharmony_ci	ring->next_to_clean = 0;
37738c2ecf20Sopenharmony_ci	ring->last_to_use = 0;
37748c2ecf20Sopenharmony_ci}
37758c2ecf20Sopenharmony_ci
37768c2ecf20Sopenharmony_cistatic void hns3_queue_to_ring(struct hnae3_queue *tqp,
37778c2ecf20Sopenharmony_ci			       struct hns3_nic_priv *priv)
37788c2ecf20Sopenharmony_ci{
37798c2ecf20Sopenharmony_ci	hns3_ring_get_cfg(tqp, priv, HNAE3_RING_TYPE_TX);
37808c2ecf20Sopenharmony_ci	hns3_ring_get_cfg(tqp, priv, HNAE3_RING_TYPE_RX);
37818c2ecf20Sopenharmony_ci}
37828c2ecf20Sopenharmony_ci
37838c2ecf20Sopenharmony_cistatic int hns3_get_ring_config(struct hns3_nic_priv *priv)
37848c2ecf20Sopenharmony_ci{
37858c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
37868c2ecf20Sopenharmony_ci	struct pci_dev *pdev = h->pdev;
37878c2ecf20Sopenharmony_ci	int i;
37888c2ecf20Sopenharmony_ci
37898c2ecf20Sopenharmony_ci	priv->ring = devm_kzalloc(&pdev->dev,
37908c2ecf20Sopenharmony_ci				  array3_size(h->kinfo.num_tqps,
37918c2ecf20Sopenharmony_ci					      sizeof(*priv->ring), 2),
37928c2ecf20Sopenharmony_ci				  GFP_KERNEL);
37938c2ecf20Sopenharmony_ci	if (!priv->ring)
37948c2ecf20Sopenharmony_ci		return -ENOMEM;
37958c2ecf20Sopenharmony_ci
37968c2ecf20Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++)
37978c2ecf20Sopenharmony_ci		hns3_queue_to_ring(h->kinfo.tqp[i], priv);
37988c2ecf20Sopenharmony_ci
37998c2ecf20Sopenharmony_ci	return 0;
38008c2ecf20Sopenharmony_ci}
38018c2ecf20Sopenharmony_ci
38028c2ecf20Sopenharmony_cistatic void hns3_put_ring_config(struct hns3_nic_priv *priv)
38038c2ecf20Sopenharmony_ci{
38048c2ecf20Sopenharmony_ci	if (!priv->ring)
38058c2ecf20Sopenharmony_ci		return;
38068c2ecf20Sopenharmony_ci
38078c2ecf20Sopenharmony_ci	devm_kfree(priv->dev, priv->ring);
38088c2ecf20Sopenharmony_ci	priv->ring = NULL;
38098c2ecf20Sopenharmony_ci}
38108c2ecf20Sopenharmony_ci
38118c2ecf20Sopenharmony_cistatic int hns3_alloc_ring_memory(struct hns3_enet_ring *ring)
38128c2ecf20Sopenharmony_ci{
38138c2ecf20Sopenharmony_ci	int ret;
38148c2ecf20Sopenharmony_ci
38158c2ecf20Sopenharmony_ci	if (ring->desc_num <= 0 || ring->buf_size <= 0)
38168c2ecf20Sopenharmony_ci		return -EINVAL;
38178c2ecf20Sopenharmony_ci
38188c2ecf20Sopenharmony_ci	ring->desc_cb = devm_kcalloc(ring_to_dev(ring), ring->desc_num,
38198c2ecf20Sopenharmony_ci				     sizeof(ring->desc_cb[0]), GFP_KERNEL);
38208c2ecf20Sopenharmony_ci	if (!ring->desc_cb) {
38218c2ecf20Sopenharmony_ci		ret = -ENOMEM;
38228c2ecf20Sopenharmony_ci		goto out;
38238c2ecf20Sopenharmony_ci	}
38248c2ecf20Sopenharmony_ci
38258c2ecf20Sopenharmony_ci	ret = hns3_alloc_desc(ring);
38268c2ecf20Sopenharmony_ci	if (ret)
38278c2ecf20Sopenharmony_ci		goto out_with_desc_cb;
38288c2ecf20Sopenharmony_ci
38298c2ecf20Sopenharmony_ci	if (!HNAE3_IS_TX_RING(ring)) {
38308c2ecf20Sopenharmony_ci		ret = hns3_alloc_ring_buffers(ring);
38318c2ecf20Sopenharmony_ci		if (ret)
38328c2ecf20Sopenharmony_ci			goto out_with_desc;
38338c2ecf20Sopenharmony_ci	}
38348c2ecf20Sopenharmony_ci
38358c2ecf20Sopenharmony_ci	return 0;
38368c2ecf20Sopenharmony_ci
38378c2ecf20Sopenharmony_ciout_with_desc:
38388c2ecf20Sopenharmony_ci	hns3_free_desc(ring);
38398c2ecf20Sopenharmony_ciout_with_desc_cb:
38408c2ecf20Sopenharmony_ci	devm_kfree(ring_to_dev(ring), ring->desc_cb);
38418c2ecf20Sopenharmony_ci	ring->desc_cb = NULL;
38428c2ecf20Sopenharmony_ciout:
38438c2ecf20Sopenharmony_ci	return ret;
38448c2ecf20Sopenharmony_ci}
38458c2ecf20Sopenharmony_ci
38468c2ecf20Sopenharmony_civoid hns3_fini_ring(struct hns3_enet_ring *ring)
38478c2ecf20Sopenharmony_ci{
38488c2ecf20Sopenharmony_ci	hns3_free_desc(ring);
38498c2ecf20Sopenharmony_ci	devm_kfree(ring_to_dev(ring), ring->desc_cb);
38508c2ecf20Sopenharmony_ci	ring->desc_cb = NULL;
38518c2ecf20Sopenharmony_ci	ring->next_to_clean = 0;
38528c2ecf20Sopenharmony_ci	ring->next_to_use = 0;
38538c2ecf20Sopenharmony_ci	ring->last_to_use = 0;
38548c2ecf20Sopenharmony_ci	ring->pending_buf = 0;
38558c2ecf20Sopenharmony_ci	if (ring->skb) {
38568c2ecf20Sopenharmony_ci		dev_kfree_skb_any(ring->skb);
38578c2ecf20Sopenharmony_ci		ring->skb = NULL;
38588c2ecf20Sopenharmony_ci	}
38598c2ecf20Sopenharmony_ci}
38608c2ecf20Sopenharmony_ci
38618c2ecf20Sopenharmony_cistatic int hns3_buf_size2type(u32 buf_size)
38628c2ecf20Sopenharmony_ci{
38638c2ecf20Sopenharmony_ci	int bd_size_type;
38648c2ecf20Sopenharmony_ci
38658c2ecf20Sopenharmony_ci	switch (buf_size) {
38668c2ecf20Sopenharmony_ci	case 512:
38678c2ecf20Sopenharmony_ci		bd_size_type = HNS3_BD_SIZE_512_TYPE;
38688c2ecf20Sopenharmony_ci		break;
38698c2ecf20Sopenharmony_ci	case 1024:
38708c2ecf20Sopenharmony_ci		bd_size_type = HNS3_BD_SIZE_1024_TYPE;
38718c2ecf20Sopenharmony_ci		break;
38728c2ecf20Sopenharmony_ci	case 2048:
38738c2ecf20Sopenharmony_ci		bd_size_type = HNS3_BD_SIZE_2048_TYPE;
38748c2ecf20Sopenharmony_ci		break;
38758c2ecf20Sopenharmony_ci	case 4096:
38768c2ecf20Sopenharmony_ci		bd_size_type = HNS3_BD_SIZE_4096_TYPE;
38778c2ecf20Sopenharmony_ci		break;
38788c2ecf20Sopenharmony_ci	default:
38798c2ecf20Sopenharmony_ci		bd_size_type = HNS3_BD_SIZE_2048_TYPE;
38808c2ecf20Sopenharmony_ci	}
38818c2ecf20Sopenharmony_ci
38828c2ecf20Sopenharmony_ci	return bd_size_type;
38838c2ecf20Sopenharmony_ci}
38848c2ecf20Sopenharmony_ci
38858c2ecf20Sopenharmony_cistatic void hns3_init_ring_hw(struct hns3_enet_ring *ring)
38868c2ecf20Sopenharmony_ci{
38878c2ecf20Sopenharmony_ci	dma_addr_t dma = ring->desc_dma_addr;
38888c2ecf20Sopenharmony_ci	struct hnae3_queue *q = ring->tqp;
38898c2ecf20Sopenharmony_ci
38908c2ecf20Sopenharmony_ci	if (!HNAE3_IS_TX_RING(ring)) {
38918c2ecf20Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_RX_RING_BASEADDR_L_REG, (u32)dma);
38928c2ecf20Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_RX_RING_BASEADDR_H_REG,
38938c2ecf20Sopenharmony_ci			       (u32)((dma >> 31) >> 1));
38948c2ecf20Sopenharmony_ci
38958c2ecf20Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_RX_RING_BD_LEN_REG,
38968c2ecf20Sopenharmony_ci			       hns3_buf_size2type(ring->buf_size));
38978c2ecf20Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_RX_RING_BD_NUM_REG,
38988c2ecf20Sopenharmony_ci			       ring->desc_num / 8 - 1);
38998c2ecf20Sopenharmony_ci
39008c2ecf20Sopenharmony_ci	} else {
39018c2ecf20Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_TX_RING_BASEADDR_L_REG,
39028c2ecf20Sopenharmony_ci			       (u32)dma);
39038c2ecf20Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_TX_RING_BASEADDR_H_REG,
39048c2ecf20Sopenharmony_ci			       (u32)((dma >> 31) >> 1));
39058c2ecf20Sopenharmony_ci
39068c2ecf20Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_TX_RING_BD_NUM_REG,
39078c2ecf20Sopenharmony_ci			       ring->desc_num / 8 - 1);
39088c2ecf20Sopenharmony_ci	}
39098c2ecf20Sopenharmony_ci}
39108c2ecf20Sopenharmony_ci
39118c2ecf20Sopenharmony_cistatic void hns3_init_tx_ring_tc(struct hns3_nic_priv *priv)
39128c2ecf20Sopenharmony_ci{
39138c2ecf20Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &priv->ae_handle->kinfo;
39148c2ecf20Sopenharmony_ci	int i;
39158c2ecf20Sopenharmony_ci
39168c2ecf20Sopenharmony_ci	for (i = 0; i < HNAE3_MAX_TC; i++) {
39178c2ecf20Sopenharmony_ci		struct hnae3_tc_info *tc_info = &kinfo->tc_info[i];
39188c2ecf20Sopenharmony_ci		int j;
39198c2ecf20Sopenharmony_ci
39208c2ecf20Sopenharmony_ci		if (!tc_info->enable)
39218c2ecf20Sopenharmony_ci			continue;
39228c2ecf20Sopenharmony_ci
39238c2ecf20Sopenharmony_ci		for (j = 0; j < tc_info->tqp_count; j++) {
39248c2ecf20Sopenharmony_ci			struct hnae3_queue *q;
39258c2ecf20Sopenharmony_ci
39268c2ecf20Sopenharmony_ci			q = priv->ring[tc_info->tqp_offset + j].tqp;
39278c2ecf20Sopenharmony_ci			hns3_write_dev(q, HNS3_RING_TX_RING_TC_REG,
39288c2ecf20Sopenharmony_ci				       tc_info->tc);
39298c2ecf20Sopenharmony_ci		}
39308c2ecf20Sopenharmony_ci	}
39318c2ecf20Sopenharmony_ci}
39328c2ecf20Sopenharmony_ci
39338c2ecf20Sopenharmony_ciint hns3_init_all_ring(struct hns3_nic_priv *priv)
39348c2ecf20Sopenharmony_ci{
39358c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
39368c2ecf20Sopenharmony_ci	int ring_num = h->kinfo.num_tqps * 2;
39378c2ecf20Sopenharmony_ci	int i, j;
39388c2ecf20Sopenharmony_ci	int ret;
39398c2ecf20Sopenharmony_ci
39408c2ecf20Sopenharmony_ci	for (i = 0; i < ring_num; i++) {
39418c2ecf20Sopenharmony_ci		ret = hns3_alloc_ring_memory(&priv->ring[i]);
39428c2ecf20Sopenharmony_ci		if (ret) {
39438c2ecf20Sopenharmony_ci			dev_err(priv->dev,
39448c2ecf20Sopenharmony_ci				"Alloc ring memory fail! ret=%d\n", ret);
39458c2ecf20Sopenharmony_ci			goto out_when_alloc_ring_memory;
39468c2ecf20Sopenharmony_ci		}
39478c2ecf20Sopenharmony_ci
39488c2ecf20Sopenharmony_ci		u64_stats_init(&priv->ring[i].syncp);
39498c2ecf20Sopenharmony_ci	}
39508c2ecf20Sopenharmony_ci
39518c2ecf20Sopenharmony_ci	return 0;
39528c2ecf20Sopenharmony_ci
39538c2ecf20Sopenharmony_ciout_when_alloc_ring_memory:
39548c2ecf20Sopenharmony_ci	for (j = i - 1; j >= 0; j--)
39558c2ecf20Sopenharmony_ci		hns3_fini_ring(&priv->ring[j]);
39568c2ecf20Sopenharmony_ci
39578c2ecf20Sopenharmony_ci	return -ENOMEM;
39588c2ecf20Sopenharmony_ci}
39598c2ecf20Sopenharmony_ci
39608c2ecf20Sopenharmony_ciint hns3_uninit_all_ring(struct hns3_nic_priv *priv)
39618c2ecf20Sopenharmony_ci{
39628c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
39638c2ecf20Sopenharmony_ci	int i;
39648c2ecf20Sopenharmony_ci
39658c2ecf20Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++) {
39668c2ecf20Sopenharmony_ci		hns3_fini_ring(&priv->ring[i]);
39678c2ecf20Sopenharmony_ci		hns3_fini_ring(&priv->ring[i + h->kinfo.num_tqps]);
39688c2ecf20Sopenharmony_ci	}
39698c2ecf20Sopenharmony_ci	return 0;
39708c2ecf20Sopenharmony_ci}
39718c2ecf20Sopenharmony_ci
39728c2ecf20Sopenharmony_ci/* Set mac addr if it is configured. or leave it to the AE driver */
39738c2ecf20Sopenharmony_cistatic int hns3_init_mac_addr(struct net_device *netdev)
39748c2ecf20Sopenharmony_ci{
39758c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
39768c2ecf20Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
39778c2ecf20Sopenharmony_ci	u8 mac_addr_temp[ETH_ALEN] = {0};
39788c2ecf20Sopenharmony_ci	int ret = 0;
39798c2ecf20Sopenharmony_ci
39808c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->get_mac_addr)
39818c2ecf20Sopenharmony_ci		h->ae_algo->ops->get_mac_addr(h, mac_addr_temp);
39828c2ecf20Sopenharmony_ci
39838c2ecf20Sopenharmony_ci	/* Check if the MAC address is valid, if not get a random one */
39848c2ecf20Sopenharmony_ci	if (!is_valid_ether_addr(mac_addr_temp)) {
39858c2ecf20Sopenharmony_ci		eth_hw_addr_random(netdev);
39868c2ecf20Sopenharmony_ci		dev_warn(priv->dev, "using random MAC address %pM\n",
39878c2ecf20Sopenharmony_ci			 netdev->dev_addr);
39888c2ecf20Sopenharmony_ci	} else if (!ether_addr_equal(netdev->dev_addr, mac_addr_temp)) {
39898c2ecf20Sopenharmony_ci		ether_addr_copy(netdev->dev_addr, mac_addr_temp);
39908c2ecf20Sopenharmony_ci		ether_addr_copy(netdev->perm_addr, mac_addr_temp);
39918c2ecf20Sopenharmony_ci	} else {
39928c2ecf20Sopenharmony_ci		return 0;
39938c2ecf20Sopenharmony_ci	}
39948c2ecf20Sopenharmony_ci
39958c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->set_mac_addr)
39968c2ecf20Sopenharmony_ci		ret = h->ae_algo->ops->set_mac_addr(h, netdev->dev_addr, true);
39978c2ecf20Sopenharmony_ci
39988c2ecf20Sopenharmony_ci	return ret;
39998c2ecf20Sopenharmony_ci}
40008c2ecf20Sopenharmony_ci
40018c2ecf20Sopenharmony_cistatic int hns3_init_phy(struct net_device *netdev)
40028c2ecf20Sopenharmony_ci{
40038c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
40048c2ecf20Sopenharmony_ci	int ret = 0;
40058c2ecf20Sopenharmony_ci
40068c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->mac_connect_phy)
40078c2ecf20Sopenharmony_ci		ret = h->ae_algo->ops->mac_connect_phy(h);
40088c2ecf20Sopenharmony_ci
40098c2ecf20Sopenharmony_ci	return ret;
40108c2ecf20Sopenharmony_ci}
40118c2ecf20Sopenharmony_ci
40128c2ecf20Sopenharmony_cistatic void hns3_uninit_phy(struct net_device *netdev)
40138c2ecf20Sopenharmony_ci{
40148c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
40158c2ecf20Sopenharmony_ci
40168c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->mac_disconnect_phy)
40178c2ecf20Sopenharmony_ci		h->ae_algo->ops->mac_disconnect_phy(h);
40188c2ecf20Sopenharmony_ci}
40198c2ecf20Sopenharmony_ci
40208c2ecf20Sopenharmony_cistatic void hns3_del_all_fd_rules(struct net_device *netdev, bool clear_list)
40218c2ecf20Sopenharmony_ci{
40228c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
40238c2ecf20Sopenharmony_ci
40248c2ecf20Sopenharmony_ci	if (h->ae_algo->ops->del_all_fd_entries)
40258c2ecf20Sopenharmony_ci		h->ae_algo->ops->del_all_fd_entries(h, clear_list);
40268c2ecf20Sopenharmony_ci}
40278c2ecf20Sopenharmony_ci
40288c2ecf20Sopenharmony_cistatic int hns3_client_start(struct hnae3_handle *handle)
40298c2ecf20Sopenharmony_ci{
40308c2ecf20Sopenharmony_ci	if (!handle->ae_algo->ops->client_start)
40318c2ecf20Sopenharmony_ci		return 0;
40328c2ecf20Sopenharmony_ci
40338c2ecf20Sopenharmony_ci	return handle->ae_algo->ops->client_start(handle);
40348c2ecf20Sopenharmony_ci}
40358c2ecf20Sopenharmony_ci
40368c2ecf20Sopenharmony_cistatic void hns3_client_stop(struct hnae3_handle *handle)
40378c2ecf20Sopenharmony_ci{
40388c2ecf20Sopenharmony_ci	if (!handle->ae_algo->ops->client_stop)
40398c2ecf20Sopenharmony_ci		return;
40408c2ecf20Sopenharmony_ci
40418c2ecf20Sopenharmony_ci	handle->ae_algo->ops->client_stop(handle);
40428c2ecf20Sopenharmony_ci}
40438c2ecf20Sopenharmony_ci
40448c2ecf20Sopenharmony_cistatic void hns3_info_show(struct hns3_nic_priv *priv)
40458c2ecf20Sopenharmony_ci{
40468c2ecf20Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &priv->ae_handle->kinfo;
40478c2ecf20Sopenharmony_ci
40488c2ecf20Sopenharmony_ci	dev_info(priv->dev, "MAC address: %pM\n", priv->netdev->dev_addr);
40498c2ecf20Sopenharmony_ci	dev_info(priv->dev, "Task queue pairs numbers: %u\n", kinfo->num_tqps);
40508c2ecf20Sopenharmony_ci	dev_info(priv->dev, "RSS size: %u\n", kinfo->rss_size);
40518c2ecf20Sopenharmony_ci	dev_info(priv->dev, "Allocated RSS size: %u\n", kinfo->req_rss_size);
40528c2ecf20Sopenharmony_ci	dev_info(priv->dev, "RX buffer length: %u\n", kinfo->rx_buf_len);
40538c2ecf20Sopenharmony_ci	dev_info(priv->dev, "Desc num per TX queue: %u\n", kinfo->num_tx_desc);
40548c2ecf20Sopenharmony_ci	dev_info(priv->dev, "Desc num per RX queue: %u\n", kinfo->num_rx_desc);
40558c2ecf20Sopenharmony_ci	dev_info(priv->dev, "Total number of enabled TCs: %u\n", kinfo->num_tc);
40568c2ecf20Sopenharmony_ci	dev_info(priv->dev, "Max mtu size: %u\n", priv->netdev->max_mtu);
40578c2ecf20Sopenharmony_ci}
40588c2ecf20Sopenharmony_ci
40598c2ecf20Sopenharmony_cistatic int hns3_client_init(struct hnae3_handle *handle)
40608c2ecf20Sopenharmony_ci{
40618c2ecf20Sopenharmony_ci	struct pci_dev *pdev = handle->pdev;
40628c2ecf20Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
40638c2ecf20Sopenharmony_ci	u16 alloc_tqps, max_rss_size;
40648c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv;
40658c2ecf20Sopenharmony_ci	struct net_device *netdev;
40668c2ecf20Sopenharmony_ci	int ret;
40678c2ecf20Sopenharmony_ci
40688c2ecf20Sopenharmony_ci	handle->ae_algo->ops->get_tqps_and_rss_info(handle, &alloc_tqps,
40698c2ecf20Sopenharmony_ci						    &max_rss_size);
40708c2ecf20Sopenharmony_ci	netdev = alloc_etherdev_mq(sizeof(struct hns3_nic_priv), alloc_tqps);
40718c2ecf20Sopenharmony_ci	if (!netdev)
40728c2ecf20Sopenharmony_ci		return -ENOMEM;
40738c2ecf20Sopenharmony_ci
40748c2ecf20Sopenharmony_ci	priv = netdev_priv(netdev);
40758c2ecf20Sopenharmony_ci	priv->dev = &pdev->dev;
40768c2ecf20Sopenharmony_ci	priv->netdev = netdev;
40778c2ecf20Sopenharmony_ci	priv->ae_handle = handle;
40788c2ecf20Sopenharmony_ci	priv->tx_timeout_count = 0;
40798c2ecf20Sopenharmony_ci	priv->max_non_tso_bd_num = ae_dev->dev_specs.max_non_tso_bd_num;
40808c2ecf20Sopenharmony_ci	set_bit(HNS3_NIC_STATE_DOWN, &priv->state);
40818c2ecf20Sopenharmony_ci
40828c2ecf20Sopenharmony_ci	handle->msg_enable = netif_msg_init(debug, DEFAULT_MSG_LEVEL);
40838c2ecf20Sopenharmony_ci
40848c2ecf20Sopenharmony_ci	handle->kinfo.netdev = netdev;
40858c2ecf20Sopenharmony_ci	handle->priv = (void *)priv;
40868c2ecf20Sopenharmony_ci
40878c2ecf20Sopenharmony_ci	hns3_init_mac_addr(netdev);
40888c2ecf20Sopenharmony_ci
40898c2ecf20Sopenharmony_ci	hns3_set_default_feature(netdev);
40908c2ecf20Sopenharmony_ci
40918c2ecf20Sopenharmony_ci	netdev->watchdog_timeo = HNS3_TX_TIMEOUT;
40928c2ecf20Sopenharmony_ci	netdev->priv_flags |= IFF_UNICAST_FLT;
40938c2ecf20Sopenharmony_ci	netdev->netdev_ops = &hns3_nic_netdev_ops;
40948c2ecf20Sopenharmony_ci	SET_NETDEV_DEV(netdev, &pdev->dev);
40958c2ecf20Sopenharmony_ci	hns3_ethtool_set_ops(netdev);
40968c2ecf20Sopenharmony_ci
40978c2ecf20Sopenharmony_ci	/* Carrier off reporting is important to ethtool even BEFORE open */
40988c2ecf20Sopenharmony_ci	netif_carrier_off(netdev);
40998c2ecf20Sopenharmony_ci
41008c2ecf20Sopenharmony_ci	ret = hns3_get_ring_config(priv);
41018c2ecf20Sopenharmony_ci	if (ret) {
41028c2ecf20Sopenharmony_ci		ret = -ENOMEM;
41038c2ecf20Sopenharmony_ci		goto out_get_ring_cfg;
41048c2ecf20Sopenharmony_ci	}
41058c2ecf20Sopenharmony_ci
41068c2ecf20Sopenharmony_ci	ret = hns3_nic_alloc_vector_data(priv);
41078c2ecf20Sopenharmony_ci	if (ret) {
41088c2ecf20Sopenharmony_ci		ret = -ENOMEM;
41098c2ecf20Sopenharmony_ci		goto out_alloc_vector_data;
41108c2ecf20Sopenharmony_ci	}
41118c2ecf20Sopenharmony_ci
41128c2ecf20Sopenharmony_ci	ret = hns3_nic_init_vector_data(priv);
41138c2ecf20Sopenharmony_ci	if (ret) {
41148c2ecf20Sopenharmony_ci		ret = -ENOMEM;
41158c2ecf20Sopenharmony_ci		goto out_init_vector_data;
41168c2ecf20Sopenharmony_ci	}
41178c2ecf20Sopenharmony_ci
41188c2ecf20Sopenharmony_ci	ret = hns3_init_all_ring(priv);
41198c2ecf20Sopenharmony_ci	if (ret) {
41208c2ecf20Sopenharmony_ci		ret = -ENOMEM;
41218c2ecf20Sopenharmony_ci		goto out_init_ring;
41228c2ecf20Sopenharmony_ci	}
41238c2ecf20Sopenharmony_ci
41248c2ecf20Sopenharmony_ci	ret = hns3_init_phy(netdev);
41258c2ecf20Sopenharmony_ci	if (ret)
41268c2ecf20Sopenharmony_ci		goto out_init_phy;
41278c2ecf20Sopenharmony_ci
41288c2ecf20Sopenharmony_ci	/* the device can work without cpu rmap, only aRFS needs it */
41298c2ecf20Sopenharmony_ci	ret = hns3_set_rx_cpu_rmap(netdev);
41308c2ecf20Sopenharmony_ci	if (ret)
41318c2ecf20Sopenharmony_ci		dev_warn(priv->dev, "set rx cpu rmap fail, ret=%d\n", ret);
41328c2ecf20Sopenharmony_ci
41338c2ecf20Sopenharmony_ci	ret = hns3_nic_init_irq(priv);
41348c2ecf20Sopenharmony_ci	if (ret) {
41358c2ecf20Sopenharmony_ci		dev_err(priv->dev, "init irq failed! ret=%d\n", ret);
41368c2ecf20Sopenharmony_ci		hns3_free_rx_cpu_rmap(netdev);
41378c2ecf20Sopenharmony_ci		goto out_init_irq_fail;
41388c2ecf20Sopenharmony_ci	}
41398c2ecf20Sopenharmony_ci
41408c2ecf20Sopenharmony_ci	ret = hns3_client_start(handle);
41418c2ecf20Sopenharmony_ci	if (ret) {
41428c2ecf20Sopenharmony_ci		dev_err(priv->dev, "hns3_client_start fail! ret=%d\n", ret);
41438c2ecf20Sopenharmony_ci		goto out_client_start;
41448c2ecf20Sopenharmony_ci	}
41458c2ecf20Sopenharmony_ci
41468c2ecf20Sopenharmony_ci	hns3_dcbnl_setup(handle);
41478c2ecf20Sopenharmony_ci
41488c2ecf20Sopenharmony_ci	hns3_dbg_init(handle);
41498c2ecf20Sopenharmony_ci
41508c2ecf20Sopenharmony_ci	/* MTU range: (ETH_MIN_MTU(kernel default) - 9702) */
41518c2ecf20Sopenharmony_ci	netdev->max_mtu = HNS3_MAX_MTU;
41528c2ecf20Sopenharmony_ci
41538c2ecf20Sopenharmony_ci	set_bit(HNS3_NIC_STATE_INITED, &priv->state);
41548c2ecf20Sopenharmony_ci
41558c2ecf20Sopenharmony_ci	ret = register_netdev(netdev);
41568c2ecf20Sopenharmony_ci	if (ret) {
41578c2ecf20Sopenharmony_ci		dev_err(priv->dev, "probe register netdev fail!\n");
41588c2ecf20Sopenharmony_ci		goto out_reg_netdev_fail;
41598c2ecf20Sopenharmony_ci	}
41608c2ecf20Sopenharmony_ci
41618c2ecf20Sopenharmony_ci	if (netif_msg_drv(handle))
41628c2ecf20Sopenharmony_ci		hns3_info_show(priv);
41638c2ecf20Sopenharmony_ci
41648c2ecf20Sopenharmony_ci	return ret;
41658c2ecf20Sopenharmony_ci
41668c2ecf20Sopenharmony_ciout_reg_netdev_fail:
41678c2ecf20Sopenharmony_ci	hns3_dbg_uninit(handle);
41688c2ecf20Sopenharmony_ciout_client_start:
41698c2ecf20Sopenharmony_ci	hns3_free_rx_cpu_rmap(netdev);
41708c2ecf20Sopenharmony_ci	hns3_nic_uninit_irq(priv);
41718c2ecf20Sopenharmony_ciout_init_irq_fail:
41728c2ecf20Sopenharmony_ci	hns3_uninit_phy(netdev);
41738c2ecf20Sopenharmony_ciout_init_phy:
41748c2ecf20Sopenharmony_ci	hns3_uninit_all_ring(priv);
41758c2ecf20Sopenharmony_ciout_init_ring:
41768c2ecf20Sopenharmony_ci	hns3_nic_uninit_vector_data(priv);
41778c2ecf20Sopenharmony_ciout_init_vector_data:
41788c2ecf20Sopenharmony_ci	hns3_nic_dealloc_vector_data(priv);
41798c2ecf20Sopenharmony_ciout_alloc_vector_data:
41808c2ecf20Sopenharmony_ci	priv->ring = NULL;
41818c2ecf20Sopenharmony_ciout_get_ring_cfg:
41828c2ecf20Sopenharmony_ci	priv->ae_handle = NULL;
41838c2ecf20Sopenharmony_ci	free_netdev(netdev);
41848c2ecf20Sopenharmony_ci	return ret;
41858c2ecf20Sopenharmony_ci}
41868c2ecf20Sopenharmony_ci
41878c2ecf20Sopenharmony_cistatic void hns3_client_uninit(struct hnae3_handle *handle, bool reset)
41888c2ecf20Sopenharmony_ci{
41898c2ecf20Sopenharmony_ci	struct net_device *netdev = handle->kinfo.netdev;
41908c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
41918c2ecf20Sopenharmony_ci	int ret;
41928c2ecf20Sopenharmony_ci
41938c2ecf20Sopenharmony_ci	if (netdev->reg_state != NETREG_UNINITIALIZED)
41948c2ecf20Sopenharmony_ci		unregister_netdev(netdev);
41958c2ecf20Sopenharmony_ci
41968c2ecf20Sopenharmony_ci	hns3_client_stop(handle);
41978c2ecf20Sopenharmony_ci
41988c2ecf20Sopenharmony_ci	hns3_uninit_phy(netdev);
41998c2ecf20Sopenharmony_ci
42008c2ecf20Sopenharmony_ci	if (!test_and_clear_bit(HNS3_NIC_STATE_INITED, &priv->state)) {
42018c2ecf20Sopenharmony_ci		netdev_warn(netdev, "already uninitialized\n");
42028c2ecf20Sopenharmony_ci		goto out_netdev_free;
42038c2ecf20Sopenharmony_ci	}
42048c2ecf20Sopenharmony_ci
42058c2ecf20Sopenharmony_ci	hns3_free_rx_cpu_rmap(netdev);
42068c2ecf20Sopenharmony_ci
42078c2ecf20Sopenharmony_ci	hns3_nic_uninit_irq(priv);
42088c2ecf20Sopenharmony_ci
42098c2ecf20Sopenharmony_ci	hns3_del_all_fd_rules(netdev, true);
42108c2ecf20Sopenharmony_ci
42118c2ecf20Sopenharmony_ci	hns3_clear_all_ring(handle, true);
42128c2ecf20Sopenharmony_ci
42138c2ecf20Sopenharmony_ci	hns3_nic_uninit_vector_data(priv);
42148c2ecf20Sopenharmony_ci
42158c2ecf20Sopenharmony_ci	hns3_nic_dealloc_vector_data(priv);
42168c2ecf20Sopenharmony_ci
42178c2ecf20Sopenharmony_ci	ret = hns3_uninit_all_ring(priv);
42188c2ecf20Sopenharmony_ci	if (ret)
42198c2ecf20Sopenharmony_ci		netdev_err(netdev, "uninit ring error\n");
42208c2ecf20Sopenharmony_ci
42218c2ecf20Sopenharmony_ci	hns3_put_ring_config(priv);
42228c2ecf20Sopenharmony_ci
42238c2ecf20Sopenharmony_ciout_netdev_free:
42248c2ecf20Sopenharmony_ci	hns3_dbg_uninit(handle);
42258c2ecf20Sopenharmony_ci	free_netdev(netdev);
42268c2ecf20Sopenharmony_ci}
42278c2ecf20Sopenharmony_ci
42288c2ecf20Sopenharmony_cistatic void hns3_link_status_change(struct hnae3_handle *handle, bool linkup)
42298c2ecf20Sopenharmony_ci{
42308c2ecf20Sopenharmony_ci	struct net_device *netdev = handle->kinfo.netdev;
42318c2ecf20Sopenharmony_ci
42328c2ecf20Sopenharmony_ci	if (!netdev)
42338c2ecf20Sopenharmony_ci		return;
42348c2ecf20Sopenharmony_ci
42358c2ecf20Sopenharmony_ci	if (linkup) {
42368c2ecf20Sopenharmony_ci		netif_tx_wake_all_queues(netdev);
42378c2ecf20Sopenharmony_ci		netif_carrier_on(netdev);
42388c2ecf20Sopenharmony_ci		if (netif_msg_link(handle))
42398c2ecf20Sopenharmony_ci			netdev_info(netdev, "link up\n");
42408c2ecf20Sopenharmony_ci	} else {
42418c2ecf20Sopenharmony_ci		netif_carrier_off(netdev);
42428c2ecf20Sopenharmony_ci		netif_tx_stop_all_queues(netdev);
42438c2ecf20Sopenharmony_ci		if (netif_msg_link(handle))
42448c2ecf20Sopenharmony_ci			netdev_info(netdev, "link down\n");
42458c2ecf20Sopenharmony_ci	}
42468c2ecf20Sopenharmony_ci}
42478c2ecf20Sopenharmony_ci
42488c2ecf20Sopenharmony_cistatic int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc)
42498c2ecf20Sopenharmony_ci{
42508c2ecf20Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
42518c2ecf20Sopenharmony_ci	struct net_device *ndev = kinfo->netdev;
42528c2ecf20Sopenharmony_ci
42538c2ecf20Sopenharmony_ci	if (tc > HNAE3_MAX_TC)
42548c2ecf20Sopenharmony_ci		return -EINVAL;
42558c2ecf20Sopenharmony_ci
42568c2ecf20Sopenharmony_ci	if (!ndev)
42578c2ecf20Sopenharmony_ci		return -ENODEV;
42588c2ecf20Sopenharmony_ci
42598c2ecf20Sopenharmony_ci	return hns3_nic_set_real_num_queue(ndev);
42608c2ecf20Sopenharmony_ci}
42618c2ecf20Sopenharmony_ci
42628c2ecf20Sopenharmony_cistatic void hns3_clear_tx_ring(struct hns3_enet_ring *ring)
42638c2ecf20Sopenharmony_ci{
42648c2ecf20Sopenharmony_ci	while (ring->next_to_clean != ring->next_to_use) {
42658c2ecf20Sopenharmony_ci		ring->desc[ring->next_to_clean].tx.bdtp_fe_sc_vld_ra_ri = 0;
42668c2ecf20Sopenharmony_ci		hns3_free_buffer_detach(ring, ring->next_to_clean, 0);
42678c2ecf20Sopenharmony_ci		ring_ptr_move_fw(ring, next_to_clean);
42688c2ecf20Sopenharmony_ci	}
42698c2ecf20Sopenharmony_ci
42708c2ecf20Sopenharmony_ci	ring->pending_buf = 0;
42718c2ecf20Sopenharmony_ci}
42728c2ecf20Sopenharmony_ci
42738c2ecf20Sopenharmony_cistatic int hns3_clear_rx_ring(struct hns3_enet_ring *ring)
42748c2ecf20Sopenharmony_ci{
42758c2ecf20Sopenharmony_ci	struct hns3_desc_cb res_cbs;
42768c2ecf20Sopenharmony_ci	int ret;
42778c2ecf20Sopenharmony_ci
42788c2ecf20Sopenharmony_ci	while (ring->next_to_use != ring->next_to_clean) {
42798c2ecf20Sopenharmony_ci		/* When a buffer is not reused, it's memory has been
42808c2ecf20Sopenharmony_ci		 * freed in hns3_handle_rx_bd or will be freed by
42818c2ecf20Sopenharmony_ci		 * stack, so we need to replace the buffer here.
42828c2ecf20Sopenharmony_ci		 */
42838c2ecf20Sopenharmony_ci		if (!ring->desc_cb[ring->next_to_use].reuse_flag) {
42848c2ecf20Sopenharmony_ci			ret = hns3_alloc_and_map_buffer(ring, &res_cbs);
42858c2ecf20Sopenharmony_ci			if (ret) {
42868c2ecf20Sopenharmony_ci				u64_stats_update_begin(&ring->syncp);
42878c2ecf20Sopenharmony_ci				ring->stats.sw_err_cnt++;
42888c2ecf20Sopenharmony_ci				u64_stats_update_end(&ring->syncp);
42898c2ecf20Sopenharmony_ci				/* if alloc new buffer fail, exit directly
42908c2ecf20Sopenharmony_ci				 * and reclear in up flow.
42918c2ecf20Sopenharmony_ci				 */
42928c2ecf20Sopenharmony_ci				netdev_warn(ring_to_netdev(ring),
42938c2ecf20Sopenharmony_ci					    "reserve buffer map failed, ret = %d\n",
42948c2ecf20Sopenharmony_ci					    ret);
42958c2ecf20Sopenharmony_ci				return ret;
42968c2ecf20Sopenharmony_ci			}
42978c2ecf20Sopenharmony_ci			hns3_replace_buffer(ring, ring->next_to_use, &res_cbs);
42988c2ecf20Sopenharmony_ci		}
42998c2ecf20Sopenharmony_ci		ring_ptr_move_fw(ring, next_to_use);
43008c2ecf20Sopenharmony_ci	}
43018c2ecf20Sopenharmony_ci
43028c2ecf20Sopenharmony_ci	/* Free the pending skb in rx ring */
43038c2ecf20Sopenharmony_ci	if (ring->skb) {
43048c2ecf20Sopenharmony_ci		dev_kfree_skb_any(ring->skb);
43058c2ecf20Sopenharmony_ci		ring->skb = NULL;
43068c2ecf20Sopenharmony_ci		ring->pending_buf = 0;
43078c2ecf20Sopenharmony_ci	}
43088c2ecf20Sopenharmony_ci
43098c2ecf20Sopenharmony_ci	return 0;
43108c2ecf20Sopenharmony_ci}
43118c2ecf20Sopenharmony_ci
43128c2ecf20Sopenharmony_cistatic void hns3_force_clear_rx_ring(struct hns3_enet_ring *ring)
43138c2ecf20Sopenharmony_ci{
43148c2ecf20Sopenharmony_ci	while (ring->next_to_use != ring->next_to_clean) {
43158c2ecf20Sopenharmony_ci		/* When a buffer is not reused, it's memory has been
43168c2ecf20Sopenharmony_ci		 * freed in hns3_handle_rx_bd or will be freed by
43178c2ecf20Sopenharmony_ci		 * stack, so only need to unmap the buffer here.
43188c2ecf20Sopenharmony_ci		 */
43198c2ecf20Sopenharmony_ci		if (!ring->desc_cb[ring->next_to_use].reuse_flag) {
43208c2ecf20Sopenharmony_ci			hns3_unmap_buffer(ring,
43218c2ecf20Sopenharmony_ci					  &ring->desc_cb[ring->next_to_use]);
43228c2ecf20Sopenharmony_ci			ring->desc_cb[ring->next_to_use].dma = 0;
43238c2ecf20Sopenharmony_ci		}
43248c2ecf20Sopenharmony_ci
43258c2ecf20Sopenharmony_ci		ring_ptr_move_fw(ring, next_to_use);
43268c2ecf20Sopenharmony_ci	}
43278c2ecf20Sopenharmony_ci}
43288c2ecf20Sopenharmony_ci
43298c2ecf20Sopenharmony_cistatic void hns3_clear_all_ring(struct hnae3_handle *h, bool force)
43308c2ecf20Sopenharmony_ci{
43318c2ecf20Sopenharmony_ci	struct net_device *ndev = h->kinfo.netdev;
43328c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
43338c2ecf20Sopenharmony_ci	u32 i;
43348c2ecf20Sopenharmony_ci
43358c2ecf20Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++) {
43368c2ecf20Sopenharmony_ci		struct hns3_enet_ring *ring;
43378c2ecf20Sopenharmony_ci
43388c2ecf20Sopenharmony_ci		ring = &priv->ring[i];
43398c2ecf20Sopenharmony_ci		hns3_clear_tx_ring(ring);
43408c2ecf20Sopenharmony_ci
43418c2ecf20Sopenharmony_ci		ring = &priv->ring[i + h->kinfo.num_tqps];
43428c2ecf20Sopenharmony_ci		/* Continue to clear other rings even if clearing some
43438c2ecf20Sopenharmony_ci		 * rings failed.
43448c2ecf20Sopenharmony_ci		 */
43458c2ecf20Sopenharmony_ci		if (force)
43468c2ecf20Sopenharmony_ci			hns3_force_clear_rx_ring(ring);
43478c2ecf20Sopenharmony_ci		else
43488c2ecf20Sopenharmony_ci			hns3_clear_rx_ring(ring);
43498c2ecf20Sopenharmony_ci	}
43508c2ecf20Sopenharmony_ci}
43518c2ecf20Sopenharmony_ci
43528c2ecf20Sopenharmony_ciint hns3_nic_reset_all_ring(struct hnae3_handle *h)
43538c2ecf20Sopenharmony_ci{
43548c2ecf20Sopenharmony_ci	struct net_device *ndev = h->kinfo.netdev;
43558c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
43568c2ecf20Sopenharmony_ci	struct hns3_enet_ring *rx_ring;
43578c2ecf20Sopenharmony_ci	int i, j;
43588c2ecf20Sopenharmony_ci	int ret;
43598c2ecf20Sopenharmony_ci
43608c2ecf20Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++) {
43618c2ecf20Sopenharmony_ci		ret = h->ae_algo->ops->reset_queue(h, i);
43628c2ecf20Sopenharmony_ci		if (ret)
43638c2ecf20Sopenharmony_ci			return ret;
43648c2ecf20Sopenharmony_ci
43658c2ecf20Sopenharmony_ci		hns3_init_ring_hw(&priv->ring[i]);
43668c2ecf20Sopenharmony_ci
43678c2ecf20Sopenharmony_ci		/* We need to clear tx ring here because self test will
43688c2ecf20Sopenharmony_ci		 * use the ring and will not run down before up
43698c2ecf20Sopenharmony_ci		 */
43708c2ecf20Sopenharmony_ci		hns3_clear_tx_ring(&priv->ring[i]);
43718c2ecf20Sopenharmony_ci		priv->ring[i].next_to_clean = 0;
43728c2ecf20Sopenharmony_ci		priv->ring[i].next_to_use = 0;
43738c2ecf20Sopenharmony_ci		priv->ring[i].last_to_use = 0;
43748c2ecf20Sopenharmony_ci
43758c2ecf20Sopenharmony_ci		rx_ring = &priv->ring[i + h->kinfo.num_tqps];
43768c2ecf20Sopenharmony_ci		hns3_init_ring_hw(rx_ring);
43778c2ecf20Sopenharmony_ci		ret = hns3_clear_rx_ring(rx_ring);
43788c2ecf20Sopenharmony_ci		if (ret)
43798c2ecf20Sopenharmony_ci			return ret;
43808c2ecf20Sopenharmony_ci
43818c2ecf20Sopenharmony_ci		/* We can not know the hardware head and tail when this
43828c2ecf20Sopenharmony_ci		 * function is called in reset flow, so we reuse all desc.
43838c2ecf20Sopenharmony_ci		 */
43848c2ecf20Sopenharmony_ci		for (j = 0; j < rx_ring->desc_num; j++)
43858c2ecf20Sopenharmony_ci			hns3_reuse_buffer(rx_ring, j);
43868c2ecf20Sopenharmony_ci
43878c2ecf20Sopenharmony_ci		rx_ring->next_to_clean = 0;
43888c2ecf20Sopenharmony_ci		rx_ring->next_to_use = 0;
43898c2ecf20Sopenharmony_ci	}
43908c2ecf20Sopenharmony_ci
43918c2ecf20Sopenharmony_ci	hns3_init_tx_ring_tc(priv);
43928c2ecf20Sopenharmony_ci
43938c2ecf20Sopenharmony_ci	return 0;
43948c2ecf20Sopenharmony_ci}
43958c2ecf20Sopenharmony_ci
43968c2ecf20Sopenharmony_cistatic void hns3_store_coal(struct hns3_nic_priv *priv)
43978c2ecf20Sopenharmony_ci{
43988c2ecf20Sopenharmony_ci	/* ethtool only support setting and querying one coal
43998c2ecf20Sopenharmony_ci	 * configuration for now, so save the vector 0' coal
44008c2ecf20Sopenharmony_ci	 * configuration here in order to restore it.
44018c2ecf20Sopenharmony_ci	 */
44028c2ecf20Sopenharmony_ci	memcpy(&priv->tx_coal, &priv->tqp_vector[0].tx_group.coal,
44038c2ecf20Sopenharmony_ci	       sizeof(struct hns3_enet_coalesce));
44048c2ecf20Sopenharmony_ci	memcpy(&priv->rx_coal, &priv->tqp_vector[0].rx_group.coal,
44058c2ecf20Sopenharmony_ci	       sizeof(struct hns3_enet_coalesce));
44068c2ecf20Sopenharmony_ci}
44078c2ecf20Sopenharmony_ci
44088c2ecf20Sopenharmony_cistatic void hns3_restore_coal(struct hns3_nic_priv *priv)
44098c2ecf20Sopenharmony_ci{
44108c2ecf20Sopenharmony_ci	u16 vector_num = priv->vector_num;
44118c2ecf20Sopenharmony_ci	int i;
44128c2ecf20Sopenharmony_ci
44138c2ecf20Sopenharmony_ci	for (i = 0; i < vector_num; i++) {
44148c2ecf20Sopenharmony_ci		memcpy(&priv->tqp_vector[i].tx_group.coal, &priv->tx_coal,
44158c2ecf20Sopenharmony_ci		       sizeof(struct hns3_enet_coalesce));
44168c2ecf20Sopenharmony_ci		memcpy(&priv->tqp_vector[i].rx_group.coal, &priv->rx_coal,
44178c2ecf20Sopenharmony_ci		       sizeof(struct hns3_enet_coalesce));
44188c2ecf20Sopenharmony_ci	}
44198c2ecf20Sopenharmony_ci}
44208c2ecf20Sopenharmony_ci
44218c2ecf20Sopenharmony_cistatic int hns3_reset_notify_down_enet(struct hnae3_handle *handle)
44228c2ecf20Sopenharmony_ci{
44238c2ecf20Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
44248c2ecf20Sopenharmony_ci	struct net_device *ndev = kinfo->netdev;
44258c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
44268c2ecf20Sopenharmony_ci
44278c2ecf20Sopenharmony_ci	if (test_and_set_bit(HNS3_NIC_STATE_RESETTING, &priv->state))
44288c2ecf20Sopenharmony_ci		return 0;
44298c2ecf20Sopenharmony_ci
44308c2ecf20Sopenharmony_ci	if (!netif_running(ndev))
44318c2ecf20Sopenharmony_ci		return 0;
44328c2ecf20Sopenharmony_ci
44338c2ecf20Sopenharmony_ci	return hns3_nic_net_stop(ndev);
44348c2ecf20Sopenharmony_ci}
44358c2ecf20Sopenharmony_ci
44368c2ecf20Sopenharmony_cistatic int hns3_reset_notify_up_enet(struct hnae3_handle *handle)
44378c2ecf20Sopenharmony_ci{
44388c2ecf20Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
44398c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(kinfo->netdev);
44408c2ecf20Sopenharmony_ci	int ret = 0;
44418c2ecf20Sopenharmony_ci
44428c2ecf20Sopenharmony_ci	if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state)) {
44438c2ecf20Sopenharmony_ci		netdev_err(kinfo->netdev, "device is not initialized yet\n");
44448c2ecf20Sopenharmony_ci		return -EFAULT;
44458c2ecf20Sopenharmony_ci	}
44468c2ecf20Sopenharmony_ci
44478c2ecf20Sopenharmony_ci	clear_bit(HNS3_NIC_STATE_RESETTING, &priv->state);
44488c2ecf20Sopenharmony_ci
44498c2ecf20Sopenharmony_ci	if (netif_running(kinfo->netdev)) {
44508c2ecf20Sopenharmony_ci		ret = hns3_nic_net_open(kinfo->netdev);
44518c2ecf20Sopenharmony_ci		if (ret) {
44528c2ecf20Sopenharmony_ci			set_bit(HNS3_NIC_STATE_RESETTING, &priv->state);
44538c2ecf20Sopenharmony_ci			netdev_err(kinfo->netdev,
44548c2ecf20Sopenharmony_ci				   "net up fail, ret=%d!\n", ret);
44558c2ecf20Sopenharmony_ci			return ret;
44568c2ecf20Sopenharmony_ci		}
44578c2ecf20Sopenharmony_ci	}
44588c2ecf20Sopenharmony_ci
44598c2ecf20Sopenharmony_ci	return ret;
44608c2ecf20Sopenharmony_ci}
44618c2ecf20Sopenharmony_ci
44628c2ecf20Sopenharmony_cistatic int hns3_reset_notify_init_enet(struct hnae3_handle *handle)
44638c2ecf20Sopenharmony_ci{
44648c2ecf20Sopenharmony_ci	struct net_device *netdev = handle->kinfo.netdev;
44658c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
44668c2ecf20Sopenharmony_ci	int ret;
44678c2ecf20Sopenharmony_ci
44688c2ecf20Sopenharmony_ci	/* Carrier off reporting is important to ethtool even BEFORE open */
44698c2ecf20Sopenharmony_ci	netif_carrier_off(netdev);
44708c2ecf20Sopenharmony_ci
44718c2ecf20Sopenharmony_ci	ret = hns3_get_ring_config(priv);
44728c2ecf20Sopenharmony_ci	if (ret)
44738c2ecf20Sopenharmony_ci		return ret;
44748c2ecf20Sopenharmony_ci
44758c2ecf20Sopenharmony_ci	ret = hns3_nic_alloc_vector_data(priv);
44768c2ecf20Sopenharmony_ci	if (ret)
44778c2ecf20Sopenharmony_ci		goto err_put_ring;
44788c2ecf20Sopenharmony_ci
44798c2ecf20Sopenharmony_ci	hns3_restore_coal(priv);
44808c2ecf20Sopenharmony_ci
44818c2ecf20Sopenharmony_ci	ret = hns3_nic_init_vector_data(priv);
44828c2ecf20Sopenharmony_ci	if (ret)
44838c2ecf20Sopenharmony_ci		goto err_dealloc_vector;
44848c2ecf20Sopenharmony_ci
44858c2ecf20Sopenharmony_ci	ret = hns3_init_all_ring(priv);
44868c2ecf20Sopenharmony_ci	if (ret)
44878c2ecf20Sopenharmony_ci		goto err_uninit_vector;
44888c2ecf20Sopenharmony_ci
44898c2ecf20Sopenharmony_ci	/* the device can work without cpu rmap, only aRFS needs it */
44908c2ecf20Sopenharmony_ci	ret = hns3_set_rx_cpu_rmap(netdev);
44918c2ecf20Sopenharmony_ci	if (ret)
44928c2ecf20Sopenharmony_ci		dev_warn(priv->dev, "set rx cpu rmap fail, ret=%d\n", ret);
44938c2ecf20Sopenharmony_ci
44948c2ecf20Sopenharmony_ci	ret = hns3_nic_init_irq(priv);
44958c2ecf20Sopenharmony_ci	if (ret) {
44968c2ecf20Sopenharmony_ci		dev_err(priv->dev, "init irq failed! ret=%d\n", ret);
44978c2ecf20Sopenharmony_ci		hns3_free_rx_cpu_rmap(netdev);
44988c2ecf20Sopenharmony_ci		goto err_init_irq_fail;
44998c2ecf20Sopenharmony_ci	}
45008c2ecf20Sopenharmony_ci
45018c2ecf20Sopenharmony_ci	if (!hns3_is_phys_func(handle->pdev))
45028c2ecf20Sopenharmony_ci		hns3_init_mac_addr(netdev);
45038c2ecf20Sopenharmony_ci
45048c2ecf20Sopenharmony_ci	ret = hns3_client_start(handle);
45058c2ecf20Sopenharmony_ci	if (ret) {
45068c2ecf20Sopenharmony_ci		dev_err(priv->dev, "hns3_client_start fail! ret=%d\n", ret);
45078c2ecf20Sopenharmony_ci		goto err_client_start_fail;
45088c2ecf20Sopenharmony_ci	}
45098c2ecf20Sopenharmony_ci
45108c2ecf20Sopenharmony_ci	set_bit(HNS3_NIC_STATE_INITED, &priv->state);
45118c2ecf20Sopenharmony_ci
45128c2ecf20Sopenharmony_ci	return ret;
45138c2ecf20Sopenharmony_ci
45148c2ecf20Sopenharmony_cierr_client_start_fail:
45158c2ecf20Sopenharmony_ci	hns3_free_rx_cpu_rmap(netdev);
45168c2ecf20Sopenharmony_ci	hns3_nic_uninit_irq(priv);
45178c2ecf20Sopenharmony_cierr_init_irq_fail:
45188c2ecf20Sopenharmony_ci	hns3_uninit_all_ring(priv);
45198c2ecf20Sopenharmony_cierr_uninit_vector:
45208c2ecf20Sopenharmony_ci	hns3_nic_uninit_vector_data(priv);
45218c2ecf20Sopenharmony_cierr_dealloc_vector:
45228c2ecf20Sopenharmony_ci	hns3_nic_dealloc_vector_data(priv);
45238c2ecf20Sopenharmony_cierr_put_ring:
45248c2ecf20Sopenharmony_ci	hns3_put_ring_config(priv);
45258c2ecf20Sopenharmony_ci
45268c2ecf20Sopenharmony_ci	return ret;
45278c2ecf20Sopenharmony_ci}
45288c2ecf20Sopenharmony_ci
45298c2ecf20Sopenharmony_cistatic int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
45308c2ecf20Sopenharmony_ci{
45318c2ecf20Sopenharmony_ci	struct net_device *netdev = handle->kinfo.netdev;
45328c2ecf20Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
45338c2ecf20Sopenharmony_ci	int ret;
45348c2ecf20Sopenharmony_ci
45358c2ecf20Sopenharmony_ci	if (!test_and_clear_bit(HNS3_NIC_STATE_INITED, &priv->state)) {
45368c2ecf20Sopenharmony_ci		netdev_warn(netdev, "already uninitialized\n");
45378c2ecf20Sopenharmony_ci		return 0;
45388c2ecf20Sopenharmony_ci	}
45398c2ecf20Sopenharmony_ci
45408c2ecf20Sopenharmony_ci	hns3_free_rx_cpu_rmap(netdev);
45418c2ecf20Sopenharmony_ci	hns3_nic_uninit_irq(priv);
45428c2ecf20Sopenharmony_ci	hns3_clear_all_ring(handle, true);
45438c2ecf20Sopenharmony_ci	hns3_reset_tx_queue(priv->ae_handle);
45448c2ecf20Sopenharmony_ci
45458c2ecf20Sopenharmony_ci	hns3_nic_uninit_vector_data(priv);
45468c2ecf20Sopenharmony_ci
45478c2ecf20Sopenharmony_ci	hns3_store_coal(priv);
45488c2ecf20Sopenharmony_ci
45498c2ecf20Sopenharmony_ci	hns3_nic_dealloc_vector_data(priv);
45508c2ecf20Sopenharmony_ci
45518c2ecf20Sopenharmony_ci	ret = hns3_uninit_all_ring(priv);
45528c2ecf20Sopenharmony_ci	if (ret)
45538c2ecf20Sopenharmony_ci		netdev_err(netdev, "uninit ring error\n");
45548c2ecf20Sopenharmony_ci
45558c2ecf20Sopenharmony_ci	hns3_put_ring_config(priv);
45568c2ecf20Sopenharmony_ci
45578c2ecf20Sopenharmony_ci	return ret;
45588c2ecf20Sopenharmony_ci}
45598c2ecf20Sopenharmony_ci
45608c2ecf20Sopenharmony_cistatic int hns3_reset_notify(struct hnae3_handle *handle,
45618c2ecf20Sopenharmony_ci			     enum hnae3_reset_notify_type type)
45628c2ecf20Sopenharmony_ci{
45638c2ecf20Sopenharmony_ci	int ret = 0;
45648c2ecf20Sopenharmony_ci
45658c2ecf20Sopenharmony_ci	switch (type) {
45668c2ecf20Sopenharmony_ci	case HNAE3_UP_CLIENT:
45678c2ecf20Sopenharmony_ci		ret = hns3_reset_notify_up_enet(handle);
45688c2ecf20Sopenharmony_ci		break;
45698c2ecf20Sopenharmony_ci	case HNAE3_DOWN_CLIENT:
45708c2ecf20Sopenharmony_ci		ret = hns3_reset_notify_down_enet(handle);
45718c2ecf20Sopenharmony_ci		break;
45728c2ecf20Sopenharmony_ci	case HNAE3_INIT_CLIENT:
45738c2ecf20Sopenharmony_ci		ret = hns3_reset_notify_init_enet(handle);
45748c2ecf20Sopenharmony_ci		break;
45758c2ecf20Sopenharmony_ci	case HNAE3_UNINIT_CLIENT:
45768c2ecf20Sopenharmony_ci		ret = hns3_reset_notify_uninit_enet(handle);
45778c2ecf20Sopenharmony_ci		break;
45788c2ecf20Sopenharmony_ci	default:
45798c2ecf20Sopenharmony_ci		break;
45808c2ecf20Sopenharmony_ci	}
45818c2ecf20Sopenharmony_ci
45828c2ecf20Sopenharmony_ci	return ret;
45838c2ecf20Sopenharmony_ci}
45848c2ecf20Sopenharmony_ci
45858c2ecf20Sopenharmony_cistatic int hns3_change_channels(struct hnae3_handle *handle, u32 new_tqp_num,
45868c2ecf20Sopenharmony_ci				bool rxfh_configured)
45878c2ecf20Sopenharmony_ci{
45888c2ecf20Sopenharmony_ci	int ret;
45898c2ecf20Sopenharmony_ci
45908c2ecf20Sopenharmony_ci	ret = handle->ae_algo->ops->set_channels(handle, new_tqp_num,
45918c2ecf20Sopenharmony_ci						 rxfh_configured);
45928c2ecf20Sopenharmony_ci	if (ret) {
45938c2ecf20Sopenharmony_ci		dev_err(&handle->pdev->dev,
45948c2ecf20Sopenharmony_ci			"Change tqp num(%u) fail.\n", new_tqp_num);
45958c2ecf20Sopenharmony_ci		return ret;
45968c2ecf20Sopenharmony_ci	}
45978c2ecf20Sopenharmony_ci
45988c2ecf20Sopenharmony_ci	ret = hns3_reset_notify(handle, HNAE3_INIT_CLIENT);
45998c2ecf20Sopenharmony_ci	if (ret)
46008c2ecf20Sopenharmony_ci		return ret;
46018c2ecf20Sopenharmony_ci
46028c2ecf20Sopenharmony_ci	ret =  hns3_reset_notify(handle, HNAE3_UP_CLIENT);
46038c2ecf20Sopenharmony_ci	if (ret)
46048c2ecf20Sopenharmony_ci		hns3_reset_notify(handle, HNAE3_UNINIT_CLIENT);
46058c2ecf20Sopenharmony_ci
46068c2ecf20Sopenharmony_ci	return ret;
46078c2ecf20Sopenharmony_ci}
46088c2ecf20Sopenharmony_ci
46098c2ecf20Sopenharmony_ciint hns3_set_channels(struct net_device *netdev,
46108c2ecf20Sopenharmony_ci		      struct ethtool_channels *ch)
46118c2ecf20Sopenharmony_ci{
46128c2ecf20Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
46138c2ecf20Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &h->kinfo;
46148c2ecf20Sopenharmony_ci	bool rxfh_configured = netif_is_rxfh_configured(netdev);
46158c2ecf20Sopenharmony_ci	u32 new_tqp_num = ch->combined_count;
46168c2ecf20Sopenharmony_ci	u16 org_tqp_num;
46178c2ecf20Sopenharmony_ci	int ret;
46188c2ecf20Sopenharmony_ci
46198c2ecf20Sopenharmony_ci	if (hns3_nic_resetting(netdev))
46208c2ecf20Sopenharmony_ci		return -EBUSY;
46218c2ecf20Sopenharmony_ci
46228c2ecf20Sopenharmony_ci	if (ch->rx_count || ch->tx_count)
46238c2ecf20Sopenharmony_ci		return -EINVAL;
46248c2ecf20Sopenharmony_ci
46258c2ecf20Sopenharmony_ci	if (new_tqp_num > hns3_get_max_available_channels(h) ||
46268c2ecf20Sopenharmony_ci	    new_tqp_num < 1) {
46278c2ecf20Sopenharmony_ci		dev_err(&netdev->dev,
46288c2ecf20Sopenharmony_ci			"Change tqps fail, the tqp range is from 1 to %u",
46298c2ecf20Sopenharmony_ci			hns3_get_max_available_channels(h));
46308c2ecf20Sopenharmony_ci		return -EINVAL;
46318c2ecf20Sopenharmony_ci	}
46328c2ecf20Sopenharmony_ci
46338c2ecf20Sopenharmony_ci	if (kinfo->rss_size == new_tqp_num)
46348c2ecf20Sopenharmony_ci		return 0;
46358c2ecf20Sopenharmony_ci
46368c2ecf20Sopenharmony_ci	netif_dbg(h, drv, netdev,
46378c2ecf20Sopenharmony_ci		  "set channels: tqp_num=%u, rxfh=%d\n",
46388c2ecf20Sopenharmony_ci		  new_tqp_num, rxfh_configured);
46398c2ecf20Sopenharmony_ci
46408c2ecf20Sopenharmony_ci	ret = hns3_reset_notify(h, HNAE3_DOWN_CLIENT);
46418c2ecf20Sopenharmony_ci	if (ret)
46428c2ecf20Sopenharmony_ci		return ret;
46438c2ecf20Sopenharmony_ci
46448c2ecf20Sopenharmony_ci	ret = hns3_reset_notify(h, HNAE3_UNINIT_CLIENT);
46458c2ecf20Sopenharmony_ci	if (ret)
46468c2ecf20Sopenharmony_ci		return ret;
46478c2ecf20Sopenharmony_ci
46488c2ecf20Sopenharmony_ci	org_tqp_num = h->kinfo.num_tqps;
46498c2ecf20Sopenharmony_ci	ret = hns3_change_channels(h, new_tqp_num, rxfh_configured);
46508c2ecf20Sopenharmony_ci	if (ret) {
46518c2ecf20Sopenharmony_ci		int ret1;
46528c2ecf20Sopenharmony_ci
46538c2ecf20Sopenharmony_ci		netdev_warn(netdev,
46548c2ecf20Sopenharmony_ci			    "Change channels fail, revert to old value\n");
46558c2ecf20Sopenharmony_ci		ret1 = hns3_change_channels(h, org_tqp_num, rxfh_configured);
46568c2ecf20Sopenharmony_ci		if (ret1) {
46578c2ecf20Sopenharmony_ci			netdev_err(netdev,
46588c2ecf20Sopenharmony_ci				   "revert to old channel fail\n");
46598c2ecf20Sopenharmony_ci			return ret1;
46608c2ecf20Sopenharmony_ci		}
46618c2ecf20Sopenharmony_ci
46628c2ecf20Sopenharmony_ci		return ret;
46638c2ecf20Sopenharmony_ci	}
46648c2ecf20Sopenharmony_ci
46658c2ecf20Sopenharmony_ci	return 0;
46668c2ecf20Sopenharmony_ci}
46678c2ecf20Sopenharmony_ci
46688c2ecf20Sopenharmony_cistatic const struct hns3_hw_error_info hns3_hw_err[] = {
46698c2ecf20Sopenharmony_ci	{ .type = HNAE3_PPU_POISON_ERROR,
46708c2ecf20Sopenharmony_ci	  .msg = "PPU poison" },
46718c2ecf20Sopenharmony_ci	{ .type = HNAE3_CMDQ_ECC_ERROR,
46728c2ecf20Sopenharmony_ci	  .msg = "IMP CMDQ error" },
46738c2ecf20Sopenharmony_ci	{ .type = HNAE3_IMP_RD_POISON_ERROR,
46748c2ecf20Sopenharmony_ci	  .msg = "IMP RD poison" },
46758c2ecf20Sopenharmony_ci	{ .type = HNAE3_ROCEE_AXI_RESP_ERROR,
46768c2ecf20Sopenharmony_ci	  .msg = "ROCEE AXI RESP error" },
46778c2ecf20Sopenharmony_ci};
46788c2ecf20Sopenharmony_ci
46798c2ecf20Sopenharmony_cistatic void hns3_process_hw_error(struct hnae3_handle *handle,
46808c2ecf20Sopenharmony_ci				  enum hnae3_hw_error_type type)
46818c2ecf20Sopenharmony_ci{
46828c2ecf20Sopenharmony_ci	int i;
46838c2ecf20Sopenharmony_ci
46848c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(hns3_hw_err); i++) {
46858c2ecf20Sopenharmony_ci		if (hns3_hw_err[i].type == type) {
46868c2ecf20Sopenharmony_ci			dev_err(&handle->pdev->dev, "Detected %s!\n",
46878c2ecf20Sopenharmony_ci				hns3_hw_err[i].msg);
46888c2ecf20Sopenharmony_ci			break;
46898c2ecf20Sopenharmony_ci		}
46908c2ecf20Sopenharmony_ci	}
46918c2ecf20Sopenharmony_ci}
46928c2ecf20Sopenharmony_ci
46938c2ecf20Sopenharmony_cistatic const struct hnae3_client_ops client_ops = {
46948c2ecf20Sopenharmony_ci	.init_instance = hns3_client_init,
46958c2ecf20Sopenharmony_ci	.uninit_instance = hns3_client_uninit,
46968c2ecf20Sopenharmony_ci	.link_status_change = hns3_link_status_change,
46978c2ecf20Sopenharmony_ci	.setup_tc = hns3_client_setup_tc,
46988c2ecf20Sopenharmony_ci	.reset_notify = hns3_reset_notify,
46998c2ecf20Sopenharmony_ci	.process_hw_error = hns3_process_hw_error,
47008c2ecf20Sopenharmony_ci};
47018c2ecf20Sopenharmony_ci
47028c2ecf20Sopenharmony_ci/* hns3_init_module - Driver registration routine
47038c2ecf20Sopenharmony_ci * hns3_init_module is the first routine called when the driver is
47048c2ecf20Sopenharmony_ci * loaded. All it does is register with the PCI subsystem.
47058c2ecf20Sopenharmony_ci */
47068c2ecf20Sopenharmony_cistatic int __init hns3_init_module(void)
47078c2ecf20Sopenharmony_ci{
47088c2ecf20Sopenharmony_ci	int ret;
47098c2ecf20Sopenharmony_ci
47108c2ecf20Sopenharmony_ci	pr_info("%s: %s - version\n", hns3_driver_name, hns3_driver_string);
47118c2ecf20Sopenharmony_ci	pr_info("%s: %s\n", hns3_driver_name, hns3_copyright);
47128c2ecf20Sopenharmony_ci
47138c2ecf20Sopenharmony_ci	client.type = HNAE3_CLIENT_KNIC;
47148c2ecf20Sopenharmony_ci	snprintf(client.name, HNAE3_CLIENT_NAME_LENGTH, "%s",
47158c2ecf20Sopenharmony_ci		 hns3_driver_name);
47168c2ecf20Sopenharmony_ci
47178c2ecf20Sopenharmony_ci	client.ops = &client_ops;
47188c2ecf20Sopenharmony_ci
47198c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&client.node);
47208c2ecf20Sopenharmony_ci
47218c2ecf20Sopenharmony_ci	hns3_dbg_register_debugfs(hns3_driver_name);
47228c2ecf20Sopenharmony_ci
47238c2ecf20Sopenharmony_ci	ret = hnae3_register_client(&client);
47248c2ecf20Sopenharmony_ci	if (ret)
47258c2ecf20Sopenharmony_ci		goto err_reg_client;
47268c2ecf20Sopenharmony_ci
47278c2ecf20Sopenharmony_ci	ret = pci_register_driver(&hns3_driver);
47288c2ecf20Sopenharmony_ci	if (ret)
47298c2ecf20Sopenharmony_ci		goto err_reg_driver;
47308c2ecf20Sopenharmony_ci
47318c2ecf20Sopenharmony_ci	return ret;
47328c2ecf20Sopenharmony_ci
47338c2ecf20Sopenharmony_cierr_reg_driver:
47348c2ecf20Sopenharmony_ci	hnae3_unregister_client(&client);
47358c2ecf20Sopenharmony_cierr_reg_client:
47368c2ecf20Sopenharmony_ci	hns3_dbg_unregister_debugfs();
47378c2ecf20Sopenharmony_ci	return ret;
47388c2ecf20Sopenharmony_ci}
47398c2ecf20Sopenharmony_cimodule_init(hns3_init_module);
47408c2ecf20Sopenharmony_ci
47418c2ecf20Sopenharmony_ci/* hns3_exit_module - Driver exit cleanup routine
47428c2ecf20Sopenharmony_ci * hns3_exit_module is called just before the driver is removed
47438c2ecf20Sopenharmony_ci * from memory.
47448c2ecf20Sopenharmony_ci */
47458c2ecf20Sopenharmony_cistatic void __exit hns3_exit_module(void)
47468c2ecf20Sopenharmony_ci{
47478c2ecf20Sopenharmony_ci	pci_unregister_driver(&hns3_driver);
47488c2ecf20Sopenharmony_ci	hnae3_unregister_client(&client);
47498c2ecf20Sopenharmony_ci	hns3_dbg_unregister_debugfs();
47508c2ecf20Sopenharmony_ci}
47518c2ecf20Sopenharmony_cimodule_exit(hns3_exit_module);
47528c2ecf20Sopenharmony_ci
47538c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("HNS3: Hisilicon Ethernet Driver");
47548c2ecf20Sopenharmony_ciMODULE_AUTHOR("Huawei Tech. Co., Ltd.");
47558c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
47568c2ecf20Sopenharmony_ciMODULE_ALIAS("pci:hns-nic");
4757