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