162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci// Copyright (c) 2016-2017 Hisilicon Limited.
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/dma-mapping.h>
562306a36Sopenharmony_ci#include <linux/etherdevice.h>
662306a36Sopenharmony_ci#include <linux/interrupt.h>
762306a36Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
862306a36Sopenharmony_ci#include <linux/cpu_rmap.h>
962306a36Sopenharmony_ci#endif
1062306a36Sopenharmony_ci#include <linux/if_vlan.h>
1162306a36Sopenharmony_ci#include <linux/irq.h>
1262306a36Sopenharmony_ci#include <linux/ip.h>
1362306a36Sopenharmony_ci#include <linux/ipv6.h>
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include <linux/pci.h>
1662306a36Sopenharmony_ci#include <linux/skbuff.h>
1762306a36Sopenharmony_ci#include <linux/sctp.h>
1862306a36Sopenharmony_ci#include <net/gre.h>
1962306a36Sopenharmony_ci#include <net/gro.h>
2062306a36Sopenharmony_ci#include <net/ip6_checksum.h>
2162306a36Sopenharmony_ci#include <net/page_pool/helpers.h>
2262306a36Sopenharmony_ci#include <net/pkt_cls.h>
2362306a36Sopenharmony_ci#include <net/pkt_sched.h>
2462306a36Sopenharmony_ci#include <net/tcp.h>
2562306a36Sopenharmony_ci#include <net/vxlan.h>
2662306a36Sopenharmony_ci#include <net/geneve.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include "hnae3.h"
2962306a36Sopenharmony_ci#include "hns3_enet.h"
3062306a36Sopenharmony_ci/* All hns3 tracepoints are defined by the include below, which
3162306a36Sopenharmony_ci * must be included exactly once across the whole kernel with
3262306a36Sopenharmony_ci * CREATE_TRACE_POINTS defined
3362306a36Sopenharmony_ci */
3462306a36Sopenharmony_ci#define CREATE_TRACE_POINTS
3562306a36Sopenharmony_ci#include "hns3_trace.h"
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define hns3_set_field(origin, shift, val)	((origin) |= (val) << (shift))
3862306a36Sopenharmony_ci#define hns3_tx_bd_count(S)	DIV_ROUND_UP(S, HNS3_MAX_BD_SIZE)
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define hns3_rl_err(fmt, ...)						\
4162306a36Sopenharmony_ci	do {								\
4262306a36Sopenharmony_ci		if (net_ratelimit())					\
4362306a36Sopenharmony_ci			netdev_err(fmt, ##__VA_ARGS__);			\
4462306a36Sopenharmony_ci	} while (0)
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic void hns3_clear_all_ring(struct hnae3_handle *h, bool force);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic const char hns3_driver_name[] = "hns3";
4962306a36Sopenharmony_cistatic const char hns3_driver_string[] =
5062306a36Sopenharmony_ci			"Hisilicon Ethernet Network Driver for Hip08 Family";
5162306a36Sopenharmony_cistatic const char hns3_copyright[] = "Copyright (c) 2017 Huawei Corporation.";
5262306a36Sopenharmony_cistatic struct hnae3_client client;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic int debug = -1;
5562306a36Sopenharmony_cimodule_param(debug, int, 0);
5662306a36Sopenharmony_ciMODULE_PARM_DESC(debug, " Network interface message level setting");
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic unsigned int tx_sgl = 1;
5962306a36Sopenharmony_cimodule_param(tx_sgl, uint, 0600);
6062306a36Sopenharmony_ciMODULE_PARM_DESC(tx_sgl, "Minimum number of frags when using dma_map_sg() to optimize the IOMMU mapping");
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistatic bool page_pool_enabled = true;
6362306a36Sopenharmony_cimodule_param(page_pool_enabled, bool, 0400);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#define HNS3_SGL_SIZE(nfrag)	(sizeof(struct scatterlist) * (nfrag) +	\
6662306a36Sopenharmony_ci				 sizeof(struct sg_table))
6762306a36Sopenharmony_ci#define HNS3_MAX_SGL_SIZE	ALIGN(HNS3_SGL_SIZE(HNS3_MAX_TSO_BD_NUM), \
6862306a36Sopenharmony_ci				      dma_get_cache_alignment())
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci#define DEFAULT_MSG_LEVEL (NETIF_MSG_PROBE | NETIF_MSG_LINK | \
7162306a36Sopenharmony_ci			   NETIF_MSG_IFDOWN | NETIF_MSG_IFUP)
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define HNS3_INNER_VLAN_TAG	1
7462306a36Sopenharmony_ci#define HNS3_OUTER_VLAN_TAG	2
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define HNS3_MIN_TX_LEN		33U
7762306a36Sopenharmony_ci#define HNS3_MIN_TUN_PKT_LEN	65U
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/* hns3_pci_tbl - PCI Device ID Table
8062306a36Sopenharmony_ci *
8162306a36Sopenharmony_ci * Last entry must be all 0s
8262306a36Sopenharmony_ci *
8362306a36Sopenharmony_ci * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
8462306a36Sopenharmony_ci *   Class, Class Mask, private data (not used) }
8562306a36Sopenharmony_ci */
8662306a36Sopenharmony_cistatic const struct pci_device_id hns3_pci_tbl[] = {
8762306a36Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_GE), 0},
8862306a36Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE), 0},
8962306a36Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA),
9062306a36Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
9162306a36Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA_MACSEC),
9262306a36Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
9362306a36Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA),
9462306a36Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
9562306a36Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA_MACSEC),
9662306a36Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
9762306a36Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_MACSEC),
9862306a36Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
9962306a36Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_200G_RDMA),
10062306a36Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
10162306a36Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_VF), 0},
10262306a36Sopenharmony_ci	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_RDMA_DCB_PFC_VF),
10362306a36Sopenharmony_ci	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
10462306a36Sopenharmony_ci	/* required last entry */
10562306a36Sopenharmony_ci	{0,}
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, hns3_pci_tbl);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci#define HNS3_RX_PTYPE_ENTRY(ptype, l, s, t, h) \
11062306a36Sopenharmony_ci	{	ptype, \
11162306a36Sopenharmony_ci		l, \
11262306a36Sopenharmony_ci		CHECKSUM_##s, \
11362306a36Sopenharmony_ci		HNS3_L3_TYPE_##t, \
11462306a36Sopenharmony_ci		1, \
11562306a36Sopenharmony_ci		h}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci#define HNS3_RX_PTYPE_UNUSED_ENTRY(ptype) \
11862306a36Sopenharmony_ci		{ ptype, 0, CHECKSUM_NONE, HNS3_L3_TYPE_PARSE_FAIL, 0, \
11962306a36Sopenharmony_ci		  PKT_HASH_TYPE_NONE }
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistatic const struct hns3_rx_ptype hns3_rx_ptype_tbl[] = {
12262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(0),
12362306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(1, 0, COMPLETE, ARP, PKT_HASH_TYPE_NONE),
12462306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(2, 0, COMPLETE, RARP, PKT_HASH_TYPE_NONE),
12562306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(3, 0, COMPLETE, LLDP, PKT_HASH_TYPE_NONE),
12662306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(4, 0, COMPLETE, PARSE_FAIL, PKT_HASH_TYPE_NONE),
12762306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(5, 0, COMPLETE, PARSE_FAIL, PKT_HASH_TYPE_NONE),
12862306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(6, 0, COMPLETE, PARSE_FAIL, PKT_HASH_TYPE_NONE),
12962306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(7, 0, COMPLETE, CNM, PKT_HASH_TYPE_NONE),
13062306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(8, 0, NONE, PARSE_FAIL, PKT_HASH_TYPE_NONE),
13162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(9),
13262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(10),
13362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(11),
13462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(12),
13562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(13),
13662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(14),
13762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(15),
13862306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(16, 0, COMPLETE, PARSE_FAIL, PKT_HASH_TYPE_NONE),
13962306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(17, 0, COMPLETE, IPV4, PKT_HASH_TYPE_NONE),
14062306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(18, 0, COMPLETE, IPV4, PKT_HASH_TYPE_NONE),
14162306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(19, 0, UNNECESSARY, IPV4, PKT_HASH_TYPE_L4),
14262306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(20, 0, UNNECESSARY, IPV4, PKT_HASH_TYPE_L4),
14362306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(21, 0, NONE, IPV4, PKT_HASH_TYPE_NONE),
14462306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(22, 0, UNNECESSARY, IPV4, PKT_HASH_TYPE_L4),
14562306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(23, 0, NONE, IPV4, PKT_HASH_TYPE_L3),
14662306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(24, 0, NONE, IPV4, PKT_HASH_TYPE_L3),
14762306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(25, 0, UNNECESSARY, IPV4, PKT_HASH_TYPE_L4),
14862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(26),
14962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(27),
15062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(28),
15162306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(29, 0, COMPLETE, PARSE_FAIL, PKT_HASH_TYPE_NONE),
15262306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(30, 0, COMPLETE, PARSE_FAIL, PKT_HASH_TYPE_NONE),
15362306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(31, 0, COMPLETE, IPV4, PKT_HASH_TYPE_L3),
15462306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(32, 0, COMPLETE, IPV4, PKT_HASH_TYPE_L3),
15562306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(33, 1, UNNECESSARY, IPV4, PKT_HASH_TYPE_L4),
15662306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(34, 1, UNNECESSARY, IPV4, PKT_HASH_TYPE_L4),
15762306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(35, 1, UNNECESSARY, IPV4, PKT_HASH_TYPE_L4),
15862306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(36, 0, COMPLETE, IPV4, PKT_HASH_TYPE_L3),
15962306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(37, 0, COMPLETE, IPV4, PKT_HASH_TYPE_L3),
16062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(38),
16162306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(39, 0, COMPLETE, IPV6, PKT_HASH_TYPE_L3),
16262306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(40, 0, COMPLETE, IPV6, PKT_HASH_TYPE_L3),
16362306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(41, 1, UNNECESSARY, IPV6, PKT_HASH_TYPE_L4),
16462306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(42, 1, UNNECESSARY, IPV6, PKT_HASH_TYPE_L4),
16562306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(43, 1, UNNECESSARY, IPV6, PKT_HASH_TYPE_L4),
16662306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(44, 0, COMPLETE, IPV6, PKT_HASH_TYPE_L3),
16762306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(45, 0, COMPLETE, IPV6, PKT_HASH_TYPE_L3),
16862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(46),
16962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(47),
17062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(48),
17162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(49),
17262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(50),
17362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(51),
17462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(52),
17562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(53),
17662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(54),
17762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(55),
17862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(56),
17962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(57),
18062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(58),
18162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(59),
18262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(60),
18362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(61),
18462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(62),
18562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(63),
18662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(64),
18762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(65),
18862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(66),
18962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(67),
19062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(68),
19162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(69),
19262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(70),
19362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(71),
19462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(72),
19562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(73),
19662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(74),
19762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(75),
19862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(76),
19962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(77),
20062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(78),
20162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(79),
20262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(80),
20362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(81),
20462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(82),
20562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(83),
20662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(84),
20762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(85),
20862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(86),
20962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(87),
21062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(88),
21162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(89),
21262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(90),
21362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(91),
21462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(92),
21562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(93),
21662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(94),
21762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(95),
21862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(96),
21962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(97),
22062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(98),
22162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(99),
22262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(100),
22362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(101),
22462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(102),
22562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(103),
22662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(104),
22762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(105),
22862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(106),
22962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(107),
23062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(108),
23162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(109),
23262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(110),
23362306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(111, 0, COMPLETE, IPV6, PKT_HASH_TYPE_L3),
23462306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(112, 0, COMPLETE, IPV6, PKT_HASH_TYPE_L3),
23562306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(113, 0, UNNECESSARY, IPV6, PKT_HASH_TYPE_L4),
23662306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(114, 0, UNNECESSARY, IPV6, PKT_HASH_TYPE_L4),
23762306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(115, 0, NONE, IPV6, PKT_HASH_TYPE_L3),
23862306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(116, 0, UNNECESSARY, IPV6, PKT_HASH_TYPE_L4),
23962306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(117, 0, NONE, IPV6, PKT_HASH_TYPE_L3),
24062306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(118, 0, NONE, IPV6, PKT_HASH_TYPE_L3),
24162306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(119, 0, UNNECESSARY, IPV6, PKT_HASH_TYPE_L4),
24262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(120),
24362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(121),
24462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(122),
24562306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(123, 0, COMPLETE, PARSE_FAIL, PKT_HASH_TYPE_NONE),
24662306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(124, 0, COMPLETE, PARSE_FAIL, PKT_HASH_TYPE_NONE),
24762306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(125, 0, COMPLETE, IPV4, PKT_HASH_TYPE_L3),
24862306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(126, 0, COMPLETE, IPV4, PKT_HASH_TYPE_L3),
24962306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(127, 1, UNNECESSARY, IPV4, PKT_HASH_TYPE_L4),
25062306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(128, 1, UNNECESSARY, IPV4, PKT_HASH_TYPE_L4),
25162306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(129, 1, UNNECESSARY, IPV4, PKT_HASH_TYPE_L4),
25262306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(130, 0, COMPLETE, IPV4, PKT_HASH_TYPE_L3),
25362306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(131, 0, COMPLETE, IPV4, PKT_HASH_TYPE_L3),
25462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(132),
25562306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(133, 0, COMPLETE, IPV6, PKT_HASH_TYPE_L3),
25662306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(134, 0, COMPLETE, IPV6, PKT_HASH_TYPE_L3),
25762306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(135, 1, UNNECESSARY, IPV6, PKT_HASH_TYPE_L4),
25862306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(136, 1, UNNECESSARY, IPV6, PKT_HASH_TYPE_L4),
25962306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(137, 1, UNNECESSARY, IPV6, PKT_HASH_TYPE_L4),
26062306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(138, 0, COMPLETE, IPV6, PKT_HASH_TYPE_L3),
26162306a36Sopenharmony_ci	HNS3_RX_PTYPE_ENTRY(139, 0, COMPLETE, IPV6, PKT_HASH_TYPE_L3),
26262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(140),
26362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(141),
26462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(142),
26562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(143),
26662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(144),
26762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(145),
26862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(146),
26962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(147),
27062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(148),
27162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(149),
27262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(150),
27362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(151),
27462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(152),
27562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(153),
27662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(154),
27762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(155),
27862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(156),
27962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(157),
28062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(158),
28162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(159),
28262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(160),
28362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(161),
28462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(162),
28562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(163),
28662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(164),
28762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(165),
28862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(166),
28962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(167),
29062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(168),
29162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(169),
29262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(170),
29362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(171),
29462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(172),
29562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(173),
29662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(174),
29762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(175),
29862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(176),
29962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(177),
30062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(178),
30162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(179),
30262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(180),
30362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(181),
30462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(182),
30562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(183),
30662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(184),
30762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(185),
30862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(186),
30962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(187),
31062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(188),
31162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(189),
31262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(190),
31362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(191),
31462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(192),
31562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(193),
31662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(194),
31762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(195),
31862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(196),
31962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(197),
32062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(198),
32162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(199),
32262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(200),
32362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(201),
32462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(202),
32562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(203),
32662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(204),
32762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(205),
32862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(206),
32962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(207),
33062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(208),
33162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(209),
33262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(210),
33362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(211),
33462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(212),
33562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(213),
33662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(214),
33762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(215),
33862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(216),
33962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(217),
34062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(218),
34162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(219),
34262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(220),
34362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(221),
34462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(222),
34562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(223),
34662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(224),
34762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(225),
34862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(226),
34962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(227),
35062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(228),
35162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(229),
35262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(230),
35362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(231),
35462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(232),
35562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(233),
35662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(234),
35762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(235),
35862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(236),
35962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(237),
36062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(238),
36162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(239),
36262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(240),
36362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(241),
36462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(242),
36562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(243),
36662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(244),
36762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(245),
36862306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(246),
36962306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(247),
37062306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(248),
37162306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(249),
37262306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(250),
37362306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(251),
37462306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(252),
37562306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(253),
37662306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(254),
37762306a36Sopenharmony_ci	HNS3_RX_PTYPE_UNUSED_ENTRY(255),
37862306a36Sopenharmony_ci};
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci#define HNS3_INVALID_PTYPE \
38162306a36Sopenharmony_ci		ARRAY_SIZE(hns3_rx_ptype_tbl)
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_cistatic irqreturn_t hns3_irq_handle(int irq, void *vector)
38462306a36Sopenharmony_ci{
38562306a36Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector = vector;
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	napi_schedule_irqoff(&tqp_vector->napi);
38862306a36Sopenharmony_ci	tqp_vector->event_cnt++;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	return IRQ_HANDLED;
39162306a36Sopenharmony_ci}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_cistatic void hns3_nic_uninit_irq(struct hns3_nic_priv *priv)
39462306a36Sopenharmony_ci{
39562306a36Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vectors;
39662306a36Sopenharmony_ci	unsigned int i;
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
39962306a36Sopenharmony_ci		tqp_vectors = &priv->tqp_vector[i];
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci		if (tqp_vectors->irq_init_flag != HNS3_VECTOR_INITED)
40262306a36Sopenharmony_ci			continue;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci		/* clear the affinity mask */
40562306a36Sopenharmony_ci		irq_set_affinity_hint(tqp_vectors->vector_irq, NULL);
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci		/* release the irq resource */
40862306a36Sopenharmony_ci		free_irq(tqp_vectors->vector_irq, tqp_vectors);
40962306a36Sopenharmony_ci		tqp_vectors->irq_init_flag = HNS3_VECTOR_NOT_INITED;
41062306a36Sopenharmony_ci	}
41162306a36Sopenharmony_ci}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_cistatic int hns3_nic_init_irq(struct hns3_nic_priv *priv)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vectors;
41662306a36Sopenharmony_ci	int txrx_int_idx = 0;
41762306a36Sopenharmony_ci	int rx_int_idx = 0;
41862306a36Sopenharmony_ci	int tx_int_idx = 0;
41962306a36Sopenharmony_ci	unsigned int i;
42062306a36Sopenharmony_ci	int ret;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
42362306a36Sopenharmony_ci		tqp_vectors = &priv->tqp_vector[i];
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci		if (tqp_vectors->irq_init_flag == HNS3_VECTOR_INITED)
42662306a36Sopenharmony_ci			continue;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci		if (tqp_vectors->tx_group.ring && tqp_vectors->rx_group.ring) {
42962306a36Sopenharmony_ci			snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN,
43062306a36Sopenharmony_ci				 "%s-%s-%s-%d", hns3_driver_name,
43162306a36Sopenharmony_ci				 pci_name(priv->ae_handle->pdev),
43262306a36Sopenharmony_ci				 "TxRx", txrx_int_idx++);
43362306a36Sopenharmony_ci			txrx_int_idx++;
43462306a36Sopenharmony_ci		} else if (tqp_vectors->rx_group.ring) {
43562306a36Sopenharmony_ci			snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN,
43662306a36Sopenharmony_ci				 "%s-%s-%s-%d", hns3_driver_name,
43762306a36Sopenharmony_ci				 pci_name(priv->ae_handle->pdev),
43862306a36Sopenharmony_ci				 "Rx", rx_int_idx++);
43962306a36Sopenharmony_ci		} else if (tqp_vectors->tx_group.ring) {
44062306a36Sopenharmony_ci			snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN,
44162306a36Sopenharmony_ci				 "%s-%s-%s-%d", hns3_driver_name,
44262306a36Sopenharmony_ci				 pci_name(priv->ae_handle->pdev),
44362306a36Sopenharmony_ci				 "Tx", tx_int_idx++);
44462306a36Sopenharmony_ci		} else {
44562306a36Sopenharmony_ci			/* Skip this unused q_vector */
44662306a36Sopenharmony_ci			continue;
44762306a36Sopenharmony_ci		}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci		tqp_vectors->name[HNAE3_INT_NAME_LEN - 1] = '\0';
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci		irq_set_status_flags(tqp_vectors->vector_irq, IRQ_NOAUTOEN);
45262306a36Sopenharmony_ci		ret = request_irq(tqp_vectors->vector_irq, hns3_irq_handle, 0,
45362306a36Sopenharmony_ci				  tqp_vectors->name, tqp_vectors);
45462306a36Sopenharmony_ci		if (ret) {
45562306a36Sopenharmony_ci			netdev_err(priv->netdev, "request irq(%d) fail\n",
45662306a36Sopenharmony_ci				   tqp_vectors->vector_irq);
45762306a36Sopenharmony_ci			hns3_nic_uninit_irq(priv);
45862306a36Sopenharmony_ci			return ret;
45962306a36Sopenharmony_ci		}
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci		irq_set_affinity_hint(tqp_vectors->vector_irq,
46262306a36Sopenharmony_ci				      &tqp_vectors->affinity_mask);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci		tqp_vectors->irq_init_flag = HNS3_VECTOR_INITED;
46562306a36Sopenharmony_ci	}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	return 0;
46862306a36Sopenharmony_ci}
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_cistatic void hns3_mask_vector_irq(struct hns3_enet_tqp_vector *tqp_vector,
47162306a36Sopenharmony_ci				 u32 mask_en)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	writel(mask_en, tqp_vector->mask_addr);
47462306a36Sopenharmony_ci}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_cistatic void hns3_vector_enable(struct hns3_enet_tqp_vector *tqp_vector)
47762306a36Sopenharmony_ci{
47862306a36Sopenharmony_ci	napi_enable(&tqp_vector->napi);
47962306a36Sopenharmony_ci	enable_irq(tqp_vector->vector_irq);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	/* enable vector */
48262306a36Sopenharmony_ci	hns3_mask_vector_irq(tqp_vector, 1);
48362306a36Sopenharmony_ci}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistatic void hns3_vector_disable(struct hns3_enet_tqp_vector *tqp_vector)
48662306a36Sopenharmony_ci{
48762306a36Sopenharmony_ci	/* disable vector */
48862306a36Sopenharmony_ci	hns3_mask_vector_irq(tqp_vector, 0);
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	disable_irq(tqp_vector->vector_irq);
49162306a36Sopenharmony_ci	napi_disable(&tqp_vector->napi);
49262306a36Sopenharmony_ci	cancel_work_sync(&tqp_vector->rx_group.dim.work);
49362306a36Sopenharmony_ci	cancel_work_sync(&tqp_vector->tx_group.dim.work);
49462306a36Sopenharmony_ci}
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_civoid hns3_set_vector_coalesce_rl(struct hns3_enet_tqp_vector *tqp_vector,
49762306a36Sopenharmony_ci				 u32 rl_value)
49862306a36Sopenharmony_ci{
49962306a36Sopenharmony_ci	u32 rl_reg = hns3_rl_usec_to_reg(rl_value);
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	/* this defines the configuration for RL (Interrupt Rate Limiter).
50262306a36Sopenharmony_ci	 * Rl defines rate of interrupts i.e. number of interrupts-per-second
50362306a36Sopenharmony_ci	 * GL and RL(Rate Limiter) are 2 ways to acheive interrupt coalescing
50462306a36Sopenharmony_ci	 */
50562306a36Sopenharmony_ci	if (rl_reg > 0 && !tqp_vector->tx_group.coal.adapt_enable &&
50662306a36Sopenharmony_ci	    !tqp_vector->rx_group.coal.adapt_enable)
50762306a36Sopenharmony_ci		/* According to the hardware, the range of rl_reg is
50862306a36Sopenharmony_ci		 * 0-59 and the unit is 4.
50962306a36Sopenharmony_ci		 */
51062306a36Sopenharmony_ci		rl_reg |=  HNS3_INT_RL_ENABLE_MASK;
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	writel(rl_reg, tqp_vector->mask_addr + HNS3_VECTOR_RL_OFFSET);
51362306a36Sopenharmony_ci}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_civoid hns3_set_vector_coalesce_rx_gl(struct hns3_enet_tqp_vector *tqp_vector,
51662306a36Sopenharmony_ci				    u32 gl_value)
51762306a36Sopenharmony_ci{
51862306a36Sopenharmony_ci	u32 new_val;
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	if (tqp_vector->rx_group.coal.unit_1us)
52162306a36Sopenharmony_ci		new_val = gl_value | HNS3_INT_GL_1US;
52262306a36Sopenharmony_ci	else
52362306a36Sopenharmony_ci		new_val = hns3_gl_usec_to_reg(gl_value);
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	writel(new_val, tqp_vector->mask_addr + HNS3_VECTOR_GL0_OFFSET);
52662306a36Sopenharmony_ci}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_civoid hns3_set_vector_coalesce_tx_gl(struct hns3_enet_tqp_vector *tqp_vector,
52962306a36Sopenharmony_ci				    u32 gl_value)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	u32 new_val;
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	if (tqp_vector->tx_group.coal.unit_1us)
53462306a36Sopenharmony_ci		new_val = gl_value | HNS3_INT_GL_1US;
53562306a36Sopenharmony_ci	else
53662306a36Sopenharmony_ci		new_val = hns3_gl_usec_to_reg(gl_value);
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	writel(new_val, tqp_vector->mask_addr + HNS3_VECTOR_GL1_OFFSET);
53962306a36Sopenharmony_ci}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_civoid hns3_set_vector_coalesce_tx_ql(struct hns3_enet_tqp_vector *tqp_vector,
54262306a36Sopenharmony_ci				    u32 ql_value)
54362306a36Sopenharmony_ci{
54462306a36Sopenharmony_ci	writel(ql_value, tqp_vector->mask_addr + HNS3_VECTOR_TX_QL_OFFSET);
54562306a36Sopenharmony_ci}
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_civoid hns3_set_vector_coalesce_rx_ql(struct hns3_enet_tqp_vector *tqp_vector,
54862306a36Sopenharmony_ci				    u32 ql_value)
54962306a36Sopenharmony_ci{
55062306a36Sopenharmony_ci	writel(ql_value, tqp_vector->mask_addr + HNS3_VECTOR_RX_QL_OFFSET);
55162306a36Sopenharmony_ci}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_cistatic void hns3_vector_coalesce_init(struct hns3_enet_tqp_vector *tqp_vector,
55462306a36Sopenharmony_ci				      struct hns3_nic_priv *priv)
55562306a36Sopenharmony_ci{
55662306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(priv->ae_handle->pdev);
55762306a36Sopenharmony_ci	struct hns3_enet_coalesce *tx_coal = &tqp_vector->tx_group.coal;
55862306a36Sopenharmony_ci	struct hns3_enet_coalesce *rx_coal = &tqp_vector->rx_group.coal;
55962306a36Sopenharmony_ci	struct hns3_enet_coalesce *ptx_coal = &priv->tx_coal;
56062306a36Sopenharmony_ci	struct hns3_enet_coalesce *prx_coal = &priv->rx_coal;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	tx_coal->adapt_enable = ptx_coal->adapt_enable;
56362306a36Sopenharmony_ci	rx_coal->adapt_enable = prx_coal->adapt_enable;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	tx_coal->int_gl = ptx_coal->int_gl;
56662306a36Sopenharmony_ci	rx_coal->int_gl = prx_coal->int_gl;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	rx_coal->flow_level = prx_coal->flow_level;
56962306a36Sopenharmony_ci	tx_coal->flow_level = ptx_coal->flow_level;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	/* device version above V3(include V3), GL can configure 1us
57262306a36Sopenharmony_ci	 * unit, so uses 1us unit.
57362306a36Sopenharmony_ci	 */
57462306a36Sopenharmony_ci	if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3) {
57562306a36Sopenharmony_ci		tx_coal->unit_1us = 1;
57662306a36Sopenharmony_ci		rx_coal->unit_1us = 1;
57762306a36Sopenharmony_ci	}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	if (ae_dev->dev_specs.int_ql_max) {
58062306a36Sopenharmony_ci		tx_coal->ql_enable = 1;
58162306a36Sopenharmony_ci		rx_coal->ql_enable = 1;
58262306a36Sopenharmony_ci		tx_coal->int_ql_max = ae_dev->dev_specs.int_ql_max;
58362306a36Sopenharmony_ci		rx_coal->int_ql_max = ae_dev->dev_specs.int_ql_max;
58462306a36Sopenharmony_ci		tx_coal->int_ql = ptx_coal->int_ql;
58562306a36Sopenharmony_ci		rx_coal->int_ql = prx_coal->int_ql;
58662306a36Sopenharmony_ci	}
58762306a36Sopenharmony_ci}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_cistatic void
59062306a36Sopenharmony_cihns3_vector_coalesce_init_hw(struct hns3_enet_tqp_vector *tqp_vector,
59162306a36Sopenharmony_ci			     struct hns3_nic_priv *priv)
59262306a36Sopenharmony_ci{
59362306a36Sopenharmony_ci	struct hns3_enet_coalesce *tx_coal = &tqp_vector->tx_group.coal;
59462306a36Sopenharmony_ci	struct hns3_enet_coalesce *rx_coal = &tqp_vector->rx_group.coal;
59562306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	hns3_set_vector_coalesce_tx_gl(tqp_vector, tx_coal->int_gl);
59862306a36Sopenharmony_ci	hns3_set_vector_coalesce_rx_gl(tqp_vector, rx_coal->int_gl);
59962306a36Sopenharmony_ci	hns3_set_vector_coalesce_rl(tqp_vector, h->kinfo.int_rl_setting);
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	if (tx_coal->ql_enable)
60262306a36Sopenharmony_ci		hns3_set_vector_coalesce_tx_ql(tqp_vector, tx_coal->int_ql);
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	if (rx_coal->ql_enable)
60562306a36Sopenharmony_ci		hns3_set_vector_coalesce_rx_ql(tqp_vector, rx_coal->int_ql);
60662306a36Sopenharmony_ci}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_cistatic int hns3_nic_set_real_num_queue(struct net_device *netdev)
60962306a36Sopenharmony_ci{
61062306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
61162306a36Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &h->kinfo;
61262306a36Sopenharmony_ci	struct hnae3_tc_info *tc_info = &kinfo->tc_info;
61362306a36Sopenharmony_ci	unsigned int queue_size = kinfo->num_tqps;
61462306a36Sopenharmony_ci	int i, ret;
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	if (tc_info->num_tc <= 1 && !tc_info->mqprio_active) {
61762306a36Sopenharmony_ci		netdev_reset_tc(netdev);
61862306a36Sopenharmony_ci	} else {
61962306a36Sopenharmony_ci		ret = netdev_set_num_tc(netdev, tc_info->num_tc);
62062306a36Sopenharmony_ci		if (ret) {
62162306a36Sopenharmony_ci			netdev_err(netdev,
62262306a36Sopenharmony_ci				   "netdev_set_num_tc fail, ret=%d!\n", ret);
62362306a36Sopenharmony_ci			return ret;
62462306a36Sopenharmony_ci		}
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci		for (i = 0; i < tc_info->num_tc; i++)
62762306a36Sopenharmony_ci			netdev_set_tc_queue(netdev, i, tc_info->tqp_count[i],
62862306a36Sopenharmony_ci					    tc_info->tqp_offset[i]);
62962306a36Sopenharmony_ci	}
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci	ret = netif_set_real_num_tx_queues(netdev, queue_size);
63262306a36Sopenharmony_ci	if (ret) {
63362306a36Sopenharmony_ci		netdev_err(netdev,
63462306a36Sopenharmony_ci			   "netif_set_real_num_tx_queues fail, ret=%d!\n", ret);
63562306a36Sopenharmony_ci		return ret;
63662306a36Sopenharmony_ci	}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	ret = netif_set_real_num_rx_queues(netdev, queue_size);
63962306a36Sopenharmony_ci	if (ret) {
64062306a36Sopenharmony_ci		netdev_err(netdev,
64162306a36Sopenharmony_ci			   "netif_set_real_num_rx_queues fail, ret=%d!\n", ret);
64262306a36Sopenharmony_ci		return ret;
64362306a36Sopenharmony_ci	}
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	return 0;
64662306a36Sopenharmony_ci}
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ciu16 hns3_get_max_available_channels(struct hnae3_handle *h)
64962306a36Sopenharmony_ci{
65062306a36Sopenharmony_ci	u16 alloc_tqps, max_rss_size, rss_size;
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	h->ae_algo->ops->get_tqps_and_rss_info(h, &alloc_tqps, &max_rss_size);
65362306a36Sopenharmony_ci	rss_size = alloc_tqps / h->kinfo.tc_info.num_tc;
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	return min_t(u16, rss_size, max_rss_size);
65662306a36Sopenharmony_ci}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_cistatic void hns3_tqp_enable(struct hnae3_queue *tqp)
65962306a36Sopenharmony_ci{
66062306a36Sopenharmony_ci	u32 rcb_reg;
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	rcb_reg = hns3_read_dev(tqp, HNS3_RING_EN_REG);
66362306a36Sopenharmony_ci	rcb_reg |= BIT(HNS3_RING_EN_B);
66462306a36Sopenharmony_ci	hns3_write_dev(tqp, HNS3_RING_EN_REG, rcb_reg);
66562306a36Sopenharmony_ci}
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_cistatic void hns3_tqp_disable(struct hnae3_queue *tqp)
66862306a36Sopenharmony_ci{
66962306a36Sopenharmony_ci	u32 rcb_reg;
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	rcb_reg = hns3_read_dev(tqp, HNS3_RING_EN_REG);
67262306a36Sopenharmony_ci	rcb_reg &= ~BIT(HNS3_RING_EN_B);
67362306a36Sopenharmony_ci	hns3_write_dev(tqp, HNS3_RING_EN_REG, rcb_reg);
67462306a36Sopenharmony_ci}
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_cistatic void hns3_free_rx_cpu_rmap(struct net_device *netdev)
67762306a36Sopenharmony_ci{
67862306a36Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
67962306a36Sopenharmony_ci	free_irq_cpu_rmap(netdev->rx_cpu_rmap);
68062306a36Sopenharmony_ci	netdev->rx_cpu_rmap = NULL;
68162306a36Sopenharmony_ci#endif
68262306a36Sopenharmony_ci}
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_cistatic int hns3_set_rx_cpu_rmap(struct net_device *netdev)
68562306a36Sopenharmony_ci{
68662306a36Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
68762306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
68862306a36Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector;
68962306a36Sopenharmony_ci	int i, ret;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	if (!netdev->rx_cpu_rmap) {
69262306a36Sopenharmony_ci		netdev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->vector_num);
69362306a36Sopenharmony_ci		if (!netdev->rx_cpu_rmap)
69462306a36Sopenharmony_ci			return -ENOMEM;
69562306a36Sopenharmony_ci	}
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
69862306a36Sopenharmony_ci		tqp_vector = &priv->tqp_vector[i];
69962306a36Sopenharmony_ci		ret = irq_cpu_rmap_add(netdev->rx_cpu_rmap,
70062306a36Sopenharmony_ci				       tqp_vector->vector_irq);
70162306a36Sopenharmony_ci		if (ret) {
70262306a36Sopenharmony_ci			hns3_free_rx_cpu_rmap(netdev);
70362306a36Sopenharmony_ci			return ret;
70462306a36Sopenharmony_ci		}
70562306a36Sopenharmony_ci	}
70662306a36Sopenharmony_ci#endif
70762306a36Sopenharmony_ci	return 0;
70862306a36Sopenharmony_ci}
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_cistatic int hns3_nic_net_up(struct net_device *netdev)
71162306a36Sopenharmony_ci{
71262306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
71362306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
71462306a36Sopenharmony_ci	int i, j;
71562306a36Sopenharmony_ci	int ret;
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	ret = hns3_nic_reset_all_ring(h);
71862306a36Sopenharmony_ci	if (ret)
71962306a36Sopenharmony_ci		return ret;
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	clear_bit(HNS3_NIC_STATE_DOWN, &priv->state);
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ci	/* enable the vectors */
72462306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++)
72562306a36Sopenharmony_ci		hns3_vector_enable(&priv->tqp_vector[i]);
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	/* enable rcb */
72862306a36Sopenharmony_ci	for (j = 0; j < h->kinfo.num_tqps; j++)
72962306a36Sopenharmony_ci		hns3_tqp_enable(h->kinfo.tqp[j]);
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	/* start the ae_dev */
73262306a36Sopenharmony_ci	ret = h->ae_algo->ops->start ? h->ae_algo->ops->start(h) : 0;
73362306a36Sopenharmony_ci	if (ret) {
73462306a36Sopenharmony_ci		set_bit(HNS3_NIC_STATE_DOWN, &priv->state);
73562306a36Sopenharmony_ci		while (j--)
73662306a36Sopenharmony_ci			hns3_tqp_disable(h->kinfo.tqp[j]);
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci		for (j = i - 1; j >= 0; j--)
73962306a36Sopenharmony_ci			hns3_vector_disable(&priv->tqp_vector[j]);
74062306a36Sopenharmony_ci	}
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	return ret;
74362306a36Sopenharmony_ci}
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_cistatic void hns3_config_xps(struct hns3_nic_priv *priv)
74662306a36Sopenharmony_ci{
74762306a36Sopenharmony_ci	int i;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
75062306a36Sopenharmony_ci		struct hns3_enet_tqp_vector *tqp_vector = &priv->tqp_vector[i];
75162306a36Sopenharmony_ci		struct hns3_enet_ring *ring = tqp_vector->tx_group.ring;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci		while (ring) {
75462306a36Sopenharmony_ci			int ret;
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci			ret = netif_set_xps_queue(priv->netdev,
75762306a36Sopenharmony_ci						  &tqp_vector->affinity_mask,
75862306a36Sopenharmony_ci						  ring->tqp->tqp_index);
75962306a36Sopenharmony_ci			if (ret)
76062306a36Sopenharmony_ci				netdev_warn(priv->netdev,
76162306a36Sopenharmony_ci					    "set xps queue failed: %d", ret);
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci			ring = ring->next;
76462306a36Sopenharmony_ci		}
76562306a36Sopenharmony_ci	}
76662306a36Sopenharmony_ci}
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_cistatic int hns3_nic_net_open(struct net_device *netdev)
76962306a36Sopenharmony_ci{
77062306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
77162306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
77262306a36Sopenharmony_ci	struct hnae3_knic_private_info *kinfo;
77362306a36Sopenharmony_ci	int i, ret;
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	if (hns3_nic_resetting(netdev))
77662306a36Sopenharmony_ci		return -EBUSY;
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci	if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) {
77962306a36Sopenharmony_ci		netdev_warn(netdev, "net open repeatedly!\n");
78062306a36Sopenharmony_ci		return 0;
78162306a36Sopenharmony_ci	}
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	netif_carrier_off(netdev);
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	ret = hns3_nic_set_real_num_queue(netdev);
78662306a36Sopenharmony_ci	if (ret)
78762306a36Sopenharmony_ci		return ret;
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	ret = hns3_nic_net_up(netdev);
79062306a36Sopenharmony_ci	if (ret) {
79162306a36Sopenharmony_ci		netdev_err(netdev, "net up fail, ret=%d!\n", ret);
79262306a36Sopenharmony_ci		return ret;
79362306a36Sopenharmony_ci	}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	kinfo = &h->kinfo;
79662306a36Sopenharmony_ci	for (i = 0; i < HNAE3_MAX_USER_PRIO; i++)
79762306a36Sopenharmony_ci		netdev_set_prio_tc_map(netdev, i, kinfo->tc_info.prio_tc[i]);
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	if (h->ae_algo->ops->set_timer_task)
80062306a36Sopenharmony_ci		h->ae_algo->ops->set_timer_task(priv->ae_handle, true);
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	hns3_config_xps(priv);
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	netif_dbg(h, drv, netdev, "net open\n");
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	return 0;
80762306a36Sopenharmony_ci}
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_cistatic void hns3_reset_tx_queue(struct hnae3_handle *h)
81062306a36Sopenharmony_ci{
81162306a36Sopenharmony_ci	struct net_device *ndev = h->kinfo.netdev;
81262306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
81362306a36Sopenharmony_ci	struct netdev_queue *dev_queue;
81462306a36Sopenharmony_ci	u32 i;
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++) {
81762306a36Sopenharmony_ci		dev_queue = netdev_get_tx_queue(ndev,
81862306a36Sopenharmony_ci						priv->ring[i].queue_index);
81962306a36Sopenharmony_ci		netdev_tx_reset_queue(dev_queue);
82062306a36Sopenharmony_ci	}
82162306a36Sopenharmony_ci}
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_cistatic void hns3_nic_net_down(struct net_device *netdev)
82462306a36Sopenharmony_ci{
82562306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
82662306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
82762306a36Sopenharmony_ci	const struct hnae3_ae_ops *ops;
82862306a36Sopenharmony_ci	int i;
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	/* disable vectors */
83162306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++)
83262306a36Sopenharmony_ci		hns3_vector_disable(&priv->tqp_vector[i]);
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	/* disable rcb */
83562306a36Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++)
83662306a36Sopenharmony_ci		hns3_tqp_disable(h->kinfo.tqp[i]);
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	/* stop ae_dev */
83962306a36Sopenharmony_ci	ops = priv->ae_handle->ae_algo->ops;
84062306a36Sopenharmony_ci	if (ops->stop)
84162306a36Sopenharmony_ci		ops->stop(priv->ae_handle);
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	/* delay ring buffer clearing to hns3_reset_notify_uninit_enet
84462306a36Sopenharmony_ci	 * during reset process, because driver may not be able
84562306a36Sopenharmony_ci	 * to disable the ring through firmware when downing the netdev.
84662306a36Sopenharmony_ci	 */
84762306a36Sopenharmony_ci	if (!hns3_nic_resetting(netdev))
84862306a36Sopenharmony_ci		hns3_clear_all_ring(priv->ae_handle, false);
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	hns3_reset_tx_queue(priv->ae_handle);
85162306a36Sopenharmony_ci}
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_cistatic int hns3_nic_net_stop(struct net_device *netdev)
85462306a36Sopenharmony_ci{
85562306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
85662306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state))
85962306a36Sopenharmony_ci		return 0;
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci	netif_dbg(h, drv, netdev, "net stop\n");
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci	if (h->ae_algo->ops->set_timer_task)
86462306a36Sopenharmony_ci		h->ae_algo->ops->set_timer_task(priv->ae_handle, false);
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	netif_carrier_off(netdev);
86762306a36Sopenharmony_ci	netif_tx_disable(netdev);
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	hns3_nic_net_down(netdev);
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	return 0;
87262306a36Sopenharmony_ci}
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_cistatic int hns3_nic_uc_sync(struct net_device *netdev,
87562306a36Sopenharmony_ci			    const unsigned char *addr)
87662306a36Sopenharmony_ci{
87762306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	if (h->ae_algo->ops->add_uc_addr)
88062306a36Sopenharmony_ci		return h->ae_algo->ops->add_uc_addr(h, addr);
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	return 0;
88362306a36Sopenharmony_ci}
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_cistatic int hns3_nic_uc_unsync(struct net_device *netdev,
88662306a36Sopenharmony_ci			      const unsigned char *addr)
88762306a36Sopenharmony_ci{
88862306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	/* need ignore the request of removing device address, because
89162306a36Sopenharmony_ci	 * we store the device address and other addresses of uc list
89262306a36Sopenharmony_ci	 * in the function's mac filter list.
89362306a36Sopenharmony_ci	 */
89462306a36Sopenharmony_ci	if (ether_addr_equal(addr, netdev->dev_addr))
89562306a36Sopenharmony_ci		return 0;
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	if (h->ae_algo->ops->rm_uc_addr)
89862306a36Sopenharmony_ci		return h->ae_algo->ops->rm_uc_addr(h, addr);
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	return 0;
90162306a36Sopenharmony_ci}
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_cistatic int hns3_nic_mc_sync(struct net_device *netdev,
90462306a36Sopenharmony_ci			    const unsigned char *addr)
90562306a36Sopenharmony_ci{
90662306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	if (h->ae_algo->ops->add_mc_addr)
90962306a36Sopenharmony_ci		return h->ae_algo->ops->add_mc_addr(h, addr);
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	return 0;
91262306a36Sopenharmony_ci}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_cistatic int hns3_nic_mc_unsync(struct net_device *netdev,
91562306a36Sopenharmony_ci			      const unsigned char *addr)
91662306a36Sopenharmony_ci{
91762306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	if (h->ae_algo->ops->rm_mc_addr)
92062306a36Sopenharmony_ci		return h->ae_algo->ops->rm_mc_addr(h, addr);
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	return 0;
92362306a36Sopenharmony_ci}
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_cistatic u8 hns3_get_netdev_flags(struct net_device *netdev)
92662306a36Sopenharmony_ci{
92762306a36Sopenharmony_ci	u8 flags = 0;
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	if (netdev->flags & IFF_PROMISC)
93062306a36Sopenharmony_ci		flags = HNAE3_USER_UPE | HNAE3_USER_MPE | HNAE3_BPE;
93162306a36Sopenharmony_ci	else if (netdev->flags & IFF_ALLMULTI)
93262306a36Sopenharmony_ci		flags = HNAE3_USER_MPE;
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	return flags;
93562306a36Sopenharmony_ci}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_cistatic void hns3_nic_set_rx_mode(struct net_device *netdev)
93862306a36Sopenharmony_ci{
93962306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
94062306a36Sopenharmony_ci	u8 new_flags;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	new_flags = hns3_get_netdev_flags(netdev);
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	__dev_uc_sync(netdev, hns3_nic_uc_sync, hns3_nic_uc_unsync);
94562306a36Sopenharmony_ci	__dev_mc_sync(netdev, hns3_nic_mc_sync, hns3_nic_mc_unsync);
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	/* User mode Promisc mode enable and vlan filtering is disabled to
94862306a36Sopenharmony_ci	 * let all packets in.
94962306a36Sopenharmony_ci	 */
95062306a36Sopenharmony_ci	h->netdev_flags = new_flags;
95162306a36Sopenharmony_ci	hns3_request_update_promisc_mode(h);
95262306a36Sopenharmony_ci}
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_civoid hns3_request_update_promisc_mode(struct hnae3_handle *handle)
95562306a36Sopenharmony_ci{
95662306a36Sopenharmony_ci	const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	if (ops->request_update_promisc_mode)
95962306a36Sopenharmony_ci		ops->request_update_promisc_mode(handle);
96062306a36Sopenharmony_ci}
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_cistatic u32 hns3_tx_spare_space(struct hns3_enet_ring *ring)
96362306a36Sopenharmony_ci{
96462306a36Sopenharmony_ci	struct hns3_tx_spare *tx_spare = ring->tx_spare;
96562306a36Sopenharmony_ci	u32 ntc, ntu;
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci	/* This smp_load_acquire() pairs with smp_store_release() in
96862306a36Sopenharmony_ci	 * hns3_tx_spare_update() called in tx desc cleaning process.
96962306a36Sopenharmony_ci	 */
97062306a36Sopenharmony_ci	ntc = smp_load_acquire(&tx_spare->last_to_clean);
97162306a36Sopenharmony_ci	ntu = tx_spare->next_to_use;
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	if (ntc > ntu)
97462306a36Sopenharmony_ci		return ntc - ntu - 1;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	/* The free tx buffer is divided into two part, so pick the
97762306a36Sopenharmony_ci	 * larger one.
97862306a36Sopenharmony_ci	 */
97962306a36Sopenharmony_ci	return max(ntc, tx_spare->len - ntu) - 1;
98062306a36Sopenharmony_ci}
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_cistatic void hns3_tx_spare_update(struct hns3_enet_ring *ring)
98362306a36Sopenharmony_ci{
98462306a36Sopenharmony_ci	struct hns3_tx_spare *tx_spare = ring->tx_spare;
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	if (!tx_spare ||
98762306a36Sopenharmony_ci	    tx_spare->last_to_clean == tx_spare->next_to_clean)
98862306a36Sopenharmony_ci		return;
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	/* This smp_store_release() pairs with smp_load_acquire() in
99162306a36Sopenharmony_ci	 * hns3_tx_spare_space() called in xmit process.
99262306a36Sopenharmony_ci	 */
99362306a36Sopenharmony_ci	smp_store_release(&tx_spare->last_to_clean,
99462306a36Sopenharmony_ci			  tx_spare->next_to_clean);
99562306a36Sopenharmony_ci}
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_cistatic bool hns3_can_use_tx_bounce(struct hns3_enet_ring *ring,
99862306a36Sopenharmony_ci				   struct sk_buff *skb,
99962306a36Sopenharmony_ci				   u32 space)
100062306a36Sopenharmony_ci{
100162306a36Sopenharmony_ci	u32 len = skb->len <= ring->tx_copybreak ? skb->len :
100262306a36Sopenharmony_ci				skb_headlen(skb);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	if (len > ring->tx_copybreak)
100562306a36Sopenharmony_ci		return false;
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	if (ALIGN(len, dma_get_cache_alignment()) > space) {
100862306a36Sopenharmony_ci		hns3_ring_stats_update(ring, tx_spare_full);
100962306a36Sopenharmony_ci		return false;
101062306a36Sopenharmony_ci	}
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	return true;
101362306a36Sopenharmony_ci}
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_cistatic bool hns3_can_use_tx_sgl(struct hns3_enet_ring *ring,
101662306a36Sopenharmony_ci				struct sk_buff *skb,
101762306a36Sopenharmony_ci				u32 space)
101862306a36Sopenharmony_ci{
101962306a36Sopenharmony_ci	if (skb->len <= ring->tx_copybreak || !tx_sgl ||
102062306a36Sopenharmony_ci	    (!skb_has_frag_list(skb) &&
102162306a36Sopenharmony_ci	     skb_shinfo(skb)->nr_frags < tx_sgl))
102262306a36Sopenharmony_ci		return false;
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	if (space < HNS3_MAX_SGL_SIZE) {
102562306a36Sopenharmony_ci		hns3_ring_stats_update(ring, tx_spare_full);
102662306a36Sopenharmony_ci		return false;
102762306a36Sopenharmony_ci	}
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	return true;
103062306a36Sopenharmony_ci}
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_cistatic void hns3_init_tx_spare_buffer(struct hns3_enet_ring *ring)
103362306a36Sopenharmony_ci{
103462306a36Sopenharmony_ci	u32 alloc_size = ring->tqp->handle->kinfo.tx_spare_buf_size;
103562306a36Sopenharmony_ci	struct hns3_tx_spare *tx_spare;
103662306a36Sopenharmony_ci	struct page *page;
103762306a36Sopenharmony_ci	dma_addr_t dma;
103862306a36Sopenharmony_ci	int order;
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ci	if (!alloc_size)
104162306a36Sopenharmony_ci		return;
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	order = get_order(alloc_size);
104462306a36Sopenharmony_ci	if (order > MAX_ORDER) {
104562306a36Sopenharmony_ci		if (net_ratelimit())
104662306a36Sopenharmony_ci			dev_warn(ring_to_dev(ring), "failed to allocate tx spare buffer, exceed to max order\n");
104762306a36Sopenharmony_ci		return;
104862306a36Sopenharmony_ci	}
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	tx_spare = devm_kzalloc(ring_to_dev(ring), sizeof(*tx_spare),
105162306a36Sopenharmony_ci				GFP_KERNEL);
105262306a36Sopenharmony_ci	if (!tx_spare) {
105362306a36Sopenharmony_ci		/* The driver still work without the tx spare buffer */
105462306a36Sopenharmony_ci		dev_warn(ring_to_dev(ring), "failed to allocate hns3_tx_spare\n");
105562306a36Sopenharmony_ci		goto devm_kzalloc_error;
105662306a36Sopenharmony_ci	}
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci	page = alloc_pages_node(dev_to_node(ring_to_dev(ring)),
105962306a36Sopenharmony_ci				GFP_KERNEL, order);
106062306a36Sopenharmony_ci	if (!page) {
106162306a36Sopenharmony_ci		dev_warn(ring_to_dev(ring), "failed to allocate tx spare pages\n");
106262306a36Sopenharmony_ci		goto alloc_pages_error;
106362306a36Sopenharmony_ci	}
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	dma = dma_map_page(ring_to_dev(ring), page, 0,
106662306a36Sopenharmony_ci			   PAGE_SIZE << order, DMA_TO_DEVICE);
106762306a36Sopenharmony_ci	if (dma_mapping_error(ring_to_dev(ring), dma)) {
106862306a36Sopenharmony_ci		dev_warn(ring_to_dev(ring), "failed to map pages for tx spare\n");
106962306a36Sopenharmony_ci		goto dma_mapping_error;
107062306a36Sopenharmony_ci	}
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci	tx_spare->dma = dma;
107362306a36Sopenharmony_ci	tx_spare->buf = page_address(page);
107462306a36Sopenharmony_ci	tx_spare->len = PAGE_SIZE << order;
107562306a36Sopenharmony_ci	ring->tx_spare = tx_spare;
107662306a36Sopenharmony_ci	return;
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_cidma_mapping_error:
107962306a36Sopenharmony_ci	put_page(page);
108062306a36Sopenharmony_cialloc_pages_error:
108162306a36Sopenharmony_ci	devm_kfree(ring_to_dev(ring), tx_spare);
108262306a36Sopenharmony_cidevm_kzalloc_error:
108362306a36Sopenharmony_ci	ring->tqp->handle->kinfo.tx_spare_buf_size = 0;
108462306a36Sopenharmony_ci}
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci/* Use hns3_tx_spare_space() to make sure there is enough buffer
108762306a36Sopenharmony_ci * before calling below function to allocate tx buffer.
108862306a36Sopenharmony_ci */
108962306a36Sopenharmony_cistatic void *hns3_tx_spare_alloc(struct hns3_enet_ring *ring,
109062306a36Sopenharmony_ci				 unsigned int size, dma_addr_t *dma,
109162306a36Sopenharmony_ci				 u32 *cb_len)
109262306a36Sopenharmony_ci{
109362306a36Sopenharmony_ci	struct hns3_tx_spare *tx_spare = ring->tx_spare;
109462306a36Sopenharmony_ci	u32 ntu = tx_spare->next_to_use;
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	size = ALIGN(size, dma_get_cache_alignment());
109762306a36Sopenharmony_ci	*cb_len = size;
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci	/* Tx spare buffer wraps back here because the end of
110062306a36Sopenharmony_ci	 * freed tx buffer is not enough.
110162306a36Sopenharmony_ci	 */
110262306a36Sopenharmony_ci	if (ntu + size > tx_spare->len) {
110362306a36Sopenharmony_ci		*cb_len += (tx_spare->len - ntu);
110462306a36Sopenharmony_ci		ntu = 0;
110562306a36Sopenharmony_ci	}
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	tx_spare->next_to_use = ntu + size;
110862306a36Sopenharmony_ci	if (tx_spare->next_to_use == tx_spare->len)
110962306a36Sopenharmony_ci		tx_spare->next_to_use = 0;
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	*dma = tx_spare->dma + ntu;
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	return tx_spare->buf + ntu;
111462306a36Sopenharmony_ci}
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_cistatic void hns3_tx_spare_rollback(struct hns3_enet_ring *ring, u32 len)
111762306a36Sopenharmony_ci{
111862306a36Sopenharmony_ci	struct hns3_tx_spare *tx_spare = ring->tx_spare;
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	if (len > tx_spare->next_to_use) {
112162306a36Sopenharmony_ci		len -= tx_spare->next_to_use;
112262306a36Sopenharmony_ci		tx_spare->next_to_use = tx_spare->len - len;
112362306a36Sopenharmony_ci	} else {
112462306a36Sopenharmony_ci		tx_spare->next_to_use -= len;
112562306a36Sopenharmony_ci	}
112662306a36Sopenharmony_ci}
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_cistatic void hns3_tx_spare_reclaim_cb(struct hns3_enet_ring *ring,
112962306a36Sopenharmony_ci				     struct hns3_desc_cb *cb)
113062306a36Sopenharmony_ci{
113162306a36Sopenharmony_ci	struct hns3_tx_spare *tx_spare = ring->tx_spare;
113262306a36Sopenharmony_ci	u32 ntc = tx_spare->next_to_clean;
113362306a36Sopenharmony_ci	u32 len = cb->length;
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	tx_spare->next_to_clean += len;
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	if (tx_spare->next_to_clean >= tx_spare->len) {
113862306a36Sopenharmony_ci		tx_spare->next_to_clean -= tx_spare->len;
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci		if (tx_spare->next_to_clean) {
114162306a36Sopenharmony_ci			ntc = 0;
114262306a36Sopenharmony_ci			len = tx_spare->next_to_clean;
114362306a36Sopenharmony_ci		}
114462306a36Sopenharmony_ci	}
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	/* This tx spare buffer is only really reclaimed after calling
114762306a36Sopenharmony_ci	 * hns3_tx_spare_update(), so it is still safe to use the info in
114862306a36Sopenharmony_ci	 * the tx buffer to do the dma sync or sg unmapping after
114962306a36Sopenharmony_ci	 * tx_spare->next_to_clean is moved forword.
115062306a36Sopenharmony_ci	 */
115162306a36Sopenharmony_ci	if (cb->type & (DESC_TYPE_BOUNCE_HEAD | DESC_TYPE_BOUNCE_ALL)) {
115262306a36Sopenharmony_ci		dma_addr_t dma = tx_spare->dma + ntc;
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci		dma_sync_single_for_cpu(ring_to_dev(ring), dma, len,
115562306a36Sopenharmony_ci					DMA_TO_DEVICE);
115662306a36Sopenharmony_ci	} else {
115762306a36Sopenharmony_ci		struct sg_table *sgt = tx_spare->buf + ntc;
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci		dma_unmap_sg(ring_to_dev(ring), sgt->sgl, sgt->orig_nents,
116062306a36Sopenharmony_ci			     DMA_TO_DEVICE);
116162306a36Sopenharmony_ci	}
116262306a36Sopenharmony_ci}
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_cistatic int hns3_set_tso(struct sk_buff *skb, u32 *paylen_fdop_ol4cs,
116562306a36Sopenharmony_ci			u16 *mss, u32 *type_cs_vlan_tso, u32 *send_bytes)
116662306a36Sopenharmony_ci{
116762306a36Sopenharmony_ci	u32 l4_offset, hdr_len;
116862306a36Sopenharmony_ci	union l3_hdr_info l3;
116962306a36Sopenharmony_ci	union l4_hdr_info l4;
117062306a36Sopenharmony_ci	u32 l4_paylen;
117162306a36Sopenharmony_ci	int ret;
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	if (!skb_is_gso(skb))
117462306a36Sopenharmony_ci		return 0;
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci	ret = skb_cow_head(skb, 0);
117762306a36Sopenharmony_ci	if (unlikely(ret < 0))
117862306a36Sopenharmony_ci		return ret;
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci	l3.hdr = skb_network_header(skb);
118162306a36Sopenharmony_ci	l4.hdr = skb_transport_header(skb);
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	/* Software should clear the IPv4's checksum field when tso is
118462306a36Sopenharmony_ci	 * needed.
118562306a36Sopenharmony_ci	 */
118662306a36Sopenharmony_ci	if (l3.v4->version == 4)
118762306a36Sopenharmony_ci		l3.v4->check = 0;
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ci	/* tunnel packet */
119062306a36Sopenharmony_ci	if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
119162306a36Sopenharmony_ci					 SKB_GSO_GRE_CSUM |
119262306a36Sopenharmony_ci					 SKB_GSO_UDP_TUNNEL |
119362306a36Sopenharmony_ci					 SKB_GSO_UDP_TUNNEL_CSUM)) {
119462306a36Sopenharmony_ci		/* reset l3&l4 pointers from outer to inner headers */
119562306a36Sopenharmony_ci		l3.hdr = skb_inner_network_header(skb);
119662306a36Sopenharmony_ci		l4.hdr = skb_inner_transport_header(skb);
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci		/* Software should clear the IPv4's checksum field when
119962306a36Sopenharmony_ci		 * tso is needed.
120062306a36Sopenharmony_ci		 */
120162306a36Sopenharmony_ci		if (l3.v4->version == 4)
120262306a36Sopenharmony_ci			l3.v4->check = 0;
120362306a36Sopenharmony_ci	}
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	/* normal or tunnel packet */
120662306a36Sopenharmony_ci	l4_offset = l4.hdr - skb->data;
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	/* remove payload length from inner pseudo checksum when tso */
120962306a36Sopenharmony_ci	l4_paylen = skb->len - l4_offset;
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci	if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
121262306a36Sopenharmony_ci		hdr_len = sizeof(*l4.udp) + l4_offset;
121362306a36Sopenharmony_ci		csum_replace_by_diff(&l4.udp->check,
121462306a36Sopenharmony_ci				     (__force __wsum)htonl(l4_paylen));
121562306a36Sopenharmony_ci	} else {
121662306a36Sopenharmony_ci		hdr_len = (l4.tcp->doff << 2) + l4_offset;
121762306a36Sopenharmony_ci		csum_replace_by_diff(&l4.tcp->check,
121862306a36Sopenharmony_ci				     (__force __wsum)htonl(l4_paylen));
121962306a36Sopenharmony_ci	}
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	*send_bytes = (skb_shinfo(skb)->gso_segs - 1) * hdr_len + skb->len;
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci	/* find the txbd field values */
122462306a36Sopenharmony_ci	*paylen_fdop_ol4cs = skb->len - hdr_len;
122562306a36Sopenharmony_ci	hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_TSO_B, 1);
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	/* offload outer UDP header checksum */
122862306a36Sopenharmony_ci	if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)
122962306a36Sopenharmony_ci		hns3_set_field(*paylen_fdop_ol4cs, HNS3_TXD_OL4CS_B, 1);
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	/* get MSS for TSO */
123262306a36Sopenharmony_ci	*mss = skb_shinfo(skb)->gso_size;
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	trace_hns3_tso(skb);
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	return 0;
123762306a36Sopenharmony_ci}
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_cistatic int hns3_get_l4_protocol(struct sk_buff *skb, u8 *ol4_proto,
124062306a36Sopenharmony_ci				u8 *il4_proto)
124162306a36Sopenharmony_ci{
124262306a36Sopenharmony_ci	union l3_hdr_info l3;
124362306a36Sopenharmony_ci	unsigned char *l4_hdr;
124462306a36Sopenharmony_ci	unsigned char *exthdr;
124562306a36Sopenharmony_ci	u8 l4_proto_tmp;
124662306a36Sopenharmony_ci	__be16 frag_off;
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	/* find outer header point */
124962306a36Sopenharmony_ci	l3.hdr = skb_network_header(skb);
125062306a36Sopenharmony_ci	l4_hdr = skb_transport_header(skb);
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_ci	if (skb->protocol == htons(ETH_P_IPV6)) {
125362306a36Sopenharmony_ci		exthdr = l3.hdr + sizeof(*l3.v6);
125462306a36Sopenharmony_ci		l4_proto_tmp = l3.v6->nexthdr;
125562306a36Sopenharmony_ci		if (l4_hdr != exthdr)
125662306a36Sopenharmony_ci			ipv6_skip_exthdr(skb, exthdr - skb->data,
125762306a36Sopenharmony_ci					 &l4_proto_tmp, &frag_off);
125862306a36Sopenharmony_ci	} else if (skb->protocol == htons(ETH_P_IP)) {
125962306a36Sopenharmony_ci		l4_proto_tmp = l3.v4->protocol;
126062306a36Sopenharmony_ci	} else {
126162306a36Sopenharmony_ci		return -EINVAL;
126262306a36Sopenharmony_ci	}
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci	*ol4_proto = l4_proto_tmp;
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci	/* tunnel packet */
126762306a36Sopenharmony_ci	if (!skb->encapsulation) {
126862306a36Sopenharmony_ci		*il4_proto = 0;
126962306a36Sopenharmony_ci		return 0;
127062306a36Sopenharmony_ci	}
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci	/* find inner header point */
127362306a36Sopenharmony_ci	l3.hdr = skb_inner_network_header(skb);
127462306a36Sopenharmony_ci	l4_hdr = skb_inner_transport_header(skb);
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci	if (l3.v6->version == 6) {
127762306a36Sopenharmony_ci		exthdr = l3.hdr + sizeof(*l3.v6);
127862306a36Sopenharmony_ci		l4_proto_tmp = l3.v6->nexthdr;
127962306a36Sopenharmony_ci		if (l4_hdr != exthdr)
128062306a36Sopenharmony_ci			ipv6_skip_exthdr(skb, exthdr - skb->data,
128162306a36Sopenharmony_ci					 &l4_proto_tmp, &frag_off);
128262306a36Sopenharmony_ci	} else if (l3.v4->version == 4) {
128362306a36Sopenharmony_ci		l4_proto_tmp = l3.v4->protocol;
128462306a36Sopenharmony_ci	}
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci	*il4_proto = l4_proto_tmp;
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	return 0;
128962306a36Sopenharmony_ci}
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci/* when skb->encapsulation is 0, skb->ip_summed is CHECKSUM_PARTIAL
129262306a36Sopenharmony_ci * and it is udp packet, which has a dest port as the IANA assigned.
129362306a36Sopenharmony_ci * the hardware is expected to do the checksum offload, but the
129462306a36Sopenharmony_ci * hardware will not do the checksum offload when udp dest port is
129562306a36Sopenharmony_ci * 4789, 4790 or 6081.
129662306a36Sopenharmony_ci */
129762306a36Sopenharmony_cistatic bool hns3_tunnel_csum_bug(struct sk_buff *skb)
129862306a36Sopenharmony_ci{
129962306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(skb->dev);
130062306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(priv->ae_handle->pdev);
130162306a36Sopenharmony_ci	union l4_hdr_info l4;
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci	/* device version above V3(include V3), the hardware can
130462306a36Sopenharmony_ci	 * do this checksum offload.
130562306a36Sopenharmony_ci	 */
130662306a36Sopenharmony_ci	if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3)
130762306a36Sopenharmony_ci		return false;
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci	l4.hdr = skb_transport_header(skb);
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci	if (!(!skb->encapsulation &&
131262306a36Sopenharmony_ci	      (l4.udp->dest == htons(IANA_VXLAN_UDP_PORT) ||
131362306a36Sopenharmony_ci	      l4.udp->dest == htons(GENEVE_UDP_PORT) ||
131462306a36Sopenharmony_ci	      l4.udp->dest == htons(IANA_VXLAN_GPE_UDP_PORT))))
131562306a36Sopenharmony_ci		return false;
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	return true;
131862306a36Sopenharmony_ci}
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_cistatic void hns3_set_outer_l2l3l4(struct sk_buff *skb, u8 ol4_proto,
132162306a36Sopenharmony_ci				  u32 *ol_type_vlan_len_msec)
132262306a36Sopenharmony_ci{
132362306a36Sopenharmony_ci	u32 l2_len, l3_len, l4_len;
132462306a36Sopenharmony_ci	unsigned char *il2_hdr;
132562306a36Sopenharmony_ci	union l3_hdr_info l3;
132662306a36Sopenharmony_ci	union l4_hdr_info l4;
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	l3.hdr = skb_network_header(skb);
132962306a36Sopenharmony_ci	l4.hdr = skb_transport_header(skb);
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci	/* compute OL2 header size, defined in 2 Bytes */
133262306a36Sopenharmony_ci	l2_len = l3.hdr - skb->data;
133362306a36Sopenharmony_ci	hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_L2LEN_S, l2_len >> 1);
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci	/* compute OL3 header size, defined in 4 Bytes */
133662306a36Sopenharmony_ci	l3_len = l4.hdr - l3.hdr;
133762306a36Sopenharmony_ci	hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_L3LEN_S, l3_len >> 2);
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_ci	il2_hdr = skb_inner_mac_header(skb);
134062306a36Sopenharmony_ci	/* compute OL4 header size, defined in 4 Bytes */
134162306a36Sopenharmony_ci	l4_len = il2_hdr - l4.hdr;
134262306a36Sopenharmony_ci	hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_L4LEN_S, l4_len >> 2);
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci	/* define outer network header type */
134562306a36Sopenharmony_ci	if (skb->protocol == htons(ETH_P_IP)) {
134662306a36Sopenharmony_ci		if (skb_is_gso(skb))
134762306a36Sopenharmony_ci			hns3_set_field(*ol_type_vlan_len_msec,
134862306a36Sopenharmony_ci				       HNS3_TXD_OL3T_S,
134962306a36Sopenharmony_ci				       HNS3_OL3T_IPV4_CSUM);
135062306a36Sopenharmony_ci		else
135162306a36Sopenharmony_ci			hns3_set_field(*ol_type_vlan_len_msec,
135262306a36Sopenharmony_ci				       HNS3_TXD_OL3T_S,
135362306a36Sopenharmony_ci				       HNS3_OL3T_IPV4_NO_CSUM);
135462306a36Sopenharmony_ci	} else if (skb->protocol == htons(ETH_P_IPV6)) {
135562306a36Sopenharmony_ci		hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_OL3T_S,
135662306a36Sopenharmony_ci			       HNS3_OL3T_IPV6);
135762306a36Sopenharmony_ci	}
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	if (ol4_proto == IPPROTO_UDP)
136062306a36Sopenharmony_ci		hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_TUNTYPE_S,
136162306a36Sopenharmony_ci			       HNS3_TUN_MAC_IN_UDP);
136262306a36Sopenharmony_ci	else if (ol4_proto == IPPROTO_GRE)
136362306a36Sopenharmony_ci		hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_TUNTYPE_S,
136462306a36Sopenharmony_ci			       HNS3_TUN_NVGRE);
136562306a36Sopenharmony_ci}
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_cistatic void hns3_set_l3_type(struct sk_buff *skb, union l3_hdr_info l3,
136862306a36Sopenharmony_ci			     u32 *type_cs_vlan_tso)
136962306a36Sopenharmony_ci{
137062306a36Sopenharmony_ci	if (l3.v4->version == 4) {
137162306a36Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_S,
137262306a36Sopenharmony_ci			       HNS3_L3T_IPV4);
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci		/* the stack computes the IP header already, the only time we
137562306a36Sopenharmony_ci		 * need the hardware to recompute it is in the case of TSO.
137662306a36Sopenharmony_ci		 */
137762306a36Sopenharmony_ci		if (skb_is_gso(skb))
137862306a36Sopenharmony_ci			hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3CS_B, 1);
137962306a36Sopenharmony_ci	} else if (l3.v6->version == 6) {
138062306a36Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_S,
138162306a36Sopenharmony_ci			       HNS3_L3T_IPV6);
138262306a36Sopenharmony_ci	}
138362306a36Sopenharmony_ci}
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_cistatic int hns3_set_l4_csum_length(struct sk_buff *skb, union l4_hdr_info l4,
138662306a36Sopenharmony_ci				   u32 l4_proto, u32 *type_cs_vlan_tso)
138762306a36Sopenharmony_ci{
138862306a36Sopenharmony_ci	/* compute inner(/normal) L4 header size, defined in 4 Bytes */
138962306a36Sopenharmony_ci	switch (l4_proto) {
139062306a36Sopenharmony_ci	case IPPROTO_TCP:
139162306a36Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
139262306a36Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S,
139362306a36Sopenharmony_ci			       HNS3_L4T_TCP);
139462306a36Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_S,
139562306a36Sopenharmony_ci			       l4.tcp->doff);
139662306a36Sopenharmony_ci		break;
139762306a36Sopenharmony_ci	case IPPROTO_UDP:
139862306a36Sopenharmony_ci		if (hns3_tunnel_csum_bug(skb)) {
139962306a36Sopenharmony_ci			int ret = skb_put_padto(skb, HNS3_MIN_TUN_PKT_LEN);
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci			return ret ? ret : skb_checksum_help(skb);
140262306a36Sopenharmony_ci		}
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
140562306a36Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S,
140662306a36Sopenharmony_ci			       HNS3_L4T_UDP);
140762306a36Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_S,
140862306a36Sopenharmony_ci			       (sizeof(struct udphdr) >> 2));
140962306a36Sopenharmony_ci		break;
141062306a36Sopenharmony_ci	case IPPROTO_SCTP:
141162306a36Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
141262306a36Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S,
141362306a36Sopenharmony_ci			       HNS3_L4T_SCTP);
141462306a36Sopenharmony_ci		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_S,
141562306a36Sopenharmony_ci			       (sizeof(struct sctphdr) >> 2));
141662306a36Sopenharmony_ci		break;
141762306a36Sopenharmony_ci	default:
141862306a36Sopenharmony_ci		/* drop the skb tunnel packet if hardware don't support,
141962306a36Sopenharmony_ci		 * because hardware can't calculate csum when TSO.
142062306a36Sopenharmony_ci		 */
142162306a36Sopenharmony_ci		if (skb_is_gso(skb))
142262306a36Sopenharmony_ci			return -EDOM;
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci		/* the stack computes the IP header already,
142562306a36Sopenharmony_ci		 * driver calculate l4 checksum when not TSO.
142662306a36Sopenharmony_ci		 */
142762306a36Sopenharmony_ci		return skb_checksum_help(skb);
142862306a36Sopenharmony_ci	}
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_ci	return 0;
143162306a36Sopenharmony_ci}
143262306a36Sopenharmony_ci
143362306a36Sopenharmony_cistatic int hns3_set_l2l3l4(struct sk_buff *skb, u8 ol4_proto,
143462306a36Sopenharmony_ci			   u8 il4_proto, u32 *type_cs_vlan_tso,
143562306a36Sopenharmony_ci			   u32 *ol_type_vlan_len_msec)
143662306a36Sopenharmony_ci{
143762306a36Sopenharmony_ci	unsigned char *l2_hdr = skb->data;
143862306a36Sopenharmony_ci	u32 l4_proto = ol4_proto;
143962306a36Sopenharmony_ci	union l4_hdr_info l4;
144062306a36Sopenharmony_ci	union l3_hdr_info l3;
144162306a36Sopenharmony_ci	u32 l2_len, l3_len;
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci	l4.hdr = skb_transport_header(skb);
144462306a36Sopenharmony_ci	l3.hdr = skb_network_header(skb);
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	/* handle encapsulation skb */
144762306a36Sopenharmony_ci	if (skb->encapsulation) {
144862306a36Sopenharmony_ci		/* If this is a not UDP/GRE encapsulation skb */
144962306a36Sopenharmony_ci		if (!(ol4_proto == IPPROTO_UDP || ol4_proto == IPPROTO_GRE)) {
145062306a36Sopenharmony_ci			/* drop the skb tunnel packet if hardware don't support,
145162306a36Sopenharmony_ci			 * because hardware can't calculate csum when TSO.
145262306a36Sopenharmony_ci			 */
145362306a36Sopenharmony_ci			if (skb_is_gso(skb))
145462306a36Sopenharmony_ci				return -EDOM;
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci			/* the stack computes the IP header already,
145762306a36Sopenharmony_ci			 * driver calculate l4 checksum when not TSO.
145862306a36Sopenharmony_ci			 */
145962306a36Sopenharmony_ci			return skb_checksum_help(skb);
146062306a36Sopenharmony_ci		}
146162306a36Sopenharmony_ci
146262306a36Sopenharmony_ci		hns3_set_outer_l2l3l4(skb, ol4_proto, ol_type_vlan_len_msec);
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci		/* switch to inner header */
146562306a36Sopenharmony_ci		l2_hdr = skb_inner_mac_header(skb);
146662306a36Sopenharmony_ci		l3.hdr = skb_inner_network_header(skb);
146762306a36Sopenharmony_ci		l4.hdr = skb_inner_transport_header(skb);
146862306a36Sopenharmony_ci		l4_proto = il4_proto;
146962306a36Sopenharmony_ci	}
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci	hns3_set_l3_type(skb, l3, type_cs_vlan_tso);
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci	/* compute inner(/normal) L2 header size, defined in 2 Bytes */
147462306a36Sopenharmony_ci	l2_len = l3.hdr - l2_hdr;
147562306a36Sopenharmony_ci	hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L2LEN_S, l2_len >> 1);
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci	/* compute inner(/normal) L3 header size, defined in 4 Bytes */
147862306a36Sopenharmony_ci	l3_len = l4.hdr - l3.hdr;
147962306a36Sopenharmony_ci	hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3LEN_S, l3_len >> 2);
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	return hns3_set_l4_csum_length(skb, l4, l4_proto, type_cs_vlan_tso);
148262306a36Sopenharmony_ci}
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_cistatic int hns3_handle_vtags(struct hns3_enet_ring *tx_ring,
148562306a36Sopenharmony_ci			     struct sk_buff *skb)
148662306a36Sopenharmony_ci{
148762306a36Sopenharmony_ci	struct hnae3_handle *handle = tx_ring->tqp->handle;
148862306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev;
148962306a36Sopenharmony_ci	struct vlan_ethhdr *vhdr;
149062306a36Sopenharmony_ci	int rc;
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	if (!(skb->protocol == htons(ETH_P_8021Q) ||
149362306a36Sopenharmony_ci	      skb_vlan_tag_present(skb)))
149462306a36Sopenharmony_ci		return 0;
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	/* For HW limitation on HNAE3_DEVICE_VERSION_V2, if port based insert
149762306a36Sopenharmony_ci	 * VLAN enabled, only one VLAN header is allowed in skb, otherwise it
149862306a36Sopenharmony_ci	 * will cause RAS error.
149962306a36Sopenharmony_ci	 */
150062306a36Sopenharmony_ci	ae_dev = pci_get_drvdata(handle->pdev);
150162306a36Sopenharmony_ci	if (unlikely(skb_vlan_tagged_multi(skb) &&
150262306a36Sopenharmony_ci		     ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2 &&
150362306a36Sopenharmony_ci		     handle->port_base_vlan_state ==
150462306a36Sopenharmony_ci		     HNAE3_PORT_BASE_VLAN_ENABLE))
150562306a36Sopenharmony_ci		return -EINVAL;
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	if (skb->protocol == htons(ETH_P_8021Q) &&
150862306a36Sopenharmony_ci	    !(handle->kinfo.netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) {
150962306a36Sopenharmony_ci		/* When HW VLAN acceleration is turned off, and the stack
151062306a36Sopenharmony_ci		 * sets the protocol to 802.1q, the driver just need to
151162306a36Sopenharmony_ci		 * set the protocol to the encapsulated ethertype.
151262306a36Sopenharmony_ci		 */
151362306a36Sopenharmony_ci		skb->protocol = vlan_get_protocol(skb);
151462306a36Sopenharmony_ci		return 0;
151562306a36Sopenharmony_ci	}
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	if (skb_vlan_tag_present(skb)) {
151862306a36Sopenharmony_ci		/* Based on hw strategy, use out_vtag in two layer tag case,
151962306a36Sopenharmony_ci		 * and use inner_vtag in one tag case.
152062306a36Sopenharmony_ci		 */
152162306a36Sopenharmony_ci		if (skb->protocol == htons(ETH_P_8021Q) &&
152262306a36Sopenharmony_ci		    handle->port_base_vlan_state ==
152362306a36Sopenharmony_ci		    HNAE3_PORT_BASE_VLAN_DISABLE)
152462306a36Sopenharmony_ci			rc = HNS3_OUTER_VLAN_TAG;
152562306a36Sopenharmony_ci		else
152662306a36Sopenharmony_ci			rc = HNS3_INNER_VLAN_TAG;
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci		skb->protocol = vlan_get_protocol(skb);
152962306a36Sopenharmony_ci		return rc;
153062306a36Sopenharmony_ci	}
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_ci	rc = skb_cow_head(skb, 0);
153362306a36Sopenharmony_ci	if (unlikely(rc < 0))
153462306a36Sopenharmony_ci		return rc;
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_ci	vhdr = skb_vlan_eth_hdr(skb);
153762306a36Sopenharmony_ci	vhdr->h_vlan_TCI |= cpu_to_be16((skb->priority << VLAN_PRIO_SHIFT)
153862306a36Sopenharmony_ci					 & VLAN_PRIO_MASK);
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	skb->protocol = vlan_get_protocol(skb);
154162306a36Sopenharmony_ci	return 0;
154262306a36Sopenharmony_ci}
154362306a36Sopenharmony_ci
154462306a36Sopenharmony_ci/* check if the hardware is capable of checksum offloading */
154562306a36Sopenharmony_cistatic bool hns3_check_hw_tx_csum(struct sk_buff *skb)
154662306a36Sopenharmony_ci{
154762306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(skb->dev);
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci	/* Kindly note, due to backward compatibility of the TX descriptor,
155062306a36Sopenharmony_ci	 * HW checksum of the non-IP packets and GSO packets is handled at
155162306a36Sopenharmony_ci	 * different place in the following code
155262306a36Sopenharmony_ci	 */
155362306a36Sopenharmony_ci	if (skb_csum_is_sctp(skb) || skb_is_gso(skb) ||
155462306a36Sopenharmony_ci	    !test_bit(HNS3_NIC_STATE_HW_TX_CSUM_ENABLE, &priv->state))
155562306a36Sopenharmony_ci		return false;
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci	return true;
155862306a36Sopenharmony_ci}
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_cistruct hns3_desc_param {
156162306a36Sopenharmony_ci	u32 paylen_ol4cs;
156262306a36Sopenharmony_ci	u32 ol_type_vlan_len_msec;
156362306a36Sopenharmony_ci	u32 type_cs_vlan_tso;
156462306a36Sopenharmony_ci	u16 mss_hw_csum;
156562306a36Sopenharmony_ci	u16 inner_vtag;
156662306a36Sopenharmony_ci	u16 out_vtag;
156762306a36Sopenharmony_ci};
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_cistatic void hns3_init_desc_data(struct sk_buff *skb, struct hns3_desc_param *pa)
157062306a36Sopenharmony_ci{
157162306a36Sopenharmony_ci	pa->paylen_ol4cs = skb->len;
157262306a36Sopenharmony_ci	pa->ol_type_vlan_len_msec = 0;
157362306a36Sopenharmony_ci	pa->type_cs_vlan_tso = 0;
157462306a36Sopenharmony_ci	pa->mss_hw_csum = 0;
157562306a36Sopenharmony_ci	pa->inner_vtag = 0;
157662306a36Sopenharmony_ci	pa->out_vtag = 0;
157762306a36Sopenharmony_ci}
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_cistatic int hns3_handle_vlan_info(struct hns3_enet_ring *ring,
158062306a36Sopenharmony_ci				 struct sk_buff *skb,
158162306a36Sopenharmony_ci				 struct hns3_desc_param *param)
158262306a36Sopenharmony_ci{
158362306a36Sopenharmony_ci	int ret;
158462306a36Sopenharmony_ci
158562306a36Sopenharmony_ci	ret = hns3_handle_vtags(ring, skb);
158662306a36Sopenharmony_ci	if (unlikely(ret < 0)) {
158762306a36Sopenharmony_ci		hns3_ring_stats_update(ring, tx_vlan_err);
158862306a36Sopenharmony_ci		return ret;
158962306a36Sopenharmony_ci	} else if (ret == HNS3_INNER_VLAN_TAG) {
159062306a36Sopenharmony_ci		param->inner_vtag = skb_vlan_tag_get(skb);
159162306a36Sopenharmony_ci		param->inner_vtag |= (skb->priority << VLAN_PRIO_SHIFT) &
159262306a36Sopenharmony_ci				VLAN_PRIO_MASK;
159362306a36Sopenharmony_ci		hns3_set_field(param->type_cs_vlan_tso, HNS3_TXD_VLAN_B, 1);
159462306a36Sopenharmony_ci	} else if (ret == HNS3_OUTER_VLAN_TAG) {
159562306a36Sopenharmony_ci		param->out_vtag = skb_vlan_tag_get(skb);
159662306a36Sopenharmony_ci		param->out_vtag |= (skb->priority << VLAN_PRIO_SHIFT) &
159762306a36Sopenharmony_ci				VLAN_PRIO_MASK;
159862306a36Sopenharmony_ci		hns3_set_field(param->ol_type_vlan_len_msec, HNS3_TXD_OVLAN_B,
159962306a36Sopenharmony_ci			       1);
160062306a36Sopenharmony_ci	}
160162306a36Sopenharmony_ci	return 0;
160262306a36Sopenharmony_ci}
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_cistatic int hns3_handle_csum_partial(struct hns3_enet_ring *ring,
160562306a36Sopenharmony_ci				    struct sk_buff *skb,
160662306a36Sopenharmony_ci				    struct hns3_desc_cb *desc_cb,
160762306a36Sopenharmony_ci				    struct hns3_desc_param *param)
160862306a36Sopenharmony_ci{
160962306a36Sopenharmony_ci	u8 ol4_proto, il4_proto;
161062306a36Sopenharmony_ci	int ret;
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci	if (hns3_check_hw_tx_csum(skb)) {
161362306a36Sopenharmony_ci		/* set checksum start and offset, defined in 2 Bytes */
161462306a36Sopenharmony_ci		hns3_set_field(param->type_cs_vlan_tso, HNS3_TXD_CSUM_START_S,
161562306a36Sopenharmony_ci			       skb_checksum_start_offset(skb) >> 1);
161662306a36Sopenharmony_ci		hns3_set_field(param->ol_type_vlan_len_msec,
161762306a36Sopenharmony_ci			       HNS3_TXD_CSUM_OFFSET_S,
161862306a36Sopenharmony_ci			       skb->csum_offset >> 1);
161962306a36Sopenharmony_ci		param->mss_hw_csum |= BIT(HNS3_TXD_HW_CS_B);
162062306a36Sopenharmony_ci		return 0;
162162306a36Sopenharmony_ci	}
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci	skb_reset_mac_len(skb);
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci	ret = hns3_get_l4_protocol(skb, &ol4_proto, &il4_proto);
162662306a36Sopenharmony_ci	if (unlikely(ret < 0)) {
162762306a36Sopenharmony_ci		hns3_ring_stats_update(ring, tx_l4_proto_err);
162862306a36Sopenharmony_ci		return ret;
162962306a36Sopenharmony_ci	}
163062306a36Sopenharmony_ci
163162306a36Sopenharmony_ci	ret = hns3_set_l2l3l4(skb, ol4_proto, il4_proto,
163262306a36Sopenharmony_ci			      &param->type_cs_vlan_tso,
163362306a36Sopenharmony_ci			      &param->ol_type_vlan_len_msec);
163462306a36Sopenharmony_ci	if (unlikely(ret < 0)) {
163562306a36Sopenharmony_ci		hns3_ring_stats_update(ring, tx_l2l3l4_err);
163662306a36Sopenharmony_ci		return ret;
163762306a36Sopenharmony_ci	}
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_ci	ret = hns3_set_tso(skb, &param->paylen_ol4cs, &param->mss_hw_csum,
164062306a36Sopenharmony_ci			   &param->type_cs_vlan_tso, &desc_cb->send_bytes);
164162306a36Sopenharmony_ci	if (unlikely(ret < 0)) {
164262306a36Sopenharmony_ci		hns3_ring_stats_update(ring, tx_tso_err);
164362306a36Sopenharmony_ci		return ret;
164462306a36Sopenharmony_ci	}
164562306a36Sopenharmony_ci	return 0;
164662306a36Sopenharmony_ci}
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_cistatic int hns3_fill_skb_desc(struct hns3_enet_ring *ring,
164962306a36Sopenharmony_ci			      struct sk_buff *skb, struct hns3_desc *desc,
165062306a36Sopenharmony_ci			      struct hns3_desc_cb *desc_cb)
165162306a36Sopenharmony_ci{
165262306a36Sopenharmony_ci	struct hns3_desc_param param;
165362306a36Sopenharmony_ci	int ret;
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci	hns3_init_desc_data(skb, &param);
165662306a36Sopenharmony_ci	ret = hns3_handle_vlan_info(ring, skb, &param);
165762306a36Sopenharmony_ci	if (unlikely(ret < 0))
165862306a36Sopenharmony_ci		return ret;
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci	desc_cb->send_bytes = skb->len;
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci	if (skb->ip_summed == CHECKSUM_PARTIAL) {
166362306a36Sopenharmony_ci		ret = hns3_handle_csum_partial(ring, skb, desc_cb, &param);
166462306a36Sopenharmony_ci		if (ret)
166562306a36Sopenharmony_ci			return ret;
166662306a36Sopenharmony_ci	}
166762306a36Sopenharmony_ci
166862306a36Sopenharmony_ci	/* Set txbd */
166962306a36Sopenharmony_ci	desc->tx.ol_type_vlan_len_msec =
167062306a36Sopenharmony_ci		cpu_to_le32(param.ol_type_vlan_len_msec);
167162306a36Sopenharmony_ci	desc->tx.type_cs_vlan_tso_len = cpu_to_le32(param.type_cs_vlan_tso);
167262306a36Sopenharmony_ci	desc->tx.paylen_ol4cs = cpu_to_le32(param.paylen_ol4cs);
167362306a36Sopenharmony_ci	desc->tx.mss_hw_csum = cpu_to_le16(param.mss_hw_csum);
167462306a36Sopenharmony_ci	desc->tx.vlan_tag = cpu_to_le16(param.inner_vtag);
167562306a36Sopenharmony_ci	desc->tx.outer_vlan_tag = cpu_to_le16(param.out_vtag);
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci	return 0;
167862306a36Sopenharmony_ci}
167962306a36Sopenharmony_ci
168062306a36Sopenharmony_cistatic int hns3_fill_desc(struct hns3_enet_ring *ring, dma_addr_t dma,
168162306a36Sopenharmony_ci			  unsigned int size)
168262306a36Sopenharmony_ci{
168362306a36Sopenharmony_ci#define HNS3_LIKELY_BD_NUM	1
168462306a36Sopenharmony_ci
168562306a36Sopenharmony_ci	struct hns3_desc *desc = &ring->desc[ring->next_to_use];
168662306a36Sopenharmony_ci	unsigned int frag_buf_num;
168762306a36Sopenharmony_ci	int k, sizeoflast;
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci	if (likely(size <= HNS3_MAX_BD_SIZE)) {
169062306a36Sopenharmony_ci		desc->addr = cpu_to_le64(dma);
169162306a36Sopenharmony_ci		desc->tx.send_size = cpu_to_le16(size);
169262306a36Sopenharmony_ci		desc->tx.bdtp_fe_sc_vld_ra_ri =
169362306a36Sopenharmony_ci			cpu_to_le16(BIT(HNS3_TXD_VLD_B));
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_ci		trace_hns3_tx_desc(ring, ring->next_to_use);
169662306a36Sopenharmony_ci		ring_ptr_move_fw(ring, next_to_use);
169762306a36Sopenharmony_ci		return HNS3_LIKELY_BD_NUM;
169862306a36Sopenharmony_ci	}
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_ci	frag_buf_num = hns3_tx_bd_count(size);
170162306a36Sopenharmony_ci	sizeoflast = size % HNS3_MAX_BD_SIZE;
170262306a36Sopenharmony_ci	sizeoflast = sizeoflast ? sizeoflast : HNS3_MAX_BD_SIZE;
170362306a36Sopenharmony_ci
170462306a36Sopenharmony_ci	/* When frag size is bigger than hardware limit, split this frag */
170562306a36Sopenharmony_ci	for (k = 0; k < frag_buf_num; k++) {
170662306a36Sopenharmony_ci		/* now, fill the descriptor */
170762306a36Sopenharmony_ci		desc->addr = cpu_to_le64(dma + HNS3_MAX_BD_SIZE * k);
170862306a36Sopenharmony_ci		desc->tx.send_size = cpu_to_le16((k == frag_buf_num - 1) ?
170962306a36Sopenharmony_ci				     (u16)sizeoflast : (u16)HNS3_MAX_BD_SIZE);
171062306a36Sopenharmony_ci		desc->tx.bdtp_fe_sc_vld_ra_ri =
171162306a36Sopenharmony_ci				cpu_to_le16(BIT(HNS3_TXD_VLD_B));
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci		trace_hns3_tx_desc(ring, ring->next_to_use);
171462306a36Sopenharmony_ci		/* move ring pointer to next */
171562306a36Sopenharmony_ci		ring_ptr_move_fw(ring, next_to_use);
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_ci		desc = &ring->desc[ring->next_to_use];
171862306a36Sopenharmony_ci	}
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	return frag_buf_num;
172162306a36Sopenharmony_ci}
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_cistatic int hns3_map_and_fill_desc(struct hns3_enet_ring *ring, void *priv,
172462306a36Sopenharmony_ci				  unsigned int type)
172562306a36Sopenharmony_ci{
172662306a36Sopenharmony_ci	struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use];
172762306a36Sopenharmony_ci	struct device *dev = ring_to_dev(ring);
172862306a36Sopenharmony_ci	unsigned int size;
172962306a36Sopenharmony_ci	dma_addr_t dma;
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci	if (type & (DESC_TYPE_FRAGLIST_SKB | DESC_TYPE_SKB)) {
173262306a36Sopenharmony_ci		struct sk_buff *skb = (struct sk_buff *)priv;
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_ci		size = skb_headlen(skb);
173562306a36Sopenharmony_ci		if (!size)
173662306a36Sopenharmony_ci			return 0;
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_ci		dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE);
173962306a36Sopenharmony_ci	} else if (type & DESC_TYPE_BOUNCE_HEAD) {
174062306a36Sopenharmony_ci		/* Head data has been filled in hns3_handle_tx_bounce(),
174162306a36Sopenharmony_ci		 * just return 0 here.
174262306a36Sopenharmony_ci		 */
174362306a36Sopenharmony_ci		return 0;
174462306a36Sopenharmony_ci	} else {
174562306a36Sopenharmony_ci		skb_frag_t *frag = (skb_frag_t *)priv;
174662306a36Sopenharmony_ci
174762306a36Sopenharmony_ci		size = skb_frag_size(frag);
174862306a36Sopenharmony_ci		if (!size)
174962306a36Sopenharmony_ci			return 0;
175062306a36Sopenharmony_ci
175162306a36Sopenharmony_ci		dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE);
175262306a36Sopenharmony_ci	}
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci	if (unlikely(dma_mapping_error(dev, dma))) {
175562306a36Sopenharmony_ci		hns3_ring_stats_update(ring, sw_err_cnt);
175662306a36Sopenharmony_ci		return -ENOMEM;
175762306a36Sopenharmony_ci	}
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_ci	desc_cb->priv = priv;
176062306a36Sopenharmony_ci	desc_cb->length = size;
176162306a36Sopenharmony_ci	desc_cb->dma = dma;
176262306a36Sopenharmony_ci	desc_cb->type = type;
176362306a36Sopenharmony_ci
176462306a36Sopenharmony_ci	return hns3_fill_desc(ring, dma, size);
176562306a36Sopenharmony_ci}
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_cistatic unsigned int hns3_skb_bd_num(struct sk_buff *skb, unsigned int *bd_size,
176862306a36Sopenharmony_ci				    unsigned int bd_num)
176962306a36Sopenharmony_ci{
177062306a36Sopenharmony_ci	unsigned int size;
177162306a36Sopenharmony_ci	int i;
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci	size = skb_headlen(skb);
177462306a36Sopenharmony_ci	while (size > HNS3_MAX_BD_SIZE) {
177562306a36Sopenharmony_ci		bd_size[bd_num++] = HNS3_MAX_BD_SIZE;
177662306a36Sopenharmony_ci		size -= HNS3_MAX_BD_SIZE;
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci		if (bd_num > HNS3_MAX_TSO_BD_NUM)
177962306a36Sopenharmony_ci			return bd_num;
178062306a36Sopenharmony_ci	}
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_ci	if (size) {
178362306a36Sopenharmony_ci		bd_size[bd_num++] = size;
178462306a36Sopenharmony_ci		if (bd_num > HNS3_MAX_TSO_BD_NUM)
178562306a36Sopenharmony_ci			return bd_num;
178662306a36Sopenharmony_ci	}
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_ci	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
178962306a36Sopenharmony_ci		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
179062306a36Sopenharmony_ci		size = skb_frag_size(frag);
179162306a36Sopenharmony_ci		if (!size)
179262306a36Sopenharmony_ci			continue;
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_ci		while (size > HNS3_MAX_BD_SIZE) {
179562306a36Sopenharmony_ci			bd_size[bd_num++] = HNS3_MAX_BD_SIZE;
179662306a36Sopenharmony_ci			size -= HNS3_MAX_BD_SIZE;
179762306a36Sopenharmony_ci
179862306a36Sopenharmony_ci			if (bd_num > HNS3_MAX_TSO_BD_NUM)
179962306a36Sopenharmony_ci				return bd_num;
180062306a36Sopenharmony_ci		}
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci		bd_size[bd_num++] = size;
180362306a36Sopenharmony_ci		if (bd_num > HNS3_MAX_TSO_BD_NUM)
180462306a36Sopenharmony_ci			return bd_num;
180562306a36Sopenharmony_ci	}
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	return bd_num;
180862306a36Sopenharmony_ci}
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_cistatic unsigned int hns3_tx_bd_num(struct sk_buff *skb, unsigned int *bd_size,
181162306a36Sopenharmony_ci				   u8 max_non_tso_bd_num, unsigned int bd_num,
181262306a36Sopenharmony_ci				   unsigned int recursion_level)
181362306a36Sopenharmony_ci{
181462306a36Sopenharmony_ci#define HNS3_MAX_RECURSION_LEVEL	24
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci	struct sk_buff *frag_skb;
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_ci	/* If the total len is within the max bd limit */
181962306a36Sopenharmony_ci	if (likely(skb->len <= HNS3_MAX_BD_SIZE && !recursion_level &&
182062306a36Sopenharmony_ci		   !skb_has_frag_list(skb) &&
182162306a36Sopenharmony_ci		   skb_shinfo(skb)->nr_frags < max_non_tso_bd_num))
182262306a36Sopenharmony_ci		return skb_shinfo(skb)->nr_frags + 1U;
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_ci	if (unlikely(recursion_level >= HNS3_MAX_RECURSION_LEVEL))
182562306a36Sopenharmony_ci		return UINT_MAX;
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_ci	bd_num = hns3_skb_bd_num(skb, bd_size, bd_num);
182862306a36Sopenharmony_ci	if (!skb_has_frag_list(skb) || bd_num > HNS3_MAX_TSO_BD_NUM)
182962306a36Sopenharmony_ci		return bd_num;
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci	skb_walk_frags(skb, frag_skb) {
183262306a36Sopenharmony_ci		bd_num = hns3_tx_bd_num(frag_skb, bd_size, max_non_tso_bd_num,
183362306a36Sopenharmony_ci					bd_num, recursion_level + 1);
183462306a36Sopenharmony_ci		if (bd_num > HNS3_MAX_TSO_BD_NUM)
183562306a36Sopenharmony_ci			return bd_num;
183662306a36Sopenharmony_ci	}
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_ci	return bd_num;
183962306a36Sopenharmony_ci}
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_cistatic unsigned int hns3_gso_hdr_len(struct sk_buff *skb)
184262306a36Sopenharmony_ci{
184362306a36Sopenharmony_ci	if (!skb->encapsulation)
184462306a36Sopenharmony_ci		return skb_tcp_all_headers(skb);
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_ci	return skb_inner_tcp_all_headers(skb);
184762306a36Sopenharmony_ci}
184862306a36Sopenharmony_ci
184962306a36Sopenharmony_ci/* HW need every continuous max_non_tso_bd_num buffer data to be larger
185062306a36Sopenharmony_ci * than MSS, we simplify it by ensuring skb_headlen + the first continuous
185162306a36Sopenharmony_ci * max_non_tso_bd_num - 1 frags to be larger than gso header len + mss,
185262306a36Sopenharmony_ci * and the remaining continuous max_non_tso_bd_num - 1 frags to be larger
185362306a36Sopenharmony_ci * than MSS except the last max_non_tso_bd_num - 1 frags.
185462306a36Sopenharmony_ci */
185562306a36Sopenharmony_cistatic bool hns3_skb_need_linearized(struct sk_buff *skb, unsigned int *bd_size,
185662306a36Sopenharmony_ci				     unsigned int bd_num, u8 max_non_tso_bd_num)
185762306a36Sopenharmony_ci{
185862306a36Sopenharmony_ci	unsigned int tot_len = 0;
185962306a36Sopenharmony_ci	int i;
186062306a36Sopenharmony_ci
186162306a36Sopenharmony_ci	for (i = 0; i < max_non_tso_bd_num - 1U; i++)
186262306a36Sopenharmony_ci		tot_len += bd_size[i];
186362306a36Sopenharmony_ci
186462306a36Sopenharmony_ci	/* ensure the first max_non_tso_bd_num frags is greater than
186562306a36Sopenharmony_ci	 * mss + header
186662306a36Sopenharmony_ci	 */
186762306a36Sopenharmony_ci	if (tot_len + bd_size[max_non_tso_bd_num - 1U] <
186862306a36Sopenharmony_ci	    skb_shinfo(skb)->gso_size + hns3_gso_hdr_len(skb))
186962306a36Sopenharmony_ci		return true;
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci	/* ensure every continuous max_non_tso_bd_num - 1 buffer is greater
187262306a36Sopenharmony_ci	 * than mss except the last one.
187362306a36Sopenharmony_ci	 */
187462306a36Sopenharmony_ci	for (i = 0; i < bd_num - max_non_tso_bd_num; i++) {
187562306a36Sopenharmony_ci		tot_len -= bd_size[i];
187662306a36Sopenharmony_ci		tot_len += bd_size[i + max_non_tso_bd_num - 1U];
187762306a36Sopenharmony_ci
187862306a36Sopenharmony_ci		if (tot_len < skb_shinfo(skb)->gso_size)
187962306a36Sopenharmony_ci			return true;
188062306a36Sopenharmony_ci	}
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_ci	return false;
188362306a36Sopenharmony_ci}
188462306a36Sopenharmony_ci
188562306a36Sopenharmony_civoid hns3_shinfo_pack(struct skb_shared_info *shinfo, __u32 *size)
188662306a36Sopenharmony_ci{
188762306a36Sopenharmony_ci	int i;
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_ci	for (i = 0; i < MAX_SKB_FRAGS; i++)
189062306a36Sopenharmony_ci		size[i] = skb_frag_size(&shinfo->frags[i]);
189162306a36Sopenharmony_ci}
189262306a36Sopenharmony_ci
189362306a36Sopenharmony_cistatic int hns3_skb_linearize(struct hns3_enet_ring *ring,
189462306a36Sopenharmony_ci			      struct sk_buff *skb,
189562306a36Sopenharmony_ci			      unsigned int bd_num)
189662306a36Sopenharmony_ci{
189762306a36Sopenharmony_ci	/* 'bd_num == UINT_MAX' means the skb' fraglist has a
189862306a36Sopenharmony_ci	 * recursion level of over HNS3_MAX_RECURSION_LEVEL.
189962306a36Sopenharmony_ci	 */
190062306a36Sopenharmony_ci	if (bd_num == UINT_MAX) {
190162306a36Sopenharmony_ci		hns3_ring_stats_update(ring, over_max_recursion);
190262306a36Sopenharmony_ci		return -ENOMEM;
190362306a36Sopenharmony_ci	}
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_ci	/* The skb->len has exceeded the hw limitation, linearization
190662306a36Sopenharmony_ci	 * will not help.
190762306a36Sopenharmony_ci	 */
190862306a36Sopenharmony_ci	if (skb->len > HNS3_MAX_TSO_SIZE ||
190962306a36Sopenharmony_ci	    (!skb_is_gso(skb) && skb->len > HNS3_MAX_NON_TSO_SIZE)) {
191062306a36Sopenharmony_ci		hns3_ring_stats_update(ring, hw_limitation);
191162306a36Sopenharmony_ci		return -ENOMEM;
191262306a36Sopenharmony_ci	}
191362306a36Sopenharmony_ci
191462306a36Sopenharmony_ci	if (__skb_linearize(skb)) {
191562306a36Sopenharmony_ci		hns3_ring_stats_update(ring, sw_err_cnt);
191662306a36Sopenharmony_ci		return -ENOMEM;
191762306a36Sopenharmony_ci	}
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_ci	return 0;
192062306a36Sopenharmony_ci}
192162306a36Sopenharmony_ci
192262306a36Sopenharmony_cistatic int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring,
192362306a36Sopenharmony_ci				  struct net_device *netdev,
192462306a36Sopenharmony_ci				  struct sk_buff *skb)
192562306a36Sopenharmony_ci{
192662306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
192762306a36Sopenharmony_ci	u8 max_non_tso_bd_num = priv->max_non_tso_bd_num;
192862306a36Sopenharmony_ci	unsigned int bd_size[HNS3_MAX_TSO_BD_NUM + 1U];
192962306a36Sopenharmony_ci	unsigned int bd_num;
193062306a36Sopenharmony_ci
193162306a36Sopenharmony_ci	bd_num = hns3_tx_bd_num(skb, bd_size, max_non_tso_bd_num, 0, 0);
193262306a36Sopenharmony_ci	if (unlikely(bd_num > max_non_tso_bd_num)) {
193362306a36Sopenharmony_ci		if (bd_num <= HNS3_MAX_TSO_BD_NUM && skb_is_gso(skb) &&
193462306a36Sopenharmony_ci		    !hns3_skb_need_linearized(skb, bd_size, bd_num,
193562306a36Sopenharmony_ci					      max_non_tso_bd_num)) {
193662306a36Sopenharmony_ci			trace_hns3_over_max_bd(skb);
193762306a36Sopenharmony_ci			goto out;
193862306a36Sopenharmony_ci		}
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci		if (hns3_skb_linearize(ring, skb, bd_num))
194162306a36Sopenharmony_ci			return -ENOMEM;
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci		bd_num = hns3_tx_bd_count(skb->len);
194462306a36Sopenharmony_ci
194562306a36Sopenharmony_ci		hns3_ring_stats_update(ring, tx_copy);
194662306a36Sopenharmony_ci	}
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ciout:
194962306a36Sopenharmony_ci	if (likely(ring_space(ring) >= bd_num))
195062306a36Sopenharmony_ci		return bd_num;
195162306a36Sopenharmony_ci
195262306a36Sopenharmony_ci	netif_stop_subqueue(netdev, ring->queue_index);
195362306a36Sopenharmony_ci	smp_mb(); /* Memory barrier before checking ring_space */
195462306a36Sopenharmony_ci
195562306a36Sopenharmony_ci	/* Start queue in case hns3_clean_tx_ring has just made room
195662306a36Sopenharmony_ci	 * available and has not seen the queue stopped state performed
195762306a36Sopenharmony_ci	 * by netif_stop_subqueue above.
195862306a36Sopenharmony_ci	 */
195962306a36Sopenharmony_ci	if (ring_space(ring) >= bd_num && netif_carrier_ok(netdev) &&
196062306a36Sopenharmony_ci	    !test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) {
196162306a36Sopenharmony_ci		netif_start_subqueue(netdev, ring->queue_index);
196262306a36Sopenharmony_ci		return bd_num;
196362306a36Sopenharmony_ci	}
196462306a36Sopenharmony_ci
196562306a36Sopenharmony_ci	hns3_ring_stats_update(ring, tx_busy);
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_ci	return -EBUSY;
196862306a36Sopenharmony_ci}
196962306a36Sopenharmony_ci
197062306a36Sopenharmony_cistatic void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig)
197162306a36Sopenharmony_ci{
197262306a36Sopenharmony_ci	struct device *dev = ring_to_dev(ring);
197362306a36Sopenharmony_ci	unsigned int i;
197462306a36Sopenharmony_ci
197562306a36Sopenharmony_ci	for (i = 0; i < ring->desc_num; i++) {
197662306a36Sopenharmony_ci		struct hns3_desc *desc = &ring->desc[ring->next_to_use];
197762306a36Sopenharmony_ci		struct hns3_desc_cb *desc_cb;
197862306a36Sopenharmony_ci
197962306a36Sopenharmony_ci		memset(desc, 0, sizeof(*desc));
198062306a36Sopenharmony_ci
198162306a36Sopenharmony_ci		/* check if this is where we started */
198262306a36Sopenharmony_ci		if (ring->next_to_use == next_to_use_orig)
198362306a36Sopenharmony_ci			break;
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci		/* rollback one */
198662306a36Sopenharmony_ci		ring_ptr_move_bw(ring, next_to_use);
198762306a36Sopenharmony_ci
198862306a36Sopenharmony_ci		desc_cb = &ring->desc_cb[ring->next_to_use];
198962306a36Sopenharmony_ci
199062306a36Sopenharmony_ci		if (!desc_cb->dma)
199162306a36Sopenharmony_ci			continue;
199262306a36Sopenharmony_ci
199362306a36Sopenharmony_ci		/* unmap the descriptor dma address */
199462306a36Sopenharmony_ci		if (desc_cb->type & (DESC_TYPE_SKB | DESC_TYPE_FRAGLIST_SKB))
199562306a36Sopenharmony_ci			dma_unmap_single(dev, desc_cb->dma, desc_cb->length,
199662306a36Sopenharmony_ci					 DMA_TO_DEVICE);
199762306a36Sopenharmony_ci		else if (desc_cb->type &
199862306a36Sopenharmony_ci			 (DESC_TYPE_BOUNCE_HEAD | DESC_TYPE_BOUNCE_ALL))
199962306a36Sopenharmony_ci			hns3_tx_spare_rollback(ring, desc_cb->length);
200062306a36Sopenharmony_ci		else if (desc_cb->length)
200162306a36Sopenharmony_ci			dma_unmap_page(dev, desc_cb->dma, desc_cb->length,
200262306a36Sopenharmony_ci				       DMA_TO_DEVICE);
200362306a36Sopenharmony_ci
200462306a36Sopenharmony_ci		desc_cb->length = 0;
200562306a36Sopenharmony_ci		desc_cb->dma = 0;
200662306a36Sopenharmony_ci		desc_cb->type = DESC_TYPE_UNKNOWN;
200762306a36Sopenharmony_ci	}
200862306a36Sopenharmony_ci}
200962306a36Sopenharmony_ci
201062306a36Sopenharmony_cistatic int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring,
201162306a36Sopenharmony_ci				 struct sk_buff *skb, unsigned int type)
201262306a36Sopenharmony_ci{
201362306a36Sopenharmony_ci	struct sk_buff *frag_skb;
201462306a36Sopenharmony_ci	int i, ret, bd_num = 0;
201562306a36Sopenharmony_ci
201662306a36Sopenharmony_ci	ret = hns3_map_and_fill_desc(ring, skb, type);
201762306a36Sopenharmony_ci	if (unlikely(ret < 0))
201862306a36Sopenharmony_ci		return ret;
201962306a36Sopenharmony_ci
202062306a36Sopenharmony_ci	bd_num += ret;
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
202362306a36Sopenharmony_ci		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ci		ret = hns3_map_and_fill_desc(ring, frag, DESC_TYPE_PAGE);
202662306a36Sopenharmony_ci		if (unlikely(ret < 0))
202762306a36Sopenharmony_ci			return ret;
202862306a36Sopenharmony_ci
202962306a36Sopenharmony_ci		bd_num += ret;
203062306a36Sopenharmony_ci	}
203162306a36Sopenharmony_ci
203262306a36Sopenharmony_ci	skb_walk_frags(skb, frag_skb) {
203362306a36Sopenharmony_ci		ret = hns3_fill_skb_to_desc(ring, frag_skb,
203462306a36Sopenharmony_ci					    DESC_TYPE_FRAGLIST_SKB);
203562306a36Sopenharmony_ci		if (unlikely(ret < 0))
203662306a36Sopenharmony_ci			return ret;
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ci		bd_num += ret;
203962306a36Sopenharmony_ci	}
204062306a36Sopenharmony_ci
204162306a36Sopenharmony_ci	return bd_num;
204262306a36Sopenharmony_ci}
204362306a36Sopenharmony_ci
204462306a36Sopenharmony_cistatic void hns3_tx_push_bd(struct hns3_enet_ring *ring, int num)
204562306a36Sopenharmony_ci{
204662306a36Sopenharmony_ci#define HNS3_BYTES_PER_64BIT		8
204762306a36Sopenharmony_ci
204862306a36Sopenharmony_ci	struct hns3_desc desc[HNS3_MAX_PUSH_BD_NUM] = {};
204962306a36Sopenharmony_ci	int offset = 0;
205062306a36Sopenharmony_ci
205162306a36Sopenharmony_ci	/* make sure everything is visible to device before
205262306a36Sopenharmony_ci	 * excuting tx push or updating doorbell
205362306a36Sopenharmony_ci	 */
205462306a36Sopenharmony_ci	dma_wmb();
205562306a36Sopenharmony_ci
205662306a36Sopenharmony_ci	do {
205762306a36Sopenharmony_ci		int idx = (ring->next_to_use - num + ring->desc_num) %
205862306a36Sopenharmony_ci			  ring->desc_num;
205962306a36Sopenharmony_ci
206062306a36Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
206162306a36Sopenharmony_ci		ring->stats.tx_push++;
206262306a36Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
206362306a36Sopenharmony_ci		memcpy(&desc[offset], &ring->desc[idx],
206462306a36Sopenharmony_ci		       sizeof(struct hns3_desc));
206562306a36Sopenharmony_ci		offset++;
206662306a36Sopenharmony_ci	} while (--num);
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci	__iowrite64_copy(ring->tqp->mem_base, desc,
206962306a36Sopenharmony_ci			 (sizeof(struct hns3_desc) * HNS3_MAX_PUSH_BD_NUM) /
207062306a36Sopenharmony_ci			 HNS3_BYTES_PER_64BIT);
207162306a36Sopenharmony_ci
207262306a36Sopenharmony_ci	io_stop_wc();
207362306a36Sopenharmony_ci}
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_cistatic void hns3_tx_mem_doorbell(struct hns3_enet_ring *ring)
207662306a36Sopenharmony_ci{
207762306a36Sopenharmony_ci#define HNS3_MEM_DOORBELL_OFFSET	64
207862306a36Sopenharmony_ci
207962306a36Sopenharmony_ci	__le64 bd_num = cpu_to_le64((u64)ring->pending_buf);
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci	/* make sure everything is visible to device before
208262306a36Sopenharmony_ci	 * excuting tx push or updating doorbell
208362306a36Sopenharmony_ci	 */
208462306a36Sopenharmony_ci	dma_wmb();
208562306a36Sopenharmony_ci
208662306a36Sopenharmony_ci	__iowrite64_copy(ring->tqp->mem_base + HNS3_MEM_DOORBELL_OFFSET,
208762306a36Sopenharmony_ci			 &bd_num, 1);
208862306a36Sopenharmony_ci	u64_stats_update_begin(&ring->syncp);
208962306a36Sopenharmony_ci	ring->stats.tx_mem_doorbell += ring->pending_buf;
209062306a36Sopenharmony_ci	u64_stats_update_end(&ring->syncp);
209162306a36Sopenharmony_ci
209262306a36Sopenharmony_ci	io_stop_wc();
209362306a36Sopenharmony_ci}
209462306a36Sopenharmony_ci
209562306a36Sopenharmony_cistatic void hns3_tx_doorbell(struct hns3_enet_ring *ring, int num,
209662306a36Sopenharmony_ci			     bool doorbell)
209762306a36Sopenharmony_ci{
209862306a36Sopenharmony_ci	struct net_device *netdev = ring_to_netdev(ring);
209962306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
210062306a36Sopenharmony_ci
210162306a36Sopenharmony_ci	/* when tx push is enabled, the packet whose number of BD below
210262306a36Sopenharmony_ci	 * HNS3_MAX_PUSH_BD_NUM can be pushed directly.
210362306a36Sopenharmony_ci	 */
210462306a36Sopenharmony_ci	if (test_bit(HNS3_NIC_STATE_TX_PUSH_ENABLE, &priv->state) && num &&
210562306a36Sopenharmony_ci	    !ring->pending_buf && num <= HNS3_MAX_PUSH_BD_NUM && doorbell) {
210662306a36Sopenharmony_ci		/* This smp_store_release() pairs with smp_load_aquire() in
210762306a36Sopenharmony_ci		 * hns3_nic_reclaim_desc(). Ensure that the BD valid bit
210862306a36Sopenharmony_ci		 * is updated.
210962306a36Sopenharmony_ci		 */
211062306a36Sopenharmony_ci		smp_store_release(&ring->last_to_use, ring->next_to_use);
211162306a36Sopenharmony_ci		hns3_tx_push_bd(ring, num);
211262306a36Sopenharmony_ci		return;
211362306a36Sopenharmony_ci	}
211462306a36Sopenharmony_ci
211562306a36Sopenharmony_ci	ring->pending_buf += num;
211662306a36Sopenharmony_ci
211762306a36Sopenharmony_ci	if (!doorbell) {
211862306a36Sopenharmony_ci		hns3_ring_stats_update(ring, tx_more);
211962306a36Sopenharmony_ci		return;
212062306a36Sopenharmony_ci	}
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci	/* This smp_store_release() pairs with smp_load_aquire() in
212362306a36Sopenharmony_ci	 * hns3_nic_reclaim_desc(). Ensure that the BD valid bit is updated.
212462306a36Sopenharmony_ci	 */
212562306a36Sopenharmony_ci	smp_store_release(&ring->last_to_use, ring->next_to_use);
212662306a36Sopenharmony_ci
212762306a36Sopenharmony_ci	if (ring->tqp->mem_base)
212862306a36Sopenharmony_ci		hns3_tx_mem_doorbell(ring);
212962306a36Sopenharmony_ci	else
213062306a36Sopenharmony_ci		writel(ring->pending_buf,
213162306a36Sopenharmony_ci		       ring->tqp->io_base + HNS3_RING_TX_RING_TAIL_REG);
213262306a36Sopenharmony_ci
213362306a36Sopenharmony_ci	ring->pending_buf = 0;
213462306a36Sopenharmony_ci}
213562306a36Sopenharmony_ci
213662306a36Sopenharmony_cistatic void hns3_tsyn(struct net_device *netdev, struct sk_buff *skb,
213762306a36Sopenharmony_ci		      struct hns3_desc *desc)
213862306a36Sopenharmony_ci{
213962306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci	if (!(h->ae_algo->ops->set_tx_hwts_info &&
214262306a36Sopenharmony_ci	      h->ae_algo->ops->set_tx_hwts_info(h, skb)))
214362306a36Sopenharmony_ci		return;
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_ci	desc->tx.bdtp_fe_sc_vld_ra_ri |= cpu_to_le16(BIT(HNS3_TXD_TSYN_B));
214662306a36Sopenharmony_ci}
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_cistatic int hns3_handle_tx_bounce(struct hns3_enet_ring *ring,
214962306a36Sopenharmony_ci				 struct sk_buff *skb)
215062306a36Sopenharmony_ci{
215162306a36Sopenharmony_ci	struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use];
215262306a36Sopenharmony_ci	unsigned int type = DESC_TYPE_BOUNCE_HEAD;
215362306a36Sopenharmony_ci	unsigned int size = skb_headlen(skb);
215462306a36Sopenharmony_ci	dma_addr_t dma;
215562306a36Sopenharmony_ci	int bd_num = 0;
215662306a36Sopenharmony_ci	u32 cb_len;
215762306a36Sopenharmony_ci	void *buf;
215862306a36Sopenharmony_ci	int ret;
215962306a36Sopenharmony_ci
216062306a36Sopenharmony_ci	if (skb->len <= ring->tx_copybreak) {
216162306a36Sopenharmony_ci		size = skb->len;
216262306a36Sopenharmony_ci		type = DESC_TYPE_BOUNCE_ALL;
216362306a36Sopenharmony_ci	}
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ci	/* hns3_can_use_tx_bounce() is called to ensure the below
216662306a36Sopenharmony_ci	 * function can always return the tx buffer.
216762306a36Sopenharmony_ci	 */
216862306a36Sopenharmony_ci	buf = hns3_tx_spare_alloc(ring, size, &dma, &cb_len);
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_ci	ret = skb_copy_bits(skb, 0, buf, size);
217162306a36Sopenharmony_ci	if (unlikely(ret < 0)) {
217262306a36Sopenharmony_ci		hns3_tx_spare_rollback(ring, cb_len);
217362306a36Sopenharmony_ci		hns3_ring_stats_update(ring, copy_bits_err);
217462306a36Sopenharmony_ci		return ret;
217562306a36Sopenharmony_ci	}
217662306a36Sopenharmony_ci
217762306a36Sopenharmony_ci	desc_cb->priv = skb;
217862306a36Sopenharmony_ci	desc_cb->length = cb_len;
217962306a36Sopenharmony_ci	desc_cb->dma = dma;
218062306a36Sopenharmony_ci	desc_cb->type = type;
218162306a36Sopenharmony_ci
218262306a36Sopenharmony_ci	bd_num += hns3_fill_desc(ring, dma, size);
218362306a36Sopenharmony_ci
218462306a36Sopenharmony_ci	if (type == DESC_TYPE_BOUNCE_HEAD) {
218562306a36Sopenharmony_ci		ret = hns3_fill_skb_to_desc(ring, skb,
218662306a36Sopenharmony_ci					    DESC_TYPE_BOUNCE_HEAD);
218762306a36Sopenharmony_ci		if (unlikely(ret < 0))
218862306a36Sopenharmony_ci			return ret;
218962306a36Sopenharmony_ci
219062306a36Sopenharmony_ci		bd_num += ret;
219162306a36Sopenharmony_ci	}
219262306a36Sopenharmony_ci
219362306a36Sopenharmony_ci	dma_sync_single_for_device(ring_to_dev(ring), dma, size,
219462306a36Sopenharmony_ci				   DMA_TO_DEVICE);
219562306a36Sopenharmony_ci
219662306a36Sopenharmony_ci	hns3_ring_stats_update(ring, tx_bounce);
219762306a36Sopenharmony_ci
219862306a36Sopenharmony_ci	return bd_num;
219962306a36Sopenharmony_ci}
220062306a36Sopenharmony_ci
220162306a36Sopenharmony_cistatic int hns3_handle_tx_sgl(struct hns3_enet_ring *ring,
220262306a36Sopenharmony_ci			      struct sk_buff *skb)
220362306a36Sopenharmony_ci{
220462306a36Sopenharmony_ci	struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use];
220562306a36Sopenharmony_ci	u32 nfrag = skb_shinfo(skb)->nr_frags + 1;
220662306a36Sopenharmony_ci	struct sg_table *sgt;
220762306a36Sopenharmony_ci	int i, bd_num = 0;
220862306a36Sopenharmony_ci	dma_addr_t dma;
220962306a36Sopenharmony_ci	u32 cb_len;
221062306a36Sopenharmony_ci	int nents;
221162306a36Sopenharmony_ci
221262306a36Sopenharmony_ci	if (skb_has_frag_list(skb))
221362306a36Sopenharmony_ci		nfrag = HNS3_MAX_TSO_BD_NUM;
221462306a36Sopenharmony_ci
221562306a36Sopenharmony_ci	/* hns3_can_use_tx_sgl() is called to ensure the below
221662306a36Sopenharmony_ci	 * function can always return the tx buffer.
221762306a36Sopenharmony_ci	 */
221862306a36Sopenharmony_ci	sgt = hns3_tx_spare_alloc(ring, HNS3_SGL_SIZE(nfrag),
221962306a36Sopenharmony_ci				  &dma, &cb_len);
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci	/* scatterlist follows by the sg table */
222262306a36Sopenharmony_ci	sgt->sgl = (struct scatterlist *)(sgt + 1);
222362306a36Sopenharmony_ci	sg_init_table(sgt->sgl, nfrag);
222462306a36Sopenharmony_ci	nents = skb_to_sgvec(skb, sgt->sgl, 0, skb->len);
222562306a36Sopenharmony_ci	if (unlikely(nents < 0)) {
222662306a36Sopenharmony_ci		hns3_tx_spare_rollback(ring, cb_len);
222762306a36Sopenharmony_ci		hns3_ring_stats_update(ring, skb2sgl_err);
222862306a36Sopenharmony_ci		return -ENOMEM;
222962306a36Sopenharmony_ci	}
223062306a36Sopenharmony_ci
223162306a36Sopenharmony_ci	sgt->orig_nents = nents;
223262306a36Sopenharmony_ci	sgt->nents = dma_map_sg(ring_to_dev(ring), sgt->sgl, sgt->orig_nents,
223362306a36Sopenharmony_ci				DMA_TO_DEVICE);
223462306a36Sopenharmony_ci	if (unlikely(!sgt->nents)) {
223562306a36Sopenharmony_ci		hns3_tx_spare_rollback(ring, cb_len);
223662306a36Sopenharmony_ci		hns3_ring_stats_update(ring, map_sg_err);
223762306a36Sopenharmony_ci		return -ENOMEM;
223862306a36Sopenharmony_ci	}
223962306a36Sopenharmony_ci
224062306a36Sopenharmony_ci	desc_cb->priv = skb;
224162306a36Sopenharmony_ci	desc_cb->length = cb_len;
224262306a36Sopenharmony_ci	desc_cb->dma = dma;
224362306a36Sopenharmony_ci	desc_cb->type = DESC_TYPE_SGL_SKB;
224462306a36Sopenharmony_ci
224562306a36Sopenharmony_ci	for (i = 0; i < sgt->nents; i++)
224662306a36Sopenharmony_ci		bd_num += hns3_fill_desc(ring, sg_dma_address(sgt->sgl + i),
224762306a36Sopenharmony_ci					 sg_dma_len(sgt->sgl + i));
224862306a36Sopenharmony_ci	hns3_ring_stats_update(ring, tx_sgl);
224962306a36Sopenharmony_ci
225062306a36Sopenharmony_ci	return bd_num;
225162306a36Sopenharmony_ci}
225262306a36Sopenharmony_ci
225362306a36Sopenharmony_cistatic int hns3_handle_desc_filling(struct hns3_enet_ring *ring,
225462306a36Sopenharmony_ci				    struct sk_buff *skb)
225562306a36Sopenharmony_ci{
225662306a36Sopenharmony_ci	u32 space;
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_ci	if (!ring->tx_spare)
225962306a36Sopenharmony_ci		goto out;
226062306a36Sopenharmony_ci
226162306a36Sopenharmony_ci	space = hns3_tx_spare_space(ring);
226262306a36Sopenharmony_ci
226362306a36Sopenharmony_ci	if (hns3_can_use_tx_sgl(ring, skb, space))
226462306a36Sopenharmony_ci		return hns3_handle_tx_sgl(ring, skb);
226562306a36Sopenharmony_ci
226662306a36Sopenharmony_ci	if (hns3_can_use_tx_bounce(ring, skb, space))
226762306a36Sopenharmony_ci		return hns3_handle_tx_bounce(ring, skb);
226862306a36Sopenharmony_ci
226962306a36Sopenharmony_ciout:
227062306a36Sopenharmony_ci	return hns3_fill_skb_to_desc(ring, skb, DESC_TYPE_SKB);
227162306a36Sopenharmony_ci}
227262306a36Sopenharmony_ci
227362306a36Sopenharmony_cistatic int hns3_handle_skb_desc(struct hns3_enet_ring *ring,
227462306a36Sopenharmony_ci				struct sk_buff *skb,
227562306a36Sopenharmony_ci				struct hns3_desc_cb *desc_cb,
227662306a36Sopenharmony_ci				int next_to_use_head)
227762306a36Sopenharmony_ci{
227862306a36Sopenharmony_ci	int ret;
227962306a36Sopenharmony_ci
228062306a36Sopenharmony_ci	ret = hns3_fill_skb_desc(ring, skb, &ring->desc[ring->next_to_use],
228162306a36Sopenharmony_ci				 desc_cb);
228262306a36Sopenharmony_ci	if (unlikely(ret < 0))
228362306a36Sopenharmony_ci		goto fill_err;
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci	/* 'ret < 0' means filling error, 'ret == 0' means skb->len is
228662306a36Sopenharmony_ci	 * zero, which is unlikely, and 'ret > 0' means how many tx desc
228762306a36Sopenharmony_ci	 * need to be notified to the hw.
228862306a36Sopenharmony_ci	 */
228962306a36Sopenharmony_ci	ret = hns3_handle_desc_filling(ring, skb);
229062306a36Sopenharmony_ci	if (likely(ret > 0))
229162306a36Sopenharmony_ci		return ret;
229262306a36Sopenharmony_ci
229362306a36Sopenharmony_cifill_err:
229462306a36Sopenharmony_ci	hns3_clear_desc(ring, next_to_use_head);
229562306a36Sopenharmony_ci	return ret;
229662306a36Sopenharmony_ci}
229762306a36Sopenharmony_ci
229862306a36Sopenharmony_cinetdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
229962306a36Sopenharmony_ci{
230062306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
230162306a36Sopenharmony_ci	struct hns3_enet_ring *ring = &priv->ring[skb->queue_mapping];
230262306a36Sopenharmony_ci	struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use];
230362306a36Sopenharmony_ci	struct netdev_queue *dev_queue;
230462306a36Sopenharmony_ci	int pre_ntu, ret;
230562306a36Sopenharmony_ci	bool doorbell;
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci	/* Hardware can only handle short frames above 32 bytes */
230862306a36Sopenharmony_ci	if (skb_put_padto(skb, HNS3_MIN_TX_LEN)) {
230962306a36Sopenharmony_ci		hns3_tx_doorbell(ring, 0, !netdev_xmit_more());
231062306a36Sopenharmony_ci
231162306a36Sopenharmony_ci		hns3_ring_stats_update(ring, sw_err_cnt);
231262306a36Sopenharmony_ci
231362306a36Sopenharmony_ci		return NETDEV_TX_OK;
231462306a36Sopenharmony_ci	}
231562306a36Sopenharmony_ci
231662306a36Sopenharmony_ci	/* Prefetch the data used later */
231762306a36Sopenharmony_ci	prefetch(skb->data);
231862306a36Sopenharmony_ci
231962306a36Sopenharmony_ci	ret = hns3_nic_maybe_stop_tx(ring, netdev, skb);
232062306a36Sopenharmony_ci	if (unlikely(ret <= 0)) {
232162306a36Sopenharmony_ci		if (ret == -EBUSY) {
232262306a36Sopenharmony_ci			hns3_tx_doorbell(ring, 0, true);
232362306a36Sopenharmony_ci			return NETDEV_TX_BUSY;
232462306a36Sopenharmony_ci		}
232562306a36Sopenharmony_ci
232662306a36Sopenharmony_ci		hns3_rl_err(netdev, "xmit error: %d!\n", ret);
232762306a36Sopenharmony_ci		goto out_err_tx_ok;
232862306a36Sopenharmony_ci	}
232962306a36Sopenharmony_ci
233062306a36Sopenharmony_ci	ret = hns3_handle_skb_desc(ring, skb, desc_cb, ring->next_to_use);
233162306a36Sopenharmony_ci	if (unlikely(ret <= 0))
233262306a36Sopenharmony_ci		goto out_err_tx_ok;
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci	pre_ntu = ring->next_to_use ? (ring->next_to_use - 1) :
233562306a36Sopenharmony_ci					(ring->desc_num - 1);
233662306a36Sopenharmony_ci
233762306a36Sopenharmony_ci	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
233862306a36Sopenharmony_ci		hns3_tsyn(netdev, skb, &ring->desc[pre_ntu]);
233962306a36Sopenharmony_ci
234062306a36Sopenharmony_ci	ring->desc[pre_ntu].tx.bdtp_fe_sc_vld_ra_ri |=
234162306a36Sopenharmony_ci				cpu_to_le16(BIT(HNS3_TXD_FE_B));
234262306a36Sopenharmony_ci	trace_hns3_tx_desc(ring, pre_ntu);
234362306a36Sopenharmony_ci
234462306a36Sopenharmony_ci	skb_tx_timestamp(skb);
234562306a36Sopenharmony_ci
234662306a36Sopenharmony_ci	/* Complete translate all packets */
234762306a36Sopenharmony_ci	dev_queue = netdev_get_tx_queue(netdev, ring->queue_index);
234862306a36Sopenharmony_ci	doorbell = __netdev_tx_sent_queue(dev_queue, desc_cb->send_bytes,
234962306a36Sopenharmony_ci					  netdev_xmit_more());
235062306a36Sopenharmony_ci	hns3_tx_doorbell(ring, ret, doorbell);
235162306a36Sopenharmony_ci
235262306a36Sopenharmony_ci	return NETDEV_TX_OK;
235362306a36Sopenharmony_ci
235462306a36Sopenharmony_ciout_err_tx_ok:
235562306a36Sopenharmony_ci	dev_kfree_skb_any(skb);
235662306a36Sopenharmony_ci	hns3_tx_doorbell(ring, 0, !netdev_xmit_more());
235762306a36Sopenharmony_ci	return NETDEV_TX_OK;
235862306a36Sopenharmony_ci}
235962306a36Sopenharmony_ci
236062306a36Sopenharmony_cistatic int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p)
236162306a36Sopenharmony_ci{
236262306a36Sopenharmony_ci	char format_mac_addr_perm[HNAE3_FORMAT_MAC_ADDR_LEN];
236362306a36Sopenharmony_ci	char format_mac_addr_sa[HNAE3_FORMAT_MAC_ADDR_LEN];
236462306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
236562306a36Sopenharmony_ci	struct sockaddr *mac_addr = p;
236662306a36Sopenharmony_ci	int ret;
236762306a36Sopenharmony_ci
236862306a36Sopenharmony_ci	if (!mac_addr || !is_valid_ether_addr((const u8 *)mac_addr->sa_data))
236962306a36Sopenharmony_ci		return -EADDRNOTAVAIL;
237062306a36Sopenharmony_ci
237162306a36Sopenharmony_ci	if (ether_addr_equal(netdev->dev_addr, mac_addr->sa_data)) {
237262306a36Sopenharmony_ci		hnae3_format_mac_addr(format_mac_addr_sa, mac_addr->sa_data);
237362306a36Sopenharmony_ci		netdev_info(netdev, "already using mac address %s\n",
237462306a36Sopenharmony_ci			    format_mac_addr_sa);
237562306a36Sopenharmony_ci		return 0;
237662306a36Sopenharmony_ci	}
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_ci	/* For VF device, if there is a perm_addr, then the user will not
237962306a36Sopenharmony_ci	 * be allowed to change the address.
238062306a36Sopenharmony_ci	 */
238162306a36Sopenharmony_ci	if (!hns3_is_phys_func(h->pdev) &&
238262306a36Sopenharmony_ci	    !is_zero_ether_addr(netdev->perm_addr)) {
238362306a36Sopenharmony_ci		hnae3_format_mac_addr(format_mac_addr_perm, netdev->perm_addr);
238462306a36Sopenharmony_ci		hnae3_format_mac_addr(format_mac_addr_sa, mac_addr->sa_data);
238562306a36Sopenharmony_ci		netdev_err(netdev, "has permanent MAC %s, user MAC %s not allow\n",
238662306a36Sopenharmony_ci			   format_mac_addr_perm, format_mac_addr_sa);
238762306a36Sopenharmony_ci		return -EPERM;
238862306a36Sopenharmony_ci	}
238962306a36Sopenharmony_ci
239062306a36Sopenharmony_ci	ret = h->ae_algo->ops->set_mac_addr(h, mac_addr->sa_data, false);
239162306a36Sopenharmony_ci	if (ret) {
239262306a36Sopenharmony_ci		netdev_err(netdev, "set_mac_address fail, ret=%d!\n", ret);
239362306a36Sopenharmony_ci		return ret;
239462306a36Sopenharmony_ci	}
239562306a36Sopenharmony_ci
239662306a36Sopenharmony_ci	eth_hw_addr_set(netdev, mac_addr->sa_data);
239762306a36Sopenharmony_ci
239862306a36Sopenharmony_ci	return 0;
239962306a36Sopenharmony_ci}
240062306a36Sopenharmony_ci
240162306a36Sopenharmony_cistatic int hns3_nic_do_ioctl(struct net_device *netdev,
240262306a36Sopenharmony_ci			     struct ifreq *ifr, int cmd)
240362306a36Sopenharmony_ci{
240462306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci	if (!netif_running(netdev))
240762306a36Sopenharmony_ci		return -EINVAL;
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci	if (!h->ae_algo->ops->do_ioctl)
241062306a36Sopenharmony_ci		return -EOPNOTSUPP;
241162306a36Sopenharmony_ci
241262306a36Sopenharmony_ci	return h->ae_algo->ops->do_ioctl(h, ifr, cmd);
241362306a36Sopenharmony_ci}
241462306a36Sopenharmony_ci
241562306a36Sopenharmony_cistatic int hns3_nic_set_features(struct net_device *netdev,
241662306a36Sopenharmony_ci				 netdev_features_t features)
241762306a36Sopenharmony_ci{
241862306a36Sopenharmony_ci	netdev_features_t changed = netdev->features ^ features;
241962306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
242062306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
242162306a36Sopenharmony_ci	bool enable;
242262306a36Sopenharmony_ci	int ret;
242362306a36Sopenharmony_ci
242462306a36Sopenharmony_ci	if (changed & (NETIF_F_GRO_HW) && h->ae_algo->ops->set_gro_en) {
242562306a36Sopenharmony_ci		enable = !!(features & NETIF_F_GRO_HW);
242662306a36Sopenharmony_ci		ret = h->ae_algo->ops->set_gro_en(h, enable);
242762306a36Sopenharmony_ci		if (ret)
242862306a36Sopenharmony_ci			return ret;
242962306a36Sopenharmony_ci	}
243062306a36Sopenharmony_ci
243162306a36Sopenharmony_ci	if ((changed & NETIF_F_HW_VLAN_CTAG_RX) &&
243262306a36Sopenharmony_ci	    h->ae_algo->ops->enable_hw_strip_rxvtag) {
243362306a36Sopenharmony_ci		enable = !!(features & NETIF_F_HW_VLAN_CTAG_RX);
243462306a36Sopenharmony_ci		ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, enable);
243562306a36Sopenharmony_ci		if (ret)
243662306a36Sopenharmony_ci			return ret;
243762306a36Sopenharmony_ci	}
243862306a36Sopenharmony_ci
243962306a36Sopenharmony_ci	if ((changed & NETIF_F_NTUPLE) && h->ae_algo->ops->enable_fd) {
244062306a36Sopenharmony_ci		enable = !!(features & NETIF_F_NTUPLE);
244162306a36Sopenharmony_ci		h->ae_algo->ops->enable_fd(h, enable);
244262306a36Sopenharmony_ci	}
244362306a36Sopenharmony_ci
244462306a36Sopenharmony_ci	if ((netdev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) &&
244562306a36Sopenharmony_ci	    h->ae_algo->ops->cls_flower_active(h)) {
244662306a36Sopenharmony_ci		netdev_err(netdev,
244762306a36Sopenharmony_ci			   "there are offloaded TC filters active, cannot disable HW TC offload");
244862306a36Sopenharmony_ci		return -EINVAL;
244962306a36Sopenharmony_ci	}
245062306a36Sopenharmony_ci
245162306a36Sopenharmony_ci	if ((changed & NETIF_F_HW_VLAN_CTAG_FILTER) &&
245262306a36Sopenharmony_ci	    h->ae_algo->ops->enable_vlan_filter) {
245362306a36Sopenharmony_ci		enable = !!(features & NETIF_F_HW_VLAN_CTAG_FILTER);
245462306a36Sopenharmony_ci		ret = h->ae_algo->ops->enable_vlan_filter(h, enable);
245562306a36Sopenharmony_ci		if (ret)
245662306a36Sopenharmony_ci			return ret;
245762306a36Sopenharmony_ci	}
245862306a36Sopenharmony_ci
245962306a36Sopenharmony_ci	netdev->features = features;
246062306a36Sopenharmony_ci	return 0;
246162306a36Sopenharmony_ci}
246262306a36Sopenharmony_ci
246362306a36Sopenharmony_cistatic netdev_features_t hns3_features_check(struct sk_buff *skb,
246462306a36Sopenharmony_ci					     struct net_device *dev,
246562306a36Sopenharmony_ci					     netdev_features_t features)
246662306a36Sopenharmony_ci{
246762306a36Sopenharmony_ci#define HNS3_MAX_HDR_LEN	480U
246862306a36Sopenharmony_ci#define HNS3_MAX_L4_HDR_LEN	60U
246962306a36Sopenharmony_ci
247062306a36Sopenharmony_ci	size_t len;
247162306a36Sopenharmony_ci
247262306a36Sopenharmony_ci	if (skb->ip_summed != CHECKSUM_PARTIAL)
247362306a36Sopenharmony_ci		return features;
247462306a36Sopenharmony_ci
247562306a36Sopenharmony_ci	if (skb->encapsulation)
247662306a36Sopenharmony_ci		len = skb_inner_transport_header(skb) - skb->data;
247762306a36Sopenharmony_ci	else
247862306a36Sopenharmony_ci		len = skb_transport_header(skb) - skb->data;
247962306a36Sopenharmony_ci
248062306a36Sopenharmony_ci	/* Assume L4 is 60 byte as TCP is the only protocol with a
248162306a36Sopenharmony_ci	 * a flexible value, and it's max len is 60 bytes.
248262306a36Sopenharmony_ci	 */
248362306a36Sopenharmony_ci	len += HNS3_MAX_L4_HDR_LEN;
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_ci	/* Hardware only supports checksum on the skb with a max header
248662306a36Sopenharmony_ci	 * len of 480 bytes.
248762306a36Sopenharmony_ci	 */
248862306a36Sopenharmony_ci	if (len > HNS3_MAX_HDR_LEN)
248962306a36Sopenharmony_ci		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
249062306a36Sopenharmony_ci
249162306a36Sopenharmony_ci	return features;
249262306a36Sopenharmony_ci}
249362306a36Sopenharmony_ci
249462306a36Sopenharmony_cistatic void hns3_fetch_stats(struct rtnl_link_stats64 *stats,
249562306a36Sopenharmony_ci			     struct hns3_enet_ring *ring, bool is_tx)
249662306a36Sopenharmony_ci{
249762306a36Sopenharmony_ci	unsigned int start;
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci	do {
250062306a36Sopenharmony_ci		start = u64_stats_fetch_begin(&ring->syncp);
250162306a36Sopenharmony_ci		if (is_tx) {
250262306a36Sopenharmony_ci			stats->tx_bytes += ring->stats.tx_bytes;
250362306a36Sopenharmony_ci			stats->tx_packets += ring->stats.tx_pkts;
250462306a36Sopenharmony_ci			stats->tx_dropped += ring->stats.sw_err_cnt;
250562306a36Sopenharmony_ci			stats->tx_dropped += ring->stats.tx_vlan_err;
250662306a36Sopenharmony_ci			stats->tx_dropped += ring->stats.tx_l4_proto_err;
250762306a36Sopenharmony_ci			stats->tx_dropped += ring->stats.tx_l2l3l4_err;
250862306a36Sopenharmony_ci			stats->tx_dropped += ring->stats.tx_tso_err;
250962306a36Sopenharmony_ci			stats->tx_dropped += ring->stats.over_max_recursion;
251062306a36Sopenharmony_ci			stats->tx_dropped += ring->stats.hw_limitation;
251162306a36Sopenharmony_ci			stats->tx_dropped += ring->stats.copy_bits_err;
251262306a36Sopenharmony_ci			stats->tx_dropped += ring->stats.skb2sgl_err;
251362306a36Sopenharmony_ci			stats->tx_dropped += ring->stats.map_sg_err;
251462306a36Sopenharmony_ci			stats->tx_errors += ring->stats.sw_err_cnt;
251562306a36Sopenharmony_ci			stats->tx_errors += ring->stats.tx_vlan_err;
251662306a36Sopenharmony_ci			stats->tx_errors += ring->stats.tx_l4_proto_err;
251762306a36Sopenharmony_ci			stats->tx_errors += ring->stats.tx_l2l3l4_err;
251862306a36Sopenharmony_ci			stats->tx_errors += ring->stats.tx_tso_err;
251962306a36Sopenharmony_ci			stats->tx_errors += ring->stats.over_max_recursion;
252062306a36Sopenharmony_ci			stats->tx_errors += ring->stats.hw_limitation;
252162306a36Sopenharmony_ci			stats->tx_errors += ring->stats.copy_bits_err;
252262306a36Sopenharmony_ci			stats->tx_errors += ring->stats.skb2sgl_err;
252362306a36Sopenharmony_ci			stats->tx_errors += ring->stats.map_sg_err;
252462306a36Sopenharmony_ci		} else {
252562306a36Sopenharmony_ci			stats->rx_bytes += ring->stats.rx_bytes;
252662306a36Sopenharmony_ci			stats->rx_packets += ring->stats.rx_pkts;
252762306a36Sopenharmony_ci			stats->rx_dropped += ring->stats.l2_err;
252862306a36Sopenharmony_ci			stats->rx_errors += ring->stats.l2_err;
252962306a36Sopenharmony_ci			stats->rx_errors += ring->stats.l3l4_csum_err;
253062306a36Sopenharmony_ci			stats->rx_crc_errors += ring->stats.l2_err;
253162306a36Sopenharmony_ci			stats->multicast += ring->stats.rx_multicast;
253262306a36Sopenharmony_ci			stats->rx_length_errors += ring->stats.err_pkt_len;
253362306a36Sopenharmony_ci		}
253462306a36Sopenharmony_ci	} while (u64_stats_fetch_retry(&ring->syncp, start));
253562306a36Sopenharmony_ci}
253662306a36Sopenharmony_ci
253762306a36Sopenharmony_cistatic void hns3_nic_get_stats64(struct net_device *netdev,
253862306a36Sopenharmony_ci				 struct rtnl_link_stats64 *stats)
253962306a36Sopenharmony_ci{
254062306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
254162306a36Sopenharmony_ci	int queue_num = priv->ae_handle->kinfo.num_tqps;
254262306a36Sopenharmony_ci	struct hnae3_handle *handle = priv->ae_handle;
254362306a36Sopenharmony_ci	struct rtnl_link_stats64 ring_total_stats;
254462306a36Sopenharmony_ci	struct hns3_enet_ring *ring;
254562306a36Sopenharmony_ci	unsigned int idx;
254662306a36Sopenharmony_ci
254762306a36Sopenharmony_ci	if (test_bit(HNS3_NIC_STATE_DOWN, &priv->state))
254862306a36Sopenharmony_ci		return;
254962306a36Sopenharmony_ci
255062306a36Sopenharmony_ci	handle->ae_algo->ops->update_stats(handle);
255162306a36Sopenharmony_ci
255262306a36Sopenharmony_ci	memset(&ring_total_stats, 0, sizeof(ring_total_stats));
255362306a36Sopenharmony_ci	for (idx = 0; idx < queue_num; idx++) {
255462306a36Sopenharmony_ci		/* fetch the tx stats */
255562306a36Sopenharmony_ci		ring = &priv->ring[idx];
255662306a36Sopenharmony_ci		hns3_fetch_stats(&ring_total_stats, ring, true);
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci		/* fetch the rx stats */
255962306a36Sopenharmony_ci		ring = &priv->ring[idx + queue_num];
256062306a36Sopenharmony_ci		hns3_fetch_stats(&ring_total_stats, ring, false);
256162306a36Sopenharmony_ci	}
256262306a36Sopenharmony_ci
256362306a36Sopenharmony_ci	stats->tx_bytes = ring_total_stats.tx_bytes;
256462306a36Sopenharmony_ci	stats->tx_packets = ring_total_stats.tx_packets;
256562306a36Sopenharmony_ci	stats->rx_bytes = ring_total_stats.rx_bytes;
256662306a36Sopenharmony_ci	stats->rx_packets = ring_total_stats.rx_packets;
256762306a36Sopenharmony_ci
256862306a36Sopenharmony_ci	stats->rx_errors = ring_total_stats.rx_errors;
256962306a36Sopenharmony_ci	stats->multicast = ring_total_stats.multicast;
257062306a36Sopenharmony_ci	stats->rx_length_errors = ring_total_stats.rx_length_errors;
257162306a36Sopenharmony_ci	stats->rx_crc_errors = ring_total_stats.rx_crc_errors;
257262306a36Sopenharmony_ci	stats->rx_missed_errors = netdev->stats.rx_missed_errors;
257362306a36Sopenharmony_ci
257462306a36Sopenharmony_ci	stats->tx_errors = ring_total_stats.tx_errors;
257562306a36Sopenharmony_ci	stats->rx_dropped = ring_total_stats.rx_dropped;
257662306a36Sopenharmony_ci	stats->tx_dropped = ring_total_stats.tx_dropped;
257762306a36Sopenharmony_ci	stats->collisions = netdev->stats.collisions;
257862306a36Sopenharmony_ci	stats->rx_over_errors = netdev->stats.rx_over_errors;
257962306a36Sopenharmony_ci	stats->rx_frame_errors = netdev->stats.rx_frame_errors;
258062306a36Sopenharmony_ci	stats->rx_fifo_errors = netdev->stats.rx_fifo_errors;
258162306a36Sopenharmony_ci	stats->tx_aborted_errors = netdev->stats.tx_aborted_errors;
258262306a36Sopenharmony_ci	stats->tx_carrier_errors = netdev->stats.tx_carrier_errors;
258362306a36Sopenharmony_ci	stats->tx_fifo_errors = netdev->stats.tx_fifo_errors;
258462306a36Sopenharmony_ci	stats->tx_heartbeat_errors = netdev->stats.tx_heartbeat_errors;
258562306a36Sopenharmony_ci	stats->tx_window_errors = netdev->stats.tx_window_errors;
258662306a36Sopenharmony_ci	stats->rx_compressed = netdev->stats.rx_compressed;
258762306a36Sopenharmony_ci	stats->tx_compressed = netdev->stats.tx_compressed;
258862306a36Sopenharmony_ci}
258962306a36Sopenharmony_ci
259062306a36Sopenharmony_cistatic int hns3_setup_tc(struct net_device *netdev, void *type_data)
259162306a36Sopenharmony_ci{
259262306a36Sopenharmony_ci	struct tc_mqprio_qopt_offload *mqprio_qopt = type_data;
259362306a36Sopenharmony_ci	struct hnae3_knic_private_info *kinfo;
259462306a36Sopenharmony_ci	u8 tc = mqprio_qopt->qopt.num_tc;
259562306a36Sopenharmony_ci	u16 mode = mqprio_qopt->mode;
259662306a36Sopenharmony_ci	u8 hw = mqprio_qopt->qopt.hw;
259762306a36Sopenharmony_ci	struct hnae3_handle *h;
259862306a36Sopenharmony_ci
259962306a36Sopenharmony_ci	if (!((hw == TC_MQPRIO_HW_OFFLOAD_TCS &&
260062306a36Sopenharmony_ci	       mode == TC_MQPRIO_MODE_CHANNEL) || (!hw && tc == 0)))
260162306a36Sopenharmony_ci		return -EOPNOTSUPP;
260262306a36Sopenharmony_ci
260362306a36Sopenharmony_ci	if (tc > HNAE3_MAX_TC)
260462306a36Sopenharmony_ci		return -EINVAL;
260562306a36Sopenharmony_ci
260662306a36Sopenharmony_ci	if (!netdev)
260762306a36Sopenharmony_ci		return -EINVAL;
260862306a36Sopenharmony_ci
260962306a36Sopenharmony_ci	h = hns3_get_handle(netdev);
261062306a36Sopenharmony_ci	kinfo = &h->kinfo;
261162306a36Sopenharmony_ci
261262306a36Sopenharmony_ci	netif_dbg(h, drv, netdev, "setup tc: num_tc=%u\n", tc);
261362306a36Sopenharmony_ci
261462306a36Sopenharmony_ci	return (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ?
261562306a36Sopenharmony_ci		kinfo->dcb_ops->setup_tc(h, mqprio_qopt) : -EOPNOTSUPP;
261662306a36Sopenharmony_ci}
261762306a36Sopenharmony_ci
261862306a36Sopenharmony_cistatic int hns3_setup_tc_cls_flower(struct hns3_nic_priv *priv,
261962306a36Sopenharmony_ci				    struct flow_cls_offload *flow)
262062306a36Sopenharmony_ci{
262162306a36Sopenharmony_ci	int tc = tc_classid_to_hwtc(priv->netdev, flow->classid);
262262306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(priv->netdev);
262362306a36Sopenharmony_ci
262462306a36Sopenharmony_ci	switch (flow->command) {
262562306a36Sopenharmony_ci	case FLOW_CLS_REPLACE:
262662306a36Sopenharmony_ci		if (h->ae_algo->ops->add_cls_flower)
262762306a36Sopenharmony_ci			return h->ae_algo->ops->add_cls_flower(h, flow, tc);
262862306a36Sopenharmony_ci		break;
262962306a36Sopenharmony_ci	case FLOW_CLS_DESTROY:
263062306a36Sopenharmony_ci		if (h->ae_algo->ops->del_cls_flower)
263162306a36Sopenharmony_ci			return h->ae_algo->ops->del_cls_flower(h, flow);
263262306a36Sopenharmony_ci		break;
263362306a36Sopenharmony_ci	default:
263462306a36Sopenharmony_ci		break;
263562306a36Sopenharmony_ci	}
263662306a36Sopenharmony_ci
263762306a36Sopenharmony_ci	return -EOPNOTSUPP;
263862306a36Sopenharmony_ci}
263962306a36Sopenharmony_ci
264062306a36Sopenharmony_cistatic int hns3_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
264162306a36Sopenharmony_ci				  void *cb_priv)
264262306a36Sopenharmony_ci{
264362306a36Sopenharmony_ci	struct hns3_nic_priv *priv = cb_priv;
264462306a36Sopenharmony_ci
264562306a36Sopenharmony_ci	if (!tc_cls_can_offload_and_chain0(priv->netdev, type_data))
264662306a36Sopenharmony_ci		return -EOPNOTSUPP;
264762306a36Sopenharmony_ci
264862306a36Sopenharmony_ci	switch (type) {
264962306a36Sopenharmony_ci	case TC_SETUP_CLSFLOWER:
265062306a36Sopenharmony_ci		return hns3_setup_tc_cls_flower(priv, type_data);
265162306a36Sopenharmony_ci	default:
265262306a36Sopenharmony_ci		return -EOPNOTSUPP;
265362306a36Sopenharmony_ci	}
265462306a36Sopenharmony_ci}
265562306a36Sopenharmony_ci
265662306a36Sopenharmony_cistatic LIST_HEAD(hns3_block_cb_list);
265762306a36Sopenharmony_ci
265862306a36Sopenharmony_cistatic int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type,
265962306a36Sopenharmony_ci			     void *type_data)
266062306a36Sopenharmony_ci{
266162306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(dev);
266262306a36Sopenharmony_ci	int ret;
266362306a36Sopenharmony_ci
266462306a36Sopenharmony_ci	switch (type) {
266562306a36Sopenharmony_ci	case TC_SETUP_QDISC_MQPRIO:
266662306a36Sopenharmony_ci		ret = hns3_setup_tc(dev, type_data);
266762306a36Sopenharmony_ci		break;
266862306a36Sopenharmony_ci	case TC_SETUP_BLOCK:
266962306a36Sopenharmony_ci		ret = flow_block_cb_setup_simple(type_data,
267062306a36Sopenharmony_ci						 &hns3_block_cb_list,
267162306a36Sopenharmony_ci						 hns3_setup_tc_block_cb,
267262306a36Sopenharmony_ci						 priv, priv, true);
267362306a36Sopenharmony_ci		break;
267462306a36Sopenharmony_ci	default:
267562306a36Sopenharmony_ci		return -EOPNOTSUPP;
267662306a36Sopenharmony_ci	}
267762306a36Sopenharmony_ci
267862306a36Sopenharmony_ci	return ret;
267962306a36Sopenharmony_ci}
268062306a36Sopenharmony_ci
268162306a36Sopenharmony_cistatic int hns3_vlan_rx_add_vid(struct net_device *netdev,
268262306a36Sopenharmony_ci				__be16 proto, u16 vid)
268362306a36Sopenharmony_ci{
268462306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
268562306a36Sopenharmony_ci	int ret = -EIO;
268662306a36Sopenharmony_ci
268762306a36Sopenharmony_ci	if (h->ae_algo->ops->set_vlan_filter)
268862306a36Sopenharmony_ci		ret = h->ae_algo->ops->set_vlan_filter(h, proto, vid, false);
268962306a36Sopenharmony_ci
269062306a36Sopenharmony_ci	return ret;
269162306a36Sopenharmony_ci}
269262306a36Sopenharmony_ci
269362306a36Sopenharmony_cistatic int hns3_vlan_rx_kill_vid(struct net_device *netdev,
269462306a36Sopenharmony_ci				 __be16 proto, u16 vid)
269562306a36Sopenharmony_ci{
269662306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
269762306a36Sopenharmony_ci	int ret = -EIO;
269862306a36Sopenharmony_ci
269962306a36Sopenharmony_ci	if (h->ae_algo->ops->set_vlan_filter)
270062306a36Sopenharmony_ci		ret = h->ae_algo->ops->set_vlan_filter(h, proto, vid, true);
270162306a36Sopenharmony_ci
270262306a36Sopenharmony_ci	return ret;
270362306a36Sopenharmony_ci}
270462306a36Sopenharmony_ci
270562306a36Sopenharmony_cistatic int hns3_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
270662306a36Sopenharmony_ci				u8 qos, __be16 vlan_proto)
270762306a36Sopenharmony_ci{
270862306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
270962306a36Sopenharmony_ci	int ret = -EIO;
271062306a36Sopenharmony_ci
271162306a36Sopenharmony_ci	netif_dbg(h, drv, netdev,
271262306a36Sopenharmony_ci		  "set vf vlan: vf=%d, vlan=%u, qos=%u, vlan_proto=0x%x\n",
271362306a36Sopenharmony_ci		  vf, vlan, qos, ntohs(vlan_proto));
271462306a36Sopenharmony_ci
271562306a36Sopenharmony_ci	if (h->ae_algo->ops->set_vf_vlan_filter)
271662306a36Sopenharmony_ci		ret = h->ae_algo->ops->set_vf_vlan_filter(h, vf, vlan,
271762306a36Sopenharmony_ci							  qos, vlan_proto);
271862306a36Sopenharmony_ci
271962306a36Sopenharmony_ci	return ret;
272062306a36Sopenharmony_ci}
272162306a36Sopenharmony_ci
272262306a36Sopenharmony_cistatic int hns3_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable)
272362306a36Sopenharmony_ci{
272462306a36Sopenharmony_ci	struct hnae3_handle *handle = hns3_get_handle(netdev);
272562306a36Sopenharmony_ci
272662306a36Sopenharmony_ci	if (hns3_nic_resetting(netdev))
272762306a36Sopenharmony_ci		return -EBUSY;
272862306a36Sopenharmony_ci
272962306a36Sopenharmony_ci	if (!handle->ae_algo->ops->set_vf_spoofchk)
273062306a36Sopenharmony_ci		return -EOPNOTSUPP;
273162306a36Sopenharmony_ci
273262306a36Sopenharmony_ci	return handle->ae_algo->ops->set_vf_spoofchk(handle, vf, enable);
273362306a36Sopenharmony_ci}
273462306a36Sopenharmony_ci
273562306a36Sopenharmony_cistatic int hns3_set_vf_trust(struct net_device *netdev, int vf, bool enable)
273662306a36Sopenharmony_ci{
273762306a36Sopenharmony_ci	struct hnae3_handle *handle = hns3_get_handle(netdev);
273862306a36Sopenharmony_ci
273962306a36Sopenharmony_ci	if (!handle->ae_algo->ops->set_vf_trust)
274062306a36Sopenharmony_ci		return -EOPNOTSUPP;
274162306a36Sopenharmony_ci
274262306a36Sopenharmony_ci	return handle->ae_algo->ops->set_vf_trust(handle, vf, enable);
274362306a36Sopenharmony_ci}
274462306a36Sopenharmony_ci
274562306a36Sopenharmony_cistatic int hns3_nic_change_mtu(struct net_device *netdev, int new_mtu)
274662306a36Sopenharmony_ci{
274762306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
274862306a36Sopenharmony_ci	int ret;
274962306a36Sopenharmony_ci
275062306a36Sopenharmony_ci	if (hns3_nic_resetting(netdev))
275162306a36Sopenharmony_ci		return -EBUSY;
275262306a36Sopenharmony_ci
275362306a36Sopenharmony_ci	if (!h->ae_algo->ops->set_mtu)
275462306a36Sopenharmony_ci		return -EOPNOTSUPP;
275562306a36Sopenharmony_ci
275662306a36Sopenharmony_ci	netif_dbg(h, drv, netdev,
275762306a36Sopenharmony_ci		  "change mtu from %u to %d\n", netdev->mtu, new_mtu);
275862306a36Sopenharmony_ci
275962306a36Sopenharmony_ci	ret = h->ae_algo->ops->set_mtu(h, new_mtu);
276062306a36Sopenharmony_ci	if (ret)
276162306a36Sopenharmony_ci		netdev_err(netdev, "failed to change MTU in hardware %d\n",
276262306a36Sopenharmony_ci			   ret);
276362306a36Sopenharmony_ci	else
276462306a36Sopenharmony_ci		netdev->mtu = new_mtu;
276562306a36Sopenharmony_ci
276662306a36Sopenharmony_ci	return ret;
276762306a36Sopenharmony_ci}
276862306a36Sopenharmony_ci
276962306a36Sopenharmony_cistatic int hns3_get_timeout_queue(struct net_device *ndev)
277062306a36Sopenharmony_ci{
277162306a36Sopenharmony_ci	int i;
277262306a36Sopenharmony_ci
277362306a36Sopenharmony_ci	/* Find the stopped queue the same way the stack does */
277462306a36Sopenharmony_ci	for (i = 0; i < ndev->num_tx_queues; i++) {
277562306a36Sopenharmony_ci		struct netdev_queue *q;
277662306a36Sopenharmony_ci		unsigned long trans_start;
277762306a36Sopenharmony_ci
277862306a36Sopenharmony_ci		q = netdev_get_tx_queue(ndev, i);
277962306a36Sopenharmony_ci		trans_start = READ_ONCE(q->trans_start);
278062306a36Sopenharmony_ci		if (netif_xmit_stopped(q) &&
278162306a36Sopenharmony_ci		    time_after(jiffies,
278262306a36Sopenharmony_ci			       (trans_start + ndev->watchdog_timeo))) {
278362306a36Sopenharmony_ci#ifdef CONFIG_BQL
278462306a36Sopenharmony_ci			struct dql *dql = &q->dql;
278562306a36Sopenharmony_ci
278662306a36Sopenharmony_ci			netdev_info(ndev, "DQL info last_cnt: %u, queued: %u, adj_limit: %u, completed: %u\n",
278762306a36Sopenharmony_ci				    dql->last_obj_cnt, dql->num_queued,
278862306a36Sopenharmony_ci				    dql->adj_limit, dql->num_completed);
278962306a36Sopenharmony_ci#endif
279062306a36Sopenharmony_ci			netdev_info(ndev, "queue state: 0x%lx, delta msecs: %u\n",
279162306a36Sopenharmony_ci				    q->state,
279262306a36Sopenharmony_ci				    jiffies_to_msecs(jiffies - trans_start));
279362306a36Sopenharmony_ci			break;
279462306a36Sopenharmony_ci		}
279562306a36Sopenharmony_ci	}
279662306a36Sopenharmony_ci
279762306a36Sopenharmony_ci	return i;
279862306a36Sopenharmony_ci}
279962306a36Sopenharmony_ci
280062306a36Sopenharmony_cistatic void hns3_dump_queue_stats(struct net_device *ndev,
280162306a36Sopenharmony_ci				  struct hns3_enet_ring *tx_ring,
280262306a36Sopenharmony_ci				  int timeout_queue)
280362306a36Sopenharmony_ci{
280462306a36Sopenharmony_ci	struct napi_struct *napi = &tx_ring->tqp_vector->napi;
280562306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
280662306a36Sopenharmony_ci
280762306a36Sopenharmony_ci	netdev_info(ndev,
280862306a36Sopenharmony_ci		    "tx_timeout count: %llu, queue id: %d, SW_NTU: 0x%x, SW_NTC: 0x%x, napi state: %lu\n",
280962306a36Sopenharmony_ci		    priv->tx_timeout_count, timeout_queue, tx_ring->next_to_use,
281062306a36Sopenharmony_ci		    tx_ring->next_to_clean, napi->state);
281162306a36Sopenharmony_ci
281262306a36Sopenharmony_ci	netdev_info(ndev,
281362306a36Sopenharmony_ci		    "tx_pkts: %llu, tx_bytes: %llu, sw_err_cnt: %llu, tx_pending: %d\n",
281462306a36Sopenharmony_ci		    tx_ring->stats.tx_pkts, tx_ring->stats.tx_bytes,
281562306a36Sopenharmony_ci		    tx_ring->stats.sw_err_cnt, tx_ring->pending_buf);
281662306a36Sopenharmony_ci
281762306a36Sopenharmony_ci	netdev_info(ndev,
281862306a36Sopenharmony_ci		    "seg_pkt_cnt: %llu, tx_more: %llu, restart_queue: %llu, tx_busy: %llu\n",
281962306a36Sopenharmony_ci		    tx_ring->stats.seg_pkt_cnt, tx_ring->stats.tx_more,
282062306a36Sopenharmony_ci		    tx_ring->stats.restart_queue, tx_ring->stats.tx_busy);
282162306a36Sopenharmony_ci
282262306a36Sopenharmony_ci	netdev_info(ndev, "tx_push: %llu, tx_mem_doorbell: %llu\n",
282362306a36Sopenharmony_ci		    tx_ring->stats.tx_push, tx_ring->stats.tx_mem_doorbell);
282462306a36Sopenharmony_ci}
282562306a36Sopenharmony_ci
282662306a36Sopenharmony_cistatic void hns3_dump_queue_reg(struct net_device *ndev,
282762306a36Sopenharmony_ci				struct hns3_enet_ring *tx_ring)
282862306a36Sopenharmony_ci{
282962306a36Sopenharmony_ci	netdev_info(ndev,
283062306a36Sopenharmony_ci		    "BD_NUM: 0x%x HW_HEAD: 0x%x, HW_TAIL: 0x%x, BD_ERR: 0x%x, INT: 0x%x\n",
283162306a36Sopenharmony_ci		    hns3_tqp_read_reg(tx_ring, HNS3_RING_TX_RING_BD_NUM_REG),
283262306a36Sopenharmony_ci		    hns3_tqp_read_reg(tx_ring, HNS3_RING_TX_RING_HEAD_REG),
283362306a36Sopenharmony_ci		    hns3_tqp_read_reg(tx_ring, HNS3_RING_TX_RING_TAIL_REG),
283462306a36Sopenharmony_ci		    hns3_tqp_read_reg(tx_ring, HNS3_RING_TX_RING_BD_ERR_REG),
283562306a36Sopenharmony_ci		    readl(tx_ring->tqp_vector->mask_addr));
283662306a36Sopenharmony_ci	netdev_info(ndev,
283762306a36Sopenharmony_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",
283862306a36Sopenharmony_ci		    hns3_tqp_read_reg(tx_ring, HNS3_RING_EN_REG),
283962306a36Sopenharmony_ci		    hns3_tqp_read_reg(tx_ring, HNS3_RING_TX_RING_TC_REG),
284062306a36Sopenharmony_ci		    hns3_tqp_read_reg(tx_ring, HNS3_RING_TX_RING_FBDNUM_REG),
284162306a36Sopenharmony_ci		    hns3_tqp_read_reg(tx_ring, HNS3_RING_TX_RING_OFFSET_REG),
284262306a36Sopenharmony_ci		    hns3_tqp_read_reg(tx_ring, HNS3_RING_TX_RING_EBDNUM_REG),
284362306a36Sopenharmony_ci		    hns3_tqp_read_reg(tx_ring,
284462306a36Sopenharmony_ci				      HNS3_RING_TX_RING_EBD_OFFSET_REG));
284562306a36Sopenharmony_ci}
284662306a36Sopenharmony_ci
284762306a36Sopenharmony_cistatic bool hns3_get_tx_timeo_queue_info(struct net_device *ndev)
284862306a36Sopenharmony_ci{
284962306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
285062306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(ndev);
285162306a36Sopenharmony_ci	struct hns3_enet_ring *tx_ring;
285262306a36Sopenharmony_ci	int timeout_queue;
285362306a36Sopenharmony_ci
285462306a36Sopenharmony_ci	timeout_queue = hns3_get_timeout_queue(ndev);
285562306a36Sopenharmony_ci	if (timeout_queue >= ndev->num_tx_queues) {
285662306a36Sopenharmony_ci		netdev_info(ndev,
285762306a36Sopenharmony_ci			    "no netdev TX timeout queue found, timeout count: %llu\n",
285862306a36Sopenharmony_ci			    priv->tx_timeout_count);
285962306a36Sopenharmony_ci		return false;
286062306a36Sopenharmony_ci	}
286162306a36Sopenharmony_ci
286262306a36Sopenharmony_ci	priv->tx_timeout_count++;
286362306a36Sopenharmony_ci
286462306a36Sopenharmony_ci	tx_ring = &priv->ring[timeout_queue];
286562306a36Sopenharmony_ci	hns3_dump_queue_stats(ndev, tx_ring, timeout_queue);
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_ci	/* When mac received many pause frames continuous, it's unable to send
286862306a36Sopenharmony_ci	 * packets, which may cause tx timeout
286962306a36Sopenharmony_ci	 */
287062306a36Sopenharmony_ci	if (h->ae_algo->ops->get_mac_stats) {
287162306a36Sopenharmony_ci		struct hns3_mac_stats mac_stats;
287262306a36Sopenharmony_ci
287362306a36Sopenharmony_ci		h->ae_algo->ops->get_mac_stats(h, &mac_stats);
287462306a36Sopenharmony_ci		netdev_info(ndev, "tx_pause_cnt: %llu, rx_pause_cnt: %llu\n",
287562306a36Sopenharmony_ci			    mac_stats.tx_pause_cnt, mac_stats.rx_pause_cnt);
287662306a36Sopenharmony_ci	}
287762306a36Sopenharmony_ci
287862306a36Sopenharmony_ci	hns3_dump_queue_reg(ndev, tx_ring);
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_ci	return true;
288162306a36Sopenharmony_ci}
288262306a36Sopenharmony_ci
288362306a36Sopenharmony_cistatic void hns3_nic_net_timeout(struct net_device *ndev, unsigned int txqueue)
288462306a36Sopenharmony_ci{
288562306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
288662306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
288762306a36Sopenharmony_ci
288862306a36Sopenharmony_ci	if (!hns3_get_tx_timeo_queue_info(ndev))
288962306a36Sopenharmony_ci		return;
289062306a36Sopenharmony_ci
289162306a36Sopenharmony_ci	/* request the reset, and let the hclge to determine
289262306a36Sopenharmony_ci	 * which reset level should be done
289362306a36Sopenharmony_ci	 */
289462306a36Sopenharmony_ci	if (h->ae_algo->ops->reset_event)
289562306a36Sopenharmony_ci		h->ae_algo->ops->reset_event(h->pdev, h);
289662306a36Sopenharmony_ci}
289762306a36Sopenharmony_ci
289862306a36Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
289962306a36Sopenharmony_cistatic int hns3_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
290062306a36Sopenharmony_ci			      u16 rxq_index, u32 flow_id)
290162306a36Sopenharmony_ci{
290262306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(dev);
290362306a36Sopenharmony_ci	struct flow_keys fkeys;
290462306a36Sopenharmony_ci
290562306a36Sopenharmony_ci	if (!h->ae_algo->ops->add_arfs_entry)
290662306a36Sopenharmony_ci		return -EOPNOTSUPP;
290762306a36Sopenharmony_ci
290862306a36Sopenharmony_ci	if (skb->encapsulation)
290962306a36Sopenharmony_ci		return -EPROTONOSUPPORT;
291062306a36Sopenharmony_ci
291162306a36Sopenharmony_ci	if (!skb_flow_dissect_flow_keys(skb, &fkeys, 0))
291262306a36Sopenharmony_ci		return -EPROTONOSUPPORT;
291362306a36Sopenharmony_ci
291462306a36Sopenharmony_ci	if ((fkeys.basic.n_proto != htons(ETH_P_IP) &&
291562306a36Sopenharmony_ci	     fkeys.basic.n_proto != htons(ETH_P_IPV6)) ||
291662306a36Sopenharmony_ci	    (fkeys.basic.ip_proto != IPPROTO_TCP &&
291762306a36Sopenharmony_ci	     fkeys.basic.ip_proto != IPPROTO_UDP))
291862306a36Sopenharmony_ci		return -EPROTONOSUPPORT;
291962306a36Sopenharmony_ci
292062306a36Sopenharmony_ci	return h->ae_algo->ops->add_arfs_entry(h, rxq_index, flow_id, &fkeys);
292162306a36Sopenharmony_ci}
292262306a36Sopenharmony_ci#endif
292362306a36Sopenharmony_ci
292462306a36Sopenharmony_cistatic int hns3_nic_get_vf_config(struct net_device *ndev, int vf,
292562306a36Sopenharmony_ci				  struct ifla_vf_info *ivf)
292662306a36Sopenharmony_ci{
292762306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(ndev);
292862306a36Sopenharmony_ci
292962306a36Sopenharmony_ci	if (!h->ae_algo->ops->get_vf_config)
293062306a36Sopenharmony_ci		return -EOPNOTSUPP;
293162306a36Sopenharmony_ci
293262306a36Sopenharmony_ci	return h->ae_algo->ops->get_vf_config(h, vf, ivf);
293362306a36Sopenharmony_ci}
293462306a36Sopenharmony_ci
293562306a36Sopenharmony_cistatic int hns3_nic_set_vf_link_state(struct net_device *ndev, int vf,
293662306a36Sopenharmony_ci				      int link_state)
293762306a36Sopenharmony_ci{
293862306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(ndev);
293962306a36Sopenharmony_ci
294062306a36Sopenharmony_ci	if (!h->ae_algo->ops->set_vf_link_state)
294162306a36Sopenharmony_ci		return -EOPNOTSUPP;
294262306a36Sopenharmony_ci
294362306a36Sopenharmony_ci	return h->ae_algo->ops->set_vf_link_state(h, vf, link_state);
294462306a36Sopenharmony_ci}
294562306a36Sopenharmony_ci
294662306a36Sopenharmony_cistatic int hns3_nic_set_vf_rate(struct net_device *ndev, int vf,
294762306a36Sopenharmony_ci				int min_tx_rate, int max_tx_rate)
294862306a36Sopenharmony_ci{
294962306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(ndev);
295062306a36Sopenharmony_ci
295162306a36Sopenharmony_ci	if (!h->ae_algo->ops->set_vf_rate)
295262306a36Sopenharmony_ci		return -EOPNOTSUPP;
295362306a36Sopenharmony_ci
295462306a36Sopenharmony_ci	return h->ae_algo->ops->set_vf_rate(h, vf, min_tx_rate, max_tx_rate,
295562306a36Sopenharmony_ci					    false);
295662306a36Sopenharmony_ci}
295762306a36Sopenharmony_ci
295862306a36Sopenharmony_cistatic int hns3_nic_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
295962306a36Sopenharmony_ci{
296062306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
296162306a36Sopenharmony_ci	char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
296262306a36Sopenharmony_ci
296362306a36Sopenharmony_ci	if (!h->ae_algo->ops->set_vf_mac)
296462306a36Sopenharmony_ci		return -EOPNOTSUPP;
296562306a36Sopenharmony_ci
296662306a36Sopenharmony_ci	if (is_multicast_ether_addr(mac)) {
296762306a36Sopenharmony_ci		hnae3_format_mac_addr(format_mac_addr, mac);
296862306a36Sopenharmony_ci		netdev_err(netdev,
296962306a36Sopenharmony_ci			   "Invalid MAC:%s specified. Could not set MAC\n",
297062306a36Sopenharmony_ci			   format_mac_addr);
297162306a36Sopenharmony_ci		return -EINVAL;
297262306a36Sopenharmony_ci	}
297362306a36Sopenharmony_ci
297462306a36Sopenharmony_ci	return h->ae_algo->ops->set_vf_mac(h, vf_id, mac);
297562306a36Sopenharmony_ci}
297662306a36Sopenharmony_ci
297762306a36Sopenharmony_ci#define HNS3_INVALID_DSCP		0xff
297862306a36Sopenharmony_ci#define HNS3_DSCP_SHIFT			2
297962306a36Sopenharmony_ci
298062306a36Sopenharmony_cistatic u8 hns3_get_skb_dscp(struct sk_buff *skb)
298162306a36Sopenharmony_ci{
298262306a36Sopenharmony_ci	__be16 protocol = skb->protocol;
298362306a36Sopenharmony_ci	u8 dscp = HNS3_INVALID_DSCP;
298462306a36Sopenharmony_ci
298562306a36Sopenharmony_ci	if (protocol == htons(ETH_P_8021Q))
298662306a36Sopenharmony_ci		protocol = vlan_get_protocol(skb);
298762306a36Sopenharmony_ci
298862306a36Sopenharmony_ci	if (protocol == htons(ETH_P_IP))
298962306a36Sopenharmony_ci		dscp = ipv4_get_dsfield(ip_hdr(skb)) >> HNS3_DSCP_SHIFT;
299062306a36Sopenharmony_ci	else if (protocol == htons(ETH_P_IPV6))
299162306a36Sopenharmony_ci		dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> HNS3_DSCP_SHIFT;
299262306a36Sopenharmony_ci
299362306a36Sopenharmony_ci	return dscp;
299462306a36Sopenharmony_ci}
299562306a36Sopenharmony_ci
299662306a36Sopenharmony_cistatic u16 hns3_nic_select_queue(struct net_device *netdev,
299762306a36Sopenharmony_ci				 struct sk_buff *skb,
299862306a36Sopenharmony_ci				 struct net_device *sb_dev)
299962306a36Sopenharmony_ci{
300062306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
300162306a36Sopenharmony_ci	u8 dscp;
300262306a36Sopenharmony_ci
300362306a36Sopenharmony_ci	if (h->kinfo.tc_map_mode != HNAE3_TC_MAP_MODE_DSCP ||
300462306a36Sopenharmony_ci	    !h->ae_algo->ops->get_dscp_prio)
300562306a36Sopenharmony_ci		goto out;
300662306a36Sopenharmony_ci
300762306a36Sopenharmony_ci	dscp = hns3_get_skb_dscp(skb);
300862306a36Sopenharmony_ci	if (unlikely(dscp >= HNAE3_MAX_DSCP))
300962306a36Sopenharmony_ci		goto out;
301062306a36Sopenharmony_ci
301162306a36Sopenharmony_ci	skb->priority = h->kinfo.dscp_prio[dscp];
301262306a36Sopenharmony_ci	if (skb->priority == HNAE3_PRIO_ID_INVALID)
301362306a36Sopenharmony_ci		skb->priority = 0;
301462306a36Sopenharmony_ci
301562306a36Sopenharmony_ciout:
301662306a36Sopenharmony_ci	return netdev_pick_tx(netdev, skb, sb_dev);
301762306a36Sopenharmony_ci}
301862306a36Sopenharmony_ci
301962306a36Sopenharmony_cistatic const struct net_device_ops hns3_nic_netdev_ops = {
302062306a36Sopenharmony_ci	.ndo_open		= hns3_nic_net_open,
302162306a36Sopenharmony_ci	.ndo_stop		= hns3_nic_net_stop,
302262306a36Sopenharmony_ci	.ndo_start_xmit		= hns3_nic_net_xmit,
302362306a36Sopenharmony_ci	.ndo_tx_timeout		= hns3_nic_net_timeout,
302462306a36Sopenharmony_ci	.ndo_set_mac_address	= hns3_nic_net_set_mac_address,
302562306a36Sopenharmony_ci	.ndo_eth_ioctl		= hns3_nic_do_ioctl,
302662306a36Sopenharmony_ci	.ndo_change_mtu		= hns3_nic_change_mtu,
302762306a36Sopenharmony_ci	.ndo_set_features	= hns3_nic_set_features,
302862306a36Sopenharmony_ci	.ndo_features_check	= hns3_features_check,
302962306a36Sopenharmony_ci	.ndo_get_stats64	= hns3_nic_get_stats64,
303062306a36Sopenharmony_ci	.ndo_setup_tc		= hns3_nic_setup_tc,
303162306a36Sopenharmony_ci	.ndo_set_rx_mode	= hns3_nic_set_rx_mode,
303262306a36Sopenharmony_ci	.ndo_vlan_rx_add_vid	= hns3_vlan_rx_add_vid,
303362306a36Sopenharmony_ci	.ndo_vlan_rx_kill_vid	= hns3_vlan_rx_kill_vid,
303462306a36Sopenharmony_ci	.ndo_set_vf_vlan	= hns3_ndo_set_vf_vlan,
303562306a36Sopenharmony_ci	.ndo_set_vf_spoofchk	= hns3_set_vf_spoofchk,
303662306a36Sopenharmony_ci	.ndo_set_vf_trust	= hns3_set_vf_trust,
303762306a36Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
303862306a36Sopenharmony_ci	.ndo_rx_flow_steer	= hns3_rx_flow_steer,
303962306a36Sopenharmony_ci#endif
304062306a36Sopenharmony_ci	.ndo_get_vf_config	= hns3_nic_get_vf_config,
304162306a36Sopenharmony_ci	.ndo_set_vf_link_state	= hns3_nic_set_vf_link_state,
304262306a36Sopenharmony_ci	.ndo_set_vf_rate	= hns3_nic_set_vf_rate,
304362306a36Sopenharmony_ci	.ndo_set_vf_mac		= hns3_nic_set_vf_mac,
304462306a36Sopenharmony_ci	.ndo_select_queue	= hns3_nic_select_queue,
304562306a36Sopenharmony_ci};
304662306a36Sopenharmony_ci
304762306a36Sopenharmony_cibool hns3_is_phys_func(struct pci_dev *pdev)
304862306a36Sopenharmony_ci{
304962306a36Sopenharmony_ci	u32 dev_id = pdev->device;
305062306a36Sopenharmony_ci
305162306a36Sopenharmony_ci	switch (dev_id) {
305262306a36Sopenharmony_ci	case HNAE3_DEV_ID_GE:
305362306a36Sopenharmony_ci	case HNAE3_DEV_ID_25GE:
305462306a36Sopenharmony_ci	case HNAE3_DEV_ID_25GE_RDMA:
305562306a36Sopenharmony_ci	case HNAE3_DEV_ID_25GE_RDMA_MACSEC:
305662306a36Sopenharmony_ci	case HNAE3_DEV_ID_50GE_RDMA:
305762306a36Sopenharmony_ci	case HNAE3_DEV_ID_50GE_RDMA_MACSEC:
305862306a36Sopenharmony_ci	case HNAE3_DEV_ID_100G_RDMA_MACSEC:
305962306a36Sopenharmony_ci	case HNAE3_DEV_ID_200G_RDMA:
306062306a36Sopenharmony_ci		return true;
306162306a36Sopenharmony_ci	case HNAE3_DEV_ID_VF:
306262306a36Sopenharmony_ci	case HNAE3_DEV_ID_RDMA_DCB_PFC_VF:
306362306a36Sopenharmony_ci		return false;
306462306a36Sopenharmony_ci	default:
306562306a36Sopenharmony_ci		dev_warn(&pdev->dev, "un-recognized pci device-id %u",
306662306a36Sopenharmony_ci			 dev_id);
306762306a36Sopenharmony_ci	}
306862306a36Sopenharmony_ci
306962306a36Sopenharmony_ci	return false;
307062306a36Sopenharmony_ci}
307162306a36Sopenharmony_ci
307262306a36Sopenharmony_cistatic void hns3_disable_sriov(struct pci_dev *pdev)
307362306a36Sopenharmony_ci{
307462306a36Sopenharmony_ci	/* If our VFs are assigned we cannot shut down SR-IOV
307562306a36Sopenharmony_ci	 * without causing issues, so just leave the hardware
307662306a36Sopenharmony_ci	 * available but disabled
307762306a36Sopenharmony_ci	 */
307862306a36Sopenharmony_ci	if (pci_vfs_assigned(pdev)) {
307962306a36Sopenharmony_ci		dev_warn(&pdev->dev,
308062306a36Sopenharmony_ci			 "disabling driver while VFs are assigned\n");
308162306a36Sopenharmony_ci		return;
308262306a36Sopenharmony_ci	}
308362306a36Sopenharmony_ci
308462306a36Sopenharmony_ci	pci_disable_sriov(pdev);
308562306a36Sopenharmony_ci}
308662306a36Sopenharmony_ci
308762306a36Sopenharmony_ci/* hns3_probe - Device initialization routine
308862306a36Sopenharmony_ci * @pdev: PCI device information struct
308962306a36Sopenharmony_ci * @ent: entry in hns3_pci_tbl
309062306a36Sopenharmony_ci *
309162306a36Sopenharmony_ci * hns3_probe initializes a PF identified by a pci_dev structure.
309262306a36Sopenharmony_ci * The OS initialization, configuring of the PF private structure,
309362306a36Sopenharmony_ci * and a hardware reset occur.
309462306a36Sopenharmony_ci *
309562306a36Sopenharmony_ci * Returns 0 on success, negative on failure
309662306a36Sopenharmony_ci */
309762306a36Sopenharmony_cistatic int hns3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
309862306a36Sopenharmony_ci{
309962306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev;
310062306a36Sopenharmony_ci	int ret;
310162306a36Sopenharmony_ci
310262306a36Sopenharmony_ci	ae_dev = devm_kzalloc(&pdev->dev, sizeof(*ae_dev), GFP_KERNEL);
310362306a36Sopenharmony_ci	if (!ae_dev)
310462306a36Sopenharmony_ci		return -ENOMEM;
310562306a36Sopenharmony_ci
310662306a36Sopenharmony_ci	ae_dev->pdev = pdev;
310762306a36Sopenharmony_ci	ae_dev->flag = ent->driver_data;
310862306a36Sopenharmony_ci	pci_set_drvdata(pdev, ae_dev);
310962306a36Sopenharmony_ci
311062306a36Sopenharmony_ci	ret = hnae3_register_ae_dev(ae_dev);
311162306a36Sopenharmony_ci	if (ret)
311262306a36Sopenharmony_ci		pci_set_drvdata(pdev, NULL);
311362306a36Sopenharmony_ci
311462306a36Sopenharmony_ci	return ret;
311562306a36Sopenharmony_ci}
311662306a36Sopenharmony_ci
311762306a36Sopenharmony_ci/**
311862306a36Sopenharmony_ci * hns3_clean_vf_config
311962306a36Sopenharmony_ci * @pdev: pointer to a pci_dev structure
312062306a36Sopenharmony_ci * @num_vfs: number of VFs allocated
312162306a36Sopenharmony_ci *
312262306a36Sopenharmony_ci * Clean residual vf config after disable sriov
312362306a36Sopenharmony_ci **/
312462306a36Sopenharmony_cistatic void hns3_clean_vf_config(struct pci_dev *pdev, int num_vfs)
312562306a36Sopenharmony_ci{
312662306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
312762306a36Sopenharmony_ci
312862306a36Sopenharmony_ci	if (ae_dev->ops->clean_vf_config)
312962306a36Sopenharmony_ci		ae_dev->ops->clean_vf_config(ae_dev, num_vfs);
313062306a36Sopenharmony_ci}
313162306a36Sopenharmony_ci
313262306a36Sopenharmony_ci/* hns3_remove - Device removal routine
313362306a36Sopenharmony_ci * @pdev: PCI device information struct
313462306a36Sopenharmony_ci */
313562306a36Sopenharmony_cistatic void hns3_remove(struct pci_dev *pdev)
313662306a36Sopenharmony_ci{
313762306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
313862306a36Sopenharmony_ci
313962306a36Sopenharmony_ci	if (hns3_is_phys_func(pdev) && IS_ENABLED(CONFIG_PCI_IOV))
314062306a36Sopenharmony_ci		hns3_disable_sriov(pdev);
314162306a36Sopenharmony_ci
314262306a36Sopenharmony_ci	hnae3_unregister_ae_dev(ae_dev);
314362306a36Sopenharmony_ci	pci_set_drvdata(pdev, NULL);
314462306a36Sopenharmony_ci}
314562306a36Sopenharmony_ci
314662306a36Sopenharmony_ci/**
314762306a36Sopenharmony_ci * hns3_pci_sriov_configure
314862306a36Sopenharmony_ci * @pdev: pointer to a pci_dev structure
314962306a36Sopenharmony_ci * @num_vfs: number of VFs to allocate
315062306a36Sopenharmony_ci *
315162306a36Sopenharmony_ci * Enable or change the number of VFs. Called when the user updates the number
315262306a36Sopenharmony_ci * of VFs in sysfs.
315362306a36Sopenharmony_ci **/
315462306a36Sopenharmony_cistatic int hns3_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
315562306a36Sopenharmony_ci{
315662306a36Sopenharmony_ci	int ret;
315762306a36Sopenharmony_ci
315862306a36Sopenharmony_ci	if (!(hns3_is_phys_func(pdev) && IS_ENABLED(CONFIG_PCI_IOV))) {
315962306a36Sopenharmony_ci		dev_warn(&pdev->dev, "Can not config SRIOV\n");
316062306a36Sopenharmony_ci		return -EINVAL;
316162306a36Sopenharmony_ci	}
316262306a36Sopenharmony_ci
316362306a36Sopenharmony_ci	if (num_vfs) {
316462306a36Sopenharmony_ci		ret = pci_enable_sriov(pdev, num_vfs);
316562306a36Sopenharmony_ci		if (ret)
316662306a36Sopenharmony_ci			dev_err(&pdev->dev, "SRIOV enable failed %d\n", ret);
316762306a36Sopenharmony_ci		else
316862306a36Sopenharmony_ci			return num_vfs;
316962306a36Sopenharmony_ci	} else if (!pci_vfs_assigned(pdev)) {
317062306a36Sopenharmony_ci		int num_vfs_pre = pci_num_vf(pdev);
317162306a36Sopenharmony_ci
317262306a36Sopenharmony_ci		pci_disable_sriov(pdev);
317362306a36Sopenharmony_ci		hns3_clean_vf_config(pdev, num_vfs_pre);
317462306a36Sopenharmony_ci	} else {
317562306a36Sopenharmony_ci		dev_warn(&pdev->dev,
317662306a36Sopenharmony_ci			 "Unable to free VFs because some are assigned to VMs.\n");
317762306a36Sopenharmony_ci	}
317862306a36Sopenharmony_ci
317962306a36Sopenharmony_ci	return 0;
318062306a36Sopenharmony_ci}
318162306a36Sopenharmony_ci
318262306a36Sopenharmony_cistatic void hns3_shutdown(struct pci_dev *pdev)
318362306a36Sopenharmony_ci{
318462306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
318562306a36Sopenharmony_ci
318662306a36Sopenharmony_ci	hnae3_unregister_ae_dev(ae_dev);
318762306a36Sopenharmony_ci	pci_set_drvdata(pdev, NULL);
318862306a36Sopenharmony_ci
318962306a36Sopenharmony_ci	if (system_state == SYSTEM_POWER_OFF)
319062306a36Sopenharmony_ci		pci_set_power_state(pdev, PCI_D3hot);
319162306a36Sopenharmony_ci}
319262306a36Sopenharmony_ci
319362306a36Sopenharmony_cistatic int __maybe_unused hns3_suspend(struct device *dev)
319462306a36Sopenharmony_ci{
319562306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = dev_get_drvdata(dev);
319662306a36Sopenharmony_ci
319762306a36Sopenharmony_ci	if (ae_dev && hns3_is_phys_func(ae_dev->pdev)) {
319862306a36Sopenharmony_ci		dev_info(dev, "Begin to suspend.\n");
319962306a36Sopenharmony_ci		if (ae_dev->ops && ae_dev->ops->reset_prepare)
320062306a36Sopenharmony_ci			ae_dev->ops->reset_prepare(ae_dev, HNAE3_FUNC_RESET);
320162306a36Sopenharmony_ci	}
320262306a36Sopenharmony_ci
320362306a36Sopenharmony_ci	return 0;
320462306a36Sopenharmony_ci}
320562306a36Sopenharmony_ci
320662306a36Sopenharmony_cistatic int __maybe_unused hns3_resume(struct device *dev)
320762306a36Sopenharmony_ci{
320862306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = dev_get_drvdata(dev);
320962306a36Sopenharmony_ci
321062306a36Sopenharmony_ci	if (ae_dev && hns3_is_phys_func(ae_dev->pdev)) {
321162306a36Sopenharmony_ci		dev_info(dev, "Begin to resume.\n");
321262306a36Sopenharmony_ci		if (ae_dev->ops && ae_dev->ops->reset_done)
321362306a36Sopenharmony_ci			ae_dev->ops->reset_done(ae_dev);
321462306a36Sopenharmony_ci	}
321562306a36Sopenharmony_ci
321662306a36Sopenharmony_ci	return 0;
321762306a36Sopenharmony_ci}
321862306a36Sopenharmony_ci
321962306a36Sopenharmony_cistatic pci_ers_result_t hns3_error_detected(struct pci_dev *pdev,
322062306a36Sopenharmony_ci					    pci_channel_state_t state)
322162306a36Sopenharmony_ci{
322262306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
322362306a36Sopenharmony_ci	pci_ers_result_t ret;
322462306a36Sopenharmony_ci
322562306a36Sopenharmony_ci	dev_info(&pdev->dev, "PCI error detected, state(=%u)!!\n", state);
322662306a36Sopenharmony_ci
322762306a36Sopenharmony_ci	if (state == pci_channel_io_perm_failure)
322862306a36Sopenharmony_ci		return PCI_ERS_RESULT_DISCONNECT;
322962306a36Sopenharmony_ci
323062306a36Sopenharmony_ci	if (!ae_dev || !ae_dev->ops) {
323162306a36Sopenharmony_ci		dev_err(&pdev->dev,
323262306a36Sopenharmony_ci			"Can't recover - error happened before device initialized\n");
323362306a36Sopenharmony_ci		return PCI_ERS_RESULT_NONE;
323462306a36Sopenharmony_ci	}
323562306a36Sopenharmony_ci
323662306a36Sopenharmony_ci	if (ae_dev->ops->handle_hw_ras_error)
323762306a36Sopenharmony_ci		ret = ae_dev->ops->handle_hw_ras_error(ae_dev);
323862306a36Sopenharmony_ci	else
323962306a36Sopenharmony_ci		return PCI_ERS_RESULT_NONE;
324062306a36Sopenharmony_ci
324162306a36Sopenharmony_ci	return ret;
324262306a36Sopenharmony_ci}
324362306a36Sopenharmony_ci
324462306a36Sopenharmony_cistatic pci_ers_result_t hns3_slot_reset(struct pci_dev *pdev)
324562306a36Sopenharmony_ci{
324662306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
324762306a36Sopenharmony_ci	const struct hnae3_ae_ops *ops;
324862306a36Sopenharmony_ci	enum hnae3_reset_type reset_type;
324962306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
325062306a36Sopenharmony_ci
325162306a36Sopenharmony_ci	if (!ae_dev || !ae_dev->ops)
325262306a36Sopenharmony_ci		return PCI_ERS_RESULT_NONE;
325362306a36Sopenharmony_ci
325462306a36Sopenharmony_ci	ops = ae_dev->ops;
325562306a36Sopenharmony_ci	/* request the reset */
325662306a36Sopenharmony_ci	if (ops->reset_event && ops->get_reset_level &&
325762306a36Sopenharmony_ci	    ops->set_default_reset_request) {
325862306a36Sopenharmony_ci		if (ae_dev->hw_err_reset_req) {
325962306a36Sopenharmony_ci			reset_type = ops->get_reset_level(ae_dev,
326062306a36Sopenharmony_ci						&ae_dev->hw_err_reset_req);
326162306a36Sopenharmony_ci			ops->set_default_reset_request(ae_dev, reset_type);
326262306a36Sopenharmony_ci			dev_info(dev, "requesting reset due to PCI error\n");
326362306a36Sopenharmony_ci			ops->reset_event(pdev, NULL);
326462306a36Sopenharmony_ci		}
326562306a36Sopenharmony_ci
326662306a36Sopenharmony_ci		return PCI_ERS_RESULT_RECOVERED;
326762306a36Sopenharmony_ci	}
326862306a36Sopenharmony_ci
326962306a36Sopenharmony_ci	return PCI_ERS_RESULT_DISCONNECT;
327062306a36Sopenharmony_ci}
327162306a36Sopenharmony_ci
327262306a36Sopenharmony_cistatic void hns3_reset_prepare(struct pci_dev *pdev)
327362306a36Sopenharmony_ci{
327462306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
327562306a36Sopenharmony_ci
327662306a36Sopenharmony_ci	dev_info(&pdev->dev, "FLR prepare\n");
327762306a36Sopenharmony_ci	if (ae_dev && ae_dev->ops && ae_dev->ops->reset_prepare)
327862306a36Sopenharmony_ci		ae_dev->ops->reset_prepare(ae_dev, HNAE3_FLR_RESET);
327962306a36Sopenharmony_ci}
328062306a36Sopenharmony_ci
328162306a36Sopenharmony_cistatic void hns3_reset_done(struct pci_dev *pdev)
328262306a36Sopenharmony_ci{
328362306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
328462306a36Sopenharmony_ci
328562306a36Sopenharmony_ci	dev_info(&pdev->dev, "FLR done\n");
328662306a36Sopenharmony_ci	if (ae_dev && ae_dev->ops && ae_dev->ops->reset_done)
328762306a36Sopenharmony_ci		ae_dev->ops->reset_done(ae_dev);
328862306a36Sopenharmony_ci}
328962306a36Sopenharmony_ci
329062306a36Sopenharmony_cistatic const struct pci_error_handlers hns3_err_handler = {
329162306a36Sopenharmony_ci	.error_detected = hns3_error_detected,
329262306a36Sopenharmony_ci	.slot_reset     = hns3_slot_reset,
329362306a36Sopenharmony_ci	.reset_prepare	= hns3_reset_prepare,
329462306a36Sopenharmony_ci	.reset_done	= hns3_reset_done,
329562306a36Sopenharmony_ci};
329662306a36Sopenharmony_ci
329762306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(hns3_pm_ops, hns3_suspend, hns3_resume);
329862306a36Sopenharmony_ci
329962306a36Sopenharmony_cistatic struct pci_driver hns3_driver = {
330062306a36Sopenharmony_ci	.name     = hns3_driver_name,
330162306a36Sopenharmony_ci	.id_table = hns3_pci_tbl,
330262306a36Sopenharmony_ci	.probe    = hns3_probe,
330362306a36Sopenharmony_ci	.remove   = hns3_remove,
330462306a36Sopenharmony_ci	.shutdown = hns3_shutdown,
330562306a36Sopenharmony_ci	.driver.pm  = &hns3_pm_ops,
330662306a36Sopenharmony_ci	.sriov_configure = hns3_pci_sriov_configure,
330762306a36Sopenharmony_ci	.err_handler    = &hns3_err_handler,
330862306a36Sopenharmony_ci};
330962306a36Sopenharmony_ci
331062306a36Sopenharmony_ci/* set default feature to hns3 */
331162306a36Sopenharmony_cistatic void hns3_set_default_feature(struct net_device *netdev)
331262306a36Sopenharmony_ci{
331362306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
331462306a36Sopenharmony_ci	struct pci_dev *pdev = h->pdev;
331562306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
331662306a36Sopenharmony_ci
331762306a36Sopenharmony_ci	netdev->priv_flags |= IFF_UNICAST_FLT;
331862306a36Sopenharmony_ci
331962306a36Sopenharmony_ci	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER |
332062306a36Sopenharmony_ci		NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
332162306a36Sopenharmony_ci		NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
332262306a36Sopenharmony_ci		NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE |
332362306a36Sopenharmony_ci		NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
332462306a36Sopenharmony_ci		NETIF_F_SCTP_CRC | NETIF_F_FRAGLIST;
332562306a36Sopenharmony_ci
332662306a36Sopenharmony_ci	if (hnae3_ae_dev_gro_supported(ae_dev))
332762306a36Sopenharmony_ci		netdev->features |= NETIF_F_GRO_HW;
332862306a36Sopenharmony_ci
332962306a36Sopenharmony_ci	if (hnae3_ae_dev_fd_supported(ae_dev))
333062306a36Sopenharmony_ci		netdev->features |= NETIF_F_NTUPLE;
333162306a36Sopenharmony_ci
333262306a36Sopenharmony_ci	if (test_bit(HNAE3_DEV_SUPPORT_UDP_GSO_B, ae_dev->caps))
333362306a36Sopenharmony_ci		netdev->features |= NETIF_F_GSO_UDP_L4;
333462306a36Sopenharmony_ci
333562306a36Sopenharmony_ci	if (test_bit(HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, ae_dev->caps))
333662306a36Sopenharmony_ci		netdev->features |= NETIF_F_HW_CSUM;
333762306a36Sopenharmony_ci	else
333862306a36Sopenharmony_ci		netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
333962306a36Sopenharmony_ci
334062306a36Sopenharmony_ci	if (test_bit(HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, ae_dev->caps))
334162306a36Sopenharmony_ci		netdev->features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
334262306a36Sopenharmony_ci
334362306a36Sopenharmony_ci	if (test_bit(HNAE3_DEV_SUPPORT_FD_FORWARD_TC_B, ae_dev->caps))
334462306a36Sopenharmony_ci		netdev->features |= NETIF_F_HW_TC;
334562306a36Sopenharmony_ci
334662306a36Sopenharmony_ci	netdev->hw_features |= netdev->features;
334762306a36Sopenharmony_ci	if (!test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps))
334862306a36Sopenharmony_ci		netdev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
334962306a36Sopenharmony_ci
335062306a36Sopenharmony_ci	netdev->vlan_features |= netdev->features &
335162306a36Sopenharmony_ci		~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_TX |
335262306a36Sopenharmony_ci		  NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_GRO_HW | NETIF_F_NTUPLE |
335362306a36Sopenharmony_ci		  NETIF_F_HW_TC);
335462306a36Sopenharmony_ci
335562306a36Sopenharmony_ci	netdev->hw_enc_features |= netdev->vlan_features | NETIF_F_TSO_MANGLEID;
335662306a36Sopenharmony_ci
335762306a36Sopenharmony_ci	/* The device_version V3 hardware can't offload the checksum for IP in
335862306a36Sopenharmony_ci	 * GRE packets, but can do it for NvGRE. So default to disable the
335962306a36Sopenharmony_ci	 * checksum and GSO offload for GRE.
336062306a36Sopenharmony_ci	 */
336162306a36Sopenharmony_ci	if (ae_dev->dev_version > HNAE3_DEVICE_VERSION_V2) {
336262306a36Sopenharmony_ci		netdev->features &= ~NETIF_F_GSO_GRE;
336362306a36Sopenharmony_ci		netdev->features &= ~NETIF_F_GSO_GRE_CSUM;
336462306a36Sopenharmony_ci	}
336562306a36Sopenharmony_ci}
336662306a36Sopenharmony_ci
336762306a36Sopenharmony_cistatic int hns3_alloc_buffer(struct hns3_enet_ring *ring,
336862306a36Sopenharmony_ci			     struct hns3_desc_cb *cb)
336962306a36Sopenharmony_ci{
337062306a36Sopenharmony_ci	unsigned int order = hns3_page_order(ring);
337162306a36Sopenharmony_ci	struct page *p;
337262306a36Sopenharmony_ci
337362306a36Sopenharmony_ci	if (ring->page_pool) {
337462306a36Sopenharmony_ci		p = page_pool_dev_alloc_frag(ring->page_pool,
337562306a36Sopenharmony_ci					     &cb->page_offset,
337662306a36Sopenharmony_ci					     hns3_buf_size(ring));
337762306a36Sopenharmony_ci		if (unlikely(!p))
337862306a36Sopenharmony_ci			return -ENOMEM;
337962306a36Sopenharmony_ci
338062306a36Sopenharmony_ci		cb->priv = p;
338162306a36Sopenharmony_ci		cb->buf = page_address(p);
338262306a36Sopenharmony_ci		cb->dma = page_pool_get_dma_addr(p);
338362306a36Sopenharmony_ci		cb->type = DESC_TYPE_PP_FRAG;
338462306a36Sopenharmony_ci		cb->reuse_flag = 0;
338562306a36Sopenharmony_ci		return 0;
338662306a36Sopenharmony_ci	}
338762306a36Sopenharmony_ci
338862306a36Sopenharmony_ci	p = dev_alloc_pages(order);
338962306a36Sopenharmony_ci	if (!p)
339062306a36Sopenharmony_ci		return -ENOMEM;
339162306a36Sopenharmony_ci
339262306a36Sopenharmony_ci	cb->priv = p;
339362306a36Sopenharmony_ci	cb->page_offset = 0;
339462306a36Sopenharmony_ci	cb->reuse_flag = 0;
339562306a36Sopenharmony_ci	cb->buf  = page_address(p);
339662306a36Sopenharmony_ci	cb->length = hns3_page_size(ring);
339762306a36Sopenharmony_ci	cb->type = DESC_TYPE_PAGE;
339862306a36Sopenharmony_ci	page_ref_add(p, USHRT_MAX - 1);
339962306a36Sopenharmony_ci	cb->pagecnt_bias = USHRT_MAX;
340062306a36Sopenharmony_ci
340162306a36Sopenharmony_ci	return 0;
340262306a36Sopenharmony_ci}
340362306a36Sopenharmony_ci
340462306a36Sopenharmony_cistatic void hns3_free_buffer(struct hns3_enet_ring *ring,
340562306a36Sopenharmony_ci			     struct hns3_desc_cb *cb, int budget)
340662306a36Sopenharmony_ci{
340762306a36Sopenharmony_ci	if (cb->type & (DESC_TYPE_SKB | DESC_TYPE_BOUNCE_HEAD |
340862306a36Sopenharmony_ci			DESC_TYPE_BOUNCE_ALL | DESC_TYPE_SGL_SKB))
340962306a36Sopenharmony_ci		napi_consume_skb(cb->priv, budget);
341062306a36Sopenharmony_ci	else if (!HNAE3_IS_TX_RING(ring)) {
341162306a36Sopenharmony_ci		if (cb->type & DESC_TYPE_PAGE && cb->pagecnt_bias)
341262306a36Sopenharmony_ci			__page_frag_cache_drain(cb->priv, cb->pagecnt_bias);
341362306a36Sopenharmony_ci		else if (cb->type & DESC_TYPE_PP_FRAG)
341462306a36Sopenharmony_ci			page_pool_put_full_page(ring->page_pool, cb->priv,
341562306a36Sopenharmony_ci						false);
341662306a36Sopenharmony_ci	}
341762306a36Sopenharmony_ci	memset(cb, 0, sizeof(*cb));
341862306a36Sopenharmony_ci}
341962306a36Sopenharmony_ci
342062306a36Sopenharmony_cistatic int hns3_map_buffer(struct hns3_enet_ring *ring, struct hns3_desc_cb *cb)
342162306a36Sopenharmony_ci{
342262306a36Sopenharmony_ci	cb->dma = dma_map_page(ring_to_dev(ring), cb->priv, 0,
342362306a36Sopenharmony_ci			       cb->length, ring_to_dma_dir(ring));
342462306a36Sopenharmony_ci
342562306a36Sopenharmony_ci	if (unlikely(dma_mapping_error(ring_to_dev(ring), cb->dma)))
342662306a36Sopenharmony_ci		return -EIO;
342762306a36Sopenharmony_ci
342862306a36Sopenharmony_ci	return 0;
342962306a36Sopenharmony_ci}
343062306a36Sopenharmony_ci
343162306a36Sopenharmony_cistatic void hns3_unmap_buffer(struct hns3_enet_ring *ring,
343262306a36Sopenharmony_ci			      struct hns3_desc_cb *cb)
343362306a36Sopenharmony_ci{
343462306a36Sopenharmony_ci	if (cb->type & (DESC_TYPE_SKB | DESC_TYPE_FRAGLIST_SKB))
343562306a36Sopenharmony_ci		dma_unmap_single(ring_to_dev(ring), cb->dma, cb->length,
343662306a36Sopenharmony_ci				 ring_to_dma_dir(ring));
343762306a36Sopenharmony_ci	else if ((cb->type & DESC_TYPE_PAGE) && cb->length)
343862306a36Sopenharmony_ci		dma_unmap_page(ring_to_dev(ring), cb->dma, cb->length,
343962306a36Sopenharmony_ci			       ring_to_dma_dir(ring));
344062306a36Sopenharmony_ci	else if (cb->type & (DESC_TYPE_BOUNCE_ALL | DESC_TYPE_BOUNCE_HEAD |
344162306a36Sopenharmony_ci			     DESC_TYPE_SGL_SKB))
344262306a36Sopenharmony_ci		hns3_tx_spare_reclaim_cb(ring, cb);
344362306a36Sopenharmony_ci}
344462306a36Sopenharmony_ci
344562306a36Sopenharmony_cistatic void hns3_buffer_detach(struct hns3_enet_ring *ring, int i)
344662306a36Sopenharmony_ci{
344762306a36Sopenharmony_ci	hns3_unmap_buffer(ring, &ring->desc_cb[i]);
344862306a36Sopenharmony_ci	ring->desc[i].addr = 0;
344962306a36Sopenharmony_ci	ring->desc_cb[i].refill = 0;
345062306a36Sopenharmony_ci}
345162306a36Sopenharmony_ci
345262306a36Sopenharmony_cistatic void hns3_free_buffer_detach(struct hns3_enet_ring *ring, int i,
345362306a36Sopenharmony_ci				    int budget)
345462306a36Sopenharmony_ci{
345562306a36Sopenharmony_ci	struct hns3_desc_cb *cb = &ring->desc_cb[i];
345662306a36Sopenharmony_ci
345762306a36Sopenharmony_ci	if (!ring->desc_cb[i].dma)
345862306a36Sopenharmony_ci		return;
345962306a36Sopenharmony_ci
346062306a36Sopenharmony_ci	hns3_buffer_detach(ring, i);
346162306a36Sopenharmony_ci	hns3_free_buffer(ring, cb, budget);
346262306a36Sopenharmony_ci}
346362306a36Sopenharmony_ci
346462306a36Sopenharmony_cistatic void hns3_free_buffers(struct hns3_enet_ring *ring)
346562306a36Sopenharmony_ci{
346662306a36Sopenharmony_ci	int i;
346762306a36Sopenharmony_ci
346862306a36Sopenharmony_ci	for (i = 0; i < ring->desc_num; i++)
346962306a36Sopenharmony_ci		hns3_free_buffer_detach(ring, i, 0);
347062306a36Sopenharmony_ci}
347162306a36Sopenharmony_ci
347262306a36Sopenharmony_ci/* free desc along with its attached buffer */
347362306a36Sopenharmony_cistatic void hns3_free_desc(struct hns3_enet_ring *ring)
347462306a36Sopenharmony_ci{
347562306a36Sopenharmony_ci	int size = ring->desc_num * sizeof(ring->desc[0]);
347662306a36Sopenharmony_ci
347762306a36Sopenharmony_ci	hns3_free_buffers(ring);
347862306a36Sopenharmony_ci
347962306a36Sopenharmony_ci	if (ring->desc) {
348062306a36Sopenharmony_ci		dma_free_coherent(ring_to_dev(ring), size,
348162306a36Sopenharmony_ci				  ring->desc, ring->desc_dma_addr);
348262306a36Sopenharmony_ci		ring->desc = NULL;
348362306a36Sopenharmony_ci	}
348462306a36Sopenharmony_ci}
348562306a36Sopenharmony_ci
348662306a36Sopenharmony_cistatic int hns3_alloc_desc(struct hns3_enet_ring *ring)
348762306a36Sopenharmony_ci{
348862306a36Sopenharmony_ci	int size = ring->desc_num * sizeof(ring->desc[0]);
348962306a36Sopenharmony_ci
349062306a36Sopenharmony_ci	ring->desc = dma_alloc_coherent(ring_to_dev(ring), size,
349162306a36Sopenharmony_ci					&ring->desc_dma_addr, GFP_KERNEL);
349262306a36Sopenharmony_ci	if (!ring->desc)
349362306a36Sopenharmony_ci		return -ENOMEM;
349462306a36Sopenharmony_ci
349562306a36Sopenharmony_ci	return 0;
349662306a36Sopenharmony_ci}
349762306a36Sopenharmony_ci
349862306a36Sopenharmony_cistatic int hns3_alloc_and_map_buffer(struct hns3_enet_ring *ring,
349962306a36Sopenharmony_ci				   struct hns3_desc_cb *cb)
350062306a36Sopenharmony_ci{
350162306a36Sopenharmony_ci	int ret;
350262306a36Sopenharmony_ci
350362306a36Sopenharmony_ci	ret = hns3_alloc_buffer(ring, cb);
350462306a36Sopenharmony_ci	if (ret || ring->page_pool)
350562306a36Sopenharmony_ci		goto out;
350662306a36Sopenharmony_ci
350762306a36Sopenharmony_ci	ret = hns3_map_buffer(ring, cb);
350862306a36Sopenharmony_ci	if (ret)
350962306a36Sopenharmony_ci		goto out_with_buf;
351062306a36Sopenharmony_ci
351162306a36Sopenharmony_ci	return 0;
351262306a36Sopenharmony_ci
351362306a36Sopenharmony_ciout_with_buf:
351462306a36Sopenharmony_ci	hns3_free_buffer(ring, cb, 0);
351562306a36Sopenharmony_ciout:
351662306a36Sopenharmony_ci	return ret;
351762306a36Sopenharmony_ci}
351862306a36Sopenharmony_ci
351962306a36Sopenharmony_cistatic int hns3_alloc_and_attach_buffer(struct hns3_enet_ring *ring, int i)
352062306a36Sopenharmony_ci{
352162306a36Sopenharmony_ci	int ret = hns3_alloc_and_map_buffer(ring, &ring->desc_cb[i]);
352262306a36Sopenharmony_ci
352362306a36Sopenharmony_ci	if (ret)
352462306a36Sopenharmony_ci		return ret;
352562306a36Sopenharmony_ci
352662306a36Sopenharmony_ci	ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma +
352762306a36Sopenharmony_ci					 ring->desc_cb[i].page_offset);
352862306a36Sopenharmony_ci	ring->desc_cb[i].refill = 1;
352962306a36Sopenharmony_ci
353062306a36Sopenharmony_ci	return 0;
353162306a36Sopenharmony_ci}
353262306a36Sopenharmony_ci
353362306a36Sopenharmony_ci/* Allocate memory for raw pkg, and map with dma */
353462306a36Sopenharmony_cistatic int hns3_alloc_ring_buffers(struct hns3_enet_ring *ring)
353562306a36Sopenharmony_ci{
353662306a36Sopenharmony_ci	int i, j, ret;
353762306a36Sopenharmony_ci
353862306a36Sopenharmony_ci	for (i = 0; i < ring->desc_num; i++) {
353962306a36Sopenharmony_ci		ret = hns3_alloc_and_attach_buffer(ring, i);
354062306a36Sopenharmony_ci		if (ret)
354162306a36Sopenharmony_ci			goto out_buffer_fail;
354262306a36Sopenharmony_ci	}
354362306a36Sopenharmony_ci
354462306a36Sopenharmony_ci	return 0;
354562306a36Sopenharmony_ci
354662306a36Sopenharmony_ciout_buffer_fail:
354762306a36Sopenharmony_ci	for (j = i - 1; j >= 0; j--)
354862306a36Sopenharmony_ci		hns3_free_buffer_detach(ring, j, 0);
354962306a36Sopenharmony_ci	return ret;
355062306a36Sopenharmony_ci}
355162306a36Sopenharmony_ci
355262306a36Sopenharmony_ci/* detach a in-used buffer and replace with a reserved one */
355362306a36Sopenharmony_cistatic void hns3_replace_buffer(struct hns3_enet_ring *ring, int i,
355462306a36Sopenharmony_ci				struct hns3_desc_cb *res_cb)
355562306a36Sopenharmony_ci{
355662306a36Sopenharmony_ci	hns3_unmap_buffer(ring, &ring->desc_cb[i]);
355762306a36Sopenharmony_ci	ring->desc_cb[i] = *res_cb;
355862306a36Sopenharmony_ci	ring->desc_cb[i].refill = 1;
355962306a36Sopenharmony_ci	ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma +
356062306a36Sopenharmony_ci					 ring->desc_cb[i].page_offset);
356162306a36Sopenharmony_ci	ring->desc[i].rx.bd_base_info = 0;
356262306a36Sopenharmony_ci}
356362306a36Sopenharmony_ci
356462306a36Sopenharmony_cistatic void hns3_reuse_buffer(struct hns3_enet_ring *ring, int i)
356562306a36Sopenharmony_ci{
356662306a36Sopenharmony_ci	ring->desc_cb[i].reuse_flag = 0;
356762306a36Sopenharmony_ci	ring->desc_cb[i].refill = 1;
356862306a36Sopenharmony_ci	ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma +
356962306a36Sopenharmony_ci					 ring->desc_cb[i].page_offset);
357062306a36Sopenharmony_ci	ring->desc[i].rx.bd_base_info = 0;
357162306a36Sopenharmony_ci
357262306a36Sopenharmony_ci	dma_sync_single_for_device(ring_to_dev(ring),
357362306a36Sopenharmony_ci			ring->desc_cb[i].dma + ring->desc_cb[i].page_offset,
357462306a36Sopenharmony_ci			hns3_buf_size(ring),
357562306a36Sopenharmony_ci			DMA_FROM_DEVICE);
357662306a36Sopenharmony_ci}
357762306a36Sopenharmony_ci
357862306a36Sopenharmony_cistatic bool hns3_nic_reclaim_desc(struct hns3_enet_ring *ring,
357962306a36Sopenharmony_ci				  int *bytes, int *pkts, int budget)
358062306a36Sopenharmony_ci{
358162306a36Sopenharmony_ci	/* This smp_load_acquire() pairs with smp_store_release() in
358262306a36Sopenharmony_ci	 * hns3_tx_doorbell().
358362306a36Sopenharmony_ci	 */
358462306a36Sopenharmony_ci	int ltu = smp_load_acquire(&ring->last_to_use);
358562306a36Sopenharmony_ci	int ntc = ring->next_to_clean;
358662306a36Sopenharmony_ci	struct hns3_desc_cb *desc_cb;
358762306a36Sopenharmony_ci	bool reclaimed = false;
358862306a36Sopenharmony_ci	struct hns3_desc *desc;
358962306a36Sopenharmony_ci
359062306a36Sopenharmony_ci	while (ltu != ntc) {
359162306a36Sopenharmony_ci		desc = &ring->desc[ntc];
359262306a36Sopenharmony_ci
359362306a36Sopenharmony_ci		if (le16_to_cpu(desc->tx.bdtp_fe_sc_vld_ra_ri) &
359462306a36Sopenharmony_ci				BIT(HNS3_TXD_VLD_B))
359562306a36Sopenharmony_ci			break;
359662306a36Sopenharmony_ci
359762306a36Sopenharmony_ci		desc_cb = &ring->desc_cb[ntc];
359862306a36Sopenharmony_ci
359962306a36Sopenharmony_ci		if (desc_cb->type & (DESC_TYPE_SKB | DESC_TYPE_BOUNCE_ALL |
360062306a36Sopenharmony_ci				     DESC_TYPE_BOUNCE_HEAD |
360162306a36Sopenharmony_ci				     DESC_TYPE_SGL_SKB)) {
360262306a36Sopenharmony_ci			(*pkts)++;
360362306a36Sopenharmony_ci			(*bytes) += desc_cb->send_bytes;
360462306a36Sopenharmony_ci		}
360562306a36Sopenharmony_ci
360662306a36Sopenharmony_ci		/* desc_cb will be cleaned, after hnae3_free_buffer_detach */
360762306a36Sopenharmony_ci		hns3_free_buffer_detach(ring, ntc, budget);
360862306a36Sopenharmony_ci
360962306a36Sopenharmony_ci		if (++ntc == ring->desc_num)
361062306a36Sopenharmony_ci			ntc = 0;
361162306a36Sopenharmony_ci
361262306a36Sopenharmony_ci		/* Issue prefetch for next Tx descriptor */
361362306a36Sopenharmony_ci		prefetch(&ring->desc_cb[ntc]);
361462306a36Sopenharmony_ci		reclaimed = true;
361562306a36Sopenharmony_ci	}
361662306a36Sopenharmony_ci
361762306a36Sopenharmony_ci	if (unlikely(!reclaimed))
361862306a36Sopenharmony_ci		return false;
361962306a36Sopenharmony_ci
362062306a36Sopenharmony_ci	/* This smp_store_release() pairs with smp_load_acquire() in
362162306a36Sopenharmony_ci	 * ring_space called by hns3_nic_net_xmit.
362262306a36Sopenharmony_ci	 */
362362306a36Sopenharmony_ci	smp_store_release(&ring->next_to_clean, ntc);
362462306a36Sopenharmony_ci
362562306a36Sopenharmony_ci	hns3_tx_spare_update(ring);
362662306a36Sopenharmony_ci
362762306a36Sopenharmony_ci	return true;
362862306a36Sopenharmony_ci}
362962306a36Sopenharmony_ci
363062306a36Sopenharmony_civoid hns3_clean_tx_ring(struct hns3_enet_ring *ring, int budget)
363162306a36Sopenharmony_ci{
363262306a36Sopenharmony_ci	struct net_device *netdev = ring_to_netdev(ring);
363362306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
363462306a36Sopenharmony_ci	struct netdev_queue *dev_queue;
363562306a36Sopenharmony_ci	int bytes, pkts;
363662306a36Sopenharmony_ci
363762306a36Sopenharmony_ci	bytes = 0;
363862306a36Sopenharmony_ci	pkts = 0;
363962306a36Sopenharmony_ci
364062306a36Sopenharmony_ci	if (unlikely(!hns3_nic_reclaim_desc(ring, &bytes, &pkts, budget)))
364162306a36Sopenharmony_ci		return;
364262306a36Sopenharmony_ci
364362306a36Sopenharmony_ci	ring->tqp_vector->tx_group.total_bytes += bytes;
364462306a36Sopenharmony_ci	ring->tqp_vector->tx_group.total_packets += pkts;
364562306a36Sopenharmony_ci
364662306a36Sopenharmony_ci	u64_stats_update_begin(&ring->syncp);
364762306a36Sopenharmony_ci	ring->stats.tx_bytes += bytes;
364862306a36Sopenharmony_ci	ring->stats.tx_pkts += pkts;
364962306a36Sopenharmony_ci	u64_stats_update_end(&ring->syncp);
365062306a36Sopenharmony_ci
365162306a36Sopenharmony_ci	dev_queue = netdev_get_tx_queue(netdev, ring->tqp->tqp_index);
365262306a36Sopenharmony_ci	netdev_tx_completed_queue(dev_queue, pkts, bytes);
365362306a36Sopenharmony_ci
365462306a36Sopenharmony_ci	if (unlikely(netif_carrier_ok(netdev) &&
365562306a36Sopenharmony_ci		     ring_space(ring) > HNS3_MAX_TSO_BD_NUM)) {
365662306a36Sopenharmony_ci		/* Make sure that anybody stopping the queue after this
365762306a36Sopenharmony_ci		 * sees the new next_to_clean.
365862306a36Sopenharmony_ci		 */
365962306a36Sopenharmony_ci		smp_mb();
366062306a36Sopenharmony_ci		if (netif_tx_queue_stopped(dev_queue) &&
366162306a36Sopenharmony_ci		    !test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) {
366262306a36Sopenharmony_ci			netif_tx_wake_queue(dev_queue);
366362306a36Sopenharmony_ci			ring->stats.restart_queue++;
366462306a36Sopenharmony_ci		}
366562306a36Sopenharmony_ci	}
366662306a36Sopenharmony_ci}
366762306a36Sopenharmony_ci
366862306a36Sopenharmony_cistatic int hns3_desc_unused(struct hns3_enet_ring *ring)
366962306a36Sopenharmony_ci{
367062306a36Sopenharmony_ci	int ntc = ring->next_to_clean;
367162306a36Sopenharmony_ci	int ntu = ring->next_to_use;
367262306a36Sopenharmony_ci
367362306a36Sopenharmony_ci	if (unlikely(ntc == ntu && !ring->desc_cb[ntc].refill))
367462306a36Sopenharmony_ci		return ring->desc_num;
367562306a36Sopenharmony_ci
367662306a36Sopenharmony_ci	return ((ntc >= ntu) ? 0 : ring->desc_num) + ntc - ntu;
367762306a36Sopenharmony_ci}
367862306a36Sopenharmony_ci
367962306a36Sopenharmony_ci/* Return true if there is any allocation failure */
368062306a36Sopenharmony_cistatic bool hns3_nic_alloc_rx_buffers(struct hns3_enet_ring *ring,
368162306a36Sopenharmony_ci				      int cleand_count)
368262306a36Sopenharmony_ci{
368362306a36Sopenharmony_ci	struct hns3_desc_cb *desc_cb;
368462306a36Sopenharmony_ci	struct hns3_desc_cb res_cbs;
368562306a36Sopenharmony_ci	int i, ret;
368662306a36Sopenharmony_ci
368762306a36Sopenharmony_ci	for (i = 0; i < cleand_count; i++) {
368862306a36Sopenharmony_ci		desc_cb = &ring->desc_cb[ring->next_to_use];
368962306a36Sopenharmony_ci		if (desc_cb->reuse_flag) {
369062306a36Sopenharmony_ci			hns3_ring_stats_update(ring, reuse_pg_cnt);
369162306a36Sopenharmony_ci
369262306a36Sopenharmony_ci			hns3_reuse_buffer(ring, ring->next_to_use);
369362306a36Sopenharmony_ci		} else {
369462306a36Sopenharmony_ci			ret = hns3_alloc_and_map_buffer(ring, &res_cbs);
369562306a36Sopenharmony_ci			if (ret) {
369662306a36Sopenharmony_ci				hns3_ring_stats_update(ring, sw_err_cnt);
369762306a36Sopenharmony_ci
369862306a36Sopenharmony_ci				hns3_rl_err(ring_to_netdev(ring),
369962306a36Sopenharmony_ci					    "alloc rx buffer failed: %d\n",
370062306a36Sopenharmony_ci					    ret);
370162306a36Sopenharmony_ci
370262306a36Sopenharmony_ci				writel(i, ring->tqp->io_base +
370362306a36Sopenharmony_ci				       HNS3_RING_RX_RING_HEAD_REG);
370462306a36Sopenharmony_ci				return true;
370562306a36Sopenharmony_ci			}
370662306a36Sopenharmony_ci			hns3_replace_buffer(ring, ring->next_to_use, &res_cbs);
370762306a36Sopenharmony_ci
370862306a36Sopenharmony_ci			hns3_ring_stats_update(ring, non_reuse_pg);
370962306a36Sopenharmony_ci		}
371062306a36Sopenharmony_ci
371162306a36Sopenharmony_ci		ring_ptr_move_fw(ring, next_to_use);
371262306a36Sopenharmony_ci	}
371362306a36Sopenharmony_ci
371462306a36Sopenharmony_ci	writel(i, ring->tqp->io_base + HNS3_RING_RX_RING_HEAD_REG);
371562306a36Sopenharmony_ci	return false;
371662306a36Sopenharmony_ci}
371762306a36Sopenharmony_ci
371862306a36Sopenharmony_cistatic bool hns3_can_reuse_page(struct hns3_desc_cb *cb)
371962306a36Sopenharmony_ci{
372062306a36Sopenharmony_ci	return page_count(cb->priv) == cb->pagecnt_bias;
372162306a36Sopenharmony_ci}
372262306a36Sopenharmony_ci
372362306a36Sopenharmony_cistatic int hns3_handle_rx_copybreak(struct sk_buff *skb, int i,
372462306a36Sopenharmony_ci				    struct hns3_enet_ring *ring,
372562306a36Sopenharmony_ci				    int pull_len,
372662306a36Sopenharmony_ci				    struct hns3_desc_cb *desc_cb)
372762306a36Sopenharmony_ci{
372862306a36Sopenharmony_ci	struct hns3_desc *desc = &ring->desc[ring->next_to_clean];
372962306a36Sopenharmony_ci	u32 frag_offset = desc_cb->page_offset + pull_len;
373062306a36Sopenharmony_ci	int size = le16_to_cpu(desc->rx.size);
373162306a36Sopenharmony_ci	u32 frag_size = size - pull_len;
373262306a36Sopenharmony_ci	void *frag = napi_alloc_frag(frag_size);
373362306a36Sopenharmony_ci
373462306a36Sopenharmony_ci	if (unlikely(!frag)) {
373562306a36Sopenharmony_ci		hns3_ring_stats_update(ring, frag_alloc_err);
373662306a36Sopenharmony_ci
373762306a36Sopenharmony_ci		hns3_rl_err(ring_to_netdev(ring),
373862306a36Sopenharmony_ci			    "failed to allocate rx frag\n");
373962306a36Sopenharmony_ci		return -ENOMEM;
374062306a36Sopenharmony_ci	}
374162306a36Sopenharmony_ci
374262306a36Sopenharmony_ci	desc_cb->reuse_flag = 1;
374362306a36Sopenharmony_ci	memcpy(frag, desc_cb->buf + frag_offset, frag_size);
374462306a36Sopenharmony_ci	skb_add_rx_frag(skb, i, virt_to_page(frag),
374562306a36Sopenharmony_ci			offset_in_page(frag), frag_size, frag_size);
374662306a36Sopenharmony_ci
374762306a36Sopenharmony_ci	hns3_ring_stats_update(ring, frag_alloc);
374862306a36Sopenharmony_ci	return 0;
374962306a36Sopenharmony_ci}
375062306a36Sopenharmony_ci
375162306a36Sopenharmony_cistatic void hns3_nic_reuse_page(struct sk_buff *skb, int i,
375262306a36Sopenharmony_ci				struct hns3_enet_ring *ring, int pull_len,
375362306a36Sopenharmony_ci				struct hns3_desc_cb *desc_cb)
375462306a36Sopenharmony_ci{
375562306a36Sopenharmony_ci	struct hns3_desc *desc = &ring->desc[ring->next_to_clean];
375662306a36Sopenharmony_ci	u32 frag_offset = desc_cb->page_offset + pull_len;
375762306a36Sopenharmony_ci	int size = le16_to_cpu(desc->rx.size);
375862306a36Sopenharmony_ci	u32 truesize = hns3_buf_size(ring);
375962306a36Sopenharmony_ci	u32 frag_size = size - pull_len;
376062306a36Sopenharmony_ci	int ret = 0;
376162306a36Sopenharmony_ci	bool reused;
376262306a36Sopenharmony_ci
376362306a36Sopenharmony_ci	if (ring->page_pool) {
376462306a36Sopenharmony_ci		skb_add_rx_frag(skb, i, desc_cb->priv, frag_offset,
376562306a36Sopenharmony_ci				frag_size, truesize);
376662306a36Sopenharmony_ci		return;
376762306a36Sopenharmony_ci	}
376862306a36Sopenharmony_ci
376962306a36Sopenharmony_ci	/* Avoid re-using remote or pfmem page */
377062306a36Sopenharmony_ci	if (unlikely(!dev_page_is_reusable(desc_cb->priv)))
377162306a36Sopenharmony_ci		goto out;
377262306a36Sopenharmony_ci
377362306a36Sopenharmony_ci	reused = hns3_can_reuse_page(desc_cb);
377462306a36Sopenharmony_ci
377562306a36Sopenharmony_ci	/* Rx page can be reused when:
377662306a36Sopenharmony_ci	 * 1. Rx page is only owned by the driver when page_offset
377762306a36Sopenharmony_ci	 *    is zero, which means 0 @ truesize will be used by
377862306a36Sopenharmony_ci	 *    stack after skb_add_rx_frag() is called, and the rest
377962306a36Sopenharmony_ci	 *    of rx page can be reused by driver.
378062306a36Sopenharmony_ci	 * Or
378162306a36Sopenharmony_ci	 * 2. Rx page is only owned by the driver when page_offset
378262306a36Sopenharmony_ci	 *    is non-zero, which means page_offset @ truesize will
378362306a36Sopenharmony_ci	 *    be used by stack after skb_add_rx_frag() is called,
378462306a36Sopenharmony_ci	 *    and 0 @ truesize can be reused by driver.
378562306a36Sopenharmony_ci	 */
378662306a36Sopenharmony_ci	if ((!desc_cb->page_offset && reused) ||
378762306a36Sopenharmony_ci	    ((desc_cb->page_offset + truesize + truesize) <=
378862306a36Sopenharmony_ci	     hns3_page_size(ring) && desc_cb->page_offset)) {
378962306a36Sopenharmony_ci		desc_cb->page_offset += truesize;
379062306a36Sopenharmony_ci		desc_cb->reuse_flag = 1;
379162306a36Sopenharmony_ci	} else if (desc_cb->page_offset && reused) {
379262306a36Sopenharmony_ci		desc_cb->page_offset = 0;
379362306a36Sopenharmony_ci		desc_cb->reuse_flag = 1;
379462306a36Sopenharmony_ci	} else if (frag_size <= ring->rx_copybreak) {
379562306a36Sopenharmony_ci		ret = hns3_handle_rx_copybreak(skb, i, ring, pull_len, desc_cb);
379662306a36Sopenharmony_ci		if (!ret)
379762306a36Sopenharmony_ci			return;
379862306a36Sopenharmony_ci	}
379962306a36Sopenharmony_ci
380062306a36Sopenharmony_ciout:
380162306a36Sopenharmony_ci	desc_cb->pagecnt_bias--;
380262306a36Sopenharmony_ci
380362306a36Sopenharmony_ci	if (unlikely(!desc_cb->pagecnt_bias)) {
380462306a36Sopenharmony_ci		page_ref_add(desc_cb->priv, USHRT_MAX);
380562306a36Sopenharmony_ci		desc_cb->pagecnt_bias = USHRT_MAX;
380662306a36Sopenharmony_ci	}
380762306a36Sopenharmony_ci
380862306a36Sopenharmony_ci	skb_add_rx_frag(skb, i, desc_cb->priv, frag_offset,
380962306a36Sopenharmony_ci			frag_size, truesize);
381062306a36Sopenharmony_ci
381162306a36Sopenharmony_ci	if (unlikely(!desc_cb->reuse_flag))
381262306a36Sopenharmony_ci		__page_frag_cache_drain(desc_cb->priv, desc_cb->pagecnt_bias);
381362306a36Sopenharmony_ci}
381462306a36Sopenharmony_ci
381562306a36Sopenharmony_cistatic int hns3_gro_complete(struct sk_buff *skb, u32 l234info)
381662306a36Sopenharmony_ci{
381762306a36Sopenharmony_ci	__be16 type = skb->protocol;
381862306a36Sopenharmony_ci	struct tcphdr *th;
381962306a36Sopenharmony_ci	int depth = 0;
382062306a36Sopenharmony_ci
382162306a36Sopenharmony_ci	while (eth_type_vlan(type)) {
382262306a36Sopenharmony_ci		struct vlan_hdr *vh;
382362306a36Sopenharmony_ci
382462306a36Sopenharmony_ci		if ((depth + VLAN_HLEN) > skb_headlen(skb))
382562306a36Sopenharmony_ci			return -EFAULT;
382662306a36Sopenharmony_ci
382762306a36Sopenharmony_ci		vh = (struct vlan_hdr *)(skb->data + depth);
382862306a36Sopenharmony_ci		type = vh->h_vlan_encapsulated_proto;
382962306a36Sopenharmony_ci		depth += VLAN_HLEN;
383062306a36Sopenharmony_ci	}
383162306a36Sopenharmony_ci
383262306a36Sopenharmony_ci	skb_set_network_header(skb, depth);
383362306a36Sopenharmony_ci
383462306a36Sopenharmony_ci	if (type == htons(ETH_P_IP)) {
383562306a36Sopenharmony_ci		const struct iphdr *iph = ip_hdr(skb);
383662306a36Sopenharmony_ci
383762306a36Sopenharmony_ci		depth += sizeof(struct iphdr);
383862306a36Sopenharmony_ci		skb_set_transport_header(skb, depth);
383962306a36Sopenharmony_ci		th = tcp_hdr(skb);
384062306a36Sopenharmony_ci		th->check = ~tcp_v4_check(skb->len - depth, iph->saddr,
384162306a36Sopenharmony_ci					  iph->daddr, 0);
384262306a36Sopenharmony_ci	} else if (type == htons(ETH_P_IPV6)) {
384362306a36Sopenharmony_ci		const struct ipv6hdr *iph = ipv6_hdr(skb);
384462306a36Sopenharmony_ci
384562306a36Sopenharmony_ci		depth += sizeof(struct ipv6hdr);
384662306a36Sopenharmony_ci		skb_set_transport_header(skb, depth);
384762306a36Sopenharmony_ci		th = tcp_hdr(skb);
384862306a36Sopenharmony_ci		th->check = ~tcp_v6_check(skb->len - depth, &iph->saddr,
384962306a36Sopenharmony_ci					  &iph->daddr, 0);
385062306a36Sopenharmony_ci	} else {
385162306a36Sopenharmony_ci		hns3_rl_err(skb->dev,
385262306a36Sopenharmony_ci			    "Error: FW GRO supports only IPv4/IPv6, not 0x%04x, depth: %d\n",
385362306a36Sopenharmony_ci			    be16_to_cpu(type), depth);
385462306a36Sopenharmony_ci		return -EFAULT;
385562306a36Sopenharmony_ci	}
385662306a36Sopenharmony_ci
385762306a36Sopenharmony_ci	skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count;
385862306a36Sopenharmony_ci	if (th->cwr)
385962306a36Sopenharmony_ci		skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
386062306a36Sopenharmony_ci
386162306a36Sopenharmony_ci	if (l234info & BIT(HNS3_RXD_GRO_FIXID_B))
386262306a36Sopenharmony_ci		skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_FIXEDID;
386362306a36Sopenharmony_ci
386462306a36Sopenharmony_ci	skb->csum_start = (unsigned char *)th - skb->head;
386562306a36Sopenharmony_ci	skb->csum_offset = offsetof(struct tcphdr, check);
386662306a36Sopenharmony_ci	skb->ip_summed = CHECKSUM_PARTIAL;
386762306a36Sopenharmony_ci
386862306a36Sopenharmony_ci	trace_hns3_gro(skb);
386962306a36Sopenharmony_ci
387062306a36Sopenharmony_ci	return 0;
387162306a36Sopenharmony_ci}
387262306a36Sopenharmony_ci
387362306a36Sopenharmony_cistatic void hns3_checksum_complete(struct hns3_enet_ring *ring,
387462306a36Sopenharmony_ci				   struct sk_buff *skb, u32 ptype, u16 csum)
387562306a36Sopenharmony_ci{
387662306a36Sopenharmony_ci	if (ptype == HNS3_INVALID_PTYPE ||
387762306a36Sopenharmony_ci	    hns3_rx_ptype_tbl[ptype].ip_summed != CHECKSUM_COMPLETE)
387862306a36Sopenharmony_ci		return;
387962306a36Sopenharmony_ci
388062306a36Sopenharmony_ci	hns3_ring_stats_update(ring, csum_complete);
388162306a36Sopenharmony_ci	skb->ip_summed = CHECKSUM_COMPLETE;
388262306a36Sopenharmony_ci	skb->csum = csum_unfold((__force __sum16)csum);
388362306a36Sopenharmony_ci}
388462306a36Sopenharmony_ci
388562306a36Sopenharmony_cistatic void hns3_rx_handle_csum(struct sk_buff *skb, u32 l234info,
388662306a36Sopenharmony_ci				u32 ol_info, u32 ptype)
388762306a36Sopenharmony_ci{
388862306a36Sopenharmony_ci	int l3_type, l4_type;
388962306a36Sopenharmony_ci	int ol4_type;
389062306a36Sopenharmony_ci
389162306a36Sopenharmony_ci	if (ptype != HNS3_INVALID_PTYPE) {
389262306a36Sopenharmony_ci		skb->csum_level = hns3_rx_ptype_tbl[ptype].csum_level;
389362306a36Sopenharmony_ci		skb->ip_summed = hns3_rx_ptype_tbl[ptype].ip_summed;
389462306a36Sopenharmony_ci
389562306a36Sopenharmony_ci		return;
389662306a36Sopenharmony_ci	}
389762306a36Sopenharmony_ci
389862306a36Sopenharmony_ci	ol4_type = hnae3_get_field(ol_info, HNS3_RXD_OL4ID_M,
389962306a36Sopenharmony_ci				   HNS3_RXD_OL4ID_S);
390062306a36Sopenharmony_ci	switch (ol4_type) {
390162306a36Sopenharmony_ci	case HNS3_OL4_TYPE_MAC_IN_UDP:
390262306a36Sopenharmony_ci	case HNS3_OL4_TYPE_NVGRE:
390362306a36Sopenharmony_ci		skb->csum_level = 1;
390462306a36Sopenharmony_ci		fallthrough;
390562306a36Sopenharmony_ci	case HNS3_OL4_TYPE_NO_TUN:
390662306a36Sopenharmony_ci		l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M,
390762306a36Sopenharmony_ci					  HNS3_RXD_L3ID_S);
390862306a36Sopenharmony_ci		l4_type = hnae3_get_field(l234info, HNS3_RXD_L4ID_M,
390962306a36Sopenharmony_ci					  HNS3_RXD_L4ID_S);
391062306a36Sopenharmony_ci		/* Can checksum ipv4 or ipv6 + UDP/TCP/SCTP packets */
391162306a36Sopenharmony_ci		if ((l3_type == HNS3_L3_TYPE_IPV4 ||
391262306a36Sopenharmony_ci		     l3_type == HNS3_L3_TYPE_IPV6) &&
391362306a36Sopenharmony_ci		    (l4_type == HNS3_L4_TYPE_UDP ||
391462306a36Sopenharmony_ci		     l4_type == HNS3_L4_TYPE_TCP ||
391562306a36Sopenharmony_ci		     l4_type == HNS3_L4_TYPE_SCTP))
391662306a36Sopenharmony_ci			skb->ip_summed = CHECKSUM_UNNECESSARY;
391762306a36Sopenharmony_ci		break;
391862306a36Sopenharmony_ci	default:
391962306a36Sopenharmony_ci		break;
392062306a36Sopenharmony_ci	}
392162306a36Sopenharmony_ci}
392262306a36Sopenharmony_ci
392362306a36Sopenharmony_cistatic void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb,
392462306a36Sopenharmony_ci			     u32 l234info, u32 bd_base_info, u32 ol_info,
392562306a36Sopenharmony_ci			     u16 csum)
392662306a36Sopenharmony_ci{
392762306a36Sopenharmony_ci	struct net_device *netdev = ring_to_netdev(ring);
392862306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
392962306a36Sopenharmony_ci	u32 ptype = HNS3_INVALID_PTYPE;
393062306a36Sopenharmony_ci
393162306a36Sopenharmony_ci	skb->ip_summed = CHECKSUM_NONE;
393262306a36Sopenharmony_ci
393362306a36Sopenharmony_ci	skb_checksum_none_assert(skb);
393462306a36Sopenharmony_ci
393562306a36Sopenharmony_ci	if (!(netdev->features & NETIF_F_RXCSUM))
393662306a36Sopenharmony_ci		return;
393762306a36Sopenharmony_ci
393862306a36Sopenharmony_ci	if (test_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state))
393962306a36Sopenharmony_ci		ptype = hnae3_get_field(ol_info, HNS3_RXD_PTYPE_M,
394062306a36Sopenharmony_ci					HNS3_RXD_PTYPE_S);
394162306a36Sopenharmony_ci
394262306a36Sopenharmony_ci	hns3_checksum_complete(ring, skb, ptype, csum);
394362306a36Sopenharmony_ci
394462306a36Sopenharmony_ci	/* check if hardware has done checksum */
394562306a36Sopenharmony_ci	if (!(bd_base_info & BIT(HNS3_RXD_L3L4P_B)))
394662306a36Sopenharmony_ci		return;
394762306a36Sopenharmony_ci
394862306a36Sopenharmony_ci	if (unlikely(l234info & (BIT(HNS3_RXD_L3E_B) | BIT(HNS3_RXD_L4E_B) |
394962306a36Sopenharmony_ci				 BIT(HNS3_RXD_OL3E_B) |
395062306a36Sopenharmony_ci				 BIT(HNS3_RXD_OL4E_B)))) {
395162306a36Sopenharmony_ci		skb->ip_summed = CHECKSUM_NONE;
395262306a36Sopenharmony_ci		hns3_ring_stats_update(ring, l3l4_csum_err);
395362306a36Sopenharmony_ci
395462306a36Sopenharmony_ci		return;
395562306a36Sopenharmony_ci	}
395662306a36Sopenharmony_ci
395762306a36Sopenharmony_ci	hns3_rx_handle_csum(skb, l234info, ol_info, ptype);
395862306a36Sopenharmony_ci}
395962306a36Sopenharmony_ci
396062306a36Sopenharmony_cistatic void hns3_rx_skb(struct hns3_enet_ring *ring, struct sk_buff *skb)
396162306a36Sopenharmony_ci{
396262306a36Sopenharmony_ci	if (skb_has_frag_list(skb))
396362306a36Sopenharmony_ci		napi_gro_flush(&ring->tqp_vector->napi, false);
396462306a36Sopenharmony_ci
396562306a36Sopenharmony_ci	napi_gro_receive(&ring->tqp_vector->napi, skb);
396662306a36Sopenharmony_ci}
396762306a36Sopenharmony_ci
396862306a36Sopenharmony_cistatic bool hns3_parse_vlan_tag(struct hns3_enet_ring *ring,
396962306a36Sopenharmony_ci				struct hns3_desc *desc, u32 l234info,
397062306a36Sopenharmony_ci				u16 *vlan_tag)
397162306a36Sopenharmony_ci{
397262306a36Sopenharmony_ci	struct hnae3_handle *handle = ring->tqp->handle;
397362306a36Sopenharmony_ci	struct pci_dev *pdev = ring->tqp->handle->pdev;
397462306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
397562306a36Sopenharmony_ci
397662306a36Sopenharmony_ci	if (unlikely(ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)) {
397762306a36Sopenharmony_ci		*vlan_tag = le16_to_cpu(desc->rx.ot_vlan_tag);
397862306a36Sopenharmony_ci		if (!(*vlan_tag & VLAN_VID_MASK))
397962306a36Sopenharmony_ci			*vlan_tag = le16_to_cpu(desc->rx.vlan_tag);
398062306a36Sopenharmony_ci
398162306a36Sopenharmony_ci		return (*vlan_tag != 0);
398262306a36Sopenharmony_ci	}
398362306a36Sopenharmony_ci
398462306a36Sopenharmony_ci#define HNS3_STRP_OUTER_VLAN	0x1
398562306a36Sopenharmony_ci#define HNS3_STRP_INNER_VLAN	0x2
398662306a36Sopenharmony_ci#define HNS3_STRP_BOTH		0x3
398762306a36Sopenharmony_ci
398862306a36Sopenharmony_ci	/* Hardware always insert VLAN tag into RX descriptor when
398962306a36Sopenharmony_ci	 * remove the tag from packet, driver needs to determine
399062306a36Sopenharmony_ci	 * reporting which tag to stack.
399162306a36Sopenharmony_ci	 */
399262306a36Sopenharmony_ci	switch (hnae3_get_field(l234info, HNS3_RXD_STRP_TAGP_M,
399362306a36Sopenharmony_ci				HNS3_RXD_STRP_TAGP_S)) {
399462306a36Sopenharmony_ci	case HNS3_STRP_OUTER_VLAN:
399562306a36Sopenharmony_ci		if (handle->port_base_vlan_state !=
399662306a36Sopenharmony_ci				HNAE3_PORT_BASE_VLAN_DISABLE)
399762306a36Sopenharmony_ci			return false;
399862306a36Sopenharmony_ci
399962306a36Sopenharmony_ci		*vlan_tag = le16_to_cpu(desc->rx.ot_vlan_tag);
400062306a36Sopenharmony_ci		return true;
400162306a36Sopenharmony_ci	case HNS3_STRP_INNER_VLAN:
400262306a36Sopenharmony_ci		if (handle->port_base_vlan_state !=
400362306a36Sopenharmony_ci				HNAE3_PORT_BASE_VLAN_DISABLE)
400462306a36Sopenharmony_ci			return false;
400562306a36Sopenharmony_ci
400662306a36Sopenharmony_ci		*vlan_tag = le16_to_cpu(desc->rx.vlan_tag);
400762306a36Sopenharmony_ci		return true;
400862306a36Sopenharmony_ci	case HNS3_STRP_BOTH:
400962306a36Sopenharmony_ci		if (handle->port_base_vlan_state ==
401062306a36Sopenharmony_ci				HNAE3_PORT_BASE_VLAN_DISABLE)
401162306a36Sopenharmony_ci			*vlan_tag = le16_to_cpu(desc->rx.ot_vlan_tag);
401262306a36Sopenharmony_ci		else
401362306a36Sopenharmony_ci			*vlan_tag = le16_to_cpu(desc->rx.vlan_tag);
401462306a36Sopenharmony_ci
401562306a36Sopenharmony_ci		return true;
401662306a36Sopenharmony_ci	default:
401762306a36Sopenharmony_ci		return false;
401862306a36Sopenharmony_ci	}
401962306a36Sopenharmony_ci}
402062306a36Sopenharmony_ci
402162306a36Sopenharmony_cistatic void hns3_rx_ring_move_fw(struct hns3_enet_ring *ring)
402262306a36Sopenharmony_ci{
402362306a36Sopenharmony_ci	ring->desc[ring->next_to_clean].rx.bd_base_info &=
402462306a36Sopenharmony_ci		cpu_to_le32(~BIT(HNS3_RXD_VLD_B));
402562306a36Sopenharmony_ci	ring->desc_cb[ring->next_to_clean].refill = 0;
402662306a36Sopenharmony_ci	ring->next_to_clean += 1;
402762306a36Sopenharmony_ci
402862306a36Sopenharmony_ci	if (unlikely(ring->next_to_clean == ring->desc_num))
402962306a36Sopenharmony_ci		ring->next_to_clean = 0;
403062306a36Sopenharmony_ci}
403162306a36Sopenharmony_ci
403262306a36Sopenharmony_cistatic int hns3_alloc_skb(struct hns3_enet_ring *ring, unsigned int length,
403362306a36Sopenharmony_ci			  unsigned char *va)
403462306a36Sopenharmony_ci{
403562306a36Sopenharmony_ci	struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_clean];
403662306a36Sopenharmony_ci	struct net_device *netdev = ring_to_netdev(ring);
403762306a36Sopenharmony_ci	struct sk_buff *skb;
403862306a36Sopenharmony_ci
403962306a36Sopenharmony_ci	ring->skb = napi_alloc_skb(&ring->tqp_vector->napi, HNS3_RX_HEAD_SIZE);
404062306a36Sopenharmony_ci	skb = ring->skb;
404162306a36Sopenharmony_ci	if (unlikely(!skb)) {
404262306a36Sopenharmony_ci		hns3_rl_err(netdev, "alloc rx skb fail\n");
404362306a36Sopenharmony_ci		hns3_ring_stats_update(ring, sw_err_cnt);
404462306a36Sopenharmony_ci
404562306a36Sopenharmony_ci		return -ENOMEM;
404662306a36Sopenharmony_ci	}
404762306a36Sopenharmony_ci
404862306a36Sopenharmony_ci	trace_hns3_rx_desc(ring);
404962306a36Sopenharmony_ci	prefetchw(skb->data);
405062306a36Sopenharmony_ci
405162306a36Sopenharmony_ci	ring->pending_buf = 1;
405262306a36Sopenharmony_ci	ring->frag_num = 0;
405362306a36Sopenharmony_ci	ring->tail_skb = NULL;
405462306a36Sopenharmony_ci	if (length <= HNS3_RX_HEAD_SIZE) {
405562306a36Sopenharmony_ci		memcpy(__skb_put(skb, length), va, ALIGN(length, sizeof(long)));
405662306a36Sopenharmony_ci
405762306a36Sopenharmony_ci		/* We can reuse buffer as-is, just make sure it is reusable */
405862306a36Sopenharmony_ci		if (dev_page_is_reusable(desc_cb->priv))
405962306a36Sopenharmony_ci			desc_cb->reuse_flag = 1;
406062306a36Sopenharmony_ci		else if (desc_cb->type & DESC_TYPE_PP_FRAG)
406162306a36Sopenharmony_ci			page_pool_put_full_page(ring->page_pool, desc_cb->priv,
406262306a36Sopenharmony_ci						false);
406362306a36Sopenharmony_ci		else /* This page cannot be reused so discard it */
406462306a36Sopenharmony_ci			__page_frag_cache_drain(desc_cb->priv,
406562306a36Sopenharmony_ci						desc_cb->pagecnt_bias);
406662306a36Sopenharmony_ci
406762306a36Sopenharmony_ci		hns3_rx_ring_move_fw(ring);
406862306a36Sopenharmony_ci		return 0;
406962306a36Sopenharmony_ci	}
407062306a36Sopenharmony_ci
407162306a36Sopenharmony_ci	if (ring->page_pool)
407262306a36Sopenharmony_ci		skb_mark_for_recycle(skb);
407362306a36Sopenharmony_ci
407462306a36Sopenharmony_ci	hns3_ring_stats_update(ring, seg_pkt_cnt);
407562306a36Sopenharmony_ci
407662306a36Sopenharmony_ci	ring->pull_len = eth_get_headlen(netdev, va, HNS3_RX_HEAD_SIZE);
407762306a36Sopenharmony_ci	__skb_put(skb, ring->pull_len);
407862306a36Sopenharmony_ci	hns3_nic_reuse_page(skb, ring->frag_num++, ring, ring->pull_len,
407962306a36Sopenharmony_ci			    desc_cb);
408062306a36Sopenharmony_ci	hns3_rx_ring_move_fw(ring);
408162306a36Sopenharmony_ci
408262306a36Sopenharmony_ci	return 0;
408362306a36Sopenharmony_ci}
408462306a36Sopenharmony_ci
408562306a36Sopenharmony_cistatic int hns3_add_frag(struct hns3_enet_ring *ring)
408662306a36Sopenharmony_ci{
408762306a36Sopenharmony_ci	struct sk_buff *skb = ring->skb;
408862306a36Sopenharmony_ci	struct sk_buff *head_skb = skb;
408962306a36Sopenharmony_ci	struct sk_buff *new_skb;
409062306a36Sopenharmony_ci	struct hns3_desc_cb *desc_cb;
409162306a36Sopenharmony_ci	struct hns3_desc *desc;
409262306a36Sopenharmony_ci	u32 bd_base_info;
409362306a36Sopenharmony_ci
409462306a36Sopenharmony_ci	do {
409562306a36Sopenharmony_ci		desc = &ring->desc[ring->next_to_clean];
409662306a36Sopenharmony_ci		desc_cb = &ring->desc_cb[ring->next_to_clean];
409762306a36Sopenharmony_ci		bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
409862306a36Sopenharmony_ci		/* make sure HW write desc complete */
409962306a36Sopenharmony_ci		dma_rmb();
410062306a36Sopenharmony_ci		if (!(bd_base_info & BIT(HNS3_RXD_VLD_B)))
410162306a36Sopenharmony_ci			return -ENXIO;
410262306a36Sopenharmony_ci
410362306a36Sopenharmony_ci		if (unlikely(ring->frag_num >= MAX_SKB_FRAGS)) {
410462306a36Sopenharmony_ci			new_skb = napi_alloc_skb(&ring->tqp_vector->napi, 0);
410562306a36Sopenharmony_ci			if (unlikely(!new_skb)) {
410662306a36Sopenharmony_ci				hns3_rl_err(ring_to_netdev(ring),
410762306a36Sopenharmony_ci					    "alloc rx fraglist skb fail\n");
410862306a36Sopenharmony_ci				return -ENXIO;
410962306a36Sopenharmony_ci			}
411062306a36Sopenharmony_ci
411162306a36Sopenharmony_ci			if (ring->page_pool)
411262306a36Sopenharmony_ci				skb_mark_for_recycle(new_skb);
411362306a36Sopenharmony_ci
411462306a36Sopenharmony_ci			ring->frag_num = 0;
411562306a36Sopenharmony_ci
411662306a36Sopenharmony_ci			if (ring->tail_skb) {
411762306a36Sopenharmony_ci				ring->tail_skb->next = new_skb;
411862306a36Sopenharmony_ci				ring->tail_skb = new_skb;
411962306a36Sopenharmony_ci			} else {
412062306a36Sopenharmony_ci				skb_shinfo(skb)->frag_list = new_skb;
412162306a36Sopenharmony_ci				ring->tail_skb = new_skb;
412262306a36Sopenharmony_ci			}
412362306a36Sopenharmony_ci		}
412462306a36Sopenharmony_ci
412562306a36Sopenharmony_ci		if (ring->tail_skb) {
412662306a36Sopenharmony_ci			head_skb->truesize += hns3_buf_size(ring);
412762306a36Sopenharmony_ci			head_skb->data_len += le16_to_cpu(desc->rx.size);
412862306a36Sopenharmony_ci			head_skb->len += le16_to_cpu(desc->rx.size);
412962306a36Sopenharmony_ci			skb = ring->tail_skb;
413062306a36Sopenharmony_ci		}
413162306a36Sopenharmony_ci
413262306a36Sopenharmony_ci		dma_sync_single_for_cpu(ring_to_dev(ring),
413362306a36Sopenharmony_ci				desc_cb->dma + desc_cb->page_offset,
413462306a36Sopenharmony_ci				hns3_buf_size(ring),
413562306a36Sopenharmony_ci				DMA_FROM_DEVICE);
413662306a36Sopenharmony_ci
413762306a36Sopenharmony_ci		hns3_nic_reuse_page(skb, ring->frag_num++, ring, 0, desc_cb);
413862306a36Sopenharmony_ci		trace_hns3_rx_desc(ring);
413962306a36Sopenharmony_ci		hns3_rx_ring_move_fw(ring);
414062306a36Sopenharmony_ci		ring->pending_buf++;
414162306a36Sopenharmony_ci	} while (!(bd_base_info & BIT(HNS3_RXD_FE_B)));
414262306a36Sopenharmony_ci
414362306a36Sopenharmony_ci	return 0;
414462306a36Sopenharmony_ci}
414562306a36Sopenharmony_ci
414662306a36Sopenharmony_cistatic int hns3_set_gro_and_checksum(struct hns3_enet_ring *ring,
414762306a36Sopenharmony_ci				     struct sk_buff *skb, u32 l234info,
414862306a36Sopenharmony_ci				     u32 bd_base_info, u32 ol_info, u16 csum)
414962306a36Sopenharmony_ci{
415062306a36Sopenharmony_ci	struct net_device *netdev = ring_to_netdev(ring);
415162306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
415262306a36Sopenharmony_ci	u32 l3_type;
415362306a36Sopenharmony_ci
415462306a36Sopenharmony_ci	skb_shinfo(skb)->gso_size = hnae3_get_field(bd_base_info,
415562306a36Sopenharmony_ci						    HNS3_RXD_GRO_SIZE_M,
415662306a36Sopenharmony_ci						    HNS3_RXD_GRO_SIZE_S);
415762306a36Sopenharmony_ci	/* if there is no HW GRO, do not set gro params */
415862306a36Sopenharmony_ci	if (!skb_shinfo(skb)->gso_size) {
415962306a36Sopenharmony_ci		hns3_rx_checksum(ring, skb, l234info, bd_base_info, ol_info,
416062306a36Sopenharmony_ci				 csum);
416162306a36Sopenharmony_ci		return 0;
416262306a36Sopenharmony_ci	}
416362306a36Sopenharmony_ci
416462306a36Sopenharmony_ci	NAPI_GRO_CB(skb)->count = hnae3_get_field(l234info,
416562306a36Sopenharmony_ci						  HNS3_RXD_GRO_COUNT_M,
416662306a36Sopenharmony_ci						  HNS3_RXD_GRO_COUNT_S);
416762306a36Sopenharmony_ci
416862306a36Sopenharmony_ci	if (test_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state)) {
416962306a36Sopenharmony_ci		u32 ptype = hnae3_get_field(ol_info, HNS3_RXD_PTYPE_M,
417062306a36Sopenharmony_ci					    HNS3_RXD_PTYPE_S);
417162306a36Sopenharmony_ci
417262306a36Sopenharmony_ci		l3_type = hns3_rx_ptype_tbl[ptype].l3_type;
417362306a36Sopenharmony_ci	} else {
417462306a36Sopenharmony_ci		l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M,
417562306a36Sopenharmony_ci					  HNS3_RXD_L3ID_S);
417662306a36Sopenharmony_ci	}
417762306a36Sopenharmony_ci
417862306a36Sopenharmony_ci	if (l3_type == HNS3_L3_TYPE_IPV4)
417962306a36Sopenharmony_ci		skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
418062306a36Sopenharmony_ci	else if (l3_type == HNS3_L3_TYPE_IPV6)
418162306a36Sopenharmony_ci		skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
418262306a36Sopenharmony_ci	else
418362306a36Sopenharmony_ci		return -EFAULT;
418462306a36Sopenharmony_ci
418562306a36Sopenharmony_ci	return  hns3_gro_complete(skb, l234info);
418662306a36Sopenharmony_ci}
418762306a36Sopenharmony_ci
418862306a36Sopenharmony_cistatic void hns3_set_rx_skb_rss_type(struct hns3_enet_ring *ring,
418962306a36Sopenharmony_ci				     struct sk_buff *skb, u32 rss_hash,
419062306a36Sopenharmony_ci				     u32 l234info, u32 ol_info)
419162306a36Sopenharmony_ci{
419262306a36Sopenharmony_ci	enum pkt_hash_types rss_type = PKT_HASH_TYPE_NONE;
419362306a36Sopenharmony_ci	struct net_device *netdev = ring_to_netdev(ring);
419462306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
419562306a36Sopenharmony_ci
419662306a36Sopenharmony_ci	if (test_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state)) {
419762306a36Sopenharmony_ci		u32 ptype = hnae3_get_field(ol_info, HNS3_RXD_PTYPE_M,
419862306a36Sopenharmony_ci					    HNS3_RXD_PTYPE_S);
419962306a36Sopenharmony_ci
420062306a36Sopenharmony_ci		rss_type = hns3_rx_ptype_tbl[ptype].hash_type;
420162306a36Sopenharmony_ci	} else {
420262306a36Sopenharmony_ci		int l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M,
420362306a36Sopenharmony_ci					      HNS3_RXD_L3ID_S);
420462306a36Sopenharmony_ci		int l4_type = hnae3_get_field(l234info, HNS3_RXD_L4ID_M,
420562306a36Sopenharmony_ci					      HNS3_RXD_L4ID_S);
420662306a36Sopenharmony_ci
420762306a36Sopenharmony_ci		if (l3_type == HNS3_L3_TYPE_IPV4 ||
420862306a36Sopenharmony_ci		    l3_type == HNS3_L3_TYPE_IPV6) {
420962306a36Sopenharmony_ci			if (l4_type == HNS3_L4_TYPE_UDP ||
421062306a36Sopenharmony_ci			    l4_type == HNS3_L4_TYPE_TCP ||
421162306a36Sopenharmony_ci			    l4_type == HNS3_L4_TYPE_SCTP)
421262306a36Sopenharmony_ci				rss_type = PKT_HASH_TYPE_L4;
421362306a36Sopenharmony_ci			else if (l4_type == HNS3_L4_TYPE_IGMP ||
421462306a36Sopenharmony_ci				 l4_type == HNS3_L4_TYPE_ICMP)
421562306a36Sopenharmony_ci				rss_type = PKT_HASH_TYPE_L3;
421662306a36Sopenharmony_ci		}
421762306a36Sopenharmony_ci	}
421862306a36Sopenharmony_ci
421962306a36Sopenharmony_ci	skb_set_hash(skb, rss_hash, rss_type);
422062306a36Sopenharmony_ci}
422162306a36Sopenharmony_ci
422262306a36Sopenharmony_cistatic void hns3_handle_rx_ts_info(struct net_device *netdev,
422362306a36Sopenharmony_ci				   struct hns3_desc *desc, struct sk_buff *skb,
422462306a36Sopenharmony_ci				   u32 bd_base_info)
422562306a36Sopenharmony_ci{
422662306a36Sopenharmony_ci	if (unlikely(bd_base_info & BIT(HNS3_RXD_TS_VLD_B))) {
422762306a36Sopenharmony_ci		struct hnae3_handle *h = hns3_get_handle(netdev);
422862306a36Sopenharmony_ci		u32 nsec = le32_to_cpu(desc->ts_nsec);
422962306a36Sopenharmony_ci		u32 sec = le32_to_cpu(desc->ts_sec);
423062306a36Sopenharmony_ci
423162306a36Sopenharmony_ci		if (h->ae_algo->ops->get_rx_hwts)
423262306a36Sopenharmony_ci			h->ae_algo->ops->get_rx_hwts(h, skb, nsec, sec);
423362306a36Sopenharmony_ci	}
423462306a36Sopenharmony_ci}
423562306a36Sopenharmony_ci
423662306a36Sopenharmony_cistatic void hns3_handle_rx_vlan_tag(struct hns3_enet_ring *ring,
423762306a36Sopenharmony_ci				    struct hns3_desc *desc, struct sk_buff *skb,
423862306a36Sopenharmony_ci				    u32 l234info)
423962306a36Sopenharmony_ci{
424062306a36Sopenharmony_ci	struct net_device *netdev = ring_to_netdev(ring);
424162306a36Sopenharmony_ci
424262306a36Sopenharmony_ci	/* Based on hw strategy, the tag offloaded will be stored at
424362306a36Sopenharmony_ci	 * ot_vlan_tag in two layer tag case, and stored at vlan_tag
424462306a36Sopenharmony_ci	 * in one layer tag case.
424562306a36Sopenharmony_ci	 */
424662306a36Sopenharmony_ci	if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
424762306a36Sopenharmony_ci		u16 vlan_tag;
424862306a36Sopenharmony_ci
424962306a36Sopenharmony_ci		if (hns3_parse_vlan_tag(ring, desc, l234info, &vlan_tag))
425062306a36Sopenharmony_ci			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
425162306a36Sopenharmony_ci					       vlan_tag);
425262306a36Sopenharmony_ci	}
425362306a36Sopenharmony_ci}
425462306a36Sopenharmony_ci
425562306a36Sopenharmony_cistatic int hns3_handle_bdinfo(struct hns3_enet_ring *ring, struct sk_buff *skb)
425662306a36Sopenharmony_ci{
425762306a36Sopenharmony_ci	struct net_device *netdev = ring_to_netdev(ring);
425862306a36Sopenharmony_ci	enum hns3_pkt_l2t_type l2_frame_type;
425962306a36Sopenharmony_ci	u32 bd_base_info, l234info, ol_info;
426062306a36Sopenharmony_ci	struct hns3_desc *desc;
426162306a36Sopenharmony_ci	unsigned int len;
426262306a36Sopenharmony_ci	int pre_ntc, ret;
426362306a36Sopenharmony_ci	u16 csum;
426462306a36Sopenharmony_ci
426562306a36Sopenharmony_ci	/* bdinfo handled below is only valid on the last BD of the
426662306a36Sopenharmony_ci	 * current packet, and ring->next_to_clean indicates the first
426762306a36Sopenharmony_ci	 * descriptor of next packet, so need - 1 below.
426862306a36Sopenharmony_ci	 */
426962306a36Sopenharmony_ci	pre_ntc = ring->next_to_clean ? (ring->next_to_clean - 1) :
427062306a36Sopenharmony_ci					(ring->desc_num - 1);
427162306a36Sopenharmony_ci	desc = &ring->desc[pre_ntc];
427262306a36Sopenharmony_ci	bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
427362306a36Sopenharmony_ci	l234info = le32_to_cpu(desc->rx.l234_info);
427462306a36Sopenharmony_ci	ol_info = le32_to_cpu(desc->rx.ol_info);
427562306a36Sopenharmony_ci	csum = le16_to_cpu(desc->csum);
427662306a36Sopenharmony_ci
427762306a36Sopenharmony_ci	hns3_handle_rx_ts_info(netdev, desc, skb, bd_base_info);
427862306a36Sopenharmony_ci
427962306a36Sopenharmony_ci	hns3_handle_rx_vlan_tag(ring, desc, skb, l234info);
428062306a36Sopenharmony_ci
428162306a36Sopenharmony_ci	if (unlikely(!desc->rx.pkt_len || (l234info & (BIT(HNS3_RXD_TRUNCAT_B) |
428262306a36Sopenharmony_ci				  BIT(HNS3_RXD_L2E_B))))) {
428362306a36Sopenharmony_ci		u64_stats_update_begin(&ring->syncp);
428462306a36Sopenharmony_ci		if (l234info & BIT(HNS3_RXD_L2E_B))
428562306a36Sopenharmony_ci			ring->stats.l2_err++;
428662306a36Sopenharmony_ci		else
428762306a36Sopenharmony_ci			ring->stats.err_pkt_len++;
428862306a36Sopenharmony_ci		u64_stats_update_end(&ring->syncp);
428962306a36Sopenharmony_ci
429062306a36Sopenharmony_ci		return -EFAULT;
429162306a36Sopenharmony_ci	}
429262306a36Sopenharmony_ci
429362306a36Sopenharmony_ci	len = skb->len;
429462306a36Sopenharmony_ci
429562306a36Sopenharmony_ci	/* Do update ip stack process */
429662306a36Sopenharmony_ci	skb->protocol = eth_type_trans(skb, netdev);
429762306a36Sopenharmony_ci
429862306a36Sopenharmony_ci	/* This is needed in order to enable forwarding support */
429962306a36Sopenharmony_ci	ret = hns3_set_gro_and_checksum(ring, skb, l234info,
430062306a36Sopenharmony_ci					bd_base_info, ol_info, csum);
430162306a36Sopenharmony_ci	if (unlikely(ret)) {
430262306a36Sopenharmony_ci		hns3_ring_stats_update(ring, rx_err_cnt);
430362306a36Sopenharmony_ci		return ret;
430462306a36Sopenharmony_ci	}
430562306a36Sopenharmony_ci
430662306a36Sopenharmony_ci	l2_frame_type = hnae3_get_field(l234info, HNS3_RXD_DMAC_M,
430762306a36Sopenharmony_ci					HNS3_RXD_DMAC_S);
430862306a36Sopenharmony_ci
430962306a36Sopenharmony_ci	u64_stats_update_begin(&ring->syncp);
431062306a36Sopenharmony_ci	ring->stats.rx_pkts++;
431162306a36Sopenharmony_ci	ring->stats.rx_bytes += len;
431262306a36Sopenharmony_ci
431362306a36Sopenharmony_ci	if (l2_frame_type == HNS3_L2_TYPE_MULTICAST)
431462306a36Sopenharmony_ci		ring->stats.rx_multicast++;
431562306a36Sopenharmony_ci
431662306a36Sopenharmony_ci	u64_stats_update_end(&ring->syncp);
431762306a36Sopenharmony_ci
431862306a36Sopenharmony_ci	ring->tqp_vector->rx_group.total_bytes += len;
431962306a36Sopenharmony_ci
432062306a36Sopenharmony_ci	hns3_set_rx_skb_rss_type(ring, skb, le32_to_cpu(desc->rx.rss_hash),
432162306a36Sopenharmony_ci				 l234info, ol_info);
432262306a36Sopenharmony_ci	return 0;
432362306a36Sopenharmony_ci}
432462306a36Sopenharmony_ci
432562306a36Sopenharmony_cistatic int hns3_handle_rx_bd(struct hns3_enet_ring *ring)
432662306a36Sopenharmony_ci{
432762306a36Sopenharmony_ci	struct sk_buff *skb = ring->skb;
432862306a36Sopenharmony_ci	struct hns3_desc_cb *desc_cb;
432962306a36Sopenharmony_ci	struct hns3_desc *desc;
433062306a36Sopenharmony_ci	unsigned int length;
433162306a36Sopenharmony_ci	u32 bd_base_info;
433262306a36Sopenharmony_ci	int ret;
433362306a36Sopenharmony_ci
433462306a36Sopenharmony_ci	desc = &ring->desc[ring->next_to_clean];
433562306a36Sopenharmony_ci	desc_cb = &ring->desc_cb[ring->next_to_clean];
433662306a36Sopenharmony_ci
433762306a36Sopenharmony_ci	prefetch(desc);
433862306a36Sopenharmony_ci
433962306a36Sopenharmony_ci	if (!skb) {
434062306a36Sopenharmony_ci		bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
434162306a36Sopenharmony_ci		/* Check valid BD */
434262306a36Sopenharmony_ci		if (unlikely(!(bd_base_info & BIT(HNS3_RXD_VLD_B))))
434362306a36Sopenharmony_ci			return -ENXIO;
434462306a36Sopenharmony_ci
434562306a36Sopenharmony_ci		dma_rmb();
434662306a36Sopenharmony_ci		length = le16_to_cpu(desc->rx.size);
434762306a36Sopenharmony_ci
434862306a36Sopenharmony_ci		ring->va = desc_cb->buf + desc_cb->page_offset;
434962306a36Sopenharmony_ci
435062306a36Sopenharmony_ci		dma_sync_single_for_cpu(ring_to_dev(ring),
435162306a36Sopenharmony_ci				desc_cb->dma + desc_cb->page_offset,
435262306a36Sopenharmony_ci				hns3_buf_size(ring),
435362306a36Sopenharmony_ci				DMA_FROM_DEVICE);
435462306a36Sopenharmony_ci
435562306a36Sopenharmony_ci		/* Prefetch first cache line of first page.
435662306a36Sopenharmony_ci		 * Idea is to cache few bytes of the header of the packet.
435762306a36Sopenharmony_ci		 * Our L1 Cache line size is 64B so need to prefetch twice to make
435862306a36Sopenharmony_ci		 * it 128B. But in actual we can have greater size of caches with
435962306a36Sopenharmony_ci		 * 128B Level 1 cache lines. In such a case, single fetch would
436062306a36Sopenharmony_ci		 * suffice to cache in the relevant part of the header.
436162306a36Sopenharmony_ci		 */
436262306a36Sopenharmony_ci		net_prefetch(ring->va);
436362306a36Sopenharmony_ci
436462306a36Sopenharmony_ci		ret = hns3_alloc_skb(ring, length, ring->va);
436562306a36Sopenharmony_ci		skb = ring->skb;
436662306a36Sopenharmony_ci
436762306a36Sopenharmony_ci		if (ret < 0) /* alloc buffer fail */
436862306a36Sopenharmony_ci			return ret;
436962306a36Sopenharmony_ci		if (!(bd_base_info & BIT(HNS3_RXD_FE_B))) { /* need add frag */
437062306a36Sopenharmony_ci			ret = hns3_add_frag(ring);
437162306a36Sopenharmony_ci			if (ret)
437262306a36Sopenharmony_ci				return ret;
437362306a36Sopenharmony_ci		}
437462306a36Sopenharmony_ci	} else {
437562306a36Sopenharmony_ci		ret = hns3_add_frag(ring);
437662306a36Sopenharmony_ci		if (ret)
437762306a36Sopenharmony_ci			return ret;
437862306a36Sopenharmony_ci	}
437962306a36Sopenharmony_ci
438062306a36Sopenharmony_ci	/* As the head data may be changed when GRO enable, copy
438162306a36Sopenharmony_ci	 * the head data in after other data rx completed
438262306a36Sopenharmony_ci	 */
438362306a36Sopenharmony_ci	if (skb->len > HNS3_RX_HEAD_SIZE)
438462306a36Sopenharmony_ci		memcpy(skb->data, ring->va,
438562306a36Sopenharmony_ci		       ALIGN(ring->pull_len, sizeof(long)));
438662306a36Sopenharmony_ci
438762306a36Sopenharmony_ci	ret = hns3_handle_bdinfo(ring, skb);
438862306a36Sopenharmony_ci	if (unlikely(ret)) {
438962306a36Sopenharmony_ci		dev_kfree_skb_any(skb);
439062306a36Sopenharmony_ci		return ret;
439162306a36Sopenharmony_ci	}
439262306a36Sopenharmony_ci
439362306a36Sopenharmony_ci	skb_record_rx_queue(skb, ring->tqp->tqp_index);
439462306a36Sopenharmony_ci	return 0;
439562306a36Sopenharmony_ci}
439662306a36Sopenharmony_ci
439762306a36Sopenharmony_ciint hns3_clean_rx_ring(struct hns3_enet_ring *ring, int budget,
439862306a36Sopenharmony_ci		       void (*rx_fn)(struct hns3_enet_ring *, struct sk_buff *))
439962306a36Sopenharmony_ci{
440062306a36Sopenharmony_ci#define RCB_NOF_ALLOC_RX_BUFF_ONCE 16
440162306a36Sopenharmony_ci	int unused_count = hns3_desc_unused(ring);
440262306a36Sopenharmony_ci	bool failure = false;
440362306a36Sopenharmony_ci	int recv_pkts = 0;
440462306a36Sopenharmony_ci	int err;
440562306a36Sopenharmony_ci
440662306a36Sopenharmony_ci	unused_count -= ring->pending_buf;
440762306a36Sopenharmony_ci
440862306a36Sopenharmony_ci	while (recv_pkts < budget) {
440962306a36Sopenharmony_ci		/* Reuse or realloc buffers */
441062306a36Sopenharmony_ci		if (unused_count >= RCB_NOF_ALLOC_RX_BUFF_ONCE) {
441162306a36Sopenharmony_ci			failure = failure ||
441262306a36Sopenharmony_ci				hns3_nic_alloc_rx_buffers(ring, unused_count);
441362306a36Sopenharmony_ci			unused_count = 0;
441462306a36Sopenharmony_ci		}
441562306a36Sopenharmony_ci
441662306a36Sopenharmony_ci		/* Poll one pkt */
441762306a36Sopenharmony_ci		err = hns3_handle_rx_bd(ring);
441862306a36Sopenharmony_ci		/* Do not get FE for the packet or failed to alloc skb */
441962306a36Sopenharmony_ci		if (unlikely(!ring->skb || err == -ENXIO)) {
442062306a36Sopenharmony_ci			goto out;
442162306a36Sopenharmony_ci		} else if (likely(!err)) {
442262306a36Sopenharmony_ci			rx_fn(ring, ring->skb);
442362306a36Sopenharmony_ci			recv_pkts++;
442462306a36Sopenharmony_ci		}
442562306a36Sopenharmony_ci
442662306a36Sopenharmony_ci		unused_count += ring->pending_buf;
442762306a36Sopenharmony_ci		ring->skb = NULL;
442862306a36Sopenharmony_ci		ring->pending_buf = 0;
442962306a36Sopenharmony_ci	}
443062306a36Sopenharmony_ci
443162306a36Sopenharmony_ciout:
443262306a36Sopenharmony_ci	/* sync head pointer before exiting, since hardware will calculate
443362306a36Sopenharmony_ci	 * FBD number with head pointer
443462306a36Sopenharmony_ci	 */
443562306a36Sopenharmony_ci	if (unused_count > 0)
443662306a36Sopenharmony_ci		failure = failure ||
443762306a36Sopenharmony_ci			  hns3_nic_alloc_rx_buffers(ring, unused_count);
443862306a36Sopenharmony_ci
443962306a36Sopenharmony_ci	return failure ? budget : recv_pkts;
444062306a36Sopenharmony_ci}
444162306a36Sopenharmony_ci
444262306a36Sopenharmony_cistatic void hns3_update_rx_int_coalesce(struct hns3_enet_tqp_vector *tqp_vector)
444362306a36Sopenharmony_ci{
444462306a36Sopenharmony_ci	struct hns3_enet_ring_group *rx_group = &tqp_vector->rx_group;
444562306a36Sopenharmony_ci	struct dim_sample sample = {};
444662306a36Sopenharmony_ci
444762306a36Sopenharmony_ci	if (!rx_group->coal.adapt_enable)
444862306a36Sopenharmony_ci		return;
444962306a36Sopenharmony_ci
445062306a36Sopenharmony_ci	dim_update_sample(tqp_vector->event_cnt, rx_group->total_packets,
445162306a36Sopenharmony_ci			  rx_group->total_bytes, &sample);
445262306a36Sopenharmony_ci	net_dim(&rx_group->dim, sample);
445362306a36Sopenharmony_ci}
445462306a36Sopenharmony_ci
445562306a36Sopenharmony_cistatic void hns3_update_tx_int_coalesce(struct hns3_enet_tqp_vector *tqp_vector)
445662306a36Sopenharmony_ci{
445762306a36Sopenharmony_ci	struct hns3_enet_ring_group *tx_group = &tqp_vector->tx_group;
445862306a36Sopenharmony_ci	struct dim_sample sample = {};
445962306a36Sopenharmony_ci
446062306a36Sopenharmony_ci	if (!tx_group->coal.adapt_enable)
446162306a36Sopenharmony_ci		return;
446262306a36Sopenharmony_ci
446362306a36Sopenharmony_ci	dim_update_sample(tqp_vector->event_cnt, tx_group->total_packets,
446462306a36Sopenharmony_ci			  tx_group->total_bytes, &sample);
446562306a36Sopenharmony_ci	net_dim(&tx_group->dim, sample);
446662306a36Sopenharmony_ci}
446762306a36Sopenharmony_ci
446862306a36Sopenharmony_cistatic int hns3_nic_common_poll(struct napi_struct *napi, int budget)
446962306a36Sopenharmony_ci{
447062306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(napi->dev);
447162306a36Sopenharmony_ci	struct hns3_enet_ring *ring;
447262306a36Sopenharmony_ci	int rx_pkt_total = 0;
447362306a36Sopenharmony_ci
447462306a36Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector =
447562306a36Sopenharmony_ci		container_of(napi, struct hns3_enet_tqp_vector, napi);
447662306a36Sopenharmony_ci	bool clean_complete = true;
447762306a36Sopenharmony_ci	int rx_budget = budget;
447862306a36Sopenharmony_ci
447962306a36Sopenharmony_ci	if (unlikely(test_bit(HNS3_NIC_STATE_DOWN, &priv->state))) {
448062306a36Sopenharmony_ci		napi_complete(napi);
448162306a36Sopenharmony_ci		return 0;
448262306a36Sopenharmony_ci	}
448362306a36Sopenharmony_ci
448462306a36Sopenharmony_ci	/* Since the actual Tx work is minimal, we can give the Tx a larger
448562306a36Sopenharmony_ci	 * budget and be more aggressive about cleaning up the Tx descriptors.
448662306a36Sopenharmony_ci	 */
448762306a36Sopenharmony_ci	hns3_for_each_ring(ring, tqp_vector->tx_group)
448862306a36Sopenharmony_ci		hns3_clean_tx_ring(ring, budget);
448962306a36Sopenharmony_ci
449062306a36Sopenharmony_ci	/* make sure rx ring budget not smaller than 1 */
449162306a36Sopenharmony_ci	if (tqp_vector->num_tqps > 1)
449262306a36Sopenharmony_ci		rx_budget = max(budget / tqp_vector->num_tqps, 1);
449362306a36Sopenharmony_ci
449462306a36Sopenharmony_ci	hns3_for_each_ring(ring, tqp_vector->rx_group) {
449562306a36Sopenharmony_ci		int rx_cleaned = hns3_clean_rx_ring(ring, rx_budget,
449662306a36Sopenharmony_ci						    hns3_rx_skb);
449762306a36Sopenharmony_ci		if (rx_cleaned >= rx_budget)
449862306a36Sopenharmony_ci			clean_complete = false;
449962306a36Sopenharmony_ci
450062306a36Sopenharmony_ci		rx_pkt_total += rx_cleaned;
450162306a36Sopenharmony_ci	}
450262306a36Sopenharmony_ci
450362306a36Sopenharmony_ci	tqp_vector->rx_group.total_packets += rx_pkt_total;
450462306a36Sopenharmony_ci
450562306a36Sopenharmony_ci	if (!clean_complete)
450662306a36Sopenharmony_ci		return budget;
450762306a36Sopenharmony_ci
450862306a36Sopenharmony_ci	if (napi_complete(napi) &&
450962306a36Sopenharmony_ci	    likely(!test_bit(HNS3_NIC_STATE_DOWN, &priv->state))) {
451062306a36Sopenharmony_ci		hns3_update_rx_int_coalesce(tqp_vector);
451162306a36Sopenharmony_ci		hns3_update_tx_int_coalesce(tqp_vector);
451262306a36Sopenharmony_ci
451362306a36Sopenharmony_ci		hns3_mask_vector_irq(tqp_vector, 1);
451462306a36Sopenharmony_ci	}
451562306a36Sopenharmony_ci
451662306a36Sopenharmony_ci	return rx_pkt_total;
451762306a36Sopenharmony_ci}
451862306a36Sopenharmony_ci
451962306a36Sopenharmony_cistatic int hns3_create_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
452062306a36Sopenharmony_ci				  struct hnae3_ring_chain_node **head,
452162306a36Sopenharmony_ci				  bool is_tx)
452262306a36Sopenharmony_ci{
452362306a36Sopenharmony_ci	u32 bit_value = is_tx ? HNAE3_RING_TYPE_TX : HNAE3_RING_TYPE_RX;
452462306a36Sopenharmony_ci	u32 field_value = is_tx ? HNAE3_RING_GL_TX : HNAE3_RING_GL_RX;
452562306a36Sopenharmony_ci	struct hnae3_ring_chain_node *cur_chain = *head;
452662306a36Sopenharmony_ci	struct pci_dev *pdev = tqp_vector->handle->pdev;
452762306a36Sopenharmony_ci	struct hnae3_ring_chain_node *chain;
452862306a36Sopenharmony_ci	struct hns3_enet_ring *ring;
452962306a36Sopenharmony_ci
453062306a36Sopenharmony_ci	ring = is_tx ? tqp_vector->tx_group.ring : tqp_vector->rx_group.ring;
453162306a36Sopenharmony_ci
453262306a36Sopenharmony_ci	if (cur_chain) {
453362306a36Sopenharmony_ci		while (cur_chain->next)
453462306a36Sopenharmony_ci			cur_chain = cur_chain->next;
453562306a36Sopenharmony_ci	}
453662306a36Sopenharmony_ci
453762306a36Sopenharmony_ci	while (ring) {
453862306a36Sopenharmony_ci		chain = devm_kzalloc(&pdev->dev, sizeof(*chain), GFP_KERNEL);
453962306a36Sopenharmony_ci		if (!chain)
454062306a36Sopenharmony_ci			return -ENOMEM;
454162306a36Sopenharmony_ci		if (cur_chain)
454262306a36Sopenharmony_ci			cur_chain->next = chain;
454362306a36Sopenharmony_ci		else
454462306a36Sopenharmony_ci			*head = chain;
454562306a36Sopenharmony_ci		chain->tqp_index = ring->tqp->tqp_index;
454662306a36Sopenharmony_ci		hnae3_set_bit(chain->flag, HNAE3_RING_TYPE_B,
454762306a36Sopenharmony_ci				bit_value);
454862306a36Sopenharmony_ci		hnae3_set_field(chain->int_gl_idx,
454962306a36Sopenharmony_ci				HNAE3_RING_GL_IDX_M,
455062306a36Sopenharmony_ci				HNAE3_RING_GL_IDX_S, field_value);
455162306a36Sopenharmony_ci
455262306a36Sopenharmony_ci		cur_chain = chain;
455362306a36Sopenharmony_ci
455462306a36Sopenharmony_ci		ring = ring->next;
455562306a36Sopenharmony_ci	}
455662306a36Sopenharmony_ci
455762306a36Sopenharmony_ci	return 0;
455862306a36Sopenharmony_ci}
455962306a36Sopenharmony_ci
456062306a36Sopenharmony_cistatic struct hnae3_ring_chain_node *
456162306a36Sopenharmony_cihns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector)
456262306a36Sopenharmony_ci{
456362306a36Sopenharmony_ci	struct pci_dev *pdev = tqp_vector->handle->pdev;
456462306a36Sopenharmony_ci	struct hnae3_ring_chain_node *cur_chain = NULL;
456562306a36Sopenharmony_ci	struct hnae3_ring_chain_node *chain;
456662306a36Sopenharmony_ci
456762306a36Sopenharmony_ci	if (hns3_create_ring_chain(tqp_vector, &cur_chain, true))
456862306a36Sopenharmony_ci		goto err_free_chain;
456962306a36Sopenharmony_ci
457062306a36Sopenharmony_ci	if (hns3_create_ring_chain(tqp_vector, &cur_chain, false))
457162306a36Sopenharmony_ci		goto err_free_chain;
457262306a36Sopenharmony_ci
457362306a36Sopenharmony_ci	return cur_chain;
457462306a36Sopenharmony_ci
457562306a36Sopenharmony_cierr_free_chain:
457662306a36Sopenharmony_ci	while (cur_chain) {
457762306a36Sopenharmony_ci		chain = cur_chain->next;
457862306a36Sopenharmony_ci		devm_kfree(&pdev->dev, cur_chain);
457962306a36Sopenharmony_ci		cur_chain = chain;
458062306a36Sopenharmony_ci	}
458162306a36Sopenharmony_ci
458262306a36Sopenharmony_ci	return NULL;
458362306a36Sopenharmony_ci}
458462306a36Sopenharmony_ci
458562306a36Sopenharmony_cistatic void hns3_free_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
458662306a36Sopenharmony_ci					struct hnae3_ring_chain_node *head)
458762306a36Sopenharmony_ci{
458862306a36Sopenharmony_ci	struct pci_dev *pdev = tqp_vector->handle->pdev;
458962306a36Sopenharmony_ci	struct hnae3_ring_chain_node *chain_tmp, *chain;
459062306a36Sopenharmony_ci
459162306a36Sopenharmony_ci	chain = head;
459262306a36Sopenharmony_ci
459362306a36Sopenharmony_ci	while (chain) {
459462306a36Sopenharmony_ci		chain_tmp = chain->next;
459562306a36Sopenharmony_ci		devm_kfree(&pdev->dev, chain);
459662306a36Sopenharmony_ci		chain = chain_tmp;
459762306a36Sopenharmony_ci	}
459862306a36Sopenharmony_ci}
459962306a36Sopenharmony_ci
460062306a36Sopenharmony_cistatic void hns3_add_ring_to_group(struct hns3_enet_ring_group *group,
460162306a36Sopenharmony_ci				   struct hns3_enet_ring *ring)
460262306a36Sopenharmony_ci{
460362306a36Sopenharmony_ci	ring->next = group->ring;
460462306a36Sopenharmony_ci	group->ring = ring;
460562306a36Sopenharmony_ci
460662306a36Sopenharmony_ci	group->count++;
460762306a36Sopenharmony_ci}
460862306a36Sopenharmony_ci
460962306a36Sopenharmony_cistatic void hns3_nic_set_cpumask(struct hns3_nic_priv *priv)
461062306a36Sopenharmony_ci{
461162306a36Sopenharmony_ci	struct pci_dev *pdev = priv->ae_handle->pdev;
461262306a36Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector;
461362306a36Sopenharmony_ci	int num_vectors = priv->vector_num;
461462306a36Sopenharmony_ci	int numa_node;
461562306a36Sopenharmony_ci	int vector_i;
461662306a36Sopenharmony_ci
461762306a36Sopenharmony_ci	numa_node = dev_to_node(&pdev->dev);
461862306a36Sopenharmony_ci
461962306a36Sopenharmony_ci	for (vector_i = 0; vector_i < num_vectors; vector_i++) {
462062306a36Sopenharmony_ci		tqp_vector = &priv->tqp_vector[vector_i];
462162306a36Sopenharmony_ci		cpumask_set_cpu(cpumask_local_spread(vector_i, numa_node),
462262306a36Sopenharmony_ci				&tqp_vector->affinity_mask);
462362306a36Sopenharmony_ci	}
462462306a36Sopenharmony_ci}
462562306a36Sopenharmony_ci
462662306a36Sopenharmony_cistatic void hns3_rx_dim_work(struct work_struct *work)
462762306a36Sopenharmony_ci{
462862306a36Sopenharmony_ci	struct dim *dim = container_of(work, struct dim, work);
462962306a36Sopenharmony_ci	struct hns3_enet_ring_group *group = container_of(dim,
463062306a36Sopenharmony_ci		struct hns3_enet_ring_group, dim);
463162306a36Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector = group->ring->tqp_vector;
463262306a36Sopenharmony_ci	struct dim_cq_moder cur_moder =
463362306a36Sopenharmony_ci		net_dim_get_rx_moderation(dim->mode, dim->profile_ix);
463462306a36Sopenharmony_ci
463562306a36Sopenharmony_ci	hns3_set_vector_coalesce_rx_gl(group->ring->tqp_vector, cur_moder.usec);
463662306a36Sopenharmony_ci	tqp_vector->rx_group.coal.int_gl = cur_moder.usec;
463762306a36Sopenharmony_ci
463862306a36Sopenharmony_ci	if (cur_moder.pkts < tqp_vector->rx_group.coal.int_ql_max) {
463962306a36Sopenharmony_ci		hns3_set_vector_coalesce_rx_ql(tqp_vector, cur_moder.pkts);
464062306a36Sopenharmony_ci		tqp_vector->rx_group.coal.int_ql = cur_moder.pkts;
464162306a36Sopenharmony_ci	}
464262306a36Sopenharmony_ci
464362306a36Sopenharmony_ci	dim->state = DIM_START_MEASURE;
464462306a36Sopenharmony_ci}
464562306a36Sopenharmony_ci
464662306a36Sopenharmony_cistatic void hns3_tx_dim_work(struct work_struct *work)
464762306a36Sopenharmony_ci{
464862306a36Sopenharmony_ci	struct dim *dim = container_of(work, struct dim, work);
464962306a36Sopenharmony_ci	struct hns3_enet_ring_group *group = container_of(dim,
465062306a36Sopenharmony_ci		struct hns3_enet_ring_group, dim);
465162306a36Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector = group->ring->tqp_vector;
465262306a36Sopenharmony_ci	struct dim_cq_moder cur_moder =
465362306a36Sopenharmony_ci		net_dim_get_tx_moderation(dim->mode, dim->profile_ix);
465462306a36Sopenharmony_ci
465562306a36Sopenharmony_ci	hns3_set_vector_coalesce_tx_gl(tqp_vector, cur_moder.usec);
465662306a36Sopenharmony_ci	tqp_vector->tx_group.coal.int_gl = cur_moder.usec;
465762306a36Sopenharmony_ci
465862306a36Sopenharmony_ci	if (cur_moder.pkts < tqp_vector->tx_group.coal.int_ql_max) {
465962306a36Sopenharmony_ci		hns3_set_vector_coalesce_tx_ql(tqp_vector, cur_moder.pkts);
466062306a36Sopenharmony_ci		tqp_vector->tx_group.coal.int_ql = cur_moder.pkts;
466162306a36Sopenharmony_ci	}
466262306a36Sopenharmony_ci
466362306a36Sopenharmony_ci	dim->state = DIM_START_MEASURE;
466462306a36Sopenharmony_ci}
466562306a36Sopenharmony_ci
466662306a36Sopenharmony_cistatic void hns3_nic_init_dim(struct hns3_enet_tqp_vector *tqp_vector)
466762306a36Sopenharmony_ci{
466862306a36Sopenharmony_ci	INIT_WORK(&tqp_vector->rx_group.dim.work, hns3_rx_dim_work);
466962306a36Sopenharmony_ci	INIT_WORK(&tqp_vector->tx_group.dim.work, hns3_tx_dim_work);
467062306a36Sopenharmony_ci}
467162306a36Sopenharmony_ci
467262306a36Sopenharmony_cistatic int hns3_nic_init_vector_data(struct hns3_nic_priv *priv)
467362306a36Sopenharmony_ci{
467462306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
467562306a36Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector;
467662306a36Sopenharmony_ci	int ret;
467762306a36Sopenharmony_ci	int i;
467862306a36Sopenharmony_ci
467962306a36Sopenharmony_ci	hns3_nic_set_cpumask(priv);
468062306a36Sopenharmony_ci
468162306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
468262306a36Sopenharmony_ci		tqp_vector = &priv->tqp_vector[i];
468362306a36Sopenharmony_ci		hns3_vector_coalesce_init_hw(tqp_vector, priv);
468462306a36Sopenharmony_ci		tqp_vector->num_tqps = 0;
468562306a36Sopenharmony_ci		hns3_nic_init_dim(tqp_vector);
468662306a36Sopenharmony_ci	}
468762306a36Sopenharmony_ci
468862306a36Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++) {
468962306a36Sopenharmony_ci		u16 vector_i = i % priv->vector_num;
469062306a36Sopenharmony_ci		u16 tqp_num = h->kinfo.num_tqps;
469162306a36Sopenharmony_ci
469262306a36Sopenharmony_ci		tqp_vector = &priv->tqp_vector[vector_i];
469362306a36Sopenharmony_ci
469462306a36Sopenharmony_ci		hns3_add_ring_to_group(&tqp_vector->tx_group,
469562306a36Sopenharmony_ci				       &priv->ring[i]);
469662306a36Sopenharmony_ci
469762306a36Sopenharmony_ci		hns3_add_ring_to_group(&tqp_vector->rx_group,
469862306a36Sopenharmony_ci				       &priv->ring[i + tqp_num]);
469962306a36Sopenharmony_ci
470062306a36Sopenharmony_ci		priv->ring[i].tqp_vector = tqp_vector;
470162306a36Sopenharmony_ci		priv->ring[i + tqp_num].tqp_vector = tqp_vector;
470262306a36Sopenharmony_ci		tqp_vector->num_tqps++;
470362306a36Sopenharmony_ci	}
470462306a36Sopenharmony_ci
470562306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
470662306a36Sopenharmony_ci		struct hnae3_ring_chain_node *vector_ring_chain;
470762306a36Sopenharmony_ci
470862306a36Sopenharmony_ci		tqp_vector = &priv->tqp_vector[i];
470962306a36Sopenharmony_ci
471062306a36Sopenharmony_ci		tqp_vector->rx_group.total_bytes = 0;
471162306a36Sopenharmony_ci		tqp_vector->rx_group.total_packets = 0;
471262306a36Sopenharmony_ci		tqp_vector->tx_group.total_bytes = 0;
471362306a36Sopenharmony_ci		tqp_vector->tx_group.total_packets = 0;
471462306a36Sopenharmony_ci		tqp_vector->handle = h;
471562306a36Sopenharmony_ci
471662306a36Sopenharmony_ci		vector_ring_chain = hns3_get_vector_ring_chain(tqp_vector);
471762306a36Sopenharmony_ci		if (!vector_ring_chain) {
471862306a36Sopenharmony_ci			ret = -ENOMEM;
471962306a36Sopenharmony_ci			goto map_ring_fail;
472062306a36Sopenharmony_ci		}
472162306a36Sopenharmony_ci
472262306a36Sopenharmony_ci		ret = h->ae_algo->ops->map_ring_to_vector(h,
472362306a36Sopenharmony_ci			tqp_vector->vector_irq, vector_ring_chain);
472462306a36Sopenharmony_ci
472562306a36Sopenharmony_ci		hns3_free_vector_ring_chain(tqp_vector, vector_ring_chain);
472662306a36Sopenharmony_ci
472762306a36Sopenharmony_ci		if (ret)
472862306a36Sopenharmony_ci			goto map_ring_fail;
472962306a36Sopenharmony_ci
473062306a36Sopenharmony_ci		netif_napi_add(priv->netdev, &tqp_vector->napi,
473162306a36Sopenharmony_ci			       hns3_nic_common_poll);
473262306a36Sopenharmony_ci	}
473362306a36Sopenharmony_ci
473462306a36Sopenharmony_ci	return 0;
473562306a36Sopenharmony_ci
473662306a36Sopenharmony_cimap_ring_fail:
473762306a36Sopenharmony_ci	while (i--)
473862306a36Sopenharmony_ci		netif_napi_del(&priv->tqp_vector[i].napi);
473962306a36Sopenharmony_ci
474062306a36Sopenharmony_ci	return ret;
474162306a36Sopenharmony_ci}
474262306a36Sopenharmony_ci
474362306a36Sopenharmony_cistatic void hns3_nic_init_coal_cfg(struct hns3_nic_priv *priv)
474462306a36Sopenharmony_ci{
474562306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(priv->ae_handle->pdev);
474662306a36Sopenharmony_ci	struct hns3_enet_coalesce *tx_coal = &priv->tx_coal;
474762306a36Sopenharmony_ci	struct hns3_enet_coalesce *rx_coal = &priv->rx_coal;
474862306a36Sopenharmony_ci
474962306a36Sopenharmony_ci	/* initialize the configuration for interrupt coalescing.
475062306a36Sopenharmony_ci	 * 1. GL (Interrupt Gap Limiter)
475162306a36Sopenharmony_ci	 * 2. RL (Interrupt Rate Limiter)
475262306a36Sopenharmony_ci	 * 3. QL (Interrupt Quantity Limiter)
475362306a36Sopenharmony_ci	 *
475462306a36Sopenharmony_ci	 * Default: enable interrupt coalescing self-adaptive and GL
475562306a36Sopenharmony_ci	 */
475662306a36Sopenharmony_ci	tx_coal->adapt_enable = 1;
475762306a36Sopenharmony_ci	rx_coal->adapt_enable = 1;
475862306a36Sopenharmony_ci
475962306a36Sopenharmony_ci	tx_coal->int_gl = HNS3_INT_GL_50K;
476062306a36Sopenharmony_ci	rx_coal->int_gl = HNS3_INT_GL_50K;
476162306a36Sopenharmony_ci
476262306a36Sopenharmony_ci	rx_coal->flow_level = HNS3_FLOW_LOW;
476362306a36Sopenharmony_ci	tx_coal->flow_level = HNS3_FLOW_LOW;
476462306a36Sopenharmony_ci
476562306a36Sopenharmony_ci	if (ae_dev->dev_specs.int_ql_max) {
476662306a36Sopenharmony_ci		tx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG;
476762306a36Sopenharmony_ci		rx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG;
476862306a36Sopenharmony_ci	}
476962306a36Sopenharmony_ci}
477062306a36Sopenharmony_ci
477162306a36Sopenharmony_cistatic int hns3_nic_alloc_vector_data(struct hns3_nic_priv *priv)
477262306a36Sopenharmony_ci{
477362306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
477462306a36Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector;
477562306a36Sopenharmony_ci	struct hnae3_vector_info *vector;
477662306a36Sopenharmony_ci	struct pci_dev *pdev = h->pdev;
477762306a36Sopenharmony_ci	u16 tqp_num = h->kinfo.num_tqps;
477862306a36Sopenharmony_ci	u16 vector_num;
477962306a36Sopenharmony_ci	int ret = 0;
478062306a36Sopenharmony_ci	u16 i;
478162306a36Sopenharmony_ci
478262306a36Sopenharmony_ci	/* RSS size, cpu online and vector_num should be the same */
478362306a36Sopenharmony_ci	/* Should consider 2p/4p later */
478462306a36Sopenharmony_ci	vector_num = min_t(u16, num_online_cpus(), tqp_num);
478562306a36Sopenharmony_ci
478662306a36Sopenharmony_ci	vector = devm_kcalloc(&pdev->dev, vector_num, sizeof(*vector),
478762306a36Sopenharmony_ci			      GFP_KERNEL);
478862306a36Sopenharmony_ci	if (!vector)
478962306a36Sopenharmony_ci		return -ENOMEM;
479062306a36Sopenharmony_ci
479162306a36Sopenharmony_ci	/* save the actual available vector number */
479262306a36Sopenharmony_ci	vector_num = h->ae_algo->ops->get_vector(h, vector_num, vector);
479362306a36Sopenharmony_ci
479462306a36Sopenharmony_ci	priv->vector_num = vector_num;
479562306a36Sopenharmony_ci	priv->tqp_vector = (struct hns3_enet_tqp_vector *)
479662306a36Sopenharmony_ci		devm_kcalloc(&pdev->dev, vector_num, sizeof(*priv->tqp_vector),
479762306a36Sopenharmony_ci			     GFP_KERNEL);
479862306a36Sopenharmony_ci	if (!priv->tqp_vector) {
479962306a36Sopenharmony_ci		ret = -ENOMEM;
480062306a36Sopenharmony_ci		goto out;
480162306a36Sopenharmony_ci	}
480262306a36Sopenharmony_ci
480362306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
480462306a36Sopenharmony_ci		tqp_vector = &priv->tqp_vector[i];
480562306a36Sopenharmony_ci		tqp_vector->idx = i;
480662306a36Sopenharmony_ci		tqp_vector->mask_addr = vector[i].io_addr;
480762306a36Sopenharmony_ci		tqp_vector->vector_irq = vector[i].vector;
480862306a36Sopenharmony_ci		hns3_vector_coalesce_init(tqp_vector, priv);
480962306a36Sopenharmony_ci	}
481062306a36Sopenharmony_ci
481162306a36Sopenharmony_ciout:
481262306a36Sopenharmony_ci	devm_kfree(&pdev->dev, vector);
481362306a36Sopenharmony_ci	return ret;
481462306a36Sopenharmony_ci}
481562306a36Sopenharmony_ci
481662306a36Sopenharmony_cistatic void hns3_clear_ring_group(struct hns3_enet_ring_group *group)
481762306a36Sopenharmony_ci{
481862306a36Sopenharmony_ci	group->ring = NULL;
481962306a36Sopenharmony_ci	group->count = 0;
482062306a36Sopenharmony_ci}
482162306a36Sopenharmony_ci
482262306a36Sopenharmony_cistatic void hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv)
482362306a36Sopenharmony_ci{
482462306a36Sopenharmony_ci	struct hnae3_ring_chain_node *vector_ring_chain;
482562306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
482662306a36Sopenharmony_ci	struct hns3_enet_tqp_vector *tqp_vector;
482762306a36Sopenharmony_ci	int i;
482862306a36Sopenharmony_ci
482962306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
483062306a36Sopenharmony_ci		tqp_vector = &priv->tqp_vector[i];
483162306a36Sopenharmony_ci
483262306a36Sopenharmony_ci		if (!tqp_vector->rx_group.ring && !tqp_vector->tx_group.ring)
483362306a36Sopenharmony_ci			continue;
483462306a36Sopenharmony_ci
483562306a36Sopenharmony_ci		/* Since the mapping can be overwritten, when fail to get the
483662306a36Sopenharmony_ci		 * chain between vector and ring, we should go on to deal with
483762306a36Sopenharmony_ci		 * the remaining options.
483862306a36Sopenharmony_ci		 */
483962306a36Sopenharmony_ci		vector_ring_chain = hns3_get_vector_ring_chain(tqp_vector);
484062306a36Sopenharmony_ci		if (!vector_ring_chain)
484162306a36Sopenharmony_ci			dev_warn(priv->dev, "failed to get ring chain\n");
484262306a36Sopenharmony_ci
484362306a36Sopenharmony_ci		h->ae_algo->ops->unmap_ring_from_vector(h,
484462306a36Sopenharmony_ci			tqp_vector->vector_irq, vector_ring_chain);
484562306a36Sopenharmony_ci
484662306a36Sopenharmony_ci		hns3_free_vector_ring_chain(tqp_vector, vector_ring_chain);
484762306a36Sopenharmony_ci
484862306a36Sopenharmony_ci		hns3_clear_ring_group(&tqp_vector->rx_group);
484962306a36Sopenharmony_ci		hns3_clear_ring_group(&tqp_vector->tx_group);
485062306a36Sopenharmony_ci		netif_napi_del(&priv->tqp_vector[i].napi);
485162306a36Sopenharmony_ci	}
485262306a36Sopenharmony_ci}
485362306a36Sopenharmony_ci
485462306a36Sopenharmony_cistatic void hns3_nic_dealloc_vector_data(struct hns3_nic_priv *priv)
485562306a36Sopenharmony_ci{
485662306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
485762306a36Sopenharmony_ci	struct pci_dev *pdev = h->pdev;
485862306a36Sopenharmony_ci	int i, ret;
485962306a36Sopenharmony_ci
486062306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++) {
486162306a36Sopenharmony_ci		struct hns3_enet_tqp_vector *tqp_vector;
486262306a36Sopenharmony_ci
486362306a36Sopenharmony_ci		tqp_vector = &priv->tqp_vector[i];
486462306a36Sopenharmony_ci		ret = h->ae_algo->ops->put_vector(h, tqp_vector->vector_irq);
486562306a36Sopenharmony_ci		if (ret)
486662306a36Sopenharmony_ci			return;
486762306a36Sopenharmony_ci	}
486862306a36Sopenharmony_ci
486962306a36Sopenharmony_ci	devm_kfree(&pdev->dev, priv->tqp_vector);
487062306a36Sopenharmony_ci}
487162306a36Sopenharmony_ci
487262306a36Sopenharmony_cistatic void hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv,
487362306a36Sopenharmony_ci			      unsigned int ring_type)
487462306a36Sopenharmony_ci{
487562306a36Sopenharmony_ci	int queue_num = priv->ae_handle->kinfo.num_tqps;
487662306a36Sopenharmony_ci	struct hns3_enet_ring *ring;
487762306a36Sopenharmony_ci	int desc_num;
487862306a36Sopenharmony_ci
487962306a36Sopenharmony_ci	if (ring_type == HNAE3_RING_TYPE_TX) {
488062306a36Sopenharmony_ci		ring = &priv->ring[q->tqp_index];
488162306a36Sopenharmony_ci		desc_num = priv->ae_handle->kinfo.num_tx_desc;
488262306a36Sopenharmony_ci		ring->queue_index = q->tqp_index;
488362306a36Sopenharmony_ci		ring->tx_copybreak = priv->tx_copybreak;
488462306a36Sopenharmony_ci		ring->last_to_use = 0;
488562306a36Sopenharmony_ci	} else {
488662306a36Sopenharmony_ci		ring = &priv->ring[q->tqp_index + queue_num];
488762306a36Sopenharmony_ci		desc_num = priv->ae_handle->kinfo.num_rx_desc;
488862306a36Sopenharmony_ci		ring->queue_index = q->tqp_index;
488962306a36Sopenharmony_ci		ring->rx_copybreak = priv->rx_copybreak;
489062306a36Sopenharmony_ci	}
489162306a36Sopenharmony_ci
489262306a36Sopenharmony_ci	hnae3_set_bit(ring->flag, HNAE3_RING_TYPE_B, ring_type);
489362306a36Sopenharmony_ci
489462306a36Sopenharmony_ci	ring->tqp = q;
489562306a36Sopenharmony_ci	ring->desc = NULL;
489662306a36Sopenharmony_ci	ring->desc_cb = NULL;
489762306a36Sopenharmony_ci	ring->dev = priv->dev;
489862306a36Sopenharmony_ci	ring->desc_dma_addr = 0;
489962306a36Sopenharmony_ci	ring->buf_size = q->buf_size;
490062306a36Sopenharmony_ci	ring->desc_num = desc_num;
490162306a36Sopenharmony_ci	ring->next_to_use = 0;
490262306a36Sopenharmony_ci	ring->next_to_clean = 0;
490362306a36Sopenharmony_ci}
490462306a36Sopenharmony_ci
490562306a36Sopenharmony_cistatic void hns3_queue_to_ring(struct hnae3_queue *tqp,
490662306a36Sopenharmony_ci			       struct hns3_nic_priv *priv)
490762306a36Sopenharmony_ci{
490862306a36Sopenharmony_ci	hns3_ring_get_cfg(tqp, priv, HNAE3_RING_TYPE_TX);
490962306a36Sopenharmony_ci	hns3_ring_get_cfg(tqp, priv, HNAE3_RING_TYPE_RX);
491062306a36Sopenharmony_ci}
491162306a36Sopenharmony_ci
491262306a36Sopenharmony_cistatic int hns3_get_ring_config(struct hns3_nic_priv *priv)
491362306a36Sopenharmony_ci{
491462306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
491562306a36Sopenharmony_ci	struct pci_dev *pdev = h->pdev;
491662306a36Sopenharmony_ci	int i;
491762306a36Sopenharmony_ci
491862306a36Sopenharmony_ci	priv->ring = devm_kzalloc(&pdev->dev,
491962306a36Sopenharmony_ci				  array3_size(h->kinfo.num_tqps,
492062306a36Sopenharmony_ci					      sizeof(*priv->ring), 2),
492162306a36Sopenharmony_ci				  GFP_KERNEL);
492262306a36Sopenharmony_ci	if (!priv->ring)
492362306a36Sopenharmony_ci		return -ENOMEM;
492462306a36Sopenharmony_ci
492562306a36Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++)
492662306a36Sopenharmony_ci		hns3_queue_to_ring(h->kinfo.tqp[i], priv);
492762306a36Sopenharmony_ci
492862306a36Sopenharmony_ci	return 0;
492962306a36Sopenharmony_ci}
493062306a36Sopenharmony_ci
493162306a36Sopenharmony_cistatic void hns3_put_ring_config(struct hns3_nic_priv *priv)
493262306a36Sopenharmony_ci{
493362306a36Sopenharmony_ci	if (!priv->ring)
493462306a36Sopenharmony_ci		return;
493562306a36Sopenharmony_ci
493662306a36Sopenharmony_ci	devm_kfree(priv->dev, priv->ring);
493762306a36Sopenharmony_ci	priv->ring = NULL;
493862306a36Sopenharmony_ci}
493962306a36Sopenharmony_ci
494062306a36Sopenharmony_cistatic void hns3_alloc_page_pool(struct hns3_enet_ring *ring)
494162306a36Sopenharmony_ci{
494262306a36Sopenharmony_ci	struct page_pool_params pp_params = {
494362306a36Sopenharmony_ci		.flags = PP_FLAG_DMA_MAP | PP_FLAG_PAGE_FRAG |
494462306a36Sopenharmony_ci				PP_FLAG_DMA_SYNC_DEV,
494562306a36Sopenharmony_ci		.order = hns3_page_order(ring),
494662306a36Sopenharmony_ci		.pool_size = ring->desc_num * hns3_buf_size(ring) /
494762306a36Sopenharmony_ci				(PAGE_SIZE << hns3_page_order(ring)),
494862306a36Sopenharmony_ci		.nid = dev_to_node(ring_to_dev(ring)),
494962306a36Sopenharmony_ci		.dev = ring_to_dev(ring),
495062306a36Sopenharmony_ci		.dma_dir = DMA_FROM_DEVICE,
495162306a36Sopenharmony_ci		.offset = 0,
495262306a36Sopenharmony_ci		.max_len = PAGE_SIZE << hns3_page_order(ring),
495362306a36Sopenharmony_ci	};
495462306a36Sopenharmony_ci
495562306a36Sopenharmony_ci	ring->page_pool = page_pool_create(&pp_params);
495662306a36Sopenharmony_ci	if (IS_ERR(ring->page_pool)) {
495762306a36Sopenharmony_ci		dev_warn(ring_to_dev(ring), "page pool creation failed: %ld\n",
495862306a36Sopenharmony_ci			 PTR_ERR(ring->page_pool));
495962306a36Sopenharmony_ci		ring->page_pool = NULL;
496062306a36Sopenharmony_ci	}
496162306a36Sopenharmony_ci}
496262306a36Sopenharmony_ci
496362306a36Sopenharmony_cistatic int hns3_alloc_ring_memory(struct hns3_enet_ring *ring)
496462306a36Sopenharmony_ci{
496562306a36Sopenharmony_ci	int ret;
496662306a36Sopenharmony_ci
496762306a36Sopenharmony_ci	if (ring->desc_num <= 0 || ring->buf_size <= 0)
496862306a36Sopenharmony_ci		return -EINVAL;
496962306a36Sopenharmony_ci
497062306a36Sopenharmony_ci	ring->desc_cb = devm_kcalloc(ring_to_dev(ring), ring->desc_num,
497162306a36Sopenharmony_ci				     sizeof(ring->desc_cb[0]), GFP_KERNEL);
497262306a36Sopenharmony_ci	if (!ring->desc_cb) {
497362306a36Sopenharmony_ci		ret = -ENOMEM;
497462306a36Sopenharmony_ci		goto out;
497562306a36Sopenharmony_ci	}
497662306a36Sopenharmony_ci
497762306a36Sopenharmony_ci	ret = hns3_alloc_desc(ring);
497862306a36Sopenharmony_ci	if (ret)
497962306a36Sopenharmony_ci		goto out_with_desc_cb;
498062306a36Sopenharmony_ci
498162306a36Sopenharmony_ci	if (!HNAE3_IS_TX_RING(ring)) {
498262306a36Sopenharmony_ci		if (page_pool_enabled)
498362306a36Sopenharmony_ci			hns3_alloc_page_pool(ring);
498462306a36Sopenharmony_ci
498562306a36Sopenharmony_ci		ret = hns3_alloc_ring_buffers(ring);
498662306a36Sopenharmony_ci		if (ret)
498762306a36Sopenharmony_ci			goto out_with_desc;
498862306a36Sopenharmony_ci	} else {
498962306a36Sopenharmony_ci		hns3_init_tx_spare_buffer(ring);
499062306a36Sopenharmony_ci	}
499162306a36Sopenharmony_ci
499262306a36Sopenharmony_ci	return 0;
499362306a36Sopenharmony_ci
499462306a36Sopenharmony_ciout_with_desc:
499562306a36Sopenharmony_ci	hns3_free_desc(ring);
499662306a36Sopenharmony_ciout_with_desc_cb:
499762306a36Sopenharmony_ci	devm_kfree(ring_to_dev(ring), ring->desc_cb);
499862306a36Sopenharmony_ci	ring->desc_cb = NULL;
499962306a36Sopenharmony_ciout:
500062306a36Sopenharmony_ci	return ret;
500162306a36Sopenharmony_ci}
500262306a36Sopenharmony_ci
500362306a36Sopenharmony_civoid hns3_fini_ring(struct hns3_enet_ring *ring)
500462306a36Sopenharmony_ci{
500562306a36Sopenharmony_ci	hns3_free_desc(ring);
500662306a36Sopenharmony_ci	devm_kfree(ring_to_dev(ring), ring->desc_cb);
500762306a36Sopenharmony_ci	ring->desc_cb = NULL;
500862306a36Sopenharmony_ci	ring->next_to_clean = 0;
500962306a36Sopenharmony_ci	ring->next_to_use = 0;
501062306a36Sopenharmony_ci	ring->last_to_use = 0;
501162306a36Sopenharmony_ci	ring->pending_buf = 0;
501262306a36Sopenharmony_ci	if (!HNAE3_IS_TX_RING(ring) && ring->skb) {
501362306a36Sopenharmony_ci		dev_kfree_skb_any(ring->skb);
501462306a36Sopenharmony_ci		ring->skb = NULL;
501562306a36Sopenharmony_ci	} else if (HNAE3_IS_TX_RING(ring) && ring->tx_spare) {
501662306a36Sopenharmony_ci		struct hns3_tx_spare *tx_spare = ring->tx_spare;
501762306a36Sopenharmony_ci
501862306a36Sopenharmony_ci		dma_unmap_page(ring_to_dev(ring), tx_spare->dma, tx_spare->len,
501962306a36Sopenharmony_ci			       DMA_TO_DEVICE);
502062306a36Sopenharmony_ci		free_pages((unsigned long)tx_spare->buf,
502162306a36Sopenharmony_ci			   get_order(tx_spare->len));
502262306a36Sopenharmony_ci		devm_kfree(ring_to_dev(ring), tx_spare);
502362306a36Sopenharmony_ci		ring->tx_spare = NULL;
502462306a36Sopenharmony_ci	}
502562306a36Sopenharmony_ci
502662306a36Sopenharmony_ci	if (!HNAE3_IS_TX_RING(ring) && ring->page_pool) {
502762306a36Sopenharmony_ci		page_pool_destroy(ring->page_pool);
502862306a36Sopenharmony_ci		ring->page_pool = NULL;
502962306a36Sopenharmony_ci	}
503062306a36Sopenharmony_ci}
503162306a36Sopenharmony_ci
503262306a36Sopenharmony_cistatic int hns3_buf_size2type(u32 buf_size)
503362306a36Sopenharmony_ci{
503462306a36Sopenharmony_ci	int bd_size_type;
503562306a36Sopenharmony_ci
503662306a36Sopenharmony_ci	switch (buf_size) {
503762306a36Sopenharmony_ci	case 512:
503862306a36Sopenharmony_ci		bd_size_type = HNS3_BD_SIZE_512_TYPE;
503962306a36Sopenharmony_ci		break;
504062306a36Sopenharmony_ci	case 1024:
504162306a36Sopenharmony_ci		bd_size_type = HNS3_BD_SIZE_1024_TYPE;
504262306a36Sopenharmony_ci		break;
504362306a36Sopenharmony_ci	case 2048:
504462306a36Sopenharmony_ci		bd_size_type = HNS3_BD_SIZE_2048_TYPE;
504562306a36Sopenharmony_ci		break;
504662306a36Sopenharmony_ci	case 4096:
504762306a36Sopenharmony_ci		bd_size_type = HNS3_BD_SIZE_4096_TYPE;
504862306a36Sopenharmony_ci		break;
504962306a36Sopenharmony_ci	default:
505062306a36Sopenharmony_ci		bd_size_type = HNS3_BD_SIZE_2048_TYPE;
505162306a36Sopenharmony_ci	}
505262306a36Sopenharmony_ci
505362306a36Sopenharmony_ci	return bd_size_type;
505462306a36Sopenharmony_ci}
505562306a36Sopenharmony_ci
505662306a36Sopenharmony_cistatic void hns3_init_ring_hw(struct hns3_enet_ring *ring)
505762306a36Sopenharmony_ci{
505862306a36Sopenharmony_ci	dma_addr_t dma = ring->desc_dma_addr;
505962306a36Sopenharmony_ci	struct hnae3_queue *q = ring->tqp;
506062306a36Sopenharmony_ci
506162306a36Sopenharmony_ci	if (!HNAE3_IS_TX_RING(ring)) {
506262306a36Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_RX_RING_BASEADDR_L_REG, (u32)dma);
506362306a36Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_RX_RING_BASEADDR_H_REG,
506462306a36Sopenharmony_ci			       (u32)((dma >> 31) >> 1));
506562306a36Sopenharmony_ci
506662306a36Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_RX_RING_BD_LEN_REG,
506762306a36Sopenharmony_ci			       hns3_buf_size2type(ring->buf_size));
506862306a36Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_RX_RING_BD_NUM_REG,
506962306a36Sopenharmony_ci			       ring->desc_num / 8 - 1);
507062306a36Sopenharmony_ci	} else {
507162306a36Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_TX_RING_BASEADDR_L_REG,
507262306a36Sopenharmony_ci			       (u32)dma);
507362306a36Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_TX_RING_BASEADDR_H_REG,
507462306a36Sopenharmony_ci			       (u32)((dma >> 31) >> 1));
507562306a36Sopenharmony_ci
507662306a36Sopenharmony_ci		hns3_write_dev(q, HNS3_RING_TX_RING_BD_NUM_REG,
507762306a36Sopenharmony_ci			       ring->desc_num / 8 - 1);
507862306a36Sopenharmony_ci	}
507962306a36Sopenharmony_ci}
508062306a36Sopenharmony_ci
508162306a36Sopenharmony_cistatic void hns3_init_tx_ring_tc(struct hns3_nic_priv *priv)
508262306a36Sopenharmony_ci{
508362306a36Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &priv->ae_handle->kinfo;
508462306a36Sopenharmony_ci	struct hnae3_tc_info *tc_info = &kinfo->tc_info;
508562306a36Sopenharmony_ci	int i;
508662306a36Sopenharmony_ci
508762306a36Sopenharmony_ci	for (i = 0; i < tc_info->num_tc; i++) {
508862306a36Sopenharmony_ci		int j;
508962306a36Sopenharmony_ci
509062306a36Sopenharmony_ci		for (j = 0; j < tc_info->tqp_count[i]; j++) {
509162306a36Sopenharmony_ci			struct hnae3_queue *q;
509262306a36Sopenharmony_ci
509362306a36Sopenharmony_ci			q = priv->ring[tc_info->tqp_offset[i] + j].tqp;
509462306a36Sopenharmony_ci			hns3_write_dev(q, HNS3_RING_TX_RING_TC_REG, i);
509562306a36Sopenharmony_ci		}
509662306a36Sopenharmony_ci	}
509762306a36Sopenharmony_ci}
509862306a36Sopenharmony_ci
509962306a36Sopenharmony_ciint hns3_init_all_ring(struct hns3_nic_priv *priv)
510062306a36Sopenharmony_ci{
510162306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
510262306a36Sopenharmony_ci	int ring_num = h->kinfo.num_tqps * 2;
510362306a36Sopenharmony_ci	int i, j;
510462306a36Sopenharmony_ci	int ret;
510562306a36Sopenharmony_ci
510662306a36Sopenharmony_ci	for (i = 0; i < ring_num; i++) {
510762306a36Sopenharmony_ci		ret = hns3_alloc_ring_memory(&priv->ring[i]);
510862306a36Sopenharmony_ci		if (ret) {
510962306a36Sopenharmony_ci			dev_err(priv->dev,
511062306a36Sopenharmony_ci				"Alloc ring memory fail! ret=%d\n", ret);
511162306a36Sopenharmony_ci			goto out_when_alloc_ring_memory;
511262306a36Sopenharmony_ci		}
511362306a36Sopenharmony_ci
511462306a36Sopenharmony_ci		u64_stats_init(&priv->ring[i].syncp);
511562306a36Sopenharmony_ci	}
511662306a36Sopenharmony_ci
511762306a36Sopenharmony_ci	return 0;
511862306a36Sopenharmony_ci
511962306a36Sopenharmony_ciout_when_alloc_ring_memory:
512062306a36Sopenharmony_ci	for (j = i - 1; j >= 0; j--)
512162306a36Sopenharmony_ci		hns3_fini_ring(&priv->ring[j]);
512262306a36Sopenharmony_ci
512362306a36Sopenharmony_ci	return -ENOMEM;
512462306a36Sopenharmony_ci}
512562306a36Sopenharmony_ci
512662306a36Sopenharmony_cistatic void hns3_uninit_all_ring(struct hns3_nic_priv *priv)
512762306a36Sopenharmony_ci{
512862306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
512962306a36Sopenharmony_ci	int i;
513062306a36Sopenharmony_ci
513162306a36Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++) {
513262306a36Sopenharmony_ci		hns3_fini_ring(&priv->ring[i]);
513362306a36Sopenharmony_ci		hns3_fini_ring(&priv->ring[i + h->kinfo.num_tqps]);
513462306a36Sopenharmony_ci	}
513562306a36Sopenharmony_ci}
513662306a36Sopenharmony_ci
513762306a36Sopenharmony_ci/* Set mac addr if it is configured. or leave it to the AE driver */
513862306a36Sopenharmony_cistatic int hns3_init_mac_addr(struct net_device *netdev)
513962306a36Sopenharmony_ci{
514062306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
514162306a36Sopenharmony_ci	char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
514262306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
514362306a36Sopenharmony_ci	u8 mac_addr_temp[ETH_ALEN] = {0};
514462306a36Sopenharmony_ci	int ret = 0;
514562306a36Sopenharmony_ci
514662306a36Sopenharmony_ci	if (h->ae_algo->ops->get_mac_addr)
514762306a36Sopenharmony_ci		h->ae_algo->ops->get_mac_addr(h, mac_addr_temp);
514862306a36Sopenharmony_ci
514962306a36Sopenharmony_ci	/* Check if the MAC address is valid, if not get a random one */
515062306a36Sopenharmony_ci	if (!is_valid_ether_addr(mac_addr_temp)) {
515162306a36Sopenharmony_ci		eth_hw_addr_random(netdev);
515262306a36Sopenharmony_ci		hnae3_format_mac_addr(format_mac_addr, netdev->dev_addr);
515362306a36Sopenharmony_ci		dev_warn(priv->dev, "using random MAC address %s\n",
515462306a36Sopenharmony_ci			 format_mac_addr);
515562306a36Sopenharmony_ci	} else if (!ether_addr_equal(netdev->dev_addr, mac_addr_temp)) {
515662306a36Sopenharmony_ci		eth_hw_addr_set(netdev, mac_addr_temp);
515762306a36Sopenharmony_ci		ether_addr_copy(netdev->perm_addr, mac_addr_temp);
515862306a36Sopenharmony_ci	} else {
515962306a36Sopenharmony_ci		return 0;
516062306a36Sopenharmony_ci	}
516162306a36Sopenharmony_ci
516262306a36Sopenharmony_ci	if (h->ae_algo->ops->set_mac_addr)
516362306a36Sopenharmony_ci		ret = h->ae_algo->ops->set_mac_addr(h, netdev->dev_addr, true);
516462306a36Sopenharmony_ci
516562306a36Sopenharmony_ci	return ret;
516662306a36Sopenharmony_ci}
516762306a36Sopenharmony_ci
516862306a36Sopenharmony_cistatic int hns3_init_phy(struct net_device *netdev)
516962306a36Sopenharmony_ci{
517062306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
517162306a36Sopenharmony_ci	int ret = 0;
517262306a36Sopenharmony_ci
517362306a36Sopenharmony_ci	if (h->ae_algo->ops->mac_connect_phy)
517462306a36Sopenharmony_ci		ret = h->ae_algo->ops->mac_connect_phy(h);
517562306a36Sopenharmony_ci
517662306a36Sopenharmony_ci	return ret;
517762306a36Sopenharmony_ci}
517862306a36Sopenharmony_ci
517962306a36Sopenharmony_cistatic void hns3_uninit_phy(struct net_device *netdev)
518062306a36Sopenharmony_ci{
518162306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
518262306a36Sopenharmony_ci
518362306a36Sopenharmony_ci	if (h->ae_algo->ops->mac_disconnect_phy)
518462306a36Sopenharmony_ci		h->ae_algo->ops->mac_disconnect_phy(h);
518562306a36Sopenharmony_ci}
518662306a36Sopenharmony_ci
518762306a36Sopenharmony_cistatic int hns3_client_start(struct hnae3_handle *handle)
518862306a36Sopenharmony_ci{
518962306a36Sopenharmony_ci	if (!handle->ae_algo->ops->client_start)
519062306a36Sopenharmony_ci		return 0;
519162306a36Sopenharmony_ci
519262306a36Sopenharmony_ci	return handle->ae_algo->ops->client_start(handle);
519362306a36Sopenharmony_ci}
519462306a36Sopenharmony_ci
519562306a36Sopenharmony_cistatic void hns3_client_stop(struct hnae3_handle *handle)
519662306a36Sopenharmony_ci{
519762306a36Sopenharmony_ci	if (!handle->ae_algo->ops->client_stop)
519862306a36Sopenharmony_ci		return;
519962306a36Sopenharmony_ci
520062306a36Sopenharmony_ci	handle->ae_algo->ops->client_stop(handle);
520162306a36Sopenharmony_ci}
520262306a36Sopenharmony_ci
520362306a36Sopenharmony_cistatic void hns3_info_show(struct hns3_nic_priv *priv)
520462306a36Sopenharmony_ci{
520562306a36Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &priv->ae_handle->kinfo;
520662306a36Sopenharmony_ci	char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
520762306a36Sopenharmony_ci
520862306a36Sopenharmony_ci	hnae3_format_mac_addr(format_mac_addr, priv->netdev->dev_addr);
520962306a36Sopenharmony_ci	dev_info(priv->dev, "MAC address: %s\n", format_mac_addr);
521062306a36Sopenharmony_ci	dev_info(priv->dev, "Task queue pairs numbers: %u\n", kinfo->num_tqps);
521162306a36Sopenharmony_ci	dev_info(priv->dev, "RSS size: %u\n", kinfo->rss_size);
521262306a36Sopenharmony_ci	dev_info(priv->dev, "Allocated RSS size: %u\n", kinfo->req_rss_size);
521362306a36Sopenharmony_ci	dev_info(priv->dev, "RX buffer length: %u\n", kinfo->rx_buf_len);
521462306a36Sopenharmony_ci	dev_info(priv->dev, "Desc num per TX queue: %u\n", kinfo->num_tx_desc);
521562306a36Sopenharmony_ci	dev_info(priv->dev, "Desc num per RX queue: %u\n", kinfo->num_rx_desc);
521662306a36Sopenharmony_ci	dev_info(priv->dev, "Total number of enabled TCs: %u\n",
521762306a36Sopenharmony_ci		 kinfo->tc_info.num_tc);
521862306a36Sopenharmony_ci	dev_info(priv->dev, "Max mtu size: %u\n", priv->netdev->max_mtu);
521962306a36Sopenharmony_ci}
522062306a36Sopenharmony_ci
522162306a36Sopenharmony_cistatic void hns3_set_cq_period_mode(struct hns3_nic_priv *priv,
522262306a36Sopenharmony_ci				    enum dim_cq_period_mode mode, bool is_tx)
522362306a36Sopenharmony_ci{
522462306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(priv->ae_handle->pdev);
522562306a36Sopenharmony_ci	struct hnae3_handle *handle = priv->ae_handle;
522662306a36Sopenharmony_ci	int i;
522762306a36Sopenharmony_ci
522862306a36Sopenharmony_ci	if (is_tx) {
522962306a36Sopenharmony_ci		priv->tx_cqe_mode = mode;
523062306a36Sopenharmony_ci
523162306a36Sopenharmony_ci		for (i = 0; i < priv->vector_num; i++)
523262306a36Sopenharmony_ci			priv->tqp_vector[i].tx_group.dim.mode = mode;
523362306a36Sopenharmony_ci	} else {
523462306a36Sopenharmony_ci		priv->rx_cqe_mode = mode;
523562306a36Sopenharmony_ci
523662306a36Sopenharmony_ci		for (i = 0; i < priv->vector_num; i++)
523762306a36Sopenharmony_ci			priv->tqp_vector[i].rx_group.dim.mode = mode;
523862306a36Sopenharmony_ci	}
523962306a36Sopenharmony_ci
524062306a36Sopenharmony_ci	if (hnae3_ae_dev_cq_supported(ae_dev)) {
524162306a36Sopenharmony_ci		u32 new_mode;
524262306a36Sopenharmony_ci		u64 reg;
524362306a36Sopenharmony_ci
524462306a36Sopenharmony_ci		new_mode = (mode == DIM_CQ_PERIOD_MODE_START_FROM_CQE) ?
524562306a36Sopenharmony_ci			HNS3_CQ_MODE_CQE : HNS3_CQ_MODE_EQE;
524662306a36Sopenharmony_ci		reg = is_tx ? HNS3_GL1_CQ_MODE_REG : HNS3_GL0_CQ_MODE_REG;
524762306a36Sopenharmony_ci
524862306a36Sopenharmony_ci		writel(new_mode, handle->kinfo.io_base + reg);
524962306a36Sopenharmony_ci	}
525062306a36Sopenharmony_ci}
525162306a36Sopenharmony_ci
525262306a36Sopenharmony_civoid hns3_cq_period_mode_init(struct hns3_nic_priv *priv,
525362306a36Sopenharmony_ci			      enum dim_cq_period_mode tx_mode,
525462306a36Sopenharmony_ci			      enum dim_cq_period_mode rx_mode)
525562306a36Sopenharmony_ci{
525662306a36Sopenharmony_ci	hns3_set_cq_period_mode(priv, tx_mode, true);
525762306a36Sopenharmony_ci	hns3_set_cq_period_mode(priv, rx_mode, false);
525862306a36Sopenharmony_ci}
525962306a36Sopenharmony_ci
526062306a36Sopenharmony_cistatic void hns3_state_init(struct hnae3_handle *handle)
526162306a36Sopenharmony_ci{
526262306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
526362306a36Sopenharmony_ci	struct net_device *netdev = handle->kinfo.netdev;
526462306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
526562306a36Sopenharmony_ci
526662306a36Sopenharmony_ci	set_bit(HNS3_NIC_STATE_INITED, &priv->state);
526762306a36Sopenharmony_ci
526862306a36Sopenharmony_ci	if (test_bit(HNAE3_DEV_SUPPORT_TX_PUSH_B, ae_dev->caps))
526962306a36Sopenharmony_ci		set_bit(HNS3_NIC_STATE_TX_PUSH_ENABLE, &priv->state);
527062306a36Sopenharmony_ci
527162306a36Sopenharmony_ci	if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3)
527262306a36Sopenharmony_ci		set_bit(HNAE3_PFLAG_LIMIT_PROMISC, &handle->supported_pflags);
527362306a36Sopenharmony_ci
527462306a36Sopenharmony_ci	if (test_bit(HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, ae_dev->caps))
527562306a36Sopenharmony_ci		set_bit(HNS3_NIC_STATE_HW_TX_CSUM_ENABLE, &priv->state);
527662306a36Sopenharmony_ci
527762306a36Sopenharmony_ci	if (hnae3_ae_dev_rxd_adv_layout_supported(ae_dev))
527862306a36Sopenharmony_ci		set_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state);
527962306a36Sopenharmony_ci}
528062306a36Sopenharmony_ci
528162306a36Sopenharmony_cistatic void hns3_state_uninit(struct hnae3_handle *handle)
528262306a36Sopenharmony_ci{
528362306a36Sopenharmony_ci	struct hns3_nic_priv *priv  = handle->priv;
528462306a36Sopenharmony_ci
528562306a36Sopenharmony_ci	clear_bit(HNS3_NIC_STATE_INITED, &priv->state);
528662306a36Sopenharmony_ci}
528762306a36Sopenharmony_ci
528862306a36Sopenharmony_cistatic int hns3_client_init(struct hnae3_handle *handle)
528962306a36Sopenharmony_ci{
529062306a36Sopenharmony_ci	struct pci_dev *pdev = handle->pdev;
529162306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
529262306a36Sopenharmony_ci	u16 alloc_tqps, max_rss_size;
529362306a36Sopenharmony_ci	struct hns3_nic_priv *priv;
529462306a36Sopenharmony_ci	struct net_device *netdev;
529562306a36Sopenharmony_ci	int ret;
529662306a36Sopenharmony_ci
529762306a36Sopenharmony_ci	handle->ae_algo->ops->get_tqps_and_rss_info(handle, &alloc_tqps,
529862306a36Sopenharmony_ci						    &max_rss_size);
529962306a36Sopenharmony_ci	netdev = alloc_etherdev_mq(sizeof(struct hns3_nic_priv), alloc_tqps);
530062306a36Sopenharmony_ci	if (!netdev)
530162306a36Sopenharmony_ci		return -ENOMEM;
530262306a36Sopenharmony_ci
530362306a36Sopenharmony_ci	priv = netdev_priv(netdev);
530462306a36Sopenharmony_ci	priv->dev = &pdev->dev;
530562306a36Sopenharmony_ci	priv->netdev = netdev;
530662306a36Sopenharmony_ci	priv->ae_handle = handle;
530762306a36Sopenharmony_ci	priv->tx_timeout_count = 0;
530862306a36Sopenharmony_ci	priv->max_non_tso_bd_num = ae_dev->dev_specs.max_non_tso_bd_num;
530962306a36Sopenharmony_ci	set_bit(HNS3_NIC_STATE_DOWN, &priv->state);
531062306a36Sopenharmony_ci
531162306a36Sopenharmony_ci	handle->msg_enable = netif_msg_init(debug, DEFAULT_MSG_LEVEL);
531262306a36Sopenharmony_ci
531362306a36Sopenharmony_ci	handle->kinfo.netdev = netdev;
531462306a36Sopenharmony_ci	handle->priv = (void *)priv;
531562306a36Sopenharmony_ci
531662306a36Sopenharmony_ci	hns3_init_mac_addr(netdev);
531762306a36Sopenharmony_ci
531862306a36Sopenharmony_ci	hns3_set_default_feature(netdev);
531962306a36Sopenharmony_ci
532062306a36Sopenharmony_ci	netdev->watchdog_timeo = HNS3_TX_TIMEOUT;
532162306a36Sopenharmony_ci	netdev->priv_flags |= IFF_UNICAST_FLT;
532262306a36Sopenharmony_ci	netdev->netdev_ops = &hns3_nic_netdev_ops;
532362306a36Sopenharmony_ci	SET_NETDEV_DEV(netdev, &pdev->dev);
532462306a36Sopenharmony_ci	hns3_ethtool_set_ops(netdev);
532562306a36Sopenharmony_ci
532662306a36Sopenharmony_ci	/* Carrier off reporting is important to ethtool even BEFORE open */
532762306a36Sopenharmony_ci	netif_carrier_off(netdev);
532862306a36Sopenharmony_ci
532962306a36Sopenharmony_ci	ret = hns3_get_ring_config(priv);
533062306a36Sopenharmony_ci	if (ret) {
533162306a36Sopenharmony_ci		ret = -ENOMEM;
533262306a36Sopenharmony_ci		goto out_get_ring_cfg;
533362306a36Sopenharmony_ci	}
533462306a36Sopenharmony_ci
533562306a36Sopenharmony_ci	hns3_nic_init_coal_cfg(priv);
533662306a36Sopenharmony_ci
533762306a36Sopenharmony_ci	ret = hns3_nic_alloc_vector_data(priv);
533862306a36Sopenharmony_ci	if (ret) {
533962306a36Sopenharmony_ci		ret = -ENOMEM;
534062306a36Sopenharmony_ci		goto out_alloc_vector_data;
534162306a36Sopenharmony_ci	}
534262306a36Sopenharmony_ci
534362306a36Sopenharmony_ci	ret = hns3_nic_init_vector_data(priv);
534462306a36Sopenharmony_ci	if (ret) {
534562306a36Sopenharmony_ci		ret = -ENOMEM;
534662306a36Sopenharmony_ci		goto out_init_vector_data;
534762306a36Sopenharmony_ci	}
534862306a36Sopenharmony_ci
534962306a36Sopenharmony_ci	ret = hns3_init_all_ring(priv);
535062306a36Sopenharmony_ci	if (ret) {
535162306a36Sopenharmony_ci		ret = -ENOMEM;
535262306a36Sopenharmony_ci		goto out_init_ring;
535362306a36Sopenharmony_ci	}
535462306a36Sopenharmony_ci
535562306a36Sopenharmony_ci	hns3_cq_period_mode_init(priv, DIM_CQ_PERIOD_MODE_START_FROM_EQE,
535662306a36Sopenharmony_ci				 DIM_CQ_PERIOD_MODE_START_FROM_EQE);
535762306a36Sopenharmony_ci
535862306a36Sopenharmony_ci	ret = hns3_init_phy(netdev);
535962306a36Sopenharmony_ci	if (ret)
536062306a36Sopenharmony_ci		goto out_init_phy;
536162306a36Sopenharmony_ci
536262306a36Sopenharmony_ci	/* the device can work without cpu rmap, only aRFS needs it */
536362306a36Sopenharmony_ci	ret = hns3_set_rx_cpu_rmap(netdev);
536462306a36Sopenharmony_ci	if (ret)
536562306a36Sopenharmony_ci		dev_warn(priv->dev, "set rx cpu rmap fail, ret=%d\n", ret);
536662306a36Sopenharmony_ci
536762306a36Sopenharmony_ci	ret = hns3_nic_init_irq(priv);
536862306a36Sopenharmony_ci	if (ret) {
536962306a36Sopenharmony_ci		dev_err(priv->dev, "init irq failed! ret=%d\n", ret);
537062306a36Sopenharmony_ci		hns3_free_rx_cpu_rmap(netdev);
537162306a36Sopenharmony_ci		goto out_init_irq_fail;
537262306a36Sopenharmony_ci	}
537362306a36Sopenharmony_ci
537462306a36Sopenharmony_ci	ret = hns3_client_start(handle);
537562306a36Sopenharmony_ci	if (ret) {
537662306a36Sopenharmony_ci		dev_err(priv->dev, "hns3_client_start fail! ret=%d\n", ret);
537762306a36Sopenharmony_ci		goto out_client_start;
537862306a36Sopenharmony_ci	}
537962306a36Sopenharmony_ci
538062306a36Sopenharmony_ci	hns3_dcbnl_setup(handle);
538162306a36Sopenharmony_ci
538262306a36Sopenharmony_ci	ret = hns3_dbg_init(handle);
538362306a36Sopenharmony_ci	if (ret) {
538462306a36Sopenharmony_ci		dev_err(priv->dev, "failed to init debugfs, ret = %d\n",
538562306a36Sopenharmony_ci			ret);
538662306a36Sopenharmony_ci		goto out_client_start;
538762306a36Sopenharmony_ci	}
538862306a36Sopenharmony_ci
538962306a36Sopenharmony_ci	netdev->max_mtu = HNS3_MAX_MTU(ae_dev->dev_specs.max_frm_size);
539062306a36Sopenharmony_ci
539162306a36Sopenharmony_ci	hns3_state_init(handle);
539262306a36Sopenharmony_ci
539362306a36Sopenharmony_ci	ret = register_netdev(netdev);
539462306a36Sopenharmony_ci	if (ret) {
539562306a36Sopenharmony_ci		dev_err(priv->dev, "probe register netdev fail!\n");
539662306a36Sopenharmony_ci		goto out_reg_netdev_fail;
539762306a36Sopenharmony_ci	}
539862306a36Sopenharmony_ci
539962306a36Sopenharmony_ci	if (netif_msg_drv(handle))
540062306a36Sopenharmony_ci		hns3_info_show(priv);
540162306a36Sopenharmony_ci
540262306a36Sopenharmony_ci	return ret;
540362306a36Sopenharmony_ci
540462306a36Sopenharmony_ciout_reg_netdev_fail:
540562306a36Sopenharmony_ci	hns3_state_uninit(handle);
540662306a36Sopenharmony_ci	hns3_dbg_uninit(handle);
540762306a36Sopenharmony_ci	hns3_client_stop(handle);
540862306a36Sopenharmony_ciout_client_start:
540962306a36Sopenharmony_ci	hns3_free_rx_cpu_rmap(netdev);
541062306a36Sopenharmony_ci	hns3_nic_uninit_irq(priv);
541162306a36Sopenharmony_ciout_init_irq_fail:
541262306a36Sopenharmony_ci	hns3_uninit_phy(netdev);
541362306a36Sopenharmony_ciout_init_phy:
541462306a36Sopenharmony_ci	hns3_uninit_all_ring(priv);
541562306a36Sopenharmony_ciout_init_ring:
541662306a36Sopenharmony_ci	hns3_nic_uninit_vector_data(priv);
541762306a36Sopenharmony_ciout_init_vector_data:
541862306a36Sopenharmony_ci	hns3_nic_dealloc_vector_data(priv);
541962306a36Sopenharmony_ciout_alloc_vector_data:
542062306a36Sopenharmony_ci	priv->ring = NULL;
542162306a36Sopenharmony_ciout_get_ring_cfg:
542262306a36Sopenharmony_ci	priv->ae_handle = NULL;
542362306a36Sopenharmony_ci	free_netdev(netdev);
542462306a36Sopenharmony_ci	return ret;
542562306a36Sopenharmony_ci}
542662306a36Sopenharmony_ci
542762306a36Sopenharmony_cistatic void hns3_client_uninit(struct hnae3_handle *handle, bool reset)
542862306a36Sopenharmony_ci{
542962306a36Sopenharmony_ci	struct net_device *netdev = handle->kinfo.netdev;
543062306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
543162306a36Sopenharmony_ci
543262306a36Sopenharmony_ci	if (netdev->reg_state != NETREG_UNINITIALIZED)
543362306a36Sopenharmony_ci		unregister_netdev(netdev);
543462306a36Sopenharmony_ci
543562306a36Sopenharmony_ci	hns3_client_stop(handle);
543662306a36Sopenharmony_ci
543762306a36Sopenharmony_ci	hns3_uninit_phy(netdev);
543862306a36Sopenharmony_ci
543962306a36Sopenharmony_ci	if (!test_and_clear_bit(HNS3_NIC_STATE_INITED, &priv->state)) {
544062306a36Sopenharmony_ci		netdev_warn(netdev, "already uninitialized\n");
544162306a36Sopenharmony_ci		goto out_netdev_free;
544262306a36Sopenharmony_ci	}
544362306a36Sopenharmony_ci
544462306a36Sopenharmony_ci	hns3_free_rx_cpu_rmap(netdev);
544562306a36Sopenharmony_ci
544662306a36Sopenharmony_ci	hns3_nic_uninit_irq(priv);
544762306a36Sopenharmony_ci
544862306a36Sopenharmony_ci	hns3_clear_all_ring(handle, true);
544962306a36Sopenharmony_ci
545062306a36Sopenharmony_ci	hns3_nic_uninit_vector_data(priv);
545162306a36Sopenharmony_ci
545262306a36Sopenharmony_ci	hns3_nic_dealloc_vector_data(priv);
545362306a36Sopenharmony_ci
545462306a36Sopenharmony_ci	hns3_uninit_all_ring(priv);
545562306a36Sopenharmony_ci
545662306a36Sopenharmony_ci	hns3_put_ring_config(priv);
545762306a36Sopenharmony_ci
545862306a36Sopenharmony_ciout_netdev_free:
545962306a36Sopenharmony_ci	hns3_dbg_uninit(handle);
546062306a36Sopenharmony_ci	free_netdev(netdev);
546162306a36Sopenharmony_ci}
546262306a36Sopenharmony_ci
546362306a36Sopenharmony_cistatic void hns3_link_status_change(struct hnae3_handle *handle, bool linkup)
546462306a36Sopenharmony_ci{
546562306a36Sopenharmony_ci	struct net_device *netdev = handle->kinfo.netdev;
546662306a36Sopenharmony_ci
546762306a36Sopenharmony_ci	if (!netdev)
546862306a36Sopenharmony_ci		return;
546962306a36Sopenharmony_ci
547062306a36Sopenharmony_ci	if (linkup) {
547162306a36Sopenharmony_ci		netif_tx_wake_all_queues(netdev);
547262306a36Sopenharmony_ci		netif_carrier_on(netdev);
547362306a36Sopenharmony_ci		if (netif_msg_link(handle))
547462306a36Sopenharmony_ci			netdev_info(netdev, "link up\n");
547562306a36Sopenharmony_ci	} else {
547662306a36Sopenharmony_ci		netif_carrier_off(netdev);
547762306a36Sopenharmony_ci		netif_tx_stop_all_queues(netdev);
547862306a36Sopenharmony_ci		if (netif_msg_link(handle))
547962306a36Sopenharmony_ci			netdev_info(netdev, "link down\n");
548062306a36Sopenharmony_ci	}
548162306a36Sopenharmony_ci}
548262306a36Sopenharmony_ci
548362306a36Sopenharmony_cistatic void hns3_clear_tx_ring(struct hns3_enet_ring *ring)
548462306a36Sopenharmony_ci{
548562306a36Sopenharmony_ci	while (ring->next_to_clean != ring->next_to_use) {
548662306a36Sopenharmony_ci		ring->desc[ring->next_to_clean].tx.bdtp_fe_sc_vld_ra_ri = 0;
548762306a36Sopenharmony_ci		hns3_free_buffer_detach(ring, ring->next_to_clean, 0);
548862306a36Sopenharmony_ci		ring_ptr_move_fw(ring, next_to_clean);
548962306a36Sopenharmony_ci	}
549062306a36Sopenharmony_ci
549162306a36Sopenharmony_ci	ring->pending_buf = 0;
549262306a36Sopenharmony_ci}
549362306a36Sopenharmony_ci
549462306a36Sopenharmony_cistatic int hns3_clear_rx_ring(struct hns3_enet_ring *ring)
549562306a36Sopenharmony_ci{
549662306a36Sopenharmony_ci	struct hns3_desc_cb res_cbs;
549762306a36Sopenharmony_ci	int ret;
549862306a36Sopenharmony_ci
549962306a36Sopenharmony_ci	while (ring->next_to_use != ring->next_to_clean) {
550062306a36Sopenharmony_ci		/* When a buffer is not reused, it's memory has been
550162306a36Sopenharmony_ci		 * freed in hns3_handle_rx_bd or will be freed by
550262306a36Sopenharmony_ci		 * stack, so we need to replace the buffer here.
550362306a36Sopenharmony_ci		 */
550462306a36Sopenharmony_ci		if (!ring->desc_cb[ring->next_to_use].reuse_flag) {
550562306a36Sopenharmony_ci			ret = hns3_alloc_and_map_buffer(ring, &res_cbs);
550662306a36Sopenharmony_ci			if (ret) {
550762306a36Sopenharmony_ci				hns3_ring_stats_update(ring, sw_err_cnt);
550862306a36Sopenharmony_ci				/* if alloc new buffer fail, exit directly
550962306a36Sopenharmony_ci				 * and reclear in up flow.
551062306a36Sopenharmony_ci				 */
551162306a36Sopenharmony_ci				netdev_warn(ring_to_netdev(ring),
551262306a36Sopenharmony_ci					    "reserve buffer map failed, ret = %d\n",
551362306a36Sopenharmony_ci					    ret);
551462306a36Sopenharmony_ci				return ret;
551562306a36Sopenharmony_ci			}
551662306a36Sopenharmony_ci			hns3_replace_buffer(ring, ring->next_to_use, &res_cbs);
551762306a36Sopenharmony_ci		}
551862306a36Sopenharmony_ci		ring_ptr_move_fw(ring, next_to_use);
551962306a36Sopenharmony_ci	}
552062306a36Sopenharmony_ci
552162306a36Sopenharmony_ci	/* Free the pending skb in rx ring */
552262306a36Sopenharmony_ci	if (ring->skb) {
552362306a36Sopenharmony_ci		dev_kfree_skb_any(ring->skb);
552462306a36Sopenharmony_ci		ring->skb = NULL;
552562306a36Sopenharmony_ci		ring->pending_buf = 0;
552662306a36Sopenharmony_ci	}
552762306a36Sopenharmony_ci
552862306a36Sopenharmony_ci	return 0;
552962306a36Sopenharmony_ci}
553062306a36Sopenharmony_ci
553162306a36Sopenharmony_cistatic void hns3_force_clear_rx_ring(struct hns3_enet_ring *ring)
553262306a36Sopenharmony_ci{
553362306a36Sopenharmony_ci	while (ring->next_to_use != ring->next_to_clean) {
553462306a36Sopenharmony_ci		/* When a buffer is not reused, it's memory has been
553562306a36Sopenharmony_ci		 * freed in hns3_handle_rx_bd or will be freed by
553662306a36Sopenharmony_ci		 * stack, so only need to unmap the buffer here.
553762306a36Sopenharmony_ci		 */
553862306a36Sopenharmony_ci		if (!ring->desc_cb[ring->next_to_use].reuse_flag) {
553962306a36Sopenharmony_ci			hns3_unmap_buffer(ring,
554062306a36Sopenharmony_ci					  &ring->desc_cb[ring->next_to_use]);
554162306a36Sopenharmony_ci			ring->desc_cb[ring->next_to_use].dma = 0;
554262306a36Sopenharmony_ci		}
554362306a36Sopenharmony_ci
554462306a36Sopenharmony_ci		ring_ptr_move_fw(ring, next_to_use);
554562306a36Sopenharmony_ci	}
554662306a36Sopenharmony_ci}
554762306a36Sopenharmony_ci
554862306a36Sopenharmony_cistatic void hns3_clear_all_ring(struct hnae3_handle *h, bool force)
554962306a36Sopenharmony_ci{
555062306a36Sopenharmony_ci	struct net_device *ndev = h->kinfo.netdev;
555162306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
555262306a36Sopenharmony_ci	u32 i;
555362306a36Sopenharmony_ci
555462306a36Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++) {
555562306a36Sopenharmony_ci		struct hns3_enet_ring *ring;
555662306a36Sopenharmony_ci
555762306a36Sopenharmony_ci		ring = &priv->ring[i];
555862306a36Sopenharmony_ci		hns3_clear_tx_ring(ring);
555962306a36Sopenharmony_ci
556062306a36Sopenharmony_ci		ring = &priv->ring[i + h->kinfo.num_tqps];
556162306a36Sopenharmony_ci		/* Continue to clear other rings even if clearing some
556262306a36Sopenharmony_ci		 * rings failed.
556362306a36Sopenharmony_ci		 */
556462306a36Sopenharmony_ci		if (force)
556562306a36Sopenharmony_ci			hns3_force_clear_rx_ring(ring);
556662306a36Sopenharmony_ci		else
556762306a36Sopenharmony_ci			hns3_clear_rx_ring(ring);
556862306a36Sopenharmony_ci	}
556962306a36Sopenharmony_ci}
557062306a36Sopenharmony_ci
557162306a36Sopenharmony_ciint hns3_nic_reset_all_ring(struct hnae3_handle *h)
557262306a36Sopenharmony_ci{
557362306a36Sopenharmony_ci	struct net_device *ndev = h->kinfo.netdev;
557462306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
557562306a36Sopenharmony_ci	struct hns3_enet_ring *rx_ring;
557662306a36Sopenharmony_ci	int i, j;
557762306a36Sopenharmony_ci	int ret;
557862306a36Sopenharmony_ci
557962306a36Sopenharmony_ci	ret = h->ae_algo->ops->reset_queue(h);
558062306a36Sopenharmony_ci	if (ret)
558162306a36Sopenharmony_ci		return ret;
558262306a36Sopenharmony_ci
558362306a36Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++) {
558462306a36Sopenharmony_ci		hns3_init_ring_hw(&priv->ring[i]);
558562306a36Sopenharmony_ci
558662306a36Sopenharmony_ci		/* We need to clear tx ring here because self test will
558762306a36Sopenharmony_ci		 * use the ring and will not run down before up
558862306a36Sopenharmony_ci		 */
558962306a36Sopenharmony_ci		hns3_clear_tx_ring(&priv->ring[i]);
559062306a36Sopenharmony_ci		priv->ring[i].next_to_clean = 0;
559162306a36Sopenharmony_ci		priv->ring[i].next_to_use = 0;
559262306a36Sopenharmony_ci		priv->ring[i].last_to_use = 0;
559362306a36Sopenharmony_ci
559462306a36Sopenharmony_ci		rx_ring = &priv->ring[i + h->kinfo.num_tqps];
559562306a36Sopenharmony_ci		hns3_init_ring_hw(rx_ring);
559662306a36Sopenharmony_ci		ret = hns3_clear_rx_ring(rx_ring);
559762306a36Sopenharmony_ci		if (ret)
559862306a36Sopenharmony_ci			return ret;
559962306a36Sopenharmony_ci
560062306a36Sopenharmony_ci		/* We can not know the hardware head and tail when this
560162306a36Sopenharmony_ci		 * function is called in reset flow, so we reuse all desc.
560262306a36Sopenharmony_ci		 */
560362306a36Sopenharmony_ci		for (j = 0; j < rx_ring->desc_num; j++)
560462306a36Sopenharmony_ci			hns3_reuse_buffer(rx_ring, j);
560562306a36Sopenharmony_ci
560662306a36Sopenharmony_ci		rx_ring->next_to_clean = 0;
560762306a36Sopenharmony_ci		rx_ring->next_to_use = 0;
560862306a36Sopenharmony_ci	}
560962306a36Sopenharmony_ci
561062306a36Sopenharmony_ci	hns3_init_tx_ring_tc(priv);
561162306a36Sopenharmony_ci
561262306a36Sopenharmony_ci	return 0;
561362306a36Sopenharmony_ci}
561462306a36Sopenharmony_ci
561562306a36Sopenharmony_cistatic int hns3_reset_notify_down_enet(struct hnae3_handle *handle)
561662306a36Sopenharmony_ci{
561762306a36Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
561862306a36Sopenharmony_ci	struct net_device *ndev = kinfo->netdev;
561962306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
562062306a36Sopenharmony_ci
562162306a36Sopenharmony_ci	if (test_and_set_bit(HNS3_NIC_STATE_RESETTING, &priv->state))
562262306a36Sopenharmony_ci		return 0;
562362306a36Sopenharmony_ci
562462306a36Sopenharmony_ci	if (!netif_running(ndev))
562562306a36Sopenharmony_ci		return 0;
562662306a36Sopenharmony_ci
562762306a36Sopenharmony_ci	return hns3_nic_net_stop(ndev);
562862306a36Sopenharmony_ci}
562962306a36Sopenharmony_ci
563062306a36Sopenharmony_cistatic int hns3_reset_notify_up_enet(struct hnae3_handle *handle)
563162306a36Sopenharmony_ci{
563262306a36Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
563362306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(kinfo->netdev);
563462306a36Sopenharmony_ci	int ret = 0;
563562306a36Sopenharmony_ci
563662306a36Sopenharmony_ci	if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state)) {
563762306a36Sopenharmony_ci		netdev_err(kinfo->netdev, "device is not initialized yet\n");
563862306a36Sopenharmony_ci		return -EFAULT;
563962306a36Sopenharmony_ci	}
564062306a36Sopenharmony_ci
564162306a36Sopenharmony_ci	clear_bit(HNS3_NIC_STATE_RESETTING, &priv->state);
564262306a36Sopenharmony_ci
564362306a36Sopenharmony_ci	if (netif_running(kinfo->netdev)) {
564462306a36Sopenharmony_ci		ret = hns3_nic_net_open(kinfo->netdev);
564562306a36Sopenharmony_ci		if (ret) {
564662306a36Sopenharmony_ci			set_bit(HNS3_NIC_STATE_RESETTING, &priv->state);
564762306a36Sopenharmony_ci			netdev_err(kinfo->netdev,
564862306a36Sopenharmony_ci				   "net up fail, ret=%d!\n", ret);
564962306a36Sopenharmony_ci			return ret;
565062306a36Sopenharmony_ci		}
565162306a36Sopenharmony_ci	}
565262306a36Sopenharmony_ci
565362306a36Sopenharmony_ci	return ret;
565462306a36Sopenharmony_ci}
565562306a36Sopenharmony_ci
565662306a36Sopenharmony_cistatic int hns3_reset_notify_init_enet(struct hnae3_handle *handle)
565762306a36Sopenharmony_ci{
565862306a36Sopenharmony_ci	struct net_device *netdev = handle->kinfo.netdev;
565962306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
566062306a36Sopenharmony_ci	int ret;
566162306a36Sopenharmony_ci
566262306a36Sopenharmony_ci	/* Carrier off reporting is important to ethtool even BEFORE open */
566362306a36Sopenharmony_ci	netif_carrier_off(netdev);
566462306a36Sopenharmony_ci
566562306a36Sopenharmony_ci	ret = hns3_get_ring_config(priv);
566662306a36Sopenharmony_ci	if (ret)
566762306a36Sopenharmony_ci		return ret;
566862306a36Sopenharmony_ci
566962306a36Sopenharmony_ci	ret = hns3_nic_alloc_vector_data(priv);
567062306a36Sopenharmony_ci	if (ret)
567162306a36Sopenharmony_ci		goto err_put_ring;
567262306a36Sopenharmony_ci
567362306a36Sopenharmony_ci	ret = hns3_nic_init_vector_data(priv);
567462306a36Sopenharmony_ci	if (ret)
567562306a36Sopenharmony_ci		goto err_dealloc_vector;
567662306a36Sopenharmony_ci
567762306a36Sopenharmony_ci	ret = hns3_init_all_ring(priv);
567862306a36Sopenharmony_ci	if (ret)
567962306a36Sopenharmony_ci		goto err_uninit_vector;
568062306a36Sopenharmony_ci
568162306a36Sopenharmony_ci	hns3_cq_period_mode_init(priv, priv->tx_cqe_mode, priv->rx_cqe_mode);
568262306a36Sopenharmony_ci
568362306a36Sopenharmony_ci	/* the device can work without cpu rmap, only aRFS needs it */
568462306a36Sopenharmony_ci	ret = hns3_set_rx_cpu_rmap(netdev);
568562306a36Sopenharmony_ci	if (ret)
568662306a36Sopenharmony_ci		dev_warn(priv->dev, "set rx cpu rmap fail, ret=%d\n", ret);
568762306a36Sopenharmony_ci
568862306a36Sopenharmony_ci	ret = hns3_nic_init_irq(priv);
568962306a36Sopenharmony_ci	if (ret) {
569062306a36Sopenharmony_ci		dev_err(priv->dev, "init irq failed! ret=%d\n", ret);
569162306a36Sopenharmony_ci		hns3_free_rx_cpu_rmap(netdev);
569262306a36Sopenharmony_ci		goto err_init_irq_fail;
569362306a36Sopenharmony_ci	}
569462306a36Sopenharmony_ci
569562306a36Sopenharmony_ci	if (!hns3_is_phys_func(handle->pdev))
569662306a36Sopenharmony_ci		hns3_init_mac_addr(netdev);
569762306a36Sopenharmony_ci
569862306a36Sopenharmony_ci	ret = hns3_client_start(handle);
569962306a36Sopenharmony_ci	if (ret) {
570062306a36Sopenharmony_ci		dev_err(priv->dev, "hns3_client_start fail! ret=%d\n", ret);
570162306a36Sopenharmony_ci		goto err_client_start_fail;
570262306a36Sopenharmony_ci	}
570362306a36Sopenharmony_ci
570462306a36Sopenharmony_ci	set_bit(HNS3_NIC_STATE_INITED, &priv->state);
570562306a36Sopenharmony_ci
570662306a36Sopenharmony_ci	return ret;
570762306a36Sopenharmony_ci
570862306a36Sopenharmony_cierr_client_start_fail:
570962306a36Sopenharmony_ci	hns3_free_rx_cpu_rmap(netdev);
571062306a36Sopenharmony_ci	hns3_nic_uninit_irq(priv);
571162306a36Sopenharmony_cierr_init_irq_fail:
571262306a36Sopenharmony_ci	hns3_uninit_all_ring(priv);
571362306a36Sopenharmony_cierr_uninit_vector:
571462306a36Sopenharmony_ci	hns3_nic_uninit_vector_data(priv);
571562306a36Sopenharmony_cierr_dealloc_vector:
571662306a36Sopenharmony_ci	hns3_nic_dealloc_vector_data(priv);
571762306a36Sopenharmony_cierr_put_ring:
571862306a36Sopenharmony_ci	hns3_put_ring_config(priv);
571962306a36Sopenharmony_ci
572062306a36Sopenharmony_ci	return ret;
572162306a36Sopenharmony_ci}
572262306a36Sopenharmony_ci
572362306a36Sopenharmony_cistatic int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
572462306a36Sopenharmony_ci{
572562306a36Sopenharmony_ci	struct net_device *netdev = handle->kinfo.netdev;
572662306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(netdev);
572762306a36Sopenharmony_ci
572862306a36Sopenharmony_ci	if (!test_and_clear_bit(HNS3_NIC_STATE_INITED, &priv->state)) {
572962306a36Sopenharmony_ci		netdev_warn(netdev, "already uninitialized\n");
573062306a36Sopenharmony_ci		return 0;
573162306a36Sopenharmony_ci	}
573262306a36Sopenharmony_ci
573362306a36Sopenharmony_ci	hns3_free_rx_cpu_rmap(netdev);
573462306a36Sopenharmony_ci	hns3_nic_uninit_irq(priv);
573562306a36Sopenharmony_ci	hns3_clear_all_ring(handle, true);
573662306a36Sopenharmony_ci	hns3_reset_tx_queue(priv->ae_handle);
573762306a36Sopenharmony_ci
573862306a36Sopenharmony_ci	hns3_nic_uninit_vector_data(priv);
573962306a36Sopenharmony_ci
574062306a36Sopenharmony_ci	hns3_nic_dealloc_vector_data(priv);
574162306a36Sopenharmony_ci
574262306a36Sopenharmony_ci	hns3_uninit_all_ring(priv);
574362306a36Sopenharmony_ci
574462306a36Sopenharmony_ci	hns3_put_ring_config(priv);
574562306a36Sopenharmony_ci
574662306a36Sopenharmony_ci	return 0;
574762306a36Sopenharmony_ci}
574862306a36Sopenharmony_ci
574962306a36Sopenharmony_ciint hns3_reset_notify(struct hnae3_handle *handle,
575062306a36Sopenharmony_ci		      enum hnae3_reset_notify_type type)
575162306a36Sopenharmony_ci{
575262306a36Sopenharmony_ci	int ret = 0;
575362306a36Sopenharmony_ci
575462306a36Sopenharmony_ci	switch (type) {
575562306a36Sopenharmony_ci	case HNAE3_UP_CLIENT:
575662306a36Sopenharmony_ci		ret = hns3_reset_notify_up_enet(handle);
575762306a36Sopenharmony_ci		break;
575862306a36Sopenharmony_ci	case HNAE3_DOWN_CLIENT:
575962306a36Sopenharmony_ci		ret = hns3_reset_notify_down_enet(handle);
576062306a36Sopenharmony_ci		break;
576162306a36Sopenharmony_ci	case HNAE3_INIT_CLIENT:
576262306a36Sopenharmony_ci		ret = hns3_reset_notify_init_enet(handle);
576362306a36Sopenharmony_ci		break;
576462306a36Sopenharmony_ci	case HNAE3_UNINIT_CLIENT:
576562306a36Sopenharmony_ci		ret = hns3_reset_notify_uninit_enet(handle);
576662306a36Sopenharmony_ci		break;
576762306a36Sopenharmony_ci	default:
576862306a36Sopenharmony_ci		break;
576962306a36Sopenharmony_ci	}
577062306a36Sopenharmony_ci
577162306a36Sopenharmony_ci	return ret;
577262306a36Sopenharmony_ci}
577362306a36Sopenharmony_ci
577462306a36Sopenharmony_cistatic int hns3_change_channels(struct hnae3_handle *handle, u32 new_tqp_num,
577562306a36Sopenharmony_ci				bool rxfh_configured)
577662306a36Sopenharmony_ci{
577762306a36Sopenharmony_ci	int ret;
577862306a36Sopenharmony_ci
577962306a36Sopenharmony_ci	ret = handle->ae_algo->ops->set_channels(handle, new_tqp_num,
578062306a36Sopenharmony_ci						 rxfh_configured);
578162306a36Sopenharmony_ci	if (ret) {
578262306a36Sopenharmony_ci		dev_err(&handle->pdev->dev,
578362306a36Sopenharmony_ci			"Change tqp num(%u) fail.\n", new_tqp_num);
578462306a36Sopenharmony_ci		return ret;
578562306a36Sopenharmony_ci	}
578662306a36Sopenharmony_ci
578762306a36Sopenharmony_ci	ret = hns3_reset_notify(handle, HNAE3_INIT_CLIENT);
578862306a36Sopenharmony_ci	if (ret)
578962306a36Sopenharmony_ci		return ret;
579062306a36Sopenharmony_ci
579162306a36Sopenharmony_ci	ret =  hns3_reset_notify(handle, HNAE3_UP_CLIENT);
579262306a36Sopenharmony_ci	if (ret)
579362306a36Sopenharmony_ci		hns3_reset_notify(handle, HNAE3_UNINIT_CLIENT);
579462306a36Sopenharmony_ci
579562306a36Sopenharmony_ci	return ret;
579662306a36Sopenharmony_ci}
579762306a36Sopenharmony_ci
579862306a36Sopenharmony_ciint hns3_set_channels(struct net_device *netdev,
579962306a36Sopenharmony_ci		      struct ethtool_channels *ch)
580062306a36Sopenharmony_ci{
580162306a36Sopenharmony_ci	struct hnae3_handle *h = hns3_get_handle(netdev);
580262306a36Sopenharmony_ci	struct hnae3_knic_private_info *kinfo = &h->kinfo;
580362306a36Sopenharmony_ci	bool rxfh_configured = netif_is_rxfh_configured(netdev);
580462306a36Sopenharmony_ci	u32 new_tqp_num = ch->combined_count;
580562306a36Sopenharmony_ci	u16 org_tqp_num;
580662306a36Sopenharmony_ci	int ret;
580762306a36Sopenharmony_ci
580862306a36Sopenharmony_ci	if (hns3_nic_resetting(netdev))
580962306a36Sopenharmony_ci		return -EBUSY;
581062306a36Sopenharmony_ci
581162306a36Sopenharmony_ci	if (ch->rx_count || ch->tx_count)
581262306a36Sopenharmony_ci		return -EINVAL;
581362306a36Sopenharmony_ci
581462306a36Sopenharmony_ci	if (kinfo->tc_info.mqprio_active) {
581562306a36Sopenharmony_ci		dev_err(&netdev->dev,
581662306a36Sopenharmony_ci			"it's not allowed to set channels via ethtool when MQPRIO mode is on\n");
581762306a36Sopenharmony_ci		return -EINVAL;
581862306a36Sopenharmony_ci	}
581962306a36Sopenharmony_ci
582062306a36Sopenharmony_ci	if (new_tqp_num > hns3_get_max_available_channels(h) ||
582162306a36Sopenharmony_ci	    new_tqp_num < 1) {
582262306a36Sopenharmony_ci		dev_err(&netdev->dev,
582362306a36Sopenharmony_ci			"Change tqps fail, the tqp range is from 1 to %u",
582462306a36Sopenharmony_ci			hns3_get_max_available_channels(h));
582562306a36Sopenharmony_ci		return -EINVAL;
582662306a36Sopenharmony_ci	}
582762306a36Sopenharmony_ci
582862306a36Sopenharmony_ci	if (kinfo->rss_size == new_tqp_num)
582962306a36Sopenharmony_ci		return 0;
583062306a36Sopenharmony_ci
583162306a36Sopenharmony_ci	netif_dbg(h, drv, netdev,
583262306a36Sopenharmony_ci		  "set channels: tqp_num=%u, rxfh=%d\n",
583362306a36Sopenharmony_ci		  new_tqp_num, rxfh_configured);
583462306a36Sopenharmony_ci
583562306a36Sopenharmony_ci	ret = hns3_reset_notify(h, HNAE3_DOWN_CLIENT);
583662306a36Sopenharmony_ci	if (ret)
583762306a36Sopenharmony_ci		return ret;
583862306a36Sopenharmony_ci
583962306a36Sopenharmony_ci	ret = hns3_reset_notify(h, HNAE3_UNINIT_CLIENT);
584062306a36Sopenharmony_ci	if (ret)
584162306a36Sopenharmony_ci		return ret;
584262306a36Sopenharmony_ci
584362306a36Sopenharmony_ci	org_tqp_num = h->kinfo.num_tqps;
584462306a36Sopenharmony_ci	ret = hns3_change_channels(h, new_tqp_num, rxfh_configured);
584562306a36Sopenharmony_ci	if (ret) {
584662306a36Sopenharmony_ci		int ret1;
584762306a36Sopenharmony_ci
584862306a36Sopenharmony_ci		netdev_warn(netdev,
584962306a36Sopenharmony_ci			    "Change channels fail, revert to old value\n");
585062306a36Sopenharmony_ci		ret1 = hns3_change_channels(h, org_tqp_num, rxfh_configured);
585162306a36Sopenharmony_ci		if (ret1) {
585262306a36Sopenharmony_ci			netdev_err(netdev,
585362306a36Sopenharmony_ci				   "revert to old channel fail\n");
585462306a36Sopenharmony_ci			return ret1;
585562306a36Sopenharmony_ci		}
585662306a36Sopenharmony_ci
585762306a36Sopenharmony_ci		return ret;
585862306a36Sopenharmony_ci	}
585962306a36Sopenharmony_ci
586062306a36Sopenharmony_ci	return 0;
586162306a36Sopenharmony_ci}
586262306a36Sopenharmony_ci
586362306a36Sopenharmony_civoid hns3_external_lb_prepare(struct net_device *ndev, bool if_running)
586462306a36Sopenharmony_ci{
586562306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
586662306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
586762306a36Sopenharmony_ci	int i;
586862306a36Sopenharmony_ci
586962306a36Sopenharmony_ci	if (!if_running)
587062306a36Sopenharmony_ci		return;
587162306a36Sopenharmony_ci
587262306a36Sopenharmony_ci	if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state))
587362306a36Sopenharmony_ci		return;
587462306a36Sopenharmony_ci
587562306a36Sopenharmony_ci	netif_carrier_off(ndev);
587662306a36Sopenharmony_ci	netif_tx_disable(ndev);
587762306a36Sopenharmony_ci
587862306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++)
587962306a36Sopenharmony_ci		hns3_vector_disable(&priv->tqp_vector[i]);
588062306a36Sopenharmony_ci
588162306a36Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++)
588262306a36Sopenharmony_ci		hns3_tqp_disable(h->kinfo.tqp[i]);
588362306a36Sopenharmony_ci
588462306a36Sopenharmony_ci	/* delay ring buffer clearing to hns3_reset_notify_uninit_enet
588562306a36Sopenharmony_ci	 * during reset process, because driver may not be able
588662306a36Sopenharmony_ci	 * to disable the ring through firmware when downing the netdev.
588762306a36Sopenharmony_ci	 */
588862306a36Sopenharmony_ci	if (!hns3_nic_resetting(ndev))
588962306a36Sopenharmony_ci		hns3_nic_reset_all_ring(priv->ae_handle);
589062306a36Sopenharmony_ci
589162306a36Sopenharmony_ci	hns3_reset_tx_queue(priv->ae_handle);
589262306a36Sopenharmony_ci}
589362306a36Sopenharmony_ci
589462306a36Sopenharmony_civoid hns3_external_lb_restore(struct net_device *ndev, bool if_running)
589562306a36Sopenharmony_ci{
589662306a36Sopenharmony_ci	struct hns3_nic_priv *priv = netdev_priv(ndev);
589762306a36Sopenharmony_ci	struct hnae3_handle *h = priv->ae_handle;
589862306a36Sopenharmony_ci	int i;
589962306a36Sopenharmony_ci
590062306a36Sopenharmony_ci	if (!if_running)
590162306a36Sopenharmony_ci		return;
590262306a36Sopenharmony_ci
590362306a36Sopenharmony_ci	if (hns3_nic_resetting(ndev))
590462306a36Sopenharmony_ci		return;
590562306a36Sopenharmony_ci
590662306a36Sopenharmony_ci	if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state))
590762306a36Sopenharmony_ci		return;
590862306a36Sopenharmony_ci
590962306a36Sopenharmony_ci	if (hns3_nic_reset_all_ring(priv->ae_handle))
591062306a36Sopenharmony_ci		return;
591162306a36Sopenharmony_ci
591262306a36Sopenharmony_ci	clear_bit(HNS3_NIC_STATE_DOWN, &priv->state);
591362306a36Sopenharmony_ci
591462306a36Sopenharmony_ci	for (i = 0; i < priv->vector_num; i++)
591562306a36Sopenharmony_ci		hns3_vector_enable(&priv->tqp_vector[i]);
591662306a36Sopenharmony_ci
591762306a36Sopenharmony_ci	for (i = 0; i < h->kinfo.num_tqps; i++)
591862306a36Sopenharmony_ci		hns3_tqp_enable(h->kinfo.tqp[i]);
591962306a36Sopenharmony_ci
592062306a36Sopenharmony_ci	netif_tx_wake_all_queues(ndev);
592162306a36Sopenharmony_ci
592262306a36Sopenharmony_ci	if (h->ae_algo->ops->get_status(h))
592362306a36Sopenharmony_ci		netif_carrier_on(ndev);
592462306a36Sopenharmony_ci}
592562306a36Sopenharmony_ci
592662306a36Sopenharmony_cistatic const struct hns3_hw_error_info hns3_hw_err[] = {
592762306a36Sopenharmony_ci	{ .type = HNAE3_PPU_POISON_ERROR,
592862306a36Sopenharmony_ci	  .msg = "PPU poison" },
592962306a36Sopenharmony_ci	{ .type = HNAE3_CMDQ_ECC_ERROR,
593062306a36Sopenharmony_ci	  .msg = "IMP CMDQ error" },
593162306a36Sopenharmony_ci	{ .type = HNAE3_IMP_RD_POISON_ERROR,
593262306a36Sopenharmony_ci	  .msg = "IMP RD poison" },
593362306a36Sopenharmony_ci	{ .type = HNAE3_ROCEE_AXI_RESP_ERROR,
593462306a36Sopenharmony_ci	  .msg = "ROCEE AXI RESP error" },
593562306a36Sopenharmony_ci};
593662306a36Sopenharmony_ci
593762306a36Sopenharmony_cistatic void hns3_process_hw_error(struct hnae3_handle *handle,
593862306a36Sopenharmony_ci				  enum hnae3_hw_error_type type)
593962306a36Sopenharmony_ci{
594062306a36Sopenharmony_ci	int i;
594162306a36Sopenharmony_ci
594262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(hns3_hw_err); i++) {
594362306a36Sopenharmony_ci		if (hns3_hw_err[i].type == type) {
594462306a36Sopenharmony_ci			dev_err(&handle->pdev->dev, "Detected %s!\n",
594562306a36Sopenharmony_ci				hns3_hw_err[i].msg);
594662306a36Sopenharmony_ci			break;
594762306a36Sopenharmony_ci		}
594862306a36Sopenharmony_ci	}
594962306a36Sopenharmony_ci}
595062306a36Sopenharmony_ci
595162306a36Sopenharmony_cistatic const struct hnae3_client_ops client_ops = {
595262306a36Sopenharmony_ci	.init_instance = hns3_client_init,
595362306a36Sopenharmony_ci	.uninit_instance = hns3_client_uninit,
595462306a36Sopenharmony_ci	.link_status_change = hns3_link_status_change,
595562306a36Sopenharmony_ci	.reset_notify = hns3_reset_notify,
595662306a36Sopenharmony_ci	.process_hw_error = hns3_process_hw_error,
595762306a36Sopenharmony_ci};
595862306a36Sopenharmony_ci
595962306a36Sopenharmony_ci/* hns3_init_module - Driver registration routine
596062306a36Sopenharmony_ci * hns3_init_module is the first routine called when the driver is
596162306a36Sopenharmony_ci * loaded. All it does is register with the PCI subsystem.
596262306a36Sopenharmony_ci */
596362306a36Sopenharmony_cistatic int __init hns3_init_module(void)
596462306a36Sopenharmony_ci{
596562306a36Sopenharmony_ci	int ret;
596662306a36Sopenharmony_ci
596762306a36Sopenharmony_ci	pr_info("%s: %s - version\n", hns3_driver_name, hns3_driver_string);
596862306a36Sopenharmony_ci	pr_info("%s: %s\n", hns3_driver_name, hns3_copyright);
596962306a36Sopenharmony_ci
597062306a36Sopenharmony_ci	client.type = HNAE3_CLIENT_KNIC;
597162306a36Sopenharmony_ci	snprintf(client.name, HNAE3_CLIENT_NAME_LENGTH, "%s",
597262306a36Sopenharmony_ci		 hns3_driver_name);
597362306a36Sopenharmony_ci
597462306a36Sopenharmony_ci	client.ops = &client_ops;
597562306a36Sopenharmony_ci
597662306a36Sopenharmony_ci	INIT_LIST_HEAD(&client.node);
597762306a36Sopenharmony_ci
597862306a36Sopenharmony_ci	hns3_dbg_register_debugfs(hns3_driver_name);
597962306a36Sopenharmony_ci
598062306a36Sopenharmony_ci	ret = hnae3_register_client(&client);
598162306a36Sopenharmony_ci	if (ret)
598262306a36Sopenharmony_ci		goto err_reg_client;
598362306a36Sopenharmony_ci
598462306a36Sopenharmony_ci	ret = pci_register_driver(&hns3_driver);
598562306a36Sopenharmony_ci	if (ret)
598662306a36Sopenharmony_ci		goto err_reg_driver;
598762306a36Sopenharmony_ci
598862306a36Sopenharmony_ci	return ret;
598962306a36Sopenharmony_ci
599062306a36Sopenharmony_cierr_reg_driver:
599162306a36Sopenharmony_ci	hnae3_unregister_client(&client);
599262306a36Sopenharmony_cierr_reg_client:
599362306a36Sopenharmony_ci	hns3_dbg_unregister_debugfs();
599462306a36Sopenharmony_ci	return ret;
599562306a36Sopenharmony_ci}
599662306a36Sopenharmony_cimodule_init(hns3_init_module);
599762306a36Sopenharmony_ci
599862306a36Sopenharmony_ci/* hns3_exit_module - Driver exit cleanup routine
599962306a36Sopenharmony_ci * hns3_exit_module is called just before the driver is removed
600062306a36Sopenharmony_ci * from memory.
600162306a36Sopenharmony_ci */
600262306a36Sopenharmony_cistatic void __exit hns3_exit_module(void)
600362306a36Sopenharmony_ci{
600462306a36Sopenharmony_ci	pci_unregister_driver(&hns3_driver);
600562306a36Sopenharmony_ci	hnae3_unregister_client(&client);
600662306a36Sopenharmony_ci	hns3_dbg_unregister_debugfs();
600762306a36Sopenharmony_ci}
600862306a36Sopenharmony_cimodule_exit(hns3_exit_module);
600962306a36Sopenharmony_ci
601062306a36Sopenharmony_ciMODULE_DESCRIPTION("HNS3: Hisilicon Ethernet Driver");
601162306a36Sopenharmony_ciMODULE_AUTHOR("Huawei Tech. Co., Ltd.");
601262306a36Sopenharmony_ciMODULE_LICENSE("GPL");
601362306a36Sopenharmony_ciMODULE_ALIAS("pci:hns-nic");
6014