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 ¶m->type_cs_vlan_tso, 163362306a36Sopenharmony_ci ¶m->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, ¶m->paylen_ol4cs, ¶m->mss_hw_csum, 164062306a36Sopenharmony_ci ¶m->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, ¶m); 165662306a36Sopenharmony_ci ret = hns3_handle_vlan_info(ring, skb, ¶m); 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, ¶m); 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