18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 2007 - 2018 Intel Corporation. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/module.h> 78c2ecf20Sopenharmony_ci#include <linux/types.h> 88c2ecf20Sopenharmony_ci#include <linux/init.h> 98c2ecf20Sopenharmony_ci#include <linux/bitops.h> 108c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 118c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 128c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 138c2ecf20Sopenharmony_ci#include <linux/ipv6.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <net/checksum.h> 168c2ecf20Sopenharmony_ci#include <net/ip6_checksum.h> 178c2ecf20Sopenharmony_ci#include <net/pkt_sched.h> 188c2ecf20Sopenharmony_ci#include <net/pkt_cls.h> 198c2ecf20Sopenharmony_ci#include <linux/net_tstamp.h> 208c2ecf20Sopenharmony_ci#include <linux/mii.h> 218c2ecf20Sopenharmony_ci#include <linux/ethtool.h> 228c2ecf20Sopenharmony_ci#include <linux/if.h> 238c2ecf20Sopenharmony_ci#include <linux/if_vlan.h> 248c2ecf20Sopenharmony_ci#include <linux/pci.h> 258c2ecf20Sopenharmony_ci#include <linux/delay.h> 268c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 278c2ecf20Sopenharmony_ci#include <linux/ip.h> 288c2ecf20Sopenharmony_ci#include <linux/tcp.h> 298c2ecf20Sopenharmony_ci#include <linux/sctp.h> 308c2ecf20Sopenharmony_ci#include <linux/if_ether.h> 318c2ecf20Sopenharmony_ci#include <linux/aer.h> 328c2ecf20Sopenharmony_ci#include <linux/prefetch.h> 338c2ecf20Sopenharmony_ci#include <linux/bpf.h> 348c2ecf20Sopenharmony_ci#include <linux/bpf_trace.h> 358c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 368c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 378c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_DCA 388c2ecf20Sopenharmony_ci#include <linux/dca.h> 398c2ecf20Sopenharmony_ci#endif 408c2ecf20Sopenharmony_ci#include <linux/i2c.h> 418c2ecf20Sopenharmony_ci#include "igb.h" 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cienum queue_mode { 448c2ecf20Sopenharmony_ci QUEUE_MODE_STRICT_PRIORITY, 458c2ecf20Sopenharmony_ci QUEUE_MODE_STREAM_RESERVATION, 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cienum tx_queue_prio { 498c2ecf20Sopenharmony_ci TX_QUEUE_PRIO_HIGH, 508c2ecf20Sopenharmony_ci TX_QUEUE_PRIO_LOW, 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cichar igb_driver_name[] = "igb"; 548c2ecf20Sopenharmony_cistatic const char igb_driver_string[] = 558c2ecf20Sopenharmony_ci "Intel(R) Gigabit Ethernet Network Driver"; 568c2ecf20Sopenharmony_cistatic const char igb_copyright[] = 578c2ecf20Sopenharmony_ci "Copyright (c) 2007-2014 Intel Corporation."; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic const struct e1000_info *igb_info_tbl[] = { 608c2ecf20Sopenharmony_ci [board_82575] = &e1000_82575_info, 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic const struct pci_device_id igb_pci_tbl[] = { 648c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_1GBPS) }, 658c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_SGMII) }, 668c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_2_5GBPS) }, 678c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I211_COPPER), board_82575 }, 688c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER), board_82575 }, 698c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_FIBER), board_82575 }, 708c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES), board_82575 }, 718c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SGMII), board_82575 }, 728c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER_FLASHLESS), board_82575 }, 738c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES_FLASHLESS), board_82575 }, 748c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_COPPER), board_82575 }, 758c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_FIBER), board_82575 }, 768c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SERDES), board_82575 }, 778c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SGMII), board_82575 }, 788c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER), board_82575 }, 798c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_FIBER), board_82575 }, 808c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_QUAD_FIBER), board_82575 }, 818c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES), board_82575 }, 828c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII), board_82575 }, 838c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 }, 848c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII), board_82575 }, 858c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES), board_82575 }, 868c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_BACKPLANE), board_82575 }, 878c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SFP), board_82575 }, 888c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 }, 898c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 }, 908c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES), board_82575 }, 918c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER), board_82575 }, 928c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES), board_82575 }, 938c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES_QUAD), board_82575 }, 948c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER_ET2), board_82575 }, 958c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER), board_82575 }, 968c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER), board_82575 }, 978c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES), board_82575 }, 988c2ecf20Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER), board_82575 }, 998c2ecf20Sopenharmony_ci /* required last entry */ 1008c2ecf20Sopenharmony_ci {0, } 1018c2ecf20Sopenharmony_ci}; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, igb_pci_tbl); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic int igb_setup_all_tx_resources(struct igb_adapter *); 1068c2ecf20Sopenharmony_cistatic int igb_setup_all_rx_resources(struct igb_adapter *); 1078c2ecf20Sopenharmony_cistatic void igb_free_all_tx_resources(struct igb_adapter *); 1088c2ecf20Sopenharmony_cistatic void igb_free_all_rx_resources(struct igb_adapter *); 1098c2ecf20Sopenharmony_cistatic void igb_setup_mrqc(struct igb_adapter *); 1108c2ecf20Sopenharmony_cistatic int igb_probe(struct pci_dev *, const struct pci_device_id *); 1118c2ecf20Sopenharmony_cistatic void igb_remove(struct pci_dev *pdev); 1128c2ecf20Sopenharmony_cistatic int igb_sw_init(struct igb_adapter *); 1138c2ecf20Sopenharmony_ciint igb_open(struct net_device *); 1148c2ecf20Sopenharmony_ciint igb_close(struct net_device *); 1158c2ecf20Sopenharmony_cistatic void igb_configure(struct igb_adapter *); 1168c2ecf20Sopenharmony_cistatic void igb_configure_tx(struct igb_adapter *); 1178c2ecf20Sopenharmony_cistatic void igb_configure_rx(struct igb_adapter *); 1188c2ecf20Sopenharmony_cistatic void igb_clean_all_tx_rings(struct igb_adapter *); 1198c2ecf20Sopenharmony_cistatic void igb_clean_all_rx_rings(struct igb_adapter *); 1208c2ecf20Sopenharmony_cistatic void igb_clean_tx_ring(struct igb_ring *); 1218c2ecf20Sopenharmony_cistatic void igb_clean_rx_ring(struct igb_ring *); 1228c2ecf20Sopenharmony_cistatic void igb_set_rx_mode(struct net_device *); 1238c2ecf20Sopenharmony_cistatic void igb_update_phy_info(struct timer_list *); 1248c2ecf20Sopenharmony_cistatic void igb_watchdog(struct timer_list *); 1258c2ecf20Sopenharmony_cistatic void igb_watchdog_task(struct work_struct *); 1268c2ecf20Sopenharmony_cistatic netdev_tx_t igb_xmit_frame(struct sk_buff *skb, struct net_device *); 1278c2ecf20Sopenharmony_cistatic void igb_get_stats64(struct net_device *dev, 1288c2ecf20Sopenharmony_ci struct rtnl_link_stats64 *stats); 1298c2ecf20Sopenharmony_cistatic int igb_change_mtu(struct net_device *, int); 1308c2ecf20Sopenharmony_cistatic int igb_set_mac(struct net_device *, void *); 1318c2ecf20Sopenharmony_cistatic void igb_set_uta(struct igb_adapter *adapter, bool set); 1328c2ecf20Sopenharmony_cistatic irqreturn_t igb_intr(int irq, void *); 1338c2ecf20Sopenharmony_cistatic irqreturn_t igb_intr_msi(int irq, void *); 1348c2ecf20Sopenharmony_cistatic irqreturn_t igb_msix_other(int irq, void *); 1358c2ecf20Sopenharmony_cistatic irqreturn_t igb_msix_ring(int irq, void *); 1368c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_DCA 1378c2ecf20Sopenharmony_cistatic void igb_update_dca(struct igb_q_vector *); 1388c2ecf20Sopenharmony_cistatic void igb_setup_dca(struct igb_adapter *); 1398c2ecf20Sopenharmony_ci#endif /* CONFIG_IGB_DCA */ 1408c2ecf20Sopenharmony_cistatic int igb_poll(struct napi_struct *, int); 1418c2ecf20Sopenharmony_cistatic bool igb_clean_tx_irq(struct igb_q_vector *, int); 1428c2ecf20Sopenharmony_cistatic int igb_clean_rx_irq(struct igb_q_vector *, int); 1438c2ecf20Sopenharmony_cistatic int igb_ioctl(struct net_device *, struct ifreq *, int cmd); 1448c2ecf20Sopenharmony_cistatic void igb_tx_timeout(struct net_device *, unsigned int txqueue); 1458c2ecf20Sopenharmony_cistatic void igb_reset_task(struct work_struct *); 1468c2ecf20Sopenharmony_cistatic void igb_vlan_mode(struct net_device *netdev, 1478c2ecf20Sopenharmony_ci netdev_features_t features); 1488c2ecf20Sopenharmony_cistatic int igb_vlan_rx_add_vid(struct net_device *, __be16, u16); 1498c2ecf20Sopenharmony_cistatic int igb_vlan_rx_kill_vid(struct net_device *, __be16, u16); 1508c2ecf20Sopenharmony_cistatic void igb_restore_vlan(struct igb_adapter *); 1518c2ecf20Sopenharmony_cistatic void igb_rar_set_index(struct igb_adapter *, u32); 1528c2ecf20Sopenharmony_cistatic void igb_ping_all_vfs(struct igb_adapter *); 1538c2ecf20Sopenharmony_cistatic void igb_msg_task(struct igb_adapter *); 1548c2ecf20Sopenharmony_cistatic void igb_vmm_control(struct igb_adapter *); 1558c2ecf20Sopenharmony_cistatic int igb_set_vf_mac(struct igb_adapter *, int, unsigned char *); 1568c2ecf20Sopenharmony_cistatic void igb_flush_mac_table(struct igb_adapter *); 1578c2ecf20Sopenharmony_cistatic int igb_available_rars(struct igb_adapter *, u8); 1588c2ecf20Sopenharmony_cistatic void igb_set_default_mac_filter(struct igb_adapter *); 1598c2ecf20Sopenharmony_cistatic int igb_uc_sync(struct net_device *, const unsigned char *); 1608c2ecf20Sopenharmony_cistatic int igb_uc_unsync(struct net_device *, const unsigned char *); 1618c2ecf20Sopenharmony_cistatic void igb_restore_vf_multicasts(struct igb_adapter *adapter); 1628c2ecf20Sopenharmony_cistatic int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac); 1638c2ecf20Sopenharmony_cistatic int igb_ndo_set_vf_vlan(struct net_device *netdev, 1648c2ecf20Sopenharmony_ci int vf, u16 vlan, u8 qos, __be16 vlan_proto); 1658c2ecf20Sopenharmony_cistatic int igb_ndo_set_vf_bw(struct net_device *, int, int, int); 1668c2ecf20Sopenharmony_cistatic int igb_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, 1678c2ecf20Sopenharmony_ci bool setting); 1688c2ecf20Sopenharmony_cistatic int igb_ndo_set_vf_trust(struct net_device *netdev, int vf, 1698c2ecf20Sopenharmony_ci bool setting); 1708c2ecf20Sopenharmony_cistatic int igb_ndo_get_vf_config(struct net_device *netdev, int vf, 1718c2ecf20Sopenharmony_ci struct ifla_vf_info *ivi); 1728c2ecf20Sopenharmony_cistatic void igb_check_vf_rate_limit(struct igb_adapter *); 1738c2ecf20Sopenharmony_cistatic void igb_nfc_filter_exit(struct igb_adapter *adapter); 1748c2ecf20Sopenharmony_cistatic void igb_nfc_filter_restore(struct igb_adapter *adapter); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 1778c2ecf20Sopenharmony_cistatic int igb_vf_configure(struct igb_adapter *adapter, int vf); 1788c2ecf20Sopenharmony_cistatic int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs); 1798c2ecf20Sopenharmony_cistatic int igb_disable_sriov(struct pci_dev *dev); 1808c2ecf20Sopenharmony_cistatic int igb_pci_disable_sriov(struct pci_dev *dev); 1818c2ecf20Sopenharmony_ci#endif 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic int igb_suspend(struct device *); 1848c2ecf20Sopenharmony_cistatic int igb_resume(struct device *); 1858c2ecf20Sopenharmony_cistatic int igb_runtime_suspend(struct device *dev); 1868c2ecf20Sopenharmony_cistatic int igb_runtime_resume(struct device *dev); 1878c2ecf20Sopenharmony_cistatic int igb_runtime_idle(struct device *dev); 1888c2ecf20Sopenharmony_cistatic const struct dev_pm_ops igb_pm_ops = { 1898c2ecf20Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(igb_suspend, igb_resume) 1908c2ecf20Sopenharmony_ci SET_RUNTIME_PM_OPS(igb_runtime_suspend, igb_runtime_resume, 1918c2ecf20Sopenharmony_ci igb_runtime_idle) 1928c2ecf20Sopenharmony_ci}; 1938c2ecf20Sopenharmony_cistatic void igb_shutdown(struct pci_dev *); 1948c2ecf20Sopenharmony_cistatic int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs); 1958c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_DCA 1968c2ecf20Sopenharmony_cistatic int igb_notify_dca(struct notifier_block *, unsigned long, void *); 1978c2ecf20Sopenharmony_cistatic struct notifier_block dca_notifier = { 1988c2ecf20Sopenharmony_ci .notifier_call = igb_notify_dca, 1998c2ecf20Sopenharmony_ci .next = NULL, 2008c2ecf20Sopenharmony_ci .priority = 0 2018c2ecf20Sopenharmony_ci}; 2028c2ecf20Sopenharmony_ci#endif 2038c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 2048c2ecf20Sopenharmony_cistatic unsigned int max_vfs; 2058c2ecf20Sopenharmony_cimodule_param(max_vfs, uint, 0); 2068c2ecf20Sopenharmony_ciMODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate per physical function"); 2078c2ecf20Sopenharmony_ci#endif /* CONFIG_PCI_IOV */ 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic pci_ers_result_t igb_io_error_detected(struct pci_dev *, 2108c2ecf20Sopenharmony_ci pci_channel_state_t); 2118c2ecf20Sopenharmony_cistatic pci_ers_result_t igb_io_slot_reset(struct pci_dev *); 2128c2ecf20Sopenharmony_cistatic void igb_io_resume(struct pci_dev *); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic const struct pci_error_handlers igb_err_handler = { 2158c2ecf20Sopenharmony_ci .error_detected = igb_io_error_detected, 2168c2ecf20Sopenharmony_ci .slot_reset = igb_io_slot_reset, 2178c2ecf20Sopenharmony_ci .resume = igb_io_resume, 2188c2ecf20Sopenharmony_ci}; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic void igb_init_dmac(struct igb_adapter *adapter, u32 pba); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic struct pci_driver igb_driver = { 2238c2ecf20Sopenharmony_ci .name = igb_driver_name, 2248c2ecf20Sopenharmony_ci .id_table = igb_pci_tbl, 2258c2ecf20Sopenharmony_ci .probe = igb_probe, 2268c2ecf20Sopenharmony_ci .remove = igb_remove, 2278c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 2288c2ecf20Sopenharmony_ci .driver.pm = &igb_pm_ops, 2298c2ecf20Sopenharmony_ci#endif 2308c2ecf20Sopenharmony_ci .shutdown = igb_shutdown, 2318c2ecf20Sopenharmony_ci .sriov_configure = igb_pci_sriov_configure, 2328c2ecf20Sopenharmony_ci .err_handler = &igb_err_handler 2338c2ecf20Sopenharmony_ci}; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ciMODULE_AUTHOR("Intel Corporation, <e1000-devel@lists.sourceforge.net>"); 2368c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver"); 2378c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) 2408c2ecf20Sopenharmony_cistatic int debug = -1; 2418c2ecf20Sopenharmony_cimodule_param(debug, int, 0); 2428c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_cistruct igb_reg_info { 2458c2ecf20Sopenharmony_ci u32 ofs; 2468c2ecf20Sopenharmony_ci char *name; 2478c2ecf20Sopenharmony_ci}; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic const struct igb_reg_info igb_reg_info_tbl[] = { 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci /* General Registers */ 2528c2ecf20Sopenharmony_ci {E1000_CTRL, "CTRL"}, 2538c2ecf20Sopenharmony_ci {E1000_STATUS, "STATUS"}, 2548c2ecf20Sopenharmony_ci {E1000_CTRL_EXT, "CTRL_EXT"}, 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci /* Interrupt Registers */ 2578c2ecf20Sopenharmony_ci {E1000_ICR, "ICR"}, 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* RX Registers */ 2608c2ecf20Sopenharmony_ci {E1000_RCTL, "RCTL"}, 2618c2ecf20Sopenharmony_ci {E1000_RDLEN(0), "RDLEN"}, 2628c2ecf20Sopenharmony_ci {E1000_RDH(0), "RDH"}, 2638c2ecf20Sopenharmony_ci {E1000_RDT(0), "RDT"}, 2648c2ecf20Sopenharmony_ci {E1000_RXDCTL(0), "RXDCTL"}, 2658c2ecf20Sopenharmony_ci {E1000_RDBAL(0), "RDBAL"}, 2668c2ecf20Sopenharmony_ci {E1000_RDBAH(0), "RDBAH"}, 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* TX Registers */ 2698c2ecf20Sopenharmony_ci {E1000_TCTL, "TCTL"}, 2708c2ecf20Sopenharmony_ci {E1000_TDBAL(0), "TDBAL"}, 2718c2ecf20Sopenharmony_ci {E1000_TDBAH(0), "TDBAH"}, 2728c2ecf20Sopenharmony_ci {E1000_TDLEN(0), "TDLEN"}, 2738c2ecf20Sopenharmony_ci {E1000_TDH(0), "TDH"}, 2748c2ecf20Sopenharmony_ci {E1000_TDT(0), "TDT"}, 2758c2ecf20Sopenharmony_ci {E1000_TXDCTL(0), "TXDCTL"}, 2768c2ecf20Sopenharmony_ci {E1000_TDFH, "TDFH"}, 2778c2ecf20Sopenharmony_ci {E1000_TDFT, "TDFT"}, 2788c2ecf20Sopenharmony_ci {E1000_TDFHS, "TDFHS"}, 2798c2ecf20Sopenharmony_ci {E1000_TDFPC, "TDFPC"}, 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci /* List Terminator */ 2828c2ecf20Sopenharmony_ci {} 2838c2ecf20Sopenharmony_ci}; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci/* igb_regdump - register printout routine */ 2868c2ecf20Sopenharmony_cistatic void igb_regdump(struct e1000_hw *hw, struct igb_reg_info *reginfo) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci int n = 0; 2898c2ecf20Sopenharmony_ci char rname[16]; 2908c2ecf20Sopenharmony_ci u32 regs[8]; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci switch (reginfo->ofs) { 2938c2ecf20Sopenharmony_ci case E1000_RDLEN(0): 2948c2ecf20Sopenharmony_ci for (n = 0; n < 4; n++) 2958c2ecf20Sopenharmony_ci regs[n] = rd32(E1000_RDLEN(n)); 2968c2ecf20Sopenharmony_ci break; 2978c2ecf20Sopenharmony_ci case E1000_RDH(0): 2988c2ecf20Sopenharmony_ci for (n = 0; n < 4; n++) 2998c2ecf20Sopenharmony_ci regs[n] = rd32(E1000_RDH(n)); 3008c2ecf20Sopenharmony_ci break; 3018c2ecf20Sopenharmony_ci case E1000_RDT(0): 3028c2ecf20Sopenharmony_ci for (n = 0; n < 4; n++) 3038c2ecf20Sopenharmony_ci regs[n] = rd32(E1000_RDT(n)); 3048c2ecf20Sopenharmony_ci break; 3058c2ecf20Sopenharmony_ci case E1000_RXDCTL(0): 3068c2ecf20Sopenharmony_ci for (n = 0; n < 4; n++) 3078c2ecf20Sopenharmony_ci regs[n] = rd32(E1000_RXDCTL(n)); 3088c2ecf20Sopenharmony_ci break; 3098c2ecf20Sopenharmony_ci case E1000_RDBAL(0): 3108c2ecf20Sopenharmony_ci for (n = 0; n < 4; n++) 3118c2ecf20Sopenharmony_ci regs[n] = rd32(E1000_RDBAL(n)); 3128c2ecf20Sopenharmony_ci break; 3138c2ecf20Sopenharmony_ci case E1000_RDBAH(0): 3148c2ecf20Sopenharmony_ci for (n = 0; n < 4; n++) 3158c2ecf20Sopenharmony_ci regs[n] = rd32(E1000_RDBAH(n)); 3168c2ecf20Sopenharmony_ci break; 3178c2ecf20Sopenharmony_ci case E1000_TDBAL(0): 3188c2ecf20Sopenharmony_ci for (n = 0; n < 4; n++) 3198c2ecf20Sopenharmony_ci regs[n] = rd32(E1000_RDBAL(n)); 3208c2ecf20Sopenharmony_ci break; 3218c2ecf20Sopenharmony_ci case E1000_TDBAH(0): 3228c2ecf20Sopenharmony_ci for (n = 0; n < 4; n++) 3238c2ecf20Sopenharmony_ci regs[n] = rd32(E1000_TDBAH(n)); 3248c2ecf20Sopenharmony_ci break; 3258c2ecf20Sopenharmony_ci case E1000_TDLEN(0): 3268c2ecf20Sopenharmony_ci for (n = 0; n < 4; n++) 3278c2ecf20Sopenharmony_ci regs[n] = rd32(E1000_TDLEN(n)); 3288c2ecf20Sopenharmony_ci break; 3298c2ecf20Sopenharmony_ci case E1000_TDH(0): 3308c2ecf20Sopenharmony_ci for (n = 0; n < 4; n++) 3318c2ecf20Sopenharmony_ci regs[n] = rd32(E1000_TDH(n)); 3328c2ecf20Sopenharmony_ci break; 3338c2ecf20Sopenharmony_ci case E1000_TDT(0): 3348c2ecf20Sopenharmony_ci for (n = 0; n < 4; n++) 3358c2ecf20Sopenharmony_ci regs[n] = rd32(E1000_TDT(n)); 3368c2ecf20Sopenharmony_ci break; 3378c2ecf20Sopenharmony_ci case E1000_TXDCTL(0): 3388c2ecf20Sopenharmony_ci for (n = 0; n < 4; n++) 3398c2ecf20Sopenharmony_ci regs[n] = rd32(E1000_TXDCTL(n)); 3408c2ecf20Sopenharmony_ci break; 3418c2ecf20Sopenharmony_ci default: 3428c2ecf20Sopenharmony_ci pr_info("%-15s %08x\n", reginfo->name, rd32(reginfo->ofs)); 3438c2ecf20Sopenharmony_ci return; 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]"); 3478c2ecf20Sopenharmony_ci pr_info("%-15s %08x %08x %08x %08x\n", rname, regs[0], regs[1], 3488c2ecf20Sopenharmony_ci regs[2], regs[3]); 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci/* igb_dump - Print registers, Tx-rings and Rx-rings */ 3528c2ecf20Sopenharmony_cistatic void igb_dump(struct igb_adapter *adapter) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 3558c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 3568c2ecf20Sopenharmony_ci struct igb_reg_info *reginfo; 3578c2ecf20Sopenharmony_ci struct igb_ring *tx_ring; 3588c2ecf20Sopenharmony_ci union e1000_adv_tx_desc *tx_desc; 3598c2ecf20Sopenharmony_ci struct my_u0 { u64 a; u64 b; } *u0; 3608c2ecf20Sopenharmony_ci struct igb_ring *rx_ring; 3618c2ecf20Sopenharmony_ci union e1000_adv_rx_desc *rx_desc; 3628c2ecf20Sopenharmony_ci u32 staterr; 3638c2ecf20Sopenharmony_ci u16 i, n; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci if (!netif_msg_hw(adapter)) 3668c2ecf20Sopenharmony_ci return; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci /* Print netdevice Info */ 3698c2ecf20Sopenharmony_ci if (netdev) { 3708c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, "Net device Info\n"); 3718c2ecf20Sopenharmony_ci pr_info("Device Name state trans_start\n"); 3728c2ecf20Sopenharmony_ci pr_info("%-15s %016lX %016lX\n", netdev->name, 3738c2ecf20Sopenharmony_ci netdev->state, dev_trans_start(netdev)); 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* Print Registers */ 3778c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, "Register Dump\n"); 3788c2ecf20Sopenharmony_ci pr_info(" Register Name Value\n"); 3798c2ecf20Sopenharmony_ci for (reginfo = (struct igb_reg_info *)igb_reg_info_tbl; 3808c2ecf20Sopenharmony_ci reginfo->name; reginfo++) { 3818c2ecf20Sopenharmony_ci igb_regdump(hw, reginfo); 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci /* Print TX Ring Summary */ 3858c2ecf20Sopenharmony_ci if (!netdev || !netif_running(netdev)) 3868c2ecf20Sopenharmony_ci goto exit; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, "TX Rings Summary\n"); 3898c2ecf20Sopenharmony_ci pr_info("Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n"); 3908c2ecf20Sopenharmony_ci for (n = 0; n < adapter->num_tx_queues; n++) { 3918c2ecf20Sopenharmony_ci struct igb_tx_buffer *buffer_info; 3928c2ecf20Sopenharmony_ci tx_ring = adapter->tx_ring[n]; 3938c2ecf20Sopenharmony_ci buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean]; 3948c2ecf20Sopenharmony_ci pr_info(" %5d %5X %5X %016llX %04X %p %016llX\n", 3958c2ecf20Sopenharmony_ci n, tx_ring->next_to_use, tx_ring->next_to_clean, 3968c2ecf20Sopenharmony_ci (u64)dma_unmap_addr(buffer_info, dma), 3978c2ecf20Sopenharmony_ci dma_unmap_len(buffer_info, len), 3988c2ecf20Sopenharmony_ci buffer_info->next_to_watch, 3998c2ecf20Sopenharmony_ci (u64)buffer_info->time_stamp); 4008c2ecf20Sopenharmony_ci } 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci /* Print TX Rings */ 4038c2ecf20Sopenharmony_ci if (!netif_msg_tx_done(adapter)) 4048c2ecf20Sopenharmony_ci goto rx_ring_summary; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, "TX Rings Dump\n"); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci /* Transmit Descriptor Formats 4098c2ecf20Sopenharmony_ci * 4108c2ecf20Sopenharmony_ci * Advanced Transmit Descriptor 4118c2ecf20Sopenharmony_ci * +--------------------------------------------------------------+ 4128c2ecf20Sopenharmony_ci * 0 | Buffer Address [63:0] | 4138c2ecf20Sopenharmony_ci * +--------------------------------------------------------------+ 4148c2ecf20Sopenharmony_ci * 8 | PAYLEN | PORTS |CC|IDX | STA | DCMD |DTYP|MAC|RSV| DTALEN | 4158c2ecf20Sopenharmony_ci * +--------------------------------------------------------------+ 4168c2ecf20Sopenharmony_ci * 63 46 45 40 39 38 36 35 32 31 24 15 0 4178c2ecf20Sopenharmony_ci */ 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci for (n = 0; n < adapter->num_tx_queues; n++) { 4208c2ecf20Sopenharmony_ci tx_ring = adapter->tx_ring[n]; 4218c2ecf20Sopenharmony_ci pr_info("------------------------------------\n"); 4228c2ecf20Sopenharmony_ci pr_info("TX QUEUE INDEX = %d\n", tx_ring->queue_index); 4238c2ecf20Sopenharmony_ci pr_info("------------------------------------\n"); 4248c2ecf20Sopenharmony_ci pr_info("T [desc] [address 63:0 ] [PlPOCIStDDM Ln] [bi->dma ] leng ntw timestamp bi->skb\n"); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { 4278c2ecf20Sopenharmony_ci const char *next_desc; 4288c2ecf20Sopenharmony_ci struct igb_tx_buffer *buffer_info; 4298c2ecf20Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, i); 4308c2ecf20Sopenharmony_ci buffer_info = &tx_ring->tx_buffer_info[i]; 4318c2ecf20Sopenharmony_ci u0 = (struct my_u0 *)tx_desc; 4328c2ecf20Sopenharmony_ci if (i == tx_ring->next_to_use && 4338c2ecf20Sopenharmony_ci i == tx_ring->next_to_clean) 4348c2ecf20Sopenharmony_ci next_desc = " NTC/U"; 4358c2ecf20Sopenharmony_ci else if (i == tx_ring->next_to_use) 4368c2ecf20Sopenharmony_ci next_desc = " NTU"; 4378c2ecf20Sopenharmony_ci else if (i == tx_ring->next_to_clean) 4388c2ecf20Sopenharmony_ci next_desc = " NTC"; 4398c2ecf20Sopenharmony_ci else 4408c2ecf20Sopenharmony_ci next_desc = ""; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci pr_info("T [0x%03X] %016llX %016llX %016llX %04X %p %016llX %p%s\n", 4438c2ecf20Sopenharmony_ci i, le64_to_cpu(u0->a), 4448c2ecf20Sopenharmony_ci le64_to_cpu(u0->b), 4458c2ecf20Sopenharmony_ci (u64)dma_unmap_addr(buffer_info, dma), 4468c2ecf20Sopenharmony_ci dma_unmap_len(buffer_info, len), 4478c2ecf20Sopenharmony_ci buffer_info->next_to_watch, 4488c2ecf20Sopenharmony_ci (u64)buffer_info->time_stamp, 4498c2ecf20Sopenharmony_ci buffer_info->skb, next_desc); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci if (netif_msg_pktdata(adapter) && buffer_info->skb) 4528c2ecf20Sopenharmony_ci print_hex_dump(KERN_INFO, "", 4538c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 4548c2ecf20Sopenharmony_ci 16, 1, buffer_info->skb->data, 4558c2ecf20Sopenharmony_ci dma_unmap_len(buffer_info, len), 4568c2ecf20Sopenharmony_ci true); 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci /* Print RX Rings Summary */ 4618c2ecf20Sopenharmony_cirx_ring_summary: 4628c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, "RX Rings Summary\n"); 4638c2ecf20Sopenharmony_ci pr_info("Queue [NTU] [NTC]\n"); 4648c2ecf20Sopenharmony_ci for (n = 0; n < adapter->num_rx_queues; n++) { 4658c2ecf20Sopenharmony_ci rx_ring = adapter->rx_ring[n]; 4668c2ecf20Sopenharmony_ci pr_info(" %5d %5X %5X\n", 4678c2ecf20Sopenharmony_ci n, rx_ring->next_to_use, rx_ring->next_to_clean); 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci /* Print RX Rings */ 4718c2ecf20Sopenharmony_ci if (!netif_msg_rx_status(adapter)) 4728c2ecf20Sopenharmony_ci goto exit; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, "RX Rings Dump\n"); 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci /* Advanced Receive Descriptor (Read) Format 4778c2ecf20Sopenharmony_ci * 63 1 0 4788c2ecf20Sopenharmony_ci * +-----------------------------------------------------+ 4798c2ecf20Sopenharmony_ci * 0 | Packet Buffer Address [63:1] |A0/NSE| 4808c2ecf20Sopenharmony_ci * +----------------------------------------------+------+ 4818c2ecf20Sopenharmony_ci * 8 | Header Buffer Address [63:1] | DD | 4828c2ecf20Sopenharmony_ci * +-----------------------------------------------------+ 4838c2ecf20Sopenharmony_ci * 4848c2ecf20Sopenharmony_ci * 4858c2ecf20Sopenharmony_ci * Advanced Receive Descriptor (Write-Back) Format 4868c2ecf20Sopenharmony_ci * 4878c2ecf20Sopenharmony_ci * 63 48 47 32 31 30 21 20 17 16 4 3 0 4888c2ecf20Sopenharmony_ci * +------------------------------------------------------+ 4898c2ecf20Sopenharmony_ci * 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS | 4908c2ecf20Sopenharmony_ci * | Checksum Ident | | | | Type | Type | 4918c2ecf20Sopenharmony_ci * +------------------------------------------------------+ 4928c2ecf20Sopenharmony_ci * 8 | VLAN Tag | Length | Extended Error | Extended Status | 4938c2ecf20Sopenharmony_ci * +------------------------------------------------------+ 4948c2ecf20Sopenharmony_ci * 63 48 47 32 31 20 19 0 4958c2ecf20Sopenharmony_ci */ 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci for (n = 0; n < adapter->num_rx_queues; n++) { 4988c2ecf20Sopenharmony_ci rx_ring = adapter->rx_ring[n]; 4998c2ecf20Sopenharmony_ci pr_info("------------------------------------\n"); 5008c2ecf20Sopenharmony_ci pr_info("RX QUEUE INDEX = %d\n", rx_ring->queue_index); 5018c2ecf20Sopenharmony_ci pr_info("------------------------------------\n"); 5028c2ecf20Sopenharmony_ci pr_info("R [desc] [ PktBuf A0] [ HeadBuf DD] [bi->dma ] [bi->skb] <-- Adv Rx Read format\n"); 5038c2ecf20Sopenharmony_ci pr_info("RWB[desc] [PcsmIpSHl PtRs] [vl er S cks ln] ---------------- [bi->skb] <-- Adv Rx Write-Back format\n"); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci for (i = 0; i < rx_ring->count; i++) { 5068c2ecf20Sopenharmony_ci const char *next_desc; 5078c2ecf20Sopenharmony_ci struct igb_rx_buffer *buffer_info; 5088c2ecf20Sopenharmony_ci buffer_info = &rx_ring->rx_buffer_info[i]; 5098c2ecf20Sopenharmony_ci rx_desc = IGB_RX_DESC(rx_ring, i); 5108c2ecf20Sopenharmony_ci u0 = (struct my_u0 *)rx_desc; 5118c2ecf20Sopenharmony_ci staterr = le32_to_cpu(rx_desc->wb.upper.status_error); 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci if (i == rx_ring->next_to_use) 5148c2ecf20Sopenharmony_ci next_desc = " NTU"; 5158c2ecf20Sopenharmony_ci else if (i == rx_ring->next_to_clean) 5168c2ecf20Sopenharmony_ci next_desc = " NTC"; 5178c2ecf20Sopenharmony_ci else 5188c2ecf20Sopenharmony_ci next_desc = ""; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci if (staterr & E1000_RXD_STAT_DD) { 5218c2ecf20Sopenharmony_ci /* Descriptor Done */ 5228c2ecf20Sopenharmony_ci pr_info("%s[0x%03X] %016llX %016llX ---------------- %s\n", 5238c2ecf20Sopenharmony_ci "RWB", i, 5248c2ecf20Sopenharmony_ci le64_to_cpu(u0->a), 5258c2ecf20Sopenharmony_ci le64_to_cpu(u0->b), 5268c2ecf20Sopenharmony_ci next_desc); 5278c2ecf20Sopenharmony_ci } else { 5288c2ecf20Sopenharmony_ci pr_info("%s[0x%03X] %016llX %016llX %016llX %s\n", 5298c2ecf20Sopenharmony_ci "R ", i, 5308c2ecf20Sopenharmony_ci le64_to_cpu(u0->a), 5318c2ecf20Sopenharmony_ci le64_to_cpu(u0->b), 5328c2ecf20Sopenharmony_ci (u64)buffer_info->dma, 5338c2ecf20Sopenharmony_ci next_desc); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci if (netif_msg_pktdata(adapter) && 5368c2ecf20Sopenharmony_ci buffer_info->dma && buffer_info->page) { 5378c2ecf20Sopenharmony_ci print_hex_dump(KERN_INFO, "", 5388c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 5398c2ecf20Sopenharmony_ci 16, 1, 5408c2ecf20Sopenharmony_ci page_address(buffer_info->page) + 5418c2ecf20Sopenharmony_ci buffer_info->page_offset, 5428c2ecf20Sopenharmony_ci igb_rx_bufsz(rx_ring), true); 5438c2ecf20Sopenharmony_ci } 5448c2ecf20Sopenharmony_ci } 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ciexit: 5498c2ecf20Sopenharmony_ci return; 5508c2ecf20Sopenharmony_ci} 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci/** 5538c2ecf20Sopenharmony_ci * igb_get_i2c_data - Reads the I2C SDA data bit 5548c2ecf20Sopenharmony_ci * @data: opaque pointer to adapter struct 5558c2ecf20Sopenharmony_ci * 5568c2ecf20Sopenharmony_ci * Returns the I2C data bit value 5578c2ecf20Sopenharmony_ci **/ 5588c2ecf20Sopenharmony_cistatic int igb_get_i2c_data(void *data) 5598c2ecf20Sopenharmony_ci{ 5608c2ecf20Sopenharmony_ci struct igb_adapter *adapter = (struct igb_adapter *)data; 5618c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 5628c2ecf20Sopenharmony_ci s32 i2cctl = rd32(E1000_I2CPARAMS); 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci return !!(i2cctl & E1000_I2C_DATA_IN); 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci/** 5688c2ecf20Sopenharmony_ci * igb_set_i2c_data - Sets the I2C data bit 5698c2ecf20Sopenharmony_ci * @data: pointer to hardware structure 5708c2ecf20Sopenharmony_ci * @state: I2C data value (0 or 1) to set 5718c2ecf20Sopenharmony_ci * 5728c2ecf20Sopenharmony_ci * Sets the I2C data bit 5738c2ecf20Sopenharmony_ci **/ 5748c2ecf20Sopenharmony_cistatic void igb_set_i2c_data(void *data, int state) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci struct igb_adapter *adapter = (struct igb_adapter *)data; 5778c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 5788c2ecf20Sopenharmony_ci s32 i2cctl = rd32(E1000_I2CPARAMS); 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci if (state) 5818c2ecf20Sopenharmony_ci i2cctl |= E1000_I2C_DATA_OUT; 5828c2ecf20Sopenharmony_ci else 5838c2ecf20Sopenharmony_ci i2cctl &= ~E1000_I2C_DATA_OUT; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci i2cctl &= ~E1000_I2C_DATA_OE_N; 5868c2ecf20Sopenharmony_ci i2cctl |= E1000_I2C_CLK_OE_N; 5878c2ecf20Sopenharmony_ci wr32(E1000_I2CPARAMS, i2cctl); 5888c2ecf20Sopenharmony_ci wrfl(); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci} 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci/** 5938c2ecf20Sopenharmony_ci * igb_set_i2c_clk - Sets the I2C SCL clock 5948c2ecf20Sopenharmony_ci * @data: pointer to hardware structure 5958c2ecf20Sopenharmony_ci * @state: state to set clock 5968c2ecf20Sopenharmony_ci * 5978c2ecf20Sopenharmony_ci * Sets the I2C clock line to state 5988c2ecf20Sopenharmony_ci **/ 5998c2ecf20Sopenharmony_cistatic void igb_set_i2c_clk(void *data, int state) 6008c2ecf20Sopenharmony_ci{ 6018c2ecf20Sopenharmony_ci struct igb_adapter *adapter = (struct igb_adapter *)data; 6028c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 6038c2ecf20Sopenharmony_ci s32 i2cctl = rd32(E1000_I2CPARAMS); 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci if (state) { 6068c2ecf20Sopenharmony_ci i2cctl |= E1000_I2C_CLK_OUT; 6078c2ecf20Sopenharmony_ci i2cctl &= ~E1000_I2C_CLK_OE_N; 6088c2ecf20Sopenharmony_ci } else { 6098c2ecf20Sopenharmony_ci i2cctl &= ~E1000_I2C_CLK_OUT; 6108c2ecf20Sopenharmony_ci i2cctl &= ~E1000_I2C_CLK_OE_N; 6118c2ecf20Sopenharmony_ci } 6128c2ecf20Sopenharmony_ci wr32(E1000_I2CPARAMS, i2cctl); 6138c2ecf20Sopenharmony_ci wrfl(); 6148c2ecf20Sopenharmony_ci} 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci/** 6178c2ecf20Sopenharmony_ci * igb_get_i2c_clk - Gets the I2C SCL clock state 6188c2ecf20Sopenharmony_ci * @data: pointer to hardware structure 6198c2ecf20Sopenharmony_ci * 6208c2ecf20Sopenharmony_ci * Gets the I2C clock state 6218c2ecf20Sopenharmony_ci **/ 6228c2ecf20Sopenharmony_cistatic int igb_get_i2c_clk(void *data) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci struct igb_adapter *adapter = (struct igb_adapter *)data; 6258c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 6268c2ecf20Sopenharmony_ci s32 i2cctl = rd32(E1000_I2CPARAMS); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci return !!(i2cctl & E1000_I2C_CLK_IN); 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic const struct i2c_algo_bit_data igb_i2c_algo = { 6328c2ecf20Sopenharmony_ci .setsda = igb_set_i2c_data, 6338c2ecf20Sopenharmony_ci .setscl = igb_set_i2c_clk, 6348c2ecf20Sopenharmony_ci .getsda = igb_get_i2c_data, 6358c2ecf20Sopenharmony_ci .getscl = igb_get_i2c_clk, 6368c2ecf20Sopenharmony_ci .udelay = 5, 6378c2ecf20Sopenharmony_ci .timeout = 20, 6388c2ecf20Sopenharmony_ci}; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci/** 6418c2ecf20Sopenharmony_ci * igb_get_hw_dev - return device 6428c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 6438c2ecf20Sopenharmony_ci * 6448c2ecf20Sopenharmony_ci * used by hardware layer to print debugging information 6458c2ecf20Sopenharmony_ci **/ 6468c2ecf20Sopenharmony_cistruct net_device *igb_get_hw_dev(struct e1000_hw *hw) 6478c2ecf20Sopenharmony_ci{ 6488c2ecf20Sopenharmony_ci struct igb_adapter *adapter = hw->back; 6498c2ecf20Sopenharmony_ci return adapter->netdev; 6508c2ecf20Sopenharmony_ci} 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci/** 6538c2ecf20Sopenharmony_ci * igb_init_module - Driver Registration Routine 6548c2ecf20Sopenharmony_ci * 6558c2ecf20Sopenharmony_ci * igb_init_module is the first routine called when the driver is 6568c2ecf20Sopenharmony_ci * loaded. All it does is register with the PCI subsystem. 6578c2ecf20Sopenharmony_ci **/ 6588c2ecf20Sopenharmony_cistatic int __init igb_init_module(void) 6598c2ecf20Sopenharmony_ci{ 6608c2ecf20Sopenharmony_ci int ret; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci pr_info("%s\n", igb_driver_string); 6638c2ecf20Sopenharmony_ci pr_info("%s\n", igb_copyright); 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_DCA 6668c2ecf20Sopenharmony_ci dca_register_notify(&dca_notifier); 6678c2ecf20Sopenharmony_ci#endif 6688c2ecf20Sopenharmony_ci ret = pci_register_driver(&igb_driver); 6698c2ecf20Sopenharmony_ci return ret; 6708c2ecf20Sopenharmony_ci} 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_cimodule_init(igb_init_module); 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci/** 6758c2ecf20Sopenharmony_ci * igb_exit_module - Driver Exit Cleanup Routine 6768c2ecf20Sopenharmony_ci * 6778c2ecf20Sopenharmony_ci * igb_exit_module is called just before the driver is removed 6788c2ecf20Sopenharmony_ci * from memory. 6798c2ecf20Sopenharmony_ci **/ 6808c2ecf20Sopenharmony_cistatic void __exit igb_exit_module(void) 6818c2ecf20Sopenharmony_ci{ 6828c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_DCA 6838c2ecf20Sopenharmony_ci dca_unregister_notify(&dca_notifier); 6848c2ecf20Sopenharmony_ci#endif 6858c2ecf20Sopenharmony_ci pci_unregister_driver(&igb_driver); 6868c2ecf20Sopenharmony_ci} 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_cimodule_exit(igb_exit_module); 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci#define Q_IDX_82576(i) (((i & 0x1) << 3) + (i >> 1)) 6918c2ecf20Sopenharmony_ci/** 6928c2ecf20Sopenharmony_ci * igb_cache_ring_register - Descriptor ring to register mapping 6938c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 6948c2ecf20Sopenharmony_ci * 6958c2ecf20Sopenharmony_ci * Once we know the feature-set enabled for the device, we'll cache 6968c2ecf20Sopenharmony_ci * the register offset the descriptor ring is assigned to. 6978c2ecf20Sopenharmony_ci **/ 6988c2ecf20Sopenharmony_cistatic void igb_cache_ring_register(struct igb_adapter *adapter) 6998c2ecf20Sopenharmony_ci{ 7008c2ecf20Sopenharmony_ci int i = 0, j = 0; 7018c2ecf20Sopenharmony_ci u32 rbase_offset = adapter->vfs_allocated_count; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci switch (adapter->hw.mac.type) { 7048c2ecf20Sopenharmony_ci case e1000_82576: 7058c2ecf20Sopenharmony_ci /* The queues are allocated for virtualization such that VF 0 7068c2ecf20Sopenharmony_ci * is allocated queues 0 and 8, VF 1 queues 1 and 9, etc. 7078c2ecf20Sopenharmony_ci * In order to avoid collision we start at the first free queue 7088c2ecf20Sopenharmony_ci * and continue consuming queues in the same sequence 7098c2ecf20Sopenharmony_ci */ 7108c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count) { 7118c2ecf20Sopenharmony_ci for (; i < adapter->rss_queues; i++) 7128c2ecf20Sopenharmony_ci adapter->rx_ring[i]->reg_idx = rbase_offset + 7138c2ecf20Sopenharmony_ci Q_IDX_82576(i); 7148c2ecf20Sopenharmony_ci } 7158c2ecf20Sopenharmony_ci fallthrough; 7168c2ecf20Sopenharmony_ci case e1000_82575: 7178c2ecf20Sopenharmony_ci case e1000_82580: 7188c2ecf20Sopenharmony_ci case e1000_i350: 7198c2ecf20Sopenharmony_ci case e1000_i354: 7208c2ecf20Sopenharmony_ci case e1000_i210: 7218c2ecf20Sopenharmony_ci case e1000_i211: 7228c2ecf20Sopenharmony_ci default: 7238c2ecf20Sopenharmony_ci for (; i < adapter->num_rx_queues; i++) 7248c2ecf20Sopenharmony_ci adapter->rx_ring[i]->reg_idx = rbase_offset + i; 7258c2ecf20Sopenharmony_ci for (; j < adapter->num_tx_queues; j++) 7268c2ecf20Sopenharmony_ci adapter->tx_ring[j]->reg_idx = rbase_offset + j; 7278c2ecf20Sopenharmony_ci break; 7288c2ecf20Sopenharmony_ci } 7298c2ecf20Sopenharmony_ci} 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ciu32 igb_rd32(struct e1000_hw *hw, u32 reg) 7328c2ecf20Sopenharmony_ci{ 7338c2ecf20Sopenharmony_ci struct igb_adapter *igb = container_of(hw, struct igb_adapter, hw); 7348c2ecf20Sopenharmony_ci u8 __iomem *hw_addr = READ_ONCE(hw->hw_addr); 7358c2ecf20Sopenharmony_ci u32 value = 0; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci if (E1000_REMOVED(hw_addr)) 7388c2ecf20Sopenharmony_ci return ~value; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci value = readl(&hw_addr[reg]); 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci /* reads should not return all F's */ 7438c2ecf20Sopenharmony_ci if (!(~value) && (!reg || !(~readl(hw_addr)))) { 7448c2ecf20Sopenharmony_ci struct net_device *netdev = igb->netdev; 7458c2ecf20Sopenharmony_ci hw->hw_addr = NULL; 7468c2ecf20Sopenharmony_ci netdev_err(netdev, "PCIe link lost\n"); 7478c2ecf20Sopenharmony_ci WARN(pci_device_is_present(igb->pdev), 7488c2ecf20Sopenharmony_ci "igb: Failed to read reg 0x%x!\n", reg); 7498c2ecf20Sopenharmony_ci } 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci return value; 7528c2ecf20Sopenharmony_ci} 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci/** 7558c2ecf20Sopenharmony_ci * igb_write_ivar - configure ivar for given MSI-X vector 7568c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 7578c2ecf20Sopenharmony_ci * @msix_vector: vector number we are allocating to a given ring 7588c2ecf20Sopenharmony_ci * @index: row index of IVAR register to write within IVAR table 7598c2ecf20Sopenharmony_ci * @offset: column offset of in IVAR, should be multiple of 8 7608c2ecf20Sopenharmony_ci * 7618c2ecf20Sopenharmony_ci * This function is intended to handle the writing of the IVAR register 7628c2ecf20Sopenharmony_ci * for adapters 82576 and newer. The IVAR table consists of 2 columns, 7638c2ecf20Sopenharmony_ci * each containing an cause allocation for an Rx and Tx ring, and a 7648c2ecf20Sopenharmony_ci * variable number of rows depending on the number of queues supported. 7658c2ecf20Sopenharmony_ci **/ 7668c2ecf20Sopenharmony_cistatic void igb_write_ivar(struct e1000_hw *hw, int msix_vector, 7678c2ecf20Sopenharmony_ci int index, int offset) 7688c2ecf20Sopenharmony_ci{ 7698c2ecf20Sopenharmony_ci u32 ivar = array_rd32(E1000_IVAR0, index); 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci /* clear any bits that are currently set */ 7728c2ecf20Sopenharmony_ci ivar &= ~((u32)0xFF << offset); 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci /* write vector and valid bit */ 7758c2ecf20Sopenharmony_ci ivar |= (msix_vector | E1000_IVAR_VALID) << offset; 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci array_wr32(E1000_IVAR0, index, ivar); 7788c2ecf20Sopenharmony_ci} 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci#define IGB_N0_QUEUE -1 7818c2ecf20Sopenharmony_cistatic void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) 7828c2ecf20Sopenharmony_ci{ 7838c2ecf20Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 7848c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 7858c2ecf20Sopenharmony_ci int rx_queue = IGB_N0_QUEUE; 7868c2ecf20Sopenharmony_ci int tx_queue = IGB_N0_QUEUE; 7878c2ecf20Sopenharmony_ci u32 msixbm = 0; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci if (q_vector->rx.ring) 7908c2ecf20Sopenharmony_ci rx_queue = q_vector->rx.ring->reg_idx; 7918c2ecf20Sopenharmony_ci if (q_vector->tx.ring) 7928c2ecf20Sopenharmony_ci tx_queue = q_vector->tx.ring->reg_idx; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci switch (hw->mac.type) { 7958c2ecf20Sopenharmony_ci case e1000_82575: 7968c2ecf20Sopenharmony_ci /* The 82575 assigns vectors using a bitmask, which matches the 7978c2ecf20Sopenharmony_ci * bitmask for the EICR/EIMS/EIMC registers. To assign one 7988c2ecf20Sopenharmony_ci * or more queues to a vector, we write the appropriate bits 7998c2ecf20Sopenharmony_ci * into the MSIXBM register for that vector. 8008c2ecf20Sopenharmony_ci */ 8018c2ecf20Sopenharmony_ci if (rx_queue > IGB_N0_QUEUE) 8028c2ecf20Sopenharmony_ci msixbm = E1000_EICR_RX_QUEUE0 << rx_queue; 8038c2ecf20Sopenharmony_ci if (tx_queue > IGB_N0_QUEUE) 8048c2ecf20Sopenharmony_ci msixbm |= E1000_EICR_TX_QUEUE0 << tx_queue; 8058c2ecf20Sopenharmony_ci if (!(adapter->flags & IGB_FLAG_HAS_MSIX) && msix_vector == 0) 8068c2ecf20Sopenharmony_ci msixbm |= E1000_EIMS_OTHER; 8078c2ecf20Sopenharmony_ci array_wr32(E1000_MSIXBM(0), msix_vector, msixbm); 8088c2ecf20Sopenharmony_ci q_vector->eims_value = msixbm; 8098c2ecf20Sopenharmony_ci break; 8108c2ecf20Sopenharmony_ci case e1000_82576: 8118c2ecf20Sopenharmony_ci /* 82576 uses a table that essentially consists of 2 columns 8128c2ecf20Sopenharmony_ci * with 8 rows. The ordering is column-major so we use the 8138c2ecf20Sopenharmony_ci * lower 3 bits as the row index, and the 4th bit as the 8148c2ecf20Sopenharmony_ci * column offset. 8158c2ecf20Sopenharmony_ci */ 8168c2ecf20Sopenharmony_ci if (rx_queue > IGB_N0_QUEUE) 8178c2ecf20Sopenharmony_ci igb_write_ivar(hw, msix_vector, 8188c2ecf20Sopenharmony_ci rx_queue & 0x7, 8198c2ecf20Sopenharmony_ci (rx_queue & 0x8) << 1); 8208c2ecf20Sopenharmony_ci if (tx_queue > IGB_N0_QUEUE) 8218c2ecf20Sopenharmony_ci igb_write_ivar(hw, msix_vector, 8228c2ecf20Sopenharmony_ci tx_queue & 0x7, 8238c2ecf20Sopenharmony_ci ((tx_queue & 0x8) << 1) + 8); 8248c2ecf20Sopenharmony_ci q_vector->eims_value = BIT(msix_vector); 8258c2ecf20Sopenharmony_ci break; 8268c2ecf20Sopenharmony_ci case e1000_82580: 8278c2ecf20Sopenharmony_ci case e1000_i350: 8288c2ecf20Sopenharmony_ci case e1000_i354: 8298c2ecf20Sopenharmony_ci case e1000_i210: 8308c2ecf20Sopenharmony_ci case e1000_i211: 8318c2ecf20Sopenharmony_ci /* On 82580 and newer adapters the scheme is similar to 82576 8328c2ecf20Sopenharmony_ci * however instead of ordering column-major we have things 8338c2ecf20Sopenharmony_ci * ordered row-major. So we traverse the table by using 8348c2ecf20Sopenharmony_ci * bit 0 as the column offset, and the remaining bits as the 8358c2ecf20Sopenharmony_ci * row index. 8368c2ecf20Sopenharmony_ci */ 8378c2ecf20Sopenharmony_ci if (rx_queue > IGB_N0_QUEUE) 8388c2ecf20Sopenharmony_ci igb_write_ivar(hw, msix_vector, 8398c2ecf20Sopenharmony_ci rx_queue >> 1, 8408c2ecf20Sopenharmony_ci (rx_queue & 0x1) << 4); 8418c2ecf20Sopenharmony_ci if (tx_queue > IGB_N0_QUEUE) 8428c2ecf20Sopenharmony_ci igb_write_ivar(hw, msix_vector, 8438c2ecf20Sopenharmony_ci tx_queue >> 1, 8448c2ecf20Sopenharmony_ci ((tx_queue & 0x1) << 4) + 8); 8458c2ecf20Sopenharmony_ci q_vector->eims_value = BIT(msix_vector); 8468c2ecf20Sopenharmony_ci break; 8478c2ecf20Sopenharmony_ci default: 8488c2ecf20Sopenharmony_ci BUG(); 8498c2ecf20Sopenharmony_ci break; 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci /* add q_vector eims value to global eims_enable_mask */ 8538c2ecf20Sopenharmony_ci adapter->eims_enable_mask |= q_vector->eims_value; 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci /* configure q_vector to set itr on first interrupt */ 8568c2ecf20Sopenharmony_ci q_vector->set_itr = 1; 8578c2ecf20Sopenharmony_ci} 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci/** 8608c2ecf20Sopenharmony_ci * igb_configure_msix - Configure MSI-X hardware 8618c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 8628c2ecf20Sopenharmony_ci * 8638c2ecf20Sopenharmony_ci * igb_configure_msix sets up the hardware to properly 8648c2ecf20Sopenharmony_ci * generate MSI-X interrupts. 8658c2ecf20Sopenharmony_ci **/ 8668c2ecf20Sopenharmony_cistatic void igb_configure_msix(struct igb_adapter *adapter) 8678c2ecf20Sopenharmony_ci{ 8688c2ecf20Sopenharmony_ci u32 tmp; 8698c2ecf20Sopenharmony_ci int i, vector = 0; 8708c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci adapter->eims_enable_mask = 0; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci /* set vector for other causes, i.e. link changes */ 8758c2ecf20Sopenharmony_ci switch (hw->mac.type) { 8768c2ecf20Sopenharmony_ci case e1000_82575: 8778c2ecf20Sopenharmony_ci tmp = rd32(E1000_CTRL_EXT); 8788c2ecf20Sopenharmony_ci /* enable MSI-X PBA support*/ 8798c2ecf20Sopenharmony_ci tmp |= E1000_CTRL_EXT_PBA_CLR; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci /* Auto-Mask interrupts upon ICR read. */ 8828c2ecf20Sopenharmony_ci tmp |= E1000_CTRL_EXT_EIAME; 8838c2ecf20Sopenharmony_ci tmp |= E1000_CTRL_EXT_IRCA; 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci wr32(E1000_CTRL_EXT, tmp); 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci /* enable msix_other interrupt */ 8888c2ecf20Sopenharmony_ci array_wr32(E1000_MSIXBM(0), vector++, E1000_EIMS_OTHER); 8898c2ecf20Sopenharmony_ci adapter->eims_other = E1000_EIMS_OTHER; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci break; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci case e1000_82576: 8948c2ecf20Sopenharmony_ci case e1000_82580: 8958c2ecf20Sopenharmony_ci case e1000_i350: 8968c2ecf20Sopenharmony_ci case e1000_i354: 8978c2ecf20Sopenharmony_ci case e1000_i210: 8988c2ecf20Sopenharmony_ci case e1000_i211: 8998c2ecf20Sopenharmony_ci /* Turn on MSI-X capability first, or our settings 9008c2ecf20Sopenharmony_ci * won't stick. And it will take days to debug. 9018c2ecf20Sopenharmony_ci */ 9028c2ecf20Sopenharmony_ci wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE | 9038c2ecf20Sopenharmony_ci E1000_GPIE_PBA | E1000_GPIE_EIAME | 9048c2ecf20Sopenharmony_ci E1000_GPIE_NSICR); 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci /* enable msix_other interrupt */ 9078c2ecf20Sopenharmony_ci adapter->eims_other = BIT(vector); 9088c2ecf20Sopenharmony_ci tmp = (vector++ | E1000_IVAR_VALID) << 8; 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci wr32(E1000_IVAR_MISC, tmp); 9118c2ecf20Sopenharmony_ci break; 9128c2ecf20Sopenharmony_ci default: 9138c2ecf20Sopenharmony_ci /* do nothing, since nothing else supports MSI-X */ 9148c2ecf20Sopenharmony_ci break; 9158c2ecf20Sopenharmony_ci } /* switch (hw->mac.type) */ 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci adapter->eims_enable_mask |= adapter->eims_other; 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) 9208c2ecf20Sopenharmony_ci igb_assign_vector(adapter->q_vector[i], vector++); 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci wrfl(); 9238c2ecf20Sopenharmony_ci} 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci/** 9268c2ecf20Sopenharmony_ci * igb_request_msix - Initialize MSI-X interrupts 9278c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 9288c2ecf20Sopenharmony_ci * 9298c2ecf20Sopenharmony_ci * igb_request_msix allocates MSI-X vectors and requests interrupts from the 9308c2ecf20Sopenharmony_ci * kernel. 9318c2ecf20Sopenharmony_ci **/ 9328c2ecf20Sopenharmony_cistatic int igb_request_msix(struct igb_adapter *adapter) 9338c2ecf20Sopenharmony_ci{ 9348c2ecf20Sopenharmony_ci unsigned int num_q_vectors = adapter->num_q_vectors; 9358c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 9368c2ecf20Sopenharmony_ci int i, err = 0, vector = 0, free_vector = 0; 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci err = request_irq(adapter->msix_entries[vector].vector, 9398c2ecf20Sopenharmony_ci igb_msix_other, 0, netdev->name, adapter); 9408c2ecf20Sopenharmony_ci if (err) 9418c2ecf20Sopenharmony_ci goto err_out; 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci if (num_q_vectors > MAX_Q_VECTORS) { 9448c2ecf20Sopenharmony_ci num_q_vectors = MAX_Q_VECTORS; 9458c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, 9468c2ecf20Sopenharmony_ci "The number of queue vectors (%d) is higher than max allowed (%d)\n", 9478c2ecf20Sopenharmony_ci adapter->num_q_vectors, MAX_Q_VECTORS); 9488c2ecf20Sopenharmony_ci } 9498c2ecf20Sopenharmony_ci for (i = 0; i < num_q_vectors; i++) { 9508c2ecf20Sopenharmony_ci struct igb_q_vector *q_vector = adapter->q_vector[i]; 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci vector++; 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci q_vector->itr_register = adapter->io_addr + E1000_EITR(vector); 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci if (q_vector->rx.ring && q_vector->tx.ring) 9578c2ecf20Sopenharmony_ci sprintf(q_vector->name, "%s-TxRx-%u", netdev->name, 9588c2ecf20Sopenharmony_ci q_vector->rx.ring->queue_index); 9598c2ecf20Sopenharmony_ci else if (q_vector->tx.ring) 9608c2ecf20Sopenharmony_ci sprintf(q_vector->name, "%s-tx-%u", netdev->name, 9618c2ecf20Sopenharmony_ci q_vector->tx.ring->queue_index); 9628c2ecf20Sopenharmony_ci else if (q_vector->rx.ring) 9638c2ecf20Sopenharmony_ci sprintf(q_vector->name, "%s-rx-%u", netdev->name, 9648c2ecf20Sopenharmony_ci q_vector->rx.ring->queue_index); 9658c2ecf20Sopenharmony_ci else 9668c2ecf20Sopenharmony_ci sprintf(q_vector->name, "%s-unused", netdev->name); 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci err = request_irq(adapter->msix_entries[vector].vector, 9698c2ecf20Sopenharmony_ci igb_msix_ring, 0, q_vector->name, 9708c2ecf20Sopenharmony_ci q_vector); 9718c2ecf20Sopenharmony_ci if (err) 9728c2ecf20Sopenharmony_ci goto err_free; 9738c2ecf20Sopenharmony_ci } 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci igb_configure_msix(adapter); 9768c2ecf20Sopenharmony_ci return 0; 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_cierr_free: 9798c2ecf20Sopenharmony_ci /* free already assigned IRQs */ 9808c2ecf20Sopenharmony_ci free_irq(adapter->msix_entries[free_vector++].vector, adapter); 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci vector--; 9838c2ecf20Sopenharmony_ci for (i = 0; i < vector; i++) { 9848c2ecf20Sopenharmony_ci free_irq(adapter->msix_entries[free_vector++].vector, 9858c2ecf20Sopenharmony_ci adapter->q_vector[i]); 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_cierr_out: 9888c2ecf20Sopenharmony_ci return err; 9898c2ecf20Sopenharmony_ci} 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci/** 9928c2ecf20Sopenharmony_ci * igb_free_q_vector - Free memory allocated for specific interrupt vector 9938c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 9948c2ecf20Sopenharmony_ci * @v_idx: Index of vector to be freed 9958c2ecf20Sopenharmony_ci * 9968c2ecf20Sopenharmony_ci * This function frees the memory allocated to the q_vector. 9978c2ecf20Sopenharmony_ci **/ 9988c2ecf20Sopenharmony_cistatic void igb_free_q_vector(struct igb_adapter *adapter, int v_idx) 9998c2ecf20Sopenharmony_ci{ 10008c2ecf20Sopenharmony_ci struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci adapter->q_vector[v_idx] = NULL; 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci /* igb_get_stats64() might access the rings on this vector, 10058c2ecf20Sopenharmony_ci * we must wait a grace period before freeing it. 10068c2ecf20Sopenharmony_ci */ 10078c2ecf20Sopenharmony_ci if (q_vector) 10088c2ecf20Sopenharmony_ci kfree_rcu(q_vector, rcu); 10098c2ecf20Sopenharmony_ci} 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci/** 10128c2ecf20Sopenharmony_ci * igb_reset_q_vector - Reset config for interrupt vector 10138c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 10148c2ecf20Sopenharmony_ci * @v_idx: Index of vector to be reset 10158c2ecf20Sopenharmony_ci * 10168c2ecf20Sopenharmony_ci * If NAPI is enabled it will delete any references to the 10178c2ecf20Sopenharmony_ci * NAPI struct. This is preparation for igb_free_q_vector. 10188c2ecf20Sopenharmony_ci **/ 10198c2ecf20Sopenharmony_cistatic void igb_reset_q_vector(struct igb_adapter *adapter, int v_idx) 10208c2ecf20Sopenharmony_ci{ 10218c2ecf20Sopenharmony_ci struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci /* Coming from igb_set_interrupt_capability, the vectors are not yet 10248c2ecf20Sopenharmony_ci * allocated. So, q_vector is NULL so we should stop here. 10258c2ecf20Sopenharmony_ci */ 10268c2ecf20Sopenharmony_ci if (!q_vector) 10278c2ecf20Sopenharmony_ci return; 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci if (q_vector->tx.ring) 10308c2ecf20Sopenharmony_ci adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL; 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci if (q_vector->rx.ring) 10338c2ecf20Sopenharmony_ci adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci netif_napi_del(&q_vector->napi); 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci} 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_cistatic void igb_reset_interrupt_capability(struct igb_adapter *adapter) 10408c2ecf20Sopenharmony_ci{ 10418c2ecf20Sopenharmony_ci int v_idx = adapter->num_q_vectors; 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) 10448c2ecf20Sopenharmony_ci pci_disable_msix(adapter->pdev); 10458c2ecf20Sopenharmony_ci else if (adapter->flags & IGB_FLAG_HAS_MSI) 10468c2ecf20Sopenharmony_ci pci_disable_msi(adapter->pdev); 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci while (v_idx--) 10498c2ecf20Sopenharmony_ci igb_reset_q_vector(adapter, v_idx); 10508c2ecf20Sopenharmony_ci} 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci/** 10538c2ecf20Sopenharmony_ci * igb_free_q_vectors - Free memory allocated for interrupt vectors 10548c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 10558c2ecf20Sopenharmony_ci * 10568c2ecf20Sopenharmony_ci * This function frees the memory allocated to the q_vectors. In addition if 10578c2ecf20Sopenharmony_ci * NAPI is enabled it will delete any references to the NAPI struct prior 10588c2ecf20Sopenharmony_ci * to freeing the q_vector. 10598c2ecf20Sopenharmony_ci **/ 10608c2ecf20Sopenharmony_cistatic void igb_free_q_vectors(struct igb_adapter *adapter) 10618c2ecf20Sopenharmony_ci{ 10628c2ecf20Sopenharmony_ci int v_idx = adapter->num_q_vectors; 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci adapter->num_tx_queues = 0; 10658c2ecf20Sopenharmony_ci adapter->num_rx_queues = 0; 10668c2ecf20Sopenharmony_ci adapter->num_q_vectors = 0; 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci while (v_idx--) { 10698c2ecf20Sopenharmony_ci igb_reset_q_vector(adapter, v_idx); 10708c2ecf20Sopenharmony_ci igb_free_q_vector(adapter, v_idx); 10718c2ecf20Sopenharmony_ci } 10728c2ecf20Sopenharmony_ci} 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci/** 10758c2ecf20Sopenharmony_ci * igb_clear_interrupt_scheme - reset the device to a state of no interrupts 10768c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 10778c2ecf20Sopenharmony_ci * 10788c2ecf20Sopenharmony_ci * This function resets the device so that it has 0 Rx queues, Tx queues, and 10798c2ecf20Sopenharmony_ci * MSI-X interrupts allocated. 10808c2ecf20Sopenharmony_ci */ 10818c2ecf20Sopenharmony_cistatic void igb_clear_interrupt_scheme(struct igb_adapter *adapter) 10828c2ecf20Sopenharmony_ci{ 10838c2ecf20Sopenharmony_ci igb_free_q_vectors(adapter); 10848c2ecf20Sopenharmony_ci igb_reset_interrupt_capability(adapter); 10858c2ecf20Sopenharmony_ci} 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci/** 10888c2ecf20Sopenharmony_ci * igb_set_interrupt_capability - set MSI or MSI-X if supported 10898c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 10908c2ecf20Sopenharmony_ci * @msix: boolean value of MSIX capability 10918c2ecf20Sopenharmony_ci * 10928c2ecf20Sopenharmony_ci * Attempt to configure interrupts using the best available 10938c2ecf20Sopenharmony_ci * capabilities of the hardware and kernel. 10948c2ecf20Sopenharmony_ci **/ 10958c2ecf20Sopenharmony_cistatic void igb_set_interrupt_capability(struct igb_adapter *adapter, bool msix) 10968c2ecf20Sopenharmony_ci{ 10978c2ecf20Sopenharmony_ci int err; 10988c2ecf20Sopenharmony_ci int numvecs, i; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci if (!msix) 11018c2ecf20Sopenharmony_ci goto msi_only; 11028c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_HAS_MSIX; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci /* Number of supported queues. */ 11058c2ecf20Sopenharmony_ci adapter->num_rx_queues = adapter->rss_queues; 11068c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count) 11078c2ecf20Sopenharmony_ci adapter->num_tx_queues = 1; 11088c2ecf20Sopenharmony_ci else 11098c2ecf20Sopenharmony_ci adapter->num_tx_queues = adapter->rss_queues; 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci /* start with one vector for every Rx queue */ 11128c2ecf20Sopenharmony_ci numvecs = adapter->num_rx_queues; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci /* if Tx handler is separate add 1 for every Tx queue */ 11158c2ecf20Sopenharmony_ci if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS)) 11168c2ecf20Sopenharmony_ci numvecs += adapter->num_tx_queues; 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci /* store the number of vectors reserved for queues */ 11198c2ecf20Sopenharmony_ci adapter->num_q_vectors = numvecs; 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci /* add 1 vector for link status interrupts */ 11228c2ecf20Sopenharmony_ci numvecs++; 11238c2ecf20Sopenharmony_ci for (i = 0; i < numvecs; i++) 11248c2ecf20Sopenharmony_ci adapter->msix_entries[i].entry = i; 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci err = pci_enable_msix_range(adapter->pdev, 11278c2ecf20Sopenharmony_ci adapter->msix_entries, 11288c2ecf20Sopenharmony_ci numvecs, 11298c2ecf20Sopenharmony_ci numvecs); 11308c2ecf20Sopenharmony_ci if (err > 0) 11318c2ecf20Sopenharmony_ci return; 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci igb_reset_interrupt_capability(adapter); 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci /* If we can't do MSI-X, try MSI */ 11368c2ecf20Sopenharmony_cimsi_only: 11378c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_HAS_MSIX; 11388c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 11398c2ecf20Sopenharmony_ci /* disable SR-IOV for non MSI-X configurations */ 11408c2ecf20Sopenharmony_ci if (adapter->vf_data) { 11418c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 11428c2ecf20Sopenharmony_ci /* disable iov and allow time for transactions to clear */ 11438c2ecf20Sopenharmony_ci pci_disable_sriov(adapter->pdev); 11448c2ecf20Sopenharmony_ci msleep(500); 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci kfree(adapter->vf_mac_list); 11478c2ecf20Sopenharmony_ci adapter->vf_mac_list = NULL; 11488c2ecf20Sopenharmony_ci kfree(adapter->vf_data); 11498c2ecf20Sopenharmony_ci adapter->vf_data = NULL; 11508c2ecf20Sopenharmony_ci wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ); 11518c2ecf20Sopenharmony_ci wrfl(); 11528c2ecf20Sopenharmony_ci msleep(100); 11538c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, "IOV Disabled\n"); 11548c2ecf20Sopenharmony_ci } 11558c2ecf20Sopenharmony_ci#endif 11568c2ecf20Sopenharmony_ci adapter->vfs_allocated_count = 0; 11578c2ecf20Sopenharmony_ci adapter->rss_queues = 1; 11588c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_QUEUE_PAIRS; 11598c2ecf20Sopenharmony_ci adapter->num_rx_queues = 1; 11608c2ecf20Sopenharmony_ci adapter->num_tx_queues = 1; 11618c2ecf20Sopenharmony_ci adapter->num_q_vectors = 1; 11628c2ecf20Sopenharmony_ci if (!pci_enable_msi(adapter->pdev)) 11638c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_HAS_MSI; 11648c2ecf20Sopenharmony_ci} 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_cistatic void igb_add_ring(struct igb_ring *ring, 11678c2ecf20Sopenharmony_ci struct igb_ring_container *head) 11688c2ecf20Sopenharmony_ci{ 11698c2ecf20Sopenharmony_ci head->ring = ring; 11708c2ecf20Sopenharmony_ci head->count++; 11718c2ecf20Sopenharmony_ci} 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci/** 11748c2ecf20Sopenharmony_ci * igb_alloc_q_vector - Allocate memory for a single interrupt vector 11758c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 11768c2ecf20Sopenharmony_ci * @v_count: q_vectors allocated on adapter, used for ring interleaving 11778c2ecf20Sopenharmony_ci * @v_idx: index of vector in adapter struct 11788c2ecf20Sopenharmony_ci * @txr_count: total number of Tx rings to allocate 11798c2ecf20Sopenharmony_ci * @txr_idx: index of first Tx ring to allocate 11808c2ecf20Sopenharmony_ci * @rxr_count: total number of Rx rings to allocate 11818c2ecf20Sopenharmony_ci * @rxr_idx: index of first Rx ring to allocate 11828c2ecf20Sopenharmony_ci * 11838c2ecf20Sopenharmony_ci * We allocate one q_vector. If allocation fails we return -ENOMEM. 11848c2ecf20Sopenharmony_ci **/ 11858c2ecf20Sopenharmony_cistatic int igb_alloc_q_vector(struct igb_adapter *adapter, 11868c2ecf20Sopenharmony_ci int v_count, int v_idx, 11878c2ecf20Sopenharmony_ci int txr_count, int txr_idx, 11888c2ecf20Sopenharmony_ci int rxr_count, int rxr_idx) 11898c2ecf20Sopenharmony_ci{ 11908c2ecf20Sopenharmony_ci struct igb_q_vector *q_vector; 11918c2ecf20Sopenharmony_ci struct igb_ring *ring; 11928c2ecf20Sopenharmony_ci int ring_count; 11938c2ecf20Sopenharmony_ci size_t size; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci /* igb only supports 1 Tx and/or 1 Rx queue per vector */ 11968c2ecf20Sopenharmony_ci if (txr_count > 1 || rxr_count > 1) 11978c2ecf20Sopenharmony_ci return -ENOMEM; 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci ring_count = txr_count + rxr_count; 12008c2ecf20Sopenharmony_ci size = struct_size(q_vector, ring, ring_count); 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci /* allocate q_vector and rings */ 12038c2ecf20Sopenharmony_ci q_vector = adapter->q_vector[v_idx]; 12048c2ecf20Sopenharmony_ci if (!q_vector) { 12058c2ecf20Sopenharmony_ci q_vector = kzalloc(size, GFP_KERNEL); 12068c2ecf20Sopenharmony_ci } else if (size > ksize(q_vector)) { 12078c2ecf20Sopenharmony_ci struct igb_q_vector *new_q_vector; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci new_q_vector = kzalloc(size, GFP_KERNEL); 12108c2ecf20Sopenharmony_ci if (new_q_vector) 12118c2ecf20Sopenharmony_ci kfree_rcu(q_vector, rcu); 12128c2ecf20Sopenharmony_ci q_vector = new_q_vector; 12138c2ecf20Sopenharmony_ci } else { 12148c2ecf20Sopenharmony_ci memset(q_vector, 0, size); 12158c2ecf20Sopenharmony_ci } 12168c2ecf20Sopenharmony_ci if (!q_vector) 12178c2ecf20Sopenharmony_ci return -ENOMEM; 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci /* initialize NAPI */ 12208c2ecf20Sopenharmony_ci netif_napi_add(adapter->netdev, &q_vector->napi, 12218c2ecf20Sopenharmony_ci igb_poll, 64); 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci /* tie q_vector and adapter together */ 12248c2ecf20Sopenharmony_ci adapter->q_vector[v_idx] = q_vector; 12258c2ecf20Sopenharmony_ci q_vector->adapter = adapter; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci /* initialize work limits */ 12288c2ecf20Sopenharmony_ci q_vector->tx.work_limit = adapter->tx_work_limit; 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci /* initialize ITR configuration */ 12318c2ecf20Sopenharmony_ci q_vector->itr_register = adapter->io_addr + E1000_EITR(0); 12328c2ecf20Sopenharmony_ci q_vector->itr_val = IGB_START_ITR; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci /* initialize pointer to rings */ 12358c2ecf20Sopenharmony_ci ring = q_vector->ring; 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci /* intialize ITR */ 12388c2ecf20Sopenharmony_ci if (rxr_count) { 12398c2ecf20Sopenharmony_ci /* rx or rx/tx vector */ 12408c2ecf20Sopenharmony_ci if (!adapter->rx_itr_setting || adapter->rx_itr_setting > 3) 12418c2ecf20Sopenharmony_ci q_vector->itr_val = adapter->rx_itr_setting; 12428c2ecf20Sopenharmony_ci } else { 12438c2ecf20Sopenharmony_ci /* tx only vector */ 12448c2ecf20Sopenharmony_ci if (!adapter->tx_itr_setting || adapter->tx_itr_setting > 3) 12458c2ecf20Sopenharmony_ci q_vector->itr_val = adapter->tx_itr_setting; 12468c2ecf20Sopenharmony_ci } 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci if (txr_count) { 12498c2ecf20Sopenharmony_ci /* assign generic ring traits */ 12508c2ecf20Sopenharmony_ci ring->dev = &adapter->pdev->dev; 12518c2ecf20Sopenharmony_ci ring->netdev = adapter->netdev; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci /* configure backlink on ring */ 12548c2ecf20Sopenharmony_ci ring->q_vector = q_vector; 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci /* update q_vector Tx values */ 12578c2ecf20Sopenharmony_ci igb_add_ring(ring, &q_vector->tx); 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci /* For 82575, context index must be unique per ring. */ 12608c2ecf20Sopenharmony_ci if (adapter->hw.mac.type == e1000_82575) 12618c2ecf20Sopenharmony_ci set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags); 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci /* apply Tx specific ring traits */ 12648c2ecf20Sopenharmony_ci ring->count = adapter->tx_ring_count; 12658c2ecf20Sopenharmony_ci ring->queue_index = txr_idx; 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci ring->cbs_enable = false; 12688c2ecf20Sopenharmony_ci ring->idleslope = 0; 12698c2ecf20Sopenharmony_ci ring->sendslope = 0; 12708c2ecf20Sopenharmony_ci ring->hicredit = 0; 12718c2ecf20Sopenharmony_ci ring->locredit = 0; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci u64_stats_init(&ring->tx_syncp); 12748c2ecf20Sopenharmony_ci u64_stats_init(&ring->tx_syncp2); 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci /* assign ring to adapter */ 12778c2ecf20Sopenharmony_ci adapter->tx_ring[txr_idx] = ring; 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci /* push pointer to next ring */ 12808c2ecf20Sopenharmony_ci ring++; 12818c2ecf20Sopenharmony_ci } 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci if (rxr_count) { 12848c2ecf20Sopenharmony_ci /* assign generic ring traits */ 12858c2ecf20Sopenharmony_ci ring->dev = &adapter->pdev->dev; 12868c2ecf20Sopenharmony_ci ring->netdev = adapter->netdev; 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci /* configure backlink on ring */ 12898c2ecf20Sopenharmony_ci ring->q_vector = q_vector; 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci /* update q_vector Rx values */ 12928c2ecf20Sopenharmony_ci igb_add_ring(ring, &q_vector->rx); 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci /* set flag indicating ring supports SCTP checksum offload */ 12958c2ecf20Sopenharmony_ci if (adapter->hw.mac.type >= e1000_82576) 12968c2ecf20Sopenharmony_ci set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags); 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci /* On i350, i354, i210, and i211, loopback VLAN packets 12998c2ecf20Sopenharmony_ci * have the tag byte-swapped. 13008c2ecf20Sopenharmony_ci */ 13018c2ecf20Sopenharmony_ci if (adapter->hw.mac.type >= e1000_i350) 13028c2ecf20Sopenharmony_ci set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags); 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci /* apply Rx specific ring traits */ 13058c2ecf20Sopenharmony_ci ring->count = adapter->rx_ring_count; 13068c2ecf20Sopenharmony_ci ring->queue_index = rxr_idx; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci u64_stats_init(&ring->rx_syncp); 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci /* assign ring to adapter */ 13118c2ecf20Sopenharmony_ci adapter->rx_ring[rxr_idx] = ring; 13128c2ecf20Sopenharmony_ci } 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci return 0; 13158c2ecf20Sopenharmony_ci} 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci/** 13198c2ecf20Sopenharmony_ci * igb_alloc_q_vectors - Allocate memory for interrupt vectors 13208c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 13218c2ecf20Sopenharmony_ci * 13228c2ecf20Sopenharmony_ci * We allocate one q_vector per queue interrupt. If allocation fails we 13238c2ecf20Sopenharmony_ci * return -ENOMEM. 13248c2ecf20Sopenharmony_ci **/ 13258c2ecf20Sopenharmony_cistatic int igb_alloc_q_vectors(struct igb_adapter *adapter) 13268c2ecf20Sopenharmony_ci{ 13278c2ecf20Sopenharmony_ci int q_vectors = adapter->num_q_vectors; 13288c2ecf20Sopenharmony_ci int rxr_remaining = adapter->num_rx_queues; 13298c2ecf20Sopenharmony_ci int txr_remaining = adapter->num_tx_queues; 13308c2ecf20Sopenharmony_ci int rxr_idx = 0, txr_idx = 0, v_idx = 0; 13318c2ecf20Sopenharmony_ci int err; 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci if (q_vectors >= (rxr_remaining + txr_remaining)) { 13348c2ecf20Sopenharmony_ci for (; rxr_remaining; v_idx++) { 13358c2ecf20Sopenharmony_ci err = igb_alloc_q_vector(adapter, q_vectors, v_idx, 13368c2ecf20Sopenharmony_ci 0, 0, 1, rxr_idx); 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci if (err) 13398c2ecf20Sopenharmony_ci goto err_out; 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci /* update counts and index */ 13428c2ecf20Sopenharmony_ci rxr_remaining--; 13438c2ecf20Sopenharmony_ci rxr_idx++; 13448c2ecf20Sopenharmony_ci } 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci for (; v_idx < q_vectors; v_idx++) { 13488c2ecf20Sopenharmony_ci int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx); 13498c2ecf20Sopenharmony_ci int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx); 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci err = igb_alloc_q_vector(adapter, q_vectors, v_idx, 13528c2ecf20Sopenharmony_ci tqpv, txr_idx, rqpv, rxr_idx); 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci if (err) 13558c2ecf20Sopenharmony_ci goto err_out; 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci /* update counts and index */ 13588c2ecf20Sopenharmony_ci rxr_remaining -= rqpv; 13598c2ecf20Sopenharmony_ci txr_remaining -= tqpv; 13608c2ecf20Sopenharmony_ci rxr_idx++; 13618c2ecf20Sopenharmony_ci txr_idx++; 13628c2ecf20Sopenharmony_ci } 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci return 0; 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_cierr_out: 13678c2ecf20Sopenharmony_ci adapter->num_tx_queues = 0; 13688c2ecf20Sopenharmony_ci adapter->num_rx_queues = 0; 13698c2ecf20Sopenharmony_ci adapter->num_q_vectors = 0; 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci while (v_idx--) 13728c2ecf20Sopenharmony_ci igb_free_q_vector(adapter, v_idx); 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_ci return -ENOMEM; 13758c2ecf20Sopenharmony_ci} 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_ci/** 13788c2ecf20Sopenharmony_ci * igb_init_interrupt_scheme - initialize interrupts, allocate queues/vectors 13798c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 13808c2ecf20Sopenharmony_ci * @msix: boolean value of MSIX capability 13818c2ecf20Sopenharmony_ci * 13828c2ecf20Sopenharmony_ci * This function initializes the interrupts and allocates all of the queues. 13838c2ecf20Sopenharmony_ci **/ 13848c2ecf20Sopenharmony_cistatic int igb_init_interrupt_scheme(struct igb_adapter *adapter, bool msix) 13858c2ecf20Sopenharmony_ci{ 13868c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 13878c2ecf20Sopenharmony_ci int err; 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci igb_set_interrupt_capability(adapter, msix); 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci err = igb_alloc_q_vectors(adapter); 13928c2ecf20Sopenharmony_ci if (err) { 13938c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unable to allocate memory for vectors\n"); 13948c2ecf20Sopenharmony_ci goto err_alloc_q_vectors; 13958c2ecf20Sopenharmony_ci } 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci igb_cache_ring_register(adapter); 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci return 0; 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_cierr_alloc_q_vectors: 14028c2ecf20Sopenharmony_ci igb_reset_interrupt_capability(adapter); 14038c2ecf20Sopenharmony_ci return err; 14048c2ecf20Sopenharmony_ci} 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci/** 14078c2ecf20Sopenharmony_ci * igb_request_irq - initialize interrupts 14088c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 14098c2ecf20Sopenharmony_ci * 14108c2ecf20Sopenharmony_ci * Attempts to configure interrupts using the best available 14118c2ecf20Sopenharmony_ci * capabilities of the hardware and kernel. 14128c2ecf20Sopenharmony_ci **/ 14138c2ecf20Sopenharmony_cistatic int igb_request_irq(struct igb_adapter *adapter) 14148c2ecf20Sopenharmony_ci{ 14158c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 14168c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 14178c2ecf20Sopenharmony_ci int err = 0; 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) { 14208c2ecf20Sopenharmony_ci err = igb_request_msix(adapter); 14218c2ecf20Sopenharmony_ci if (!err) 14228c2ecf20Sopenharmony_ci goto request_done; 14238c2ecf20Sopenharmony_ci /* fall back to MSI */ 14248c2ecf20Sopenharmony_ci igb_free_all_tx_resources(adapter); 14258c2ecf20Sopenharmony_ci igb_free_all_rx_resources(adapter); 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci igb_clear_interrupt_scheme(adapter); 14288c2ecf20Sopenharmony_ci err = igb_init_interrupt_scheme(adapter, false); 14298c2ecf20Sopenharmony_ci if (err) 14308c2ecf20Sopenharmony_ci goto request_done; 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci igb_setup_all_tx_resources(adapter); 14338c2ecf20Sopenharmony_ci igb_setup_all_rx_resources(adapter); 14348c2ecf20Sopenharmony_ci igb_configure(adapter); 14358c2ecf20Sopenharmony_ci } 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci igb_assign_vector(adapter->q_vector[0], 0); 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSI) { 14408c2ecf20Sopenharmony_ci err = request_irq(pdev->irq, igb_intr_msi, 0, 14418c2ecf20Sopenharmony_ci netdev->name, adapter); 14428c2ecf20Sopenharmony_ci if (!err) 14438c2ecf20Sopenharmony_ci goto request_done; 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci /* fall back to legacy interrupts */ 14468c2ecf20Sopenharmony_ci igb_reset_interrupt_capability(adapter); 14478c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_HAS_MSI; 14488c2ecf20Sopenharmony_ci } 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci err = request_irq(pdev->irq, igb_intr, IRQF_SHARED, 14518c2ecf20Sopenharmony_ci netdev->name, adapter); 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci if (err) 14548c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Error %d getting interrupt\n", 14558c2ecf20Sopenharmony_ci err); 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_cirequest_done: 14588c2ecf20Sopenharmony_ci return err; 14598c2ecf20Sopenharmony_ci} 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_cistatic void igb_free_irq(struct igb_adapter *adapter) 14628c2ecf20Sopenharmony_ci{ 14638c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) { 14648c2ecf20Sopenharmony_ci int vector = 0, i; 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci free_irq(adapter->msix_entries[vector++].vector, adapter); 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) 14698c2ecf20Sopenharmony_ci free_irq(adapter->msix_entries[vector++].vector, 14708c2ecf20Sopenharmony_ci adapter->q_vector[i]); 14718c2ecf20Sopenharmony_ci } else { 14728c2ecf20Sopenharmony_ci free_irq(adapter->pdev->irq, adapter); 14738c2ecf20Sopenharmony_ci } 14748c2ecf20Sopenharmony_ci} 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci/** 14778c2ecf20Sopenharmony_ci * igb_irq_disable - Mask off interrupt generation on the NIC 14788c2ecf20Sopenharmony_ci * @adapter: board private structure 14798c2ecf20Sopenharmony_ci **/ 14808c2ecf20Sopenharmony_cistatic void igb_irq_disable(struct igb_adapter *adapter) 14818c2ecf20Sopenharmony_ci{ 14828c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci /* we need to be careful when disabling interrupts. The VFs are also 14858c2ecf20Sopenharmony_ci * mapped into these registers and so clearing the bits can cause 14868c2ecf20Sopenharmony_ci * issues on the VF drivers so we only need to clear what we set 14878c2ecf20Sopenharmony_ci */ 14888c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) { 14898c2ecf20Sopenharmony_ci u32 regval = rd32(E1000_EIAM); 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci wr32(E1000_EIAM, regval & ~adapter->eims_enable_mask); 14928c2ecf20Sopenharmony_ci wr32(E1000_EIMC, adapter->eims_enable_mask); 14938c2ecf20Sopenharmony_ci regval = rd32(E1000_EIAC); 14948c2ecf20Sopenharmony_ci wr32(E1000_EIAC, regval & ~adapter->eims_enable_mask); 14958c2ecf20Sopenharmony_ci } 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci wr32(E1000_IAM, 0); 14988c2ecf20Sopenharmony_ci wr32(E1000_IMC, ~0); 14998c2ecf20Sopenharmony_ci wrfl(); 15008c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) { 15018c2ecf20Sopenharmony_ci int i; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) 15048c2ecf20Sopenharmony_ci synchronize_irq(adapter->msix_entries[i].vector); 15058c2ecf20Sopenharmony_ci } else { 15068c2ecf20Sopenharmony_ci synchronize_irq(adapter->pdev->irq); 15078c2ecf20Sopenharmony_ci } 15088c2ecf20Sopenharmony_ci} 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci/** 15118c2ecf20Sopenharmony_ci * igb_irq_enable - Enable default interrupt generation settings 15128c2ecf20Sopenharmony_ci * @adapter: board private structure 15138c2ecf20Sopenharmony_ci **/ 15148c2ecf20Sopenharmony_cistatic void igb_irq_enable(struct igb_adapter *adapter) 15158c2ecf20Sopenharmony_ci{ 15168c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) { 15198c2ecf20Sopenharmony_ci u32 ims = E1000_IMS_LSC | E1000_IMS_DOUTSYNC | E1000_IMS_DRSTA; 15208c2ecf20Sopenharmony_ci u32 regval = rd32(E1000_EIAC); 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci wr32(E1000_EIAC, regval | adapter->eims_enable_mask); 15238c2ecf20Sopenharmony_ci regval = rd32(E1000_EIAM); 15248c2ecf20Sopenharmony_ci wr32(E1000_EIAM, regval | adapter->eims_enable_mask); 15258c2ecf20Sopenharmony_ci wr32(E1000_EIMS, adapter->eims_enable_mask); 15268c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count) { 15278c2ecf20Sopenharmony_ci wr32(E1000_MBVFIMR, 0xFF); 15288c2ecf20Sopenharmony_ci ims |= E1000_IMS_VMMB; 15298c2ecf20Sopenharmony_ci } 15308c2ecf20Sopenharmony_ci wr32(E1000_IMS, ims); 15318c2ecf20Sopenharmony_ci } else { 15328c2ecf20Sopenharmony_ci wr32(E1000_IMS, IMS_ENABLE_MASK | 15338c2ecf20Sopenharmony_ci E1000_IMS_DRSTA); 15348c2ecf20Sopenharmony_ci wr32(E1000_IAM, IMS_ENABLE_MASK | 15358c2ecf20Sopenharmony_ci E1000_IMS_DRSTA); 15368c2ecf20Sopenharmony_ci } 15378c2ecf20Sopenharmony_ci} 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_cistatic void igb_update_mng_vlan(struct igb_adapter *adapter) 15408c2ecf20Sopenharmony_ci{ 15418c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 15428c2ecf20Sopenharmony_ci u16 pf_id = adapter->vfs_allocated_count; 15438c2ecf20Sopenharmony_ci u16 vid = adapter->hw.mng_cookie.vlan_id; 15448c2ecf20Sopenharmony_ci u16 old_vid = adapter->mng_vlan_id; 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci if (hw->mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) { 15478c2ecf20Sopenharmony_ci /* add VID to filter table */ 15488c2ecf20Sopenharmony_ci igb_vfta_set(hw, vid, pf_id, true, true); 15498c2ecf20Sopenharmony_ci adapter->mng_vlan_id = vid; 15508c2ecf20Sopenharmony_ci } else { 15518c2ecf20Sopenharmony_ci adapter->mng_vlan_id = IGB_MNG_VLAN_NONE; 15528c2ecf20Sopenharmony_ci } 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci if ((old_vid != (u16)IGB_MNG_VLAN_NONE) && 15558c2ecf20Sopenharmony_ci (vid != old_vid) && 15568c2ecf20Sopenharmony_ci !test_bit(old_vid, adapter->active_vlans)) { 15578c2ecf20Sopenharmony_ci /* remove VID from filter table */ 15588c2ecf20Sopenharmony_ci igb_vfta_set(hw, vid, pf_id, false, true); 15598c2ecf20Sopenharmony_ci } 15608c2ecf20Sopenharmony_ci} 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci/** 15638c2ecf20Sopenharmony_ci * igb_release_hw_control - release control of the h/w to f/w 15648c2ecf20Sopenharmony_ci * @adapter: address of board private structure 15658c2ecf20Sopenharmony_ci * 15668c2ecf20Sopenharmony_ci * igb_release_hw_control resets CTRL_EXT:DRV_LOAD bit. 15678c2ecf20Sopenharmony_ci * For ASF and Pass Through versions of f/w this means that the 15688c2ecf20Sopenharmony_ci * driver is no longer loaded. 15698c2ecf20Sopenharmony_ci **/ 15708c2ecf20Sopenharmony_cistatic void igb_release_hw_control(struct igb_adapter *adapter) 15718c2ecf20Sopenharmony_ci{ 15728c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 15738c2ecf20Sopenharmony_ci u32 ctrl_ext; 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci /* Let firmware take over control of h/w */ 15768c2ecf20Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 15778c2ecf20Sopenharmony_ci wr32(E1000_CTRL_EXT, 15788c2ecf20Sopenharmony_ci ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); 15798c2ecf20Sopenharmony_ci} 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci/** 15828c2ecf20Sopenharmony_ci * igb_get_hw_control - get control of the h/w from f/w 15838c2ecf20Sopenharmony_ci * @adapter: address of board private structure 15848c2ecf20Sopenharmony_ci * 15858c2ecf20Sopenharmony_ci * igb_get_hw_control sets CTRL_EXT:DRV_LOAD bit. 15868c2ecf20Sopenharmony_ci * For ASF and Pass Through versions of f/w this means that 15878c2ecf20Sopenharmony_ci * the driver is loaded. 15888c2ecf20Sopenharmony_ci **/ 15898c2ecf20Sopenharmony_cistatic void igb_get_hw_control(struct igb_adapter *adapter) 15908c2ecf20Sopenharmony_ci{ 15918c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 15928c2ecf20Sopenharmony_ci u32 ctrl_ext; 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci /* Let firmware know the driver has taken over */ 15958c2ecf20Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 15968c2ecf20Sopenharmony_ci wr32(E1000_CTRL_EXT, 15978c2ecf20Sopenharmony_ci ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); 15988c2ecf20Sopenharmony_ci} 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_cistatic void enable_fqtss(struct igb_adapter *adapter, bool enable) 16018c2ecf20Sopenharmony_ci{ 16028c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 16038c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci WARN_ON(hw->mac.type != e1000_i210); 16068c2ecf20Sopenharmony_ci 16078c2ecf20Sopenharmony_ci if (enable) 16088c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_FQTSS; 16098c2ecf20Sopenharmony_ci else 16108c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_FQTSS; 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci if (netif_running(netdev)) 16138c2ecf20Sopenharmony_ci schedule_work(&adapter->reset_task); 16148c2ecf20Sopenharmony_ci} 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_cistatic bool is_fqtss_enabled(struct igb_adapter *adapter) 16178c2ecf20Sopenharmony_ci{ 16188c2ecf20Sopenharmony_ci return (adapter->flags & IGB_FLAG_FQTSS) ? true : false; 16198c2ecf20Sopenharmony_ci} 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_cistatic void set_tx_desc_fetch_prio(struct e1000_hw *hw, int queue, 16228c2ecf20Sopenharmony_ci enum tx_queue_prio prio) 16238c2ecf20Sopenharmony_ci{ 16248c2ecf20Sopenharmony_ci u32 val; 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci WARN_ON(hw->mac.type != e1000_i210); 16278c2ecf20Sopenharmony_ci WARN_ON(queue < 0 || queue > 4); 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci val = rd32(E1000_I210_TXDCTL(queue)); 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci if (prio == TX_QUEUE_PRIO_HIGH) 16328c2ecf20Sopenharmony_ci val |= E1000_TXDCTL_PRIORITY; 16338c2ecf20Sopenharmony_ci else 16348c2ecf20Sopenharmony_ci val &= ~E1000_TXDCTL_PRIORITY; 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci wr32(E1000_I210_TXDCTL(queue), val); 16378c2ecf20Sopenharmony_ci} 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_cistatic void set_queue_mode(struct e1000_hw *hw, int queue, enum queue_mode mode) 16408c2ecf20Sopenharmony_ci{ 16418c2ecf20Sopenharmony_ci u32 val; 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci WARN_ON(hw->mac.type != e1000_i210); 16448c2ecf20Sopenharmony_ci WARN_ON(queue < 0 || queue > 1); 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci val = rd32(E1000_I210_TQAVCC(queue)); 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci if (mode == QUEUE_MODE_STREAM_RESERVATION) 16498c2ecf20Sopenharmony_ci val |= E1000_TQAVCC_QUEUEMODE; 16508c2ecf20Sopenharmony_ci else 16518c2ecf20Sopenharmony_ci val &= ~E1000_TQAVCC_QUEUEMODE; 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci wr32(E1000_I210_TQAVCC(queue), val); 16548c2ecf20Sopenharmony_ci} 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_cistatic bool is_any_cbs_enabled(struct igb_adapter *adapter) 16578c2ecf20Sopenharmony_ci{ 16588c2ecf20Sopenharmony_ci int i; 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 16618c2ecf20Sopenharmony_ci if (adapter->tx_ring[i]->cbs_enable) 16628c2ecf20Sopenharmony_ci return true; 16638c2ecf20Sopenharmony_ci } 16648c2ecf20Sopenharmony_ci 16658c2ecf20Sopenharmony_ci return false; 16668c2ecf20Sopenharmony_ci} 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_cistatic bool is_any_txtime_enabled(struct igb_adapter *adapter) 16698c2ecf20Sopenharmony_ci{ 16708c2ecf20Sopenharmony_ci int i; 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 16738c2ecf20Sopenharmony_ci if (adapter->tx_ring[i]->launchtime_enable) 16748c2ecf20Sopenharmony_ci return true; 16758c2ecf20Sopenharmony_ci } 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci return false; 16788c2ecf20Sopenharmony_ci} 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci/** 16818c2ecf20Sopenharmony_ci * igb_config_tx_modes - Configure "Qav Tx mode" features on igb 16828c2ecf20Sopenharmony_ci * @adapter: pointer to adapter struct 16838c2ecf20Sopenharmony_ci * @queue: queue number 16848c2ecf20Sopenharmony_ci * 16858c2ecf20Sopenharmony_ci * Configure CBS and Launchtime for a given hardware queue. 16868c2ecf20Sopenharmony_ci * Parameters are retrieved from the correct Tx ring, so 16878c2ecf20Sopenharmony_ci * igb_save_cbs_params() and igb_save_txtime_params() should be used 16888c2ecf20Sopenharmony_ci * for setting those correctly prior to this function being called. 16898c2ecf20Sopenharmony_ci **/ 16908c2ecf20Sopenharmony_cistatic void igb_config_tx_modes(struct igb_adapter *adapter, int queue) 16918c2ecf20Sopenharmony_ci{ 16928c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 16938c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 16948c2ecf20Sopenharmony_ci struct igb_ring *ring; 16958c2ecf20Sopenharmony_ci u32 tqavcc, tqavctrl; 16968c2ecf20Sopenharmony_ci u16 value; 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci WARN_ON(hw->mac.type != e1000_i210); 16998c2ecf20Sopenharmony_ci WARN_ON(queue < 0 || queue > 1); 17008c2ecf20Sopenharmony_ci ring = adapter->tx_ring[queue]; 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci /* If any of the Qav features is enabled, configure queues as SR and 17038c2ecf20Sopenharmony_ci * with HIGH PRIO. If none is, then configure them with LOW PRIO and 17048c2ecf20Sopenharmony_ci * as SP. 17058c2ecf20Sopenharmony_ci */ 17068c2ecf20Sopenharmony_ci if (ring->cbs_enable || ring->launchtime_enable) { 17078c2ecf20Sopenharmony_ci set_tx_desc_fetch_prio(hw, queue, TX_QUEUE_PRIO_HIGH); 17088c2ecf20Sopenharmony_ci set_queue_mode(hw, queue, QUEUE_MODE_STREAM_RESERVATION); 17098c2ecf20Sopenharmony_ci } else { 17108c2ecf20Sopenharmony_ci set_tx_desc_fetch_prio(hw, queue, TX_QUEUE_PRIO_LOW); 17118c2ecf20Sopenharmony_ci set_queue_mode(hw, queue, QUEUE_MODE_STRICT_PRIORITY); 17128c2ecf20Sopenharmony_ci } 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci /* If CBS is enabled, set DataTranARB and config its parameters. */ 17158c2ecf20Sopenharmony_ci if (ring->cbs_enable || queue == 0) { 17168c2ecf20Sopenharmony_ci /* i210 does not allow the queue 0 to be in the Strict 17178c2ecf20Sopenharmony_ci * Priority mode while the Qav mode is enabled, so, 17188c2ecf20Sopenharmony_ci * instead of disabling strict priority mode, we give 17198c2ecf20Sopenharmony_ci * queue 0 the maximum of credits possible. 17208c2ecf20Sopenharmony_ci * 17218c2ecf20Sopenharmony_ci * See section 8.12.19 of the i210 datasheet, "Note: 17228c2ecf20Sopenharmony_ci * Queue0 QueueMode must be set to 1b when 17238c2ecf20Sopenharmony_ci * TransmitMode is set to Qav." 17248c2ecf20Sopenharmony_ci */ 17258c2ecf20Sopenharmony_ci if (queue == 0 && !ring->cbs_enable) { 17268c2ecf20Sopenharmony_ci /* max "linkspeed" idleslope in kbps */ 17278c2ecf20Sopenharmony_ci ring->idleslope = 1000000; 17288c2ecf20Sopenharmony_ci ring->hicredit = ETH_FRAME_LEN; 17298c2ecf20Sopenharmony_ci } 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci /* Always set data transfer arbitration to credit-based 17328c2ecf20Sopenharmony_ci * shaper algorithm on TQAVCTRL if CBS is enabled for any of 17338c2ecf20Sopenharmony_ci * the queues. 17348c2ecf20Sopenharmony_ci */ 17358c2ecf20Sopenharmony_ci tqavctrl = rd32(E1000_I210_TQAVCTRL); 17368c2ecf20Sopenharmony_ci tqavctrl |= E1000_TQAVCTRL_DATATRANARB; 17378c2ecf20Sopenharmony_ci wr32(E1000_I210_TQAVCTRL, tqavctrl); 17388c2ecf20Sopenharmony_ci 17398c2ecf20Sopenharmony_ci /* According to i210 datasheet section 7.2.7.7, we should set 17408c2ecf20Sopenharmony_ci * the 'idleSlope' field from TQAVCC register following the 17418c2ecf20Sopenharmony_ci * equation: 17428c2ecf20Sopenharmony_ci * 17438c2ecf20Sopenharmony_ci * For 100 Mbps link speed: 17448c2ecf20Sopenharmony_ci * 17458c2ecf20Sopenharmony_ci * value = BW * 0x7735 * 0.2 (E1) 17468c2ecf20Sopenharmony_ci * 17478c2ecf20Sopenharmony_ci * For 1000Mbps link speed: 17488c2ecf20Sopenharmony_ci * 17498c2ecf20Sopenharmony_ci * value = BW * 0x7735 * 2 (E2) 17508c2ecf20Sopenharmony_ci * 17518c2ecf20Sopenharmony_ci * E1 and E2 can be merged into one equation as shown below. 17528c2ecf20Sopenharmony_ci * Note that 'link-speed' is in Mbps. 17538c2ecf20Sopenharmony_ci * 17548c2ecf20Sopenharmony_ci * value = BW * 0x7735 * 2 * link-speed 17558c2ecf20Sopenharmony_ci * -------------- (E3) 17568c2ecf20Sopenharmony_ci * 1000 17578c2ecf20Sopenharmony_ci * 17588c2ecf20Sopenharmony_ci * 'BW' is the percentage bandwidth out of full link speed 17598c2ecf20Sopenharmony_ci * which can be found with the following equation. Note that 17608c2ecf20Sopenharmony_ci * idleSlope here is the parameter from this function which 17618c2ecf20Sopenharmony_ci * is in kbps. 17628c2ecf20Sopenharmony_ci * 17638c2ecf20Sopenharmony_ci * BW = idleSlope 17648c2ecf20Sopenharmony_ci * ----------------- (E4) 17658c2ecf20Sopenharmony_ci * link-speed * 1000 17668c2ecf20Sopenharmony_ci * 17678c2ecf20Sopenharmony_ci * That said, we can come up with a generic equation to 17688c2ecf20Sopenharmony_ci * calculate the value we should set it TQAVCC register by 17698c2ecf20Sopenharmony_ci * replacing 'BW' in E3 by E4. The resulting equation is: 17708c2ecf20Sopenharmony_ci * 17718c2ecf20Sopenharmony_ci * value = idleSlope * 0x7735 * 2 * link-speed 17728c2ecf20Sopenharmony_ci * ----------------- -------------- (E5) 17738c2ecf20Sopenharmony_ci * link-speed * 1000 1000 17748c2ecf20Sopenharmony_ci * 17758c2ecf20Sopenharmony_ci * 'link-speed' is present in both sides of the fraction so 17768c2ecf20Sopenharmony_ci * it is canceled out. The final equation is the following: 17778c2ecf20Sopenharmony_ci * 17788c2ecf20Sopenharmony_ci * value = idleSlope * 61034 17798c2ecf20Sopenharmony_ci * ----------------- (E6) 17808c2ecf20Sopenharmony_ci * 1000000 17818c2ecf20Sopenharmony_ci * 17828c2ecf20Sopenharmony_ci * NOTE: For i210, given the above, we can see that idleslope 17838c2ecf20Sopenharmony_ci * is represented in 16.38431 kbps units by the value at 17848c2ecf20Sopenharmony_ci * the TQAVCC register (1Gbps / 61034), which reduces 17858c2ecf20Sopenharmony_ci * the granularity for idleslope increments. 17868c2ecf20Sopenharmony_ci * For instance, if you want to configure a 2576kbps 17878c2ecf20Sopenharmony_ci * idleslope, the value to be written on the register 17888c2ecf20Sopenharmony_ci * would have to be 157.23. If rounded down, you end 17898c2ecf20Sopenharmony_ci * up with less bandwidth available than originally 17908c2ecf20Sopenharmony_ci * required (~2572 kbps). If rounded up, you end up 17918c2ecf20Sopenharmony_ci * with a higher bandwidth (~2589 kbps). Below the 17928c2ecf20Sopenharmony_ci * approach we take is to always round up the 17938c2ecf20Sopenharmony_ci * calculated value, so the resulting bandwidth might 17948c2ecf20Sopenharmony_ci * be slightly higher for some configurations. 17958c2ecf20Sopenharmony_ci */ 17968c2ecf20Sopenharmony_ci value = DIV_ROUND_UP_ULL(ring->idleslope * 61034ULL, 1000000); 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci tqavcc = rd32(E1000_I210_TQAVCC(queue)); 17998c2ecf20Sopenharmony_ci tqavcc &= ~E1000_TQAVCC_IDLESLOPE_MASK; 18008c2ecf20Sopenharmony_ci tqavcc |= value; 18018c2ecf20Sopenharmony_ci wr32(E1000_I210_TQAVCC(queue), tqavcc); 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci wr32(E1000_I210_TQAVHC(queue), 18048c2ecf20Sopenharmony_ci 0x80000000 + ring->hicredit * 0x7735); 18058c2ecf20Sopenharmony_ci } else { 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci /* Set idleSlope to zero. */ 18088c2ecf20Sopenharmony_ci tqavcc = rd32(E1000_I210_TQAVCC(queue)); 18098c2ecf20Sopenharmony_ci tqavcc &= ~E1000_TQAVCC_IDLESLOPE_MASK; 18108c2ecf20Sopenharmony_ci wr32(E1000_I210_TQAVCC(queue), tqavcc); 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci /* Set hiCredit to zero. */ 18138c2ecf20Sopenharmony_ci wr32(E1000_I210_TQAVHC(queue), 0); 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci /* If CBS is not enabled for any queues anymore, then return to 18168c2ecf20Sopenharmony_ci * the default state of Data Transmission Arbitration on 18178c2ecf20Sopenharmony_ci * TQAVCTRL. 18188c2ecf20Sopenharmony_ci */ 18198c2ecf20Sopenharmony_ci if (!is_any_cbs_enabled(adapter)) { 18208c2ecf20Sopenharmony_ci tqavctrl = rd32(E1000_I210_TQAVCTRL); 18218c2ecf20Sopenharmony_ci tqavctrl &= ~E1000_TQAVCTRL_DATATRANARB; 18228c2ecf20Sopenharmony_ci wr32(E1000_I210_TQAVCTRL, tqavctrl); 18238c2ecf20Sopenharmony_ci } 18248c2ecf20Sopenharmony_ci } 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_ci /* If LaunchTime is enabled, set DataTranTIM. */ 18278c2ecf20Sopenharmony_ci if (ring->launchtime_enable) { 18288c2ecf20Sopenharmony_ci /* Always set DataTranTIM on TQAVCTRL if LaunchTime is enabled 18298c2ecf20Sopenharmony_ci * for any of the SR queues, and configure fetchtime delta. 18308c2ecf20Sopenharmony_ci * XXX NOTE: 18318c2ecf20Sopenharmony_ci * - LaunchTime will be enabled for all SR queues. 18328c2ecf20Sopenharmony_ci * - A fixed offset can be added relative to the launch 18338c2ecf20Sopenharmony_ci * time of all packets if configured at reg LAUNCH_OS0. 18348c2ecf20Sopenharmony_ci * We are keeping it as 0 for now (default value). 18358c2ecf20Sopenharmony_ci */ 18368c2ecf20Sopenharmony_ci tqavctrl = rd32(E1000_I210_TQAVCTRL); 18378c2ecf20Sopenharmony_ci tqavctrl |= E1000_TQAVCTRL_DATATRANTIM | 18388c2ecf20Sopenharmony_ci E1000_TQAVCTRL_FETCHTIME_DELTA; 18398c2ecf20Sopenharmony_ci wr32(E1000_I210_TQAVCTRL, tqavctrl); 18408c2ecf20Sopenharmony_ci } else { 18418c2ecf20Sopenharmony_ci /* If Launchtime is not enabled for any SR queues anymore, 18428c2ecf20Sopenharmony_ci * then clear DataTranTIM on TQAVCTRL and clear fetchtime delta, 18438c2ecf20Sopenharmony_ci * effectively disabling Launchtime. 18448c2ecf20Sopenharmony_ci */ 18458c2ecf20Sopenharmony_ci if (!is_any_txtime_enabled(adapter)) { 18468c2ecf20Sopenharmony_ci tqavctrl = rd32(E1000_I210_TQAVCTRL); 18478c2ecf20Sopenharmony_ci tqavctrl &= ~E1000_TQAVCTRL_DATATRANTIM; 18488c2ecf20Sopenharmony_ci tqavctrl &= ~E1000_TQAVCTRL_FETCHTIME_DELTA; 18498c2ecf20Sopenharmony_ci wr32(E1000_I210_TQAVCTRL, tqavctrl); 18508c2ecf20Sopenharmony_ci } 18518c2ecf20Sopenharmony_ci } 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci /* XXX: In i210 controller the sendSlope and loCredit parameters from 18548c2ecf20Sopenharmony_ci * CBS are not configurable by software so we don't do any 'controller 18558c2ecf20Sopenharmony_ci * configuration' in respect to these parameters. 18568c2ecf20Sopenharmony_ci */ 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci netdev_dbg(netdev, "Qav Tx mode: cbs %s, launchtime %s, queue %d idleslope %d sendslope %d hiCredit %d locredit %d\n", 18598c2ecf20Sopenharmony_ci ring->cbs_enable ? "enabled" : "disabled", 18608c2ecf20Sopenharmony_ci ring->launchtime_enable ? "enabled" : "disabled", 18618c2ecf20Sopenharmony_ci queue, 18628c2ecf20Sopenharmony_ci ring->idleslope, ring->sendslope, 18638c2ecf20Sopenharmony_ci ring->hicredit, ring->locredit); 18648c2ecf20Sopenharmony_ci} 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_cistatic int igb_save_txtime_params(struct igb_adapter *adapter, int queue, 18678c2ecf20Sopenharmony_ci bool enable) 18688c2ecf20Sopenharmony_ci{ 18698c2ecf20Sopenharmony_ci struct igb_ring *ring; 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci if (queue < 0 || queue > adapter->num_tx_queues) 18728c2ecf20Sopenharmony_ci return -EINVAL; 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_ci ring = adapter->tx_ring[queue]; 18758c2ecf20Sopenharmony_ci ring->launchtime_enable = enable; 18768c2ecf20Sopenharmony_ci 18778c2ecf20Sopenharmony_ci return 0; 18788c2ecf20Sopenharmony_ci} 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_cistatic int igb_save_cbs_params(struct igb_adapter *adapter, int queue, 18818c2ecf20Sopenharmony_ci bool enable, int idleslope, int sendslope, 18828c2ecf20Sopenharmony_ci int hicredit, int locredit) 18838c2ecf20Sopenharmony_ci{ 18848c2ecf20Sopenharmony_ci struct igb_ring *ring; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci if (queue < 0 || queue > adapter->num_tx_queues) 18878c2ecf20Sopenharmony_ci return -EINVAL; 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_ci ring = adapter->tx_ring[queue]; 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci ring->cbs_enable = enable; 18928c2ecf20Sopenharmony_ci ring->idleslope = idleslope; 18938c2ecf20Sopenharmony_ci ring->sendslope = sendslope; 18948c2ecf20Sopenharmony_ci ring->hicredit = hicredit; 18958c2ecf20Sopenharmony_ci ring->locredit = locredit; 18968c2ecf20Sopenharmony_ci 18978c2ecf20Sopenharmony_ci return 0; 18988c2ecf20Sopenharmony_ci} 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci/** 19018c2ecf20Sopenharmony_ci * igb_setup_tx_mode - Switch to/from Qav Tx mode when applicable 19028c2ecf20Sopenharmony_ci * @adapter: pointer to adapter struct 19038c2ecf20Sopenharmony_ci * 19048c2ecf20Sopenharmony_ci * Configure TQAVCTRL register switching the controller's Tx mode 19058c2ecf20Sopenharmony_ci * if FQTSS mode is enabled or disabled. Additionally, will issue 19068c2ecf20Sopenharmony_ci * a call to igb_config_tx_modes() per queue so any previously saved 19078c2ecf20Sopenharmony_ci * Tx parameters are applied. 19088c2ecf20Sopenharmony_ci **/ 19098c2ecf20Sopenharmony_cistatic void igb_setup_tx_mode(struct igb_adapter *adapter) 19108c2ecf20Sopenharmony_ci{ 19118c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 19128c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 19138c2ecf20Sopenharmony_ci u32 val; 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_ci /* Only i210 controller supports changing the transmission mode. */ 19168c2ecf20Sopenharmony_ci if (hw->mac.type != e1000_i210) 19178c2ecf20Sopenharmony_ci return; 19188c2ecf20Sopenharmony_ci 19198c2ecf20Sopenharmony_ci if (is_fqtss_enabled(adapter)) { 19208c2ecf20Sopenharmony_ci int i, max_queue; 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci /* Configure TQAVCTRL register: set transmit mode to 'Qav', 19238c2ecf20Sopenharmony_ci * set data fetch arbitration to 'round robin', set SP_WAIT_SR 19248c2ecf20Sopenharmony_ci * so SP queues wait for SR ones. 19258c2ecf20Sopenharmony_ci */ 19268c2ecf20Sopenharmony_ci val = rd32(E1000_I210_TQAVCTRL); 19278c2ecf20Sopenharmony_ci val |= E1000_TQAVCTRL_XMIT_MODE | E1000_TQAVCTRL_SP_WAIT_SR; 19288c2ecf20Sopenharmony_ci val &= ~E1000_TQAVCTRL_DATAFETCHARB; 19298c2ecf20Sopenharmony_ci wr32(E1000_I210_TQAVCTRL, val); 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci /* Configure Tx and Rx packet buffers sizes as described in 19328c2ecf20Sopenharmony_ci * i210 datasheet section 7.2.7.7. 19338c2ecf20Sopenharmony_ci */ 19348c2ecf20Sopenharmony_ci val = rd32(E1000_TXPBS); 19358c2ecf20Sopenharmony_ci val &= ~I210_TXPBSIZE_MASK; 19368c2ecf20Sopenharmony_ci val |= I210_TXPBSIZE_PB0_8KB | I210_TXPBSIZE_PB1_8KB | 19378c2ecf20Sopenharmony_ci I210_TXPBSIZE_PB2_4KB | I210_TXPBSIZE_PB3_4KB; 19388c2ecf20Sopenharmony_ci wr32(E1000_TXPBS, val); 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_ci val = rd32(E1000_RXPBS); 19418c2ecf20Sopenharmony_ci val &= ~I210_RXPBSIZE_MASK; 19428c2ecf20Sopenharmony_ci val |= I210_RXPBSIZE_PB_30KB; 19438c2ecf20Sopenharmony_ci wr32(E1000_RXPBS, val); 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_ci /* Section 8.12.9 states that MAX_TPKT_SIZE from DTXMXPKTSZ 19468c2ecf20Sopenharmony_ci * register should not exceed the buffer size programmed in 19478c2ecf20Sopenharmony_ci * TXPBS. The smallest buffer size programmed in TXPBS is 4kB 19488c2ecf20Sopenharmony_ci * so according to the datasheet we should set MAX_TPKT_SIZE to 19498c2ecf20Sopenharmony_ci * 4kB / 64. 19508c2ecf20Sopenharmony_ci * 19518c2ecf20Sopenharmony_ci * However, when we do so, no frame from queue 2 and 3 are 19528c2ecf20Sopenharmony_ci * transmitted. It seems the MAX_TPKT_SIZE should not be great 19538c2ecf20Sopenharmony_ci * or _equal_ to the buffer size programmed in TXPBS. For this 19548c2ecf20Sopenharmony_ci * reason, we set set MAX_ TPKT_SIZE to (4kB - 1) / 64. 19558c2ecf20Sopenharmony_ci */ 19568c2ecf20Sopenharmony_ci val = (4096 - 1) / 64; 19578c2ecf20Sopenharmony_ci wr32(E1000_I210_DTXMXPKTSZ, val); 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_ci /* Since FQTSS mode is enabled, apply any CBS configuration 19608c2ecf20Sopenharmony_ci * previously set. If no previous CBS configuration has been 19618c2ecf20Sopenharmony_ci * done, then the initial configuration is applied, which means 19628c2ecf20Sopenharmony_ci * CBS is disabled. 19638c2ecf20Sopenharmony_ci */ 19648c2ecf20Sopenharmony_ci max_queue = (adapter->num_tx_queues < I210_SR_QUEUES_NUM) ? 19658c2ecf20Sopenharmony_ci adapter->num_tx_queues : I210_SR_QUEUES_NUM; 19668c2ecf20Sopenharmony_ci 19678c2ecf20Sopenharmony_ci for (i = 0; i < max_queue; i++) { 19688c2ecf20Sopenharmony_ci igb_config_tx_modes(adapter, i); 19698c2ecf20Sopenharmony_ci } 19708c2ecf20Sopenharmony_ci } else { 19718c2ecf20Sopenharmony_ci wr32(E1000_RXPBS, I210_RXPBSIZE_DEFAULT); 19728c2ecf20Sopenharmony_ci wr32(E1000_TXPBS, I210_TXPBSIZE_DEFAULT); 19738c2ecf20Sopenharmony_ci wr32(E1000_I210_DTXMXPKTSZ, I210_DTXMXPKTSZ_DEFAULT); 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_ci val = rd32(E1000_I210_TQAVCTRL); 19768c2ecf20Sopenharmony_ci /* According to Section 8.12.21, the other flags we've set when 19778c2ecf20Sopenharmony_ci * enabling FQTSS are not relevant when disabling FQTSS so we 19788c2ecf20Sopenharmony_ci * don't set they here. 19798c2ecf20Sopenharmony_ci */ 19808c2ecf20Sopenharmony_ci val &= ~E1000_TQAVCTRL_XMIT_MODE; 19818c2ecf20Sopenharmony_ci wr32(E1000_I210_TQAVCTRL, val); 19828c2ecf20Sopenharmony_ci } 19838c2ecf20Sopenharmony_ci 19848c2ecf20Sopenharmony_ci netdev_dbg(netdev, "FQTSS %s\n", (is_fqtss_enabled(adapter)) ? 19858c2ecf20Sopenharmony_ci "enabled" : "disabled"); 19868c2ecf20Sopenharmony_ci} 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_ci/** 19898c2ecf20Sopenharmony_ci * igb_configure - configure the hardware for RX and TX 19908c2ecf20Sopenharmony_ci * @adapter: private board structure 19918c2ecf20Sopenharmony_ci **/ 19928c2ecf20Sopenharmony_cistatic void igb_configure(struct igb_adapter *adapter) 19938c2ecf20Sopenharmony_ci{ 19948c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 19958c2ecf20Sopenharmony_ci int i; 19968c2ecf20Sopenharmony_ci 19978c2ecf20Sopenharmony_ci igb_get_hw_control(adapter); 19988c2ecf20Sopenharmony_ci igb_set_rx_mode(netdev); 19998c2ecf20Sopenharmony_ci igb_setup_tx_mode(adapter); 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_ci igb_restore_vlan(adapter); 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci igb_setup_tctl(adapter); 20048c2ecf20Sopenharmony_ci igb_setup_mrqc(adapter); 20058c2ecf20Sopenharmony_ci igb_setup_rctl(adapter); 20068c2ecf20Sopenharmony_ci 20078c2ecf20Sopenharmony_ci igb_nfc_filter_restore(adapter); 20088c2ecf20Sopenharmony_ci igb_configure_tx(adapter); 20098c2ecf20Sopenharmony_ci igb_configure_rx(adapter); 20108c2ecf20Sopenharmony_ci 20118c2ecf20Sopenharmony_ci igb_rx_fifo_flush_82575(&adapter->hw); 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci /* call igb_desc_unused which always leaves 20148c2ecf20Sopenharmony_ci * at least 1 descriptor unused to make sure 20158c2ecf20Sopenharmony_ci * next_to_use != next_to_clean 20168c2ecf20Sopenharmony_ci */ 20178c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 20188c2ecf20Sopenharmony_ci struct igb_ring *ring = adapter->rx_ring[i]; 20198c2ecf20Sopenharmony_ci igb_alloc_rx_buffers(ring, igb_desc_unused(ring)); 20208c2ecf20Sopenharmony_ci } 20218c2ecf20Sopenharmony_ci} 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci/** 20248c2ecf20Sopenharmony_ci * igb_power_up_link - Power up the phy/serdes link 20258c2ecf20Sopenharmony_ci * @adapter: address of board private structure 20268c2ecf20Sopenharmony_ci **/ 20278c2ecf20Sopenharmony_civoid igb_power_up_link(struct igb_adapter *adapter) 20288c2ecf20Sopenharmony_ci{ 20298c2ecf20Sopenharmony_ci igb_reset_phy(&adapter->hw); 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci if (adapter->hw.phy.media_type == e1000_media_type_copper) 20328c2ecf20Sopenharmony_ci igb_power_up_phy_copper(&adapter->hw); 20338c2ecf20Sopenharmony_ci else 20348c2ecf20Sopenharmony_ci igb_power_up_serdes_link_82575(&adapter->hw); 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci igb_setup_link(&adapter->hw); 20378c2ecf20Sopenharmony_ci} 20388c2ecf20Sopenharmony_ci 20398c2ecf20Sopenharmony_ci/** 20408c2ecf20Sopenharmony_ci * igb_power_down_link - Power down the phy/serdes link 20418c2ecf20Sopenharmony_ci * @adapter: address of board private structure 20428c2ecf20Sopenharmony_ci */ 20438c2ecf20Sopenharmony_cistatic void igb_power_down_link(struct igb_adapter *adapter) 20448c2ecf20Sopenharmony_ci{ 20458c2ecf20Sopenharmony_ci if (adapter->hw.phy.media_type == e1000_media_type_copper) 20468c2ecf20Sopenharmony_ci igb_power_down_phy_copper_82575(&adapter->hw); 20478c2ecf20Sopenharmony_ci else 20488c2ecf20Sopenharmony_ci igb_shutdown_serdes_link_82575(&adapter->hw); 20498c2ecf20Sopenharmony_ci} 20508c2ecf20Sopenharmony_ci 20518c2ecf20Sopenharmony_ci/** 20528c2ecf20Sopenharmony_ci * Detect and switch function for Media Auto Sense 20538c2ecf20Sopenharmony_ci * @adapter: address of the board private structure 20548c2ecf20Sopenharmony_ci **/ 20558c2ecf20Sopenharmony_cistatic void igb_check_swap_media(struct igb_adapter *adapter) 20568c2ecf20Sopenharmony_ci{ 20578c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 20588c2ecf20Sopenharmony_ci u32 ctrl_ext, connsw; 20598c2ecf20Sopenharmony_ci bool swap_now = false; 20608c2ecf20Sopenharmony_ci 20618c2ecf20Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 20628c2ecf20Sopenharmony_ci connsw = rd32(E1000_CONNSW); 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_ci /* need to live swap if current media is copper and we have fiber/serdes 20658c2ecf20Sopenharmony_ci * to go to. 20668c2ecf20Sopenharmony_ci */ 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci if ((hw->phy.media_type == e1000_media_type_copper) && 20698c2ecf20Sopenharmony_ci (!(connsw & E1000_CONNSW_AUTOSENSE_EN))) { 20708c2ecf20Sopenharmony_ci swap_now = true; 20718c2ecf20Sopenharmony_ci } else if ((hw->phy.media_type != e1000_media_type_copper) && 20728c2ecf20Sopenharmony_ci !(connsw & E1000_CONNSW_SERDESD)) { 20738c2ecf20Sopenharmony_ci /* copper signal takes time to appear */ 20748c2ecf20Sopenharmony_ci if (adapter->copper_tries < 4) { 20758c2ecf20Sopenharmony_ci adapter->copper_tries++; 20768c2ecf20Sopenharmony_ci connsw |= E1000_CONNSW_AUTOSENSE_CONF; 20778c2ecf20Sopenharmony_ci wr32(E1000_CONNSW, connsw); 20788c2ecf20Sopenharmony_ci return; 20798c2ecf20Sopenharmony_ci } else { 20808c2ecf20Sopenharmony_ci adapter->copper_tries = 0; 20818c2ecf20Sopenharmony_ci if ((connsw & E1000_CONNSW_PHYSD) && 20828c2ecf20Sopenharmony_ci (!(connsw & E1000_CONNSW_PHY_PDN))) { 20838c2ecf20Sopenharmony_ci swap_now = true; 20848c2ecf20Sopenharmony_ci connsw &= ~E1000_CONNSW_AUTOSENSE_CONF; 20858c2ecf20Sopenharmony_ci wr32(E1000_CONNSW, connsw); 20868c2ecf20Sopenharmony_ci } 20878c2ecf20Sopenharmony_ci } 20888c2ecf20Sopenharmony_ci } 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci if (!swap_now) 20918c2ecf20Sopenharmony_ci return; 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci switch (hw->phy.media_type) { 20948c2ecf20Sopenharmony_ci case e1000_media_type_copper: 20958c2ecf20Sopenharmony_ci netdev_info(adapter->netdev, 20968c2ecf20Sopenharmony_ci "MAS: changing media to fiber/serdes\n"); 20978c2ecf20Sopenharmony_ci ctrl_ext |= 20988c2ecf20Sopenharmony_ci E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; 20998c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_MEDIA_RESET; 21008c2ecf20Sopenharmony_ci adapter->copper_tries = 0; 21018c2ecf20Sopenharmony_ci break; 21028c2ecf20Sopenharmony_ci case e1000_media_type_internal_serdes: 21038c2ecf20Sopenharmony_ci case e1000_media_type_fiber: 21048c2ecf20Sopenharmony_ci netdev_info(adapter->netdev, 21058c2ecf20Sopenharmony_ci "MAS: changing media to copper\n"); 21068c2ecf20Sopenharmony_ci ctrl_ext &= 21078c2ecf20Sopenharmony_ci ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; 21088c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_MEDIA_RESET; 21098c2ecf20Sopenharmony_ci break; 21108c2ecf20Sopenharmony_ci default: 21118c2ecf20Sopenharmony_ci /* shouldn't get here during regular operation */ 21128c2ecf20Sopenharmony_ci netdev_err(adapter->netdev, 21138c2ecf20Sopenharmony_ci "AMS: Invalid media type found, returning\n"); 21148c2ecf20Sopenharmony_ci break; 21158c2ecf20Sopenharmony_ci } 21168c2ecf20Sopenharmony_ci wr32(E1000_CTRL_EXT, ctrl_ext); 21178c2ecf20Sopenharmony_ci} 21188c2ecf20Sopenharmony_ci 21198c2ecf20Sopenharmony_ci/** 21208c2ecf20Sopenharmony_ci * igb_up - Open the interface and prepare it to handle traffic 21218c2ecf20Sopenharmony_ci * @adapter: board private structure 21228c2ecf20Sopenharmony_ci **/ 21238c2ecf20Sopenharmony_ciint igb_up(struct igb_adapter *adapter) 21248c2ecf20Sopenharmony_ci{ 21258c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 21268c2ecf20Sopenharmony_ci int i; 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ci /* hardware has been reset, we need to reload some things */ 21298c2ecf20Sopenharmony_ci igb_configure(adapter); 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_ci clear_bit(__IGB_DOWN, &adapter->state); 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) 21348c2ecf20Sopenharmony_ci napi_enable(&(adapter->q_vector[i]->napi)); 21358c2ecf20Sopenharmony_ci 21368c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) 21378c2ecf20Sopenharmony_ci igb_configure_msix(adapter); 21388c2ecf20Sopenharmony_ci else 21398c2ecf20Sopenharmony_ci igb_assign_vector(adapter->q_vector[0], 0); 21408c2ecf20Sopenharmony_ci 21418c2ecf20Sopenharmony_ci /* Clear any pending interrupts. */ 21428c2ecf20Sopenharmony_ci rd32(E1000_TSICR); 21438c2ecf20Sopenharmony_ci rd32(E1000_ICR); 21448c2ecf20Sopenharmony_ci igb_irq_enable(adapter); 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci /* notify VFs that reset has been completed */ 21478c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count) { 21488c2ecf20Sopenharmony_ci u32 reg_data = rd32(E1000_CTRL_EXT); 21498c2ecf20Sopenharmony_ci 21508c2ecf20Sopenharmony_ci reg_data |= E1000_CTRL_EXT_PFRSTD; 21518c2ecf20Sopenharmony_ci wr32(E1000_CTRL_EXT, reg_data); 21528c2ecf20Sopenharmony_ci } 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_ci netif_tx_start_all_queues(adapter->netdev); 21558c2ecf20Sopenharmony_ci 21568c2ecf20Sopenharmony_ci /* start the watchdog. */ 21578c2ecf20Sopenharmony_ci hw->mac.get_link_status = 1; 21588c2ecf20Sopenharmony_ci schedule_work(&adapter->watchdog_task); 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci if ((adapter->flags & IGB_FLAG_EEE) && 21618c2ecf20Sopenharmony_ci (!hw->dev_spec._82575.eee_disable)) 21628c2ecf20Sopenharmony_ci adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T; 21638c2ecf20Sopenharmony_ci 21648c2ecf20Sopenharmony_ci return 0; 21658c2ecf20Sopenharmony_ci} 21668c2ecf20Sopenharmony_ci 21678c2ecf20Sopenharmony_civoid igb_down(struct igb_adapter *adapter) 21688c2ecf20Sopenharmony_ci{ 21698c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 21708c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 21718c2ecf20Sopenharmony_ci u32 tctl, rctl; 21728c2ecf20Sopenharmony_ci int i; 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_ci /* signal that we're down so the interrupt handler does not 21758c2ecf20Sopenharmony_ci * reschedule our watchdog timer 21768c2ecf20Sopenharmony_ci */ 21778c2ecf20Sopenharmony_ci set_bit(__IGB_DOWN, &adapter->state); 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_ci /* disable receives in the hardware */ 21808c2ecf20Sopenharmony_ci rctl = rd32(E1000_RCTL); 21818c2ecf20Sopenharmony_ci wr32(E1000_RCTL, rctl & ~E1000_RCTL_EN); 21828c2ecf20Sopenharmony_ci /* flush and sleep below */ 21838c2ecf20Sopenharmony_ci 21848c2ecf20Sopenharmony_ci igb_nfc_filter_exit(adapter); 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ci netif_carrier_off(netdev); 21878c2ecf20Sopenharmony_ci netif_tx_stop_all_queues(netdev); 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ci /* disable transmits in the hardware */ 21908c2ecf20Sopenharmony_ci tctl = rd32(E1000_TCTL); 21918c2ecf20Sopenharmony_ci tctl &= ~E1000_TCTL_EN; 21928c2ecf20Sopenharmony_ci wr32(E1000_TCTL, tctl); 21938c2ecf20Sopenharmony_ci /* flush both disables and wait for them to finish */ 21948c2ecf20Sopenharmony_ci wrfl(); 21958c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci igb_irq_disable(adapter); 21988c2ecf20Sopenharmony_ci 21998c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) { 22028c2ecf20Sopenharmony_ci if (adapter->q_vector[i]) { 22038c2ecf20Sopenharmony_ci napi_synchronize(&adapter->q_vector[i]->napi); 22048c2ecf20Sopenharmony_ci napi_disable(&adapter->q_vector[i]->napi); 22058c2ecf20Sopenharmony_ci } 22068c2ecf20Sopenharmony_ci } 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci del_timer_sync(&adapter->watchdog_timer); 22098c2ecf20Sopenharmony_ci del_timer_sync(&adapter->phy_info_timer); 22108c2ecf20Sopenharmony_ci 22118c2ecf20Sopenharmony_ci /* record the stats before reset*/ 22128c2ecf20Sopenharmony_ci spin_lock(&adapter->stats64_lock); 22138c2ecf20Sopenharmony_ci igb_update_stats(adapter); 22148c2ecf20Sopenharmony_ci spin_unlock(&adapter->stats64_lock); 22158c2ecf20Sopenharmony_ci 22168c2ecf20Sopenharmony_ci adapter->link_speed = 0; 22178c2ecf20Sopenharmony_ci adapter->link_duplex = 0; 22188c2ecf20Sopenharmony_ci 22198c2ecf20Sopenharmony_ci if (!pci_channel_offline(adapter->pdev)) 22208c2ecf20Sopenharmony_ci igb_reset(adapter); 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_ci /* clear VLAN promisc flag so VFTA will be updated if necessary */ 22238c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_VLAN_PROMISC; 22248c2ecf20Sopenharmony_ci 22258c2ecf20Sopenharmony_ci igb_clean_all_tx_rings(adapter); 22268c2ecf20Sopenharmony_ci igb_clean_all_rx_rings(adapter); 22278c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_DCA 22288c2ecf20Sopenharmony_ci 22298c2ecf20Sopenharmony_ci /* since we reset the hardware DCA settings were cleared */ 22308c2ecf20Sopenharmony_ci igb_setup_dca(adapter); 22318c2ecf20Sopenharmony_ci#endif 22328c2ecf20Sopenharmony_ci} 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_civoid igb_reinit_locked(struct igb_adapter *adapter) 22358c2ecf20Sopenharmony_ci{ 22368c2ecf20Sopenharmony_ci while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) 22378c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 22388c2ecf20Sopenharmony_ci igb_down(adapter); 22398c2ecf20Sopenharmony_ci igb_up(adapter); 22408c2ecf20Sopenharmony_ci clear_bit(__IGB_RESETTING, &adapter->state); 22418c2ecf20Sopenharmony_ci} 22428c2ecf20Sopenharmony_ci 22438c2ecf20Sopenharmony_ci/** igb_enable_mas - Media Autosense re-enable after swap 22448c2ecf20Sopenharmony_ci * 22458c2ecf20Sopenharmony_ci * @adapter: adapter struct 22468c2ecf20Sopenharmony_ci **/ 22478c2ecf20Sopenharmony_cistatic void igb_enable_mas(struct igb_adapter *adapter) 22488c2ecf20Sopenharmony_ci{ 22498c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 22508c2ecf20Sopenharmony_ci u32 connsw = rd32(E1000_CONNSW); 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_ci /* configure for SerDes media detect */ 22538c2ecf20Sopenharmony_ci if ((hw->phy.media_type == e1000_media_type_copper) && 22548c2ecf20Sopenharmony_ci (!(connsw & E1000_CONNSW_SERDESD))) { 22558c2ecf20Sopenharmony_ci connsw |= E1000_CONNSW_ENRGSRC; 22568c2ecf20Sopenharmony_ci connsw |= E1000_CONNSW_AUTOSENSE_EN; 22578c2ecf20Sopenharmony_ci wr32(E1000_CONNSW, connsw); 22588c2ecf20Sopenharmony_ci wrfl(); 22598c2ecf20Sopenharmony_ci } 22608c2ecf20Sopenharmony_ci} 22618c2ecf20Sopenharmony_ci 22628c2ecf20Sopenharmony_civoid igb_reset(struct igb_adapter *adapter) 22638c2ecf20Sopenharmony_ci{ 22648c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 22658c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 22668c2ecf20Sopenharmony_ci struct e1000_mac_info *mac = &hw->mac; 22678c2ecf20Sopenharmony_ci struct e1000_fc_info *fc = &hw->fc; 22688c2ecf20Sopenharmony_ci u32 pba, hwm; 22698c2ecf20Sopenharmony_ci 22708c2ecf20Sopenharmony_ci /* Repartition Pba for greater than 9k mtu 22718c2ecf20Sopenharmony_ci * To take effect CTRL.RST is required. 22728c2ecf20Sopenharmony_ci */ 22738c2ecf20Sopenharmony_ci switch (mac->type) { 22748c2ecf20Sopenharmony_ci case e1000_i350: 22758c2ecf20Sopenharmony_ci case e1000_i354: 22768c2ecf20Sopenharmony_ci case e1000_82580: 22778c2ecf20Sopenharmony_ci pba = rd32(E1000_RXPBS); 22788c2ecf20Sopenharmony_ci pba = igb_rxpbs_adjust_82580(pba); 22798c2ecf20Sopenharmony_ci break; 22808c2ecf20Sopenharmony_ci case e1000_82576: 22818c2ecf20Sopenharmony_ci pba = rd32(E1000_RXPBS); 22828c2ecf20Sopenharmony_ci pba &= E1000_RXPBS_SIZE_MASK_82576; 22838c2ecf20Sopenharmony_ci break; 22848c2ecf20Sopenharmony_ci case e1000_82575: 22858c2ecf20Sopenharmony_ci case e1000_i210: 22868c2ecf20Sopenharmony_ci case e1000_i211: 22878c2ecf20Sopenharmony_ci default: 22888c2ecf20Sopenharmony_ci pba = E1000_PBA_34K; 22898c2ecf20Sopenharmony_ci break; 22908c2ecf20Sopenharmony_ci } 22918c2ecf20Sopenharmony_ci 22928c2ecf20Sopenharmony_ci if (mac->type == e1000_82575) { 22938c2ecf20Sopenharmony_ci u32 min_rx_space, min_tx_space, needed_tx_space; 22948c2ecf20Sopenharmony_ci 22958c2ecf20Sopenharmony_ci /* write Rx PBA so that hardware can report correct Tx PBA */ 22968c2ecf20Sopenharmony_ci wr32(E1000_PBA, pba); 22978c2ecf20Sopenharmony_ci 22988c2ecf20Sopenharmony_ci /* To maintain wire speed transmits, the Tx FIFO should be 22998c2ecf20Sopenharmony_ci * large enough to accommodate two full transmit packets, 23008c2ecf20Sopenharmony_ci * rounded up to the next 1KB and expressed in KB. Likewise, 23018c2ecf20Sopenharmony_ci * the Rx FIFO should be large enough to accommodate at least 23028c2ecf20Sopenharmony_ci * one full receive packet and is similarly rounded up and 23038c2ecf20Sopenharmony_ci * expressed in KB. 23048c2ecf20Sopenharmony_ci */ 23058c2ecf20Sopenharmony_ci min_rx_space = DIV_ROUND_UP(MAX_JUMBO_FRAME_SIZE, 1024); 23068c2ecf20Sopenharmony_ci 23078c2ecf20Sopenharmony_ci /* The Tx FIFO also stores 16 bytes of information about the Tx 23088c2ecf20Sopenharmony_ci * but don't include Ethernet FCS because hardware appends it. 23098c2ecf20Sopenharmony_ci * We only need to round down to the nearest 512 byte block 23108c2ecf20Sopenharmony_ci * count since the value we care about is 2 frames, not 1. 23118c2ecf20Sopenharmony_ci */ 23128c2ecf20Sopenharmony_ci min_tx_space = adapter->max_frame_size; 23138c2ecf20Sopenharmony_ci min_tx_space += sizeof(union e1000_adv_tx_desc) - ETH_FCS_LEN; 23148c2ecf20Sopenharmony_ci min_tx_space = DIV_ROUND_UP(min_tx_space, 512); 23158c2ecf20Sopenharmony_ci 23168c2ecf20Sopenharmony_ci /* upper 16 bits has Tx packet buffer allocation size in KB */ 23178c2ecf20Sopenharmony_ci needed_tx_space = min_tx_space - (rd32(E1000_PBA) >> 16); 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_ci /* If current Tx allocation is less than the min Tx FIFO size, 23208c2ecf20Sopenharmony_ci * and the min Tx FIFO size is less than the current Rx FIFO 23218c2ecf20Sopenharmony_ci * allocation, take space away from current Rx allocation. 23228c2ecf20Sopenharmony_ci */ 23238c2ecf20Sopenharmony_ci if (needed_tx_space < pba) { 23248c2ecf20Sopenharmony_ci pba -= needed_tx_space; 23258c2ecf20Sopenharmony_ci 23268c2ecf20Sopenharmony_ci /* if short on Rx space, Rx wins and must trump Tx 23278c2ecf20Sopenharmony_ci * adjustment 23288c2ecf20Sopenharmony_ci */ 23298c2ecf20Sopenharmony_ci if (pba < min_rx_space) 23308c2ecf20Sopenharmony_ci pba = min_rx_space; 23318c2ecf20Sopenharmony_ci } 23328c2ecf20Sopenharmony_ci 23338c2ecf20Sopenharmony_ci /* adjust PBA for jumbo frames */ 23348c2ecf20Sopenharmony_ci wr32(E1000_PBA, pba); 23358c2ecf20Sopenharmony_ci } 23368c2ecf20Sopenharmony_ci 23378c2ecf20Sopenharmony_ci /* flow control settings 23388c2ecf20Sopenharmony_ci * The high water mark must be low enough to fit one full frame 23398c2ecf20Sopenharmony_ci * after transmitting the pause frame. As such we must have enough 23408c2ecf20Sopenharmony_ci * space to allow for us to complete our current transmit and then 23418c2ecf20Sopenharmony_ci * receive the frame that is in progress from the link partner. 23428c2ecf20Sopenharmony_ci * Set it to: 23438c2ecf20Sopenharmony_ci * - the full Rx FIFO size minus one full Tx plus one full Rx frame 23448c2ecf20Sopenharmony_ci */ 23458c2ecf20Sopenharmony_ci hwm = (pba << 10) - (adapter->max_frame_size + MAX_JUMBO_FRAME_SIZE); 23468c2ecf20Sopenharmony_ci 23478c2ecf20Sopenharmony_ci fc->high_water = hwm & 0xFFFFFFF0; /* 16-byte granularity */ 23488c2ecf20Sopenharmony_ci fc->low_water = fc->high_water - 16; 23498c2ecf20Sopenharmony_ci fc->pause_time = 0xFFFF; 23508c2ecf20Sopenharmony_ci fc->send_xon = 1; 23518c2ecf20Sopenharmony_ci fc->current_mode = fc->requested_mode; 23528c2ecf20Sopenharmony_ci 23538c2ecf20Sopenharmony_ci /* disable receive for all VFs and wait one second */ 23548c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count) { 23558c2ecf20Sopenharmony_ci int i; 23568c2ecf20Sopenharmony_ci 23578c2ecf20Sopenharmony_ci for (i = 0 ; i < adapter->vfs_allocated_count; i++) 23588c2ecf20Sopenharmony_ci adapter->vf_data[i].flags &= IGB_VF_FLAG_PF_SET_MAC; 23598c2ecf20Sopenharmony_ci 23608c2ecf20Sopenharmony_ci /* ping all the active vfs to let them know we are going down */ 23618c2ecf20Sopenharmony_ci igb_ping_all_vfs(adapter); 23628c2ecf20Sopenharmony_ci 23638c2ecf20Sopenharmony_ci /* disable transmits and receives */ 23648c2ecf20Sopenharmony_ci wr32(E1000_VFRE, 0); 23658c2ecf20Sopenharmony_ci wr32(E1000_VFTE, 0); 23668c2ecf20Sopenharmony_ci } 23678c2ecf20Sopenharmony_ci 23688c2ecf20Sopenharmony_ci /* Allow time for pending master requests to run */ 23698c2ecf20Sopenharmony_ci hw->mac.ops.reset_hw(hw); 23708c2ecf20Sopenharmony_ci wr32(E1000_WUC, 0); 23718c2ecf20Sopenharmony_ci 23728c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_MEDIA_RESET) { 23738c2ecf20Sopenharmony_ci /* need to resetup here after media swap */ 23748c2ecf20Sopenharmony_ci adapter->ei.get_invariants(hw); 23758c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_MEDIA_RESET; 23768c2ecf20Sopenharmony_ci } 23778c2ecf20Sopenharmony_ci if ((mac->type == e1000_82575 || mac->type == e1000_i350) && 23788c2ecf20Sopenharmony_ci (adapter->flags & IGB_FLAG_MAS_ENABLE)) { 23798c2ecf20Sopenharmony_ci igb_enable_mas(adapter); 23808c2ecf20Sopenharmony_ci } 23818c2ecf20Sopenharmony_ci if (hw->mac.ops.init_hw(hw)) 23828c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Hardware Error\n"); 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ci /* RAR registers were cleared during init_hw, clear mac table */ 23858c2ecf20Sopenharmony_ci igb_flush_mac_table(adapter); 23868c2ecf20Sopenharmony_ci __dev_uc_unsync(adapter->netdev, NULL); 23878c2ecf20Sopenharmony_ci 23888c2ecf20Sopenharmony_ci /* Recover default RAR entry */ 23898c2ecf20Sopenharmony_ci igb_set_default_mac_filter(adapter); 23908c2ecf20Sopenharmony_ci 23918c2ecf20Sopenharmony_ci /* Flow control settings reset on hardware reset, so guarantee flow 23928c2ecf20Sopenharmony_ci * control is off when forcing speed. 23938c2ecf20Sopenharmony_ci */ 23948c2ecf20Sopenharmony_ci if (!hw->mac.autoneg) 23958c2ecf20Sopenharmony_ci igb_force_mac_fc(hw); 23968c2ecf20Sopenharmony_ci 23978c2ecf20Sopenharmony_ci igb_init_dmac(adapter, pba); 23988c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_HWMON 23998c2ecf20Sopenharmony_ci /* Re-initialize the thermal sensor on i350 devices. */ 24008c2ecf20Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) { 24018c2ecf20Sopenharmony_ci if (mac->type == e1000_i350 && hw->bus.func == 0) { 24028c2ecf20Sopenharmony_ci /* If present, re-initialize the external thermal sensor 24038c2ecf20Sopenharmony_ci * interface. 24048c2ecf20Sopenharmony_ci */ 24058c2ecf20Sopenharmony_ci if (adapter->ets) 24068c2ecf20Sopenharmony_ci mac->ops.init_thermal_sensor_thresh(hw); 24078c2ecf20Sopenharmony_ci } 24088c2ecf20Sopenharmony_ci } 24098c2ecf20Sopenharmony_ci#endif 24108c2ecf20Sopenharmony_ci /* Re-establish EEE setting */ 24118c2ecf20Sopenharmony_ci if (hw->phy.media_type == e1000_media_type_copper) { 24128c2ecf20Sopenharmony_ci switch (mac->type) { 24138c2ecf20Sopenharmony_ci case e1000_i350: 24148c2ecf20Sopenharmony_ci case e1000_i210: 24158c2ecf20Sopenharmony_ci case e1000_i211: 24168c2ecf20Sopenharmony_ci igb_set_eee_i350(hw, true, true); 24178c2ecf20Sopenharmony_ci break; 24188c2ecf20Sopenharmony_ci case e1000_i354: 24198c2ecf20Sopenharmony_ci igb_set_eee_i354(hw, true, true); 24208c2ecf20Sopenharmony_ci break; 24218c2ecf20Sopenharmony_ci default: 24228c2ecf20Sopenharmony_ci break; 24238c2ecf20Sopenharmony_ci } 24248c2ecf20Sopenharmony_ci } 24258c2ecf20Sopenharmony_ci if (!netif_running(adapter->netdev)) 24268c2ecf20Sopenharmony_ci igb_power_down_link(adapter); 24278c2ecf20Sopenharmony_ci 24288c2ecf20Sopenharmony_ci igb_update_mng_vlan(adapter); 24298c2ecf20Sopenharmony_ci 24308c2ecf20Sopenharmony_ci /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ 24318c2ecf20Sopenharmony_ci wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE); 24328c2ecf20Sopenharmony_ci 24338c2ecf20Sopenharmony_ci /* Re-enable PTP, where applicable. */ 24348c2ecf20Sopenharmony_ci if (adapter->ptp_flags & IGB_PTP_ENABLED) 24358c2ecf20Sopenharmony_ci igb_ptp_reset(adapter); 24368c2ecf20Sopenharmony_ci 24378c2ecf20Sopenharmony_ci igb_get_phy_info(hw); 24388c2ecf20Sopenharmony_ci} 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_cistatic netdev_features_t igb_fix_features(struct net_device *netdev, 24418c2ecf20Sopenharmony_ci netdev_features_t features) 24428c2ecf20Sopenharmony_ci{ 24438c2ecf20Sopenharmony_ci /* Since there is no support for separate Rx/Tx vlan accel 24448c2ecf20Sopenharmony_ci * enable/disable make sure Tx flag is always in same state as Rx. 24458c2ecf20Sopenharmony_ci */ 24468c2ecf20Sopenharmony_ci if (features & NETIF_F_HW_VLAN_CTAG_RX) 24478c2ecf20Sopenharmony_ci features |= NETIF_F_HW_VLAN_CTAG_TX; 24488c2ecf20Sopenharmony_ci else 24498c2ecf20Sopenharmony_ci features &= ~NETIF_F_HW_VLAN_CTAG_TX; 24508c2ecf20Sopenharmony_ci 24518c2ecf20Sopenharmony_ci return features; 24528c2ecf20Sopenharmony_ci} 24538c2ecf20Sopenharmony_ci 24548c2ecf20Sopenharmony_cistatic int igb_set_features(struct net_device *netdev, 24558c2ecf20Sopenharmony_ci netdev_features_t features) 24568c2ecf20Sopenharmony_ci{ 24578c2ecf20Sopenharmony_ci netdev_features_t changed = netdev->features ^ features; 24588c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci if (changed & NETIF_F_HW_VLAN_CTAG_RX) 24618c2ecf20Sopenharmony_ci igb_vlan_mode(netdev, features); 24628c2ecf20Sopenharmony_ci 24638c2ecf20Sopenharmony_ci if (!(changed & (NETIF_F_RXALL | NETIF_F_NTUPLE))) 24648c2ecf20Sopenharmony_ci return 0; 24658c2ecf20Sopenharmony_ci 24668c2ecf20Sopenharmony_ci if (!(features & NETIF_F_NTUPLE)) { 24678c2ecf20Sopenharmony_ci struct hlist_node *node2; 24688c2ecf20Sopenharmony_ci struct igb_nfc_filter *rule; 24698c2ecf20Sopenharmony_ci 24708c2ecf20Sopenharmony_ci spin_lock(&adapter->nfc_lock); 24718c2ecf20Sopenharmony_ci hlist_for_each_entry_safe(rule, node2, 24728c2ecf20Sopenharmony_ci &adapter->nfc_filter_list, nfc_node) { 24738c2ecf20Sopenharmony_ci igb_erase_filter(adapter, rule); 24748c2ecf20Sopenharmony_ci hlist_del(&rule->nfc_node); 24758c2ecf20Sopenharmony_ci kfree(rule); 24768c2ecf20Sopenharmony_ci } 24778c2ecf20Sopenharmony_ci spin_unlock(&adapter->nfc_lock); 24788c2ecf20Sopenharmony_ci adapter->nfc_filter_count = 0; 24798c2ecf20Sopenharmony_ci } 24808c2ecf20Sopenharmony_ci 24818c2ecf20Sopenharmony_ci netdev->features = features; 24828c2ecf20Sopenharmony_ci 24838c2ecf20Sopenharmony_ci if (netif_running(netdev)) 24848c2ecf20Sopenharmony_ci igb_reinit_locked(adapter); 24858c2ecf20Sopenharmony_ci else 24868c2ecf20Sopenharmony_ci igb_reset(adapter); 24878c2ecf20Sopenharmony_ci 24888c2ecf20Sopenharmony_ci return 1; 24898c2ecf20Sopenharmony_ci} 24908c2ecf20Sopenharmony_ci 24918c2ecf20Sopenharmony_cistatic int igb_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 24928c2ecf20Sopenharmony_ci struct net_device *dev, 24938c2ecf20Sopenharmony_ci const unsigned char *addr, u16 vid, 24948c2ecf20Sopenharmony_ci u16 flags, 24958c2ecf20Sopenharmony_ci struct netlink_ext_ack *extack) 24968c2ecf20Sopenharmony_ci{ 24978c2ecf20Sopenharmony_ci /* guarantee we can provide a unique filter for the unicast address */ 24988c2ecf20Sopenharmony_ci if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) { 24998c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(dev); 25008c2ecf20Sopenharmony_ci int vfn = adapter->vfs_allocated_count; 25018c2ecf20Sopenharmony_ci 25028c2ecf20Sopenharmony_ci if (netdev_uc_count(dev) >= igb_available_rars(adapter, vfn)) 25038c2ecf20Sopenharmony_ci return -ENOMEM; 25048c2ecf20Sopenharmony_ci } 25058c2ecf20Sopenharmony_ci 25068c2ecf20Sopenharmony_ci return ndo_dflt_fdb_add(ndm, tb, dev, addr, vid, flags); 25078c2ecf20Sopenharmony_ci} 25088c2ecf20Sopenharmony_ci 25098c2ecf20Sopenharmony_ci#define IGB_MAX_MAC_HDR_LEN 127 25108c2ecf20Sopenharmony_ci#define IGB_MAX_NETWORK_HDR_LEN 511 25118c2ecf20Sopenharmony_ci 25128c2ecf20Sopenharmony_cistatic netdev_features_t 25138c2ecf20Sopenharmony_ciigb_features_check(struct sk_buff *skb, struct net_device *dev, 25148c2ecf20Sopenharmony_ci netdev_features_t features) 25158c2ecf20Sopenharmony_ci{ 25168c2ecf20Sopenharmony_ci unsigned int network_hdr_len, mac_hdr_len; 25178c2ecf20Sopenharmony_ci 25188c2ecf20Sopenharmony_ci /* Make certain the headers can be described by a context descriptor */ 25198c2ecf20Sopenharmony_ci mac_hdr_len = skb_network_header(skb) - skb->data; 25208c2ecf20Sopenharmony_ci if (unlikely(mac_hdr_len > IGB_MAX_MAC_HDR_LEN)) 25218c2ecf20Sopenharmony_ci return features & ~(NETIF_F_HW_CSUM | 25228c2ecf20Sopenharmony_ci NETIF_F_SCTP_CRC | 25238c2ecf20Sopenharmony_ci NETIF_F_GSO_UDP_L4 | 25248c2ecf20Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_TX | 25258c2ecf20Sopenharmony_ci NETIF_F_TSO | 25268c2ecf20Sopenharmony_ci NETIF_F_TSO6); 25278c2ecf20Sopenharmony_ci 25288c2ecf20Sopenharmony_ci network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb); 25298c2ecf20Sopenharmony_ci if (unlikely(network_hdr_len > IGB_MAX_NETWORK_HDR_LEN)) 25308c2ecf20Sopenharmony_ci return features & ~(NETIF_F_HW_CSUM | 25318c2ecf20Sopenharmony_ci NETIF_F_SCTP_CRC | 25328c2ecf20Sopenharmony_ci NETIF_F_GSO_UDP_L4 | 25338c2ecf20Sopenharmony_ci NETIF_F_TSO | 25348c2ecf20Sopenharmony_ci NETIF_F_TSO6); 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci /* We can only support IPV4 TSO in tunnels if we can mangle the 25378c2ecf20Sopenharmony_ci * inner IP ID field, so strip TSO if MANGLEID is not supported. 25388c2ecf20Sopenharmony_ci */ 25398c2ecf20Sopenharmony_ci if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID)) 25408c2ecf20Sopenharmony_ci features &= ~NETIF_F_TSO; 25418c2ecf20Sopenharmony_ci 25428c2ecf20Sopenharmony_ci return features; 25438c2ecf20Sopenharmony_ci} 25448c2ecf20Sopenharmony_ci 25458c2ecf20Sopenharmony_cistatic void igb_offload_apply(struct igb_adapter *adapter, s32 queue) 25468c2ecf20Sopenharmony_ci{ 25478c2ecf20Sopenharmony_ci if (!is_fqtss_enabled(adapter)) { 25488c2ecf20Sopenharmony_ci enable_fqtss(adapter, true); 25498c2ecf20Sopenharmony_ci return; 25508c2ecf20Sopenharmony_ci } 25518c2ecf20Sopenharmony_ci 25528c2ecf20Sopenharmony_ci igb_config_tx_modes(adapter, queue); 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ci if (!is_any_cbs_enabled(adapter) && !is_any_txtime_enabled(adapter)) 25558c2ecf20Sopenharmony_ci enable_fqtss(adapter, false); 25568c2ecf20Sopenharmony_ci} 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_cistatic int igb_offload_cbs(struct igb_adapter *adapter, 25598c2ecf20Sopenharmony_ci struct tc_cbs_qopt_offload *qopt) 25608c2ecf20Sopenharmony_ci{ 25618c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 25628c2ecf20Sopenharmony_ci int err; 25638c2ecf20Sopenharmony_ci 25648c2ecf20Sopenharmony_ci /* CBS offloading is only supported by i210 controller. */ 25658c2ecf20Sopenharmony_ci if (hw->mac.type != e1000_i210) 25668c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 25678c2ecf20Sopenharmony_ci 25688c2ecf20Sopenharmony_ci /* CBS offloading is only supported by queue 0 and queue 1. */ 25698c2ecf20Sopenharmony_ci if (qopt->queue < 0 || qopt->queue > 1) 25708c2ecf20Sopenharmony_ci return -EINVAL; 25718c2ecf20Sopenharmony_ci 25728c2ecf20Sopenharmony_ci err = igb_save_cbs_params(adapter, qopt->queue, qopt->enable, 25738c2ecf20Sopenharmony_ci qopt->idleslope, qopt->sendslope, 25748c2ecf20Sopenharmony_ci qopt->hicredit, qopt->locredit); 25758c2ecf20Sopenharmony_ci if (err) 25768c2ecf20Sopenharmony_ci return err; 25778c2ecf20Sopenharmony_ci 25788c2ecf20Sopenharmony_ci igb_offload_apply(adapter, qopt->queue); 25798c2ecf20Sopenharmony_ci 25808c2ecf20Sopenharmony_ci return 0; 25818c2ecf20Sopenharmony_ci} 25828c2ecf20Sopenharmony_ci 25838c2ecf20Sopenharmony_ci#define ETHER_TYPE_FULL_MASK ((__force __be16)~0) 25848c2ecf20Sopenharmony_ci#define VLAN_PRIO_FULL_MASK (0x07) 25858c2ecf20Sopenharmony_ci 25868c2ecf20Sopenharmony_cistatic int igb_parse_cls_flower(struct igb_adapter *adapter, 25878c2ecf20Sopenharmony_ci struct flow_cls_offload *f, 25888c2ecf20Sopenharmony_ci int traffic_class, 25898c2ecf20Sopenharmony_ci struct igb_nfc_filter *input) 25908c2ecf20Sopenharmony_ci{ 25918c2ecf20Sopenharmony_ci struct flow_rule *rule = flow_cls_offload_flow_rule(f); 25928c2ecf20Sopenharmony_ci struct flow_dissector *dissector = rule->match.dissector; 25938c2ecf20Sopenharmony_ci struct netlink_ext_ack *extack = f->common.extack; 25948c2ecf20Sopenharmony_ci 25958c2ecf20Sopenharmony_ci if (dissector->used_keys & 25968c2ecf20Sopenharmony_ci ~(BIT(FLOW_DISSECTOR_KEY_BASIC) | 25978c2ecf20Sopenharmony_ci BIT(FLOW_DISSECTOR_KEY_CONTROL) | 25988c2ecf20Sopenharmony_ci BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 25998c2ecf20Sopenharmony_ci BIT(FLOW_DISSECTOR_KEY_VLAN))) { 26008c2ecf20Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, 26018c2ecf20Sopenharmony_ci "Unsupported key used, only BASIC, CONTROL, ETH_ADDRS and VLAN are supported"); 26028c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 26038c2ecf20Sopenharmony_ci } 26048c2ecf20Sopenharmony_ci 26058c2ecf20Sopenharmony_ci if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { 26068c2ecf20Sopenharmony_ci struct flow_match_eth_addrs match; 26078c2ecf20Sopenharmony_ci 26088c2ecf20Sopenharmony_ci flow_rule_match_eth_addrs(rule, &match); 26098c2ecf20Sopenharmony_ci if (!is_zero_ether_addr(match.mask->dst)) { 26108c2ecf20Sopenharmony_ci if (!is_broadcast_ether_addr(match.mask->dst)) { 26118c2ecf20Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, "Only full masks are supported for destination MAC address"); 26128c2ecf20Sopenharmony_ci return -EINVAL; 26138c2ecf20Sopenharmony_ci } 26148c2ecf20Sopenharmony_ci 26158c2ecf20Sopenharmony_ci input->filter.match_flags |= 26168c2ecf20Sopenharmony_ci IGB_FILTER_FLAG_DST_MAC_ADDR; 26178c2ecf20Sopenharmony_ci ether_addr_copy(input->filter.dst_addr, match.key->dst); 26188c2ecf20Sopenharmony_ci } 26198c2ecf20Sopenharmony_ci 26208c2ecf20Sopenharmony_ci if (!is_zero_ether_addr(match.mask->src)) { 26218c2ecf20Sopenharmony_ci if (!is_broadcast_ether_addr(match.mask->src)) { 26228c2ecf20Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, "Only full masks are supported for source MAC address"); 26238c2ecf20Sopenharmony_ci return -EINVAL; 26248c2ecf20Sopenharmony_ci } 26258c2ecf20Sopenharmony_ci 26268c2ecf20Sopenharmony_ci input->filter.match_flags |= 26278c2ecf20Sopenharmony_ci IGB_FILTER_FLAG_SRC_MAC_ADDR; 26288c2ecf20Sopenharmony_ci ether_addr_copy(input->filter.src_addr, match.key->src); 26298c2ecf20Sopenharmony_ci } 26308c2ecf20Sopenharmony_ci } 26318c2ecf20Sopenharmony_ci 26328c2ecf20Sopenharmony_ci if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { 26338c2ecf20Sopenharmony_ci struct flow_match_basic match; 26348c2ecf20Sopenharmony_ci 26358c2ecf20Sopenharmony_ci flow_rule_match_basic(rule, &match); 26368c2ecf20Sopenharmony_ci if (match.mask->n_proto) { 26378c2ecf20Sopenharmony_ci if (match.mask->n_proto != ETHER_TYPE_FULL_MASK) { 26388c2ecf20Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, "Only full mask is supported for EtherType filter"); 26398c2ecf20Sopenharmony_ci return -EINVAL; 26408c2ecf20Sopenharmony_ci } 26418c2ecf20Sopenharmony_ci 26428c2ecf20Sopenharmony_ci input->filter.match_flags |= IGB_FILTER_FLAG_ETHER_TYPE; 26438c2ecf20Sopenharmony_ci input->filter.etype = match.key->n_proto; 26448c2ecf20Sopenharmony_ci } 26458c2ecf20Sopenharmony_ci } 26468c2ecf20Sopenharmony_ci 26478c2ecf20Sopenharmony_ci if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { 26488c2ecf20Sopenharmony_ci struct flow_match_vlan match; 26498c2ecf20Sopenharmony_ci 26508c2ecf20Sopenharmony_ci flow_rule_match_vlan(rule, &match); 26518c2ecf20Sopenharmony_ci if (match.mask->vlan_priority) { 26528c2ecf20Sopenharmony_ci if (match.mask->vlan_priority != VLAN_PRIO_FULL_MASK) { 26538c2ecf20Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, "Only full mask is supported for VLAN priority"); 26548c2ecf20Sopenharmony_ci return -EINVAL; 26558c2ecf20Sopenharmony_ci } 26568c2ecf20Sopenharmony_ci 26578c2ecf20Sopenharmony_ci input->filter.match_flags |= IGB_FILTER_FLAG_VLAN_TCI; 26588c2ecf20Sopenharmony_ci input->filter.vlan_tci = 26598c2ecf20Sopenharmony_ci (__force __be16)match.key->vlan_priority; 26608c2ecf20Sopenharmony_ci } 26618c2ecf20Sopenharmony_ci } 26628c2ecf20Sopenharmony_ci 26638c2ecf20Sopenharmony_ci input->action = traffic_class; 26648c2ecf20Sopenharmony_ci input->cookie = f->cookie; 26658c2ecf20Sopenharmony_ci 26668c2ecf20Sopenharmony_ci return 0; 26678c2ecf20Sopenharmony_ci} 26688c2ecf20Sopenharmony_ci 26698c2ecf20Sopenharmony_cistatic int igb_configure_clsflower(struct igb_adapter *adapter, 26708c2ecf20Sopenharmony_ci struct flow_cls_offload *cls_flower) 26718c2ecf20Sopenharmony_ci{ 26728c2ecf20Sopenharmony_ci struct netlink_ext_ack *extack = cls_flower->common.extack; 26738c2ecf20Sopenharmony_ci struct igb_nfc_filter *filter, *f; 26748c2ecf20Sopenharmony_ci int err, tc; 26758c2ecf20Sopenharmony_ci 26768c2ecf20Sopenharmony_ci tc = tc_classid_to_hwtc(adapter->netdev, cls_flower->classid); 26778c2ecf20Sopenharmony_ci if (tc < 0) { 26788c2ecf20Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, "Invalid traffic class"); 26798c2ecf20Sopenharmony_ci return -EINVAL; 26808c2ecf20Sopenharmony_ci } 26818c2ecf20Sopenharmony_ci 26828c2ecf20Sopenharmony_ci filter = kzalloc(sizeof(*filter), GFP_KERNEL); 26838c2ecf20Sopenharmony_ci if (!filter) 26848c2ecf20Sopenharmony_ci return -ENOMEM; 26858c2ecf20Sopenharmony_ci 26868c2ecf20Sopenharmony_ci err = igb_parse_cls_flower(adapter, cls_flower, tc, filter); 26878c2ecf20Sopenharmony_ci if (err < 0) 26888c2ecf20Sopenharmony_ci goto err_parse; 26898c2ecf20Sopenharmony_ci 26908c2ecf20Sopenharmony_ci spin_lock(&adapter->nfc_lock); 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_ci hlist_for_each_entry(f, &adapter->nfc_filter_list, nfc_node) { 26938c2ecf20Sopenharmony_ci if (!memcmp(&f->filter, &filter->filter, sizeof(f->filter))) { 26948c2ecf20Sopenharmony_ci err = -EEXIST; 26958c2ecf20Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, 26968c2ecf20Sopenharmony_ci "This filter is already set in ethtool"); 26978c2ecf20Sopenharmony_ci goto err_locked; 26988c2ecf20Sopenharmony_ci } 26998c2ecf20Sopenharmony_ci } 27008c2ecf20Sopenharmony_ci 27018c2ecf20Sopenharmony_ci hlist_for_each_entry(f, &adapter->cls_flower_list, nfc_node) { 27028c2ecf20Sopenharmony_ci if (!memcmp(&f->filter, &filter->filter, sizeof(f->filter))) { 27038c2ecf20Sopenharmony_ci err = -EEXIST; 27048c2ecf20Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, 27058c2ecf20Sopenharmony_ci "This filter is already set in cls_flower"); 27068c2ecf20Sopenharmony_ci goto err_locked; 27078c2ecf20Sopenharmony_ci } 27088c2ecf20Sopenharmony_ci } 27098c2ecf20Sopenharmony_ci 27108c2ecf20Sopenharmony_ci err = igb_add_filter(adapter, filter); 27118c2ecf20Sopenharmony_ci if (err < 0) { 27128c2ecf20Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, "Could not add filter to the adapter"); 27138c2ecf20Sopenharmony_ci goto err_locked; 27148c2ecf20Sopenharmony_ci } 27158c2ecf20Sopenharmony_ci 27168c2ecf20Sopenharmony_ci hlist_add_head(&filter->nfc_node, &adapter->cls_flower_list); 27178c2ecf20Sopenharmony_ci 27188c2ecf20Sopenharmony_ci spin_unlock(&adapter->nfc_lock); 27198c2ecf20Sopenharmony_ci 27208c2ecf20Sopenharmony_ci return 0; 27218c2ecf20Sopenharmony_ci 27228c2ecf20Sopenharmony_cierr_locked: 27238c2ecf20Sopenharmony_ci spin_unlock(&adapter->nfc_lock); 27248c2ecf20Sopenharmony_ci 27258c2ecf20Sopenharmony_cierr_parse: 27268c2ecf20Sopenharmony_ci kfree(filter); 27278c2ecf20Sopenharmony_ci 27288c2ecf20Sopenharmony_ci return err; 27298c2ecf20Sopenharmony_ci} 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_cistatic int igb_delete_clsflower(struct igb_adapter *adapter, 27328c2ecf20Sopenharmony_ci struct flow_cls_offload *cls_flower) 27338c2ecf20Sopenharmony_ci{ 27348c2ecf20Sopenharmony_ci struct igb_nfc_filter *filter; 27358c2ecf20Sopenharmony_ci int err; 27368c2ecf20Sopenharmony_ci 27378c2ecf20Sopenharmony_ci spin_lock(&adapter->nfc_lock); 27388c2ecf20Sopenharmony_ci 27398c2ecf20Sopenharmony_ci hlist_for_each_entry(filter, &adapter->cls_flower_list, nfc_node) 27408c2ecf20Sopenharmony_ci if (filter->cookie == cls_flower->cookie) 27418c2ecf20Sopenharmony_ci break; 27428c2ecf20Sopenharmony_ci 27438c2ecf20Sopenharmony_ci if (!filter) { 27448c2ecf20Sopenharmony_ci err = -ENOENT; 27458c2ecf20Sopenharmony_ci goto out; 27468c2ecf20Sopenharmony_ci } 27478c2ecf20Sopenharmony_ci 27488c2ecf20Sopenharmony_ci err = igb_erase_filter(adapter, filter); 27498c2ecf20Sopenharmony_ci if (err < 0) 27508c2ecf20Sopenharmony_ci goto out; 27518c2ecf20Sopenharmony_ci 27528c2ecf20Sopenharmony_ci hlist_del(&filter->nfc_node); 27538c2ecf20Sopenharmony_ci kfree(filter); 27548c2ecf20Sopenharmony_ci 27558c2ecf20Sopenharmony_ciout: 27568c2ecf20Sopenharmony_ci spin_unlock(&adapter->nfc_lock); 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci return err; 27598c2ecf20Sopenharmony_ci} 27608c2ecf20Sopenharmony_ci 27618c2ecf20Sopenharmony_cistatic int igb_setup_tc_cls_flower(struct igb_adapter *adapter, 27628c2ecf20Sopenharmony_ci struct flow_cls_offload *cls_flower) 27638c2ecf20Sopenharmony_ci{ 27648c2ecf20Sopenharmony_ci switch (cls_flower->command) { 27658c2ecf20Sopenharmony_ci case FLOW_CLS_REPLACE: 27668c2ecf20Sopenharmony_ci return igb_configure_clsflower(adapter, cls_flower); 27678c2ecf20Sopenharmony_ci case FLOW_CLS_DESTROY: 27688c2ecf20Sopenharmony_ci return igb_delete_clsflower(adapter, cls_flower); 27698c2ecf20Sopenharmony_ci case FLOW_CLS_STATS: 27708c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 27718c2ecf20Sopenharmony_ci default: 27728c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 27738c2ecf20Sopenharmony_ci } 27748c2ecf20Sopenharmony_ci} 27758c2ecf20Sopenharmony_ci 27768c2ecf20Sopenharmony_cistatic int igb_setup_tc_block_cb(enum tc_setup_type type, void *type_data, 27778c2ecf20Sopenharmony_ci void *cb_priv) 27788c2ecf20Sopenharmony_ci{ 27798c2ecf20Sopenharmony_ci struct igb_adapter *adapter = cb_priv; 27808c2ecf20Sopenharmony_ci 27818c2ecf20Sopenharmony_ci if (!tc_cls_can_offload_and_chain0(adapter->netdev, type_data)) 27828c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 27838c2ecf20Sopenharmony_ci 27848c2ecf20Sopenharmony_ci switch (type) { 27858c2ecf20Sopenharmony_ci case TC_SETUP_CLSFLOWER: 27868c2ecf20Sopenharmony_ci return igb_setup_tc_cls_flower(adapter, type_data); 27878c2ecf20Sopenharmony_ci 27888c2ecf20Sopenharmony_ci default: 27898c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 27908c2ecf20Sopenharmony_ci } 27918c2ecf20Sopenharmony_ci} 27928c2ecf20Sopenharmony_ci 27938c2ecf20Sopenharmony_cistatic int igb_offload_txtime(struct igb_adapter *adapter, 27948c2ecf20Sopenharmony_ci struct tc_etf_qopt_offload *qopt) 27958c2ecf20Sopenharmony_ci{ 27968c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 27978c2ecf20Sopenharmony_ci int err; 27988c2ecf20Sopenharmony_ci 27998c2ecf20Sopenharmony_ci /* Launchtime offloading is only supported by i210 controller. */ 28008c2ecf20Sopenharmony_ci if (hw->mac.type != e1000_i210) 28018c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 28028c2ecf20Sopenharmony_ci 28038c2ecf20Sopenharmony_ci /* Launchtime offloading is only supported by queues 0 and 1. */ 28048c2ecf20Sopenharmony_ci if (qopt->queue < 0 || qopt->queue > 1) 28058c2ecf20Sopenharmony_ci return -EINVAL; 28068c2ecf20Sopenharmony_ci 28078c2ecf20Sopenharmony_ci err = igb_save_txtime_params(adapter, qopt->queue, qopt->enable); 28088c2ecf20Sopenharmony_ci if (err) 28098c2ecf20Sopenharmony_ci return err; 28108c2ecf20Sopenharmony_ci 28118c2ecf20Sopenharmony_ci igb_offload_apply(adapter, qopt->queue); 28128c2ecf20Sopenharmony_ci 28138c2ecf20Sopenharmony_ci return 0; 28148c2ecf20Sopenharmony_ci} 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_cistatic LIST_HEAD(igb_block_cb_list); 28178c2ecf20Sopenharmony_ci 28188c2ecf20Sopenharmony_cistatic int igb_setup_tc(struct net_device *dev, enum tc_setup_type type, 28198c2ecf20Sopenharmony_ci void *type_data) 28208c2ecf20Sopenharmony_ci{ 28218c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(dev); 28228c2ecf20Sopenharmony_ci 28238c2ecf20Sopenharmony_ci switch (type) { 28248c2ecf20Sopenharmony_ci case TC_SETUP_QDISC_CBS: 28258c2ecf20Sopenharmony_ci return igb_offload_cbs(adapter, type_data); 28268c2ecf20Sopenharmony_ci case TC_SETUP_BLOCK: 28278c2ecf20Sopenharmony_ci return flow_block_cb_setup_simple(type_data, 28288c2ecf20Sopenharmony_ci &igb_block_cb_list, 28298c2ecf20Sopenharmony_ci igb_setup_tc_block_cb, 28308c2ecf20Sopenharmony_ci adapter, adapter, true); 28318c2ecf20Sopenharmony_ci 28328c2ecf20Sopenharmony_ci case TC_SETUP_QDISC_ETF: 28338c2ecf20Sopenharmony_ci return igb_offload_txtime(adapter, type_data); 28348c2ecf20Sopenharmony_ci 28358c2ecf20Sopenharmony_ci default: 28368c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 28378c2ecf20Sopenharmony_ci } 28388c2ecf20Sopenharmony_ci} 28398c2ecf20Sopenharmony_ci 28408c2ecf20Sopenharmony_cistatic int igb_xdp_setup(struct net_device *dev, struct netdev_bpf *bpf) 28418c2ecf20Sopenharmony_ci{ 28428c2ecf20Sopenharmony_ci int i, frame_size = dev->mtu + IGB_ETH_PKT_HDR_PAD; 28438c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(dev); 28448c2ecf20Sopenharmony_ci struct bpf_prog *prog = bpf->prog, *old_prog; 28458c2ecf20Sopenharmony_ci bool running = netif_running(dev); 28468c2ecf20Sopenharmony_ci bool need_reset; 28478c2ecf20Sopenharmony_ci 28488c2ecf20Sopenharmony_ci /* verify igb ring attributes are sufficient for XDP */ 28498c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 28508c2ecf20Sopenharmony_ci struct igb_ring *ring = adapter->rx_ring[i]; 28518c2ecf20Sopenharmony_ci 28528c2ecf20Sopenharmony_ci if (frame_size > igb_rx_bufsz(ring)) { 28538c2ecf20Sopenharmony_ci NL_SET_ERR_MSG_MOD(bpf->extack, 28548c2ecf20Sopenharmony_ci "The RX buffer size is too small for the frame size"); 28558c2ecf20Sopenharmony_ci netdev_warn(dev, "XDP RX buffer size %d is too small for the frame size %d\n", 28568c2ecf20Sopenharmony_ci igb_rx_bufsz(ring), frame_size); 28578c2ecf20Sopenharmony_ci return -EINVAL; 28588c2ecf20Sopenharmony_ci } 28598c2ecf20Sopenharmony_ci } 28608c2ecf20Sopenharmony_ci 28618c2ecf20Sopenharmony_ci old_prog = xchg(&adapter->xdp_prog, prog); 28628c2ecf20Sopenharmony_ci need_reset = (!!prog != !!old_prog); 28638c2ecf20Sopenharmony_ci 28648c2ecf20Sopenharmony_ci /* device is up and bpf is added/removed, must setup the RX queues */ 28658c2ecf20Sopenharmony_ci if (need_reset && running) { 28668c2ecf20Sopenharmony_ci igb_close(dev); 28678c2ecf20Sopenharmony_ci } else { 28688c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) 28698c2ecf20Sopenharmony_ci (void)xchg(&adapter->rx_ring[i]->xdp_prog, 28708c2ecf20Sopenharmony_ci adapter->xdp_prog); 28718c2ecf20Sopenharmony_ci } 28728c2ecf20Sopenharmony_ci 28738c2ecf20Sopenharmony_ci if (old_prog) 28748c2ecf20Sopenharmony_ci bpf_prog_put(old_prog); 28758c2ecf20Sopenharmony_ci 28768c2ecf20Sopenharmony_ci /* bpf is just replaced, RXQ and MTU are already setup */ 28778c2ecf20Sopenharmony_ci if (!need_reset) 28788c2ecf20Sopenharmony_ci return 0; 28798c2ecf20Sopenharmony_ci 28808c2ecf20Sopenharmony_ci if (running) 28818c2ecf20Sopenharmony_ci igb_open(dev); 28828c2ecf20Sopenharmony_ci 28838c2ecf20Sopenharmony_ci return 0; 28848c2ecf20Sopenharmony_ci} 28858c2ecf20Sopenharmony_ci 28868c2ecf20Sopenharmony_cistatic int igb_xdp(struct net_device *dev, struct netdev_bpf *xdp) 28878c2ecf20Sopenharmony_ci{ 28888c2ecf20Sopenharmony_ci switch (xdp->command) { 28898c2ecf20Sopenharmony_ci case XDP_SETUP_PROG: 28908c2ecf20Sopenharmony_ci return igb_xdp_setup(dev, xdp); 28918c2ecf20Sopenharmony_ci default: 28928c2ecf20Sopenharmony_ci return -EINVAL; 28938c2ecf20Sopenharmony_ci } 28948c2ecf20Sopenharmony_ci} 28958c2ecf20Sopenharmony_ci 28968c2ecf20Sopenharmony_cistatic void igb_xdp_ring_update_tail(struct igb_ring *ring) 28978c2ecf20Sopenharmony_ci{ 28988c2ecf20Sopenharmony_ci /* Force memory writes to complete before letting h/w know there 28998c2ecf20Sopenharmony_ci * are new descriptors to fetch. 29008c2ecf20Sopenharmony_ci */ 29018c2ecf20Sopenharmony_ci wmb(); 29028c2ecf20Sopenharmony_ci writel(ring->next_to_use, ring->tail); 29038c2ecf20Sopenharmony_ci} 29048c2ecf20Sopenharmony_ci 29058c2ecf20Sopenharmony_cistatic struct igb_ring *igb_xdp_tx_queue_mapping(struct igb_adapter *adapter) 29068c2ecf20Sopenharmony_ci{ 29078c2ecf20Sopenharmony_ci unsigned int r_idx = smp_processor_id(); 29088c2ecf20Sopenharmony_ci 29098c2ecf20Sopenharmony_ci if (r_idx >= adapter->num_tx_queues) 29108c2ecf20Sopenharmony_ci r_idx = r_idx % adapter->num_tx_queues; 29118c2ecf20Sopenharmony_ci 29128c2ecf20Sopenharmony_ci return adapter->tx_ring[r_idx]; 29138c2ecf20Sopenharmony_ci} 29148c2ecf20Sopenharmony_ci 29158c2ecf20Sopenharmony_cistatic int igb_xdp_xmit_back(struct igb_adapter *adapter, struct xdp_buff *xdp) 29168c2ecf20Sopenharmony_ci{ 29178c2ecf20Sopenharmony_ci struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); 29188c2ecf20Sopenharmony_ci int cpu = smp_processor_id(); 29198c2ecf20Sopenharmony_ci struct igb_ring *tx_ring; 29208c2ecf20Sopenharmony_ci struct netdev_queue *nq; 29218c2ecf20Sopenharmony_ci u32 ret; 29228c2ecf20Sopenharmony_ci 29238c2ecf20Sopenharmony_ci if (unlikely(!xdpf)) 29248c2ecf20Sopenharmony_ci return IGB_XDP_CONSUMED; 29258c2ecf20Sopenharmony_ci 29268c2ecf20Sopenharmony_ci /* During program transitions its possible adapter->xdp_prog is assigned 29278c2ecf20Sopenharmony_ci * but ring has not been configured yet. In this case simply abort xmit. 29288c2ecf20Sopenharmony_ci */ 29298c2ecf20Sopenharmony_ci tx_ring = adapter->xdp_prog ? igb_xdp_tx_queue_mapping(adapter) : NULL; 29308c2ecf20Sopenharmony_ci if (unlikely(!tx_ring)) 29318c2ecf20Sopenharmony_ci return IGB_XDP_CONSUMED; 29328c2ecf20Sopenharmony_ci 29338c2ecf20Sopenharmony_ci nq = txring_txq(tx_ring); 29348c2ecf20Sopenharmony_ci __netif_tx_lock(nq, cpu); 29358c2ecf20Sopenharmony_ci /* Avoid transmit queue timeout since we share it with the slow path */ 29368c2ecf20Sopenharmony_ci nq->trans_start = jiffies; 29378c2ecf20Sopenharmony_ci ret = igb_xmit_xdp_ring(adapter, tx_ring, xdpf); 29388c2ecf20Sopenharmony_ci __netif_tx_unlock(nq); 29398c2ecf20Sopenharmony_ci 29408c2ecf20Sopenharmony_ci return ret; 29418c2ecf20Sopenharmony_ci} 29428c2ecf20Sopenharmony_ci 29438c2ecf20Sopenharmony_cistatic int igb_xdp_xmit(struct net_device *dev, int n, 29448c2ecf20Sopenharmony_ci struct xdp_frame **frames, u32 flags) 29458c2ecf20Sopenharmony_ci{ 29468c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(dev); 29478c2ecf20Sopenharmony_ci int cpu = smp_processor_id(); 29488c2ecf20Sopenharmony_ci struct igb_ring *tx_ring; 29498c2ecf20Sopenharmony_ci struct netdev_queue *nq; 29508c2ecf20Sopenharmony_ci int drops = 0; 29518c2ecf20Sopenharmony_ci int i; 29528c2ecf20Sopenharmony_ci 29538c2ecf20Sopenharmony_ci if (unlikely(test_bit(__IGB_DOWN, &adapter->state))) 29548c2ecf20Sopenharmony_ci return -ENETDOWN; 29558c2ecf20Sopenharmony_ci 29568c2ecf20Sopenharmony_ci if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) 29578c2ecf20Sopenharmony_ci return -EINVAL; 29588c2ecf20Sopenharmony_ci 29598c2ecf20Sopenharmony_ci /* During program transitions its possible adapter->xdp_prog is assigned 29608c2ecf20Sopenharmony_ci * but ring has not been configured yet. In this case simply abort xmit. 29618c2ecf20Sopenharmony_ci */ 29628c2ecf20Sopenharmony_ci tx_ring = adapter->xdp_prog ? igb_xdp_tx_queue_mapping(adapter) : NULL; 29638c2ecf20Sopenharmony_ci if (unlikely(!tx_ring)) 29648c2ecf20Sopenharmony_ci return -ENXIO; 29658c2ecf20Sopenharmony_ci 29668c2ecf20Sopenharmony_ci nq = txring_txq(tx_ring); 29678c2ecf20Sopenharmony_ci __netif_tx_lock(nq, cpu); 29688c2ecf20Sopenharmony_ci 29698c2ecf20Sopenharmony_ci /* Avoid transmit queue timeout since we share it with the slow path */ 29708c2ecf20Sopenharmony_ci nq->trans_start = jiffies; 29718c2ecf20Sopenharmony_ci 29728c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) { 29738c2ecf20Sopenharmony_ci struct xdp_frame *xdpf = frames[i]; 29748c2ecf20Sopenharmony_ci int err; 29758c2ecf20Sopenharmony_ci 29768c2ecf20Sopenharmony_ci err = igb_xmit_xdp_ring(adapter, tx_ring, xdpf); 29778c2ecf20Sopenharmony_ci if (err != IGB_XDP_TX) { 29788c2ecf20Sopenharmony_ci xdp_return_frame_rx_napi(xdpf); 29798c2ecf20Sopenharmony_ci drops++; 29808c2ecf20Sopenharmony_ci } 29818c2ecf20Sopenharmony_ci } 29828c2ecf20Sopenharmony_ci 29838c2ecf20Sopenharmony_ci __netif_tx_unlock(nq); 29848c2ecf20Sopenharmony_ci 29858c2ecf20Sopenharmony_ci if (unlikely(flags & XDP_XMIT_FLUSH)) 29868c2ecf20Sopenharmony_ci igb_xdp_ring_update_tail(tx_ring); 29878c2ecf20Sopenharmony_ci 29888c2ecf20Sopenharmony_ci return n - drops; 29898c2ecf20Sopenharmony_ci} 29908c2ecf20Sopenharmony_ci 29918c2ecf20Sopenharmony_cistatic const struct net_device_ops igb_netdev_ops = { 29928c2ecf20Sopenharmony_ci .ndo_open = igb_open, 29938c2ecf20Sopenharmony_ci .ndo_stop = igb_close, 29948c2ecf20Sopenharmony_ci .ndo_start_xmit = igb_xmit_frame, 29958c2ecf20Sopenharmony_ci .ndo_get_stats64 = igb_get_stats64, 29968c2ecf20Sopenharmony_ci .ndo_set_rx_mode = igb_set_rx_mode, 29978c2ecf20Sopenharmony_ci .ndo_set_mac_address = igb_set_mac, 29988c2ecf20Sopenharmony_ci .ndo_change_mtu = igb_change_mtu, 29998c2ecf20Sopenharmony_ci .ndo_do_ioctl = igb_ioctl, 30008c2ecf20Sopenharmony_ci .ndo_tx_timeout = igb_tx_timeout, 30018c2ecf20Sopenharmony_ci .ndo_validate_addr = eth_validate_addr, 30028c2ecf20Sopenharmony_ci .ndo_vlan_rx_add_vid = igb_vlan_rx_add_vid, 30038c2ecf20Sopenharmony_ci .ndo_vlan_rx_kill_vid = igb_vlan_rx_kill_vid, 30048c2ecf20Sopenharmony_ci .ndo_set_vf_mac = igb_ndo_set_vf_mac, 30058c2ecf20Sopenharmony_ci .ndo_set_vf_vlan = igb_ndo_set_vf_vlan, 30068c2ecf20Sopenharmony_ci .ndo_set_vf_rate = igb_ndo_set_vf_bw, 30078c2ecf20Sopenharmony_ci .ndo_set_vf_spoofchk = igb_ndo_set_vf_spoofchk, 30088c2ecf20Sopenharmony_ci .ndo_set_vf_trust = igb_ndo_set_vf_trust, 30098c2ecf20Sopenharmony_ci .ndo_get_vf_config = igb_ndo_get_vf_config, 30108c2ecf20Sopenharmony_ci .ndo_fix_features = igb_fix_features, 30118c2ecf20Sopenharmony_ci .ndo_set_features = igb_set_features, 30128c2ecf20Sopenharmony_ci .ndo_fdb_add = igb_ndo_fdb_add, 30138c2ecf20Sopenharmony_ci .ndo_features_check = igb_features_check, 30148c2ecf20Sopenharmony_ci .ndo_setup_tc = igb_setup_tc, 30158c2ecf20Sopenharmony_ci .ndo_bpf = igb_xdp, 30168c2ecf20Sopenharmony_ci .ndo_xdp_xmit = igb_xdp_xmit, 30178c2ecf20Sopenharmony_ci}; 30188c2ecf20Sopenharmony_ci 30198c2ecf20Sopenharmony_ci/** 30208c2ecf20Sopenharmony_ci * igb_set_fw_version - Configure version string for ethtool 30218c2ecf20Sopenharmony_ci * @adapter: adapter struct 30228c2ecf20Sopenharmony_ci **/ 30238c2ecf20Sopenharmony_civoid igb_set_fw_version(struct igb_adapter *adapter) 30248c2ecf20Sopenharmony_ci{ 30258c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 30268c2ecf20Sopenharmony_ci struct e1000_fw_version fw; 30278c2ecf20Sopenharmony_ci 30288c2ecf20Sopenharmony_ci igb_get_fw_version(hw, &fw); 30298c2ecf20Sopenharmony_ci 30308c2ecf20Sopenharmony_ci switch (hw->mac.type) { 30318c2ecf20Sopenharmony_ci case e1000_i210: 30328c2ecf20Sopenharmony_ci case e1000_i211: 30338c2ecf20Sopenharmony_ci if (!(igb_get_flash_presence_i210(hw))) { 30348c2ecf20Sopenharmony_ci snprintf(adapter->fw_version, 30358c2ecf20Sopenharmony_ci sizeof(adapter->fw_version), 30368c2ecf20Sopenharmony_ci "%2d.%2d-%d", 30378c2ecf20Sopenharmony_ci fw.invm_major, fw.invm_minor, 30388c2ecf20Sopenharmony_ci fw.invm_img_type); 30398c2ecf20Sopenharmony_ci break; 30408c2ecf20Sopenharmony_ci } 30418c2ecf20Sopenharmony_ci fallthrough; 30428c2ecf20Sopenharmony_ci default: 30438c2ecf20Sopenharmony_ci /* if option is rom valid, display its version too */ 30448c2ecf20Sopenharmony_ci if (fw.or_valid) { 30458c2ecf20Sopenharmony_ci snprintf(adapter->fw_version, 30468c2ecf20Sopenharmony_ci sizeof(adapter->fw_version), 30478c2ecf20Sopenharmony_ci "%d.%d, 0x%08x, %d.%d.%d", 30488c2ecf20Sopenharmony_ci fw.eep_major, fw.eep_minor, fw.etrack_id, 30498c2ecf20Sopenharmony_ci fw.or_major, fw.or_build, fw.or_patch); 30508c2ecf20Sopenharmony_ci /* no option rom */ 30518c2ecf20Sopenharmony_ci } else if (fw.etrack_id != 0X0000) { 30528c2ecf20Sopenharmony_ci snprintf(adapter->fw_version, 30538c2ecf20Sopenharmony_ci sizeof(adapter->fw_version), 30548c2ecf20Sopenharmony_ci "%d.%d, 0x%08x", 30558c2ecf20Sopenharmony_ci fw.eep_major, fw.eep_minor, fw.etrack_id); 30568c2ecf20Sopenharmony_ci } else { 30578c2ecf20Sopenharmony_ci snprintf(adapter->fw_version, 30588c2ecf20Sopenharmony_ci sizeof(adapter->fw_version), 30598c2ecf20Sopenharmony_ci "%d.%d.%d", 30608c2ecf20Sopenharmony_ci fw.eep_major, fw.eep_minor, fw.eep_build); 30618c2ecf20Sopenharmony_ci } 30628c2ecf20Sopenharmony_ci break; 30638c2ecf20Sopenharmony_ci } 30648c2ecf20Sopenharmony_ci} 30658c2ecf20Sopenharmony_ci 30668c2ecf20Sopenharmony_ci/** 30678c2ecf20Sopenharmony_ci * igb_init_mas - init Media Autosense feature if enabled in the NVM 30688c2ecf20Sopenharmony_ci * 30698c2ecf20Sopenharmony_ci * @adapter: adapter struct 30708c2ecf20Sopenharmony_ci **/ 30718c2ecf20Sopenharmony_cistatic void igb_init_mas(struct igb_adapter *adapter) 30728c2ecf20Sopenharmony_ci{ 30738c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 30748c2ecf20Sopenharmony_ci u16 eeprom_data; 30758c2ecf20Sopenharmony_ci 30768c2ecf20Sopenharmony_ci hw->nvm.ops.read(hw, NVM_COMPAT, 1, &eeprom_data); 30778c2ecf20Sopenharmony_ci switch (hw->bus.func) { 30788c2ecf20Sopenharmony_ci case E1000_FUNC_0: 30798c2ecf20Sopenharmony_ci if (eeprom_data & IGB_MAS_ENABLE_0) { 30808c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_MAS_ENABLE; 30818c2ecf20Sopenharmony_ci netdev_info(adapter->netdev, 30828c2ecf20Sopenharmony_ci "MAS: Enabling Media Autosense for port %d\n", 30838c2ecf20Sopenharmony_ci hw->bus.func); 30848c2ecf20Sopenharmony_ci } 30858c2ecf20Sopenharmony_ci break; 30868c2ecf20Sopenharmony_ci case E1000_FUNC_1: 30878c2ecf20Sopenharmony_ci if (eeprom_data & IGB_MAS_ENABLE_1) { 30888c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_MAS_ENABLE; 30898c2ecf20Sopenharmony_ci netdev_info(adapter->netdev, 30908c2ecf20Sopenharmony_ci "MAS: Enabling Media Autosense for port %d\n", 30918c2ecf20Sopenharmony_ci hw->bus.func); 30928c2ecf20Sopenharmony_ci } 30938c2ecf20Sopenharmony_ci break; 30948c2ecf20Sopenharmony_ci case E1000_FUNC_2: 30958c2ecf20Sopenharmony_ci if (eeprom_data & IGB_MAS_ENABLE_2) { 30968c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_MAS_ENABLE; 30978c2ecf20Sopenharmony_ci netdev_info(adapter->netdev, 30988c2ecf20Sopenharmony_ci "MAS: Enabling Media Autosense for port %d\n", 30998c2ecf20Sopenharmony_ci hw->bus.func); 31008c2ecf20Sopenharmony_ci } 31018c2ecf20Sopenharmony_ci break; 31028c2ecf20Sopenharmony_ci case E1000_FUNC_3: 31038c2ecf20Sopenharmony_ci if (eeprom_data & IGB_MAS_ENABLE_3) { 31048c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_MAS_ENABLE; 31058c2ecf20Sopenharmony_ci netdev_info(adapter->netdev, 31068c2ecf20Sopenharmony_ci "MAS: Enabling Media Autosense for port %d\n", 31078c2ecf20Sopenharmony_ci hw->bus.func); 31088c2ecf20Sopenharmony_ci } 31098c2ecf20Sopenharmony_ci break; 31108c2ecf20Sopenharmony_ci default: 31118c2ecf20Sopenharmony_ci /* Shouldn't get here */ 31128c2ecf20Sopenharmony_ci netdev_err(adapter->netdev, 31138c2ecf20Sopenharmony_ci "MAS: Invalid port configuration, returning\n"); 31148c2ecf20Sopenharmony_ci break; 31158c2ecf20Sopenharmony_ci } 31168c2ecf20Sopenharmony_ci} 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_ci/** 31198c2ecf20Sopenharmony_ci * igb_init_i2c - Init I2C interface 31208c2ecf20Sopenharmony_ci * @adapter: pointer to adapter structure 31218c2ecf20Sopenharmony_ci **/ 31228c2ecf20Sopenharmony_cistatic s32 igb_init_i2c(struct igb_adapter *adapter) 31238c2ecf20Sopenharmony_ci{ 31248c2ecf20Sopenharmony_ci s32 status = 0; 31258c2ecf20Sopenharmony_ci 31268c2ecf20Sopenharmony_ci /* I2C interface supported on i350 devices */ 31278c2ecf20Sopenharmony_ci if (adapter->hw.mac.type != e1000_i350) 31288c2ecf20Sopenharmony_ci return 0; 31298c2ecf20Sopenharmony_ci 31308c2ecf20Sopenharmony_ci /* Initialize the i2c bus which is controlled by the registers. 31318c2ecf20Sopenharmony_ci * This bus will use the i2c_algo_bit structue that implements 31328c2ecf20Sopenharmony_ci * the protocol through toggling of the 4 bits in the register. 31338c2ecf20Sopenharmony_ci */ 31348c2ecf20Sopenharmony_ci adapter->i2c_adap.owner = THIS_MODULE; 31358c2ecf20Sopenharmony_ci adapter->i2c_algo = igb_i2c_algo; 31368c2ecf20Sopenharmony_ci adapter->i2c_algo.data = adapter; 31378c2ecf20Sopenharmony_ci adapter->i2c_adap.algo_data = &adapter->i2c_algo; 31388c2ecf20Sopenharmony_ci adapter->i2c_adap.dev.parent = &adapter->pdev->dev; 31398c2ecf20Sopenharmony_ci strlcpy(adapter->i2c_adap.name, "igb BB", 31408c2ecf20Sopenharmony_ci sizeof(adapter->i2c_adap.name)); 31418c2ecf20Sopenharmony_ci status = i2c_bit_add_bus(&adapter->i2c_adap); 31428c2ecf20Sopenharmony_ci return status; 31438c2ecf20Sopenharmony_ci} 31448c2ecf20Sopenharmony_ci 31458c2ecf20Sopenharmony_ci/** 31468c2ecf20Sopenharmony_ci * igb_probe - Device Initialization Routine 31478c2ecf20Sopenharmony_ci * @pdev: PCI device information struct 31488c2ecf20Sopenharmony_ci * @ent: entry in igb_pci_tbl 31498c2ecf20Sopenharmony_ci * 31508c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure 31518c2ecf20Sopenharmony_ci * 31528c2ecf20Sopenharmony_ci * igb_probe initializes an adapter identified by a pci_dev structure. 31538c2ecf20Sopenharmony_ci * The OS initialization, configuring of the adapter private structure, 31548c2ecf20Sopenharmony_ci * and a hardware reset occur. 31558c2ecf20Sopenharmony_ci **/ 31568c2ecf20Sopenharmony_cistatic int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 31578c2ecf20Sopenharmony_ci{ 31588c2ecf20Sopenharmony_ci struct net_device *netdev; 31598c2ecf20Sopenharmony_ci struct igb_adapter *adapter; 31608c2ecf20Sopenharmony_ci struct e1000_hw *hw; 31618c2ecf20Sopenharmony_ci u16 eeprom_data = 0; 31628c2ecf20Sopenharmony_ci s32 ret_val; 31638c2ecf20Sopenharmony_ci static int global_quad_port_a; /* global quad port a indication */ 31648c2ecf20Sopenharmony_ci const struct e1000_info *ei = igb_info_tbl[ent->driver_data]; 31658c2ecf20Sopenharmony_ci int err, pci_using_dac; 31668c2ecf20Sopenharmony_ci u8 part_str[E1000_PBANUM_LENGTH]; 31678c2ecf20Sopenharmony_ci 31688c2ecf20Sopenharmony_ci /* Catch broken hardware that put the wrong VF device ID in 31698c2ecf20Sopenharmony_ci * the PCIe SR-IOV capability. 31708c2ecf20Sopenharmony_ci */ 31718c2ecf20Sopenharmony_ci if (pdev->is_virtfn) { 31728c2ecf20Sopenharmony_ci WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n", 31738c2ecf20Sopenharmony_ci pci_name(pdev), pdev->vendor, pdev->device); 31748c2ecf20Sopenharmony_ci return -EINVAL; 31758c2ecf20Sopenharmony_ci } 31768c2ecf20Sopenharmony_ci 31778c2ecf20Sopenharmony_ci err = pci_enable_device_mem(pdev); 31788c2ecf20Sopenharmony_ci if (err) 31798c2ecf20Sopenharmony_ci return err; 31808c2ecf20Sopenharmony_ci 31818c2ecf20Sopenharmony_ci pci_using_dac = 0; 31828c2ecf20Sopenharmony_ci err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 31838c2ecf20Sopenharmony_ci if (!err) { 31848c2ecf20Sopenharmony_ci pci_using_dac = 1; 31858c2ecf20Sopenharmony_ci } else { 31868c2ecf20Sopenharmony_ci err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 31878c2ecf20Sopenharmony_ci if (err) { 31888c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 31898c2ecf20Sopenharmony_ci "No usable DMA configuration, aborting\n"); 31908c2ecf20Sopenharmony_ci goto err_dma; 31918c2ecf20Sopenharmony_ci } 31928c2ecf20Sopenharmony_ci } 31938c2ecf20Sopenharmony_ci 31948c2ecf20Sopenharmony_ci err = pci_request_mem_regions(pdev, igb_driver_name); 31958c2ecf20Sopenharmony_ci if (err) 31968c2ecf20Sopenharmony_ci goto err_pci_reg; 31978c2ecf20Sopenharmony_ci 31988c2ecf20Sopenharmony_ci pci_enable_pcie_error_reporting(pdev); 31998c2ecf20Sopenharmony_ci 32008c2ecf20Sopenharmony_ci pci_set_master(pdev); 32018c2ecf20Sopenharmony_ci pci_save_state(pdev); 32028c2ecf20Sopenharmony_ci 32038c2ecf20Sopenharmony_ci err = -ENOMEM; 32048c2ecf20Sopenharmony_ci netdev = alloc_etherdev_mq(sizeof(struct igb_adapter), 32058c2ecf20Sopenharmony_ci IGB_MAX_TX_QUEUES); 32068c2ecf20Sopenharmony_ci if (!netdev) 32078c2ecf20Sopenharmony_ci goto err_alloc_etherdev; 32088c2ecf20Sopenharmony_ci 32098c2ecf20Sopenharmony_ci SET_NETDEV_DEV(netdev, &pdev->dev); 32108c2ecf20Sopenharmony_ci 32118c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, netdev); 32128c2ecf20Sopenharmony_ci adapter = netdev_priv(netdev); 32138c2ecf20Sopenharmony_ci adapter->netdev = netdev; 32148c2ecf20Sopenharmony_ci adapter->pdev = pdev; 32158c2ecf20Sopenharmony_ci hw = &adapter->hw; 32168c2ecf20Sopenharmony_ci hw->back = adapter; 32178c2ecf20Sopenharmony_ci adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); 32188c2ecf20Sopenharmony_ci 32198c2ecf20Sopenharmony_ci err = -EIO; 32208c2ecf20Sopenharmony_ci adapter->io_addr = pci_iomap(pdev, 0, 0); 32218c2ecf20Sopenharmony_ci if (!adapter->io_addr) 32228c2ecf20Sopenharmony_ci goto err_ioremap; 32238c2ecf20Sopenharmony_ci /* hw->hw_addr can be altered, we'll use adapter->io_addr for unmap */ 32248c2ecf20Sopenharmony_ci hw->hw_addr = adapter->io_addr; 32258c2ecf20Sopenharmony_ci 32268c2ecf20Sopenharmony_ci netdev->netdev_ops = &igb_netdev_ops; 32278c2ecf20Sopenharmony_ci igb_set_ethtool_ops(netdev); 32288c2ecf20Sopenharmony_ci netdev->watchdog_timeo = 5 * HZ; 32298c2ecf20Sopenharmony_ci 32308c2ecf20Sopenharmony_ci strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); 32318c2ecf20Sopenharmony_ci 32328c2ecf20Sopenharmony_ci netdev->mem_start = pci_resource_start(pdev, 0); 32338c2ecf20Sopenharmony_ci netdev->mem_end = pci_resource_end(pdev, 0); 32348c2ecf20Sopenharmony_ci 32358c2ecf20Sopenharmony_ci /* PCI config space info */ 32368c2ecf20Sopenharmony_ci hw->vendor_id = pdev->vendor; 32378c2ecf20Sopenharmony_ci hw->device_id = pdev->device; 32388c2ecf20Sopenharmony_ci hw->revision_id = pdev->revision; 32398c2ecf20Sopenharmony_ci hw->subsystem_vendor_id = pdev->subsystem_vendor; 32408c2ecf20Sopenharmony_ci hw->subsystem_device_id = pdev->subsystem_device; 32418c2ecf20Sopenharmony_ci 32428c2ecf20Sopenharmony_ci /* Copy the default MAC, PHY and NVM function pointers */ 32438c2ecf20Sopenharmony_ci memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops)); 32448c2ecf20Sopenharmony_ci memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops)); 32458c2ecf20Sopenharmony_ci memcpy(&hw->nvm.ops, ei->nvm_ops, sizeof(hw->nvm.ops)); 32468c2ecf20Sopenharmony_ci /* Initialize skew-specific constants */ 32478c2ecf20Sopenharmony_ci err = ei->get_invariants(hw); 32488c2ecf20Sopenharmony_ci if (err) 32498c2ecf20Sopenharmony_ci goto err_sw_init; 32508c2ecf20Sopenharmony_ci 32518c2ecf20Sopenharmony_ci /* setup the private structure */ 32528c2ecf20Sopenharmony_ci err = igb_sw_init(adapter); 32538c2ecf20Sopenharmony_ci if (err) 32548c2ecf20Sopenharmony_ci goto err_sw_init; 32558c2ecf20Sopenharmony_ci 32568c2ecf20Sopenharmony_ci igb_get_bus_info_pcie(hw); 32578c2ecf20Sopenharmony_ci 32588c2ecf20Sopenharmony_ci hw->phy.autoneg_wait_to_complete = false; 32598c2ecf20Sopenharmony_ci 32608c2ecf20Sopenharmony_ci /* Copper options */ 32618c2ecf20Sopenharmony_ci if (hw->phy.media_type == e1000_media_type_copper) { 32628c2ecf20Sopenharmony_ci hw->phy.mdix = AUTO_ALL_MODES; 32638c2ecf20Sopenharmony_ci hw->phy.disable_polarity_correction = false; 32648c2ecf20Sopenharmony_ci hw->phy.ms_type = e1000_ms_hw_default; 32658c2ecf20Sopenharmony_ci } 32668c2ecf20Sopenharmony_ci 32678c2ecf20Sopenharmony_ci if (igb_check_reset_block(hw)) 32688c2ecf20Sopenharmony_ci dev_info(&pdev->dev, 32698c2ecf20Sopenharmony_ci "PHY reset is blocked due to SOL/IDER session.\n"); 32708c2ecf20Sopenharmony_ci 32718c2ecf20Sopenharmony_ci /* features is initialized to 0 in allocation, it might have bits 32728c2ecf20Sopenharmony_ci * set by igb_sw_init so we should use an or instead of an 32738c2ecf20Sopenharmony_ci * assignment. 32748c2ecf20Sopenharmony_ci */ 32758c2ecf20Sopenharmony_ci netdev->features |= NETIF_F_SG | 32768c2ecf20Sopenharmony_ci NETIF_F_TSO | 32778c2ecf20Sopenharmony_ci NETIF_F_TSO6 | 32788c2ecf20Sopenharmony_ci NETIF_F_RXHASH | 32798c2ecf20Sopenharmony_ci NETIF_F_RXCSUM | 32808c2ecf20Sopenharmony_ci NETIF_F_HW_CSUM; 32818c2ecf20Sopenharmony_ci 32828c2ecf20Sopenharmony_ci if (hw->mac.type >= e1000_82576) 32838c2ecf20Sopenharmony_ci netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_GSO_UDP_L4; 32848c2ecf20Sopenharmony_ci 32858c2ecf20Sopenharmony_ci if (hw->mac.type >= e1000_i350) 32868c2ecf20Sopenharmony_ci netdev->features |= NETIF_F_HW_TC; 32878c2ecf20Sopenharmony_ci 32888c2ecf20Sopenharmony_ci#define IGB_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \ 32898c2ecf20Sopenharmony_ci NETIF_F_GSO_GRE_CSUM | \ 32908c2ecf20Sopenharmony_ci NETIF_F_GSO_IPXIP4 | \ 32918c2ecf20Sopenharmony_ci NETIF_F_GSO_IPXIP6 | \ 32928c2ecf20Sopenharmony_ci NETIF_F_GSO_UDP_TUNNEL | \ 32938c2ecf20Sopenharmony_ci NETIF_F_GSO_UDP_TUNNEL_CSUM) 32948c2ecf20Sopenharmony_ci 32958c2ecf20Sopenharmony_ci netdev->gso_partial_features = IGB_GSO_PARTIAL_FEATURES; 32968c2ecf20Sopenharmony_ci netdev->features |= NETIF_F_GSO_PARTIAL | IGB_GSO_PARTIAL_FEATURES; 32978c2ecf20Sopenharmony_ci 32988c2ecf20Sopenharmony_ci /* copy netdev features into list of user selectable features */ 32998c2ecf20Sopenharmony_ci netdev->hw_features |= netdev->features | 33008c2ecf20Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_RX | 33018c2ecf20Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_TX | 33028c2ecf20Sopenharmony_ci NETIF_F_RXALL; 33038c2ecf20Sopenharmony_ci 33048c2ecf20Sopenharmony_ci if (hw->mac.type >= e1000_i350) 33058c2ecf20Sopenharmony_ci netdev->hw_features |= NETIF_F_NTUPLE; 33068c2ecf20Sopenharmony_ci 33078c2ecf20Sopenharmony_ci if (pci_using_dac) 33088c2ecf20Sopenharmony_ci netdev->features |= NETIF_F_HIGHDMA; 33098c2ecf20Sopenharmony_ci 33108c2ecf20Sopenharmony_ci netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID; 33118c2ecf20Sopenharmony_ci netdev->mpls_features |= NETIF_F_HW_CSUM; 33128c2ecf20Sopenharmony_ci netdev->hw_enc_features |= netdev->vlan_features; 33138c2ecf20Sopenharmony_ci 33148c2ecf20Sopenharmony_ci /* set this bit last since it cannot be part of vlan_features */ 33158c2ecf20Sopenharmony_ci netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | 33168c2ecf20Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_RX | 33178c2ecf20Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_TX; 33188c2ecf20Sopenharmony_ci 33198c2ecf20Sopenharmony_ci netdev->priv_flags |= IFF_SUPP_NOFCS; 33208c2ecf20Sopenharmony_ci 33218c2ecf20Sopenharmony_ci netdev->priv_flags |= IFF_UNICAST_FLT; 33228c2ecf20Sopenharmony_ci 33238c2ecf20Sopenharmony_ci /* MTU range: 68 - 9216 */ 33248c2ecf20Sopenharmony_ci netdev->min_mtu = ETH_MIN_MTU; 33258c2ecf20Sopenharmony_ci netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; 33268c2ecf20Sopenharmony_ci 33278c2ecf20Sopenharmony_ci adapter->en_mng_pt = igb_enable_mng_pass_thru(hw); 33288c2ecf20Sopenharmony_ci 33298c2ecf20Sopenharmony_ci /* before reading the NVM, reset the controller to put the device in a 33308c2ecf20Sopenharmony_ci * known good starting state 33318c2ecf20Sopenharmony_ci */ 33328c2ecf20Sopenharmony_ci hw->mac.ops.reset_hw(hw); 33338c2ecf20Sopenharmony_ci 33348c2ecf20Sopenharmony_ci /* make sure the NVM is good , i211/i210 parts can have special NVM 33358c2ecf20Sopenharmony_ci * that doesn't contain a checksum 33368c2ecf20Sopenharmony_ci */ 33378c2ecf20Sopenharmony_ci switch (hw->mac.type) { 33388c2ecf20Sopenharmony_ci case e1000_i210: 33398c2ecf20Sopenharmony_ci case e1000_i211: 33408c2ecf20Sopenharmony_ci if (igb_get_flash_presence_i210(hw)) { 33418c2ecf20Sopenharmony_ci if (hw->nvm.ops.validate(hw) < 0) { 33428c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 33438c2ecf20Sopenharmony_ci "The NVM Checksum Is Not Valid\n"); 33448c2ecf20Sopenharmony_ci err = -EIO; 33458c2ecf20Sopenharmony_ci goto err_eeprom; 33468c2ecf20Sopenharmony_ci } 33478c2ecf20Sopenharmony_ci } 33488c2ecf20Sopenharmony_ci break; 33498c2ecf20Sopenharmony_ci default: 33508c2ecf20Sopenharmony_ci if (hw->nvm.ops.validate(hw) < 0) { 33518c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); 33528c2ecf20Sopenharmony_ci err = -EIO; 33538c2ecf20Sopenharmony_ci goto err_eeprom; 33548c2ecf20Sopenharmony_ci } 33558c2ecf20Sopenharmony_ci break; 33568c2ecf20Sopenharmony_ci } 33578c2ecf20Sopenharmony_ci 33588c2ecf20Sopenharmony_ci if (eth_platform_get_mac_address(&pdev->dev, hw->mac.addr)) { 33598c2ecf20Sopenharmony_ci /* copy the MAC address out of the NVM */ 33608c2ecf20Sopenharmony_ci if (hw->mac.ops.read_mac_addr(hw)) 33618c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "NVM Read Error\n"); 33628c2ecf20Sopenharmony_ci } 33638c2ecf20Sopenharmony_ci 33648c2ecf20Sopenharmony_ci memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len); 33658c2ecf20Sopenharmony_ci 33668c2ecf20Sopenharmony_ci if (!is_valid_ether_addr(netdev->dev_addr)) { 33678c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Invalid MAC Address\n"); 33688c2ecf20Sopenharmony_ci err = -EIO; 33698c2ecf20Sopenharmony_ci goto err_eeprom; 33708c2ecf20Sopenharmony_ci } 33718c2ecf20Sopenharmony_ci 33728c2ecf20Sopenharmony_ci igb_set_default_mac_filter(adapter); 33738c2ecf20Sopenharmony_ci 33748c2ecf20Sopenharmony_ci /* get firmware version for ethtool -i */ 33758c2ecf20Sopenharmony_ci igb_set_fw_version(adapter); 33768c2ecf20Sopenharmony_ci 33778c2ecf20Sopenharmony_ci /* configure RXPBSIZE and TXPBSIZE */ 33788c2ecf20Sopenharmony_ci if (hw->mac.type == e1000_i210) { 33798c2ecf20Sopenharmony_ci wr32(E1000_RXPBS, I210_RXPBSIZE_DEFAULT); 33808c2ecf20Sopenharmony_ci wr32(E1000_TXPBS, I210_TXPBSIZE_DEFAULT); 33818c2ecf20Sopenharmony_ci } 33828c2ecf20Sopenharmony_ci 33838c2ecf20Sopenharmony_ci timer_setup(&adapter->watchdog_timer, igb_watchdog, 0); 33848c2ecf20Sopenharmony_ci timer_setup(&adapter->phy_info_timer, igb_update_phy_info, 0); 33858c2ecf20Sopenharmony_ci 33868c2ecf20Sopenharmony_ci INIT_WORK(&adapter->reset_task, igb_reset_task); 33878c2ecf20Sopenharmony_ci INIT_WORK(&adapter->watchdog_task, igb_watchdog_task); 33888c2ecf20Sopenharmony_ci 33898c2ecf20Sopenharmony_ci /* Initialize link properties that are user-changeable */ 33908c2ecf20Sopenharmony_ci adapter->fc_autoneg = true; 33918c2ecf20Sopenharmony_ci hw->mac.autoneg = true; 33928c2ecf20Sopenharmony_ci hw->phy.autoneg_advertised = 0x2f; 33938c2ecf20Sopenharmony_ci 33948c2ecf20Sopenharmony_ci hw->fc.requested_mode = e1000_fc_default; 33958c2ecf20Sopenharmony_ci hw->fc.current_mode = e1000_fc_default; 33968c2ecf20Sopenharmony_ci 33978c2ecf20Sopenharmony_ci igb_validate_mdi_setting(hw); 33988c2ecf20Sopenharmony_ci 33998c2ecf20Sopenharmony_ci /* By default, support wake on port A */ 34008c2ecf20Sopenharmony_ci if (hw->bus.func == 0) 34018c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_WOL_SUPPORTED; 34028c2ecf20Sopenharmony_ci 34038c2ecf20Sopenharmony_ci /* Check the NVM for wake support on non-port A ports */ 34048c2ecf20Sopenharmony_ci if (hw->mac.type >= e1000_82580) 34058c2ecf20Sopenharmony_ci hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + 34068c2ecf20Sopenharmony_ci NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, 34078c2ecf20Sopenharmony_ci &eeprom_data); 34088c2ecf20Sopenharmony_ci else if (hw->bus.func == 1) 34098c2ecf20Sopenharmony_ci hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); 34108c2ecf20Sopenharmony_ci 34118c2ecf20Sopenharmony_ci if (eeprom_data & IGB_EEPROM_APME) 34128c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_WOL_SUPPORTED; 34138c2ecf20Sopenharmony_ci 34148c2ecf20Sopenharmony_ci /* now that we have the eeprom settings, apply the special cases where 34158c2ecf20Sopenharmony_ci * the eeprom may be wrong or the board simply won't support wake on 34168c2ecf20Sopenharmony_ci * lan on a particular port 34178c2ecf20Sopenharmony_ci */ 34188c2ecf20Sopenharmony_ci switch (pdev->device) { 34198c2ecf20Sopenharmony_ci case E1000_DEV_ID_82575GB_QUAD_COPPER: 34208c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; 34218c2ecf20Sopenharmony_ci break; 34228c2ecf20Sopenharmony_ci case E1000_DEV_ID_82575EB_FIBER_SERDES: 34238c2ecf20Sopenharmony_ci case E1000_DEV_ID_82576_FIBER: 34248c2ecf20Sopenharmony_ci case E1000_DEV_ID_82576_SERDES: 34258c2ecf20Sopenharmony_ci /* Wake events only supported on port A for dual fiber 34268c2ecf20Sopenharmony_ci * regardless of eeprom setting 34278c2ecf20Sopenharmony_ci */ 34288c2ecf20Sopenharmony_ci if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1) 34298c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; 34308c2ecf20Sopenharmony_ci break; 34318c2ecf20Sopenharmony_ci case E1000_DEV_ID_82576_QUAD_COPPER: 34328c2ecf20Sopenharmony_ci case E1000_DEV_ID_82576_QUAD_COPPER_ET2: 34338c2ecf20Sopenharmony_ci /* if quad port adapter, disable WoL on all but port A */ 34348c2ecf20Sopenharmony_ci if (global_quad_port_a != 0) 34358c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; 34368c2ecf20Sopenharmony_ci else 34378c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_QUAD_PORT_A; 34388c2ecf20Sopenharmony_ci /* Reset for multiple quad port adapters */ 34398c2ecf20Sopenharmony_ci if (++global_quad_port_a == 4) 34408c2ecf20Sopenharmony_ci global_quad_port_a = 0; 34418c2ecf20Sopenharmony_ci break; 34428c2ecf20Sopenharmony_ci default: 34438c2ecf20Sopenharmony_ci /* If the device can't wake, don't set software support */ 34448c2ecf20Sopenharmony_ci if (!device_can_wakeup(&adapter->pdev->dev)) 34458c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; 34468c2ecf20Sopenharmony_ci } 34478c2ecf20Sopenharmony_ci 34488c2ecf20Sopenharmony_ci /* initialize the wol settings based on the eeprom settings */ 34498c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_WOL_SUPPORTED) 34508c2ecf20Sopenharmony_ci adapter->wol |= E1000_WUFC_MAG; 34518c2ecf20Sopenharmony_ci 34528c2ecf20Sopenharmony_ci /* Some vendors want WoL disabled by default, but still supported */ 34538c2ecf20Sopenharmony_ci if ((hw->mac.type == e1000_i350) && 34548c2ecf20Sopenharmony_ci (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)) { 34558c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_WOL_SUPPORTED; 34568c2ecf20Sopenharmony_ci adapter->wol = 0; 34578c2ecf20Sopenharmony_ci } 34588c2ecf20Sopenharmony_ci 34598c2ecf20Sopenharmony_ci /* Some vendors want the ability to Use the EEPROM setting as 34608c2ecf20Sopenharmony_ci * enable/disable only, and not for capability 34618c2ecf20Sopenharmony_ci */ 34628c2ecf20Sopenharmony_ci if (((hw->mac.type == e1000_i350) || 34638c2ecf20Sopenharmony_ci (hw->mac.type == e1000_i354)) && 34648c2ecf20Sopenharmony_ci (pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)) { 34658c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_WOL_SUPPORTED; 34668c2ecf20Sopenharmony_ci adapter->wol = 0; 34678c2ecf20Sopenharmony_ci } 34688c2ecf20Sopenharmony_ci if (hw->mac.type == e1000_i350) { 34698c2ecf20Sopenharmony_ci if (((pdev->subsystem_device == 0x5001) || 34708c2ecf20Sopenharmony_ci (pdev->subsystem_device == 0x5002)) && 34718c2ecf20Sopenharmony_ci (hw->bus.func == 0)) { 34728c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_WOL_SUPPORTED; 34738c2ecf20Sopenharmony_ci adapter->wol = 0; 34748c2ecf20Sopenharmony_ci } 34758c2ecf20Sopenharmony_ci if (pdev->subsystem_device == 0x1F52) 34768c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_WOL_SUPPORTED; 34778c2ecf20Sopenharmony_ci } 34788c2ecf20Sopenharmony_ci 34798c2ecf20Sopenharmony_ci device_set_wakeup_enable(&adapter->pdev->dev, 34808c2ecf20Sopenharmony_ci adapter->flags & IGB_FLAG_WOL_SUPPORTED); 34818c2ecf20Sopenharmony_ci 34828c2ecf20Sopenharmony_ci /* reset the hardware with the new settings */ 34838c2ecf20Sopenharmony_ci igb_reset(adapter); 34848c2ecf20Sopenharmony_ci 34858c2ecf20Sopenharmony_ci /* Init the I2C interface */ 34868c2ecf20Sopenharmony_ci err = igb_init_i2c(adapter); 34878c2ecf20Sopenharmony_ci if (err) { 34888c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to init i2c interface\n"); 34898c2ecf20Sopenharmony_ci goto err_eeprom; 34908c2ecf20Sopenharmony_ci } 34918c2ecf20Sopenharmony_ci 34928c2ecf20Sopenharmony_ci /* let the f/w know that the h/w is now under the control of the 34938c2ecf20Sopenharmony_ci * driver. 34948c2ecf20Sopenharmony_ci */ 34958c2ecf20Sopenharmony_ci igb_get_hw_control(adapter); 34968c2ecf20Sopenharmony_ci 34978c2ecf20Sopenharmony_ci strcpy(netdev->name, "eth%d"); 34988c2ecf20Sopenharmony_ci err = register_netdev(netdev); 34998c2ecf20Sopenharmony_ci if (err) 35008c2ecf20Sopenharmony_ci goto err_register; 35018c2ecf20Sopenharmony_ci 35028c2ecf20Sopenharmony_ci /* carrier off reporting is important to ethtool even BEFORE open */ 35038c2ecf20Sopenharmony_ci netif_carrier_off(netdev); 35048c2ecf20Sopenharmony_ci 35058c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_DCA 35068c2ecf20Sopenharmony_ci if (dca_add_requester(&pdev->dev) == 0) { 35078c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_DCA_ENABLED; 35088c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "DCA enabled\n"); 35098c2ecf20Sopenharmony_ci igb_setup_dca(adapter); 35108c2ecf20Sopenharmony_ci } 35118c2ecf20Sopenharmony_ci 35128c2ecf20Sopenharmony_ci#endif 35138c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_HWMON 35148c2ecf20Sopenharmony_ci /* Initialize the thermal sensor on i350 devices. */ 35158c2ecf20Sopenharmony_ci if (hw->mac.type == e1000_i350 && hw->bus.func == 0) { 35168c2ecf20Sopenharmony_ci u16 ets_word; 35178c2ecf20Sopenharmony_ci 35188c2ecf20Sopenharmony_ci /* Read the NVM to determine if this i350 device supports an 35198c2ecf20Sopenharmony_ci * external thermal sensor. 35208c2ecf20Sopenharmony_ci */ 35218c2ecf20Sopenharmony_ci hw->nvm.ops.read(hw, NVM_ETS_CFG, 1, &ets_word); 35228c2ecf20Sopenharmony_ci if (ets_word != 0x0000 && ets_word != 0xFFFF) 35238c2ecf20Sopenharmony_ci adapter->ets = true; 35248c2ecf20Sopenharmony_ci else 35258c2ecf20Sopenharmony_ci adapter->ets = false; 35268c2ecf20Sopenharmony_ci if (igb_sysfs_init(adapter)) 35278c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 35288c2ecf20Sopenharmony_ci "failed to allocate sysfs resources\n"); 35298c2ecf20Sopenharmony_ci } else { 35308c2ecf20Sopenharmony_ci adapter->ets = false; 35318c2ecf20Sopenharmony_ci } 35328c2ecf20Sopenharmony_ci#endif 35338c2ecf20Sopenharmony_ci /* Check if Media Autosense is enabled */ 35348c2ecf20Sopenharmony_ci adapter->ei = *ei; 35358c2ecf20Sopenharmony_ci if (hw->dev_spec._82575.mas_capable) 35368c2ecf20Sopenharmony_ci igb_init_mas(adapter); 35378c2ecf20Sopenharmony_ci 35388c2ecf20Sopenharmony_ci /* do hw tstamp init after resetting */ 35398c2ecf20Sopenharmony_ci igb_ptp_init(adapter); 35408c2ecf20Sopenharmony_ci 35418c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n"); 35428c2ecf20Sopenharmony_ci /* print bus type/speed/width info, not applicable to i354 */ 35438c2ecf20Sopenharmony_ci if (hw->mac.type != e1000_i354) { 35448c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n", 35458c2ecf20Sopenharmony_ci netdev->name, 35468c2ecf20Sopenharmony_ci ((hw->bus.speed == e1000_bus_speed_2500) ? "2.5Gb/s" : 35478c2ecf20Sopenharmony_ci (hw->bus.speed == e1000_bus_speed_5000) ? "5.0Gb/s" : 35488c2ecf20Sopenharmony_ci "unknown"), 35498c2ecf20Sopenharmony_ci ((hw->bus.width == e1000_bus_width_pcie_x4) ? 35508c2ecf20Sopenharmony_ci "Width x4" : 35518c2ecf20Sopenharmony_ci (hw->bus.width == e1000_bus_width_pcie_x2) ? 35528c2ecf20Sopenharmony_ci "Width x2" : 35538c2ecf20Sopenharmony_ci (hw->bus.width == e1000_bus_width_pcie_x1) ? 35548c2ecf20Sopenharmony_ci "Width x1" : "unknown"), netdev->dev_addr); 35558c2ecf20Sopenharmony_ci } 35568c2ecf20Sopenharmony_ci 35578c2ecf20Sopenharmony_ci if ((hw->mac.type == e1000_82576 && 35588c2ecf20Sopenharmony_ci rd32(E1000_EECD) & E1000_EECD_PRES) || 35598c2ecf20Sopenharmony_ci (hw->mac.type >= e1000_i210 || 35608c2ecf20Sopenharmony_ci igb_get_flash_presence_i210(hw))) { 35618c2ecf20Sopenharmony_ci ret_val = igb_read_part_string(hw, part_str, 35628c2ecf20Sopenharmony_ci E1000_PBANUM_LENGTH); 35638c2ecf20Sopenharmony_ci } else { 35648c2ecf20Sopenharmony_ci ret_val = -E1000_ERR_INVM_VALUE_NOT_FOUND; 35658c2ecf20Sopenharmony_ci } 35668c2ecf20Sopenharmony_ci 35678c2ecf20Sopenharmony_ci if (ret_val) 35688c2ecf20Sopenharmony_ci strcpy(part_str, "Unknown"); 35698c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "%s: PBA No: %s\n", netdev->name, part_str); 35708c2ecf20Sopenharmony_ci dev_info(&pdev->dev, 35718c2ecf20Sopenharmony_ci "Using %s interrupts. %d rx queue(s), %d tx queue(s)\n", 35728c2ecf20Sopenharmony_ci (adapter->flags & IGB_FLAG_HAS_MSIX) ? "MSI-X" : 35738c2ecf20Sopenharmony_ci (adapter->flags & IGB_FLAG_HAS_MSI) ? "MSI" : "legacy", 35748c2ecf20Sopenharmony_ci adapter->num_rx_queues, adapter->num_tx_queues); 35758c2ecf20Sopenharmony_ci if (hw->phy.media_type == e1000_media_type_copper) { 35768c2ecf20Sopenharmony_ci switch (hw->mac.type) { 35778c2ecf20Sopenharmony_ci case e1000_i350: 35788c2ecf20Sopenharmony_ci case e1000_i210: 35798c2ecf20Sopenharmony_ci case e1000_i211: 35808c2ecf20Sopenharmony_ci /* Enable EEE for internal copper PHY devices */ 35818c2ecf20Sopenharmony_ci err = igb_set_eee_i350(hw, true, true); 35828c2ecf20Sopenharmony_ci if ((!err) && 35838c2ecf20Sopenharmony_ci (!hw->dev_spec._82575.eee_disable)) { 35848c2ecf20Sopenharmony_ci adapter->eee_advert = 35858c2ecf20Sopenharmony_ci MDIO_EEE_100TX | MDIO_EEE_1000T; 35868c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_EEE; 35878c2ecf20Sopenharmony_ci } 35888c2ecf20Sopenharmony_ci break; 35898c2ecf20Sopenharmony_ci case e1000_i354: 35908c2ecf20Sopenharmony_ci if ((rd32(E1000_CTRL_EXT) & 35918c2ecf20Sopenharmony_ci E1000_CTRL_EXT_LINK_MODE_SGMII)) { 35928c2ecf20Sopenharmony_ci err = igb_set_eee_i354(hw, true, true); 35938c2ecf20Sopenharmony_ci if ((!err) && 35948c2ecf20Sopenharmony_ci (!hw->dev_spec._82575.eee_disable)) { 35958c2ecf20Sopenharmony_ci adapter->eee_advert = 35968c2ecf20Sopenharmony_ci MDIO_EEE_100TX | MDIO_EEE_1000T; 35978c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_EEE; 35988c2ecf20Sopenharmony_ci } 35998c2ecf20Sopenharmony_ci } 36008c2ecf20Sopenharmony_ci break; 36018c2ecf20Sopenharmony_ci default: 36028c2ecf20Sopenharmony_ci break; 36038c2ecf20Sopenharmony_ci } 36048c2ecf20Sopenharmony_ci } 36058c2ecf20Sopenharmony_ci 36068c2ecf20Sopenharmony_ci dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NO_DIRECT_COMPLETE); 36078c2ecf20Sopenharmony_ci 36088c2ecf20Sopenharmony_ci pm_runtime_put_noidle(&pdev->dev); 36098c2ecf20Sopenharmony_ci return 0; 36108c2ecf20Sopenharmony_ci 36118c2ecf20Sopenharmony_cierr_register: 36128c2ecf20Sopenharmony_ci igb_release_hw_control(adapter); 36138c2ecf20Sopenharmony_ci memset(&adapter->i2c_adap, 0, sizeof(adapter->i2c_adap)); 36148c2ecf20Sopenharmony_cierr_eeprom: 36158c2ecf20Sopenharmony_ci if (!igb_check_reset_block(hw)) 36168c2ecf20Sopenharmony_ci igb_reset_phy(hw); 36178c2ecf20Sopenharmony_ci 36188c2ecf20Sopenharmony_ci if (hw->flash_address) 36198c2ecf20Sopenharmony_ci iounmap(hw->flash_address); 36208c2ecf20Sopenharmony_cierr_sw_init: 36218c2ecf20Sopenharmony_ci kfree(adapter->mac_table); 36228c2ecf20Sopenharmony_ci kfree(adapter->shadow_vfta); 36238c2ecf20Sopenharmony_ci igb_clear_interrupt_scheme(adapter); 36248c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 36258c2ecf20Sopenharmony_ci igb_disable_sriov(pdev); 36268c2ecf20Sopenharmony_ci#endif 36278c2ecf20Sopenharmony_ci pci_iounmap(pdev, adapter->io_addr); 36288c2ecf20Sopenharmony_cierr_ioremap: 36298c2ecf20Sopenharmony_ci free_netdev(netdev); 36308c2ecf20Sopenharmony_cierr_alloc_etherdev: 36318c2ecf20Sopenharmony_ci pci_disable_pcie_error_reporting(pdev); 36328c2ecf20Sopenharmony_ci pci_release_mem_regions(pdev); 36338c2ecf20Sopenharmony_cierr_pci_reg: 36348c2ecf20Sopenharmony_cierr_dma: 36358c2ecf20Sopenharmony_ci pci_disable_device(pdev); 36368c2ecf20Sopenharmony_ci return err; 36378c2ecf20Sopenharmony_ci} 36388c2ecf20Sopenharmony_ci 36398c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 36408c2ecf20Sopenharmony_cistatic int igb_disable_sriov(struct pci_dev *pdev) 36418c2ecf20Sopenharmony_ci{ 36428c2ecf20Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 36438c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 36448c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 36458c2ecf20Sopenharmony_ci unsigned long flags; 36468c2ecf20Sopenharmony_ci 36478c2ecf20Sopenharmony_ci /* reclaim resources allocated to VFs */ 36488c2ecf20Sopenharmony_ci if (adapter->vf_data) { 36498c2ecf20Sopenharmony_ci /* disable iov and allow time for transactions to clear */ 36508c2ecf20Sopenharmony_ci if (pci_vfs_assigned(pdev)) { 36518c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, 36528c2ecf20Sopenharmony_ci "Cannot deallocate SR-IOV virtual functions while they are assigned - VFs will not be deallocated\n"); 36538c2ecf20Sopenharmony_ci return -EPERM; 36548c2ecf20Sopenharmony_ci } else { 36558c2ecf20Sopenharmony_ci pci_disable_sriov(pdev); 36568c2ecf20Sopenharmony_ci msleep(500); 36578c2ecf20Sopenharmony_ci } 36588c2ecf20Sopenharmony_ci spin_lock_irqsave(&adapter->vfs_lock, flags); 36598c2ecf20Sopenharmony_ci kfree(adapter->vf_mac_list); 36608c2ecf20Sopenharmony_ci adapter->vf_mac_list = NULL; 36618c2ecf20Sopenharmony_ci kfree(adapter->vf_data); 36628c2ecf20Sopenharmony_ci adapter->vf_data = NULL; 36638c2ecf20Sopenharmony_ci adapter->vfs_allocated_count = 0; 36648c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&adapter->vfs_lock, flags); 36658c2ecf20Sopenharmony_ci wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ); 36668c2ecf20Sopenharmony_ci wrfl(); 36678c2ecf20Sopenharmony_ci msleep(100); 36688c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "IOV Disabled\n"); 36698c2ecf20Sopenharmony_ci 36708c2ecf20Sopenharmony_ci /* Re-enable DMA Coalescing flag since IOV is turned off */ 36718c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_DMAC; 36728c2ecf20Sopenharmony_ci } 36738c2ecf20Sopenharmony_ci 36748c2ecf20Sopenharmony_ci return 0; 36758c2ecf20Sopenharmony_ci} 36768c2ecf20Sopenharmony_ci 36778c2ecf20Sopenharmony_cistatic int igb_enable_sriov(struct pci_dev *pdev, int num_vfs) 36788c2ecf20Sopenharmony_ci{ 36798c2ecf20Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 36808c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 36818c2ecf20Sopenharmony_ci int old_vfs = pci_num_vf(pdev); 36828c2ecf20Sopenharmony_ci struct vf_mac_filter *mac_list; 36838c2ecf20Sopenharmony_ci int err = 0; 36848c2ecf20Sopenharmony_ci int num_vf_mac_filters, i; 36858c2ecf20Sopenharmony_ci 36868c2ecf20Sopenharmony_ci if (!(adapter->flags & IGB_FLAG_HAS_MSIX) || num_vfs > 7) { 36878c2ecf20Sopenharmony_ci err = -EPERM; 36888c2ecf20Sopenharmony_ci goto out; 36898c2ecf20Sopenharmony_ci } 36908c2ecf20Sopenharmony_ci if (!num_vfs) 36918c2ecf20Sopenharmony_ci goto out; 36928c2ecf20Sopenharmony_ci 36938c2ecf20Sopenharmony_ci if (old_vfs) { 36948c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "%d pre-allocated VFs found - override max_vfs setting of %d\n", 36958c2ecf20Sopenharmony_ci old_vfs, max_vfs); 36968c2ecf20Sopenharmony_ci adapter->vfs_allocated_count = old_vfs; 36978c2ecf20Sopenharmony_ci } else 36988c2ecf20Sopenharmony_ci adapter->vfs_allocated_count = num_vfs; 36998c2ecf20Sopenharmony_ci 37008c2ecf20Sopenharmony_ci adapter->vf_data = kcalloc(adapter->vfs_allocated_count, 37018c2ecf20Sopenharmony_ci sizeof(struct vf_data_storage), GFP_KERNEL); 37028c2ecf20Sopenharmony_ci 37038c2ecf20Sopenharmony_ci /* if allocation failed then we do not support SR-IOV */ 37048c2ecf20Sopenharmony_ci if (!adapter->vf_data) { 37058c2ecf20Sopenharmony_ci adapter->vfs_allocated_count = 0; 37068c2ecf20Sopenharmony_ci err = -ENOMEM; 37078c2ecf20Sopenharmony_ci goto out; 37088c2ecf20Sopenharmony_ci } 37098c2ecf20Sopenharmony_ci 37108c2ecf20Sopenharmony_ci /* Due to the limited number of RAR entries calculate potential 37118c2ecf20Sopenharmony_ci * number of MAC filters available for the VFs. Reserve entries 37128c2ecf20Sopenharmony_ci * for PF default MAC, PF MAC filters and at least one RAR entry 37138c2ecf20Sopenharmony_ci * for each VF for VF MAC. 37148c2ecf20Sopenharmony_ci */ 37158c2ecf20Sopenharmony_ci num_vf_mac_filters = adapter->hw.mac.rar_entry_count - 37168c2ecf20Sopenharmony_ci (1 + IGB_PF_MAC_FILTERS_RESERVED + 37178c2ecf20Sopenharmony_ci adapter->vfs_allocated_count); 37188c2ecf20Sopenharmony_ci 37198c2ecf20Sopenharmony_ci adapter->vf_mac_list = kcalloc(num_vf_mac_filters, 37208c2ecf20Sopenharmony_ci sizeof(struct vf_mac_filter), 37218c2ecf20Sopenharmony_ci GFP_KERNEL); 37228c2ecf20Sopenharmony_ci 37238c2ecf20Sopenharmony_ci mac_list = adapter->vf_mac_list; 37248c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&adapter->vf_macs.l); 37258c2ecf20Sopenharmony_ci 37268c2ecf20Sopenharmony_ci if (adapter->vf_mac_list) { 37278c2ecf20Sopenharmony_ci /* Initialize list of VF MAC filters */ 37288c2ecf20Sopenharmony_ci for (i = 0; i < num_vf_mac_filters; i++) { 37298c2ecf20Sopenharmony_ci mac_list->vf = -1; 37308c2ecf20Sopenharmony_ci mac_list->free = true; 37318c2ecf20Sopenharmony_ci list_add(&mac_list->l, &adapter->vf_macs.l); 37328c2ecf20Sopenharmony_ci mac_list++; 37338c2ecf20Sopenharmony_ci } 37348c2ecf20Sopenharmony_ci } else { 37358c2ecf20Sopenharmony_ci /* If we could not allocate memory for the VF MAC filters 37368c2ecf20Sopenharmony_ci * we can continue without this feature but warn user. 37378c2ecf20Sopenharmony_ci */ 37388c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 37398c2ecf20Sopenharmony_ci "Unable to allocate memory for VF MAC filter list\n"); 37408c2ecf20Sopenharmony_ci } 37418c2ecf20Sopenharmony_ci 37428c2ecf20Sopenharmony_ci /* only call pci_enable_sriov() if no VFs are allocated already */ 37438c2ecf20Sopenharmony_ci if (!old_vfs) { 37448c2ecf20Sopenharmony_ci err = pci_enable_sriov(pdev, adapter->vfs_allocated_count); 37458c2ecf20Sopenharmony_ci if (err) 37468c2ecf20Sopenharmony_ci goto err_out; 37478c2ecf20Sopenharmony_ci } 37488c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "%d VFs allocated\n", 37498c2ecf20Sopenharmony_ci adapter->vfs_allocated_count); 37508c2ecf20Sopenharmony_ci for (i = 0; i < adapter->vfs_allocated_count; i++) 37518c2ecf20Sopenharmony_ci igb_vf_configure(adapter, i); 37528c2ecf20Sopenharmony_ci 37538c2ecf20Sopenharmony_ci /* DMA Coalescing is not supported in IOV mode. */ 37548c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_DMAC; 37558c2ecf20Sopenharmony_ci goto out; 37568c2ecf20Sopenharmony_ci 37578c2ecf20Sopenharmony_cierr_out: 37588c2ecf20Sopenharmony_ci kfree(adapter->vf_mac_list); 37598c2ecf20Sopenharmony_ci adapter->vf_mac_list = NULL; 37608c2ecf20Sopenharmony_ci kfree(adapter->vf_data); 37618c2ecf20Sopenharmony_ci adapter->vf_data = NULL; 37628c2ecf20Sopenharmony_ci adapter->vfs_allocated_count = 0; 37638c2ecf20Sopenharmony_ciout: 37648c2ecf20Sopenharmony_ci return err; 37658c2ecf20Sopenharmony_ci} 37668c2ecf20Sopenharmony_ci 37678c2ecf20Sopenharmony_ci#endif 37688c2ecf20Sopenharmony_ci/** 37698c2ecf20Sopenharmony_ci * igb_remove_i2c - Cleanup I2C interface 37708c2ecf20Sopenharmony_ci * @adapter: pointer to adapter structure 37718c2ecf20Sopenharmony_ci **/ 37728c2ecf20Sopenharmony_cistatic void igb_remove_i2c(struct igb_adapter *adapter) 37738c2ecf20Sopenharmony_ci{ 37748c2ecf20Sopenharmony_ci /* free the adapter bus structure */ 37758c2ecf20Sopenharmony_ci i2c_del_adapter(&adapter->i2c_adap); 37768c2ecf20Sopenharmony_ci} 37778c2ecf20Sopenharmony_ci 37788c2ecf20Sopenharmony_ci/** 37798c2ecf20Sopenharmony_ci * igb_remove - Device Removal Routine 37808c2ecf20Sopenharmony_ci * @pdev: PCI device information struct 37818c2ecf20Sopenharmony_ci * 37828c2ecf20Sopenharmony_ci * igb_remove is called by the PCI subsystem to alert the driver 37838c2ecf20Sopenharmony_ci * that it should release a PCI device. The could be caused by a 37848c2ecf20Sopenharmony_ci * Hot-Plug event, or because the driver is going to be removed from 37858c2ecf20Sopenharmony_ci * memory. 37868c2ecf20Sopenharmony_ci **/ 37878c2ecf20Sopenharmony_cistatic void igb_remove(struct pci_dev *pdev) 37888c2ecf20Sopenharmony_ci{ 37898c2ecf20Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 37908c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 37918c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 37928c2ecf20Sopenharmony_ci 37938c2ecf20Sopenharmony_ci pm_runtime_get_noresume(&pdev->dev); 37948c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_HWMON 37958c2ecf20Sopenharmony_ci igb_sysfs_exit(adapter); 37968c2ecf20Sopenharmony_ci#endif 37978c2ecf20Sopenharmony_ci igb_remove_i2c(adapter); 37988c2ecf20Sopenharmony_ci igb_ptp_stop(adapter); 37998c2ecf20Sopenharmony_ci /* The watchdog timer may be rescheduled, so explicitly 38008c2ecf20Sopenharmony_ci * disable watchdog from being rescheduled. 38018c2ecf20Sopenharmony_ci */ 38028c2ecf20Sopenharmony_ci set_bit(__IGB_DOWN, &adapter->state); 38038c2ecf20Sopenharmony_ci del_timer_sync(&adapter->watchdog_timer); 38048c2ecf20Sopenharmony_ci del_timer_sync(&adapter->phy_info_timer); 38058c2ecf20Sopenharmony_ci 38068c2ecf20Sopenharmony_ci cancel_work_sync(&adapter->reset_task); 38078c2ecf20Sopenharmony_ci cancel_work_sync(&adapter->watchdog_task); 38088c2ecf20Sopenharmony_ci 38098c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_DCA 38108c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_DCA_ENABLED) { 38118c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "DCA disabled\n"); 38128c2ecf20Sopenharmony_ci dca_remove_requester(&pdev->dev); 38138c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_DCA_ENABLED; 38148c2ecf20Sopenharmony_ci wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_DISABLE); 38158c2ecf20Sopenharmony_ci } 38168c2ecf20Sopenharmony_ci#endif 38178c2ecf20Sopenharmony_ci 38188c2ecf20Sopenharmony_ci /* Release control of h/w to f/w. If f/w is AMT enabled, this 38198c2ecf20Sopenharmony_ci * would have already happened in close and is redundant. 38208c2ecf20Sopenharmony_ci */ 38218c2ecf20Sopenharmony_ci igb_release_hw_control(adapter); 38228c2ecf20Sopenharmony_ci 38238c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 38248c2ecf20Sopenharmony_ci igb_disable_sriov(pdev); 38258c2ecf20Sopenharmony_ci#endif 38268c2ecf20Sopenharmony_ci 38278c2ecf20Sopenharmony_ci unregister_netdev(netdev); 38288c2ecf20Sopenharmony_ci 38298c2ecf20Sopenharmony_ci igb_clear_interrupt_scheme(adapter); 38308c2ecf20Sopenharmony_ci 38318c2ecf20Sopenharmony_ci pci_iounmap(pdev, adapter->io_addr); 38328c2ecf20Sopenharmony_ci if (hw->flash_address) 38338c2ecf20Sopenharmony_ci iounmap(hw->flash_address); 38348c2ecf20Sopenharmony_ci pci_release_mem_regions(pdev); 38358c2ecf20Sopenharmony_ci 38368c2ecf20Sopenharmony_ci kfree(adapter->mac_table); 38378c2ecf20Sopenharmony_ci kfree(adapter->shadow_vfta); 38388c2ecf20Sopenharmony_ci free_netdev(netdev); 38398c2ecf20Sopenharmony_ci 38408c2ecf20Sopenharmony_ci pci_disable_pcie_error_reporting(pdev); 38418c2ecf20Sopenharmony_ci 38428c2ecf20Sopenharmony_ci pci_disable_device(pdev); 38438c2ecf20Sopenharmony_ci} 38448c2ecf20Sopenharmony_ci 38458c2ecf20Sopenharmony_ci/** 38468c2ecf20Sopenharmony_ci * igb_probe_vfs - Initialize vf data storage and add VFs to pci config space 38478c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 38488c2ecf20Sopenharmony_ci * 38498c2ecf20Sopenharmony_ci * This function initializes the vf specific data storage and then attempts to 38508c2ecf20Sopenharmony_ci * allocate the VFs. The reason for ordering it this way is because it is much 38518c2ecf20Sopenharmony_ci * mor expensive time wise to disable SR-IOV than it is to allocate and free 38528c2ecf20Sopenharmony_ci * the memory for the VFs. 38538c2ecf20Sopenharmony_ci **/ 38548c2ecf20Sopenharmony_cistatic void igb_probe_vfs(struct igb_adapter *adapter) 38558c2ecf20Sopenharmony_ci{ 38568c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 38578c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 38588c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 38598c2ecf20Sopenharmony_ci 38608c2ecf20Sopenharmony_ci /* Virtualization features not supported on i210 and 82580 family. */ 38618c2ecf20Sopenharmony_ci if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211) || 38628c2ecf20Sopenharmony_ci (hw->mac.type == e1000_82580)) 38638c2ecf20Sopenharmony_ci return; 38648c2ecf20Sopenharmony_ci 38658c2ecf20Sopenharmony_ci /* Of the below we really only want the effect of getting 38668c2ecf20Sopenharmony_ci * IGB_FLAG_HAS_MSIX set (if available), without which 38678c2ecf20Sopenharmony_ci * igb_enable_sriov() has no effect. 38688c2ecf20Sopenharmony_ci */ 38698c2ecf20Sopenharmony_ci igb_set_interrupt_capability(adapter, true); 38708c2ecf20Sopenharmony_ci igb_reset_interrupt_capability(adapter); 38718c2ecf20Sopenharmony_ci 38728c2ecf20Sopenharmony_ci pci_sriov_set_totalvfs(pdev, 7); 38738c2ecf20Sopenharmony_ci igb_enable_sriov(pdev, max_vfs); 38748c2ecf20Sopenharmony_ci 38758c2ecf20Sopenharmony_ci#endif /* CONFIG_PCI_IOV */ 38768c2ecf20Sopenharmony_ci} 38778c2ecf20Sopenharmony_ci 38788c2ecf20Sopenharmony_ciunsigned int igb_get_max_rss_queues(struct igb_adapter *adapter) 38798c2ecf20Sopenharmony_ci{ 38808c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 38818c2ecf20Sopenharmony_ci unsigned int max_rss_queues; 38828c2ecf20Sopenharmony_ci 38838c2ecf20Sopenharmony_ci /* Determine the maximum number of RSS queues supported. */ 38848c2ecf20Sopenharmony_ci switch (hw->mac.type) { 38858c2ecf20Sopenharmony_ci case e1000_i211: 38868c2ecf20Sopenharmony_ci max_rss_queues = IGB_MAX_RX_QUEUES_I211; 38878c2ecf20Sopenharmony_ci break; 38888c2ecf20Sopenharmony_ci case e1000_82575: 38898c2ecf20Sopenharmony_ci case e1000_i210: 38908c2ecf20Sopenharmony_ci max_rss_queues = IGB_MAX_RX_QUEUES_82575; 38918c2ecf20Sopenharmony_ci break; 38928c2ecf20Sopenharmony_ci case e1000_i350: 38938c2ecf20Sopenharmony_ci /* I350 cannot do RSS and SR-IOV at the same time */ 38948c2ecf20Sopenharmony_ci if (!!adapter->vfs_allocated_count) { 38958c2ecf20Sopenharmony_ci max_rss_queues = 1; 38968c2ecf20Sopenharmony_ci break; 38978c2ecf20Sopenharmony_ci } 38988c2ecf20Sopenharmony_ci fallthrough; 38998c2ecf20Sopenharmony_ci case e1000_82576: 39008c2ecf20Sopenharmony_ci if (!!adapter->vfs_allocated_count) { 39018c2ecf20Sopenharmony_ci max_rss_queues = 2; 39028c2ecf20Sopenharmony_ci break; 39038c2ecf20Sopenharmony_ci } 39048c2ecf20Sopenharmony_ci fallthrough; 39058c2ecf20Sopenharmony_ci case e1000_82580: 39068c2ecf20Sopenharmony_ci case e1000_i354: 39078c2ecf20Sopenharmony_ci default: 39088c2ecf20Sopenharmony_ci max_rss_queues = IGB_MAX_RX_QUEUES; 39098c2ecf20Sopenharmony_ci break; 39108c2ecf20Sopenharmony_ci } 39118c2ecf20Sopenharmony_ci 39128c2ecf20Sopenharmony_ci return max_rss_queues; 39138c2ecf20Sopenharmony_ci} 39148c2ecf20Sopenharmony_ci 39158c2ecf20Sopenharmony_cistatic void igb_init_queue_configuration(struct igb_adapter *adapter) 39168c2ecf20Sopenharmony_ci{ 39178c2ecf20Sopenharmony_ci u32 max_rss_queues; 39188c2ecf20Sopenharmony_ci 39198c2ecf20Sopenharmony_ci max_rss_queues = igb_get_max_rss_queues(adapter); 39208c2ecf20Sopenharmony_ci adapter->rss_queues = min_t(u32, max_rss_queues, num_online_cpus()); 39218c2ecf20Sopenharmony_ci 39228c2ecf20Sopenharmony_ci igb_set_flag_queue_pairs(adapter, max_rss_queues); 39238c2ecf20Sopenharmony_ci} 39248c2ecf20Sopenharmony_ci 39258c2ecf20Sopenharmony_civoid igb_set_flag_queue_pairs(struct igb_adapter *adapter, 39268c2ecf20Sopenharmony_ci const u32 max_rss_queues) 39278c2ecf20Sopenharmony_ci{ 39288c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 39298c2ecf20Sopenharmony_ci 39308c2ecf20Sopenharmony_ci /* Determine if we need to pair queues. */ 39318c2ecf20Sopenharmony_ci switch (hw->mac.type) { 39328c2ecf20Sopenharmony_ci case e1000_82575: 39338c2ecf20Sopenharmony_ci case e1000_i211: 39348c2ecf20Sopenharmony_ci /* Device supports enough interrupts without queue pairing. */ 39358c2ecf20Sopenharmony_ci break; 39368c2ecf20Sopenharmony_ci case e1000_82576: 39378c2ecf20Sopenharmony_ci case e1000_82580: 39388c2ecf20Sopenharmony_ci case e1000_i350: 39398c2ecf20Sopenharmony_ci case e1000_i354: 39408c2ecf20Sopenharmony_ci case e1000_i210: 39418c2ecf20Sopenharmony_ci default: 39428c2ecf20Sopenharmony_ci /* If rss_queues > half of max_rss_queues, pair the queues in 39438c2ecf20Sopenharmony_ci * order to conserve interrupts due to limited supply. 39448c2ecf20Sopenharmony_ci */ 39458c2ecf20Sopenharmony_ci if (adapter->rss_queues > (max_rss_queues / 2)) 39468c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_QUEUE_PAIRS; 39478c2ecf20Sopenharmony_ci else 39488c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_QUEUE_PAIRS; 39498c2ecf20Sopenharmony_ci break; 39508c2ecf20Sopenharmony_ci } 39518c2ecf20Sopenharmony_ci} 39528c2ecf20Sopenharmony_ci 39538c2ecf20Sopenharmony_ci/** 39548c2ecf20Sopenharmony_ci * igb_sw_init - Initialize general software structures (struct igb_adapter) 39558c2ecf20Sopenharmony_ci * @adapter: board private structure to initialize 39568c2ecf20Sopenharmony_ci * 39578c2ecf20Sopenharmony_ci * igb_sw_init initializes the Adapter private data structure. 39588c2ecf20Sopenharmony_ci * Fields are initialized based on PCI device information and 39598c2ecf20Sopenharmony_ci * OS network device settings (MTU size). 39608c2ecf20Sopenharmony_ci **/ 39618c2ecf20Sopenharmony_cistatic int igb_sw_init(struct igb_adapter *adapter) 39628c2ecf20Sopenharmony_ci{ 39638c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 39648c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 39658c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 39668c2ecf20Sopenharmony_ci 39678c2ecf20Sopenharmony_ci pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); 39688c2ecf20Sopenharmony_ci 39698c2ecf20Sopenharmony_ci /* set default ring sizes */ 39708c2ecf20Sopenharmony_ci adapter->tx_ring_count = IGB_DEFAULT_TXD; 39718c2ecf20Sopenharmony_ci adapter->rx_ring_count = IGB_DEFAULT_RXD; 39728c2ecf20Sopenharmony_ci 39738c2ecf20Sopenharmony_ci /* set default ITR values */ 39748c2ecf20Sopenharmony_ci adapter->rx_itr_setting = IGB_DEFAULT_ITR; 39758c2ecf20Sopenharmony_ci adapter->tx_itr_setting = IGB_DEFAULT_ITR; 39768c2ecf20Sopenharmony_ci 39778c2ecf20Sopenharmony_ci /* set default work limits */ 39788c2ecf20Sopenharmony_ci adapter->tx_work_limit = IGB_DEFAULT_TX_WORK; 39798c2ecf20Sopenharmony_ci 39808c2ecf20Sopenharmony_ci adapter->max_frame_size = netdev->mtu + IGB_ETH_PKT_HDR_PAD; 39818c2ecf20Sopenharmony_ci adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; 39828c2ecf20Sopenharmony_ci 39838c2ecf20Sopenharmony_ci spin_lock_init(&adapter->nfc_lock); 39848c2ecf20Sopenharmony_ci spin_lock_init(&adapter->stats64_lock); 39858c2ecf20Sopenharmony_ci 39868c2ecf20Sopenharmony_ci /* init spinlock to avoid concurrency of VF resources */ 39878c2ecf20Sopenharmony_ci spin_lock_init(&adapter->vfs_lock); 39888c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 39898c2ecf20Sopenharmony_ci switch (hw->mac.type) { 39908c2ecf20Sopenharmony_ci case e1000_82576: 39918c2ecf20Sopenharmony_ci case e1000_i350: 39928c2ecf20Sopenharmony_ci if (max_vfs > 7) { 39938c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, 39948c2ecf20Sopenharmony_ci "Maximum of 7 VFs per PF, using max\n"); 39958c2ecf20Sopenharmony_ci max_vfs = adapter->vfs_allocated_count = 7; 39968c2ecf20Sopenharmony_ci } else 39978c2ecf20Sopenharmony_ci adapter->vfs_allocated_count = max_vfs; 39988c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count) 39998c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, 40008c2ecf20Sopenharmony_ci "Enabling SR-IOV VFs using the module parameter is deprecated - please use the pci sysfs interface.\n"); 40018c2ecf20Sopenharmony_ci break; 40028c2ecf20Sopenharmony_ci default: 40038c2ecf20Sopenharmony_ci break; 40048c2ecf20Sopenharmony_ci } 40058c2ecf20Sopenharmony_ci#endif /* CONFIG_PCI_IOV */ 40068c2ecf20Sopenharmony_ci 40078c2ecf20Sopenharmony_ci /* Assume MSI-X interrupts, will be checked during IRQ allocation */ 40088c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_HAS_MSIX; 40098c2ecf20Sopenharmony_ci 40108c2ecf20Sopenharmony_ci adapter->mac_table = kcalloc(hw->mac.rar_entry_count, 40118c2ecf20Sopenharmony_ci sizeof(struct igb_mac_addr), 40128c2ecf20Sopenharmony_ci GFP_KERNEL); 40138c2ecf20Sopenharmony_ci if (!adapter->mac_table) 40148c2ecf20Sopenharmony_ci return -ENOMEM; 40158c2ecf20Sopenharmony_ci 40168c2ecf20Sopenharmony_ci igb_probe_vfs(adapter); 40178c2ecf20Sopenharmony_ci 40188c2ecf20Sopenharmony_ci igb_init_queue_configuration(adapter); 40198c2ecf20Sopenharmony_ci 40208c2ecf20Sopenharmony_ci /* Setup and initialize a copy of the hw vlan table array */ 40218c2ecf20Sopenharmony_ci adapter->shadow_vfta = kcalloc(E1000_VLAN_FILTER_TBL_SIZE, sizeof(u32), 40228c2ecf20Sopenharmony_ci GFP_KERNEL); 40238c2ecf20Sopenharmony_ci if (!adapter->shadow_vfta) 40248c2ecf20Sopenharmony_ci return -ENOMEM; 40258c2ecf20Sopenharmony_ci 40268c2ecf20Sopenharmony_ci /* This call may decrease the number of queues */ 40278c2ecf20Sopenharmony_ci if (igb_init_interrupt_scheme(adapter, true)) { 40288c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); 40298c2ecf20Sopenharmony_ci return -ENOMEM; 40308c2ecf20Sopenharmony_ci } 40318c2ecf20Sopenharmony_ci 40328c2ecf20Sopenharmony_ci /* Explicitly disable IRQ since the NIC can be in any state. */ 40338c2ecf20Sopenharmony_ci igb_irq_disable(adapter); 40348c2ecf20Sopenharmony_ci 40358c2ecf20Sopenharmony_ci if (hw->mac.type >= e1000_i350) 40368c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_DMAC; 40378c2ecf20Sopenharmony_ci 40388c2ecf20Sopenharmony_ci set_bit(__IGB_DOWN, &adapter->state); 40398c2ecf20Sopenharmony_ci return 0; 40408c2ecf20Sopenharmony_ci} 40418c2ecf20Sopenharmony_ci 40428c2ecf20Sopenharmony_ci/** 40438c2ecf20Sopenharmony_ci * igb_open - Called when a network interface is made active 40448c2ecf20Sopenharmony_ci * @netdev: network interface device structure 40458c2ecf20Sopenharmony_ci * @resuming: indicates whether we are in a resume call 40468c2ecf20Sopenharmony_ci * 40478c2ecf20Sopenharmony_ci * Returns 0 on success, negative value on failure 40488c2ecf20Sopenharmony_ci * 40498c2ecf20Sopenharmony_ci * The open entry point is called when a network interface is made 40508c2ecf20Sopenharmony_ci * active by the system (IFF_UP). At this point all resources needed 40518c2ecf20Sopenharmony_ci * for transmit and receive operations are allocated, the interrupt 40528c2ecf20Sopenharmony_ci * handler is registered with the OS, the watchdog timer is started, 40538c2ecf20Sopenharmony_ci * and the stack is notified that the interface is ready. 40548c2ecf20Sopenharmony_ci **/ 40558c2ecf20Sopenharmony_cistatic int __igb_open(struct net_device *netdev, bool resuming) 40568c2ecf20Sopenharmony_ci{ 40578c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 40588c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 40598c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 40608c2ecf20Sopenharmony_ci int err; 40618c2ecf20Sopenharmony_ci int i; 40628c2ecf20Sopenharmony_ci 40638c2ecf20Sopenharmony_ci /* disallow open during test */ 40648c2ecf20Sopenharmony_ci if (test_bit(__IGB_TESTING, &adapter->state)) { 40658c2ecf20Sopenharmony_ci WARN_ON(resuming); 40668c2ecf20Sopenharmony_ci return -EBUSY; 40678c2ecf20Sopenharmony_ci } 40688c2ecf20Sopenharmony_ci 40698c2ecf20Sopenharmony_ci if (!resuming) 40708c2ecf20Sopenharmony_ci pm_runtime_get_sync(&pdev->dev); 40718c2ecf20Sopenharmony_ci 40728c2ecf20Sopenharmony_ci netif_carrier_off(netdev); 40738c2ecf20Sopenharmony_ci 40748c2ecf20Sopenharmony_ci /* allocate transmit descriptors */ 40758c2ecf20Sopenharmony_ci err = igb_setup_all_tx_resources(adapter); 40768c2ecf20Sopenharmony_ci if (err) 40778c2ecf20Sopenharmony_ci goto err_setup_tx; 40788c2ecf20Sopenharmony_ci 40798c2ecf20Sopenharmony_ci /* allocate receive descriptors */ 40808c2ecf20Sopenharmony_ci err = igb_setup_all_rx_resources(adapter); 40818c2ecf20Sopenharmony_ci if (err) 40828c2ecf20Sopenharmony_ci goto err_setup_rx; 40838c2ecf20Sopenharmony_ci 40848c2ecf20Sopenharmony_ci igb_power_up_link(adapter); 40858c2ecf20Sopenharmony_ci 40868c2ecf20Sopenharmony_ci /* before we allocate an interrupt, we must be ready to handle it. 40878c2ecf20Sopenharmony_ci * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt 40888c2ecf20Sopenharmony_ci * as soon as we call pci_request_irq, so we have to setup our 40898c2ecf20Sopenharmony_ci * clean_rx handler before we do so. 40908c2ecf20Sopenharmony_ci */ 40918c2ecf20Sopenharmony_ci igb_configure(adapter); 40928c2ecf20Sopenharmony_ci 40938c2ecf20Sopenharmony_ci err = igb_request_irq(adapter); 40948c2ecf20Sopenharmony_ci if (err) 40958c2ecf20Sopenharmony_ci goto err_req_irq; 40968c2ecf20Sopenharmony_ci 40978c2ecf20Sopenharmony_ci /* Notify the stack of the actual queue counts. */ 40988c2ecf20Sopenharmony_ci err = netif_set_real_num_tx_queues(adapter->netdev, 40998c2ecf20Sopenharmony_ci adapter->num_tx_queues); 41008c2ecf20Sopenharmony_ci if (err) 41018c2ecf20Sopenharmony_ci goto err_set_queues; 41028c2ecf20Sopenharmony_ci 41038c2ecf20Sopenharmony_ci err = netif_set_real_num_rx_queues(adapter->netdev, 41048c2ecf20Sopenharmony_ci adapter->num_rx_queues); 41058c2ecf20Sopenharmony_ci if (err) 41068c2ecf20Sopenharmony_ci goto err_set_queues; 41078c2ecf20Sopenharmony_ci 41088c2ecf20Sopenharmony_ci /* From here on the code is the same as igb_up() */ 41098c2ecf20Sopenharmony_ci clear_bit(__IGB_DOWN, &adapter->state); 41108c2ecf20Sopenharmony_ci 41118c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) 41128c2ecf20Sopenharmony_ci napi_enable(&(adapter->q_vector[i]->napi)); 41138c2ecf20Sopenharmony_ci 41148c2ecf20Sopenharmony_ci /* Clear any pending interrupts. */ 41158c2ecf20Sopenharmony_ci rd32(E1000_TSICR); 41168c2ecf20Sopenharmony_ci rd32(E1000_ICR); 41178c2ecf20Sopenharmony_ci 41188c2ecf20Sopenharmony_ci igb_irq_enable(adapter); 41198c2ecf20Sopenharmony_ci 41208c2ecf20Sopenharmony_ci /* notify VFs that reset has been completed */ 41218c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count) { 41228c2ecf20Sopenharmony_ci u32 reg_data = rd32(E1000_CTRL_EXT); 41238c2ecf20Sopenharmony_ci 41248c2ecf20Sopenharmony_ci reg_data |= E1000_CTRL_EXT_PFRSTD; 41258c2ecf20Sopenharmony_ci wr32(E1000_CTRL_EXT, reg_data); 41268c2ecf20Sopenharmony_ci } 41278c2ecf20Sopenharmony_ci 41288c2ecf20Sopenharmony_ci netif_tx_start_all_queues(netdev); 41298c2ecf20Sopenharmony_ci 41308c2ecf20Sopenharmony_ci if (!resuming) 41318c2ecf20Sopenharmony_ci pm_runtime_put(&pdev->dev); 41328c2ecf20Sopenharmony_ci 41338c2ecf20Sopenharmony_ci /* start the watchdog. */ 41348c2ecf20Sopenharmony_ci hw->mac.get_link_status = 1; 41358c2ecf20Sopenharmony_ci schedule_work(&adapter->watchdog_task); 41368c2ecf20Sopenharmony_ci 41378c2ecf20Sopenharmony_ci return 0; 41388c2ecf20Sopenharmony_ci 41398c2ecf20Sopenharmony_cierr_set_queues: 41408c2ecf20Sopenharmony_ci igb_free_irq(adapter); 41418c2ecf20Sopenharmony_cierr_req_irq: 41428c2ecf20Sopenharmony_ci igb_release_hw_control(adapter); 41438c2ecf20Sopenharmony_ci igb_power_down_link(adapter); 41448c2ecf20Sopenharmony_ci igb_free_all_rx_resources(adapter); 41458c2ecf20Sopenharmony_cierr_setup_rx: 41468c2ecf20Sopenharmony_ci igb_free_all_tx_resources(adapter); 41478c2ecf20Sopenharmony_cierr_setup_tx: 41488c2ecf20Sopenharmony_ci igb_reset(adapter); 41498c2ecf20Sopenharmony_ci if (!resuming) 41508c2ecf20Sopenharmony_ci pm_runtime_put(&pdev->dev); 41518c2ecf20Sopenharmony_ci 41528c2ecf20Sopenharmony_ci return err; 41538c2ecf20Sopenharmony_ci} 41548c2ecf20Sopenharmony_ci 41558c2ecf20Sopenharmony_ciint igb_open(struct net_device *netdev) 41568c2ecf20Sopenharmony_ci{ 41578c2ecf20Sopenharmony_ci return __igb_open(netdev, false); 41588c2ecf20Sopenharmony_ci} 41598c2ecf20Sopenharmony_ci 41608c2ecf20Sopenharmony_ci/** 41618c2ecf20Sopenharmony_ci * igb_close - Disables a network interface 41628c2ecf20Sopenharmony_ci * @netdev: network interface device structure 41638c2ecf20Sopenharmony_ci * @suspending: indicates we are in a suspend call 41648c2ecf20Sopenharmony_ci * 41658c2ecf20Sopenharmony_ci * Returns 0, this is not allowed to fail 41668c2ecf20Sopenharmony_ci * 41678c2ecf20Sopenharmony_ci * The close entry point is called when an interface is de-activated 41688c2ecf20Sopenharmony_ci * by the OS. The hardware is still under the driver's control, but 41698c2ecf20Sopenharmony_ci * needs to be disabled. A global MAC reset is issued to stop the 41708c2ecf20Sopenharmony_ci * hardware, and all transmit and receive resources are freed. 41718c2ecf20Sopenharmony_ci **/ 41728c2ecf20Sopenharmony_cistatic int __igb_close(struct net_device *netdev, bool suspending) 41738c2ecf20Sopenharmony_ci{ 41748c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 41758c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 41768c2ecf20Sopenharmony_ci 41778c2ecf20Sopenharmony_ci WARN_ON(test_bit(__IGB_RESETTING, &adapter->state)); 41788c2ecf20Sopenharmony_ci 41798c2ecf20Sopenharmony_ci if (!suspending) 41808c2ecf20Sopenharmony_ci pm_runtime_get_sync(&pdev->dev); 41818c2ecf20Sopenharmony_ci 41828c2ecf20Sopenharmony_ci igb_down(adapter); 41838c2ecf20Sopenharmony_ci igb_free_irq(adapter); 41848c2ecf20Sopenharmony_ci 41858c2ecf20Sopenharmony_ci igb_free_all_tx_resources(adapter); 41868c2ecf20Sopenharmony_ci igb_free_all_rx_resources(adapter); 41878c2ecf20Sopenharmony_ci 41888c2ecf20Sopenharmony_ci if (!suspending) 41898c2ecf20Sopenharmony_ci pm_runtime_put_sync(&pdev->dev); 41908c2ecf20Sopenharmony_ci return 0; 41918c2ecf20Sopenharmony_ci} 41928c2ecf20Sopenharmony_ci 41938c2ecf20Sopenharmony_ciint igb_close(struct net_device *netdev) 41948c2ecf20Sopenharmony_ci{ 41958c2ecf20Sopenharmony_ci if (netif_device_present(netdev) || netdev->dismantle) 41968c2ecf20Sopenharmony_ci return __igb_close(netdev, false); 41978c2ecf20Sopenharmony_ci return 0; 41988c2ecf20Sopenharmony_ci} 41998c2ecf20Sopenharmony_ci 42008c2ecf20Sopenharmony_ci/** 42018c2ecf20Sopenharmony_ci * igb_setup_tx_resources - allocate Tx resources (Descriptors) 42028c2ecf20Sopenharmony_ci * @tx_ring: tx descriptor ring (for a specific queue) to setup 42038c2ecf20Sopenharmony_ci * 42048c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure 42058c2ecf20Sopenharmony_ci **/ 42068c2ecf20Sopenharmony_ciint igb_setup_tx_resources(struct igb_ring *tx_ring) 42078c2ecf20Sopenharmony_ci{ 42088c2ecf20Sopenharmony_ci struct device *dev = tx_ring->dev; 42098c2ecf20Sopenharmony_ci int size; 42108c2ecf20Sopenharmony_ci 42118c2ecf20Sopenharmony_ci size = sizeof(struct igb_tx_buffer) * tx_ring->count; 42128c2ecf20Sopenharmony_ci 42138c2ecf20Sopenharmony_ci tx_ring->tx_buffer_info = vmalloc(size); 42148c2ecf20Sopenharmony_ci if (!tx_ring->tx_buffer_info) 42158c2ecf20Sopenharmony_ci goto err; 42168c2ecf20Sopenharmony_ci 42178c2ecf20Sopenharmony_ci /* round up to nearest 4K */ 42188c2ecf20Sopenharmony_ci tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc); 42198c2ecf20Sopenharmony_ci tx_ring->size = ALIGN(tx_ring->size, 4096); 42208c2ecf20Sopenharmony_ci 42218c2ecf20Sopenharmony_ci tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size, 42228c2ecf20Sopenharmony_ci &tx_ring->dma, GFP_KERNEL); 42238c2ecf20Sopenharmony_ci if (!tx_ring->desc) 42248c2ecf20Sopenharmony_ci goto err; 42258c2ecf20Sopenharmony_ci 42268c2ecf20Sopenharmony_ci tx_ring->next_to_use = 0; 42278c2ecf20Sopenharmony_ci tx_ring->next_to_clean = 0; 42288c2ecf20Sopenharmony_ci 42298c2ecf20Sopenharmony_ci return 0; 42308c2ecf20Sopenharmony_ci 42318c2ecf20Sopenharmony_cierr: 42328c2ecf20Sopenharmony_ci vfree(tx_ring->tx_buffer_info); 42338c2ecf20Sopenharmony_ci tx_ring->tx_buffer_info = NULL; 42348c2ecf20Sopenharmony_ci dev_err(dev, "Unable to allocate memory for the Tx descriptor ring\n"); 42358c2ecf20Sopenharmony_ci return -ENOMEM; 42368c2ecf20Sopenharmony_ci} 42378c2ecf20Sopenharmony_ci 42388c2ecf20Sopenharmony_ci/** 42398c2ecf20Sopenharmony_ci * igb_setup_all_tx_resources - wrapper to allocate Tx resources 42408c2ecf20Sopenharmony_ci * (Descriptors) for all queues 42418c2ecf20Sopenharmony_ci * @adapter: board private structure 42428c2ecf20Sopenharmony_ci * 42438c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure 42448c2ecf20Sopenharmony_ci **/ 42458c2ecf20Sopenharmony_cistatic int igb_setup_all_tx_resources(struct igb_adapter *adapter) 42468c2ecf20Sopenharmony_ci{ 42478c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 42488c2ecf20Sopenharmony_ci int i, err = 0; 42498c2ecf20Sopenharmony_ci 42508c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 42518c2ecf20Sopenharmony_ci err = igb_setup_tx_resources(adapter->tx_ring[i]); 42528c2ecf20Sopenharmony_ci if (err) { 42538c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 42548c2ecf20Sopenharmony_ci "Allocation for Tx Queue %u failed\n", i); 42558c2ecf20Sopenharmony_ci for (i--; i >= 0; i--) 42568c2ecf20Sopenharmony_ci igb_free_tx_resources(adapter->tx_ring[i]); 42578c2ecf20Sopenharmony_ci break; 42588c2ecf20Sopenharmony_ci } 42598c2ecf20Sopenharmony_ci } 42608c2ecf20Sopenharmony_ci 42618c2ecf20Sopenharmony_ci return err; 42628c2ecf20Sopenharmony_ci} 42638c2ecf20Sopenharmony_ci 42648c2ecf20Sopenharmony_ci/** 42658c2ecf20Sopenharmony_ci * igb_setup_tctl - configure the transmit control registers 42668c2ecf20Sopenharmony_ci * @adapter: Board private structure 42678c2ecf20Sopenharmony_ci **/ 42688c2ecf20Sopenharmony_civoid igb_setup_tctl(struct igb_adapter *adapter) 42698c2ecf20Sopenharmony_ci{ 42708c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 42718c2ecf20Sopenharmony_ci u32 tctl; 42728c2ecf20Sopenharmony_ci 42738c2ecf20Sopenharmony_ci /* disable queue 0 which is enabled by default on 82575 and 82576 */ 42748c2ecf20Sopenharmony_ci wr32(E1000_TXDCTL(0), 0); 42758c2ecf20Sopenharmony_ci 42768c2ecf20Sopenharmony_ci /* Program the Transmit Control Register */ 42778c2ecf20Sopenharmony_ci tctl = rd32(E1000_TCTL); 42788c2ecf20Sopenharmony_ci tctl &= ~E1000_TCTL_CT; 42798c2ecf20Sopenharmony_ci tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | 42808c2ecf20Sopenharmony_ci (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); 42818c2ecf20Sopenharmony_ci 42828c2ecf20Sopenharmony_ci igb_config_collision_dist(hw); 42838c2ecf20Sopenharmony_ci 42848c2ecf20Sopenharmony_ci /* Enable transmits */ 42858c2ecf20Sopenharmony_ci tctl |= E1000_TCTL_EN; 42868c2ecf20Sopenharmony_ci 42878c2ecf20Sopenharmony_ci wr32(E1000_TCTL, tctl); 42888c2ecf20Sopenharmony_ci} 42898c2ecf20Sopenharmony_ci 42908c2ecf20Sopenharmony_ci/** 42918c2ecf20Sopenharmony_ci * igb_configure_tx_ring - Configure transmit ring after Reset 42928c2ecf20Sopenharmony_ci * @adapter: board private structure 42938c2ecf20Sopenharmony_ci * @ring: tx ring to configure 42948c2ecf20Sopenharmony_ci * 42958c2ecf20Sopenharmony_ci * Configure a transmit ring after a reset. 42968c2ecf20Sopenharmony_ci **/ 42978c2ecf20Sopenharmony_civoid igb_configure_tx_ring(struct igb_adapter *adapter, 42988c2ecf20Sopenharmony_ci struct igb_ring *ring) 42998c2ecf20Sopenharmony_ci{ 43008c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 43018c2ecf20Sopenharmony_ci u32 txdctl = 0; 43028c2ecf20Sopenharmony_ci u64 tdba = ring->dma; 43038c2ecf20Sopenharmony_ci int reg_idx = ring->reg_idx; 43048c2ecf20Sopenharmony_ci 43058c2ecf20Sopenharmony_ci wr32(E1000_TDLEN(reg_idx), 43068c2ecf20Sopenharmony_ci ring->count * sizeof(union e1000_adv_tx_desc)); 43078c2ecf20Sopenharmony_ci wr32(E1000_TDBAL(reg_idx), 43088c2ecf20Sopenharmony_ci tdba & 0x00000000ffffffffULL); 43098c2ecf20Sopenharmony_ci wr32(E1000_TDBAH(reg_idx), tdba >> 32); 43108c2ecf20Sopenharmony_ci 43118c2ecf20Sopenharmony_ci ring->tail = adapter->io_addr + E1000_TDT(reg_idx); 43128c2ecf20Sopenharmony_ci wr32(E1000_TDH(reg_idx), 0); 43138c2ecf20Sopenharmony_ci writel(0, ring->tail); 43148c2ecf20Sopenharmony_ci 43158c2ecf20Sopenharmony_ci txdctl |= IGB_TX_PTHRESH; 43168c2ecf20Sopenharmony_ci txdctl |= IGB_TX_HTHRESH << 8; 43178c2ecf20Sopenharmony_ci txdctl |= IGB_TX_WTHRESH << 16; 43188c2ecf20Sopenharmony_ci 43198c2ecf20Sopenharmony_ci /* reinitialize tx_buffer_info */ 43208c2ecf20Sopenharmony_ci memset(ring->tx_buffer_info, 0, 43218c2ecf20Sopenharmony_ci sizeof(struct igb_tx_buffer) * ring->count); 43228c2ecf20Sopenharmony_ci 43238c2ecf20Sopenharmony_ci txdctl |= E1000_TXDCTL_QUEUE_ENABLE; 43248c2ecf20Sopenharmony_ci wr32(E1000_TXDCTL(reg_idx), txdctl); 43258c2ecf20Sopenharmony_ci} 43268c2ecf20Sopenharmony_ci 43278c2ecf20Sopenharmony_ci/** 43288c2ecf20Sopenharmony_ci * igb_configure_tx - Configure transmit Unit after Reset 43298c2ecf20Sopenharmony_ci * @adapter: board private structure 43308c2ecf20Sopenharmony_ci * 43318c2ecf20Sopenharmony_ci * Configure the Tx unit of the MAC after a reset. 43328c2ecf20Sopenharmony_ci **/ 43338c2ecf20Sopenharmony_cistatic void igb_configure_tx(struct igb_adapter *adapter) 43348c2ecf20Sopenharmony_ci{ 43358c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 43368c2ecf20Sopenharmony_ci int i; 43378c2ecf20Sopenharmony_ci 43388c2ecf20Sopenharmony_ci /* disable the queues */ 43398c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 43408c2ecf20Sopenharmony_ci wr32(E1000_TXDCTL(adapter->tx_ring[i]->reg_idx), 0); 43418c2ecf20Sopenharmony_ci 43428c2ecf20Sopenharmony_ci wrfl(); 43438c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 43448c2ecf20Sopenharmony_ci 43458c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 43468c2ecf20Sopenharmony_ci igb_configure_tx_ring(adapter, adapter->tx_ring[i]); 43478c2ecf20Sopenharmony_ci} 43488c2ecf20Sopenharmony_ci 43498c2ecf20Sopenharmony_ci/** 43508c2ecf20Sopenharmony_ci * igb_setup_rx_resources - allocate Rx resources (Descriptors) 43518c2ecf20Sopenharmony_ci * @rx_ring: Rx descriptor ring (for a specific queue) to setup 43528c2ecf20Sopenharmony_ci * 43538c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure 43548c2ecf20Sopenharmony_ci **/ 43558c2ecf20Sopenharmony_ciint igb_setup_rx_resources(struct igb_ring *rx_ring) 43568c2ecf20Sopenharmony_ci{ 43578c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(rx_ring->netdev); 43588c2ecf20Sopenharmony_ci struct device *dev = rx_ring->dev; 43598c2ecf20Sopenharmony_ci int size; 43608c2ecf20Sopenharmony_ci 43618c2ecf20Sopenharmony_ci size = sizeof(struct igb_rx_buffer) * rx_ring->count; 43628c2ecf20Sopenharmony_ci 43638c2ecf20Sopenharmony_ci rx_ring->rx_buffer_info = vmalloc(size); 43648c2ecf20Sopenharmony_ci if (!rx_ring->rx_buffer_info) 43658c2ecf20Sopenharmony_ci goto err; 43668c2ecf20Sopenharmony_ci 43678c2ecf20Sopenharmony_ci /* Round up to nearest 4K */ 43688c2ecf20Sopenharmony_ci rx_ring->size = rx_ring->count * sizeof(union e1000_adv_rx_desc); 43698c2ecf20Sopenharmony_ci rx_ring->size = ALIGN(rx_ring->size, 4096); 43708c2ecf20Sopenharmony_ci 43718c2ecf20Sopenharmony_ci rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size, 43728c2ecf20Sopenharmony_ci &rx_ring->dma, GFP_KERNEL); 43738c2ecf20Sopenharmony_ci if (!rx_ring->desc) 43748c2ecf20Sopenharmony_ci goto err; 43758c2ecf20Sopenharmony_ci 43768c2ecf20Sopenharmony_ci rx_ring->next_to_alloc = 0; 43778c2ecf20Sopenharmony_ci rx_ring->next_to_clean = 0; 43788c2ecf20Sopenharmony_ci rx_ring->next_to_use = 0; 43798c2ecf20Sopenharmony_ci 43808c2ecf20Sopenharmony_ci rx_ring->xdp_prog = adapter->xdp_prog; 43818c2ecf20Sopenharmony_ci 43828c2ecf20Sopenharmony_ci /* XDP RX-queue info */ 43838c2ecf20Sopenharmony_ci if (xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev, 43848c2ecf20Sopenharmony_ci rx_ring->queue_index) < 0) 43858c2ecf20Sopenharmony_ci goto err; 43868c2ecf20Sopenharmony_ci 43878c2ecf20Sopenharmony_ci return 0; 43888c2ecf20Sopenharmony_ci 43898c2ecf20Sopenharmony_cierr: 43908c2ecf20Sopenharmony_ci vfree(rx_ring->rx_buffer_info); 43918c2ecf20Sopenharmony_ci rx_ring->rx_buffer_info = NULL; 43928c2ecf20Sopenharmony_ci dev_err(dev, "Unable to allocate memory for the Rx descriptor ring\n"); 43938c2ecf20Sopenharmony_ci return -ENOMEM; 43948c2ecf20Sopenharmony_ci} 43958c2ecf20Sopenharmony_ci 43968c2ecf20Sopenharmony_ci/** 43978c2ecf20Sopenharmony_ci * igb_setup_all_rx_resources - wrapper to allocate Rx resources 43988c2ecf20Sopenharmony_ci * (Descriptors) for all queues 43998c2ecf20Sopenharmony_ci * @adapter: board private structure 44008c2ecf20Sopenharmony_ci * 44018c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure 44028c2ecf20Sopenharmony_ci **/ 44038c2ecf20Sopenharmony_cistatic int igb_setup_all_rx_resources(struct igb_adapter *adapter) 44048c2ecf20Sopenharmony_ci{ 44058c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 44068c2ecf20Sopenharmony_ci int i, err = 0; 44078c2ecf20Sopenharmony_ci 44088c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 44098c2ecf20Sopenharmony_ci err = igb_setup_rx_resources(adapter->rx_ring[i]); 44108c2ecf20Sopenharmony_ci if (err) { 44118c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 44128c2ecf20Sopenharmony_ci "Allocation for Rx Queue %u failed\n", i); 44138c2ecf20Sopenharmony_ci for (i--; i >= 0; i--) 44148c2ecf20Sopenharmony_ci igb_free_rx_resources(adapter->rx_ring[i]); 44158c2ecf20Sopenharmony_ci break; 44168c2ecf20Sopenharmony_ci } 44178c2ecf20Sopenharmony_ci } 44188c2ecf20Sopenharmony_ci 44198c2ecf20Sopenharmony_ci return err; 44208c2ecf20Sopenharmony_ci} 44218c2ecf20Sopenharmony_ci 44228c2ecf20Sopenharmony_ci/** 44238c2ecf20Sopenharmony_ci * igb_setup_mrqc - configure the multiple receive queue control registers 44248c2ecf20Sopenharmony_ci * @adapter: Board private structure 44258c2ecf20Sopenharmony_ci **/ 44268c2ecf20Sopenharmony_cistatic void igb_setup_mrqc(struct igb_adapter *adapter) 44278c2ecf20Sopenharmony_ci{ 44288c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 44298c2ecf20Sopenharmony_ci u32 mrqc, rxcsum; 44308c2ecf20Sopenharmony_ci u32 j, num_rx_queues; 44318c2ecf20Sopenharmony_ci u32 rss_key[10]; 44328c2ecf20Sopenharmony_ci 44338c2ecf20Sopenharmony_ci netdev_rss_key_fill(rss_key, sizeof(rss_key)); 44348c2ecf20Sopenharmony_ci for (j = 0; j < 10; j++) 44358c2ecf20Sopenharmony_ci wr32(E1000_RSSRK(j), rss_key[j]); 44368c2ecf20Sopenharmony_ci 44378c2ecf20Sopenharmony_ci num_rx_queues = adapter->rss_queues; 44388c2ecf20Sopenharmony_ci 44398c2ecf20Sopenharmony_ci switch (hw->mac.type) { 44408c2ecf20Sopenharmony_ci case e1000_82576: 44418c2ecf20Sopenharmony_ci /* 82576 supports 2 RSS queues for SR-IOV */ 44428c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count) 44438c2ecf20Sopenharmony_ci num_rx_queues = 2; 44448c2ecf20Sopenharmony_ci break; 44458c2ecf20Sopenharmony_ci default: 44468c2ecf20Sopenharmony_ci break; 44478c2ecf20Sopenharmony_ci } 44488c2ecf20Sopenharmony_ci 44498c2ecf20Sopenharmony_ci if (adapter->rss_indir_tbl_init != num_rx_queues) { 44508c2ecf20Sopenharmony_ci for (j = 0; j < IGB_RETA_SIZE; j++) 44518c2ecf20Sopenharmony_ci adapter->rss_indir_tbl[j] = 44528c2ecf20Sopenharmony_ci (j * num_rx_queues) / IGB_RETA_SIZE; 44538c2ecf20Sopenharmony_ci adapter->rss_indir_tbl_init = num_rx_queues; 44548c2ecf20Sopenharmony_ci } 44558c2ecf20Sopenharmony_ci igb_write_rss_indir_tbl(adapter); 44568c2ecf20Sopenharmony_ci 44578c2ecf20Sopenharmony_ci /* Disable raw packet checksumming so that RSS hash is placed in 44588c2ecf20Sopenharmony_ci * descriptor on writeback. No need to enable TCP/UDP/IP checksum 44598c2ecf20Sopenharmony_ci * offloads as they are enabled by default 44608c2ecf20Sopenharmony_ci */ 44618c2ecf20Sopenharmony_ci rxcsum = rd32(E1000_RXCSUM); 44628c2ecf20Sopenharmony_ci rxcsum |= E1000_RXCSUM_PCSD; 44638c2ecf20Sopenharmony_ci 44648c2ecf20Sopenharmony_ci if (adapter->hw.mac.type >= e1000_82576) 44658c2ecf20Sopenharmony_ci /* Enable Receive Checksum Offload for SCTP */ 44668c2ecf20Sopenharmony_ci rxcsum |= E1000_RXCSUM_CRCOFL; 44678c2ecf20Sopenharmony_ci 44688c2ecf20Sopenharmony_ci /* Don't need to set TUOFL or IPOFL, they default to 1 */ 44698c2ecf20Sopenharmony_ci wr32(E1000_RXCSUM, rxcsum); 44708c2ecf20Sopenharmony_ci 44718c2ecf20Sopenharmony_ci /* Generate RSS hash based on packet types, TCP/UDP 44728c2ecf20Sopenharmony_ci * port numbers and/or IPv4/v6 src and dst addresses 44738c2ecf20Sopenharmony_ci */ 44748c2ecf20Sopenharmony_ci mrqc = E1000_MRQC_RSS_FIELD_IPV4 | 44758c2ecf20Sopenharmony_ci E1000_MRQC_RSS_FIELD_IPV4_TCP | 44768c2ecf20Sopenharmony_ci E1000_MRQC_RSS_FIELD_IPV6 | 44778c2ecf20Sopenharmony_ci E1000_MRQC_RSS_FIELD_IPV6_TCP | 44788c2ecf20Sopenharmony_ci E1000_MRQC_RSS_FIELD_IPV6_TCP_EX; 44798c2ecf20Sopenharmony_ci 44808c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP) 44818c2ecf20Sopenharmony_ci mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP; 44828c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP) 44838c2ecf20Sopenharmony_ci mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP; 44848c2ecf20Sopenharmony_ci 44858c2ecf20Sopenharmony_ci /* If VMDq is enabled then we set the appropriate mode for that, else 44868c2ecf20Sopenharmony_ci * we default to RSS so that an RSS hash is calculated per packet even 44878c2ecf20Sopenharmony_ci * if we are only using one queue 44888c2ecf20Sopenharmony_ci */ 44898c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count) { 44908c2ecf20Sopenharmony_ci if (hw->mac.type > e1000_82575) { 44918c2ecf20Sopenharmony_ci /* Set the default pool for the PF's first queue */ 44928c2ecf20Sopenharmony_ci u32 vtctl = rd32(E1000_VT_CTL); 44938c2ecf20Sopenharmony_ci 44948c2ecf20Sopenharmony_ci vtctl &= ~(E1000_VT_CTL_DEFAULT_POOL_MASK | 44958c2ecf20Sopenharmony_ci E1000_VT_CTL_DISABLE_DEF_POOL); 44968c2ecf20Sopenharmony_ci vtctl |= adapter->vfs_allocated_count << 44978c2ecf20Sopenharmony_ci E1000_VT_CTL_DEFAULT_POOL_SHIFT; 44988c2ecf20Sopenharmony_ci wr32(E1000_VT_CTL, vtctl); 44998c2ecf20Sopenharmony_ci } 45008c2ecf20Sopenharmony_ci if (adapter->rss_queues > 1) 45018c2ecf20Sopenharmony_ci mrqc |= E1000_MRQC_ENABLE_VMDQ_RSS_MQ; 45028c2ecf20Sopenharmony_ci else 45038c2ecf20Sopenharmony_ci mrqc |= E1000_MRQC_ENABLE_VMDQ; 45048c2ecf20Sopenharmony_ci } else { 45058c2ecf20Sopenharmony_ci mrqc |= E1000_MRQC_ENABLE_RSS_MQ; 45068c2ecf20Sopenharmony_ci } 45078c2ecf20Sopenharmony_ci igb_vmm_control(adapter); 45088c2ecf20Sopenharmony_ci 45098c2ecf20Sopenharmony_ci wr32(E1000_MRQC, mrqc); 45108c2ecf20Sopenharmony_ci} 45118c2ecf20Sopenharmony_ci 45128c2ecf20Sopenharmony_ci/** 45138c2ecf20Sopenharmony_ci * igb_setup_rctl - configure the receive control registers 45148c2ecf20Sopenharmony_ci * @adapter: Board private structure 45158c2ecf20Sopenharmony_ci **/ 45168c2ecf20Sopenharmony_civoid igb_setup_rctl(struct igb_adapter *adapter) 45178c2ecf20Sopenharmony_ci{ 45188c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 45198c2ecf20Sopenharmony_ci u32 rctl; 45208c2ecf20Sopenharmony_ci 45218c2ecf20Sopenharmony_ci rctl = rd32(E1000_RCTL); 45228c2ecf20Sopenharmony_ci 45238c2ecf20Sopenharmony_ci rctl &= ~(3 << E1000_RCTL_MO_SHIFT); 45248c2ecf20Sopenharmony_ci rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); 45258c2ecf20Sopenharmony_ci 45268c2ecf20Sopenharmony_ci rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF | 45278c2ecf20Sopenharmony_ci (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT); 45288c2ecf20Sopenharmony_ci 45298c2ecf20Sopenharmony_ci /* enable stripping of CRC. It's unlikely this will break BMC 45308c2ecf20Sopenharmony_ci * redirection as it did with e1000. Newer features require 45318c2ecf20Sopenharmony_ci * that the HW strips the CRC. 45328c2ecf20Sopenharmony_ci */ 45338c2ecf20Sopenharmony_ci rctl |= E1000_RCTL_SECRC; 45348c2ecf20Sopenharmony_ci 45358c2ecf20Sopenharmony_ci /* disable store bad packets and clear size bits. */ 45368c2ecf20Sopenharmony_ci rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256); 45378c2ecf20Sopenharmony_ci 45388c2ecf20Sopenharmony_ci /* enable LPE to allow for reception of jumbo frames */ 45398c2ecf20Sopenharmony_ci rctl |= E1000_RCTL_LPE; 45408c2ecf20Sopenharmony_ci 45418c2ecf20Sopenharmony_ci /* disable queue 0 to prevent tail write w/o re-config */ 45428c2ecf20Sopenharmony_ci wr32(E1000_RXDCTL(0), 0); 45438c2ecf20Sopenharmony_ci 45448c2ecf20Sopenharmony_ci /* Attention!!! For SR-IOV PF driver operations you must enable 45458c2ecf20Sopenharmony_ci * queue drop for all VF and PF queues to prevent head of line blocking 45468c2ecf20Sopenharmony_ci * if an un-trusted VF does not provide descriptors to hardware. 45478c2ecf20Sopenharmony_ci */ 45488c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count) { 45498c2ecf20Sopenharmony_ci /* set all queue drop enable bits */ 45508c2ecf20Sopenharmony_ci wr32(E1000_QDE, ALL_QUEUES); 45518c2ecf20Sopenharmony_ci } 45528c2ecf20Sopenharmony_ci 45538c2ecf20Sopenharmony_ci /* This is useful for sniffing bad packets. */ 45548c2ecf20Sopenharmony_ci if (adapter->netdev->features & NETIF_F_RXALL) { 45558c2ecf20Sopenharmony_ci /* UPE and MPE will be handled by normal PROMISC logic 45568c2ecf20Sopenharmony_ci * in e1000e_set_rx_mode 45578c2ecf20Sopenharmony_ci */ 45588c2ecf20Sopenharmony_ci rctl |= (E1000_RCTL_SBP | /* Receive bad packets */ 45598c2ecf20Sopenharmony_ci E1000_RCTL_BAM | /* RX All Bcast Pkts */ 45608c2ecf20Sopenharmony_ci E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */ 45618c2ecf20Sopenharmony_ci 45628c2ecf20Sopenharmony_ci rctl &= ~(E1000_RCTL_DPF | /* Allow filtered pause */ 45638c2ecf20Sopenharmony_ci E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */ 45648c2ecf20Sopenharmony_ci /* Do not mess with E1000_CTRL_VME, it affects transmit as well, 45658c2ecf20Sopenharmony_ci * and that breaks VLANs. 45668c2ecf20Sopenharmony_ci */ 45678c2ecf20Sopenharmony_ci } 45688c2ecf20Sopenharmony_ci 45698c2ecf20Sopenharmony_ci wr32(E1000_RCTL, rctl); 45708c2ecf20Sopenharmony_ci} 45718c2ecf20Sopenharmony_ci 45728c2ecf20Sopenharmony_cistatic inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size, 45738c2ecf20Sopenharmony_ci int vfn) 45748c2ecf20Sopenharmony_ci{ 45758c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 45768c2ecf20Sopenharmony_ci u32 vmolr; 45778c2ecf20Sopenharmony_ci 45788c2ecf20Sopenharmony_ci if (size > MAX_JUMBO_FRAME_SIZE) 45798c2ecf20Sopenharmony_ci size = MAX_JUMBO_FRAME_SIZE; 45808c2ecf20Sopenharmony_ci 45818c2ecf20Sopenharmony_ci vmolr = rd32(E1000_VMOLR(vfn)); 45828c2ecf20Sopenharmony_ci vmolr &= ~E1000_VMOLR_RLPML_MASK; 45838c2ecf20Sopenharmony_ci vmolr |= size | E1000_VMOLR_LPE; 45848c2ecf20Sopenharmony_ci wr32(E1000_VMOLR(vfn), vmolr); 45858c2ecf20Sopenharmony_ci 45868c2ecf20Sopenharmony_ci return 0; 45878c2ecf20Sopenharmony_ci} 45888c2ecf20Sopenharmony_ci 45898c2ecf20Sopenharmony_cistatic inline void igb_set_vf_vlan_strip(struct igb_adapter *adapter, 45908c2ecf20Sopenharmony_ci int vfn, bool enable) 45918c2ecf20Sopenharmony_ci{ 45928c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 45938c2ecf20Sopenharmony_ci u32 val, reg; 45948c2ecf20Sopenharmony_ci 45958c2ecf20Sopenharmony_ci if (hw->mac.type < e1000_82576) 45968c2ecf20Sopenharmony_ci return; 45978c2ecf20Sopenharmony_ci 45988c2ecf20Sopenharmony_ci if (hw->mac.type == e1000_i350) 45998c2ecf20Sopenharmony_ci reg = E1000_DVMOLR(vfn); 46008c2ecf20Sopenharmony_ci else 46018c2ecf20Sopenharmony_ci reg = E1000_VMOLR(vfn); 46028c2ecf20Sopenharmony_ci 46038c2ecf20Sopenharmony_ci val = rd32(reg); 46048c2ecf20Sopenharmony_ci if (enable) 46058c2ecf20Sopenharmony_ci val |= E1000_VMOLR_STRVLAN; 46068c2ecf20Sopenharmony_ci else 46078c2ecf20Sopenharmony_ci val &= ~(E1000_VMOLR_STRVLAN); 46088c2ecf20Sopenharmony_ci wr32(reg, val); 46098c2ecf20Sopenharmony_ci} 46108c2ecf20Sopenharmony_ci 46118c2ecf20Sopenharmony_cistatic inline void igb_set_vmolr(struct igb_adapter *adapter, 46128c2ecf20Sopenharmony_ci int vfn, bool aupe) 46138c2ecf20Sopenharmony_ci{ 46148c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 46158c2ecf20Sopenharmony_ci u32 vmolr; 46168c2ecf20Sopenharmony_ci 46178c2ecf20Sopenharmony_ci /* This register exists only on 82576 and newer so if we are older then 46188c2ecf20Sopenharmony_ci * we should exit and do nothing 46198c2ecf20Sopenharmony_ci */ 46208c2ecf20Sopenharmony_ci if (hw->mac.type < e1000_82576) 46218c2ecf20Sopenharmony_ci return; 46228c2ecf20Sopenharmony_ci 46238c2ecf20Sopenharmony_ci vmolr = rd32(E1000_VMOLR(vfn)); 46248c2ecf20Sopenharmony_ci if (aupe) 46258c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_AUPE; /* Accept untagged packets */ 46268c2ecf20Sopenharmony_ci else 46278c2ecf20Sopenharmony_ci vmolr &= ~(E1000_VMOLR_AUPE); /* Tagged packets ONLY */ 46288c2ecf20Sopenharmony_ci 46298c2ecf20Sopenharmony_ci /* clear all bits that might not be set */ 46308c2ecf20Sopenharmony_ci vmolr &= ~(E1000_VMOLR_BAM | E1000_VMOLR_RSSE); 46318c2ecf20Sopenharmony_ci 46328c2ecf20Sopenharmony_ci if (adapter->rss_queues > 1 && vfn == adapter->vfs_allocated_count) 46338c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_RSSE; /* enable RSS */ 46348c2ecf20Sopenharmony_ci /* for VMDq only allow the VFs and pool 0 to accept broadcast and 46358c2ecf20Sopenharmony_ci * multicast packets 46368c2ecf20Sopenharmony_ci */ 46378c2ecf20Sopenharmony_ci if (vfn <= adapter->vfs_allocated_count) 46388c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_BAM; /* Accept broadcast */ 46398c2ecf20Sopenharmony_ci 46408c2ecf20Sopenharmony_ci wr32(E1000_VMOLR(vfn), vmolr); 46418c2ecf20Sopenharmony_ci} 46428c2ecf20Sopenharmony_ci 46438c2ecf20Sopenharmony_ci/** 46448c2ecf20Sopenharmony_ci * igb_setup_srrctl - configure the split and replication receive control 46458c2ecf20Sopenharmony_ci * registers 46468c2ecf20Sopenharmony_ci * @adapter: Board private structure 46478c2ecf20Sopenharmony_ci * @ring: receive ring to be configured 46488c2ecf20Sopenharmony_ci **/ 46498c2ecf20Sopenharmony_civoid igb_setup_srrctl(struct igb_adapter *adapter, struct igb_ring *ring) 46508c2ecf20Sopenharmony_ci{ 46518c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 46528c2ecf20Sopenharmony_ci int reg_idx = ring->reg_idx; 46538c2ecf20Sopenharmony_ci u32 srrctl = 0; 46548c2ecf20Sopenharmony_ci 46558c2ecf20Sopenharmony_ci srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT; 46568c2ecf20Sopenharmony_ci if (ring_uses_large_buffer(ring)) 46578c2ecf20Sopenharmony_ci srrctl |= IGB_RXBUFFER_3072 >> E1000_SRRCTL_BSIZEPKT_SHIFT; 46588c2ecf20Sopenharmony_ci else 46598c2ecf20Sopenharmony_ci srrctl |= IGB_RXBUFFER_2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; 46608c2ecf20Sopenharmony_ci srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; 46618c2ecf20Sopenharmony_ci if (hw->mac.type >= e1000_82580) 46628c2ecf20Sopenharmony_ci srrctl |= E1000_SRRCTL_TIMESTAMP; 46638c2ecf20Sopenharmony_ci /* Only set Drop Enable if VFs allocated, or we are supporting multiple 46648c2ecf20Sopenharmony_ci * queues and rx flow control is disabled 46658c2ecf20Sopenharmony_ci */ 46668c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count || 46678c2ecf20Sopenharmony_ci (!(hw->fc.current_mode & e1000_fc_rx_pause) && 46688c2ecf20Sopenharmony_ci adapter->num_rx_queues > 1)) 46698c2ecf20Sopenharmony_ci srrctl |= E1000_SRRCTL_DROP_EN; 46708c2ecf20Sopenharmony_ci 46718c2ecf20Sopenharmony_ci wr32(E1000_SRRCTL(reg_idx), srrctl); 46728c2ecf20Sopenharmony_ci} 46738c2ecf20Sopenharmony_ci 46748c2ecf20Sopenharmony_ci/** 46758c2ecf20Sopenharmony_ci * igb_configure_rx_ring - Configure a receive ring after Reset 46768c2ecf20Sopenharmony_ci * @adapter: board private structure 46778c2ecf20Sopenharmony_ci * @ring: receive ring to be configured 46788c2ecf20Sopenharmony_ci * 46798c2ecf20Sopenharmony_ci * Configure the Rx unit of the MAC after a reset. 46808c2ecf20Sopenharmony_ci **/ 46818c2ecf20Sopenharmony_civoid igb_configure_rx_ring(struct igb_adapter *adapter, 46828c2ecf20Sopenharmony_ci struct igb_ring *ring) 46838c2ecf20Sopenharmony_ci{ 46848c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 46858c2ecf20Sopenharmony_ci union e1000_adv_rx_desc *rx_desc; 46868c2ecf20Sopenharmony_ci u64 rdba = ring->dma; 46878c2ecf20Sopenharmony_ci int reg_idx = ring->reg_idx; 46888c2ecf20Sopenharmony_ci u32 rxdctl = 0; 46898c2ecf20Sopenharmony_ci 46908c2ecf20Sopenharmony_ci xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq); 46918c2ecf20Sopenharmony_ci WARN_ON(xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, 46928c2ecf20Sopenharmony_ci MEM_TYPE_PAGE_SHARED, NULL)); 46938c2ecf20Sopenharmony_ci 46948c2ecf20Sopenharmony_ci /* disable the queue */ 46958c2ecf20Sopenharmony_ci wr32(E1000_RXDCTL(reg_idx), 0); 46968c2ecf20Sopenharmony_ci 46978c2ecf20Sopenharmony_ci /* Set DMA base address registers */ 46988c2ecf20Sopenharmony_ci wr32(E1000_RDBAL(reg_idx), 46998c2ecf20Sopenharmony_ci rdba & 0x00000000ffffffffULL); 47008c2ecf20Sopenharmony_ci wr32(E1000_RDBAH(reg_idx), rdba >> 32); 47018c2ecf20Sopenharmony_ci wr32(E1000_RDLEN(reg_idx), 47028c2ecf20Sopenharmony_ci ring->count * sizeof(union e1000_adv_rx_desc)); 47038c2ecf20Sopenharmony_ci 47048c2ecf20Sopenharmony_ci /* initialize head and tail */ 47058c2ecf20Sopenharmony_ci ring->tail = adapter->io_addr + E1000_RDT(reg_idx); 47068c2ecf20Sopenharmony_ci wr32(E1000_RDH(reg_idx), 0); 47078c2ecf20Sopenharmony_ci writel(0, ring->tail); 47088c2ecf20Sopenharmony_ci 47098c2ecf20Sopenharmony_ci /* set descriptor configuration */ 47108c2ecf20Sopenharmony_ci igb_setup_srrctl(adapter, ring); 47118c2ecf20Sopenharmony_ci 47128c2ecf20Sopenharmony_ci /* set filtering for VMDQ pools */ 47138c2ecf20Sopenharmony_ci igb_set_vmolr(adapter, reg_idx & 0x7, true); 47148c2ecf20Sopenharmony_ci 47158c2ecf20Sopenharmony_ci rxdctl |= IGB_RX_PTHRESH; 47168c2ecf20Sopenharmony_ci rxdctl |= IGB_RX_HTHRESH << 8; 47178c2ecf20Sopenharmony_ci rxdctl |= IGB_RX_WTHRESH << 16; 47188c2ecf20Sopenharmony_ci 47198c2ecf20Sopenharmony_ci /* initialize rx_buffer_info */ 47208c2ecf20Sopenharmony_ci memset(ring->rx_buffer_info, 0, 47218c2ecf20Sopenharmony_ci sizeof(struct igb_rx_buffer) * ring->count); 47228c2ecf20Sopenharmony_ci 47238c2ecf20Sopenharmony_ci /* initialize Rx descriptor 0 */ 47248c2ecf20Sopenharmony_ci rx_desc = IGB_RX_DESC(ring, 0); 47258c2ecf20Sopenharmony_ci rx_desc->wb.upper.length = 0; 47268c2ecf20Sopenharmony_ci 47278c2ecf20Sopenharmony_ci /* enable receive descriptor fetching */ 47288c2ecf20Sopenharmony_ci rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; 47298c2ecf20Sopenharmony_ci wr32(E1000_RXDCTL(reg_idx), rxdctl); 47308c2ecf20Sopenharmony_ci} 47318c2ecf20Sopenharmony_ci 47328c2ecf20Sopenharmony_cistatic void igb_set_rx_buffer_len(struct igb_adapter *adapter, 47338c2ecf20Sopenharmony_ci struct igb_ring *rx_ring) 47348c2ecf20Sopenharmony_ci{ 47358c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 47368c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 47378c2ecf20Sopenharmony_ci#endif 47388c2ecf20Sopenharmony_ci 47398c2ecf20Sopenharmony_ci /* set build_skb and buffer size flags */ 47408c2ecf20Sopenharmony_ci clear_ring_build_skb_enabled(rx_ring); 47418c2ecf20Sopenharmony_ci clear_ring_uses_large_buffer(rx_ring); 47428c2ecf20Sopenharmony_ci 47438c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_RX_LEGACY) 47448c2ecf20Sopenharmony_ci return; 47458c2ecf20Sopenharmony_ci 47468c2ecf20Sopenharmony_ci set_ring_build_skb_enabled(rx_ring); 47478c2ecf20Sopenharmony_ci 47488c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 47498c2ecf20Sopenharmony_ci if (adapter->max_frame_size > IGB_MAX_FRAME_BUILD_SKB || 47508c2ecf20Sopenharmony_ci rd32(E1000_RCTL) & E1000_RCTL_SBP) 47518c2ecf20Sopenharmony_ci set_ring_uses_large_buffer(rx_ring); 47528c2ecf20Sopenharmony_ci#endif 47538c2ecf20Sopenharmony_ci} 47548c2ecf20Sopenharmony_ci 47558c2ecf20Sopenharmony_ci/** 47568c2ecf20Sopenharmony_ci * igb_configure_rx - Configure receive Unit after Reset 47578c2ecf20Sopenharmony_ci * @adapter: board private structure 47588c2ecf20Sopenharmony_ci * 47598c2ecf20Sopenharmony_ci * Configure the Rx unit of the MAC after a reset. 47608c2ecf20Sopenharmony_ci **/ 47618c2ecf20Sopenharmony_cistatic void igb_configure_rx(struct igb_adapter *adapter) 47628c2ecf20Sopenharmony_ci{ 47638c2ecf20Sopenharmony_ci int i; 47648c2ecf20Sopenharmony_ci 47658c2ecf20Sopenharmony_ci /* set the correct pool for the PF default MAC address in entry 0 */ 47668c2ecf20Sopenharmony_ci igb_set_default_mac_filter(adapter); 47678c2ecf20Sopenharmony_ci 47688c2ecf20Sopenharmony_ci /* Setup the HW Rx Head and Tail Descriptor Pointers and 47698c2ecf20Sopenharmony_ci * the Base and Length of the Rx Descriptor Ring 47708c2ecf20Sopenharmony_ci */ 47718c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 47728c2ecf20Sopenharmony_ci struct igb_ring *rx_ring = adapter->rx_ring[i]; 47738c2ecf20Sopenharmony_ci 47748c2ecf20Sopenharmony_ci igb_set_rx_buffer_len(adapter, rx_ring); 47758c2ecf20Sopenharmony_ci igb_configure_rx_ring(adapter, rx_ring); 47768c2ecf20Sopenharmony_ci } 47778c2ecf20Sopenharmony_ci} 47788c2ecf20Sopenharmony_ci 47798c2ecf20Sopenharmony_ci/** 47808c2ecf20Sopenharmony_ci * igb_free_tx_resources - Free Tx Resources per Queue 47818c2ecf20Sopenharmony_ci * @tx_ring: Tx descriptor ring for a specific queue 47828c2ecf20Sopenharmony_ci * 47838c2ecf20Sopenharmony_ci * Free all transmit software resources 47848c2ecf20Sopenharmony_ci **/ 47858c2ecf20Sopenharmony_civoid igb_free_tx_resources(struct igb_ring *tx_ring) 47868c2ecf20Sopenharmony_ci{ 47878c2ecf20Sopenharmony_ci igb_clean_tx_ring(tx_ring); 47888c2ecf20Sopenharmony_ci 47898c2ecf20Sopenharmony_ci vfree(tx_ring->tx_buffer_info); 47908c2ecf20Sopenharmony_ci tx_ring->tx_buffer_info = NULL; 47918c2ecf20Sopenharmony_ci 47928c2ecf20Sopenharmony_ci /* if not set, then don't free */ 47938c2ecf20Sopenharmony_ci if (!tx_ring->desc) 47948c2ecf20Sopenharmony_ci return; 47958c2ecf20Sopenharmony_ci 47968c2ecf20Sopenharmony_ci dma_free_coherent(tx_ring->dev, tx_ring->size, 47978c2ecf20Sopenharmony_ci tx_ring->desc, tx_ring->dma); 47988c2ecf20Sopenharmony_ci 47998c2ecf20Sopenharmony_ci tx_ring->desc = NULL; 48008c2ecf20Sopenharmony_ci} 48018c2ecf20Sopenharmony_ci 48028c2ecf20Sopenharmony_ci/** 48038c2ecf20Sopenharmony_ci * igb_free_all_tx_resources - Free Tx Resources for All Queues 48048c2ecf20Sopenharmony_ci * @adapter: board private structure 48058c2ecf20Sopenharmony_ci * 48068c2ecf20Sopenharmony_ci * Free all transmit software resources 48078c2ecf20Sopenharmony_ci **/ 48088c2ecf20Sopenharmony_cistatic void igb_free_all_tx_resources(struct igb_adapter *adapter) 48098c2ecf20Sopenharmony_ci{ 48108c2ecf20Sopenharmony_ci int i; 48118c2ecf20Sopenharmony_ci 48128c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 48138c2ecf20Sopenharmony_ci if (adapter->tx_ring[i]) 48148c2ecf20Sopenharmony_ci igb_free_tx_resources(adapter->tx_ring[i]); 48158c2ecf20Sopenharmony_ci} 48168c2ecf20Sopenharmony_ci 48178c2ecf20Sopenharmony_ci/** 48188c2ecf20Sopenharmony_ci * igb_clean_tx_ring - Free Tx Buffers 48198c2ecf20Sopenharmony_ci * @tx_ring: ring to be cleaned 48208c2ecf20Sopenharmony_ci **/ 48218c2ecf20Sopenharmony_cistatic void igb_clean_tx_ring(struct igb_ring *tx_ring) 48228c2ecf20Sopenharmony_ci{ 48238c2ecf20Sopenharmony_ci u16 i = tx_ring->next_to_clean; 48248c2ecf20Sopenharmony_ci struct igb_tx_buffer *tx_buffer = &tx_ring->tx_buffer_info[i]; 48258c2ecf20Sopenharmony_ci 48268c2ecf20Sopenharmony_ci while (i != tx_ring->next_to_use) { 48278c2ecf20Sopenharmony_ci union e1000_adv_tx_desc *eop_desc, *tx_desc; 48288c2ecf20Sopenharmony_ci 48298c2ecf20Sopenharmony_ci /* Free all the Tx ring sk_buffs or xdp frames */ 48308c2ecf20Sopenharmony_ci if (tx_buffer->type == IGB_TYPE_SKB) 48318c2ecf20Sopenharmony_ci dev_kfree_skb_any(tx_buffer->skb); 48328c2ecf20Sopenharmony_ci else 48338c2ecf20Sopenharmony_ci xdp_return_frame(tx_buffer->xdpf); 48348c2ecf20Sopenharmony_ci 48358c2ecf20Sopenharmony_ci /* unmap skb header data */ 48368c2ecf20Sopenharmony_ci dma_unmap_single(tx_ring->dev, 48378c2ecf20Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 48388c2ecf20Sopenharmony_ci dma_unmap_len(tx_buffer, len), 48398c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 48408c2ecf20Sopenharmony_ci 48418c2ecf20Sopenharmony_ci /* check for eop_desc to determine the end of the packet */ 48428c2ecf20Sopenharmony_ci eop_desc = tx_buffer->next_to_watch; 48438c2ecf20Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, i); 48448c2ecf20Sopenharmony_ci 48458c2ecf20Sopenharmony_ci /* unmap remaining buffers */ 48468c2ecf20Sopenharmony_ci while (tx_desc != eop_desc) { 48478c2ecf20Sopenharmony_ci tx_buffer++; 48488c2ecf20Sopenharmony_ci tx_desc++; 48498c2ecf20Sopenharmony_ci i++; 48508c2ecf20Sopenharmony_ci if (unlikely(i == tx_ring->count)) { 48518c2ecf20Sopenharmony_ci i = 0; 48528c2ecf20Sopenharmony_ci tx_buffer = tx_ring->tx_buffer_info; 48538c2ecf20Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, 0); 48548c2ecf20Sopenharmony_ci } 48558c2ecf20Sopenharmony_ci 48568c2ecf20Sopenharmony_ci /* unmap any remaining paged data */ 48578c2ecf20Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) 48588c2ecf20Sopenharmony_ci dma_unmap_page(tx_ring->dev, 48598c2ecf20Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 48608c2ecf20Sopenharmony_ci dma_unmap_len(tx_buffer, len), 48618c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 48628c2ecf20Sopenharmony_ci } 48638c2ecf20Sopenharmony_ci 48648c2ecf20Sopenharmony_ci tx_buffer->next_to_watch = NULL; 48658c2ecf20Sopenharmony_ci 48668c2ecf20Sopenharmony_ci /* move us one more past the eop_desc for start of next pkt */ 48678c2ecf20Sopenharmony_ci tx_buffer++; 48688c2ecf20Sopenharmony_ci i++; 48698c2ecf20Sopenharmony_ci if (unlikely(i == tx_ring->count)) { 48708c2ecf20Sopenharmony_ci i = 0; 48718c2ecf20Sopenharmony_ci tx_buffer = tx_ring->tx_buffer_info; 48728c2ecf20Sopenharmony_ci } 48738c2ecf20Sopenharmony_ci } 48748c2ecf20Sopenharmony_ci 48758c2ecf20Sopenharmony_ci /* reset BQL for queue */ 48768c2ecf20Sopenharmony_ci netdev_tx_reset_queue(txring_txq(tx_ring)); 48778c2ecf20Sopenharmony_ci 48788c2ecf20Sopenharmony_ci /* reset next_to_use and next_to_clean */ 48798c2ecf20Sopenharmony_ci tx_ring->next_to_use = 0; 48808c2ecf20Sopenharmony_ci tx_ring->next_to_clean = 0; 48818c2ecf20Sopenharmony_ci} 48828c2ecf20Sopenharmony_ci 48838c2ecf20Sopenharmony_ci/** 48848c2ecf20Sopenharmony_ci * igb_clean_all_tx_rings - Free Tx Buffers for all queues 48858c2ecf20Sopenharmony_ci * @adapter: board private structure 48868c2ecf20Sopenharmony_ci **/ 48878c2ecf20Sopenharmony_cistatic void igb_clean_all_tx_rings(struct igb_adapter *adapter) 48888c2ecf20Sopenharmony_ci{ 48898c2ecf20Sopenharmony_ci int i; 48908c2ecf20Sopenharmony_ci 48918c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 48928c2ecf20Sopenharmony_ci if (adapter->tx_ring[i]) 48938c2ecf20Sopenharmony_ci igb_clean_tx_ring(adapter->tx_ring[i]); 48948c2ecf20Sopenharmony_ci} 48958c2ecf20Sopenharmony_ci 48968c2ecf20Sopenharmony_ci/** 48978c2ecf20Sopenharmony_ci * igb_free_rx_resources - Free Rx Resources 48988c2ecf20Sopenharmony_ci * @rx_ring: ring to clean the resources from 48998c2ecf20Sopenharmony_ci * 49008c2ecf20Sopenharmony_ci * Free all receive software resources 49018c2ecf20Sopenharmony_ci **/ 49028c2ecf20Sopenharmony_civoid igb_free_rx_resources(struct igb_ring *rx_ring) 49038c2ecf20Sopenharmony_ci{ 49048c2ecf20Sopenharmony_ci igb_clean_rx_ring(rx_ring); 49058c2ecf20Sopenharmony_ci 49068c2ecf20Sopenharmony_ci rx_ring->xdp_prog = NULL; 49078c2ecf20Sopenharmony_ci xdp_rxq_info_unreg(&rx_ring->xdp_rxq); 49088c2ecf20Sopenharmony_ci vfree(rx_ring->rx_buffer_info); 49098c2ecf20Sopenharmony_ci rx_ring->rx_buffer_info = NULL; 49108c2ecf20Sopenharmony_ci 49118c2ecf20Sopenharmony_ci /* if not set, then don't free */ 49128c2ecf20Sopenharmony_ci if (!rx_ring->desc) 49138c2ecf20Sopenharmony_ci return; 49148c2ecf20Sopenharmony_ci 49158c2ecf20Sopenharmony_ci dma_free_coherent(rx_ring->dev, rx_ring->size, 49168c2ecf20Sopenharmony_ci rx_ring->desc, rx_ring->dma); 49178c2ecf20Sopenharmony_ci 49188c2ecf20Sopenharmony_ci rx_ring->desc = NULL; 49198c2ecf20Sopenharmony_ci} 49208c2ecf20Sopenharmony_ci 49218c2ecf20Sopenharmony_ci/** 49228c2ecf20Sopenharmony_ci * igb_free_all_rx_resources - Free Rx Resources for All Queues 49238c2ecf20Sopenharmony_ci * @adapter: board private structure 49248c2ecf20Sopenharmony_ci * 49258c2ecf20Sopenharmony_ci * Free all receive software resources 49268c2ecf20Sopenharmony_ci **/ 49278c2ecf20Sopenharmony_cistatic void igb_free_all_rx_resources(struct igb_adapter *adapter) 49288c2ecf20Sopenharmony_ci{ 49298c2ecf20Sopenharmony_ci int i; 49308c2ecf20Sopenharmony_ci 49318c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) 49328c2ecf20Sopenharmony_ci if (adapter->rx_ring[i]) 49338c2ecf20Sopenharmony_ci igb_free_rx_resources(adapter->rx_ring[i]); 49348c2ecf20Sopenharmony_ci} 49358c2ecf20Sopenharmony_ci 49368c2ecf20Sopenharmony_ci/** 49378c2ecf20Sopenharmony_ci * igb_clean_rx_ring - Free Rx Buffers per Queue 49388c2ecf20Sopenharmony_ci * @rx_ring: ring to free buffers from 49398c2ecf20Sopenharmony_ci **/ 49408c2ecf20Sopenharmony_cistatic void igb_clean_rx_ring(struct igb_ring *rx_ring) 49418c2ecf20Sopenharmony_ci{ 49428c2ecf20Sopenharmony_ci u16 i = rx_ring->next_to_clean; 49438c2ecf20Sopenharmony_ci 49448c2ecf20Sopenharmony_ci dev_kfree_skb(rx_ring->skb); 49458c2ecf20Sopenharmony_ci rx_ring->skb = NULL; 49468c2ecf20Sopenharmony_ci 49478c2ecf20Sopenharmony_ci /* Free all the Rx ring sk_buffs */ 49488c2ecf20Sopenharmony_ci while (i != rx_ring->next_to_alloc) { 49498c2ecf20Sopenharmony_ci struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i]; 49508c2ecf20Sopenharmony_ci 49518c2ecf20Sopenharmony_ci /* Invalidate cache lines that may have been written to by 49528c2ecf20Sopenharmony_ci * device so that we avoid corrupting memory. 49538c2ecf20Sopenharmony_ci */ 49548c2ecf20Sopenharmony_ci dma_sync_single_range_for_cpu(rx_ring->dev, 49558c2ecf20Sopenharmony_ci buffer_info->dma, 49568c2ecf20Sopenharmony_ci buffer_info->page_offset, 49578c2ecf20Sopenharmony_ci igb_rx_bufsz(rx_ring), 49588c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 49598c2ecf20Sopenharmony_ci 49608c2ecf20Sopenharmony_ci /* free resources associated with mapping */ 49618c2ecf20Sopenharmony_ci dma_unmap_page_attrs(rx_ring->dev, 49628c2ecf20Sopenharmony_ci buffer_info->dma, 49638c2ecf20Sopenharmony_ci igb_rx_pg_size(rx_ring), 49648c2ecf20Sopenharmony_ci DMA_FROM_DEVICE, 49658c2ecf20Sopenharmony_ci IGB_RX_DMA_ATTR); 49668c2ecf20Sopenharmony_ci __page_frag_cache_drain(buffer_info->page, 49678c2ecf20Sopenharmony_ci buffer_info->pagecnt_bias); 49688c2ecf20Sopenharmony_ci 49698c2ecf20Sopenharmony_ci i++; 49708c2ecf20Sopenharmony_ci if (i == rx_ring->count) 49718c2ecf20Sopenharmony_ci i = 0; 49728c2ecf20Sopenharmony_ci } 49738c2ecf20Sopenharmony_ci 49748c2ecf20Sopenharmony_ci rx_ring->next_to_alloc = 0; 49758c2ecf20Sopenharmony_ci rx_ring->next_to_clean = 0; 49768c2ecf20Sopenharmony_ci rx_ring->next_to_use = 0; 49778c2ecf20Sopenharmony_ci} 49788c2ecf20Sopenharmony_ci 49798c2ecf20Sopenharmony_ci/** 49808c2ecf20Sopenharmony_ci * igb_clean_all_rx_rings - Free Rx Buffers for all queues 49818c2ecf20Sopenharmony_ci * @adapter: board private structure 49828c2ecf20Sopenharmony_ci **/ 49838c2ecf20Sopenharmony_cistatic void igb_clean_all_rx_rings(struct igb_adapter *adapter) 49848c2ecf20Sopenharmony_ci{ 49858c2ecf20Sopenharmony_ci int i; 49868c2ecf20Sopenharmony_ci 49878c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) 49888c2ecf20Sopenharmony_ci if (adapter->rx_ring[i]) 49898c2ecf20Sopenharmony_ci igb_clean_rx_ring(adapter->rx_ring[i]); 49908c2ecf20Sopenharmony_ci} 49918c2ecf20Sopenharmony_ci 49928c2ecf20Sopenharmony_ci/** 49938c2ecf20Sopenharmony_ci * igb_set_mac - Change the Ethernet Address of the NIC 49948c2ecf20Sopenharmony_ci * @netdev: network interface device structure 49958c2ecf20Sopenharmony_ci * @p: pointer to an address structure 49968c2ecf20Sopenharmony_ci * 49978c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure 49988c2ecf20Sopenharmony_ci **/ 49998c2ecf20Sopenharmony_cistatic int igb_set_mac(struct net_device *netdev, void *p) 50008c2ecf20Sopenharmony_ci{ 50018c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 50028c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 50038c2ecf20Sopenharmony_ci struct sockaddr *addr = p; 50048c2ecf20Sopenharmony_ci 50058c2ecf20Sopenharmony_ci if (!is_valid_ether_addr(addr->sa_data)) 50068c2ecf20Sopenharmony_ci return -EADDRNOTAVAIL; 50078c2ecf20Sopenharmony_ci 50088c2ecf20Sopenharmony_ci memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); 50098c2ecf20Sopenharmony_ci memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); 50108c2ecf20Sopenharmony_ci 50118c2ecf20Sopenharmony_ci /* set the correct pool for the new PF MAC address in entry 0 */ 50128c2ecf20Sopenharmony_ci igb_set_default_mac_filter(adapter); 50138c2ecf20Sopenharmony_ci 50148c2ecf20Sopenharmony_ci return 0; 50158c2ecf20Sopenharmony_ci} 50168c2ecf20Sopenharmony_ci 50178c2ecf20Sopenharmony_ci/** 50188c2ecf20Sopenharmony_ci * igb_write_mc_addr_list - write multicast addresses to MTA 50198c2ecf20Sopenharmony_ci * @netdev: network interface device structure 50208c2ecf20Sopenharmony_ci * 50218c2ecf20Sopenharmony_ci * Writes multicast address list to the MTA hash table. 50228c2ecf20Sopenharmony_ci * Returns: -ENOMEM on failure 50238c2ecf20Sopenharmony_ci * 0 on no addresses written 50248c2ecf20Sopenharmony_ci * X on writing X addresses to MTA 50258c2ecf20Sopenharmony_ci **/ 50268c2ecf20Sopenharmony_cistatic int igb_write_mc_addr_list(struct net_device *netdev) 50278c2ecf20Sopenharmony_ci{ 50288c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 50298c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 50308c2ecf20Sopenharmony_ci struct netdev_hw_addr *ha; 50318c2ecf20Sopenharmony_ci u8 *mta_list; 50328c2ecf20Sopenharmony_ci int i; 50338c2ecf20Sopenharmony_ci 50348c2ecf20Sopenharmony_ci if (netdev_mc_empty(netdev)) { 50358c2ecf20Sopenharmony_ci /* nothing to program, so clear mc list */ 50368c2ecf20Sopenharmony_ci igb_update_mc_addr_list(hw, NULL, 0); 50378c2ecf20Sopenharmony_ci igb_restore_vf_multicasts(adapter); 50388c2ecf20Sopenharmony_ci return 0; 50398c2ecf20Sopenharmony_ci } 50408c2ecf20Sopenharmony_ci 50418c2ecf20Sopenharmony_ci mta_list = kcalloc(netdev_mc_count(netdev), 6, GFP_ATOMIC); 50428c2ecf20Sopenharmony_ci if (!mta_list) 50438c2ecf20Sopenharmony_ci return -ENOMEM; 50448c2ecf20Sopenharmony_ci 50458c2ecf20Sopenharmony_ci /* The shared function expects a packed array of only addresses. */ 50468c2ecf20Sopenharmony_ci i = 0; 50478c2ecf20Sopenharmony_ci netdev_for_each_mc_addr(ha, netdev) 50488c2ecf20Sopenharmony_ci memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); 50498c2ecf20Sopenharmony_ci 50508c2ecf20Sopenharmony_ci igb_update_mc_addr_list(hw, mta_list, i); 50518c2ecf20Sopenharmony_ci kfree(mta_list); 50528c2ecf20Sopenharmony_ci 50538c2ecf20Sopenharmony_ci return netdev_mc_count(netdev); 50548c2ecf20Sopenharmony_ci} 50558c2ecf20Sopenharmony_ci 50568c2ecf20Sopenharmony_cistatic int igb_vlan_promisc_enable(struct igb_adapter *adapter) 50578c2ecf20Sopenharmony_ci{ 50588c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 50598c2ecf20Sopenharmony_ci u32 i, pf_id; 50608c2ecf20Sopenharmony_ci 50618c2ecf20Sopenharmony_ci switch (hw->mac.type) { 50628c2ecf20Sopenharmony_ci case e1000_i210: 50638c2ecf20Sopenharmony_ci case e1000_i211: 50648c2ecf20Sopenharmony_ci case e1000_i350: 50658c2ecf20Sopenharmony_ci /* VLAN filtering needed for VLAN prio filter */ 50668c2ecf20Sopenharmony_ci if (adapter->netdev->features & NETIF_F_NTUPLE) 50678c2ecf20Sopenharmony_ci break; 50688c2ecf20Sopenharmony_ci fallthrough; 50698c2ecf20Sopenharmony_ci case e1000_82576: 50708c2ecf20Sopenharmony_ci case e1000_82580: 50718c2ecf20Sopenharmony_ci case e1000_i354: 50728c2ecf20Sopenharmony_ci /* VLAN filtering needed for pool filtering */ 50738c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count) 50748c2ecf20Sopenharmony_ci break; 50758c2ecf20Sopenharmony_ci fallthrough; 50768c2ecf20Sopenharmony_ci default: 50778c2ecf20Sopenharmony_ci return 1; 50788c2ecf20Sopenharmony_ci } 50798c2ecf20Sopenharmony_ci 50808c2ecf20Sopenharmony_ci /* We are already in VLAN promisc, nothing to do */ 50818c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_VLAN_PROMISC) 50828c2ecf20Sopenharmony_ci return 0; 50838c2ecf20Sopenharmony_ci 50848c2ecf20Sopenharmony_ci if (!adapter->vfs_allocated_count) 50858c2ecf20Sopenharmony_ci goto set_vfta; 50868c2ecf20Sopenharmony_ci 50878c2ecf20Sopenharmony_ci /* Add PF to all active pools */ 50888c2ecf20Sopenharmony_ci pf_id = adapter->vfs_allocated_count + E1000_VLVF_POOLSEL_SHIFT; 50898c2ecf20Sopenharmony_ci 50908c2ecf20Sopenharmony_ci for (i = E1000_VLVF_ARRAY_SIZE; --i;) { 50918c2ecf20Sopenharmony_ci u32 vlvf = rd32(E1000_VLVF(i)); 50928c2ecf20Sopenharmony_ci 50938c2ecf20Sopenharmony_ci vlvf |= BIT(pf_id); 50948c2ecf20Sopenharmony_ci wr32(E1000_VLVF(i), vlvf); 50958c2ecf20Sopenharmony_ci } 50968c2ecf20Sopenharmony_ci 50978c2ecf20Sopenharmony_ciset_vfta: 50988c2ecf20Sopenharmony_ci /* Set all bits in the VLAN filter table array */ 50998c2ecf20Sopenharmony_ci for (i = E1000_VLAN_FILTER_TBL_SIZE; i--;) 51008c2ecf20Sopenharmony_ci hw->mac.ops.write_vfta(hw, i, ~0U); 51018c2ecf20Sopenharmony_ci 51028c2ecf20Sopenharmony_ci /* Set flag so we don't redo unnecessary work */ 51038c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_VLAN_PROMISC; 51048c2ecf20Sopenharmony_ci 51058c2ecf20Sopenharmony_ci return 0; 51068c2ecf20Sopenharmony_ci} 51078c2ecf20Sopenharmony_ci 51088c2ecf20Sopenharmony_ci#define VFTA_BLOCK_SIZE 8 51098c2ecf20Sopenharmony_cistatic void igb_scrub_vfta(struct igb_adapter *adapter, u32 vfta_offset) 51108c2ecf20Sopenharmony_ci{ 51118c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 51128c2ecf20Sopenharmony_ci u32 vfta[VFTA_BLOCK_SIZE] = { 0 }; 51138c2ecf20Sopenharmony_ci u32 vid_start = vfta_offset * 32; 51148c2ecf20Sopenharmony_ci u32 vid_end = vid_start + (VFTA_BLOCK_SIZE * 32); 51158c2ecf20Sopenharmony_ci u32 i, vid, word, bits, pf_id; 51168c2ecf20Sopenharmony_ci 51178c2ecf20Sopenharmony_ci /* guarantee that we don't scrub out management VLAN */ 51188c2ecf20Sopenharmony_ci vid = adapter->mng_vlan_id; 51198c2ecf20Sopenharmony_ci if (vid >= vid_start && vid < vid_end) 51208c2ecf20Sopenharmony_ci vfta[(vid - vid_start) / 32] |= BIT(vid % 32); 51218c2ecf20Sopenharmony_ci 51228c2ecf20Sopenharmony_ci if (!adapter->vfs_allocated_count) 51238c2ecf20Sopenharmony_ci goto set_vfta; 51248c2ecf20Sopenharmony_ci 51258c2ecf20Sopenharmony_ci pf_id = adapter->vfs_allocated_count + E1000_VLVF_POOLSEL_SHIFT; 51268c2ecf20Sopenharmony_ci 51278c2ecf20Sopenharmony_ci for (i = E1000_VLVF_ARRAY_SIZE; --i;) { 51288c2ecf20Sopenharmony_ci u32 vlvf = rd32(E1000_VLVF(i)); 51298c2ecf20Sopenharmony_ci 51308c2ecf20Sopenharmony_ci /* pull VLAN ID from VLVF */ 51318c2ecf20Sopenharmony_ci vid = vlvf & VLAN_VID_MASK; 51328c2ecf20Sopenharmony_ci 51338c2ecf20Sopenharmony_ci /* only concern ourselves with a certain range */ 51348c2ecf20Sopenharmony_ci if (vid < vid_start || vid >= vid_end) 51358c2ecf20Sopenharmony_ci continue; 51368c2ecf20Sopenharmony_ci 51378c2ecf20Sopenharmony_ci if (vlvf & E1000_VLVF_VLANID_ENABLE) { 51388c2ecf20Sopenharmony_ci /* record VLAN ID in VFTA */ 51398c2ecf20Sopenharmony_ci vfta[(vid - vid_start) / 32] |= BIT(vid % 32); 51408c2ecf20Sopenharmony_ci 51418c2ecf20Sopenharmony_ci /* if PF is part of this then continue */ 51428c2ecf20Sopenharmony_ci if (test_bit(vid, adapter->active_vlans)) 51438c2ecf20Sopenharmony_ci continue; 51448c2ecf20Sopenharmony_ci } 51458c2ecf20Sopenharmony_ci 51468c2ecf20Sopenharmony_ci /* remove PF from the pool */ 51478c2ecf20Sopenharmony_ci bits = ~BIT(pf_id); 51488c2ecf20Sopenharmony_ci bits &= rd32(E1000_VLVF(i)); 51498c2ecf20Sopenharmony_ci wr32(E1000_VLVF(i), bits); 51508c2ecf20Sopenharmony_ci } 51518c2ecf20Sopenharmony_ci 51528c2ecf20Sopenharmony_ciset_vfta: 51538c2ecf20Sopenharmony_ci /* extract values from active_vlans and write back to VFTA */ 51548c2ecf20Sopenharmony_ci for (i = VFTA_BLOCK_SIZE; i--;) { 51558c2ecf20Sopenharmony_ci vid = (vfta_offset + i) * 32; 51568c2ecf20Sopenharmony_ci word = vid / BITS_PER_LONG; 51578c2ecf20Sopenharmony_ci bits = vid % BITS_PER_LONG; 51588c2ecf20Sopenharmony_ci 51598c2ecf20Sopenharmony_ci vfta[i] |= adapter->active_vlans[word] >> bits; 51608c2ecf20Sopenharmony_ci 51618c2ecf20Sopenharmony_ci hw->mac.ops.write_vfta(hw, vfta_offset + i, vfta[i]); 51628c2ecf20Sopenharmony_ci } 51638c2ecf20Sopenharmony_ci} 51648c2ecf20Sopenharmony_ci 51658c2ecf20Sopenharmony_cistatic void igb_vlan_promisc_disable(struct igb_adapter *adapter) 51668c2ecf20Sopenharmony_ci{ 51678c2ecf20Sopenharmony_ci u32 i; 51688c2ecf20Sopenharmony_ci 51698c2ecf20Sopenharmony_ci /* We are not in VLAN promisc, nothing to do */ 51708c2ecf20Sopenharmony_ci if (!(adapter->flags & IGB_FLAG_VLAN_PROMISC)) 51718c2ecf20Sopenharmony_ci return; 51728c2ecf20Sopenharmony_ci 51738c2ecf20Sopenharmony_ci /* Set flag so we don't redo unnecessary work */ 51748c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_VLAN_PROMISC; 51758c2ecf20Sopenharmony_ci 51768c2ecf20Sopenharmony_ci for (i = 0; i < E1000_VLAN_FILTER_TBL_SIZE; i += VFTA_BLOCK_SIZE) 51778c2ecf20Sopenharmony_ci igb_scrub_vfta(adapter, i); 51788c2ecf20Sopenharmony_ci} 51798c2ecf20Sopenharmony_ci 51808c2ecf20Sopenharmony_ci/** 51818c2ecf20Sopenharmony_ci * igb_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set 51828c2ecf20Sopenharmony_ci * @netdev: network interface device structure 51838c2ecf20Sopenharmony_ci * 51848c2ecf20Sopenharmony_ci * The set_rx_mode entry point is called whenever the unicast or multicast 51858c2ecf20Sopenharmony_ci * address lists or the network interface flags are updated. This routine is 51868c2ecf20Sopenharmony_ci * responsible for configuring the hardware for proper unicast, multicast, 51878c2ecf20Sopenharmony_ci * promiscuous mode, and all-multi behavior. 51888c2ecf20Sopenharmony_ci **/ 51898c2ecf20Sopenharmony_cistatic void igb_set_rx_mode(struct net_device *netdev) 51908c2ecf20Sopenharmony_ci{ 51918c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 51928c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 51938c2ecf20Sopenharmony_ci unsigned int vfn = adapter->vfs_allocated_count; 51948c2ecf20Sopenharmony_ci u32 rctl = 0, vmolr = 0, rlpml = MAX_JUMBO_FRAME_SIZE; 51958c2ecf20Sopenharmony_ci int count; 51968c2ecf20Sopenharmony_ci 51978c2ecf20Sopenharmony_ci /* Check for Promiscuous and All Multicast modes */ 51988c2ecf20Sopenharmony_ci if (netdev->flags & IFF_PROMISC) { 51998c2ecf20Sopenharmony_ci rctl |= E1000_RCTL_UPE | E1000_RCTL_MPE; 52008c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_MPME; 52018c2ecf20Sopenharmony_ci 52028c2ecf20Sopenharmony_ci /* enable use of UTA filter to force packets to default pool */ 52038c2ecf20Sopenharmony_ci if (hw->mac.type == e1000_82576) 52048c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_ROPE; 52058c2ecf20Sopenharmony_ci } else { 52068c2ecf20Sopenharmony_ci if (netdev->flags & IFF_ALLMULTI) { 52078c2ecf20Sopenharmony_ci rctl |= E1000_RCTL_MPE; 52088c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_MPME; 52098c2ecf20Sopenharmony_ci } else { 52108c2ecf20Sopenharmony_ci /* Write addresses to the MTA, if the attempt fails 52118c2ecf20Sopenharmony_ci * then we should just turn on promiscuous mode so 52128c2ecf20Sopenharmony_ci * that we can at least receive multicast traffic 52138c2ecf20Sopenharmony_ci */ 52148c2ecf20Sopenharmony_ci count = igb_write_mc_addr_list(netdev); 52158c2ecf20Sopenharmony_ci if (count < 0) { 52168c2ecf20Sopenharmony_ci rctl |= E1000_RCTL_MPE; 52178c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_MPME; 52188c2ecf20Sopenharmony_ci } else if (count) { 52198c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_ROMPE; 52208c2ecf20Sopenharmony_ci } 52218c2ecf20Sopenharmony_ci } 52228c2ecf20Sopenharmony_ci } 52238c2ecf20Sopenharmony_ci 52248c2ecf20Sopenharmony_ci /* Write addresses to available RAR registers, if there is not 52258c2ecf20Sopenharmony_ci * sufficient space to store all the addresses then enable 52268c2ecf20Sopenharmony_ci * unicast promiscuous mode 52278c2ecf20Sopenharmony_ci */ 52288c2ecf20Sopenharmony_ci if (__dev_uc_sync(netdev, igb_uc_sync, igb_uc_unsync)) { 52298c2ecf20Sopenharmony_ci rctl |= E1000_RCTL_UPE; 52308c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_ROPE; 52318c2ecf20Sopenharmony_ci } 52328c2ecf20Sopenharmony_ci 52338c2ecf20Sopenharmony_ci /* enable VLAN filtering by default */ 52348c2ecf20Sopenharmony_ci rctl |= E1000_RCTL_VFE; 52358c2ecf20Sopenharmony_ci 52368c2ecf20Sopenharmony_ci /* disable VLAN filtering for modes that require it */ 52378c2ecf20Sopenharmony_ci if ((netdev->flags & IFF_PROMISC) || 52388c2ecf20Sopenharmony_ci (netdev->features & NETIF_F_RXALL)) { 52398c2ecf20Sopenharmony_ci /* if we fail to set all rules then just clear VFE */ 52408c2ecf20Sopenharmony_ci if (igb_vlan_promisc_enable(adapter)) 52418c2ecf20Sopenharmony_ci rctl &= ~E1000_RCTL_VFE; 52428c2ecf20Sopenharmony_ci } else { 52438c2ecf20Sopenharmony_ci igb_vlan_promisc_disable(adapter); 52448c2ecf20Sopenharmony_ci } 52458c2ecf20Sopenharmony_ci 52468c2ecf20Sopenharmony_ci /* update state of unicast, multicast, and VLAN filtering modes */ 52478c2ecf20Sopenharmony_ci rctl |= rd32(E1000_RCTL) & ~(E1000_RCTL_UPE | E1000_RCTL_MPE | 52488c2ecf20Sopenharmony_ci E1000_RCTL_VFE); 52498c2ecf20Sopenharmony_ci wr32(E1000_RCTL, rctl); 52508c2ecf20Sopenharmony_ci 52518c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 52528c2ecf20Sopenharmony_ci if (!adapter->vfs_allocated_count) { 52538c2ecf20Sopenharmony_ci if (adapter->max_frame_size <= IGB_MAX_FRAME_BUILD_SKB) 52548c2ecf20Sopenharmony_ci rlpml = IGB_MAX_FRAME_BUILD_SKB; 52558c2ecf20Sopenharmony_ci } 52568c2ecf20Sopenharmony_ci#endif 52578c2ecf20Sopenharmony_ci wr32(E1000_RLPML, rlpml); 52588c2ecf20Sopenharmony_ci 52598c2ecf20Sopenharmony_ci /* In order to support SR-IOV and eventually VMDq it is necessary to set 52608c2ecf20Sopenharmony_ci * the VMOLR to enable the appropriate modes. Without this workaround 52618c2ecf20Sopenharmony_ci * we will have issues with VLAN tag stripping not being done for frames 52628c2ecf20Sopenharmony_ci * that are only arriving because we are the default pool 52638c2ecf20Sopenharmony_ci */ 52648c2ecf20Sopenharmony_ci if ((hw->mac.type < e1000_82576) || (hw->mac.type > e1000_i350)) 52658c2ecf20Sopenharmony_ci return; 52668c2ecf20Sopenharmony_ci 52678c2ecf20Sopenharmony_ci /* set UTA to appropriate mode */ 52688c2ecf20Sopenharmony_ci igb_set_uta(adapter, !!(vmolr & E1000_VMOLR_ROPE)); 52698c2ecf20Sopenharmony_ci 52708c2ecf20Sopenharmony_ci vmolr |= rd32(E1000_VMOLR(vfn)) & 52718c2ecf20Sopenharmony_ci ~(E1000_VMOLR_ROPE | E1000_VMOLR_MPME | E1000_VMOLR_ROMPE); 52728c2ecf20Sopenharmony_ci 52738c2ecf20Sopenharmony_ci /* enable Rx jumbo frames, restrict as needed to support build_skb */ 52748c2ecf20Sopenharmony_ci vmolr &= ~E1000_VMOLR_RLPML_MASK; 52758c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 52768c2ecf20Sopenharmony_ci if (adapter->max_frame_size <= IGB_MAX_FRAME_BUILD_SKB) 52778c2ecf20Sopenharmony_ci vmolr |= IGB_MAX_FRAME_BUILD_SKB; 52788c2ecf20Sopenharmony_ci else 52798c2ecf20Sopenharmony_ci#endif 52808c2ecf20Sopenharmony_ci vmolr |= MAX_JUMBO_FRAME_SIZE; 52818c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_LPE; 52828c2ecf20Sopenharmony_ci 52838c2ecf20Sopenharmony_ci wr32(E1000_VMOLR(vfn), vmolr); 52848c2ecf20Sopenharmony_ci 52858c2ecf20Sopenharmony_ci igb_restore_vf_multicasts(adapter); 52868c2ecf20Sopenharmony_ci} 52878c2ecf20Sopenharmony_ci 52888c2ecf20Sopenharmony_cistatic void igb_check_wvbr(struct igb_adapter *adapter) 52898c2ecf20Sopenharmony_ci{ 52908c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 52918c2ecf20Sopenharmony_ci u32 wvbr = 0; 52928c2ecf20Sopenharmony_ci 52938c2ecf20Sopenharmony_ci switch (hw->mac.type) { 52948c2ecf20Sopenharmony_ci case e1000_82576: 52958c2ecf20Sopenharmony_ci case e1000_i350: 52968c2ecf20Sopenharmony_ci wvbr = rd32(E1000_WVBR); 52978c2ecf20Sopenharmony_ci if (!wvbr) 52988c2ecf20Sopenharmony_ci return; 52998c2ecf20Sopenharmony_ci break; 53008c2ecf20Sopenharmony_ci default: 53018c2ecf20Sopenharmony_ci break; 53028c2ecf20Sopenharmony_ci } 53038c2ecf20Sopenharmony_ci 53048c2ecf20Sopenharmony_ci adapter->wvbr |= wvbr; 53058c2ecf20Sopenharmony_ci} 53068c2ecf20Sopenharmony_ci 53078c2ecf20Sopenharmony_ci#define IGB_STAGGERED_QUEUE_OFFSET 8 53088c2ecf20Sopenharmony_ci 53098c2ecf20Sopenharmony_cistatic void igb_spoof_check(struct igb_adapter *adapter) 53108c2ecf20Sopenharmony_ci{ 53118c2ecf20Sopenharmony_ci int j; 53128c2ecf20Sopenharmony_ci 53138c2ecf20Sopenharmony_ci if (!adapter->wvbr) 53148c2ecf20Sopenharmony_ci return; 53158c2ecf20Sopenharmony_ci 53168c2ecf20Sopenharmony_ci for (j = 0; j < adapter->vfs_allocated_count; j++) { 53178c2ecf20Sopenharmony_ci if (adapter->wvbr & BIT(j) || 53188c2ecf20Sopenharmony_ci adapter->wvbr & BIT(j + IGB_STAGGERED_QUEUE_OFFSET)) { 53198c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, 53208c2ecf20Sopenharmony_ci "Spoof event(s) detected on VF %d\n", j); 53218c2ecf20Sopenharmony_ci adapter->wvbr &= 53228c2ecf20Sopenharmony_ci ~(BIT(j) | 53238c2ecf20Sopenharmony_ci BIT(j + IGB_STAGGERED_QUEUE_OFFSET)); 53248c2ecf20Sopenharmony_ci } 53258c2ecf20Sopenharmony_ci } 53268c2ecf20Sopenharmony_ci} 53278c2ecf20Sopenharmony_ci 53288c2ecf20Sopenharmony_ci/* Need to wait a few seconds after link up to get diagnostic information from 53298c2ecf20Sopenharmony_ci * the phy 53308c2ecf20Sopenharmony_ci */ 53318c2ecf20Sopenharmony_cistatic void igb_update_phy_info(struct timer_list *t) 53328c2ecf20Sopenharmony_ci{ 53338c2ecf20Sopenharmony_ci struct igb_adapter *adapter = from_timer(adapter, t, phy_info_timer); 53348c2ecf20Sopenharmony_ci igb_get_phy_info(&adapter->hw); 53358c2ecf20Sopenharmony_ci} 53368c2ecf20Sopenharmony_ci 53378c2ecf20Sopenharmony_ci/** 53388c2ecf20Sopenharmony_ci * igb_has_link - check shared code for link and determine up/down 53398c2ecf20Sopenharmony_ci * @adapter: pointer to driver private info 53408c2ecf20Sopenharmony_ci **/ 53418c2ecf20Sopenharmony_cibool igb_has_link(struct igb_adapter *adapter) 53428c2ecf20Sopenharmony_ci{ 53438c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 53448c2ecf20Sopenharmony_ci bool link_active = false; 53458c2ecf20Sopenharmony_ci 53468c2ecf20Sopenharmony_ci /* get_link_status is set on LSC (link status) interrupt or 53478c2ecf20Sopenharmony_ci * rx sequence error interrupt. get_link_status will stay 53488c2ecf20Sopenharmony_ci * false until the e1000_check_for_link establishes link 53498c2ecf20Sopenharmony_ci * for copper adapters ONLY 53508c2ecf20Sopenharmony_ci */ 53518c2ecf20Sopenharmony_ci switch (hw->phy.media_type) { 53528c2ecf20Sopenharmony_ci case e1000_media_type_copper: 53538c2ecf20Sopenharmony_ci if (!hw->mac.get_link_status) 53548c2ecf20Sopenharmony_ci return true; 53558c2ecf20Sopenharmony_ci fallthrough; 53568c2ecf20Sopenharmony_ci case e1000_media_type_internal_serdes: 53578c2ecf20Sopenharmony_ci hw->mac.ops.check_for_link(hw); 53588c2ecf20Sopenharmony_ci link_active = !hw->mac.get_link_status; 53598c2ecf20Sopenharmony_ci break; 53608c2ecf20Sopenharmony_ci default: 53618c2ecf20Sopenharmony_ci case e1000_media_type_unknown: 53628c2ecf20Sopenharmony_ci break; 53638c2ecf20Sopenharmony_ci } 53648c2ecf20Sopenharmony_ci 53658c2ecf20Sopenharmony_ci if (((hw->mac.type == e1000_i210) || 53668c2ecf20Sopenharmony_ci (hw->mac.type == e1000_i211)) && 53678c2ecf20Sopenharmony_ci (hw->phy.id == I210_I_PHY_ID)) { 53688c2ecf20Sopenharmony_ci if (!netif_carrier_ok(adapter->netdev)) { 53698c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; 53708c2ecf20Sopenharmony_ci } else if (!(adapter->flags & IGB_FLAG_NEED_LINK_UPDATE)) { 53718c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_NEED_LINK_UPDATE; 53728c2ecf20Sopenharmony_ci adapter->link_check_timeout = jiffies; 53738c2ecf20Sopenharmony_ci } 53748c2ecf20Sopenharmony_ci } 53758c2ecf20Sopenharmony_ci 53768c2ecf20Sopenharmony_ci return link_active; 53778c2ecf20Sopenharmony_ci} 53788c2ecf20Sopenharmony_ci 53798c2ecf20Sopenharmony_cistatic bool igb_thermal_sensor_event(struct e1000_hw *hw, u32 event) 53808c2ecf20Sopenharmony_ci{ 53818c2ecf20Sopenharmony_ci bool ret = false; 53828c2ecf20Sopenharmony_ci u32 ctrl_ext, thstat; 53838c2ecf20Sopenharmony_ci 53848c2ecf20Sopenharmony_ci /* check for thermal sensor event on i350 copper only */ 53858c2ecf20Sopenharmony_ci if (hw->mac.type == e1000_i350) { 53868c2ecf20Sopenharmony_ci thstat = rd32(E1000_THSTAT); 53878c2ecf20Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 53888c2ecf20Sopenharmony_ci 53898c2ecf20Sopenharmony_ci if ((hw->phy.media_type == e1000_media_type_copper) && 53908c2ecf20Sopenharmony_ci !(ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII)) 53918c2ecf20Sopenharmony_ci ret = !!(thstat & event); 53928c2ecf20Sopenharmony_ci } 53938c2ecf20Sopenharmony_ci 53948c2ecf20Sopenharmony_ci return ret; 53958c2ecf20Sopenharmony_ci} 53968c2ecf20Sopenharmony_ci 53978c2ecf20Sopenharmony_ci/** 53988c2ecf20Sopenharmony_ci * igb_check_lvmmc - check for malformed packets received 53998c2ecf20Sopenharmony_ci * and indicated in LVMMC register 54008c2ecf20Sopenharmony_ci * @adapter: pointer to adapter 54018c2ecf20Sopenharmony_ci **/ 54028c2ecf20Sopenharmony_cistatic void igb_check_lvmmc(struct igb_adapter *adapter) 54038c2ecf20Sopenharmony_ci{ 54048c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 54058c2ecf20Sopenharmony_ci u32 lvmmc; 54068c2ecf20Sopenharmony_ci 54078c2ecf20Sopenharmony_ci lvmmc = rd32(E1000_LVMMC); 54088c2ecf20Sopenharmony_ci if (lvmmc) { 54098c2ecf20Sopenharmony_ci if (unlikely(net_ratelimit())) { 54108c2ecf20Sopenharmony_ci netdev_warn(adapter->netdev, 54118c2ecf20Sopenharmony_ci "malformed Tx packet detected and dropped, LVMMC:0x%08x\n", 54128c2ecf20Sopenharmony_ci lvmmc); 54138c2ecf20Sopenharmony_ci } 54148c2ecf20Sopenharmony_ci } 54158c2ecf20Sopenharmony_ci} 54168c2ecf20Sopenharmony_ci 54178c2ecf20Sopenharmony_ci/** 54188c2ecf20Sopenharmony_ci * igb_watchdog - Timer Call-back 54198c2ecf20Sopenharmony_ci * @t: pointer to timer_list containing our private info pointer 54208c2ecf20Sopenharmony_ci **/ 54218c2ecf20Sopenharmony_cistatic void igb_watchdog(struct timer_list *t) 54228c2ecf20Sopenharmony_ci{ 54238c2ecf20Sopenharmony_ci struct igb_adapter *adapter = from_timer(adapter, t, watchdog_timer); 54248c2ecf20Sopenharmony_ci /* Do the rest outside of interrupt context */ 54258c2ecf20Sopenharmony_ci schedule_work(&adapter->watchdog_task); 54268c2ecf20Sopenharmony_ci} 54278c2ecf20Sopenharmony_ci 54288c2ecf20Sopenharmony_cistatic void igb_watchdog_task(struct work_struct *work) 54298c2ecf20Sopenharmony_ci{ 54308c2ecf20Sopenharmony_ci struct igb_adapter *adapter = container_of(work, 54318c2ecf20Sopenharmony_ci struct igb_adapter, 54328c2ecf20Sopenharmony_ci watchdog_task); 54338c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 54348c2ecf20Sopenharmony_ci struct e1000_phy_info *phy = &hw->phy; 54358c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 54368c2ecf20Sopenharmony_ci u32 link; 54378c2ecf20Sopenharmony_ci int i; 54388c2ecf20Sopenharmony_ci u32 connsw; 54398c2ecf20Sopenharmony_ci u16 phy_data, retry_count = 20; 54408c2ecf20Sopenharmony_ci 54418c2ecf20Sopenharmony_ci link = igb_has_link(adapter); 54428c2ecf20Sopenharmony_ci 54438c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) { 54448c2ecf20Sopenharmony_ci if (time_after(jiffies, (adapter->link_check_timeout + HZ))) 54458c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; 54468c2ecf20Sopenharmony_ci else 54478c2ecf20Sopenharmony_ci link = false; 54488c2ecf20Sopenharmony_ci } 54498c2ecf20Sopenharmony_ci 54508c2ecf20Sopenharmony_ci /* Force link down if we have fiber to swap to */ 54518c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_MAS_ENABLE) { 54528c2ecf20Sopenharmony_ci if (hw->phy.media_type == e1000_media_type_copper) { 54538c2ecf20Sopenharmony_ci connsw = rd32(E1000_CONNSW); 54548c2ecf20Sopenharmony_ci if (!(connsw & E1000_CONNSW_AUTOSENSE_EN)) 54558c2ecf20Sopenharmony_ci link = 0; 54568c2ecf20Sopenharmony_ci } 54578c2ecf20Sopenharmony_ci } 54588c2ecf20Sopenharmony_ci if (link) { 54598c2ecf20Sopenharmony_ci /* Perform a reset if the media type changed. */ 54608c2ecf20Sopenharmony_ci if (hw->dev_spec._82575.media_changed) { 54618c2ecf20Sopenharmony_ci hw->dev_spec._82575.media_changed = false; 54628c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_MEDIA_RESET; 54638c2ecf20Sopenharmony_ci igb_reset(adapter); 54648c2ecf20Sopenharmony_ci } 54658c2ecf20Sopenharmony_ci /* Cancel scheduled suspend requests. */ 54668c2ecf20Sopenharmony_ci pm_runtime_resume(netdev->dev.parent); 54678c2ecf20Sopenharmony_ci 54688c2ecf20Sopenharmony_ci if (!netif_carrier_ok(netdev)) { 54698c2ecf20Sopenharmony_ci u32 ctrl; 54708c2ecf20Sopenharmony_ci 54718c2ecf20Sopenharmony_ci hw->mac.ops.get_speed_and_duplex(hw, 54728c2ecf20Sopenharmony_ci &adapter->link_speed, 54738c2ecf20Sopenharmony_ci &adapter->link_duplex); 54748c2ecf20Sopenharmony_ci 54758c2ecf20Sopenharmony_ci ctrl = rd32(E1000_CTRL); 54768c2ecf20Sopenharmony_ci /* Links status message must follow this format */ 54778c2ecf20Sopenharmony_ci netdev_info(netdev, 54788c2ecf20Sopenharmony_ci "igb: %s NIC Link is Up %d Mbps %s Duplex, Flow Control: %s\n", 54798c2ecf20Sopenharmony_ci netdev->name, 54808c2ecf20Sopenharmony_ci adapter->link_speed, 54818c2ecf20Sopenharmony_ci adapter->link_duplex == FULL_DUPLEX ? 54828c2ecf20Sopenharmony_ci "Full" : "Half", 54838c2ecf20Sopenharmony_ci (ctrl & E1000_CTRL_TFCE) && 54848c2ecf20Sopenharmony_ci (ctrl & E1000_CTRL_RFCE) ? "RX/TX" : 54858c2ecf20Sopenharmony_ci (ctrl & E1000_CTRL_RFCE) ? "RX" : 54868c2ecf20Sopenharmony_ci (ctrl & E1000_CTRL_TFCE) ? "TX" : "None"); 54878c2ecf20Sopenharmony_ci 54888c2ecf20Sopenharmony_ci /* disable EEE if enabled */ 54898c2ecf20Sopenharmony_ci if ((adapter->flags & IGB_FLAG_EEE) && 54908c2ecf20Sopenharmony_ci (adapter->link_duplex == HALF_DUPLEX)) { 54918c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, 54928c2ecf20Sopenharmony_ci "EEE Disabled: unsupported at half duplex. Re-enable using ethtool when at full duplex.\n"); 54938c2ecf20Sopenharmony_ci adapter->hw.dev_spec._82575.eee_disable = true; 54948c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_EEE; 54958c2ecf20Sopenharmony_ci } 54968c2ecf20Sopenharmony_ci 54978c2ecf20Sopenharmony_ci /* check if SmartSpeed worked */ 54988c2ecf20Sopenharmony_ci igb_check_downshift(hw); 54998c2ecf20Sopenharmony_ci if (phy->speed_downgraded) 55008c2ecf20Sopenharmony_ci netdev_warn(netdev, "Link Speed was downgraded by SmartSpeed\n"); 55018c2ecf20Sopenharmony_ci 55028c2ecf20Sopenharmony_ci /* check for thermal sensor event */ 55038c2ecf20Sopenharmony_ci if (igb_thermal_sensor_event(hw, 55048c2ecf20Sopenharmony_ci E1000_THSTAT_LINK_THROTTLE)) 55058c2ecf20Sopenharmony_ci netdev_info(netdev, "The network adapter link speed was downshifted because it overheated\n"); 55068c2ecf20Sopenharmony_ci 55078c2ecf20Sopenharmony_ci /* adjust timeout factor according to speed/duplex */ 55088c2ecf20Sopenharmony_ci adapter->tx_timeout_factor = 1; 55098c2ecf20Sopenharmony_ci switch (adapter->link_speed) { 55108c2ecf20Sopenharmony_ci case SPEED_10: 55118c2ecf20Sopenharmony_ci adapter->tx_timeout_factor = 14; 55128c2ecf20Sopenharmony_ci break; 55138c2ecf20Sopenharmony_ci case SPEED_100: 55148c2ecf20Sopenharmony_ci /* maybe add some timeout factor ? */ 55158c2ecf20Sopenharmony_ci break; 55168c2ecf20Sopenharmony_ci } 55178c2ecf20Sopenharmony_ci 55188c2ecf20Sopenharmony_ci if (adapter->link_speed != SPEED_1000 || 55198c2ecf20Sopenharmony_ci !hw->phy.ops.read_reg) 55208c2ecf20Sopenharmony_ci goto no_wait; 55218c2ecf20Sopenharmony_ci 55228c2ecf20Sopenharmony_ci /* wait for Remote receiver status OK */ 55238c2ecf20Sopenharmony_ciretry_read_status: 55248c2ecf20Sopenharmony_ci if (!igb_read_phy_reg(hw, PHY_1000T_STATUS, 55258c2ecf20Sopenharmony_ci &phy_data)) { 55268c2ecf20Sopenharmony_ci if (!(phy_data & SR_1000T_REMOTE_RX_STATUS) && 55278c2ecf20Sopenharmony_ci retry_count) { 55288c2ecf20Sopenharmony_ci msleep(100); 55298c2ecf20Sopenharmony_ci retry_count--; 55308c2ecf20Sopenharmony_ci goto retry_read_status; 55318c2ecf20Sopenharmony_ci } else if (!retry_count) { 55328c2ecf20Sopenharmony_ci dev_err(&adapter->pdev->dev, "exceed max 2 second\n"); 55338c2ecf20Sopenharmony_ci } 55348c2ecf20Sopenharmony_ci } else { 55358c2ecf20Sopenharmony_ci dev_err(&adapter->pdev->dev, "read 1000Base-T Status Reg\n"); 55368c2ecf20Sopenharmony_ci } 55378c2ecf20Sopenharmony_cino_wait: 55388c2ecf20Sopenharmony_ci netif_carrier_on(netdev); 55398c2ecf20Sopenharmony_ci 55408c2ecf20Sopenharmony_ci igb_ping_all_vfs(adapter); 55418c2ecf20Sopenharmony_ci igb_check_vf_rate_limit(adapter); 55428c2ecf20Sopenharmony_ci 55438c2ecf20Sopenharmony_ci /* link state has changed, schedule phy info update */ 55448c2ecf20Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) 55458c2ecf20Sopenharmony_ci mod_timer(&adapter->phy_info_timer, 55468c2ecf20Sopenharmony_ci round_jiffies(jiffies + 2 * HZ)); 55478c2ecf20Sopenharmony_ci } 55488c2ecf20Sopenharmony_ci } else { 55498c2ecf20Sopenharmony_ci if (netif_carrier_ok(netdev)) { 55508c2ecf20Sopenharmony_ci adapter->link_speed = 0; 55518c2ecf20Sopenharmony_ci adapter->link_duplex = 0; 55528c2ecf20Sopenharmony_ci 55538c2ecf20Sopenharmony_ci /* check for thermal sensor event */ 55548c2ecf20Sopenharmony_ci if (igb_thermal_sensor_event(hw, 55558c2ecf20Sopenharmony_ci E1000_THSTAT_PWR_DOWN)) { 55568c2ecf20Sopenharmony_ci netdev_err(netdev, "The network adapter was stopped because it overheated\n"); 55578c2ecf20Sopenharmony_ci } 55588c2ecf20Sopenharmony_ci 55598c2ecf20Sopenharmony_ci /* Links status message must follow this format */ 55608c2ecf20Sopenharmony_ci netdev_info(netdev, "igb: %s NIC Link is Down\n", 55618c2ecf20Sopenharmony_ci netdev->name); 55628c2ecf20Sopenharmony_ci netif_carrier_off(netdev); 55638c2ecf20Sopenharmony_ci 55648c2ecf20Sopenharmony_ci igb_ping_all_vfs(adapter); 55658c2ecf20Sopenharmony_ci 55668c2ecf20Sopenharmony_ci /* link state has changed, schedule phy info update */ 55678c2ecf20Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) 55688c2ecf20Sopenharmony_ci mod_timer(&adapter->phy_info_timer, 55698c2ecf20Sopenharmony_ci round_jiffies(jiffies + 2 * HZ)); 55708c2ecf20Sopenharmony_ci 55718c2ecf20Sopenharmony_ci /* link is down, time to check for alternate media */ 55728c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_MAS_ENABLE) { 55738c2ecf20Sopenharmony_ci igb_check_swap_media(adapter); 55748c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_MEDIA_RESET) { 55758c2ecf20Sopenharmony_ci schedule_work(&adapter->reset_task); 55768c2ecf20Sopenharmony_ci /* return immediately */ 55778c2ecf20Sopenharmony_ci return; 55788c2ecf20Sopenharmony_ci } 55798c2ecf20Sopenharmony_ci } 55808c2ecf20Sopenharmony_ci pm_schedule_suspend(netdev->dev.parent, 55818c2ecf20Sopenharmony_ci MSEC_PER_SEC * 5); 55828c2ecf20Sopenharmony_ci 55838c2ecf20Sopenharmony_ci /* also check for alternate media here */ 55848c2ecf20Sopenharmony_ci } else if (!netif_carrier_ok(netdev) && 55858c2ecf20Sopenharmony_ci (adapter->flags & IGB_FLAG_MAS_ENABLE)) { 55868c2ecf20Sopenharmony_ci igb_check_swap_media(adapter); 55878c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_MEDIA_RESET) { 55888c2ecf20Sopenharmony_ci schedule_work(&adapter->reset_task); 55898c2ecf20Sopenharmony_ci /* return immediately */ 55908c2ecf20Sopenharmony_ci return; 55918c2ecf20Sopenharmony_ci } 55928c2ecf20Sopenharmony_ci } 55938c2ecf20Sopenharmony_ci } 55948c2ecf20Sopenharmony_ci 55958c2ecf20Sopenharmony_ci spin_lock(&adapter->stats64_lock); 55968c2ecf20Sopenharmony_ci igb_update_stats(adapter); 55978c2ecf20Sopenharmony_ci spin_unlock(&adapter->stats64_lock); 55988c2ecf20Sopenharmony_ci 55998c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 56008c2ecf20Sopenharmony_ci struct igb_ring *tx_ring = adapter->tx_ring[i]; 56018c2ecf20Sopenharmony_ci if (!netif_carrier_ok(netdev)) { 56028c2ecf20Sopenharmony_ci /* We've lost link, so the controller stops DMA, 56038c2ecf20Sopenharmony_ci * but we've got queued Tx work that's never going 56048c2ecf20Sopenharmony_ci * to get done, so reset controller to flush Tx. 56058c2ecf20Sopenharmony_ci * (Do the reset outside of interrupt context). 56068c2ecf20Sopenharmony_ci */ 56078c2ecf20Sopenharmony_ci if (igb_desc_unused(tx_ring) + 1 < tx_ring->count) { 56088c2ecf20Sopenharmony_ci adapter->tx_timeout_count++; 56098c2ecf20Sopenharmony_ci schedule_work(&adapter->reset_task); 56108c2ecf20Sopenharmony_ci /* return immediately since reset is imminent */ 56118c2ecf20Sopenharmony_ci return; 56128c2ecf20Sopenharmony_ci } 56138c2ecf20Sopenharmony_ci } 56148c2ecf20Sopenharmony_ci 56158c2ecf20Sopenharmony_ci /* Force detection of hung controller every watchdog period */ 56168c2ecf20Sopenharmony_ci set_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); 56178c2ecf20Sopenharmony_ci } 56188c2ecf20Sopenharmony_ci 56198c2ecf20Sopenharmony_ci /* Cause software interrupt to ensure Rx ring is cleaned */ 56208c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) { 56218c2ecf20Sopenharmony_ci u32 eics = 0; 56228c2ecf20Sopenharmony_ci 56238c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) 56248c2ecf20Sopenharmony_ci eics |= adapter->q_vector[i]->eims_value; 56258c2ecf20Sopenharmony_ci wr32(E1000_EICS, eics); 56268c2ecf20Sopenharmony_ci } else { 56278c2ecf20Sopenharmony_ci wr32(E1000_ICS, E1000_ICS_RXDMT0); 56288c2ecf20Sopenharmony_ci } 56298c2ecf20Sopenharmony_ci 56308c2ecf20Sopenharmony_ci igb_spoof_check(adapter); 56318c2ecf20Sopenharmony_ci igb_ptp_rx_hang(adapter); 56328c2ecf20Sopenharmony_ci igb_ptp_tx_hang(adapter); 56338c2ecf20Sopenharmony_ci 56348c2ecf20Sopenharmony_ci /* Check LVMMC register on i350/i354 only */ 56358c2ecf20Sopenharmony_ci if ((adapter->hw.mac.type == e1000_i350) || 56368c2ecf20Sopenharmony_ci (adapter->hw.mac.type == e1000_i354)) 56378c2ecf20Sopenharmony_ci igb_check_lvmmc(adapter); 56388c2ecf20Sopenharmony_ci 56398c2ecf20Sopenharmony_ci /* Reset the timer */ 56408c2ecf20Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) { 56418c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) 56428c2ecf20Sopenharmony_ci mod_timer(&adapter->watchdog_timer, 56438c2ecf20Sopenharmony_ci round_jiffies(jiffies + HZ)); 56448c2ecf20Sopenharmony_ci else 56458c2ecf20Sopenharmony_ci mod_timer(&adapter->watchdog_timer, 56468c2ecf20Sopenharmony_ci round_jiffies(jiffies + 2 * HZ)); 56478c2ecf20Sopenharmony_ci } 56488c2ecf20Sopenharmony_ci} 56498c2ecf20Sopenharmony_ci 56508c2ecf20Sopenharmony_cienum latency_range { 56518c2ecf20Sopenharmony_ci lowest_latency = 0, 56528c2ecf20Sopenharmony_ci low_latency = 1, 56538c2ecf20Sopenharmony_ci bulk_latency = 2, 56548c2ecf20Sopenharmony_ci latency_invalid = 255 56558c2ecf20Sopenharmony_ci}; 56568c2ecf20Sopenharmony_ci 56578c2ecf20Sopenharmony_ci/** 56588c2ecf20Sopenharmony_ci * igb_update_ring_itr - update the dynamic ITR value based on packet size 56598c2ecf20Sopenharmony_ci * @q_vector: pointer to q_vector 56608c2ecf20Sopenharmony_ci * 56618c2ecf20Sopenharmony_ci * Stores a new ITR value based on strictly on packet size. This 56628c2ecf20Sopenharmony_ci * algorithm is less sophisticated than that used in igb_update_itr, 56638c2ecf20Sopenharmony_ci * due to the difficulty of synchronizing statistics across multiple 56648c2ecf20Sopenharmony_ci * receive rings. The divisors and thresholds used by this function 56658c2ecf20Sopenharmony_ci * were determined based on theoretical maximum wire speed and testing 56668c2ecf20Sopenharmony_ci * data, in order to minimize response time while increasing bulk 56678c2ecf20Sopenharmony_ci * throughput. 56688c2ecf20Sopenharmony_ci * This functionality is controlled by ethtool's coalescing settings. 56698c2ecf20Sopenharmony_ci * NOTE: This function is called only when operating in a multiqueue 56708c2ecf20Sopenharmony_ci * receive environment. 56718c2ecf20Sopenharmony_ci **/ 56728c2ecf20Sopenharmony_cistatic void igb_update_ring_itr(struct igb_q_vector *q_vector) 56738c2ecf20Sopenharmony_ci{ 56748c2ecf20Sopenharmony_ci int new_val = q_vector->itr_val; 56758c2ecf20Sopenharmony_ci int avg_wire_size = 0; 56768c2ecf20Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 56778c2ecf20Sopenharmony_ci unsigned int packets; 56788c2ecf20Sopenharmony_ci 56798c2ecf20Sopenharmony_ci /* For non-gigabit speeds, just fix the interrupt rate at 4000 56808c2ecf20Sopenharmony_ci * ints/sec - ITR timer value of 120 ticks. 56818c2ecf20Sopenharmony_ci */ 56828c2ecf20Sopenharmony_ci if (adapter->link_speed != SPEED_1000) { 56838c2ecf20Sopenharmony_ci new_val = IGB_4K_ITR; 56848c2ecf20Sopenharmony_ci goto set_itr_val; 56858c2ecf20Sopenharmony_ci } 56868c2ecf20Sopenharmony_ci 56878c2ecf20Sopenharmony_ci packets = q_vector->rx.total_packets; 56888c2ecf20Sopenharmony_ci if (packets) 56898c2ecf20Sopenharmony_ci avg_wire_size = q_vector->rx.total_bytes / packets; 56908c2ecf20Sopenharmony_ci 56918c2ecf20Sopenharmony_ci packets = q_vector->tx.total_packets; 56928c2ecf20Sopenharmony_ci if (packets) 56938c2ecf20Sopenharmony_ci avg_wire_size = max_t(u32, avg_wire_size, 56948c2ecf20Sopenharmony_ci q_vector->tx.total_bytes / packets); 56958c2ecf20Sopenharmony_ci 56968c2ecf20Sopenharmony_ci /* if avg_wire_size isn't set no work was done */ 56978c2ecf20Sopenharmony_ci if (!avg_wire_size) 56988c2ecf20Sopenharmony_ci goto clear_counts; 56998c2ecf20Sopenharmony_ci 57008c2ecf20Sopenharmony_ci /* Add 24 bytes to size to account for CRC, preamble, and gap */ 57018c2ecf20Sopenharmony_ci avg_wire_size += 24; 57028c2ecf20Sopenharmony_ci 57038c2ecf20Sopenharmony_ci /* Don't starve jumbo frames */ 57048c2ecf20Sopenharmony_ci avg_wire_size = min(avg_wire_size, 3000); 57058c2ecf20Sopenharmony_ci 57068c2ecf20Sopenharmony_ci /* Give a little boost to mid-size frames */ 57078c2ecf20Sopenharmony_ci if ((avg_wire_size > 300) && (avg_wire_size < 1200)) 57088c2ecf20Sopenharmony_ci new_val = avg_wire_size / 3; 57098c2ecf20Sopenharmony_ci else 57108c2ecf20Sopenharmony_ci new_val = avg_wire_size / 2; 57118c2ecf20Sopenharmony_ci 57128c2ecf20Sopenharmony_ci /* conservative mode (itr 3) eliminates the lowest_latency setting */ 57138c2ecf20Sopenharmony_ci if (new_val < IGB_20K_ITR && 57148c2ecf20Sopenharmony_ci ((q_vector->rx.ring && adapter->rx_itr_setting == 3) || 57158c2ecf20Sopenharmony_ci (!q_vector->rx.ring && adapter->tx_itr_setting == 3))) 57168c2ecf20Sopenharmony_ci new_val = IGB_20K_ITR; 57178c2ecf20Sopenharmony_ci 57188c2ecf20Sopenharmony_ciset_itr_val: 57198c2ecf20Sopenharmony_ci if (new_val != q_vector->itr_val) { 57208c2ecf20Sopenharmony_ci q_vector->itr_val = new_val; 57218c2ecf20Sopenharmony_ci q_vector->set_itr = 1; 57228c2ecf20Sopenharmony_ci } 57238c2ecf20Sopenharmony_ciclear_counts: 57248c2ecf20Sopenharmony_ci q_vector->rx.total_bytes = 0; 57258c2ecf20Sopenharmony_ci q_vector->rx.total_packets = 0; 57268c2ecf20Sopenharmony_ci q_vector->tx.total_bytes = 0; 57278c2ecf20Sopenharmony_ci q_vector->tx.total_packets = 0; 57288c2ecf20Sopenharmony_ci} 57298c2ecf20Sopenharmony_ci 57308c2ecf20Sopenharmony_ci/** 57318c2ecf20Sopenharmony_ci * igb_update_itr - update the dynamic ITR value based on statistics 57328c2ecf20Sopenharmony_ci * @q_vector: pointer to q_vector 57338c2ecf20Sopenharmony_ci * @ring_container: ring info to update the itr for 57348c2ecf20Sopenharmony_ci * 57358c2ecf20Sopenharmony_ci * Stores a new ITR value based on packets and byte 57368c2ecf20Sopenharmony_ci * counts during the last interrupt. The advantage of per interrupt 57378c2ecf20Sopenharmony_ci * computation is faster updates and more accurate ITR for the current 57388c2ecf20Sopenharmony_ci * traffic pattern. Constants in this function were computed 57398c2ecf20Sopenharmony_ci * based on theoretical maximum wire speed and thresholds were set based 57408c2ecf20Sopenharmony_ci * on testing data as well as attempting to minimize response time 57418c2ecf20Sopenharmony_ci * while increasing bulk throughput. 57428c2ecf20Sopenharmony_ci * This functionality is controlled by ethtool's coalescing settings. 57438c2ecf20Sopenharmony_ci * NOTE: These calculations are only valid when operating in a single- 57448c2ecf20Sopenharmony_ci * queue environment. 57458c2ecf20Sopenharmony_ci **/ 57468c2ecf20Sopenharmony_cistatic void igb_update_itr(struct igb_q_vector *q_vector, 57478c2ecf20Sopenharmony_ci struct igb_ring_container *ring_container) 57488c2ecf20Sopenharmony_ci{ 57498c2ecf20Sopenharmony_ci unsigned int packets = ring_container->total_packets; 57508c2ecf20Sopenharmony_ci unsigned int bytes = ring_container->total_bytes; 57518c2ecf20Sopenharmony_ci u8 itrval = ring_container->itr; 57528c2ecf20Sopenharmony_ci 57538c2ecf20Sopenharmony_ci /* no packets, exit with status unchanged */ 57548c2ecf20Sopenharmony_ci if (packets == 0) 57558c2ecf20Sopenharmony_ci return; 57568c2ecf20Sopenharmony_ci 57578c2ecf20Sopenharmony_ci switch (itrval) { 57588c2ecf20Sopenharmony_ci case lowest_latency: 57598c2ecf20Sopenharmony_ci /* handle TSO and jumbo frames */ 57608c2ecf20Sopenharmony_ci if (bytes/packets > 8000) 57618c2ecf20Sopenharmony_ci itrval = bulk_latency; 57628c2ecf20Sopenharmony_ci else if ((packets < 5) && (bytes > 512)) 57638c2ecf20Sopenharmony_ci itrval = low_latency; 57648c2ecf20Sopenharmony_ci break; 57658c2ecf20Sopenharmony_ci case low_latency: /* 50 usec aka 20000 ints/s */ 57668c2ecf20Sopenharmony_ci if (bytes > 10000) { 57678c2ecf20Sopenharmony_ci /* this if handles the TSO accounting */ 57688c2ecf20Sopenharmony_ci if (bytes/packets > 8000) 57698c2ecf20Sopenharmony_ci itrval = bulk_latency; 57708c2ecf20Sopenharmony_ci else if ((packets < 10) || ((bytes/packets) > 1200)) 57718c2ecf20Sopenharmony_ci itrval = bulk_latency; 57728c2ecf20Sopenharmony_ci else if ((packets > 35)) 57738c2ecf20Sopenharmony_ci itrval = lowest_latency; 57748c2ecf20Sopenharmony_ci } else if (bytes/packets > 2000) { 57758c2ecf20Sopenharmony_ci itrval = bulk_latency; 57768c2ecf20Sopenharmony_ci } else if (packets <= 2 && bytes < 512) { 57778c2ecf20Sopenharmony_ci itrval = lowest_latency; 57788c2ecf20Sopenharmony_ci } 57798c2ecf20Sopenharmony_ci break; 57808c2ecf20Sopenharmony_ci case bulk_latency: /* 250 usec aka 4000 ints/s */ 57818c2ecf20Sopenharmony_ci if (bytes > 25000) { 57828c2ecf20Sopenharmony_ci if (packets > 35) 57838c2ecf20Sopenharmony_ci itrval = low_latency; 57848c2ecf20Sopenharmony_ci } else if (bytes < 1500) { 57858c2ecf20Sopenharmony_ci itrval = low_latency; 57868c2ecf20Sopenharmony_ci } 57878c2ecf20Sopenharmony_ci break; 57888c2ecf20Sopenharmony_ci } 57898c2ecf20Sopenharmony_ci 57908c2ecf20Sopenharmony_ci /* clear work counters since we have the values we need */ 57918c2ecf20Sopenharmony_ci ring_container->total_bytes = 0; 57928c2ecf20Sopenharmony_ci ring_container->total_packets = 0; 57938c2ecf20Sopenharmony_ci 57948c2ecf20Sopenharmony_ci /* write updated itr to ring container */ 57958c2ecf20Sopenharmony_ci ring_container->itr = itrval; 57968c2ecf20Sopenharmony_ci} 57978c2ecf20Sopenharmony_ci 57988c2ecf20Sopenharmony_cistatic void igb_set_itr(struct igb_q_vector *q_vector) 57998c2ecf20Sopenharmony_ci{ 58008c2ecf20Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 58018c2ecf20Sopenharmony_ci u32 new_itr = q_vector->itr_val; 58028c2ecf20Sopenharmony_ci u8 current_itr = 0; 58038c2ecf20Sopenharmony_ci 58048c2ecf20Sopenharmony_ci /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ 58058c2ecf20Sopenharmony_ci if (adapter->link_speed != SPEED_1000) { 58068c2ecf20Sopenharmony_ci current_itr = 0; 58078c2ecf20Sopenharmony_ci new_itr = IGB_4K_ITR; 58088c2ecf20Sopenharmony_ci goto set_itr_now; 58098c2ecf20Sopenharmony_ci } 58108c2ecf20Sopenharmony_ci 58118c2ecf20Sopenharmony_ci igb_update_itr(q_vector, &q_vector->tx); 58128c2ecf20Sopenharmony_ci igb_update_itr(q_vector, &q_vector->rx); 58138c2ecf20Sopenharmony_ci 58148c2ecf20Sopenharmony_ci current_itr = max(q_vector->rx.itr, q_vector->tx.itr); 58158c2ecf20Sopenharmony_ci 58168c2ecf20Sopenharmony_ci /* conservative mode (itr 3) eliminates the lowest_latency setting */ 58178c2ecf20Sopenharmony_ci if (current_itr == lowest_latency && 58188c2ecf20Sopenharmony_ci ((q_vector->rx.ring && adapter->rx_itr_setting == 3) || 58198c2ecf20Sopenharmony_ci (!q_vector->rx.ring && adapter->tx_itr_setting == 3))) 58208c2ecf20Sopenharmony_ci current_itr = low_latency; 58218c2ecf20Sopenharmony_ci 58228c2ecf20Sopenharmony_ci switch (current_itr) { 58238c2ecf20Sopenharmony_ci /* counts and packets in update_itr are dependent on these numbers */ 58248c2ecf20Sopenharmony_ci case lowest_latency: 58258c2ecf20Sopenharmony_ci new_itr = IGB_70K_ITR; /* 70,000 ints/sec */ 58268c2ecf20Sopenharmony_ci break; 58278c2ecf20Sopenharmony_ci case low_latency: 58288c2ecf20Sopenharmony_ci new_itr = IGB_20K_ITR; /* 20,000 ints/sec */ 58298c2ecf20Sopenharmony_ci break; 58308c2ecf20Sopenharmony_ci case bulk_latency: 58318c2ecf20Sopenharmony_ci new_itr = IGB_4K_ITR; /* 4,000 ints/sec */ 58328c2ecf20Sopenharmony_ci break; 58338c2ecf20Sopenharmony_ci default: 58348c2ecf20Sopenharmony_ci break; 58358c2ecf20Sopenharmony_ci } 58368c2ecf20Sopenharmony_ci 58378c2ecf20Sopenharmony_ciset_itr_now: 58388c2ecf20Sopenharmony_ci if (new_itr != q_vector->itr_val) { 58398c2ecf20Sopenharmony_ci /* this attempts to bias the interrupt rate towards Bulk 58408c2ecf20Sopenharmony_ci * by adding intermediate steps when interrupt rate is 58418c2ecf20Sopenharmony_ci * increasing 58428c2ecf20Sopenharmony_ci */ 58438c2ecf20Sopenharmony_ci new_itr = new_itr > q_vector->itr_val ? 58448c2ecf20Sopenharmony_ci max((new_itr * q_vector->itr_val) / 58458c2ecf20Sopenharmony_ci (new_itr + (q_vector->itr_val >> 2)), 58468c2ecf20Sopenharmony_ci new_itr) : new_itr; 58478c2ecf20Sopenharmony_ci /* Don't write the value here; it resets the adapter's 58488c2ecf20Sopenharmony_ci * internal timer, and causes us to delay far longer than 58498c2ecf20Sopenharmony_ci * we should between interrupts. Instead, we write the ITR 58508c2ecf20Sopenharmony_ci * value at the beginning of the next interrupt so the timing 58518c2ecf20Sopenharmony_ci * ends up being correct. 58528c2ecf20Sopenharmony_ci */ 58538c2ecf20Sopenharmony_ci q_vector->itr_val = new_itr; 58548c2ecf20Sopenharmony_ci q_vector->set_itr = 1; 58558c2ecf20Sopenharmony_ci } 58568c2ecf20Sopenharmony_ci} 58578c2ecf20Sopenharmony_ci 58588c2ecf20Sopenharmony_cistatic void igb_tx_ctxtdesc(struct igb_ring *tx_ring, 58598c2ecf20Sopenharmony_ci struct igb_tx_buffer *first, 58608c2ecf20Sopenharmony_ci u32 vlan_macip_lens, u32 type_tucmd, 58618c2ecf20Sopenharmony_ci u32 mss_l4len_idx) 58628c2ecf20Sopenharmony_ci{ 58638c2ecf20Sopenharmony_ci struct e1000_adv_tx_context_desc *context_desc; 58648c2ecf20Sopenharmony_ci u16 i = tx_ring->next_to_use; 58658c2ecf20Sopenharmony_ci struct timespec64 ts; 58668c2ecf20Sopenharmony_ci 58678c2ecf20Sopenharmony_ci context_desc = IGB_TX_CTXTDESC(tx_ring, i); 58688c2ecf20Sopenharmony_ci 58698c2ecf20Sopenharmony_ci i++; 58708c2ecf20Sopenharmony_ci tx_ring->next_to_use = (i < tx_ring->count) ? i : 0; 58718c2ecf20Sopenharmony_ci 58728c2ecf20Sopenharmony_ci /* set bits to identify this as an advanced context descriptor */ 58738c2ecf20Sopenharmony_ci type_tucmd |= E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT; 58748c2ecf20Sopenharmony_ci 58758c2ecf20Sopenharmony_ci /* For 82575, context index must be unique per ring. */ 58768c2ecf20Sopenharmony_ci if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) 58778c2ecf20Sopenharmony_ci mss_l4len_idx |= tx_ring->reg_idx << 4; 58788c2ecf20Sopenharmony_ci 58798c2ecf20Sopenharmony_ci context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); 58808c2ecf20Sopenharmony_ci context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); 58818c2ecf20Sopenharmony_ci context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); 58828c2ecf20Sopenharmony_ci 58838c2ecf20Sopenharmony_ci /* We assume there is always a valid tx time available. Invalid times 58848c2ecf20Sopenharmony_ci * should have been handled by the upper layers. 58858c2ecf20Sopenharmony_ci */ 58868c2ecf20Sopenharmony_ci if (tx_ring->launchtime_enable) { 58878c2ecf20Sopenharmony_ci ts = ktime_to_timespec64(first->skb->tstamp); 58888c2ecf20Sopenharmony_ci skb_txtime_consumed(first->skb); 58898c2ecf20Sopenharmony_ci context_desc->seqnum_seed = cpu_to_le32(ts.tv_nsec / 32); 58908c2ecf20Sopenharmony_ci } else { 58918c2ecf20Sopenharmony_ci context_desc->seqnum_seed = 0; 58928c2ecf20Sopenharmony_ci } 58938c2ecf20Sopenharmony_ci} 58948c2ecf20Sopenharmony_ci 58958c2ecf20Sopenharmony_cistatic int igb_tso(struct igb_ring *tx_ring, 58968c2ecf20Sopenharmony_ci struct igb_tx_buffer *first, 58978c2ecf20Sopenharmony_ci u8 *hdr_len) 58988c2ecf20Sopenharmony_ci{ 58998c2ecf20Sopenharmony_ci u32 vlan_macip_lens, type_tucmd, mss_l4len_idx; 59008c2ecf20Sopenharmony_ci struct sk_buff *skb = first->skb; 59018c2ecf20Sopenharmony_ci union { 59028c2ecf20Sopenharmony_ci struct iphdr *v4; 59038c2ecf20Sopenharmony_ci struct ipv6hdr *v6; 59048c2ecf20Sopenharmony_ci unsigned char *hdr; 59058c2ecf20Sopenharmony_ci } ip; 59068c2ecf20Sopenharmony_ci union { 59078c2ecf20Sopenharmony_ci struct tcphdr *tcp; 59088c2ecf20Sopenharmony_ci struct udphdr *udp; 59098c2ecf20Sopenharmony_ci unsigned char *hdr; 59108c2ecf20Sopenharmony_ci } l4; 59118c2ecf20Sopenharmony_ci u32 paylen, l4_offset; 59128c2ecf20Sopenharmony_ci int err; 59138c2ecf20Sopenharmony_ci 59148c2ecf20Sopenharmony_ci if (skb->ip_summed != CHECKSUM_PARTIAL) 59158c2ecf20Sopenharmony_ci return 0; 59168c2ecf20Sopenharmony_ci 59178c2ecf20Sopenharmony_ci if (!skb_is_gso(skb)) 59188c2ecf20Sopenharmony_ci return 0; 59198c2ecf20Sopenharmony_ci 59208c2ecf20Sopenharmony_ci err = skb_cow_head(skb, 0); 59218c2ecf20Sopenharmony_ci if (err < 0) 59228c2ecf20Sopenharmony_ci return err; 59238c2ecf20Sopenharmony_ci 59248c2ecf20Sopenharmony_ci ip.hdr = skb_network_header(skb); 59258c2ecf20Sopenharmony_ci l4.hdr = skb_checksum_start(skb); 59268c2ecf20Sopenharmony_ci 59278c2ecf20Sopenharmony_ci /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ 59288c2ecf20Sopenharmony_ci type_tucmd = (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ? 59298c2ecf20Sopenharmony_ci E1000_ADVTXD_TUCMD_L4T_UDP : E1000_ADVTXD_TUCMD_L4T_TCP; 59308c2ecf20Sopenharmony_ci 59318c2ecf20Sopenharmony_ci /* initialize outer IP header fields */ 59328c2ecf20Sopenharmony_ci if (ip.v4->version == 4) { 59338c2ecf20Sopenharmony_ci unsigned char *csum_start = skb_checksum_start(skb); 59348c2ecf20Sopenharmony_ci unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4); 59358c2ecf20Sopenharmony_ci 59368c2ecf20Sopenharmony_ci /* IP header will have to cancel out any data that 59378c2ecf20Sopenharmony_ci * is not a part of the outer IP header 59388c2ecf20Sopenharmony_ci */ 59398c2ecf20Sopenharmony_ci ip.v4->check = csum_fold(csum_partial(trans_start, 59408c2ecf20Sopenharmony_ci csum_start - trans_start, 59418c2ecf20Sopenharmony_ci 0)); 59428c2ecf20Sopenharmony_ci type_tucmd |= E1000_ADVTXD_TUCMD_IPV4; 59438c2ecf20Sopenharmony_ci 59448c2ecf20Sopenharmony_ci ip.v4->tot_len = 0; 59458c2ecf20Sopenharmony_ci first->tx_flags |= IGB_TX_FLAGS_TSO | 59468c2ecf20Sopenharmony_ci IGB_TX_FLAGS_CSUM | 59478c2ecf20Sopenharmony_ci IGB_TX_FLAGS_IPV4; 59488c2ecf20Sopenharmony_ci } else { 59498c2ecf20Sopenharmony_ci ip.v6->payload_len = 0; 59508c2ecf20Sopenharmony_ci first->tx_flags |= IGB_TX_FLAGS_TSO | 59518c2ecf20Sopenharmony_ci IGB_TX_FLAGS_CSUM; 59528c2ecf20Sopenharmony_ci } 59538c2ecf20Sopenharmony_ci 59548c2ecf20Sopenharmony_ci /* determine offset of inner transport header */ 59558c2ecf20Sopenharmony_ci l4_offset = l4.hdr - skb->data; 59568c2ecf20Sopenharmony_ci 59578c2ecf20Sopenharmony_ci /* remove payload length from inner checksum */ 59588c2ecf20Sopenharmony_ci paylen = skb->len - l4_offset; 59598c2ecf20Sopenharmony_ci if (type_tucmd & E1000_ADVTXD_TUCMD_L4T_TCP) { 59608c2ecf20Sopenharmony_ci /* compute length of segmentation header */ 59618c2ecf20Sopenharmony_ci *hdr_len = (l4.tcp->doff * 4) + l4_offset; 59628c2ecf20Sopenharmony_ci csum_replace_by_diff(&l4.tcp->check, 59638c2ecf20Sopenharmony_ci (__force __wsum)htonl(paylen)); 59648c2ecf20Sopenharmony_ci } else { 59658c2ecf20Sopenharmony_ci /* compute length of segmentation header */ 59668c2ecf20Sopenharmony_ci *hdr_len = sizeof(*l4.udp) + l4_offset; 59678c2ecf20Sopenharmony_ci csum_replace_by_diff(&l4.udp->check, 59688c2ecf20Sopenharmony_ci (__force __wsum)htonl(paylen)); 59698c2ecf20Sopenharmony_ci } 59708c2ecf20Sopenharmony_ci 59718c2ecf20Sopenharmony_ci /* update gso size and bytecount with header size */ 59728c2ecf20Sopenharmony_ci first->gso_segs = skb_shinfo(skb)->gso_segs; 59738c2ecf20Sopenharmony_ci first->bytecount += (first->gso_segs - 1) * *hdr_len; 59748c2ecf20Sopenharmony_ci 59758c2ecf20Sopenharmony_ci /* MSS L4LEN IDX */ 59768c2ecf20Sopenharmony_ci mss_l4len_idx = (*hdr_len - l4_offset) << E1000_ADVTXD_L4LEN_SHIFT; 59778c2ecf20Sopenharmony_ci mss_l4len_idx |= skb_shinfo(skb)->gso_size << E1000_ADVTXD_MSS_SHIFT; 59788c2ecf20Sopenharmony_ci 59798c2ecf20Sopenharmony_ci /* VLAN MACLEN IPLEN */ 59808c2ecf20Sopenharmony_ci vlan_macip_lens = l4.hdr - ip.hdr; 59818c2ecf20Sopenharmony_ci vlan_macip_lens |= (ip.hdr - skb->data) << E1000_ADVTXD_MACLEN_SHIFT; 59828c2ecf20Sopenharmony_ci vlan_macip_lens |= first->tx_flags & IGB_TX_FLAGS_VLAN_MASK; 59838c2ecf20Sopenharmony_ci 59848c2ecf20Sopenharmony_ci igb_tx_ctxtdesc(tx_ring, first, vlan_macip_lens, 59858c2ecf20Sopenharmony_ci type_tucmd, mss_l4len_idx); 59868c2ecf20Sopenharmony_ci 59878c2ecf20Sopenharmony_ci return 1; 59888c2ecf20Sopenharmony_ci} 59898c2ecf20Sopenharmony_ci 59908c2ecf20Sopenharmony_cistatic inline bool igb_ipv6_csum_is_sctp(struct sk_buff *skb) 59918c2ecf20Sopenharmony_ci{ 59928c2ecf20Sopenharmony_ci unsigned int offset = 0; 59938c2ecf20Sopenharmony_ci 59948c2ecf20Sopenharmony_ci ipv6_find_hdr(skb, &offset, IPPROTO_SCTP, NULL, NULL); 59958c2ecf20Sopenharmony_ci 59968c2ecf20Sopenharmony_ci return offset == skb_checksum_start_offset(skb); 59978c2ecf20Sopenharmony_ci} 59988c2ecf20Sopenharmony_ci 59998c2ecf20Sopenharmony_cistatic void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first) 60008c2ecf20Sopenharmony_ci{ 60018c2ecf20Sopenharmony_ci struct sk_buff *skb = first->skb; 60028c2ecf20Sopenharmony_ci u32 vlan_macip_lens = 0; 60038c2ecf20Sopenharmony_ci u32 type_tucmd = 0; 60048c2ecf20Sopenharmony_ci 60058c2ecf20Sopenharmony_ci if (skb->ip_summed != CHECKSUM_PARTIAL) { 60068c2ecf20Sopenharmony_cicsum_failed: 60078c2ecf20Sopenharmony_ci if (!(first->tx_flags & IGB_TX_FLAGS_VLAN) && 60088c2ecf20Sopenharmony_ci !tx_ring->launchtime_enable) 60098c2ecf20Sopenharmony_ci return; 60108c2ecf20Sopenharmony_ci goto no_csum; 60118c2ecf20Sopenharmony_ci } 60128c2ecf20Sopenharmony_ci 60138c2ecf20Sopenharmony_ci switch (skb->csum_offset) { 60148c2ecf20Sopenharmony_ci case offsetof(struct tcphdr, check): 60158c2ecf20Sopenharmony_ci type_tucmd = E1000_ADVTXD_TUCMD_L4T_TCP; 60168c2ecf20Sopenharmony_ci fallthrough; 60178c2ecf20Sopenharmony_ci case offsetof(struct udphdr, check): 60188c2ecf20Sopenharmony_ci break; 60198c2ecf20Sopenharmony_ci case offsetof(struct sctphdr, checksum): 60208c2ecf20Sopenharmony_ci /* validate that this is actually an SCTP request */ 60218c2ecf20Sopenharmony_ci if (((first->protocol == htons(ETH_P_IP)) && 60228c2ecf20Sopenharmony_ci (ip_hdr(skb)->protocol == IPPROTO_SCTP)) || 60238c2ecf20Sopenharmony_ci ((first->protocol == htons(ETH_P_IPV6)) && 60248c2ecf20Sopenharmony_ci igb_ipv6_csum_is_sctp(skb))) { 60258c2ecf20Sopenharmony_ci type_tucmd = E1000_ADVTXD_TUCMD_L4T_SCTP; 60268c2ecf20Sopenharmony_ci break; 60278c2ecf20Sopenharmony_ci } 60288c2ecf20Sopenharmony_ci fallthrough; 60298c2ecf20Sopenharmony_ci default: 60308c2ecf20Sopenharmony_ci skb_checksum_help(skb); 60318c2ecf20Sopenharmony_ci goto csum_failed; 60328c2ecf20Sopenharmony_ci } 60338c2ecf20Sopenharmony_ci 60348c2ecf20Sopenharmony_ci /* update TX checksum flag */ 60358c2ecf20Sopenharmony_ci first->tx_flags |= IGB_TX_FLAGS_CSUM; 60368c2ecf20Sopenharmony_ci vlan_macip_lens = skb_checksum_start_offset(skb) - 60378c2ecf20Sopenharmony_ci skb_network_offset(skb); 60388c2ecf20Sopenharmony_cino_csum: 60398c2ecf20Sopenharmony_ci vlan_macip_lens |= skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT; 60408c2ecf20Sopenharmony_ci vlan_macip_lens |= first->tx_flags & IGB_TX_FLAGS_VLAN_MASK; 60418c2ecf20Sopenharmony_ci 60428c2ecf20Sopenharmony_ci igb_tx_ctxtdesc(tx_ring, first, vlan_macip_lens, type_tucmd, 0); 60438c2ecf20Sopenharmony_ci} 60448c2ecf20Sopenharmony_ci 60458c2ecf20Sopenharmony_ci#define IGB_SET_FLAG(_input, _flag, _result) \ 60468c2ecf20Sopenharmony_ci ((_flag <= _result) ? \ 60478c2ecf20Sopenharmony_ci ((u32)(_input & _flag) * (_result / _flag)) : \ 60488c2ecf20Sopenharmony_ci ((u32)(_input & _flag) / (_flag / _result))) 60498c2ecf20Sopenharmony_ci 60508c2ecf20Sopenharmony_cistatic u32 igb_tx_cmd_type(struct sk_buff *skb, u32 tx_flags) 60518c2ecf20Sopenharmony_ci{ 60528c2ecf20Sopenharmony_ci /* set type for advanced descriptor with frame checksum insertion */ 60538c2ecf20Sopenharmony_ci u32 cmd_type = E1000_ADVTXD_DTYP_DATA | 60548c2ecf20Sopenharmony_ci E1000_ADVTXD_DCMD_DEXT | 60558c2ecf20Sopenharmony_ci E1000_ADVTXD_DCMD_IFCS; 60568c2ecf20Sopenharmony_ci 60578c2ecf20Sopenharmony_ci /* set HW vlan bit if vlan is present */ 60588c2ecf20Sopenharmony_ci cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_VLAN, 60598c2ecf20Sopenharmony_ci (E1000_ADVTXD_DCMD_VLE)); 60608c2ecf20Sopenharmony_ci 60618c2ecf20Sopenharmony_ci /* set segmentation bits for TSO */ 60628c2ecf20Sopenharmony_ci cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSO, 60638c2ecf20Sopenharmony_ci (E1000_ADVTXD_DCMD_TSE)); 60648c2ecf20Sopenharmony_ci 60658c2ecf20Sopenharmony_ci /* set timestamp bit if present */ 60668c2ecf20Sopenharmony_ci cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSTAMP, 60678c2ecf20Sopenharmony_ci (E1000_ADVTXD_MAC_TSTAMP)); 60688c2ecf20Sopenharmony_ci 60698c2ecf20Sopenharmony_ci /* insert frame checksum */ 60708c2ecf20Sopenharmony_ci cmd_type ^= IGB_SET_FLAG(skb->no_fcs, 1, E1000_ADVTXD_DCMD_IFCS); 60718c2ecf20Sopenharmony_ci 60728c2ecf20Sopenharmony_ci return cmd_type; 60738c2ecf20Sopenharmony_ci} 60748c2ecf20Sopenharmony_ci 60758c2ecf20Sopenharmony_cistatic void igb_tx_olinfo_status(struct igb_ring *tx_ring, 60768c2ecf20Sopenharmony_ci union e1000_adv_tx_desc *tx_desc, 60778c2ecf20Sopenharmony_ci u32 tx_flags, unsigned int paylen) 60788c2ecf20Sopenharmony_ci{ 60798c2ecf20Sopenharmony_ci u32 olinfo_status = paylen << E1000_ADVTXD_PAYLEN_SHIFT; 60808c2ecf20Sopenharmony_ci 60818c2ecf20Sopenharmony_ci /* 82575 requires a unique index per ring */ 60828c2ecf20Sopenharmony_ci if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) 60838c2ecf20Sopenharmony_ci olinfo_status |= tx_ring->reg_idx << 4; 60848c2ecf20Sopenharmony_ci 60858c2ecf20Sopenharmony_ci /* insert L4 checksum */ 60868c2ecf20Sopenharmony_ci olinfo_status |= IGB_SET_FLAG(tx_flags, 60878c2ecf20Sopenharmony_ci IGB_TX_FLAGS_CSUM, 60888c2ecf20Sopenharmony_ci (E1000_TXD_POPTS_TXSM << 8)); 60898c2ecf20Sopenharmony_ci 60908c2ecf20Sopenharmony_ci /* insert IPv4 checksum */ 60918c2ecf20Sopenharmony_ci olinfo_status |= IGB_SET_FLAG(tx_flags, 60928c2ecf20Sopenharmony_ci IGB_TX_FLAGS_IPV4, 60938c2ecf20Sopenharmony_ci (E1000_TXD_POPTS_IXSM << 8)); 60948c2ecf20Sopenharmony_ci 60958c2ecf20Sopenharmony_ci tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); 60968c2ecf20Sopenharmony_ci} 60978c2ecf20Sopenharmony_ci 60988c2ecf20Sopenharmony_cistatic int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size) 60998c2ecf20Sopenharmony_ci{ 61008c2ecf20Sopenharmony_ci struct net_device *netdev = tx_ring->netdev; 61018c2ecf20Sopenharmony_ci 61028c2ecf20Sopenharmony_ci netif_stop_subqueue(netdev, tx_ring->queue_index); 61038c2ecf20Sopenharmony_ci 61048c2ecf20Sopenharmony_ci /* Herbert's original patch had: 61058c2ecf20Sopenharmony_ci * smp_mb__after_netif_stop_queue(); 61068c2ecf20Sopenharmony_ci * but since that doesn't exist yet, just open code it. 61078c2ecf20Sopenharmony_ci */ 61088c2ecf20Sopenharmony_ci smp_mb(); 61098c2ecf20Sopenharmony_ci 61108c2ecf20Sopenharmony_ci /* We need to check again in a case another CPU has just 61118c2ecf20Sopenharmony_ci * made room available. 61128c2ecf20Sopenharmony_ci */ 61138c2ecf20Sopenharmony_ci if (igb_desc_unused(tx_ring) < size) 61148c2ecf20Sopenharmony_ci return -EBUSY; 61158c2ecf20Sopenharmony_ci 61168c2ecf20Sopenharmony_ci /* A reprieve! */ 61178c2ecf20Sopenharmony_ci netif_wake_subqueue(netdev, tx_ring->queue_index); 61188c2ecf20Sopenharmony_ci 61198c2ecf20Sopenharmony_ci u64_stats_update_begin(&tx_ring->tx_syncp2); 61208c2ecf20Sopenharmony_ci tx_ring->tx_stats.restart_queue2++; 61218c2ecf20Sopenharmony_ci u64_stats_update_end(&tx_ring->tx_syncp2); 61228c2ecf20Sopenharmony_ci 61238c2ecf20Sopenharmony_ci return 0; 61248c2ecf20Sopenharmony_ci} 61258c2ecf20Sopenharmony_ci 61268c2ecf20Sopenharmony_cistatic inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size) 61278c2ecf20Sopenharmony_ci{ 61288c2ecf20Sopenharmony_ci if (igb_desc_unused(tx_ring) >= size) 61298c2ecf20Sopenharmony_ci return 0; 61308c2ecf20Sopenharmony_ci return __igb_maybe_stop_tx(tx_ring, size); 61318c2ecf20Sopenharmony_ci} 61328c2ecf20Sopenharmony_ci 61338c2ecf20Sopenharmony_cistatic int igb_tx_map(struct igb_ring *tx_ring, 61348c2ecf20Sopenharmony_ci struct igb_tx_buffer *first, 61358c2ecf20Sopenharmony_ci const u8 hdr_len) 61368c2ecf20Sopenharmony_ci{ 61378c2ecf20Sopenharmony_ci struct sk_buff *skb = first->skb; 61388c2ecf20Sopenharmony_ci struct igb_tx_buffer *tx_buffer; 61398c2ecf20Sopenharmony_ci union e1000_adv_tx_desc *tx_desc; 61408c2ecf20Sopenharmony_ci skb_frag_t *frag; 61418c2ecf20Sopenharmony_ci dma_addr_t dma; 61428c2ecf20Sopenharmony_ci unsigned int data_len, size; 61438c2ecf20Sopenharmony_ci u32 tx_flags = first->tx_flags; 61448c2ecf20Sopenharmony_ci u32 cmd_type = igb_tx_cmd_type(skb, tx_flags); 61458c2ecf20Sopenharmony_ci u16 i = tx_ring->next_to_use; 61468c2ecf20Sopenharmony_ci 61478c2ecf20Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, i); 61488c2ecf20Sopenharmony_ci 61498c2ecf20Sopenharmony_ci igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, skb->len - hdr_len); 61508c2ecf20Sopenharmony_ci 61518c2ecf20Sopenharmony_ci size = skb_headlen(skb); 61528c2ecf20Sopenharmony_ci data_len = skb->data_len; 61538c2ecf20Sopenharmony_ci 61548c2ecf20Sopenharmony_ci dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE); 61558c2ecf20Sopenharmony_ci 61568c2ecf20Sopenharmony_ci tx_buffer = first; 61578c2ecf20Sopenharmony_ci 61588c2ecf20Sopenharmony_ci for (frag = &skb_shinfo(skb)->frags[0];; frag++) { 61598c2ecf20Sopenharmony_ci if (dma_mapping_error(tx_ring->dev, dma)) 61608c2ecf20Sopenharmony_ci goto dma_error; 61618c2ecf20Sopenharmony_ci 61628c2ecf20Sopenharmony_ci /* record length, and DMA address */ 61638c2ecf20Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, size); 61648c2ecf20Sopenharmony_ci dma_unmap_addr_set(tx_buffer, dma, dma); 61658c2ecf20Sopenharmony_ci 61668c2ecf20Sopenharmony_ci tx_desc->read.buffer_addr = cpu_to_le64(dma); 61678c2ecf20Sopenharmony_ci 61688c2ecf20Sopenharmony_ci while (unlikely(size > IGB_MAX_DATA_PER_TXD)) { 61698c2ecf20Sopenharmony_ci tx_desc->read.cmd_type_len = 61708c2ecf20Sopenharmony_ci cpu_to_le32(cmd_type ^ IGB_MAX_DATA_PER_TXD); 61718c2ecf20Sopenharmony_ci 61728c2ecf20Sopenharmony_ci i++; 61738c2ecf20Sopenharmony_ci tx_desc++; 61748c2ecf20Sopenharmony_ci if (i == tx_ring->count) { 61758c2ecf20Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, 0); 61768c2ecf20Sopenharmony_ci i = 0; 61778c2ecf20Sopenharmony_ci } 61788c2ecf20Sopenharmony_ci tx_desc->read.olinfo_status = 0; 61798c2ecf20Sopenharmony_ci 61808c2ecf20Sopenharmony_ci dma += IGB_MAX_DATA_PER_TXD; 61818c2ecf20Sopenharmony_ci size -= IGB_MAX_DATA_PER_TXD; 61828c2ecf20Sopenharmony_ci 61838c2ecf20Sopenharmony_ci tx_desc->read.buffer_addr = cpu_to_le64(dma); 61848c2ecf20Sopenharmony_ci } 61858c2ecf20Sopenharmony_ci 61868c2ecf20Sopenharmony_ci if (likely(!data_len)) 61878c2ecf20Sopenharmony_ci break; 61888c2ecf20Sopenharmony_ci 61898c2ecf20Sopenharmony_ci tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type ^ size); 61908c2ecf20Sopenharmony_ci 61918c2ecf20Sopenharmony_ci i++; 61928c2ecf20Sopenharmony_ci tx_desc++; 61938c2ecf20Sopenharmony_ci if (i == tx_ring->count) { 61948c2ecf20Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, 0); 61958c2ecf20Sopenharmony_ci i = 0; 61968c2ecf20Sopenharmony_ci } 61978c2ecf20Sopenharmony_ci tx_desc->read.olinfo_status = 0; 61988c2ecf20Sopenharmony_ci 61998c2ecf20Sopenharmony_ci size = skb_frag_size(frag); 62008c2ecf20Sopenharmony_ci data_len -= size; 62018c2ecf20Sopenharmony_ci 62028c2ecf20Sopenharmony_ci dma = skb_frag_dma_map(tx_ring->dev, frag, 0, 62038c2ecf20Sopenharmony_ci size, DMA_TO_DEVICE); 62048c2ecf20Sopenharmony_ci 62058c2ecf20Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[i]; 62068c2ecf20Sopenharmony_ci } 62078c2ecf20Sopenharmony_ci 62088c2ecf20Sopenharmony_ci /* write last descriptor with RS and EOP bits */ 62098c2ecf20Sopenharmony_ci cmd_type |= size | IGB_TXD_DCMD; 62108c2ecf20Sopenharmony_ci tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); 62118c2ecf20Sopenharmony_ci 62128c2ecf20Sopenharmony_ci netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); 62138c2ecf20Sopenharmony_ci 62148c2ecf20Sopenharmony_ci /* set the timestamp */ 62158c2ecf20Sopenharmony_ci first->time_stamp = jiffies; 62168c2ecf20Sopenharmony_ci 62178c2ecf20Sopenharmony_ci skb_tx_timestamp(skb); 62188c2ecf20Sopenharmony_ci 62198c2ecf20Sopenharmony_ci /* Force memory writes to complete before letting h/w know there 62208c2ecf20Sopenharmony_ci * are new descriptors to fetch. (Only applicable for weak-ordered 62218c2ecf20Sopenharmony_ci * memory model archs, such as IA-64). 62228c2ecf20Sopenharmony_ci * 62238c2ecf20Sopenharmony_ci * We also need this memory barrier to make certain all of the 62248c2ecf20Sopenharmony_ci * status bits have been updated before next_to_watch is written. 62258c2ecf20Sopenharmony_ci */ 62268c2ecf20Sopenharmony_ci dma_wmb(); 62278c2ecf20Sopenharmony_ci 62288c2ecf20Sopenharmony_ci /* set next_to_watch value indicating a packet is present */ 62298c2ecf20Sopenharmony_ci first->next_to_watch = tx_desc; 62308c2ecf20Sopenharmony_ci 62318c2ecf20Sopenharmony_ci i++; 62328c2ecf20Sopenharmony_ci if (i == tx_ring->count) 62338c2ecf20Sopenharmony_ci i = 0; 62348c2ecf20Sopenharmony_ci 62358c2ecf20Sopenharmony_ci tx_ring->next_to_use = i; 62368c2ecf20Sopenharmony_ci 62378c2ecf20Sopenharmony_ci /* Make sure there is space in the ring for the next send. */ 62388c2ecf20Sopenharmony_ci igb_maybe_stop_tx(tx_ring, DESC_NEEDED); 62398c2ecf20Sopenharmony_ci 62408c2ecf20Sopenharmony_ci if (netif_xmit_stopped(txring_txq(tx_ring)) || !netdev_xmit_more()) { 62418c2ecf20Sopenharmony_ci writel(i, tx_ring->tail); 62428c2ecf20Sopenharmony_ci } 62438c2ecf20Sopenharmony_ci return 0; 62448c2ecf20Sopenharmony_ci 62458c2ecf20Sopenharmony_cidma_error: 62468c2ecf20Sopenharmony_ci dev_err(tx_ring->dev, "TX DMA map failed\n"); 62478c2ecf20Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[i]; 62488c2ecf20Sopenharmony_ci 62498c2ecf20Sopenharmony_ci /* clear dma mappings for failed tx_buffer_info map */ 62508c2ecf20Sopenharmony_ci while (tx_buffer != first) { 62518c2ecf20Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) 62528c2ecf20Sopenharmony_ci dma_unmap_page(tx_ring->dev, 62538c2ecf20Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 62548c2ecf20Sopenharmony_ci dma_unmap_len(tx_buffer, len), 62558c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 62568c2ecf20Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 62578c2ecf20Sopenharmony_ci 62588c2ecf20Sopenharmony_ci if (i-- == 0) 62598c2ecf20Sopenharmony_ci i += tx_ring->count; 62608c2ecf20Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[i]; 62618c2ecf20Sopenharmony_ci } 62628c2ecf20Sopenharmony_ci 62638c2ecf20Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) 62648c2ecf20Sopenharmony_ci dma_unmap_single(tx_ring->dev, 62658c2ecf20Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 62668c2ecf20Sopenharmony_ci dma_unmap_len(tx_buffer, len), 62678c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 62688c2ecf20Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 62698c2ecf20Sopenharmony_ci 62708c2ecf20Sopenharmony_ci dev_kfree_skb_any(tx_buffer->skb); 62718c2ecf20Sopenharmony_ci tx_buffer->skb = NULL; 62728c2ecf20Sopenharmony_ci 62738c2ecf20Sopenharmony_ci tx_ring->next_to_use = i; 62748c2ecf20Sopenharmony_ci 62758c2ecf20Sopenharmony_ci return -1; 62768c2ecf20Sopenharmony_ci} 62778c2ecf20Sopenharmony_ci 62788c2ecf20Sopenharmony_ciint igb_xmit_xdp_ring(struct igb_adapter *adapter, 62798c2ecf20Sopenharmony_ci struct igb_ring *tx_ring, 62808c2ecf20Sopenharmony_ci struct xdp_frame *xdpf) 62818c2ecf20Sopenharmony_ci{ 62828c2ecf20Sopenharmony_ci union e1000_adv_tx_desc *tx_desc; 62838c2ecf20Sopenharmony_ci u32 len, cmd_type, olinfo_status; 62848c2ecf20Sopenharmony_ci struct igb_tx_buffer *tx_buffer; 62858c2ecf20Sopenharmony_ci dma_addr_t dma; 62868c2ecf20Sopenharmony_ci u16 i; 62878c2ecf20Sopenharmony_ci 62888c2ecf20Sopenharmony_ci len = xdpf->len; 62898c2ecf20Sopenharmony_ci 62908c2ecf20Sopenharmony_ci if (unlikely(!igb_desc_unused(tx_ring))) 62918c2ecf20Sopenharmony_ci return IGB_XDP_CONSUMED; 62928c2ecf20Sopenharmony_ci 62938c2ecf20Sopenharmony_ci dma = dma_map_single(tx_ring->dev, xdpf->data, len, DMA_TO_DEVICE); 62948c2ecf20Sopenharmony_ci if (dma_mapping_error(tx_ring->dev, dma)) 62958c2ecf20Sopenharmony_ci return IGB_XDP_CONSUMED; 62968c2ecf20Sopenharmony_ci 62978c2ecf20Sopenharmony_ci /* record the location of the first descriptor for this packet */ 62988c2ecf20Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; 62998c2ecf20Sopenharmony_ci tx_buffer->bytecount = len; 63008c2ecf20Sopenharmony_ci tx_buffer->gso_segs = 1; 63018c2ecf20Sopenharmony_ci tx_buffer->protocol = 0; 63028c2ecf20Sopenharmony_ci 63038c2ecf20Sopenharmony_ci i = tx_ring->next_to_use; 63048c2ecf20Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, i); 63058c2ecf20Sopenharmony_ci 63068c2ecf20Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, len); 63078c2ecf20Sopenharmony_ci dma_unmap_addr_set(tx_buffer, dma, dma); 63088c2ecf20Sopenharmony_ci tx_buffer->type = IGB_TYPE_XDP; 63098c2ecf20Sopenharmony_ci tx_buffer->xdpf = xdpf; 63108c2ecf20Sopenharmony_ci 63118c2ecf20Sopenharmony_ci tx_desc->read.buffer_addr = cpu_to_le64(dma); 63128c2ecf20Sopenharmony_ci 63138c2ecf20Sopenharmony_ci /* put descriptor type bits */ 63148c2ecf20Sopenharmony_ci cmd_type = E1000_ADVTXD_DTYP_DATA | 63158c2ecf20Sopenharmony_ci E1000_ADVTXD_DCMD_DEXT | 63168c2ecf20Sopenharmony_ci E1000_ADVTXD_DCMD_IFCS; 63178c2ecf20Sopenharmony_ci cmd_type |= len | IGB_TXD_DCMD; 63188c2ecf20Sopenharmony_ci tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); 63198c2ecf20Sopenharmony_ci 63208c2ecf20Sopenharmony_ci olinfo_status = len << E1000_ADVTXD_PAYLEN_SHIFT; 63218c2ecf20Sopenharmony_ci /* 82575 requires a unique index per ring */ 63228c2ecf20Sopenharmony_ci if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) 63238c2ecf20Sopenharmony_ci olinfo_status |= tx_ring->reg_idx << 4; 63248c2ecf20Sopenharmony_ci 63258c2ecf20Sopenharmony_ci tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); 63268c2ecf20Sopenharmony_ci 63278c2ecf20Sopenharmony_ci netdev_tx_sent_queue(txring_txq(tx_ring), tx_buffer->bytecount); 63288c2ecf20Sopenharmony_ci 63298c2ecf20Sopenharmony_ci /* set the timestamp */ 63308c2ecf20Sopenharmony_ci tx_buffer->time_stamp = jiffies; 63318c2ecf20Sopenharmony_ci 63328c2ecf20Sopenharmony_ci /* Avoid any potential race with xdp_xmit and cleanup */ 63338c2ecf20Sopenharmony_ci smp_wmb(); 63348c2ecf20Sopenharmony_ci 63358c2ecf20Sopenharmony_ci /* set next_to_watch value indicating a packet is present */ 63368c2ecf20Sopenharmony_ci i++; 63378c2ecf20Sopenharmony_ci if (i == tx_ring->count) 63388c2ecf20Sopenharmony_ci i = 0; 63398c2ecf20Sopenharmony_ci 63408c2ecf20Sopenharmony_ci tx_buffer->next_to_watch = tx_desc; 63418c2ecf20Sopenharmony_ci tx_ring->next_to_use = i; 63428c2ecf20Sopenharmony_ci 63438c2ecf20Sopenharmony_ci /* Make sure there is space in the ring for the next send. */ 63448c2ecf20Sopenharmony_ci igb_maybe_stop_tx(tx_ring, DESC_NEEDED); 63458c2ecf20Sopenharmony_ci 63468c2ecf20Sopenharmony_ci if (netif_xmit_stopped(txring_txq(tx_ring)) || !netdev_xmit_more()) 63478c2ecf20Sopenharmony_ci writel(i, tx_ring->tail); 63488c2ecf20Sopenharmony_ci 63498c2ecf20Sopenharmony_ci return IGB_XDP_TX; 63508c2ecf20Sopenharmony_ci} 63518c2ecf20Sopenharmony_ci 63528c2ecf20Sopenharmony_cinetdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, 63538c2ecf20Sopenharmony_ci struct igb_ring *tx_ring) 63548c2ecf20Sopenharmony_ci{ 63558c2ecf20Sopenharmony_ci struct igb_tx_buffer *first; 63568c2ecf20Sopenharmony_ci int tso; 63578c2ecf20Sopenharmony_ci u32 tx_flags = 0; 63588c2ecf20Sopenharmony_ci unsigned short f; 63598c2ecf20Sopenharmony_ci u16 count = TXD_USE_COUNT(skb_headlen(skb)); 63608c2ecf20Sopenharmony_ci __be16 protocol = vlan_get_protocol(skb); 63618c2ecf20Sopenharmony_ci u8 hdr_len = 0; 63628c2ecf20Sopenharmony_ci 63638c2ecf20Sopenharmony_ci /* need: 1 descriptor per page * PAGE_SIZE/IGB_MAX_DATA_PER_TXD, 63648c2ecf20Sopenharmony_ci * + 1 desc for skb_headlen/IGB_MAX_DATA_PER_TXD, 63658c2ecf20Sopenharmony_ci * + 2 desc gap to keep tail from touching head, 63668c2ecf20Sopenharmony_ci * + 1 desc for context descriptor, 63678c2ecf20Sopenharmony_ci * otherwise try next time 63688c2ecf20Sopenharmony_ci */ 63698c2ecf20Sopenharmony_ci for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) 63708c2ecf20Sopenharmony_ci count += TXD_USE_COUNT(skb_frag_size( 63718c2ecf20Sopenharmony_ci &skb_shinfo(skb)->frags[f])); 63728c2ecf20Sopenharmony_ci 63738c2ecf20Sopenharmony_ci if (igb_maybe_stop_tx(tx_ring, count + 3)) { 63748c2ecf20Sopenharmony_ci /* this is a hard error */ 63758c2ecf20Sopenharmony_ci return NETDEV_TX_BUSY; 63768c2ecf20Sopenharmony_ci } 63778c2ecf20Sopenharmony_ci 63788c2ecf20Sopenharmony_ci /* record the location of the first descriptor for this packet */ 63798c2ecf20Sopenharmony_ci first = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; 63808c2ecf20Sopenharmony_ci first->type = IGB_TYPE_SKB; 63818c2ecf20Sopenharmony_ci first->skb = skb; 63828c2ecf20Sopenharmony_ci first->bytecount = skb->len; 63838c2ecf20Sopenharmony_ci first->gso_segs = 1; 63848c2ecf20Sopenharmony_ci 63858c2ecf20Sopenharmony_ci if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { 63868c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); 63878c2ecf20Sopenharmony_ci 63888c2ecf20Sopenharmony_ci if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON && 63898c2ecf20Sopenharmony_ci !test_and_set_bit_lock(__IGB_PTP_TX_IN_PROGRESS, 63908c2ecf20Sopenharmony_ci &adapter->state)) { 63918c2ecf20Sopenharmony_ci skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 63928c2ecf20Sopenharmony_ci tx_flags |= IGB_TX_FLAGS_TSTAMP; 63938c2ecf20Sopenharmony_ci 63948c2ecf20Sopenharmony_ci adapter->ptp_tx_skb = skb_get(skb); 63958c2ecf20Sopenharmony_ci adapter->ptp_tx_start = jiffies; 63968c2ecf20Sopenharmony_ci if (adapter->hw.mac.type == e1000_82576) 63978c2ecf20Sopenharmony_ci schedule_work(&adapter->ptp_tx_work); 63988c2ecf20Sopenharmony_ci } else { 63998c2ecf20Sopenharmony_ci adapter->tx_hwtstamp_skipped++; 64008c2ecf20Sopenharmony_ci } 64018c2ecf20Sopenharmony_ci } 64028c2ecf20Sopenharmony_ci 64038c2ecf20Sopenharmony_ci if (skb_vlan_tag_present(skb)) { 64048c2ecf20Sopenharmony_ci tx_flags |= IGB_TX_FLAGS_VLAN; 64058c2ecf20Sopenharmony_ci tx_flags |= (skb_vlan_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT); 64068c2ecf20Sopenharmony_ci } 64078c2ecf20Sopenharmony_ci 64088c2ecf20Sopenharmony_ci /* record initial flags and protocol */ 64098c2ecf20Sopenharmony_ci first->tx_flags = tx_flags; 64108c2ecf20Sopenharmony_ci first->protocol = protocol; 64118c2ecf20Sopenharmony_ci 64128c2ecf20Sopenharmony_ci tso = igb_tso(tx_ring, first, &hdr_len); 64138c2ecf20Sopenharmony_ci if (tso < 0) 64148c2ecf20Sopenharmony_ci goto out_drop; 64158c2ecf20Sopenharmony_ci else if (!tso) 64168c2ecf20Sopenharmony_ci igb_tx_csum(tx_ring, first); 64178c2ecf20Sopenharmony_ci 64188c2ecf20Sopenharmony_ci if (igb_tx_map(tx_ring, first, hdr_len)) 64198c2ecf20Sopenharmony_ci goto cleanup_tx_tstamp; 64208c2ecf20Sopenharmony_ci 64218c2ecf20Sopenharmony_ci return NETDEV_TX_OK; 64228c2ecf20Sopenharmony_ci 64238c2ecf20Sopenharmony_ciout_drop: 64248c2ecf20Sopenharmony_ci dev_kfree_skb_any(first->skb); 64258c2ecf20Sopenharmony_ci first->skb = NULL; 64268c2ecf20Sopenharmony_cicleanup_tx_tstamp: 64278c2ecf20Sopenharmony_ci if (unlikely(tx_flags & IGB_TX_FLAGS_TSTAMP)) { 64288c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); 64298c2ecf20Sopenharmony_ci 64308c2ecf20Sopenharmony_ci dev_kfree_skb_any(adapter->ptp_tx_skb); 64318c2ecf20Sopenharmony_ci adapter->ptp_tx_skb = NULL; 64328c2ecf20Sopenharmony_ci if (adapter->hw.mac.type == e1000_82576) 64338c2ecf20Sopenharmony_ci cancel_work_sync(&adapter->ptp_tx_work); 64348c2ecf20Sopenharmony_ci clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); 64358c2ecf20Sopenharmony_ci } 64368c2ecf20Sopenharmony_ci 64378c2ecf20Sopenharmony_ci return NETDEV_TX_OK; 64388c2ecf20Sopenharmony_ci} 64398c2ecf20Sopenharmony_ci 64408c2ecf20Sopenharmony_cistatic inline struct igb_ring *igb_tx_queue_mapping(struct igb_adapter *adapter, 64418c2ecf20Sopenharmony_ci struct sk_buff *skb) 64428c2ecf20Sopenharmony_ci{ 64438c2ecf20Sopenharmony_ci unsigned int r_idx = skb->queue_mapping; 64448c2ecf20Sopenharmony_ci 64458c2ecf20Sopenharmony_ci if (r_idx >= adapter->num_tx_queues) 64468c2ecf20Sopenharmony_ci r_idx = r_idx % adapter->num_tx_queues; 64478c2ecf20Sopenharmony_ci 64488c2ecf20Sopenharmony_ci return adapter->tx_ring[r_idx]; 64498c2ecf20Sopenharmony_ci} 64508c2ecf20Sopenharmony_ci 64518c2ecf20Sopenharmony_cistatic netdev_tx_t igb_xmit_frame(struct sk_buff *skb, 64528c2ecf20Sopenharmony_ci struct net_device *netdev) 64538c2ecf20Sopenharmony_ci{ 64548c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 64558c2ecf20Sopenharmony_ci 64568c2ecf20Sopenharmony_ci /* The minimum packet size with TCTL.PSP set is 17 so pad the skb 64578c2ecf20Sopenharmony_ci * in order to meet this minimum size requirement. 64588c2ecf20Sopenharmony_ci */ 64598c2ecf20Sopenharmony_ci if (skb_put_padto(skb, 17)) 64608c2ecf20Sopenharmony_ci return NETDEV_TX_OK; 64618c2ecf20Sopenharmony_ci 64628c2ecf20Sopenharmony_ci return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb)); 64638c2ecf20Sopenharmony_ci} 64648c2ecf20Sopenharmony_ci 64658c2ecf20Sopenharmony_ci/** 64668c2ecf20Sopenharmony_ci * igb_tx_timeout - Respond to a Tx Hang 64678c2ecf20Sopenharmony_ci * @netdev: network interface device structure 64688c2ecf20Sopenharmony_ci * @txqueue: number of the Tx queue that hung (unused) 64698c2ecf20Sopenharmony_ci **/ 64708c2ecf20Sopenharmony_cistatic void igb_tx_timeout(struct net_device *netdev, unsigned int __always_unused txqueue) 64718c2ecf20Sopenharmony_ci{ 64728c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 64738c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 64748c2ecf20Sopenharmony_ci 64758c2ecf20Sopenharmony_ci /* Do the reset outside of interrupt context */ 64768c2ecf20Sopenharmony_ci adapter->tx_timeout_count++; 64778c2ecf20Sopenharmony_ci 64788c2ecf20Sopenharmony_ci if (hw->mac.type >= e1000_82580) 64798c2ecf20Sopenharmony_ci hw->dev_spec._82575.global_device_reset = true; 64808c2ecf20Sopenharmony_ci 64818c2ecf20Sopenharmony_ci schedule_work(&adapter->reset_task); 64828c2ecf20Sopenharmony_ci wr32(E1000_EICS, 64838c2ecf20Sopenharmony_ci (adapter->eims_enable_mask & ~adapter->eims_other)); 64848c2ecf20Sopenharmony_ci} 64858c2ecf20Sopenharmony_ci 64868c2ecf20Sopenharmony_cistatic void igb_reset_task(struct work_struct *work) 64878c2ecf20Sopenharmony_ci{ 64888c2ecf20Sopenharmony_ci struct igb_adapter *adapter; 64898c2ecf20Sopenharmony_ci adapter = container_of(work, struct igb_adapter, reset_task); 64908c2ecf20Sopenharmony_ci 64918c2ecf20Sopenharmony_ci rtnl_lock(); 64928c2ecf20Sopenharmony_ci /* If we're already down or resetting, just bail */ 64938c2ecf20Sopenharmony_ci if (test_bit(__IGB_DOWN, &adapter->state) || 64948c2ecf20Sopenharmony_ci test_bit(__IGB_RESETTING, &adapter->state)) { 64958c2ecf20Sopenharmony_ci rtnl_unlock(); 64968c2ecf20Sopenharmony_ci return; 64978c2ecf20Sopenharmony_ci } 64988c2ecf20Sopenharmony_ci 64998c2ecf20Sopenharmony_ci igb_dump(adapter); 65008c2ecf20Sopenharmony_ci netdev_err(adapter->netdev, "Reset adapter\n"); 65018c2ecf20Sopenharmony_ci igb_reinit_locked(adapter); 65028c2ecf20Sopenharmony_ci rtnl_unlock(); 65038c2ecf20Sopenharmony_ci} 65048c2ecf20Sopenharmony_ci 65058c2ecf20Sopenharmony_ci/** 65068c2ecf20Sopenharmony_ci * igb_get_stats64 - Get System Network Statistics 65078c2ecf20Sopenharmony_ci * @netdev: network interface device structure 65088c2ecf20Sopenharmony_ci * @stats: rtnl_link_stats64 pointer 65098c2ecf20Sopenharmony_ci **/ 65108c2ecf20Sopenharmony_cistatic void igb_get_stats64(struct net_device *netdev, 65118c2ecf20Sopenharmony_ci struct rtnl_link_stats64 *stats) 65128c2ecf20Sopenharmony_ci{ 65138c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 65148c2ecf20Sopenharmony_ci 65158c2ecf20Sopenharmony_ci spin_lock(&adapter->stats64_lock); 65168c2ecf20Sopenharmony_ci igb_update_stats(adapter); 65178c2ecf20Sopenharmony_ci memcpy(stats, &adapter->stats64, sizeof(*stats)); 65188c2ecf20Sopenharmony_ci spin_unlock(&adapter->stats64_lock); 65198c2ecf20Sopenharmony_ci} 65208c2ecf20Sopenharmony_ci 65218c2ecf20Sopenharmony_ci/** 65228c2ecf20Sopenharmony_ci * igb_change_mtu - Change the Maximum Transfer Unit 65238c2ecf20Sopenharmony_ci * @netdev: network interface device structure 65248c2ecf20Sopenharmony_ci * @new_mtu: new value for maximum frame size 65258c2ecf20Sopenharmony_ci * 65268c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure 65278c2ecf20Sopenharmony_ci **/ 65288c2ecf20Sopenharmony_cistatic int igb_change_mtu(struct net_device *netdev, int new_mtu) 65298c2ecf20Sopenharmony_ci{ 65308c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 65318c2ecf20Sopenharmony_ci int max_frame = new_mtu + IGB_ETH_PKT_HDR_PAD; 65328c2ecf20Sopenharmony_ci 65338c2ecf20Sopenharmony_ci if (adapter->xdp_prog) { 65348c2ecf20Sopenharmony_ci int i; 65358c2ecf20Sopenharmony_ci 65368c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 65378c2ecf20Sopenharmony_ci struct igb_ring *ring = adapter->rx_ring[i]; 65388c2ecf20Sopenharmony_ci 65398c2ecf20Sopenharmony_ci if (max_frame > igb_rx_bufsz(ring)) { 65408c2ecf20Sopenharmony_ci netdev_warn(adapter->netdev, 65418c2ecf20Sopenharmony_ci "Requested MTU size is not supported with XDP. Max frame size is %d\n", 65428c2ecf20Sopenharmony_ci max_frame); 65438c2ecf20Sopenharmony_ci return -EINVAL; 65448c2ecf20Sopenharmony_ci } 65458c2ecf20Sopenharmony_ci } 65468c2ecf20Sopenharmony_ci } 65478c2ecf20Sopenharmony_ci 65488c2ecf20Sopenharmony_ci /* adjust max frame to be at least the size of a standard frame */ 65498c2ecf20Sopenharmony_ci if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN)) 65508c2ecf20Sopenharmony_ci max_frame = ETH_FRAME_LEN + ETH_FCS_LEN; 65518c2ecf20Sopenharmony_ci 65528c2ecf20Sopenharmony_ci while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) 65538c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 65548c2ecf20Sopenharmony_ci 65558c2ecf20Sopenharmony_ci /* igb_down has a dependency on max_frame_size */ 65568c2ecf20Sopenharmony_ci adapter->max_frame_size = max_frame; 65578c2ecf20Sopenharmony_ci 65588c2ecf20Sopenharmony_ci if (netif_running(netdev)) 65598c2ecf20Sopenharmony_ci igb_down(adapter); 65608c2ecf20Sopenharmony_ci 65618c2ecf20Sopenharmony_ci netdev_dbg(netdev, "changing MTU from %d to %d\n", 65628c2ecf20Sopenharmony_ci netdev->mtu, new_mtu); 65638c2ecf20Sopenharmony_ci netdev->mtu = new_mtu; 65648c2ecf20Sopenharmony_ci 65658c2ecf20Sopenharmony_ci if (netif_running(netdev)) 65668c2ecf20Sopenharmony_ci igb_up(adapter); 65678c2ecf20Sopenharmony_ci else 65688c2ecf20Sopenharmony_ci igb_reset(adapter); 65698c2ecf20Sopenharmony_ci 65708c2ecf20Sopenharmony_ci clear_bit(__IGB_RESETTING, &adapter->state); 65718c2ecf20Sopenharmony_ci 65728c2ecf20Sopenharmony_ci return 0; 65738c2ecf20Sopenharmony_ci} 65748c2ecf20Sopenharmony_ci 65758c2ecf20Sopenharmony_ci/** 65768c2ecf20Sopenharmony_ci * igb_update_stats - Update the board statistics counters 65778c2ecf20Sopenharmony_ci * @adapter: board private structure 65788c2ecf20Sopenharmony_ci **/ 65798c2ecf20Sopenharmony_civoid igb_update_stats(struct igb_adapter *adapter) 65808c2ecf20Sopenharmony_ci{ 65818c2ecf20Sopenharmony_ci struct rtnl_link_stats64 *net_stats = &adapter->stats64; 65828c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 65838c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 65848c2ecf20Sopenharmony_ci u32 reg, mpc; 65858c2ecf20Sopenharmony_ci int i; 65868c2ecf20Sopenharmony_ci u64 bytes, packets; 65878c2ecf20Sopenharmony_ci unsigned int start; 65888c2ecf20Sopenharmony_ci u64 _bytes, _packets; 65898c2ecf20Sopenharmony_ci 65908c2ecf20Sopenharmony_ci /* Prevent stats update while adapter is being reset, or if the pci 65918c2ecf20Sopenharmony_ci * connection is down. 65928c2ecf20Sopenharmony_ci */ 65938c2ecf20Sopenharmony_ci if (adapter->link_speed == 0) 65948c2ecf20Sopenharmony_ci return; 65958c2ecf20Sopenharmony_ci if (pci_channel_offline(pdev)) 65968c2ecf20Sopenharmony_ci return; 65978c2ecf20Sopenharmony_ci 65988c2ecf20Sopenharmony_ci bytes = 0; 65998c2ecf20Sopenharmony_ci packets = 0; 66008c2ecf20Sopenharmony_ci 66018c2ecf20Sopenharmony_ci rcu_read_lock(); 66028c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 66038c2ecf20Sopenharmony_ci struct igb_ring *ring = adapter->rx_ring[i]; 66048c2ecf20Sopenharmony_ci u32 rqdpc = rd32(E1000_RQDPC(i)); 66058c2ecf20Sopenharmony_ci if (hw->mac.type >= e1000_i210) 66068c2ecf20Sopenharmony_ci wr32(E1000_RQDPC(i), 0); 66078c2ecf20Sopenharmony_ci 66088c2ecf20Sopenharmony_ci if (rqdpc) { 66098c2ecf20Sopenharmony_ci ring->rx_stats.drops += rqdpc; 66108c2ecf20Sopenharmony_ci net_stats->rx_fifo_errors += rqdpc; 66118c2ecf20Sopenharmony_ci } 66128c2ecf20Sopenharmony_ci 66138c2ecf20Sopenharmony_ci do { 66148c2ecf20Sopenharmony_ci start = u64_stats_fetch_begin_irq(&ring->rx_syncp); 66158c2ecf20Sopenharmony_ci _bytes = ring->rx_stats.bytes; 66168c2ecf20Sopenharmony_ci _packets = ring->rx_stats.packets; 66178c2ecf20Sopenharmony_ci } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start)); 66188c2ecf20Sopenharmony_ci bytes += _bytes; 66198c2ecf20Sopenharmony_ci packets += _packets; 66208c2ecf20Sopenharmony_ci } 66218c2ecf20Sopenharmony_ci 66228c2ecf20Sopenharmony_ci net_stats->rx_bytes = bytes; 66238c2ecf20Sopenharmony_ci net_stats->rx_packets = packets; 66248c2ecf20Sopenharmony_ci 66258c2ecf20Sopenharmony_ci bytes = 0; 66268c2ecf20Sopenharmony_ci packets = 0; 66278c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 66288c2ecf20Sopenharmony_ci struct igb_ring *ring = adapter->tx_ring[i]; 66298c2ecf20Sopenharmony_ci do { 66308c2ecf20Sopenharmony_ci start = u64_stats_fetch_begin_irq(&ring->tx_syncp); 66318c2ecf20Sopenharmony_ci _bytes = ring->tx_stats.bytes; 66328c2ecf20Sopenharmony_ci _packets = ring->tx_stats.packets; 66338c2ecf20Sopenharmony_ci } while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start)); 66348c2ecf20Sopenharmony_ci bytes += _bytes; 66358c2ecf20Sopenharmony_ci packets += _packets; 66368c2ecf20Sopenharmony_ci } 66378c2ecf20Sopenharmony_ci net_stats->tx_bytes = bytes; 66388c2ecf20Sopenharmony_ci net_stats->tx_packets = packets; 66398c2ecf20Sopenharmony_ci rcu_read_unlock(); 66408c2ecf20Sopenharmony_ci 66418c2ecf20Sopenharmony_ci /* read stats registers */ 66428c2ecf20Sopenharmony_ci adapter->stats.crcerrs += rd32(E1000_CRCERRS); 66438c2ecf20Sopenharmony_ci adapter->stats.gprc += rd32(E1000_GPRC); 66448c2ecf20Sopenharmony_ci adapter->stats.gorc += rd32(E1000_GORCL); 66458c2ecf20Sopenharmony_ci rd32(E1000_GORCH); /* clear GORCL */ 66468c2ecf20Sopenharmony_ci adapter->stats.bprc += rd32(E1000_BPRC); 66478c2ecf20Sopenharmony_ci adapter->stats.mprc += rd32(E1000_MPRC); 66488c2ecf20Sopenharmony_ci adapter->stats.roc += rd32(E1000_ROC); 66498c2ecf20Sopenharmony_ci 66508c2ecf20Sopenharmony_ci adapter->stats.prc64 += rd32(E1000_PRC64); 66518c2ecf20Sopenharmony_ci adapter->stats.prc127 += rd32(E1000_PRC127); 66528c2ecf20Sopenharmony_ci adapter->stats.prc255 += rd32(E1000_PRC255); 66538c2ecf20Sopenharmony_ci adapter->stats.prc511 += rd32(E1000_PRC511); 66548c2ecf20Sopenharmony_ci adapter->stats.prc1023 += rd32(E1000_PRC1023); 66558c2ecf20Sopenharmony_ci adapter->stats.prc1522 += rd32(E1000_PRC1522); 66568c2ecf20Sopenharmony_ci adapter->stats.symerrs += rd32(E1000_SYMERRS); 66578c2ecf20Sopenharmony_ci adapter->stats.sec += rd32(E1000_SEC); 66588c2ecf20Sopenharmony_ci 66598c2ecf20Sopenharmony_ci mpc = rd32(E1000_MPC); 66608c2ecf20Sopenharmony_ci adapter->stats.mpc += mpc; 66618c2ecf20Sopenharmony_ci net_stats->rx_fifo_errors += mpc; 66628c2ecf20Sopenharmony_ci adapter->stats.scc += rd32(E1000_SCC); 66638c2ecf20Sopenharmony_ci adapter->stats.ecol += rd32(E1000_ECOL); 66648c2ecf20Sopenharmony_ci adapter->stats.mcc += rd32(E1000_MCC); 66658c2ecf20Sopenharmony_ci adapter->stats.latecol += rd32(E1000_LATECOL); 66668c2ecf20Sopenharmony_ci adapter->stats.dc += rd32(E1000_DC); 66678c2ecf20Sopenharmony_ci adapter->stats.rlec += rd32(E1000_RLEC); 66688c2ecf20Sopenharmony_ci adapter->stats.xonrxc += rd32(E1000_XONRXC); 66698c2ecf20Sopenharmony_ci adapter->stats.xontxc += rd32(E1000_XONTXC); 66708c2ecf20Sopenharmony_ci adapter->stats.xoffrxc += rd32(E1000_XOFFRXC); 66718c2ecf20Sopenharmony_ci adapter->stats.xofftxc += rd32(E1000_XOFFTXC); 66728c2ecf20Sopenharmony_ci adapter->stats.fcruc += rd32(E1000_FCRUC); 66738c2ecf20Sopenharmony_ci adapter->stats.gptc += rd32(E1000_GPTC); 66748c2ecf20Sopenharmony_ci adapter->stats.gotc += rd32(E1000_GOTCL); 66758c2ecf20Sopenharmony_ci rd32(E1000_GOTCH); /* clear GOTCL */ 66768c2ecf20Sopenharmony_ci adapter->stats.rnbc += rd32(E1000_RNBC); 66778c2ecf20Sopenharmony_ci adapter->stats.ruc += rd32(E1000_RUC); 66788c2ecf20Sopenharmony_ci adapter->stats.rfc += rd32(E1000_RFC); 66798c2ecf20Sopenharmony_ci adapter->stats.rjc += rd32(E1000_RJC); 66808c2ecf20Sopenharmony_ci adapter->stats.tor += rd32(E1000_TORH); 66818c2ecf20Sopenharmony_ci adapter->stats.tot += rd32(E1000_TOTH); 66828c2ecf20Sopenharmony_ci adapter->stats.tpr += rd32(E1000_TPR); 66838c2ecf20Sopenharmony_ci 66848c2ecf20Sopenharmony_ci adapter->stats.ptc64 += rd32(E1000_PTC64); 66858c2ecf20Sopenharmony_ci adapter->stats.ptc127 += rd32(E1000_PTC127); 66868c2ecf20Sopenharmony_ci adapter->stats.ptc255 += rd32(E1000_PTC255); 66878c2ecf20Sopenharmony_ci adapter->stats.ptc511 += rd32(E1000_PTC511); 66888c2ecf20Sopenharmony_ci adapter->stats.ptc1023 += rd32(E1000_PTC1023); 66898c2ecf20Sopenharmony_ci adapter->stats.ptc1522 += rd32(E1000_PTC1522); 66908c2ecf20Sopenharmony_ci 66918c2ecf20Sopenharmony_ci adapter->stats.mptc += rd32(E1000_MPTC); 66928c2ecf20Sopenharmony_ci adapter->stats.bptc += rd32(E1000_BPTC); 66938c2ecf20Sopenharmony_ci 66948c2ecf20Sopenharmony_ci adapter->stats.tpt += rd32(E1000_TPT); 66958c2ecf20Sopenharmony_ci adapter->stats.colc += rd32(E1000_COLC); 66968c2ecf20Sopenharmony_ci 66978c2ecf20Sopenharmony_ci adapter->stats.algnerrc += rd32(E1000_ALGNERRC); 66988c2ecf20Sopenharmony_ci /* read internal phy specific stats */ 66998c2ecf20Sopenharmony_ci reg = rd32(E1000_CTRL_EXT); 67008c2ecf20Sopenharmony_ci if (!(reg & E1000_CTRL_EXT_LINK_MODE_MASK)) { 67018c2ecf20Sopenharmony_ci adapter->stats.rxerrc += rd32(E1000_RXERRC); 67028c2ecf20Sopenharmony_ci 67038c2ecf20Sopenharmony_ci /* this stat has invalid values on i210/i211 */ 67048c2ecf20Sopenharmony_ci if ((hw->mac.type != e1000_i210) && 67058c2ecf20Sopenharmony_ci (hw->mac.type != e1000_i211)) 67068c2ecf20Sopenharmony_ci adapter->stats.tncrs += rd32(E1000_TNCRS); 67078c2ecf20Sopenharmony_ci } 67088c2ecf20Sopenharmony_ci 67098c2ecf20Sopenharmony_ci adapter->stats.tsctc += rd32(E1000_TSCTC); 67108c2ecf20Sopenharmony_ci adapter->stats.tsctfc += rd32(E1000_TSCTFC); 67118c2ecf20Sopenharmony_ci 67128c2ecf20Sopenharmony_ci adapter->stats.iac += rd32(E1000_IAC); 67138c2ecf20Sopenharmony_ci adapter->stats.icrxoc += rd32(E1000_ICRXOC); 67148c2ecf20Sopenharmony_ci adapter->stats.icrxptc += rd32(E1000_ICRXPTC); 67158c2ecf20Sopenharmony_ci adapter->stats.icrxatc += rd32(E1000_ICRXATC); 67168c2ecf20Sopenharmony_ci adapter->stats.ictxptc += rd32(E1000_ICTXPTC); 67178c2ecf20Sopenharmony_ci adapter->stats.ictxatc += rd32(E1000_ICTXATC); 67188c2ecf20Sopenharmony_ci adapter->stats.ictxqec += rd32(E1000_ICTXQEC); 67198c2ecf20Sopenharmony_ci adapter->stats.ictxqmtc += rd32(E1000_ICTXQMTC); 67208c2ecf20Sopenharmony_ci adapter->stats.icrxdmtc += rd32(E1000_ICRXDMTC); 67218c2ecf20Sopenharmony_ci 67228c2ecf20Sopenharmony_ci /* Fill out the OS statistics structure */ 67238c2ecf20Sopenharmony_ci net_stats->multicast = adapter->stats.mprc; 67248c2ecf20Sopenharmony_ci net_stats->collisions = adapter->stats.colc; 67258c2ecf20Sopenharmony_ci 67268c2ecf20Sopenharmony_ci /* Rx Errors */ 67278c2ecf20Sopenharmony_ci 67288c2ecf20Sopenharmony_ci /* RLEC on some newer hardware can be incorrect so build 67298c2ecf20Sopenharmony_ci * our own version based on RUC and ROC 67308c2ecf20Sopenharmony_ci */ 67318c2ecf20Sopenharmony_ci net_stats->rx_errors = adapter->stats.rxerrc + 67328c2ecf20Sopenharmony_ci adapter->stats.crcerrs + adapter->stats.algnerrc + 67338c2ecf20Sopenharmony_ci adapter->stats.ruc + adapter->stats.roc + 67348c2ecf20Sopenharmony_ci adapter->stats.cexterr; 67358c2ecf20Sopenharmony_ci net_stats->rx_length_errors = adapter->stats.ruc + 67368c2ecf20Sopenharmony_ci adapter->stats.roc; 67378c2ecf20Sopenharmony_ci net_stats->rx_crc_errors = adapter->stats.crcerrs; 67388c2ecf20Sopenharmony_ci net_stats->rx_frame_errors = adapter->stats.algnerrc; 67398c2ecf20Sopenharmony_ci net_stats->rx_missed_errors = adapter->stats.mpc; 67408c2ecf20Sopenharmony_ci 67418c2ecf20Sopenharmony_ci /* Tx Errors */ 67428c2ecf20Sopenharmony_ci net_stats->tx_errors = adapter->stats.ecol + 67438c2ecf20Sopenharmony_ci adapter->stats.latecol; 67448c2ecf20Sopenharmony_ci net_stats->tx_aborted_errors = adapter->stats.ecol; 67458c2ecf20Sopenharmony_ci net_stats->tx_window_errors = adapter->stats.latecol; 67468c2ecf20Sopenharmony_ci net_stats->tx_carrier_errors = adapter->stats.tncrs; 67478c2ecf20Sopenharmony_ci 67488c2ecf20Sopenharmony_ci /* Tx Dropped needs to be maintained elsewhere */ 67498c2ecf20Sopenharmony_ci 67508c2ecf20Sopenharmony_ci /* Management Stats */ 67518c2ecf20Sopenharmony_ci adapter->stats.mgptc += rd32(E1000_MGTPTC); 67528c2ecf20Sopenharmony_ci adapter->stats.mgprc += rd32(E1000_MGTPRC); 67538c2ecf20Sopenharmony_ci adapter->stats.mgpdc += rd32(E1000_MGTPDC); 67548c2ecf20Sopenharmony_ci 67558c2ecf20Sopenharmony_ci /* OS2BMC Stats */ 67568c2ecf20Sopenharmony_ci reg = rd32(E1000_MANC); 67578c2ecf20Sopenharmony_ci if (reg & E1000_MANC_EN_BMC2OS) { 67588c2ecf20Sopenharmony_ci adapter->stats.o2bgptc += rd32(E1000_O2BGPTC); 67598c2ecf20Sopenharmony_ci adapter->stats.o2bspc += rd32(E1000_O2BSPC); 67608c2ecf20Sopenharmony_ci adapter->stats.b2ospc += rd32(E1000_B2OSPC); 67618c2ecf20Sopenharmony_ci adapter->stats.b2ogprc += rd32(E1000_B2OGPRC); 67628c2ecf20Sopenharmony_ci } 67638c2ecf20Sopenharmony_ci} 67648c2ecf20Sopenharmony_ci 67658c2ecf20Sopenharmony_cistatic void igb_tsync_interrupt(struct igb_adapter *adapter) 67668c2ecf20Sopenharmony_ci{ 67678c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 67688c2ecf20Sopenharmony_ci struct ptp_clock_event event; 67698c2ecf20Sopenharmony_ci struct timespec64 ts; 67708c2ecf20Sopenharmony_ci u32 ack = 0, tsauxc, sec, nsec, tsicr = rd32(E1000_TSICR); 67718c2ecf20Sopenharmony_ci 67728c2ecf20Sopenharmony_ci if (tsicr & TSINTR_SYS_WRAP) { 67738c2ecf20Sopenharmony_ci event.type = PTP_CLOCK_PPS; 67748c2ecf20Sopenharmony_ci if (adapter->ptp_caps.pps) 67758c2ecf20Sopenharmony_ci ptp_clock_event(adapter->ptp_clock, &event); 67768c2ecf20Sopenharmony_ci ack |= TSINTR_SYS_WRAP; 67778c2ecf20Sopenharmony_ci } 67788c2ecf20Sopenharmony_ci 67798c2ecf20Sopenharmony_ci if (tsicr & E1000_TSICR_TXTS) { 67808c2ecf20Sopenharmony_ci /* retrieve hardware timestamp */ 67818c2ecf20Sopenharmony_ci schedule_work(&adapter->ptp_tx_work); 67828c2ecf20Sopenharmony_ci ack |= E1000_TSICR_TXTS; 67838c2ecf20Sopenharmony_ci } 67848c2ecf20Sopenharmony_ci 67858c2ecf20Sopenharmony_ci if (tsicr & TSINTR_TT0) { 67868c2ecf20Sopenharmony_ci spin_lock(&adapter->tmreg_lock); 67878c2ecf20Sopenharmony_ci ts = timespec64_add(adapter->perout[0].start, 67888c2ecf20Sopenharmony_ci adapter->perout[0].period); 67898c2ecf20Sopenharmony_ci /* u32 conversion of tv_sec is safe until y2106 */ 67908c2ecf20Sopenharmony_ci wr32(E1000_TRGTTIML0, ts.tv_nsec); 67918c2ecf20Sopenharmony_ci wr32(E1000_TRGTTIMH0, (u32)ts.tv_sec); 67928c2ecf20Sopenharmony_ci tsauxc = rd32(E1000_TSAUXC); 67938c2ecf20Sopenharmony_ci tsauxc |= TSAUXC_EN_TT0; 67948c2ecf20Sopenharmony_ci wr32(E1000_TSAUXC, tsauxc); 67958c2ecf20Sopenharmony_ci adapter->perout[0].start = ts; 67968c2ecf20Sopenharmony_ci spin_unlock(&adapter->tmreg_lock); 67978c2ecf20Sopenharmony_ci ack |= TSINTR_TT0; 67988c2ecf20Sopenharmony_ci } 67998c2ecf20Sopenharmony_ci 68008c2ecf20Sopenharmony_ci if (tsicr & TSINTR_TT1) { 68018c2ecf20Sopenharmony_ci spin_lock(&adapter->tmreg_lock); 68028c2ecf20Sopenharmony_ci ts = timespec64_add(adapter->perout[1].start, 68038c2ecf20Sopenharmony_ci adapter->perout[1].period); 68048c2ecf20Sopenharmony_ci wr32(E1000_TRGTTIML1, ts.tv_nsec); 68058c2ecf20Sopenharmony_ci wr32(E1000_TRGTTIMH1, (u32)ts.tv_sec); 68068c2ecf20Sopenharmony_ci tsauxc = rd32(E1000_TSAUXC); 68078c2ecf20Sopenharmony_ci tsauxc |= TSAUXC_EN_TT1; 68088c2ecf20Sopenharmony_ci wr32(E1000_TSAUXC, tsauxc); 68098c2ecf20Sopenharmony_ci adapter->perout[1].start = ts; 68108c2ecf20Sopenharmony_ci spin_unlock(&adapter->tmreg_lock); 68118c2ecf20Sopenharmony_ci ack |= TSINTR_TT1; 68128c2ecf20Sopenharmony_ci } 68138c2ecf20Sopenharmony_ci 68148c2ecf20Sopenharmony_ci if (tsicr & TSINTR_AUTT0) { 68158c2ecf20Sopenharmony_ci nsec = rd32(E1000_AUXSTMPL0); 68168c2ecf20Sopenharmony_ci sec = rd32(E1000_AUXSTMPH0); 68178c2ecf20Sopenharmony_ci event.type = PTP_CLOCK_EXTTS; 68188c2ecf20Sopenharmony_ci event.index = 0; 68198c2ecf20Sopenharmony_ci event.timestamp = sec * 1000000000ULL + nsec; 68208c2ecf20Sopenharmony_ci ptp_clock_event(adapter->ptp_clock, &event); 68218c2ecf20Sopenharmony_ci ack |= TSINTR_AUTT0; 68228c2ecf20Sopenharmony_ci } 68238c2ecf20Sopenharmony_ci 68248c2ecf20Sopenharmony_ci if (tsicr & TSINTR_AUTT1) { 68258c2ecf20Sopenharmony_ci nsec = rd32(E1000_AUXSTMPL1); 68268c2ecf20Sopenharmony_ci sec = rd32(E1000_AUXSTMPH1); 68278c2ecf20Sopenharmony_ci event.type = PTP_CLOCK_EXTTS; 68288c2ecf20Sopenharmony_ci event.index = 1; 68298c2ecf20Sopenharmony_ci event.timestamp = sec * 1000000000ULL + nsec; 68308c2ecf20Sopenharmony_ci ptp_clock_event(adapter->ptp_clock, &event); 68318c2ecf20Sopenharmony_ci ack |= TSINTR_AUTT1; 68328c2ecf20Sopenharmony_ci } 68338c2ecf20Sopenharmony_ci 68348c2ecf20Sopenharmony_ci /* acknowledge the interrupts */ 68358c2ecf20Sopenharmony_ci wr32(E1000_TSICR, ack); 68368c2ecf20Sopenharmony_ci} 68378c2ecf20Sopenharmony_ci 68388c2ecf20Sopenharmony_cistatic irqreturn_t igb_msix_other(int irq, void *data) 68398c2ecf20Sopenharmony_ci{ 68408c2ecf20Sopenharmony_ci struct igb_adapter *adapter = data; 68418c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 68428c2ecf20Sopenharmony_ci u32 icr = rd32(E1000_ICR); 68438c2ecf20Sopenharmony_ci /* reading ICR causes bit 31 of EICR to be cleared */ 68448c2ecf20Sopenharmony_ci 68458c2ecf20Sopenharmony_ci if (icr & E1000_ICR_DRSTA) 68468c2ecf20Sopenharmony_ci schedule_work(&adapter->reset_task); 68478c2ecf20Sopenharmony_ci 68488c2ecf20Sopenharmony_ci if (icr & E1000_ICR_DOUTSYNC) { 68498c2ecf20Sopenharmony_ci /* HW is reporting DMA is out of sync */ 68508c2ecf20Sopenharmony_ci adapter->stats.doosync++; 68518c2ecf20Sopenharmony_ci /* The DMA Out of Sync is also indication of a spoof event 68528c2ecf20Sopenharmony_ci * in IOV mode. Check the Wrong VM Behavior register to 68538c2ecf20Sopenharmony_ci * see if it is really a spoof event. 68548c2ecf20Sopenharmony_ci */ 68558c2ecf20Sopenharmony_ci igb_check_wvbr(adapter); 68568c2ecf20Sopenharmony_ci } 68578c2ecf20Sopenharmony_ci 68588c2ecf20Sopenharmony_ci /* Check for a mailbox event */ 68598c2ecf20Sopenharmony_ci if (icr & E1000_ICR_VMMB) 68608c2ecf20Sopenharmony_ci igb_msg_task(adapter); 68618c2ecf20Sopenharmony_ci 68628c2ecf20Sopenharmony_ci if (icr & E1000_ICR_LSC) { 68638c2ecf20Sopenharmony_ci hw->mac.get_link_status = 1; 68648c2ecf20Sopenharmony_ci /* guard against interrupt when we're going down */ 68658c2ecf20Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) 68668c2ecf20Sopenharmony_ci mod_timer(&adapter->watchdog_timer, jiffies + 1); 68678c2ecf20Sopenharmony_ci } 68688c2ecf20Sopenharmony_ci 68698c2ecf20Sopenharmony_ci if (icr & E1000_ICR_TS) 68708c2ecf20Sopenharmony_ci igb_tsync_interrupt(adapter); 68718c2ecf20Sopenharmony_ci 68728c2ecf20Sopenharmony_ci wr32(E1000_EIMS, adapter->eims_other); 68738c2ecf20Sopenharmony_ci 68748c2ecf20Sopenharmony_ci return IRQ_HANDLED; 68758c2ecf20Sopenharmony_ci} 68768c2ecf20Sopenharmony_ci 68778c2ecf20Sopenharmony_cistatic void igb_write_itr(struct igb_q_vector *q_vector) 68788c2ecf20Sopenharmony_ci{ 68798c2ecf20Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 68808c2ecf20Sopenharmony_ci u32 itr_val = q_vector->itr_val & 0x7FFC; 68818c2ecf20Sopenharmony_ci 68828c2ecf20Sopenharmony_ci if (!q_vector->set_itr) 68838c2ecf20Sopenharmony_ci return; 68848c2ecf20Sopenharmony_ci 68858c2ecf20Sopenharmony_ci if (!itr_val) 68868c2ecf20Sopenharmony_ci itr_val = 0x4; 68878c2ecf20Sopenharmony_ci 68888c2ecf20Sopenharmony_ci if (adapter->hw.mac.type == e1000_82575) 68898c2ecf20Sopenharmony_ci itr_val |= itr_val << 16; 68908c2ecf20Sopenharmony_ci else 68918c2ecf20Sopenharmony_ci itr_val |= E1000_EITR_CNT_IGNR; 68928c2ecf20Sopenharmony_ci 68938c2ecf20Sopenharmony_ci writel(itr_val, q_vector->itr_register); 68948c2ecf20Sopenharmony_ci q_vector->set_itr = 0; 68958c2ecf20Sopenharmony_ci} 68968c2ecf20Sopenharmony_ci 68978c2ecf20Sopenharmony_cistatic irqreturn_t igb_msix_ring(int irq, void *data) 68988c2ecf20Sopenharmony_ci{ 68998c2ecf20Sopenharmony_ci struct igb_q_vector *q_vector = data; 69008c2ecf20Sopenharmony_ci 69018c2ecf20Sopenharmony_ci /* Write the ITR value calculated from the previous interrupt. */ 69028c2ecf20Sopenharmony_ci igb_write_itr(q_vector); 69038c2ecf20Sopenharmony_ci 69048c2ecf20Sopenharmony_ci napi_schedule(&q_vector->napi); 69058c2ecf20Sopenharmony_ci 69068c2ecf20Sopenharmony_ci return IRQ_HANDLED; 69078c2ecf20Sopenharmony_ci} 69088c2ecf20Sopenharmony_ci 69098c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_DCA 69108c2ecf20Sopenharmony_cistatic void igb_update_tx_dca(struct igb_adapter *adapter, 69118c2ecf20Sopenharmony_ci struct igb_ring *tx_ring, 69128c2ecf20Sopenharmony_ci int cpu) 69138c2ecf20Sopenharmony_ci{ 69148c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 69158c2ecf20Sopenharmony_ci u32 txctrl = dca3_get_tag(tx_ring->dev, cpu); 69168c2ecf20Sopenharmony_ci 69178c2ecf20Sopenharmony_ci if (hw->mac.type != e1000_82575) 69188c2ecf20Sopenharmony_ci txctrl <<= E1000_DCA_TXCTRL_CPUID_SHIFT; 69198c2ecf20Sopenharmony_ci 69208c2ecf20Sopenharmony_ci /* We can enable relaxed ordering for reads, but not writes when 69218c2ecf20Sopenharmony_ci * DCA is enabled. This is due to a known issue in some chipsets 69228c2ecf20Sopenharmony_ci * which will cause the DCA tag to be cleared. 69238c2ecf20Sopenharmony_ci */ 69248c2ecf20Sopenharmony_ci txctrl |= E1000_DCA_TXCTRL_DESC_RRO_EN | 69258c2ecf20Sopenharmony_ci E1000_DCA_TXCTRL_DATA_RRO_EN | 69268c2ecf20Sopenharmony_ci E1000_DCA_TXCTRL_DESC_DCA_EN; 69278c2ecf20Sopenharmony_ci 69288c2ecf20Sopenharmony_ci wr32(E1000_DCA_TXCTRL(tx_ring->reg_idx), txctrl); 69298c2ecf20Sopenharmony_ci} 69308c2ecf20Sopenharmony_ci 69318c2ecf20Sopenharmony_cistatic void igb_update_rx_dca(struct igb_adapter *adapter, 69328c2ecf20Sopenharmony_ci struct igb_ring *rx_ring, 69338c2ecf20Sopenharmony_ci int cpu) 69348c2ecf20Sopenharmony_ci{ 69358c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 69368c2ecf20Sopenharmony_ci u32 rxctrl = dca3_get_tag(&adapter->pdev->dev, cpu); 69378c2ecf20Sopenharmony_ci 69388c2ecf20Sopenharmony_ci if (hw->mac.type != e1000_82575) 69398c2ecf20Sopenharmony_ci rxctrl <<= E1000_DCA_RXCTRL_CPUID_SHIFT; 69408c2ecf20Sopenharmony_ci 69418c2ecf20Sopenharmony_ci /* We can enable relaxed ordering for reads, but not writes when 69428c2ecf20Sopenharmony_ci * DCA is enabled. This is due to a known issue in some chipsets 69438c2ecf20Sopenharmony_ci * which will cause the DCA tag to be cleared. 69448c2ecf20Sopenharmony_ci */ 69458c2ecf20Sopenharmony_ci rxctrl |= E1000_DCA_RXCTRL_DESC_RRO_EN | 69468c2ecf20Sopenharmony_ci E1000_DCA_RXCTRL_DESC_DCA_EN; 69478c2ecf20Sopenharmony_ci 69488c2ecf20Sopenharmony_ci wr32(E1000_DCA_RXCTRL(rx_ring->reg_idx), rxctrl); 69498c2ecf20Sopenharmony_ci} 69508c2ecf20Sopenharmony_ci 69518c2ecf20Sopenharmony_cistatic void igb_update_dca(struct igb_q_vector *q_vector) 69528c2ecf20Sopenharmony_ci{ 69538c2ecf20Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 69548c2ecf20Sopenharmony_ci int cpu = get_cpu(); 69558c2ecf20Sopenharmony_ci 69568c2ecf20Sopenharmony_ci if (q_vector->cpu == cpu) 69578c2ecf20Sopenharmony_ci goto out_no_update; 69588c2ecf20Sopenharmony_ci 69598c2ecf20Sopenharmony_ci if (q_vector->tx.ring) 69608c2ecf20Sopenharmony_ci igb_update_tx_dca(adapter, q_vector->tx.ring, cpu); 69618c2ecf20Sopenharmony_ci 69628c2ecf20Sopenharmony_ci if (q_vector->rx.ring) 69638c2ecf20Sopenharmony_ci igb_update_rx_dca(adapter, q_vector->rx.ring, cpu); 69648c2ecf20Sopenharmony_ci 69658c2ecf20Sopenharmony_ci q_vector->cpu = cpu; 69668c2ecf20Sopenharmony_ciout_no_update: 69678c2ecf20Sopenharmony_ci put_cpu(); 69688c2ecf20Sopenharmony_ci} 69698c2ecf20Sopenharmony_ci 69708c2ecf20Sopenharmony_cistatic void igb_setup_dca(struct igb_adapter *adapter) 69718c2ecf20Sopenharmony_ci{ 69728c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 69738c2ecf20Sopenharmony_ci int i; 69748c2ecf20Sopenharmony_ci 69758c2ecf20Sopenharmony_ci if (!(adapter->flags & IGB_FLAG_DCA_ENABLED)) 69768c2ecf20Sopenharmony_ci return; 69778c2ecf20Sopenharmony_ci 69788c2ecf20Sopenharmony_ci /* Always use CB2 mode, difference is masked in the CB driver. */ 69798c2ecf20Sopenharmony_ci wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2); 69808c2ecf20Sopenharmony_ci 69818c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) { 69828c2ecf20Sopenharmony_ci adapter->q_vector[i]->cpu = -1; 69838c2ecf20Sopenharmony_ci igb_update_dca(adapter->q_vector[i]); 69848c2ecf20Sopenharmony_ci } 69858c2ecf20Sopenharmony_ci} 69868c2ecf20Sopenharmony_ci 69878c2ecf20Sopenharmony_cistatic int __igb_notify_dca(struct device *dev, void *data) 69888c2ecf20Sopenharmony_ci{ 69898c2ecf20Sopenharmony_ci struct net_device *netdev = dev_get_drvdata(dev); 69908c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 69918c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 69928c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 69938c2ecf20Sopenharmony_ci unsigned long event = *(unsigned long *)data; 69948c2ecf20Sopenharmony_ci 69958c2ecf20Sopenharmony_ci switch (event) { 69968c2ecf20Sopenharmony_ci case DCA_PROVIDER_ADD: 69978c2ecf20Sopenharmony_ci /* if already enabled, don't do it again */ 69988c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_DCA_ENABLED) 69998c2ecf20Sopenharmony_ci break; 70008c2ecf20Sopenharmony_ci if (dca_add_requester(dev) == 0) { 70018c2ecf20Sopenharmony_ci adapter->flags |= IGB_FLAG_DCA_ENABLED; 70028c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "DCA enabled\n"); 70038c2ecf20Sopenharmony_ci igb_setup_dca(adapter); 70048c2ecf20Sopenharmony_ci break; 70058c2ecf20Sopenharmony_ci } 70068c2ecf20Sopenharmony_ci fallthrough; /* since DCA is disabled. */ 70078c2ecf20Sopenharmony_ci case DCA_PROVIDER_REMOVE: 70088c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_DCA_ENABLED) { 70098c2ecf20Sopenharmony_ci /* without this a class_device is left 70108c2ecf20Sopenharmony_ci * hanging around in the sysfs model 70118c2ecf20Sopenharmony_ci */ 70128c2ecf20Sopenharmony_ci dca_remove_requester(dev); 70138c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "DCA disabled\n"); 70148c2ecf20Sopenharmony_ci adapter->flags &= ~IGB_FLAG_DCA_ENABLED; 70158c2ecf20Sopenharmony_ci wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_DISABLE); 70168c2ecf20Sopenharmony_ci } 70178c2ecf20Sopenharmony_ci break; 70188c2ecf20Sopenharmony_ci } 70198c2ecf20Sopenharmony_ci 70208c2ecf20Sopenharmony_ci return 0; 70218c2ecf20Sopenharmony_ci} 70228c2ecf20Sopenharmony_ci 70238c2ecf20Sopenharmony_cistatic int igb_notify_dca(struct notifier_block *nb, unsigned long event, 70248c2ecf20Sopenharmony_ci void *p) 70258c2ecf20Sopenharmony_ci{ 70268c2ecf20Sopenharmony_ci int ret_val; 70278c2ecf20Sopenharmony_ci 70288c2ecf20Sopenharmony_ci ret_val = driver_for_each_device(&igb_driver.driver, NULL, &event, 70298c2ecf20Sopenharmony_ci __igb_notify_dca); 70308c2ecf20Sopenharmony_ci 70318c2ecf20Sopenharmony_ci return ret_val ? NOTIFY_BAD : NOTIFY_DONE; 70328c2ecf20Sopenharmony_ci} 70338c2ecf20Sopenharmony_ci#endif /* CONFIG_IGB_DCA */ 70348c2ecf20Sopenharmony_ci 70358c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 70368c2ecf20Sopenharmony_cistatic int igb_vf_configure(struct igb_adapter *adapter, int vf) 70378c2ecf20Sopenharmony_ci{ 70388c2ecf20Sopenharmony_ci unsigned char mac_addr[ETH_ALEN]; 70398c2ecf20Sopenharmony_ci 70408c2ecf20Sopenharmony_ci eth_zero_addr(mac_addr); 70418c2ecf20Sopenharmony_ci igb_set_vf_mac(adapter, vf, mac_addr); 70428c2ecf20Sopenharmony_ci 70438c2ecf20Sopenharmony_ci /* By default spoof check is enabled for all VFs */ 70448c2ecf20Sopenharmony_ci adapter->vf_data[vf].spoofchk_enabled = true; 70458c2ecf20Sopenharmony_ci 70468c2ecf20Sopenharmony_ci /* By default VFs are not trusted */ 70478c2ecf20Sopenharmony_ci adapter->vf_data[vf].trusted = false; 70488c2ecf20Sopenharmony_ci 70498c2ecf20Sopenharmony_ci return 0; 70508c2ecf20Sopenharmony_ci} 70518c2ecf20Sopenharmony_ci 70528c2ecf20Sopenharmony_ci#endif 70538c2ecf20Sopenharmony_cistatic void igb_ping_all_vfs(struct igb_adapter *adapter) 70548c2ecf20Sopenharmony_ci{ 70558c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 70568c2ecf20Sopenharmony_ci u32 ping; 70578c2ecf20Sopenharmony_ci int i; 70588c2ecf20Sopenharmony_ci 70598c2ecf20Sopenharmony_ci for (i = 0 ; i < adapter->vfs_allocated_count; i++) { 70608c2ecf20Sopenharmony_ci ping = E1000_PF_CONTROL_MSG; 70618c2ecf20Sopenharmony_ci if (adapter->vf_data[i].flags & IGB_VF_FLAG_CTS) 70628c2ecf20Sopenharmony_ci ping |= E1000_VT_MSGTYPE_CTS; 70638c2ecf20Sopenharmony_ci igb_write_mbx(hw, &ping, 1, i); 70648c2ecf20Sopenharmony_ci } 70658c2ecf20Sopenharmony_ci} 70668c2ecf20Sopenharmony_ci 70678c2ecf20Sopenharmony_cistatic int igb_set_vf_promisc(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) 70688c2ecf20Sopenharmony_ci{ 70698c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 70708c2ecf20Sopenharmony_ci u32 vmolr = rd32(E1000_VMOLR(vf)); 70718c2ecf20Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 70728c2ecf20Sopenharmony_ci 70738c2ecf20Sopenharmony_ci vf_data->flags &= ~(IGB_VF_FLAG_UNI_PROMISC | 70748c2ecf20Sopenharmony_ci IGB_VF_FLAG_MULTI_PROMISC); 70758c2ecf20Sopenharmony_ci vmolr &= ~(E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE | E1000_VMOLR_MPME); 70768c2ecf20Sopenharmony_ci 70778c2ecf20Sopenharmony_ci if (*msgbuf & E1000_VF_SET_PROMISC_MULTICAST) { 70788c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_MPME; 70798c2ecf20Sopenharmony_ci vf_data->flags |= IGB_VF_FLAG_MULTI_PROMISC; 70808c2ecf20Sopenharmony_ci *msgbuf &= ~E1000_VF_SET_PROMISC_MULTICAST; 70818c2ecf20Sopenharmony_ci } else { 70828c2ecf20Sopenharmony_ci /* if we have hashes and we are clearing a multicast promisc 70838c2ecf20Sopenharmony_ci * flag we need to write the hashes to the MTA as this step 70848c2ecf20Sopenharmony_ci * was previously skipped 70858c2ecf20Sopenharmony_ci */ 70868c2ecf20Sopenharmony_ci if (vf_data->num_vf_mc_hashes > 30) { 70878c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_MPME; 70888c2ecf20Sopenharmony_ci } else if (vf_data->num_vf_mc_hashes) { 70898c2ecf20Sopenharmony_ci int j; 70908c2ecf20Sopenharmony_ci 70918c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_ROMPE; 70928c2ecf20Sopenharmony_ci for (j = 0; j < vf_data->num_vf_mc_hashes; j++) 70938c2ecf20Sopenharmony_ci igb_mta_set(hw, vf_data->vf_mc_hashes[j]); 70948c2ecf20Sopenharmony_ci } 70958c2ecf20Sopenharmony_ci } 70968c2ecf20Sopenharmony_ci 70978c2ecf20Sopenharmony_ci wr32(E1000_VMOLR(vf), vmolr); 70988c2ecf20Sopenharmony_ci 70998c2ecf20Sopenharmony_ci /* there are flags left unprocessed, likely not supported */ 71008c2ecf20Sopenharmony_ci if (*msgbuf & E1000_VT_MSGINFO_MASK) 71018c2ecf20Sopenharmony_ci return -EINVAL; 71028c2ecf20Sopenharmony_ci 71038c2ecf20Sopenharmony_ci return 0; 71048c2ecf20Sopenharmony_ci} 71058c2ecf20Sopenharmony_ci 71068c2ecf20Sopenharmony_cistatic int igb_set_vf_multicasts(struct igb_adapter *adapter, 71078c2ecf20Sopenharmony_ci u32 *msgbuf, u32 vf) 71088c2ecf20Sopenharmony_ci{ 71098c2ecf20Sopenharmony_ci int n = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; 71108c2ecf20Sopenharmony_ci u16 *hash_list = (u16 *)&msgbuf[1]; 71118c2ecf20Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 71128c2ecf20Sopenharmony_ci int i; 71138c2ecf20Sopenharmony_ci 71148c2ecf20Sopenharmony_ci /* salt away the number of multicast addresses assigned 71158c2ecf20Sopenharmony_ci * to this VF for later use to restore when the PF multi cast 71168c2ecf20Sopenharmony_ci * list changes 71178c2ecf20Sopenharmony_ci */ 71188c2ecf20Sopenharmony_ci vf_data->num_vf_mc_hashes = n; 71198c2ecf20Sopenharmony_ci 71208c2ecf20Sopenharmony_ci /* only up to 30 hash values supported */ 71218c2ecf20Sopenharmony_ci if (n > 30) 71228c2ecf20Sopenharmony_ci n = 30; 71238c2ecf20Sopenharmony_ci 71248c2ecf20Sopenharmony_ci /* store the hashes for later use */ 71258c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) 71268c2ecf20Sopenharmony_ci vf_data->vf_mc_hashes[i] = hash_list[i]; 71278c2ecf20Sopenharmony_ci 71288c2ecf20Sopenharmony_ci /* Flush and reset the mta with the new values */ 71298c2ecf20Sopenharmony_ci igb_set_rx_mode(adapter->netdev); 71308c2ecf20Sopenharmony_ci 71318c2ecf20Sopenharmony_ci return 0; 71328c2ecf20Sopenharmony_ci} 71338c2ecf20Sopenharmony_ci 71348c2ecf20Sopenharmony_cistatic void igb_restore_vf_multicasts(struct igb_adapter *adapter) 71358c2ecf20Sopenharmony_ci{ 71368c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 71378c2ecf20Sopenharmony_ci struct vf_data_storage *vf_data; 71388c2ecf20Sopenharmony_ci int i, j; 71398c2ecf20Sopenharmony_ci 71408c2ecf20Sopenharmony_ci for (i = 0; i < adapter->vfs_allocated_count; i++) { 71418c2ecf20Sopenharmony_ci u32 vmolr = rd32(E1000_VMOLR(i)); 71428c2ecf20Sopenharmony_ci 71438c2ecf20Sopenharmony_ci vmolr &= ~(E1000_VMOLR_ROMPE | E1000_VMOLR_MPME); 71448c2ecf20Sopenharmony_ci 71458c2ecf20Sopenharmony_ci vf_data = &adapter->vf_data[i]; 71468c2ecf20Sopenharmony_ci 71478c2ecf20Sopenharmony_ci if ((vf_data->num_vf_mc_hashes > 30) || 71488c2ecf20Sopenharmony_ci (vf_data->flags & IGB_VF_FLAG_MULTI_PROMISC)) { 71498c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_MPME; 71508c2ecf20Sopenharmony_ci } else if (vf_data->num_vf_mc_hashes) { 71518c2ecf20Sopenharmony_ci vmolr |= E1000_VMOLR_ROMPE; 71528c2ecf20Sopenharmony_ci for (j = 0; j < vf_data->num_vf_mc_hashes; j++) 71538c2ecf20Sopenharmony_ci igb_mta_set(hw, vf_data->vf_mc_hashes[j]); 71548c2ecf20Sopenharmony_ci } 71558c2ecf20Sopenharmony_ci wr32(E1000_VMOLR(i), vmolr); 71568c2ecf20Sopenharmony_ci } 71578c2ecf20Sopenharmony_ci} 71588c2ecf20Sopenharmony_ci 71598c2ecf20Sopenharmony_cistatic void igb_clear_vf_vfta(struct igb_adapter *adapter, u32 vf) 71608c2ecf20Sopenharmony_ci{ 71618c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 71628c2ecf20Sopenharmony_ci u32 pool_mask, vlvf_mask, i; 71638c2ecf20Sopenharmony_ci 71648c2ecf20Sopenharmony_ci /* create mask for VF and other pools */ 71658c2ecf20Sopenharmony_ci pool_mask = E1000_VLVF_POOLSEL_MASK; 71668c2ecf20Sopenharmony_ci vlvf_mask = BIT(E1000_VLVF_POOLSEL_SHIFT + vf); 71678c2ecf20Sopenharmony_ci 71688c2ecf20Sopenharmony_ci /* drop PF from pool bits */ 71698c2ecf20Sopenharmony_ci pool_mask &= ~BIT(E1000_VLVF_POOLSEL_SHIFT + 71708c2ecf20Sopenharmony_ci adapter->vfs_allocated_count); 71718c2ecf20Sopenharmony_ci 71728c2ecf20Sopenharmony_ci /* Find the vlan filter for this id */ 71738c2ecf20Sopenharmony_ci for (i = E1000_VLVF_ARRAY_SIZE; i--;) { 71748c2ecf20Sopenharmony_ci u32 vlvf = rd32(E1000_VLVF(i)); 71758c2ecf20Sopenharmony_ci u32 vfta_mask, vid, vfta; 71768c2ecf20Sopenharmony_ci 71778c2ecf20Sopenharmony_ci /* remove the vf from the pool */ 71788c2ecf20Sopenharmony_ci if (!(vlvf & vlvf_mask)) 71798c2ecf20Sopenharmony_ci continue; 71808c2ecf20Sopenharmony_ci 71818c2ecf20Sopenharmony_ci /* clear out bit from VLVF */ 71828c2ecf20Sopenharmony_ci vlvf ^= vlvf_mask; 71838c2ecf20Sopenharmony_ci 71848c2ecf20Sopenharmony_ci /* if other pools are present, just remove ourselves */ 71858c2ecf20Sopenharmony_ci if (vlvf & pool_mask) 71868c2ecf20Sopenharmony_ci goto update_vlvfb; 71878c2ecf20Sopenharmony_ci 71888c2ecf20Sopenharmony_ci /* if PF is present, leave VFTA */ 71898c2ecf20Sopenharmony_ci if (vlvf & E1000_VLVF_POOLSEL_MASK) 71908c2ecf20Sopenharmony_ci goto update_vlvf; 71918c2ecf20Sopenharmony_ci 71928c2ecf20Sopenharmony_ci vid = vlvf & E1000_VLVF_VLANID_MASK; 71938c2ecf20Sopenharmony_ci vfta_mask = BIT(vid % 32); 71948c2ecf20Sopenharmony_ci 71958c2ecf20Sopenharmony_ci /* clear bit from VFTA */ 71968c2ecf20Sopenharmony_ci vfta = adapter->shadow_vfta[vid / 32]; 71978c2ecf20Sopenharmony_ci if (vfta & vfta_mask) 71988c2ecf20Sopenharmony_ci hw->mac.ops.write_vfta(hw, vid / 32, vfta ^ vfta_mask); 71998c2ecf20Sopenharmony_ciupdate_vlvf: 72008c2ecf20Sopenharmony_ci /* clear pool selection enable */ 72018c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_VLAN_PROMISC) 72028c2ecf20Sopenharmony_ci vlvf &= E1000_VLVF_POOLSEL_MASK; 72038c2ecf20Sopenharmony_ci else 72048c2ecf20Sopenharmony_ci vlvf = 0; 72058c2ecf20Sopenharmony_ciupdate_vlvfb: 72068c2ecf20Sopenharmony_ci /* clear pool bits */ 72078c2ecf20Sopenharmony_ci wr32(E1000_VLVF(i), vlvf); 72088c2ecf20Sopenharmony_ci } 72098c2ecf20Sopenharmony_ci} 72108c2ecf20Sopenharmony_ci 72118c2ecf20Sopenharmony_cistatic int igb_find_vlvf_entry(struct e1000_hw *hw, u32 vlan) 72128c2ecf20Sopenharmony_ci{ 72138c2ecf20Sopenharmony_ci u32 vlvf; 72148c2ecf20Sopenharmony_ci int idx; 72158c2ecf20Sopenharmony_ci 72168c2ecf20Sopenharmony_ci /* short cut the special case */ 72178c2ecf20Sopenharmony_ci if (vlan == 0) 72188c2ecf20Sopenharmony_ci return 0; 72198c2ecf20Sopenharmony_ci 72208c2ecf20Sopenharmony_ci /* Search for the VLAN id in the VLVF entries */ 72218c2ecf20Sopenharmony_ci for (idx = E1000_VLVF_ARRAY_SIZE; --idx;) { 72228c2ecf20Sopenharmony_ci vlvf = rd32(E1000_VLVF(idx)); 72238c2ecf20Sopenharmony_ci if ((vlvf & VLAN_VID_MASK) == vlan) 72248c2ecf20Sopenharmony_ci break; 72258c2ecf20Sopenharmony_ci } 72268c2ecf20Sopenharmony_ci 72278c2ecf20Sopenharmony_ci return idx; 72288c2ecf20Sopenharmony_ci} 72298c2ecf20Sopenharmony_ci 72308c2ecf20Sopenharmony_cistatic void igb_update_pf_vlvf(struct igb_adapter *adapter, u32 vid) 72318c2ecf20Sopenharmony_ci{ 72328c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 72338c2ecf20Sopenharmony_ci u32 bits, pf_id; 72348c2ecf20Sopenharmony_ci int idx; 72358c2ecf20Sopenharmony_ci 72368c2ecf20Sopenharmony_ci idx = igb_find_vlvf_entry(hw, vid); 72378c2ecf20Sopenharmony_ci if (!idx) 72388c2ecf20Sopenharmony_ci return; 72398c2ecf20Sopenharmony_ci 72408c2ecf20Sopenharmony_ci /* See if any other pools are set for this VLAN filter 72418c2ecf20Sopenharmony_ci * entry other than the PF. 72428c2ecf20Sopenharmony_ci */ 72438c2ecf20Sopenharmony_ci pf_id = adapter->vfs_allocated_count + E1000_VLVF_POOLSEL_SHIFT; 72448c2ecf20Sopenharmony_ci bits = ~BIT(pf_id) & E1000_VLVF_POOLSEL_MASK; 72458c2ecf20Sopenharmony_ci bits &= rd32(E1000_VLVF(idx)); 72468c2ecf20Sopenharmony_ci 72478c2ecf20Sopenharmony_ci /* Disable the filter so this falls into the default pool. */ 72488c2ecf20Sopenharmony_ci if (!bits) { 72498c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_VLAN_PROMISC) 72508c2ecf20Sopenharmony_ci wr32(E1000_VLVF(idx), BIT(pf_id)); 72518c2ecf20Sopenharmony_ci else 72528c2ecf20Sopenharmony_ci wr32(E1000_VLVF(idx), 0); 72538c2ecf20Sopenharmony_ci } 72548c2ecf20Sopenharmony_ci} 72558c2ecf20Sopenharmony_ci 72568c2ecf20Sopenharmony_cistatic s32 igb_set_vf_vlan(struct igb_adapter *adapter, u32 vid, 72578c2ecf20Sopenharmony_ci bool add, u32 vf) 72588c2ecf20Sopenharmony_ci{ 72598c2ecf20Sopenharmony_ci int pf_id = adapter->vfs_allocated_count; 72608c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 72618c2ecf20Sopenharmony_ci int err; 72628c2ecf20Sopenharmony_ci 72638c2ecf20Sopenharmony_ci /* If VLAN overlaps with one the PF is currently monitoring make 72648c2ecf20Sopenharmony_ci * sure that we are able to allocate a VLVF entry. This may be 72658c2ecf20Sopenharmony_ci * redundant but it guarantees PF will maintain visibility to 72668c2ecf20Sopenharmony_ci * the VLAN. 72678c2ecf20Sopenharmony_ci */ 72688c2ecf20Sopenharmony_ci if (add && test_bit(vid, adapter->active_vlans)) { 72698c2ecf20Sopenharmony_ci err = igb_vfta_set(hw, vid, pf_id, true, false); 72708c2ecf20Sopenharmony_ci if (err) 72718c2ecf20Sopenharmony_ci return err; 72728c2ecf20Sopenharmony_ci } 72738c2ecf20Sopenharmony_ci 72748c2ecf20Sopenharmony_ci err = igb_vfta_set(hw, vid, vf, add, false); 72758c2ecf20Sopenharmony_ci 72768c2ecf20Sopenharmony_ci if (add && !err) 72778c2ecf20Sopenharmony_ci return err; 72788c2ecf20Sopenharmony_ci 72798c2ecf20Sopenharmony_ci /* If we failed to add the VF VLAN or we are removing the VF VLAN 72808c2ecf20Sopenharmony_ci * we may need to drop the PF pool bit in order to allow us to free 72818c2ecf20Sopenharmony_ci * up the VLVF resources. 72828c2ecf20Sopenharmony_ci */ 72838c2ecf20Sopenharmony_ci if (test_bit(vid, adapter->active_vlans) || 72848c2ecf20Sopenharmony_ci (adapter->flags & IGB_FLAG_VLAN_PROMISC)) 72858c2ecf20Sopenharmony_ci igb_update_pf_vlvf(adapter, vid); 72868c2ecf20Sopenharmony_ci 72878c2ecf20Sopenharmony_ci return err; 72888c2ecf20Sopenharmony_ci} 72898c2ecf20Sopenharmony_ci 72908c2ecf20Sopenharmony_cistatic void igb_set_vmvir(struct igb_adapter *adapter, u32 vid, u32 vf) 72918c2ecf20Sopenharmony_ci{ 72928c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 72938c2ecf20Sopenharmony_ci 72948c2ecf20Sopenharmony_ci if (vid) 72958c2ecf20Sopenharmony_ci wr32(E1000_VMVIR(vf), (vid | E1000_VMVIR_VLANA_DEFAULT)); 72968c2ecf20Sopenharmony_ci else 72978c2ecf20Sopenharmony_ci wr32(E1000_VMVIR(vf), 0); 72988c2ecf20Sopenharmony_ci} 72998c2ecf20Sopenharmony_ci 73008c2ecf20Sopenharmony_cistatic int igb_enable_port_vlan(struct igb_adapter *adapter, int vf, 73018c2ecf20Sopenharmony_ci u16 vlan, u8 qos) 73028c2ecf20Sopenharmony_ci{ 73038c2ecf20Sopenharmony_ci int err; 73048c2ecf20Sopenharmony_ci 73058c2ecf20Sopenharmony_ci err = igb_set_vf_vlan(adapter, vlan, true, vf); 73068c2ecf20Sopenharmony_ci if (err) 73078c2ecf20Sopenharmony_ci return err; 73088c2ecf20Sopenharmony_ci 73098c2ecf20Sopenharmony_ci igb_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf); 73108c2ecf20Sopenharmony_ci igb_set_vmolr(adapter, vf, !vlan); 73118c2ecf20Sopenharmony_ci 73128c2ecf20Sopenharmony_ci /* revoke access to previous VLAN */ 73138c2ecf20Sopenharmony_ci if (vlan != adapter->vf_data[vf].pf_vlan) 73148c2ecf20Sopenharmony_ci igb_set_vf_vlan(adapter, adapter->vf_data[vf].pf_vlan, 73158c2ecf20Sopenharmony_ci false, vf); 73168c2ecf20Sopenharmony_ci 73178c2ecf20Sopenharmony_ci adapter->vf_data[vf].pf_vlan = vlan; 73188c2ecf20Sopenharmony_ci adapter->vf_data[vf].pf_qos = qos; 73198c2ecf20Sopenharmony_ci igb_set_vf_vlan_strip(adapter, vf, true); 73208c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, 73218c2ecf20Sopenharmony_ci "Setting VLAN %d, QOS 0x%x on VF %d\n", vlan, qos, vf); 73228c2ecf20Sopenharmony_ci if (test_bit(__IGB_DOWN, &adapter->state)) { 73238c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, 73248c2ecf20Sopenharmony_ci "The VF VLAN has been set, but the PF device is not up.\n"); 73258c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, 73268c2ecf20Sopenharmony_ci "Bring the PF device up before attempting to use the VF device.\n"); 73278c2ecf20Sopenharmony_ci } 73288c2ecf20Sopenharmony_ci 73298c2ecf20Sopenharmony_ci return err; 73308c2ecf20Sopenharmony_ci} 73318c2ecf20Sopenharmony_ci 73328c2ecf20Sopenharmony_cistatic int igb_disable_port_vlan(struct igb_adapter *adapter, int vf) 73338c2ecf20Sopenharmony_ci{ 73348c2ecf20Sopenharmony_ci /* Restore tagless access via VLAN 0 */ 73358c2ecf20Sopenharmony_ci igb_set_vf_vlan(adapter, 0, true, vf); 73368c2ecf20Sopenharmony_ci 73378c2ecf20Sopenharmony_ci igb_set_vmvir(adapter, 0, vf); 73388c2ecf20Sopenharmony_ci igb_set_vmolr(adapter, vf, true); 73398c2ecf20Sopenharmony_ci 73408c2ecf20Sopenharmony_ci /* Remove any PF assigned VLAN */ 73418c2ecf20Sopenharmony_ci if (adapter->vf_data[vf].pf_vlan) 73428c2ecf20Sopenharmony_ci igb_set_vf_vlan(adapter, adapter->vf_data[vf].pf_vlan, 73438c2ecf20Sopenharmony_ci false, vf); 73448c2ecf20Sopenharmony_ci 73458c2ecf20Sopenharmony_ci adapter->vf_data[vf].pf_vlan = 0; 73468c2ecf20Sopenharmony_ci adapter->vf_data[vf].pf_qos = 0; 73478c2ecf20Sopenharmony_ci igb_set_vf_vlan_strip(adapter, vf, false); 73488c2ecf20Sopenharmony_ci 73498c2ecf20Sopenharmony_ci return 0; 73508c2ecf20Sopenharmony_ci} 73518c2ecf20Sopenharmony_ci 73528c2ecf20Sopenharmony_cistatic int igb_ndo_set_vf_vlan(struct net_device *netdev, int vf, 73538c2ecf20Sopenharmony_ci u16 vlan, u8 qos, __be16 vlan_proto) 73548c2ecf20Sopenharmony_ci{ 73558c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 73568c2ecf20Sopenharmony_ci 73578c2ecf20Sopenharmony_ci if ((vf >= adapter->vfs_allocated_count) || (vlan > 4095) || (qos > 7)) 73588c2ecf20Sopenharmony_ci return -EINVAL; 73598c2ecf20Sopenharmony_ci 73608c2ecf20Sopenharmony_ci if (vlan_proto != htons(ETH_P_8021Q)) 73618c2ecf20Sopenharmony_ci return -EPROTONOSUPPORT; 73628c2ecf20Sopenharmony_ci 73638c2ecf20Sopenharmony_ci return (vlan || qos) ? igb_enable_port_vlan(adapter, vf, vlan, qos) : 73648c2ecf20Sopenharmony_ci igb_disable_port_vlan(adapter, vf); 73658c2ecf20Sopenharmony_ci} 73668c2ecf20Sopenharmony_ci 73678c2ecf20Sopenharmony_cistatic int igb_set_vf_vlan_msg(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) 73688c2ecf20Sopenharmony_ci{ 73698c2ecf20Sopenharmony_ci int add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; 73708c2ecf20Sopenharmony_ci int vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK); 73718c2ecf20Sopenharmony_ci int ret; 73728c2ecf20Sopenharmony_ci 73738c2ecf20Sopenharmony_ci if (adapter->vf_data[vf].pf_vlan) 73748c2ecf20Sopenharmony_ci return -1; 73758c2ecf20Sopenharmony_ci 73768c2ecf20Sopenharmony_ci /* VLAN 0 is a special case, don't allow it to be removed */ 73778c2ecf20Sopenharmony_ci if (!vid && !add) 73788c2ecf20Sopenharmony_ci return 0; 73798c2ecf20Sopenharmony_ci 73808c2ecf20Sopenharmony_ci ret = igb_set_vf_vlan(adapter, vid, !!add, vf); 73818c2ecf20Sopenharmony_ci if (!ret) 73828c2ecf20Sopenharmony_ci igb_set_vf_vlan_strip(adapter, vf, !!vid); 73838c2ecf20Sopenharmony_ci return ret; 73848c2ecf20Sopenharmony_ci} 73858c2ecf20Sopenharmony_ci 73868c2ecf20Sopenharmony_cistatic inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf) 73878c2ecf20Sopenharmony_ci{ 73888c2ecf20Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 73898c2ecf20Sopenharmony_ci 73908c2ecf20Sopenharmony_ci /* clear flags - except flag that indicates PF has set the MAC */ 73918c2ecf20Sopenharmony_ci vf_data->flags &= IGB_VF_FLAG_PF_SET_MAC; 73928c2ecf20Sopenharmony_ci vf_data->last_nack = jiffies; 73938c2ecf20Sopenharmony_ci 73948c2ecf20Sopenharmony_ci /* reset vlans for device */ 73958c2ecf20Sopenharmony_ci igb_clear_vf_vfta(adapter, vf); 73968c2ecf20Sopenharmony_ci igb_set_vf_vlan(adapter, vf_data->pf_vlan, true, vf); 73978c2ecf20Sopenharmony_ci igb_set_vmvir(adapter, vf_data->pf_vlan | 73988c2ecf20Sopenharmony_ci (vf_data->pf_qos << VLAN_PRIO_SHIFT), vf); 73998c2ecf20Sopenharmony_ci igb_set_vmolr(adapter, vf, !vf_data->pf_vlan); 74008c2ecf20Sopenharmony_ci igb_set_vf_vlan_strip(adapter, vf, !!(vf_data->pf_vlan)); 74018c2ecf20Sopenharmony_ci 74028c2ecf20Sopenharmony_ci /* reset multicast table array for vf */ 74038c2ecf20Sopenharmony_ci adapter->vf_data[vf].num_vf_mc_hashes = 0; 74048c2ecf20Sopenharmony_ci 74058c2ecf20Sopenharmony_ci /* Flush and reset the mta with the new values */ 74068c2ecf20Sopenharmony_ci igb_set_rx_mode(adapter->netdev); 74078c2ecf20Sopenharmony_ci} 74088c2ecf20Sopenharmony_ci 74098c2ecf20Sopenharmony_cistatic void igb_vf_reset_event(struct igb_adapter *adapter, u32 vf) 74108c2ecf20Sopenharmony_ci{ 74118c2ecf20Sopenharmony_ci unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; 74128c2ecf20Sopenharmony_ci 74138c2ecf20Sopenharmony_ci /* clear mac address as we were hotplug removed/added */ 74148c2ecf20Sopenharmony_ci if (!(adapter->vf_data[vf].flags & IGB_VF_FLAG_PF_SET_MAC)) 74158c2ecf20Sopenharmony_ci eth_zero_addr(vf_mac); 74168c2ecf20Sopenharmony_ci 74178c2ecf20Sopenharmony_ci /* process remaining reset events */ 74188c2ecf20Sopenharmony_ci igb_vf_reset(adapter, vf); 74198c2ecf20Sopenharmony_ci} 74208c2ecf20Sopenharmony_ci 74218c2ecf20Sopenharmony_cistatic void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) 74228c2ecf20Sopenharmony_ci{ 74238c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 74248c2ecf20Sopenharmony_ci unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; 74258c2ecf20Sopenharmony_ci u32 reg, msgbuf[3] = {}; 74268c2ecf20Sopenharmony_ci u8 *addr = (u8 *)(&msgbuf[1]); 74278c2ecf20Sopenharmony_ci 74288c2ecf20Sopenharmony_ci /* process all the same items cleared in a function level reset */ 74298c2ecf20Sopenharmony_ci igb_vf_reset(adapter, vf); 74308c2ecf20Sopenharmony_ci 74318c2ecf20Sopenharmony_ci /* set vf mac address */ 74328c2ecf20Sopenharmony_ci igb_set_vf_mac(adapter, vf, vf_mac); 74338c2ecf20Sopenharmony_ci 74348c2ecf20Sopenharmony_ci /* enable transmit and receive for vf */ 74358c2ecf20Sopenharmony_ci reg = rd32(E1000_VFTE); 74368c2ecf20Sopenharmony_ci wr32(E1000_VFTE, reg | BIT(vf)); 74378c2ecf20Sopenharmony_ci reg = rd32(E1000_VFRE); 74388c2ecf20Sopenharmony_ci wr32(E1000_VFRE, reg | BIT(vf)); 74398c2ecf20Sopenharmony_ci 74408c2ecf20Sopenharmony_ci adapter->vf_data[vf].flags |= IGB_VF_FLAG_CTS; 74418c2ecf20Sopenharmony_ci 74428c2ecf20Sopenharmony_ci /* reply to reset with ack and vf mac address */ 74438c2ecf20Sopenharmony_ci if (!is_zero_ether_addr(vf_mac)) { 74448c2ecf20Sopenharmony_ci msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; 74458c2ecf20Sopenharmony_ci memcpy(addr, vf_mac, ETH_ALEN); 74468c2ecf20Sopenharmony_ci } else { 74478c2ecf20Sopenharmony_ci msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_NACK; 74488c2ecf20Sopenharmony_ci } 74498c2ecf20Sopenharmony_ci igb_write_mbx(hw, msgbuf, 3, vf); 74508c2ecf20Sopenharmony_ci} 74518c2ecf20Sopenharmony_ci 74528c2ecf20Sopenharmony_cistatic void igb_flush_mac_table(struct igb_adapter *adapter) 74538c2ecf20Sopenharmony_ci{ 74548c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 74558c2ecf20Sopenharmony_ci int i; 74568c2ecf20Sopenharmony_ci 74578c2ecf20Sopenharmony_ci for (i = 0; i < hw->mac.rar_entry_count; i++) { 74588c2ecf20Sopenharmony_ci adapter->mac_table[i].state &= ~IGB_MAC_STATE_IN_USE; 74598c2ecf20Sopenharmony_ci eth_zero_addr(adapter->mac_table[i].addr); 74608c2ecf20Sopenharmony_ci adapter->mac_table[i].queue = 0; 74618c2ecf20Sopenharmony_ci igb_rar_set_index(adapter, i); 74628c2ecf20Sopenharmony_ci } 74638c2ecf20Sopenharmony_ci} 74648c2ecf20Sopenharmony_ci 74658c2ecf20Sopenharmony_cistatic int igb_available_rars(struct igb_adapter *adapter, u8 queue) 74668c2ecf20Sopenharmony_ci{ 74678c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 74688c2ecf20Sopenharmony_ci /* do not count rar entries reserved for VFs MAC addresses */ 74698c2ecf20Sopenharmony_ci int rar_entries = hw->mac.rar_entry_count - 74708c2ecf20Sopenharmony_ci adapter->vfs_allocated_count; 74718c2ecf20Sopenharmony_ci int i, count = 0; 74728c2ecf20Sopenharmony_ci 74738c2ecf20Sopenharmony_ci for (i = 0; i < rar_entries; i++) { 74748c2ecf20Sopenharmony_ci /* do not count default entries */ 74758c2ecf20Sopenharmony_ci if (adapter->mac_table[i].state & IGB_MAC_STATE_DEFAULT) 74768c2ecf20Sopenharmony_ci continue; 74778c2ecf20Sopenharmony_ci 74788c2ecf20Sopenharmony_ci /* do not count "in use" entries for different queues */ 74798c2ecf20Sopenharmony_ci if ((adapter->mac_table[i].state & IGB_MAC_STATE_IN_USE) && 74808c2ecf20Sopenharmony_ci (adapter->mac_table[i].queue != queue)) 74818c2ecf20Sopenharmony_ci continue; 74828c2ecf20Sopenharmony_ci 74838c2ecf20Sopenharmony_ci count++; 74848c2ecf20Sopenharmony_ci } 74858c2ecf20Sopenharmony_ci 74868c2ecf20Sopenharmony_ci return count; 74878c2ecf20Sopenharmony_ci} 74888c2ecf20Sopenharmony_ci 74898c2ecf20Sopenharmony_ci/* Set default MAC address for the PF in the first RAR entry */ 74908c2ecf20Sopenharmony_cistatic void igb_set_default_mac_filter(struct igb_adapter *adapter) 74918c2ecf20Sopenharmony_ci{ 74928c2ecf20Sopenharmony_ci struct igb_mac_addr *mac_table = &adapter->mac_table[0]; 74938c2ecf20Sopenharmony_ci 74948c2ecf20Sopenharmony_ci ether_addr_copy(mac_table->addr, adapter->hw.mac.addr); 74958c2ecf20Sopenharmony_ci mac_table->queue = adapter->vfs_allocated_count; 74968c2ecf20Sopenharmony_ci mac_table->state = IGB_MAC_STATE_DEFAULT | IGB_MAC_STATE_IN_USE; 74978c2ecf20Sopenharmony_ci 74988c2ecf20Sopenharmony_ci igb_rar_set_index(adapter, 0); 74998c2ecf20Sopenharmony_ci} 75008c2ecf20Sopenharmony_ci 75018c2ecf20Sopenharmony_ci/* If the filter to be added and an already existing filter express 75028c2ecf20Sopenharmony_ci * the same address and address type, it should be possible to only 75038c2ecf20Sopenharmony_ci * override the other configurations, for example the queue to steer 75048c2ecf20Sopenharmony_ci * traffic. 75058c2ecf20Sopenharmony_ci */ 75068c2ecf20Sopenharmony_cistatic bool igb_mac_entry_can_be_used(const struct igb_mac_addr *entry, 75078c2ecf20Sopenharmony_ci const u8 *addr, const u8 flags) 75088c2ecf20Sopenharmony_ci{ 75098c2ecf20Sopenharmony_ci if (!(entry->state & IGB_MAC_STATE_IN_USE)) 75108c2ecf20Sopenharmony_ci return true; 75118c2ecf20Sopenharmony_ci 75128c2ecf20Sopenharmony_ci if ((entry->state & IGB_MAC_STATE_SRC_ADDR) != 75138c2ecf20Sopenharmony_ci (flags & IGB_MAC_STATE_SRC_ADDR)) 75148c2ecf20Sopenharmony_ci return false; 75158c2ecf20Sopenharmony_ci 75168c2ecf20Sopenharmony_ci if (!ether_addr_equal(addr, entry->addr)) 75178c2ecf20Sopenharmony_ci return false; 75188c2ecf20Sopenharmony_ci 75198c2ecf20Sopenharmony_ci return true; 75208c2ecf20Sopenharmony_ci} 75218c2ecf20Sopenharmony_ci 75228c2ecf20Sopenharmony_ci/* Add a MAC filter for 'addr' directing matching traffic to 'queue', 75238c2ecf20Sopenharmony_ci * 'flags' is used to indicate what kind of match is made, match is by 75248c2ecf20Sopenharmony_ci * default for the destination address, if matching by source address 75258c2ecf20Sopenharmony_ci * is desired the flag IGB_MAC_STATE_SRC_ADDR can be used. 75268c2ecf20Sopenharmony_ci */ 75278c2ecf20Sopenharmony_cistatic int igb_add_mac_filter_flags(struct igb_adapter *adapter, 75288c2ecf20Sopenharmony_ci const u8 *addr, const u8 queue, 75298c2ecf20Sopenharmony_ci const u8 flags) 75308c2ecf20Sopenharmony_ci{ 75318c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 75328c2ecf20Sopenharmony_ci int rar_entries = hw->mac.rar_entry_count - 75338c2ecf20Sopenharmony_ci adapter->vfs_allocated_count; 75348c2ecf20Sopenharmony_ci int i; 75358c2ecf20Sopenharmony_ci 75368c2ecf20Sopenharmony_ci if (is_zero_ether_addr(addr)) 75378c2ecf20Sopenharmony_ci return -EINVAL; 75388c2ecf20Sopenharmony_ci 75398c2ecf20Sopenharmony_ci /* Search for the first empty entry in the MAC table. 75408c2ecf20Sopenharmony_ci * Do not touch entries at the end of the table reserved for the VF MAC 75418c2ecf20Sopenharmony_ci * addresses. 75428c2ecf20Sopenharmony_ci */ 75438c2ecf20Sopenharmony_ci for (i = 0; i < rar_entries; i++) { 75448c2ecf20Sopenharmony_ci if (!igb_mac_entry_can_be_used(&adapter->mac_table[i], 75458c2ecf20Sopenharmony_ci addr, flags)) 75468c2ecf20Sopenharmony_ci continue; 75478c2ecf20Sopenharmony_ci 75488c2ecf20Sopenharmony_ci ether_addr_copy(adapter->mac_table[i].addr, addr); 75498c2ecf20Sopenharmony_ci adapter->mac_table[i].queue = queue; 75508c2ecf20Sopenharmony_ci adapter->mac_table[i].state |= IGB_MAC_STATE_IN_USE | flags; 75518c2ecf20Sopenharmony_ci 75528c2ecf20Sopenharmony_ci igb_rar_set_index(adapter, i); 75538c2ecf20Sopenharmony_ci return i; 75548c2ecf20Sopenharmony_ci } 75558c2ecf20Sopenharmony_ci 75568c2ecf20Sopenharmony_ci return -ENOSPC; 75578c2ecf20Sopenharmony_ci} 75588c2ecf20Sopenharmony_ci 75598c2ecf20Sopenharmony_cistatic int igb_add_mac_filter(struct igb_adapter *adapter, const u8 *addr, 75608c2ecf20Sopenharmony_ci const u8 queue) 75618c2ecf20Sopenharmony_ci{ 75628c2ecf20Sopenharmony_ci return igb_add_mac_filter_flags(adapter, addr, queue, 0); 75638c2ecf20Sopenharmony_ci} 75648c2ecf20Sopenharmony_ci 75658c2ecf20Sopenharmony_ci/* Remove a MAC filter for 'addr' directing matching traffic to 75668c2ecf20Sopenharmony_ci * 'queue', 'flags' is used to indicate what kind of match need to be 75678c2ecf20Sopenharmony_ci * removed, match is by default for the destination address, if 75688c2ecf20Sopenharmony_ci * matching by source address is to be removed the flag 75698c2ecf20Sopenharmony_ci * IGB_MAC_STATE_SRC_ADDR can be used. 75708c2ecf20Sopenharmony_ci */ 75718c2ecf20Sopenharmony_cistatic int igb_del_mac_filter_flags(struct igb_adapter *adapter, 75728c2ecf20Sopenharmony_ci const u8 *addr, const u8 queue, 75738c2ecf20Sopenharmony_ci const u8 flags) 75748c2ecf20Sopenharmony_ci{ 75758c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 75768c2ecf20Sopenharmony_ci int rar_entries = hw->mac.rar_entry_count - 75778c2ecf20Sopenharmony_ci adapter->vfs_allocated_count; 75788c2ecf20Sopenharmony_ci int i; 75798c2ecf20Sopenharmony_ci 75808c2ecf20Sopenharmony_ci if (is_zero_ether_addr(addr)) 75818c2ecf20Sopenharmony_ci return -EINVAL; 75828c2ecf20Sopenharmony_ci 75838c2ecf20Sopenharmony_ci /* Search for matching entry in the MAC table based on given address 75848c2ecf20Sopenharmony_ci * and queue. Do not touch entries at the end of the table reserved 75858c2ecf20Sopenharmony_ci * for the VF MAC addresses. 75868c2ecf20Sopenharmony_ci */ 75878c2ecf20Sopenharmony_ci for (i = 0; i < rar_entries; i++) { 75888c2ecf20Sopenharmony_ci if (!(adapter->mac_table[i].state & IGB_MAC_STATE_IN_USE)) 75898c2ecf20Sopenharmony_ci continue; 75908c2ecf20Sopenharmony_ci if ((adapter->mac_table[i].state & flags) != flags) 75918c2ecf20Sopenharmony_ci continue; 75928c2ecf20Sopenharmony_ci if (adapter->mac_table[i].queue != queue) 75938c2ecf20Sopenharmony_ci continue; 75948c2ecf20Sopenharmony_ci if (!ether_addr_equal(adapter->mac_table[i].addr, addr)) 75958c2ecf20Sopenharmony_ci continue; 75968c2ecf20Sopenharmony_ci 75978c2ecf20Sopenharmony_ci /* When a filter for the default address is "deleted", 75988c2ecf20Sopenharmony_ci * we return it to its initial configuration 75998c2ecf20Sopenharmony_ci */ 76008c2ecf20Sopenharmony_ci if (adapter->mac_table[i].state & IGB_MAC_STATE_DEFAULT) { 76018c2ecf20Sopenharmony_ci adapter->mac_table[i].state = 76028c2ecf20Sopenharmony_ci IGB_MAC_STATE_DEFAULT | IGB_MAC_STATE_IN_USE; 76038c2ecf20Sopenharmony_ci adapter->mac_table[i].queue = 76048c2ecf20Sopenharmony_ci adapter->vfs_allocated_count; 76058c2ecf20Sopenharmony_ci } else { 76068c2ecf20Sopenharmony_ci adapter->mac_table[i].state = 0; 76078c2ecf20Sopenharmony_ci adapter->mac_table[i].queue = 0; 76088c2ecf20Sopenharmony_ci eth_zero_addr(adapter->mac_table[i].addr); 76098c2ecf20Sopenharmony_ci } 76108c2ecf20Sopenharmony_ci 76118c2ecf20Sopenharmony_ci igb_rar_set_index(adapter, i); 76128c2ecf20Sopenharmony_ci return 0; 76138c2ecf20Sopenharmony_ci } 76148c2ecf20Sopenharmony_ci 76158c2ecf20Sopenharmony_ci return -ENOENT; 76168c2ecf20Sopenharmony_ci} 76178c2ecf20Sopenharmony_ci 76188c2ecf20Sopenharmony_cistatic int igb_del_mac_filter(struct igb_adapter *adapter, const u8 *addr, 76198c2ecf20Sopenharmony_ci const u8 queue) 76208c2ecf20Sopenharmony_ci{ 76218c2ecf20Sopenharmony_ci return igb_del_mac_filter_flags(adapter, addr, queue, 0); 76228c2ecf20Sopenharmony_ci} 76238c2ecf20Sopenharmony_ci 76248c2ecf20Sopenharmony_ciint igb_add_mac_steering_filter(struct igb_adapter *adapter, 76258c2ecf20Sopenharmony_ci const u8 *addr, u8 queue, u8 flags) 76268c2ecf20Sopenharmony_ci{ 76278c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 76288c2ecf20Sopenharmony_ci 76298c2ecf20Sopenharmony_ci /* In theory, this should be supported on 82575 as well, but 76308c2ecf20Sopenharmony_ci * that part wasn't easily accessible during development. 76318c2ecf20Sopenharmony_ci */ 76328c2ecf20Sopenharmony_ci if (hw->mac.type != e1000_i210) 76338c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 76348c2ecf20Sopenharmony_ci 76358c2ecf20Sopenharmony_ci return igb_add_mac_filter_flags(adapter, addr, queue, 76368c2ecf20Sopenharmony_ci IGB_MAC_STATE_QUEUE_STEERING | flags); 76378c2ecf20Sopenharmony_ci} 76388c2ecf20Sopenharmony_ci 76398c2ecf20Sopenharmony_ciint igb_del_mac_steering_filter(struct igb_adapter *adapter, 76408c2ecf20Sopenharmony_ci const u8 *addr, u8 queue, u8 flags) 76418c2ecf20Sopenharmony_ci{ 76428c2ecf20Sopenharmony_ci return igb_del_mac_filter_flags(adapter, addr, queue, 76438c2ecf20Sopenharmony_ci IGB_MAC_STATE_QUEUE_STEERING | flags); 76448c2ecf20Sopenharmony_ci} 76458c2ecf20Sopenharmony_ci 76468c2ecf20Sopenharmony_cistatic int igb_uc_sync(struct net_device *netdev, const unsigned char *addr) 76478c2ecf20Sopenharmony_ci{ 76488c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 76498c2ecf20Sopenharmony_ci int ret; 76508c2ecf20Sopenharmony_ci 76518c2ecf20Sopenharmony_ci ret = igb_add_mac_filter(adapter, addr, adapter->vfs_allocated_count); 76528c2ecf20Sopenharmony_ci 76538c2ecf20Sopenharmony_ci return min_t(int, ret, 0); 76548c2ecf20Sopenharmony_ci} 76558c2ecf20Sopenharmony_ci 76568c2ecf20Sopenharmony_cistatic int igb_uc_unsync(struct net_device *netdev, const unsigned char *addr) 76578c2ecf20Sopenharmony_ci{ 76588c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 76598c2ecf20Sopenharmony_ci 76608c2ecf20Sopenharmony_ci igb_del_mac_filter(adapter, addr, adapter->vfs_allocated_count); 76618c2ecf20Sopenharmony_ci 76628c2ecf20Sopenharmony_ci return 0; 76638c2ecf20Sopenharmony_ci} 76648c2ecf20Sopenharmony_ci 76658c2ecf20Sopenharmony_cistatic int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf, 76668c2ecf20Sopenharmony_ci const u32 info, const u8 *addr) 76678c2ecf20Sopenharmony_ci{ 76688c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 76698c2ecf20Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 76708c2ecf20Sopenharmony_ci struct list_head *pos; 76718c2ecf20Sopenharmony_ci struct vf_mac_filter *entry = NULL; 76728c2ecf20Sopenharmony_ci int ret = 0; 76738c2ecf20Sopenharmony_ci 76748c2ecf20Sopenharmony_ci if ((vf_data->flags & IGB_VF_FLAG_PF_SET_MAC) && 76758c2ecf20Sopenharmony_ci !vf_data->trusted) { 76768c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, 76778c2ecf20Sopenharmony_ci "VF %d requested MAC filter but is administratively denied\n", 76788c2ecf20Sopenharmony_ci vf); 76798c2ecf20Sopenharmony_ci return -EINVAL; 76808c2ecf20Sopenharmony_ci } 76818c2ecf20Sopenharmony_ci if (!is_valid_ether_addr(addr)) { 76828c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, 76838c2ecf20Sopenharmony_ci "VF %d attempted to set invalid MAC filter\n", 76848c2ecf20Sopenharmony_ci vf); 76858c2ecf20Sopenharmony_ci return -EINVAL; 76868c2ecf20Sopenharmony_ci } 76878c2ecf20Sopenharmony_ci 76888c2ecf20Sopenharmony_ci switch (info) { 76898c2ecf20Sopenharmony_ci case E1000_VF_MAC_FILTER_CLR: 76908c2ecf20Sopenharmony_ci /* remove all unicast MAC filters related to the current VF */ 76918c2ecf20Sopenharmony_ci list_for_each(pos, &adapter->vf_macs.l) { 76928c2ecf20Sopenharmony_ci entry = list_entry(pos, struct vf_mac_filter, l); 76938c2ecf20Sopenharmony_ci if (entry->vf == vf) { 76948c2ecf20Sopenharmony_ci entry->vf = -1; 76958c2ecf20Sopenharmony_ci entry->free = true; 76968c2ecf20Sopenharmony_ci igb_del_mac_filter(adapter, entry->vf_mac, vf); 76978c2ecf20Sopenharmony_ci } 76988c2ecf20Sopenharmony_ci } 76998c2ecf20Sopenharmony_ci break; 77008c2ecf20Sopenharmony_ci case E1000_VF_MAC_FILTER_ADD: 77018c2ecf20Sopenharmony_ci /* try to find empty slot in the list */ 77028c2ecf20Sopenharmony_ci list_for_each(pos, &adapter->vf_macs.l) { 77038c2ecf20Sopenharmony_ci entry = list_entry(pos, struct vf_mac_filter, l); 77048c2ecf20Sopenharmony_ci if (entry->free) 77058c2ecf20Sopenharmony_ci break; 77068c2ecf20Sopenharmony_ci } 77078c2ecf20Sopenharmony_ci 77088c2ecf20Sopenharmony_ci if (entry && entry->free) { 77098c2ecf20Sopenharmony_ci entry->free = false; 77108c2ecf20Sopenharmony_ci entry->vf = vf; 77118c2ecf20Sopenharmony_ci ether_addr_copy(entry->vf_mac, addr); 77128c2ecf20Sopenharmony_ci 77138c2ecf20Sopenharmony_ci ret = igb_add_mac_filter(adapter, addr, vf); 77148c2ecf20Sopenharmony_ci ret = min_t(int, ret, 0); 77158c2ecf20Sopenharmony_ci } else { 77168c2ecf20Sopenharmony_ci ret = -ENOSPC; 77178c2ecf20Sopenharmony_ci } 77188c2ecf20Sopenharmony_ci 77198c2ecf20Sopenharmony_ci if (ret == -ENOSPC) 77208c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, 77218c2ecf20Sopenharmony_ci "VF %d has requested MAC filter but there is no space for it\n", 77228c2ecf20Sopenharmony_ci vf); 77238c2ecf20Sopenharmony_ci break; 77248c2ecf20Sopenharmony_ci default: 77258c2ecf20Sopenharmony_ci ret = -EINVAL; 77268c2ecf20Sopenharmony_ci break; 77278c2ecf20Sopenharmony_ci } 77288c2ecf20Sopenharmony_ci 77298c2ecf20Sopenharmony_ci return ret; 77308c2ecf20Sopenharmony_ci} 77318c2ecf20Sopenharmony_ci 77328c2ecf20Sopenharmony_cistatic int igb_set_vf_mac_addr(struct igb_adapter *adapter, u32 *msg, int vf) 77338c2ecf20Sopenharmony_ci{ 77348c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 77358c2ecf20Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 77368c2ecf20Sopenharmony_ci u32 info = msg[0] & E1000_VT_MSGINFO_MASK; 77378c2ecf20Sopenharmony_ci 77388c2ecf20Sopenharmony_ci /* The VF MAC Address is stored in a packed array of bytes 77398c2ecf20Sopenharmony_ci * starting at the second 32 bit word of the msg array 77408c2ecf20Sopenharmony_ci */ 77418c2ecf20Sopenharmony_ci unsigned char *addr = (unsigned char *)&msg[1]; 77428c2ecf20Sopenharmony_ci int ret = 0; 77438c2ecf20Sopenharmony_ci 77448c2ecf20Sopenharmony_ci if (!info) { 77458c2ecf20Sopenharmony_ci if ((vf_data->flags & IGB_VF_FLAG_PF_SET_MAC) && 77468c2ecf20Sopenharmony_ci !vf_data->trusted) { 77478c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, 77488c2ecf20Sopenharmony_ci "VF %d attempted to override administratively set MAC address\nReload the VF driver to resume operations\n", 77498c2ecf20Sopenharmony_ci vf); 77508c2ecf20Sopenharmony_ci return -EINVAL; 77518c2ecf20Sopenharmony_ci } 77528c2ecf20Sopenharmony_ci 77538c2ecf20Sopenharmony_ci if (!is_valid_ether_addr(addr)) { 77548c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, 77558c2ecf20Sopenharmony_ci "VF %d attempted to set invalid MAC\n", 77568c2ecf20Sopenharmony_ci vf); 77578c2ecf20Sopenharmony_ci return -EINVAL; 77588c2ecf20Sopenharmony_ci } 77598c2ecf20Sopenharmony_ci 77608c2ecf20Sopenharmony_ci ret = igb_set_vf_mac(adapter, vf, addr); 77618c2ecf20Sopenharmony_ci } else { 77628c2ecf20Sopenharmony_ci ret = igb_set_vf_mac_filter(adapter, vf, info, addr); 77638c2ecf20Sopenharmony_ci } 77648c2ecf20Sopenharmony_ci 77658c2ecf20Sopenharmony_ci return ret; 77668c2ecf20Sopenharmony_ci} 77678c2ecf20Sopenharmony_ci 77688c2ecf20Sopenharmony_cistatic void igb_rcv_ack_from_vf(struct igb_adapter *adapter, u32 vf) 77698c2ecf20Sopenharmony_ci{ 77708c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 77718c2ecf20Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 77728c2ecf20Sopenharmony_ci u32 msg = E1000_VT_MSGTYPE_NACK; 77738c2ecf20Sopenharmony_ci 77748c2ecf20Sopenharmony_ci /* if device isn't clear to send it shouldn't be reading either */ 77758c2ecf20Sopenharmony_ci if (!(vf_data->flags & IGB_VF_FLAG_CTS) && 77768c2ecf20Sopenharmony_ci time_after(jiffies, vf_data->last_nack + (2 * HZ))) { 77778c2ecf20Sopenharmony_ci igb_write_mbx(hw, &msg, 1, vf); 77788c2ecf20Sopenharmony_ci vf_data->last_nack = jiffies; 77798c2ecf20Sopenharmony_ci } 77808c2ecf20Sopenharmony_ci} 77818c2ecf20Sopenharmony_ci 77828c2ecf20Sopenharmony_cistatic void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) 77838c2ecf20Sopenharmony_ci{ 77848c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 77858c2ecf20Sopenharmony_ci u32 msgbuf[E1000_VFMAILBOX_SIZE]; 77868c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 77878c2ecf20Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 77888c2ecf20Sopenharmony_ci s32 retval; 77898c2ecf20Sopenharmony_ci 77908c2ecf20Sopenharmony_ci retval = igb_read_mbx(hw, msgbuf, E1000_VFMAILBOX_SIZE, vf, false); 77918c2ecf20Sopenharmony_ci 77928c2ecf20Sopenharmony_ci if (retval) { 77938c2ecf20Sopenharmony_ci /* if receive failed revoke VF CTS stats and restart init */ 77948c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Error receiving message from VF\n"); 77958c2ecf20Sopenharmony_ci vf_data->flags &= ~IGB_VF_FLAG_CTS; 77968c2ecf20Sopenharmony_ci if (!time_after(jiffies, vf_data->last_nack + (2 * HZ))) 77978c2ecf20Sopenharmony_ci goto unlock; 77988c2ecf20Sopenharmony_ci goto out; 77998c2ecf20Sopenharmony_ci } 78008c2ecf20Sopenharmony_ci 78018c2ecf20Sopenharmony_ci /* this is a message we already processed, do nothing */ 78028c2ecf20Sopenharmony_ci if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK)) 78038c2ecf20Sopenharmony_ci goto unlock; 78048c2ecf20Sopenharmony_ci 78058c2ecf20Sopenharmony_ci /* until the vf completes a reset it should not be 78068c2ecf20Sopenharmony_ci * allowed to start any configuration. 78078c2ecf20Sopenharmony_ci */ 78088c2ecf20Sopenharmony_ci if (msgbuf[0] == E1000_VF_RESET) { 78098c2ecf20Sopenharmony_ci /* unlocks mailbox */ 78108c2ecf20Sopenharmony_ci igb_vf_reset_msg(adapter, vf); 78118c2ecf20Sopenharmony_ci return; 78128c2ecf20Sopenharmony_ci } 78138c2ecf20Sopenharmony_ci 78148c2ecf20Sopenharmony_ci if (!(vf_data->flags & IGB_VF_FLAG_CTS)) { 78158c2ecf20Sopenharmony_ci if (!time_after(jiffies, vf_data->last_nack + (2 * HZ))) 78168c2ecf20Sopenharmony_ci goto unlock; 78178c2ecf20Sopenharmony_ci retval = -1; 78188c2ecf20Sopenharmony_ci goto out; 78198c2ecf20Sopenharmony_ci } 78208c2ecf20Sopenharmony_ci 78218c2ecf20Sopenharmony_ci switch ((msgbuf[0] & 0xFFFF)) { 78228c2ecf20Sopenharmony_ci case E1000_VF_SET_MAC_ADDR: 78238c2ecf20Sopenharmony_ci retval = igb_set_vf_mac_addr(adapter, msgbuf, vf); 78248c2ecf20Sopenharmony_ci break; 78258c2ecf20Sopenharmony_ci case E1000_VF_SET_PROMISC: 78268c2ecf20Sopenharmony_ci retval = igb_set_vf_promisc(adapter, msgbuf, vf); 78278c2ecf20Sopenharmony_ci break; 78288c2ecf20Sopenharmony_ci case E1000_VF_SET_MULTICAST: 78298c2ecf20Sopenharmony_ci retval = igb_set_vf_multicasts(adapter, msgbuf, vf); 78308c2ecf20Sopenharmony_ci break; 78318c2ecf20Sopenharmony_ci case E1000_VF_SET_LPE: 78328c2ecf20Sopenharmony_ci retval = igb_set_vf_rlpml(adapter, msgbuf[1], vf); 78338c2ecf20Sopenharmony_ci break; 78348c2ecf20Sopenharmony_ci case E1000_VF_SET_VLAN: 78358c2ecf20Sopenharmony_ci retval = -1; 78368c2ecf20Sopenharmony_ci if (vf_data->pf_vlan) 78378c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, 78388c2ecf20Sopenharmony_ci "VF %d attempted to override administratively set VLAN tag\nReload the VF driver to resume operations\n", 78398c2ecf20Sopenharmony_ci vf); 78408c2ecf20Sopenharmony_ci else 78418c2ecf20Sopenharmony_ci retval = igb_set_vf_vlan_msg(adapter, msgbuf, vf); 78428c2ecf20Sopenharmony_ci break; 78438c2ecf20Sopenharmony_ci default: 78448c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unhandled Msg %08x\n", msgbuf[0]); 78458c2ecf20Sopenharmony_ci retval = -1; 78468c2ecf20Sopenharmony_ci break; 78478c2ecf20Sopenharmony_ci } 78488c2ecf20Sopenharmony_ci 78498c2ecf20Sopenharmony_ci msgbuf[0] |= E1000_VT_MSGTYPE_CTS; 78508c2ecf20Sopenharmony_ciout: 78518c2ecf20Sopenharmony_ci /* notify the VF of the results of what it sent us */ 78528c2ecf20Sopenharmony_ci if (retval) 78538c2ecf20Sopenharmony_ci msgbuf[0] |= E1000_VT_MSGTYPE_NACK; 78548c2ecf20Sopenharmony_ci else 78558c2ecf20Sopenharmony_ci msgbuf[0] |= E1000_VT_MSGTYPE_ACK; 78568c2ecf20Sopenharmony_ci 78578c2ecf20Sopenharmony_ci /* unlocks mailbox */ 78588c2ecf20Sopenharmony_ci igb_write_mbx(hw, msgbuf, 1, vf); 78598c2ecf20Sopenharmony_ci return; 78608c2ecf20Sopenharmony_ci 78618c2ecf20Sopenharmony_ciunlock: 78628c2ecf20Sopenharmony_ci igb_unlock_mbx(hw, vf); 78638c2ecf20Sopenharmony_ci} 78648c2ecf20Sopenharmony_ci 78658c2ecf20Sopenharmony_cistatic void igb_msg_task(struct igb_adapter *adapter) 78668c2ecf20Sopenharmony_ci{ 78678c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 78688c2ecf20Sopenharmony_ci unsigned long flags; 78698c2ecf20Sopenharmony_ci u32 vf; 78708c2ecf20Sopenharmony_ci 78718c2ecf20Sopenharmony_ci spin_lock_irqsave(&adapter->vfs_lock, flags); 78728c2ecf20Sopenharmony_ci for (vf = 0; vf < adapter->vfs_allocated_count; vf++) { 78738c2ecf20Sopenharmony_ci /* process any reset requests */ 78748c2ecf20Sopenharmony_ci if (!igb_check_for_rst(hw, vf)) 78758c2ecf20Sopenharmony_ci igb_vf_reset_event(adapter, vf); 78768c2ecf20Sopenharmony_ci 78778c2ecf20Sopenharmony_ci /* process any messages pending */ 78788c2ecf20Sopenharmony_ci if (!igb_check_for_msg(hw, vf)) 78798c2ecf20Sopenharmony_ci igb_rcv_msg_from_vf(adapter, vf); 78808c2ecf20Sopenharmony_ci 78818c2ecf20Sopenharmony_ci /* process any acks */ 78828c2ecf20Sopenharmony_ci if (!igb_check_for_ack(hw, vf)) 78838c2ecf20Sopenharmony_ci igb_rcv_ack_from_vf(adapter, vf); 78848c2ecf20Sopenharmony_ci } 78858c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&adapter->vfs_lock, flags); 78868c2ecf20Sopenharmony_ci} 78878c2ecf20Sopenharmony_ci 78888c2ecf20Sopenharmony_ci/** 78898c2ecf20Sopenharmony_ci * igb_set_uta - Set unicast filter table address 78908c2ecf20Sopenharmony_ci * @adapter: board private structure 78918c2ecf20Sopenharmony_ci * @set: boolean indicating if we are setting or clearing bits 78928c2ecf20Sopenharmony_ci * 78938c2ecf20Sopenharmony_ci * The unicast table address is a register array of 32-bit registers. 78948c2ecf20Sopenharmony_ci * The table is meant to be used in a way similar to how the MTA is used 78958c2ecf20Sopenharmony_ci * however due to certain limitations in the hardware it is necessary to 78968c2ecf20Sopenharmony_ci * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscuous 78978c2ecf20Sopenharmony_ci * enable bit to allow vlan tag stripping when promiscuous mode is enabled 78988c2ecf20Sopenharmony_ci **/ 78998c2ecf20Sopenharmony_cistatic void igb_set_uta(struct igb_adapter *adapter, bool set) 79008c2ecf20Sopenharmony_ci{ 79018c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 79028c2ecf20Sopenharmony_ci u32 uta = set ? ~0 : 0; 79038c2ecf20Sopenharmony_ci int i; 79048c2ecf20Sopenharmony_ci 79058c2ecf20Sopenharmony_ci /* we only need to do this if VMDq is enabled */ 79068c2ecf20Sopenharmony_ci if (!adapter->vfs_allocated_count) 79078c2ecf20Sopenharmony_ci return; 79088c2ecf20Sopenharmony_ci 79098c2ecf20Sopenharmony_ci for (i = hw->mac.uta_reg_count; i--;) 79108c2ecf20Sopenharmony_ci array_wr32(E1000_UTA, i, uta); 79118c2ecf20Sopenharmony_ci} 79128c2ecf20Sopenharmony_ci 79138c2ecf20Sopenharmony_ci/** 79148c2ecf20Sopenharmony_ci * igb_intr_msi - Interrupt Handler 79158c2ecf20Sopenharmony_ci * @irq: interrupt number 79168c2ecf20Sopenharmony_ci * @data: pointer to a network interface device structure 79178c2ecf20Sopenharmony_ci **/ 79188c2ecf20Sopenharmony_cistatic irqreturn_t igb_intr_msi(int irq, void *data) 79198c2ecf20Sopenharmony_ci{ 79208c2ecf20Sopenharmony_ci struct igb_adapter *adapter = data; 79218c2ecf20Sopenharmony_ci struct igb_q_vector *q_vector = adapter->q_vector[0]; 79228c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 79238c2ecf20Sopenharmony_ci /* read ICR disables interrupts using IAM */ 79248c2ecf20Sopenharmony_ci u32 icr = rd32(E1000_ICR); 79258c2ecf20Sopenharmony_ci 79268c2ecf20Sopenharmony_ci igb_write_itr(q_vector); 79278c2ecf20Sopenharmony_ci 79288c2ecf20Sopenharmony_ci if (icr & E1000_ICR_DRSTA) 79298c2ecf20Sopenharmony_ci schedule_work(&adapter->reset_task); 79308c2ecf20Sopenharmony_ci 79318c2ecf20Sopenharmony_ci if (icr & E1000_ICR_DOUTSYNC) { 79328c2ecf20Sopenharmony_ci /* HW is reporting DMA is out of sync */ 79338c2ecf20Sopenharmony_ci adapter->stats.doosync++; 79348c2ecf20Sopenharmony_ci } 79358c2ecf20Sopenharmony_ci 79368c2ecf20Sopenharmony_ci if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 79378c2ecf20Sopenharmony_ci hw->mac.get_link_status = 1; 79388c2ecf20Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) 79398c2ecf20Sopenharmony_ci mod_timer(&adapter->watchdog_timer, jiffies + 1); 79408c2ecf20Sopenharmony_ci } 79418c2ecf20Sopenharmony_ci 79428c2ecf20Sopenharmony_ci if (icr & E1000_ICR_TS) 79438c2ecf20Sopenharmony_ci igb_tsync_interrupt(adapter); 79448c2ecf20Sopenharmony_ci 79458c2ecf20Sopenharmony_ci napi_schedule(&q_vector->napi); 79468c2ecf20Sopenharmony_ci 79478c2ecf20Sopenharmony_ci return IRQ_HANDLED; 79488c2ecf20Sopenharmony_ci} 79498c2ecf20Sopenharmony_ci 79508c2ecf20Sopenharmony_ci/** 79518c2ecf20Sopenharmony_ci * igb_intr - Legacy Interrupt Handler 79528c2ecf20Sopenharmony_ci * @irq: interrupt number 79538c2ecf20Sopenharmony_ci * @data: pointer to a network interface device structure 79548c2ecf20Sopenharmony_ci **/ 79558c2ecf20Sopenharmony_cistatic irqreturn_t igb_intr(int irq, void *data) 79568c2ecf20Sopenharmony_ci{ 79578c2ecf20Sopenharmony_ci struct igb_adapter *adapter = data; 79588c2ecf20Sopenharmony_ci struct igb_q_vector *q_vector = adapter->q_vector[0]; 79598c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 79608c2ecf20Sopenharmony_ci /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No 79618c2ecf20Sopenharmony_ci * need for the IMC write 79628c2ecf20Sopenharmony_ci */ 79638c2ecf20Sopenharmony_ci u32 icr = rd32(E1000_ICR); 79648c2ecf20Sopenharmony_ci 79658c2ecf20Sopenharmony_ci /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is 79668c2ecf20Sopenharmony_ci * not set, then the adapter didn't send an interrupt 79678c2ecf20Sopenharmony_ci */ 79688c2ecf20Sopenharmony_ci if (!(icr & E1000_ICR_INT_ASSERTED)) 79698c2ecf20Sopenharmony_ci return IRQ_NONE; 79708c2ecf20Sopenharmony_ci 79718c2ecf20Sopenharmony_ci igb_write_itr(q_vector); 79728c2ecf20Sopenharmony_ci 79738c2ecf20Sopenharmony_ci if (icr & E1000_ICR_DRSTA) 79748c2ecf20Sopenharmony_ci schedule_work(&adapter->reset_task); 79758c2ecf20Sopenharmony_ci 79768c2ecf20Sopenharmony_ci if (icr & E1000_ICR_DOUTSYNC) { 79778c2ecf20Sopenharmony_ci /* HW is reporting DMA is out of sync */ 79788c2ecf20Sopenharmony_ci adapter->stats.doosync++; 79798c2ecf20Sopenharmony_ci } 79808c2ecf20Sopenharmony_ci 79818c2ecf20Sopenharmony_ci if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 79828c2ecf20Sopenharmony_ci hw->mac.get_link_status = 1; 79838c2ecf20Sopenharmony_ci /* guard against interrupt when we're going down */ 79848c2ecf20Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) 79858c2ecf20Sopenharmony_ci mod_timer(&adapter->watchdog_timer, jiffies + 1); 79868c2ecf20Sopenharmony_ci } 79878c2ecf20Sopenharmony_ci 79888c2ecf20Sopenharmony_ci if (icr & E1000_ICR_TS) 79898c2ecf20Sopenharmony_ci igb_tsync_interrupt(adapter); 79908c2ecf20Sopenharmony_ci 79918c2ecf20Sopenharmony_ci napi_schedule(&q_vector->napi); 79928c2ecf20Sopenharmony_ci 79938c2ecf20Sopenharmony_ci return IRQ_HANDLED; 79948c2ecf20Sopenharmony_ci} 79958c2ecf20Sopenharmony_ci 79968c2ecf20Sopenharmony_cistatic void igb_ring_irq_enable(struct igb_q_vector *q_vector) 79978c2ecf20Sopenharmony_ci{ 79988c2ecf20Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 79998c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 80008c2ecf20Sopenharmony_ci 80018c2ecf20Sopenharmony_ci if ((q_vector->rx.ring && (adapter->rx_itr_setting & 3)) || 80028c2ecf20Sopenharmony_ci (!q_vector->rx.ring && (adapter->tx_itr_setting & 3))) { 80038c2ecf20Sopenharmony_ci if ((adapter->num_q_vectors == 1) && !adapter->vf_data) 80048c2ecf20Sopenharmony_ci igb_set_itr(q_vector); 80058c2ecf20Sopenharmony_ci else 80068c2ecf20Sopenharmony_ci igb_update_ring_itr(q_vector); 80078c2ecf20Sopenharmony_ci } 80088c2ecf20Sopenharmony_ci 80098c2ecf20Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) { 80108c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) 80118c2ecf20Sopenharmony_ci wr32(E1000_EIMS, q_vector->eims_value); 80128c2ecf20Sopenharmony_ci else 80138c2ecf20Sopenharmony_ci igb_irq_enable(adapter); 80148c2ecf20Sopenharmony_ci } 80158c2ecf20Sopenharmony_ci} 80168c2ecf20Sopenharmony_ci 80178c2ecf20Sopenharmony_ci/** 80188c2ecf20Sopenharmony_ci * igb_poll - NAPI Rx polling callback 80198c2ecf20Sopenharmony_ci * @napi: napi polling structure 80208c2ecf20Sopenharmony_ci * @budget: count of how many packets we should handle 80218c2ecf20Sopenharmony_ci **/ 80228c2ecf20Sopenharmony_cistatic int igb_poll(struct napi_struct *napi, int budget) 80238c2ecf20Sopenharmony_ci{ 80248c2ecf20Sopenharmony_ci struct igb_q_vector *q_vector = container_of(napi, 80258c2ecf20Sopenharmony_ci struct igb_q_vector, 80268c2ecf20Sopenharmony_ci napi); 80278c2ecf20Sopenharmony_ci bool clean_complete = true; 80288c2ecf20Sopenharmony_ci int work_done = 0; 80298c2ecf20Sopenharmony_ci 80308c2ecf20Sopenharmony_ci#ifdef CONFIG_IGB_DCA 80318c2ecf20Sopenharmony_ci if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED) 80328c2ecf20Sopenharmony_ci igb_update_dca(q_vector); 80338c2ecf20Sopenharmony_ci#endif 80348c2ecf20Sopenharmony_ci if (q_vector->tx.ring) 80358c2ecf20Sopenharmony_ci clean_complete = igb_clean_tx_irq(q_vector, budget); 80368c2ecf20Sopenharmony_ci 80378c2ecf20Sopenharmony_ci if (q_vector->rx.ring) { 80388c2ecf20Sopenharmony_ci int cleaned = igb_clean_rx_irq(q_vector, budget); 80398c2ecf20Sopenharmony_ci 80408c2ecf20Sopenharmony_ci work_done += cleaned; 80418c2ecf20Sopenharmony_ci if (cleaned >= budget) 80428c2ecf20Sopenharmony_ci clean_complete = false; 80438c2ecf20Sopenharmony_ci } 80448c2ecf20Sopenharmony_ci 80458c2ecf20Sopenharmony_ci /* If all work not completed, return budget and keep polling */ 80468c2ecf20Sopenharmony_ci if (!clean_complete) 80478c2ecf20Sopenharmony_ci return budget; 80488c2ecf20Sopenharmony_ci 80498c2ecf20Sopenharmony_ci /* Exit the polling mode, but don't re-enable interrupts if stack might 80508c2ecf20Sopenharmony_ci * poll us due to busy-polling 80518c2ecf20Sopenharmony_ci */ 80528c2ecf20Sopenharmony_ci if (likely(napi_complete_done(napi, work_done))) 80538c2ecf20Sopenharmony_ci igb_ring_irq_enable(q_vector); 80548c2ecf20Sopenharmony_ci 80558c2ecf20Sopenharmony_ci return work_done; 80568c2ecf20Sopenharmony_ci} 80578c2ecf20Sopenharmony_ci 80588c2ecf20Sopenharmony_ci/** 80598c2ecf20Sopenharmony_ci * igb_clean_tx_irq - Reclaim resources after transmit completes 80608c2ecf20Sopenharmony_ci * @q_vector: pointer to q_vector containing needed info 80618c2ecf20Sopenharmony_ci * @napi_budget: Used to determine if we are in netpoll 80628c2ecf20Sopenharmony_ci * 80638c2ecf20Sopenharmony_ci * returns true if ring is completely cleaned 80648c2ecf20Sopenharmony_ci **/ 80658c2ecf20Sopenharmony_cistatic bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget) 80668c2ecf20Sopenharmony_ci{ 80678c2ecf20Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 80688c2ecf20Sopenharmony_ci struct igb_ring *tx_ring = q_vector->tx.ring; 80698c2ecf20Sopenharmony_ci struct igb_tx_buffer *tx_buffer; 80708c2ecf20Sopenharmony_ci union e1000_adv_tx_desc *tx_desc; 80718c2ecf20Sopenharmony_ci unsigned int total_bytes = 0, total_packets = 0; 80728c2ecf20Sopenharmony_ci unsigned int budget = q_vector->tx.work_limit; 80738c2ecf20Sopenharmony_ci unsigned int i = tx_ring->next_to_clean; 80748c2ecf20Sopenharmony_ci 80758c2ecf20Sopenharmony_ci if (test_bit(__IGB_DOWN, &adapter->state)) 80768c2ecf20Sopenharmony_ci return true; 80778c2ecf20Sopenharmony_ci 80788c2ecf20Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[i]; 80798c2ecf20Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, i); 80808c2ecf20Sopenharmony_ci i -= tx_ring->count; 80818c2ecf20Sopenharmony_ci 80828c2ecf20Sopenharmony_ci do { 80838c2ecf20Sopenharmony_ci union e1000_adv_tx_desc *eop_desc = tx_buffer->next_to_watch; 80848c2ecf20Sopenharmony_ci 80858c2ecf20Sopenharmony_ci /* if next_to_watch is not set then there is no work pending */ 80868c2ecf20Sopenharmony_ci if (!eop_desc) 80878c2ecf20Sopenharmony_ci break; 80888c2ecf20Sopenharmony_ci 80898c2ecf20Sopenharmony_ci /* prevent any other reads prior to eop_desc */ 80908c2ecf20Sopenharmony_ci smp_rmb(); 80918c2ecf20Sopenharmony_ci 80928c2ecf20Sopenharmony_ci /* if DD is not set pending work has not been completed */ 80938c2ecf20Sopenharmony_ci if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) 80948c2ecf20Sopenharmony_ci break; 80958c2ecf20Sopenharmony_ci 80968c2ecf20Sopenharmony_ci /* clear next_to_watch to prevent false hangs */ 80978c2ecf20Sopenharmony_ci tx_buffer->next_to_watch = NULL; 80988c2ecf20Sopenharmony_ci 80998c2ecf20Sopenharmony_ci /* update the statistics for this packet */ 81008c2ecf20Sopenharmony_ci total_bytes += tx_buffer->bytecount; 81018c2ecf20Sopenharmony_ci total_packets += tx_buffer->gso_segs; 81028c2ecf20Sopenharmony_ci 81038c2ecf20Sopenharmony_ci /* free the skb */ 81048c2ecf20Sopenharmony_ci if (tx_buffer->type == IGB_TYPE_SKB) 81058c2ecf20Sopenharmony_ci napi_consume_skb(tx_buffer->skb, napi_budget); 81068c2ecf20Sopenharmony_ci else 81078c2ecf20Sopenharmony_ci xdp_return_frame(tx_buffer->xdpf); 81088c2ecf20Sopenharmony_ci 81098c2ecf20Sopenharmony_ci /* unmap skb header data */ 81108c2ecf20Sopenharmony_ci dma_unmap_single(tx_ring->dev, 81118c2ecf20Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 81128c2ecf20Sopenharmony_ci dma_unmap_len(tx_buffer, len), 81138c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 81148c2ecf20Sopenharmony_ci 81158c2ecf20Sopenharmony_ci /* clear tx_buffer data */ 81168c2ecf20Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 81178c2ecf20Sopenharmony_ci 81188c2ecf20Sopenharmony_ci /* clear last DMA location and unmap remaining buffers */ 81198c2ecf20Sopenharmony_ci while (tx_desc != eop_desc) { 81208c2ecf20Sopenharmony_ci tx_buffer++; 81218c2ecf20Sopenharmony_ci tx_desc++; 81228c2ecf20Sopenharmony_ci i++; 81238c2ecf20Sopenharmony_ci if (unlikely(!i)) { 81248c2ecf20Sopenharmony_ci i -= tx_ring->count; 81258c2ecf20Sopenharmony_ci tx_buffer = tx_ring->tx_buffer_info; 81268c2ecf20Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, 0); 81278c2ecf20Sopenharmony_ci } 81288c2ecf20Sopenharmony_ci 81298c2ecf20Sopenharmony_ci /* unmap any remaining paged data */ 81308c2ecf20Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) { 81318c2ecf20Sopenharmony_ci dma_unmap_page(tx_ring->dev, 81328c2ecf20Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 81338c2ecf20Sopenharmony_ci dma_unmap_len(tx_buffer, len), 81348c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 81358c2ecf20Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 81368c2ecf20Sopenharmony_ci } 81378c2ecf20Sopenharmony_ci } 81388c2ecf20Sopenharmony_ci 81398c2ecf20Sopenharmony_ci /* move us one more past the eop_desc for start of next pkt */ 81408c2ecf20Sopenharmony_ci tx_buffer++; 81418c2ecf20Sopenharmony_ci tx_desc++; 81428c2ecf20Sopenharmony_ci i++; 81438c2ecf20Sopenharmony_ci if (unlikely(!i)) { 81448c2ecf20Sopenharmony_ci i -= tx_ring->count; 81458c2ecf20Sopenharmony_ci tx_buffer = tx_ring->tx_buffer_info; 81468c2ecf20Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, 0); 81478c2ecf20Sopenharmony_ci } 81488c2ecf20Sopenharmony_ci 81498c2ecf20Sopenharmony_ci /* issue prefetch for next Tx descriptor */ 81508c2ecf20Sopenharmony_ci prefetch(tx_desc); 81518c2ecf20Sopenharmony_ci 81528c2ecf20Sopenharmony_ci /* update budget accounting */ 81538c2ecf20Sopenharmony_ci budget--; 81548c2ecf20Sopenharmony_ci } while (likely(budget)); 81558c2ecf20Sopenharmony_ci 81568c2ecf20Sopenharmony_ci netdev_tx_completed_queue(txring_txq(tx_ring), 81578c2ecf20Sopenharmony_ci total_packets, total_bytes); 81588c2ecf20Sopenharmony_ci i += tx_ring->count; 81598c2ecf20Sopenharmony_ci tx_ring->next_to_clean = i; 81608c2ecf20Sopenharmony_ci u64_stats_update_begin(&tx_ring->tx_syncp); 81618c2ecf20Sopenharmony_ci tx_ring->tx_stats.bytes += total_bytes; 81628c2ecf20Sopenharmony_ci tx_ring->tx_stats.packets += total_packets; 81638c2ecf20Sopenharmony_ci u64_stats_update_end(&tx_ring->tx_syncp); 81648c2ecf20Sopenharmony_ci q_vector->tx.total_bytes += total_bytes; 81658c2ecf20Sopenharmony_ci q_vector->tx.total_packets += total_packets; 81668c2ecf20Sopenharmony_ci 81678c2ecf20Sopenharmony_ci if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { 81688c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 81698c2ecf20Sopenharmony_ci 81708c2ecf20Sopenharmony_ci /* Detect a transmit hang in hardware, this serializes the 81718c2ecf20Sopenharmony_ci * check with the clearing of time_stamp and movement of i 81728c2ecf20Sopenharmony_ci */ 81738c2ecf20Sopenharmony_ci clear_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); 81748c2ecf20Sopenharmony_ci if (tx_buffer->next_to_watch && 81758c2ecf20Sopenharmony_ci time_after(jiffies, tx_buffer->time_stamp + 81768c2ecf20Sopenharmony_ci (adapter->tx_timeout_factor * HZ)) && 81778c2ecf20Sopenharmony_ci !(rd32(E1000_STATUS) & E1000_STATUS_TXOFF)) { 81788c2ecf20Sopenharmony_ci 81798c2ecf20Sopenharmony_ci /* detected Tx unit hang */ 81808c2ecf20Sopenharmony_ci dev_err(tx_ring->dev, 81818c2ecf20Sopenharmony_ci "Detected Tx Unit Hang\n" 81828c2ecf20Sopenharmony_ci " Tx Queue <%d>\n" 81838c2ecf20Sopenharmony_ci " TDH <%x>\n" 81848c2ecf20Sopenharmony_ci " TDT <%x>\n" 81858c2ecf20Sopenharmony_ci " next_to_use <%x>\n" 81868c2ecf20Sopenharmony_ci " next_to_clean <%x>\n" 81878c2ecf20Sopenharmony_ci "buffer_info[next_to_clean]\n" 81888c2ecf20Sopenharmony_ci " time_stamp <%lx>\n" 81898c2ecf20Sopenharmony_ci " next_to_watch <%p>\n" 81908c2ecf20Sopenharmony_ci " jiffies <%lx>\n" 81918c2ecf20Sopenharmony_ci " desc.status <%x>\n", 81928c2ecf20Sopenharmony_ci tx_ring->queue_index, 81938c2ecf20Sopenharmony_ci rd32(E1000_TDH(tx_ring->reg_idx)), 81948c2ecf20Sopenharmony_ci readl(tx_ring->tail), 81958c2ecf20Sopenharmony_ci tx_ring->next_to_use, 81968c2ecf20Sopenharmony_ci tx_ring->next_to_clean, 81978c2ecf20Sopenharmony_ci tx_buffer->time_stamp, 81988c2ecf20Sopenharmony_ci tx_buffer->next_to_watch, 81998c2ecf20Sopenharmony_ci jiffies, 82008c2ecf20Sopenharmony_ci tx_buffer->next_to_watch->wb.status); 82018c2ecf20Sopenharmony_ci netif_stop_subqueue(tx_ring->netdev, 82028c2ecf20Sopenharmony_ci tx_ring->queue_index); 82038c2ecf20Sopenharmony_ci 82048c2ecf20Sopenharmony_ci /* we are about to reset, no point in enabling stuff */ 82058c2ecf20Sopenharmony_ci return true; 82068c2ecf20Sopenharmony_ci } 82078c2ecf20Sopenharmony_ci } 82088c2ecf20Sopenharmony_ci 82098c2ecf20Sopenharmony_ci#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) 82108c2ecf20Sopenharmony_ci if (unlikely(total_packets && 82118c2ecf20Sopenharmony_ci netif_carrier_ok(tx_ring->netdev) && 82128c2ecf20Sopenharmony_ci igb_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) { 82138c2ecf20Sopenharmony_ci /* Make sure that anybody stopping the queue after this 82148c2ecf20Sopenharmony_ci * sees the new next_to_clean. 82158c2ecf20Sopenharmony_ci */ 82168c2ecf20Sopenharmony_ci smp_mb(); 82178c2ecf20Sopenharmony_ci if (__netif_subqueue_stopped(tx_ring->netdev, 82188c2ecf20Sopenharmony_ci tx_ring->queue_index) && 82198c2ecf20Sopenharmony_ci !(test_bit(__IGB_DOWN, &adapter->state))) { 82208c2ecf20Sopenharmony_ci netif_wake_subqueue(tx_ring->netdev, 82218c2ecf20Sopenharmony_ci tx_ring->queue_index); 82228c2ecf20Sopenharmony_ci 82238c2ecf20Sopenharmony_ci u64_stats_update_begin(&tx_ring->tx_syncp); 82248c2ecf20Sopenharmony_ci tx_ring->tx_stats.restart_queue++; 82258c2ecf20Sopenharmony_ci u64_stats_update_end(&tx_ring->tx_syncp); 82268c2ecf20Sopenharmony_ci } 82278c2ecf20Sopenharmony_ci } 82288c2ecf20Sopenharmony_ci 82298c2ecf20Sopenharmony_ci return !!budget; 82308c2ecf20Sopenharmony_ci} 82318c2ecf20Sopenharmony_ci 82328c2ecf20Sopenharmony_ci/** 82338c2ecf20Sopenharmony_ci * igb_reuse_rx_page - page flip buffer and store it back on the ring 82348c2ecf20Sopenharmony_ci * @rx_ring: rx descriptor ring to store buffers on 82358c2ecf20Sopenharmony_ci * @old_buff: donor buffer to have page reused 82368c2ecf20Sopenharmony_ci * 82378c2ecf20Sopenharmony_ci * Synchronizes page for reuse by the adapter 82388c2ecf20Sopenharmony_ci **/ 82398c2ecf20Sopenharmony_cistatic void igb_reuse_rx_page(struct igb_ring *rx_ring, 82408c2ecf20Sopenharmony_ci struct igb_rx_buffer *old_buff) 82418c2ecf20Sopenharmony_ci{ 82428c2ecf20Sopenharmony_ci struct igb_rx_buffer *new_buff; 82438c2ecf20Sopenharmony_ci u16 nta = rx_ring->next_to_alloc; 82448c2ecf20Sopenharmony_ci 82458c2ecf20Sopenharmony_ci new_buff = &rx_ring->rx_buffer_info[nta]; 82468c2ecf20Sopenharmony_ci 82478c2ecf20Sopenharmony_ci /* update, and store next to alloc */ 82488c2ecf20Sopenharmony_ci nta++; 82498c2ecf20Sopenharmony_ci rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0; 82508c2ecf20Sopenharmony_ci 82518c2ecf20Sopenharmony_ci /* Transfer page from old buffer to new buffer. 82528c2ecf20Sopenharmony_ci * Move each member individually to avoid possible store 82538c2ecf20Sopenharmony_ci * forwarding stalls. 82548c2ecf20Sopenharmony_ci */ 82558c2ecf20Sopenharmony_ci new_buff->dma = old_buff->dma; 82568c2ecf20Sopenharmony_ci new_buff->page = old_buff->page; 82578c2ecf20Sopenharmony_ci new_buff->page_offset = old_buff->page_offset; 82588c2ecf20Sopenharmony_ci new_buff->pagecnt_bias = old_buff->pagecnt_bias; 82598c2ecf20Sopenharmony_ci} 82608c2ecf20Sopenharmony_ci 82618c2ecf20Sopenharmony_cistatic inline bool igb_page_is_reserved(struct page *page) 82628c2ecf20Sopenharmony_ci{ 82638c2ecf20Sopenharmony_ci return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page); 82648c2ecf20Sopenharmony_ci} 82658c2ecf20Sopenharmony_ci 82668c2ecf20Sopenharmony_cistatic bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer, 82678c2ecf20Sopenharmony_ci int rx_buf_pgcnt) 82688c2ecf20Sopenharmony_ci{ 82698c2ecf20Sopenharmony_ci unsigned int pagecnt_bias = rx_buffer->pagecnt_bias; 82708c2ecf20Sopenharmony_ci struct page *page = rx_buffer->page; 82718c2ecf20Sopenharmony_ci 82728c2ecf20Sopenharmony_ci /* avoid re-using remote pages */ 82738c2ecf20Sopenharmony_ci if (unlikely(igb_page_is_reserved(page))) 82748c2ecf20Sopenharmony_ci return false; 82758c2ecf20Sopenharmony_ci 82768c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 82778c2ecf20Sopenharmony_ci /* if we are only owner of page we can reuse it */ 82788c2ecf20Sopenharmony_ci if (unlikely((rx_buf_pgcnt - pagecnt_bias) > 1)) 82798c2ecf20Sopenharmony_ci return false; 82808c2ecf20Sopenharmony_ci#else 82818c2ecf20Sopenharmony_ci#define IGB_LAST_OFFSET \ 82828c2ecf20Sopenharmony_ci (SKB_WITH_OVERHEAD(PAGE_SIZE) - IGB_RXBUFFER_2048) 82838c2ecf20Sopenharmony_ci 82848c2ecf20Sopenharmony_ci if (rx_buffer->page_offset > IGB_LAST_OFFSET) 82858c2ecf20Sopenharmony_ci return false; 82868c2ecf20Sopenharmony_ci#endif 82878c2ecf20Sopenharmony_ci 82888c2ecf20Sopenharmony_ci /* If we have drained the page fragment pool we need to update 82898c2ecf20Sopenharmony_ci * the pagecnt_bias and page count so that we fully restock the 82908c2ecf20Sopenharmony_ci * number of references the driver holds. 82918c2ecf20Sopenharmony_ci */ 82928c2ecf20Sopenharmony_ci if (unlikely(pagecnt_bias == 1)) { 82938c2ecf20Sopenharmony_ci page_ref_add(page, USHRT_MAX - 1); 82948c2ecf20Sopenharmony_ci rx_buffer->pagecnt_bias = USHRT_MAX; 82958c2ecf20Sopenharmony_ci } 82968c2ecf20Sopenharmony_ci 82978c2ecf20Sopenharmony_ci return true; 82988c2ecf20Sopenharmony_ci} 82998c2ecf20Sopenharmony_ci 83008c2ecf20Sopenharmony_ci/** 83018c2ecf20Sopenharmony_ci * igb_add_rx_frag - Add contents of Rx buffer to sk_buff 83028c2ecf20Sopenharmony_ci * @rx_ring: rx descriptor ring to transact packets on 83038c2ecf20Sopenharmony_ci * @rx_buffer: buffer containing page to add 83048c2ecf20Sopenharmony_ci * @skb: sk_buff to place the data into 83058c2ecf20Sopenharmony_ci * @size: size of buffer to be added 83068c2ecf20Sopenharmony_ci * 83078c2ecf20Sopenharmony_ci * This function will add the data contained in rx_buffer->page to the skb. 83088c2ecf20Sopenharmony_ci **/ 83098c2ecf20Sopenharmony_cistatic void igb_add_rx_frag(struct igb_ring *rx_ring, 83108c2ecf20Sopenharmony_ci struct igb_rx_buffer *rx_buffer, 83118c2ecf20Sopenharmony_ci struct sk_buff *skb, 83128c2ecf20Sopenharmony_ci unsigned int size) 83138c2ecf20Sopenharmony_ci{ 83148c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 83158c2ecf20Sopenharmony_ci unsigned int truesize = igb_rx_pg_size(rx_ring) / 2; 83168c2ecf20Sopenharmony_ci#else 83178c2ecf20Sopenharmony_ci unsigned int truesize = ring_uses_build_skb(rx_ring) ? 83188c2ecf20Sopenharmony_ci SKB_DATA_ALIGN(IGB_SKB_PAD + size) : 83198c2ecf20Sopenharmony_ci SKB_DATA_ALIGN(size); 83208c2ecf20Sopenharmony_ci#endif 83218c2ecf20Sopenharmony_ci skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page, 83228c2ecf20Sopenharmony_ci rx_buffer->page_offset, size, truesize); 83238c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 83248c2ecf20Sopenharmony_ci rx_buffer->page_offset ^= truesize; 83258c2ecf20Sopenharmony_ci#else 83268c2ecf20Sopenharmony_ci rx_buffer->page_offset += truesize; 83278c2ecf20Sopenharmony_ci#endif 83288c2ecf20Sopenharmony_ci} 83298c2ecf20Sopenharmony_ci 83308c2ecf20Sopenharmony_cistatic struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring, 83318c2ecf20Sopenharmony_ci struct igb_rx_buffer *rx_buffer, 83328c2ecf20Sopenharmony_ci struct xdp_buff *xdp, 83338c2ecf20Sopenharmony_ci union e1000_adv_rx_desc *rx_desc) 83348c2ecf20Sopenharmony_ci{ 83358c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 83368c2ecf20Sopenharmony_ci unsigned int truesize = igb_rx_pg_size(rx_ring) / 2; 83378c2ecf20Sopenharmony_ci#else 83388c2ecf20Sopenharmony_ci unsigned int truesize = SKB_DATA_ALIGN(xdp->data_end - 83398c2ecf20Sopenharmony_ci xdp->data_hard_start); 83408c2ecf20Sopenharmony_ci#endif 83418c2ecf20Sopenharmony_ci unsigned int size = xdp->data_end - xdp->data; 83428c2ecf20Sopenharmony_ci unsigned int headlen; 83438c2ecf20Sopenharmony_ci struct sk_buff *skb; 83448c2ecf20Sopenharmony_ci 83458c2ecf20Sopenharmony_ci /* prefetch first cache line of first page */ 83468c2ecf20Sopenharmony_ci net_prefetch(xdp->data); 83478c2ecf20Sopenharmony_ci 83488c2ecf20Sopenharmony_ci /* allocate a skb to store the frags */ 83498c2ecf20Sopenharmony_ci skb = napi_alloc_skb(&rx_ring->q_vector->napi, IGB_RX_HDR_LEN); 83508c2ecf20Sopenharmony_ci if (unlikely(!skb)) 83518c2ecf20Sopenharmony_ci return NULL; 83528c2ecf20Sopenharmony_ci 83538c2ecf20Sopenharmony_ci if (unlikely(igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))) { 83548c2ecf20Sopenharmony_ci if (!igb_ptp_rx_pktstamp(rx_ring->q_vector, xdp->data, skb)) { 83558c2ecf20Sopenharmony_ci xdp->data += IGB_TS_HDR_LEN; 83568c2ecf20Sopenharmony_ci size -= IGB_TS_HDR_LEN; 83578c2ecf20Sopenharmony_ci } 83588c2ecf20Sopenharmony_ci } 83598c2ecf20Sopenharmony_ci 83608c2ecf20Sopenharmony_ci /* Determine available headroom for copy */ 83618c2ecf20Sopenharmony_ci headlen = size; 83628c2ecf20Sopenharmony_ci if (headlen > IGB_RX_HDR_LEN) 83638c2ecf20Sopenharmony_ci headlen = eth_get_headlen(skb->dev, xdp->data, IGB_RX_HDR_LEN); 83648c2ecf20Sopenharmony_ci 83658c2ecf20Sopenharmony_ci /* align pull length to size of long to optimize memcpy performance */ 83668c2ecf20Sopenharmony_ci memcpy(__skb_put(skb, headlen), xdp->data, ALIGN(headlen, sizeof(long))); 83678c2ecf20Sopenharmony_ci 83688c2ecf20Sopenharmony_ci /* update all of the pointers */ 83698c2ecf20Sopenharmony_ci size -= headlen; 83708c2ecf20Sopenharmony_ci if (size) { 83718c2ecf20Sopenharmony_ci skb_add_rx_frag(skb, 0, rx_buffer->page, 83728c2ecf20Sopenharmony_ci (xdp->data + headlen) - page_address(rx_buffer->page), 83738c2ecf20Sopenharmony_ci size, truesize); 83748c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 83758c2ecf20Sopenharmony_ci rx_buffer->page_offset ^= truesize; 83768c2ecf20Sopenharmony_ci#else 83778c2ecf20Sopenharmony_ci rx_buffer->page_offset += truesize; 83788c2ecf20Sopenharmony_ci#endif 83798c2ecf20Sopenharmony_ci } else { 83808c2ecf20Sopenharmony_ci rx_buffer->pagecnt_bias++; 83818c2ecf20Sopenharmony_ci } 83828c2ecf20Sopenharmony_ci 83838c2ecf20Sopenharmony_ci return skb; 83848c2ecf20Sopenharmony_ci} 83858c2ecf20Sopenharmony_ci 83868c2ecf20Sopenharmony_cistatic struct sk_buff *igb_build_skb(struct igb_ring *rx_ring, 83878c2ecf20Sopenharmony_ci struct igb_rx_buffer *rx_buffer, 83888c2ecf20Sopenharmony_ci struct xdp_buff *xdp, 83898c2ecf20Sopenharmony_ci union e1000_adv_rx_desc *rx_desc) 83908c2ecf20Sopenharmony_ci{ 83918c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 83928c2ecf20Sopenharmony_ci unsigned int truesize = igb_rx_pg_size(rx_ring) / 2; 83938c2ecf20Sopenharmony_ci#else 83948c2ecf20Sopenharmony_ci unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + 83958c2ecf20Sopenharmony_ci SKB_DATA_ALIGN(xdp->data_end - 83968c2ecf20Sopenharmony_ci xdp->data_hard_start); 83978c2ecf20Sopenharmony_ci#endif 83988c2ecf20Sopenharmony_ci unsigned int metasize = xdp->data - xdp->data_meta; 83998c2ecf20Sopenharmony_ci struct sk_buff *skb; 84008c2ecf20Sopenharmony_ci 84018c2ecf20Sopenharmony_ci /* prefetch first cache line of first page */ 84028c2ecf20Sopenharmony_ci net_prefetch(xdp->data_meta); 84038c2ecf20Sopenharmony_ci 84048c2ecf20Sopenharmony_ci /* build an skb around the page buffer */ 84058c2ecf20Sopenharmony_ci skb = build_skb(xdp->data_hard_start, truesize); 84068c2ecf20Sopenharmony_ci if (unlikely(!skb)) 84078c2ecf20Sopenharmony_ci return NULL; 84088c2ecf20Sopenharmony_ci 84098c2ecf20Sopenharmony_ci /* update pointers within the skb to store the data */ 84108c2ecf20Sopenharmony_ci skb_reserve(skb, xdp->data - xdp->data_hard_start); 84118c2ecf20Sopenharmony_ci __skb_put(skb, xdp->data_end - xdp->data); 84128c2ecf20Sopenharmony_ci 84138c2ecf20Sopenharmony_ci if (metasize) 84148c2ecf20Sopenharmony_ci skb_metadata_set(skb, metasize); 84158c2ecf20Sopenharmony_ci 84168c2ecf20Sopenharmony_ci /* pull timestamp out of packet data */ 84178c2ecf20Sopenharmony_ci if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { 84188c2ecf20Sopenharmony_ci if (!igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb)) 84198c2ecf20Sopenharmony_ci __skb_pull(skb, IGB_TS_HDR_LEN); 84208c2ecf20Sopenharmony_ci } 84218c2ecf20Sopenharmony_ci 84228c2ecf20Sopenharmony_ci /* update buffer offset */ 84238c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 84248c2ecf20Sopenharmony_ci rx_buffer->page_offset ^= truesize; 84258c2ecf20Sopenharmony_ci#else 84268c2ecf20Sopenharmony_ci rx_buffer->page_offset += truesize; 84278c2ecf20Sopenharmony_ci#endif 84288c2ecf20Sopenharmony_ci 84298c2ecf20Sopenharmony_ci return skb; 84308c2ecf20Sopenharmony_ci} 84318c2ecf20Sopenharmony_ci 84328c2ecf20Sopenharmony_cistatic struct sk_buff *igb_run_xdp(struct igb_adapter *adapter, 84338c2ecf20Sopenharmony_ci struct igb_ring *rx_ring, 84348c2ecf20Sopenharmony_ci struct xdp_buff *xdp) 84358c2ecf20Sopenharmony_ci{ 84368c2ecf20Sopenharmony_ci int err, result = IGB_XDP_PASS; 84378c2ecf20Sopenharmony_ci struct bpf_prog *xdp_prog; 84388c2ecf20Sopenharmony_ci u32 act; 84398c2ecf20Sopenharmony_ci 84408c2ecf20Sopenharmony_ci rcu_read_lock(); 84418c2ecf20Sopenharmony_ci xdp_prog = READ_ONCE(rx_ring->xdp_prog); 84428c2ecf20Sopenharmony_ci 84438c2ecf20Sopenharmony_ci if (!xdp_prog) 84448c2ecf20Sopenharmony_ci goto xdp_out; 84458c2ecf20Sopenharmony_ci 84468c2ecf20Sopenharmony_ci prefetchw(xdp->data_hard_start); /* xdp_frame write */ 84478c2ecf20Sopenharmony_ci 84488c2ecf20Sopenharmony_ci act = bpf_prog_run_xdp(xdp_prog, xdp); 84498c2ecf20Sopenharmony_ci switch (act) { 84508c2ecf20Sopenharmony_ci case XDP_PASS: 84518c2ecf20Sopenharmony_ci break; 84528c2ecf20Sopenharmony_ci case XDP_TX: 84538c2ecf20Sopenharmony_ci result = igb_xdp_xmit_back(adapter, xdp); 84548c2ecf20Sopenharmony_ci if (result == IGB_XDP_CONSUMED) 84558c2ecf20Sopenharmony_ci goto out_failure; 84568c2ecf20Sopenharmony_ci break; 84578c2ecf20Sopenharmony_ci case XDP_REDIRECT: 84588c2ecf20Sopenharmony_ci err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog); 84598c2ecf20Sopenharmony_ci if (err) 84608c2ecf20Sopenharmony_ci goto out_failure; 84618c2ecf20Sopenharmony_ci result = IGB_XDP_REDIR; 84628c2ecf20Sopenharmony_ci break; 84638c2ecf20Sopenharmony_ci default: 84648c2ecf20Sopenharmony_ci bpf_warn_invalid_xdp_action(act); 84658c2ecf20Sopenharmony_ci fallthrough; 84668c2ecf20Sopenharmony_ci case XDP_ABORTED: 84678c2ecf20Sopenharmony_ciout_failure: 84688c2ecf20Sopenharmony_ci trace_xdp_exception(rx_ring->netdev, xdp_prog, act); 84698c2ecf20Sopenharmony_ci fallthrough; 84708c2ecf20Sopenharmony_ci case XDP_DROP: 84718c2ecf20Sopenharmony_ci result = IGB_XDP_CONSUMED; 84728c2ecf20Sopenharmony_ci break; 84738c2ecf20Sopenharmony_ci } 84748c2ecf20Sopenharmony_cixdp_out: 84758c2ecf20Sopenharmony_ci rcu_read_unlock(); 84768c2ecf20Sopenharmony_ci return ERR_PTR(-result); 84778c2ecf20Sopenharmony_ci} 84788c2ecf20Sopenharmony_ci 84798c2ecf20Sopenharmony_cistatic unsigned int igb_rx_frame_truesize(struct igb_ring *rx_ring, 84808c2ecf20Sopenharmony_ci unsigned int size) 84818c2ecf20Sopenharmony_ci{ 84828c2ecf20Sopenharmony_ci unsigned int truesize; 84838c2ecf20Sopenharmony_ci 84848c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 84858c2ecf20Sopenharmony_ci truesize = igb_rx_pg_size(rx_ring) / 2; /* Must be power-of-2 */ 84868c2ecf20Sopenharmony_ci#else 84878c2ecf20Sopenharmony_ci truesize = ring_uses_build_skb(rx_ring) ? 84888c2ecf20Sopenharmony_ci SKB_DATA_ALIGN(IGB_SKB_PAD + size) + 84898c2ecf20Sopenharmony_ci SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : 84908c2ecf20Sopenharmony_ci SKB_DATA_ALIGN(size); 84918c2ecf20Sopenharmony_ci#endif 84928c2ecf20Sopenharmony_ci return truesize; 84938c2ecf20Sopenharmony_ci} 84948c2ecf20Sopenharmony_ci 84958c2ecf20Sopenharmony_cistatic void igb_rx_buffer_flip(struct igb_ring *rx_ring, 84968c2ecf20Sopenharmony_ci struct igb_rx_buffer *rx_buffer, 84978c2ecf20Sopenharmony_ci unsigned int size) 84988c2ecf20Sopenharmony_ci{ 84998c2ecf20Sopenharmony_ci unsigned int truesize = igb_rx_frame_truesize(rx_ring, size); 85008c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 85018c2ecf20Sopenharmony_ci rx_buffer->page_offset ^= truesize; 85028c2ecf20Sopenharmony_ci#else 85038c2ecf20Sopenharmony_ci rx_buffer->page_offset += truesize; 85048c2ecf20Sopenharmony_ci#endif 85058c2ecf20Sopenharmony_ci} 85068c2ecf20Sopenharmony_ci 85078c2ecf20Sopenharmony_cistatic inline void igb_rx_checksum(struct igb_ring *ring, 85088c2ecf20Sopenharmony_ci union e1000_adv_rx_desc *rx_desc, 85098c2ecf20Sopenharmony_ci struct sk_buff *skb) 85108c2ecf20Sopenharmony_ci{ 85118c2ecf20Sopenharmony_ci skb_checksum_none_assert(skb); 85128c2ecf20Sopenharmony_ci 85138c2ecf20Sopenharmony_ci /* Ignore Checksum bit is set */ 85148c2ecf20Sopenharmony_ci if (igb_test_staterr(rx_desc, E1000_RXD_STAT_IXSM)) 85158c2ecf20Sopenharmony_ci return; 85168c2ecf20Sopenharmony_ci 85178c2ecf20Sopenharmony_ci /* Rx checksum disabled via ethtool */ 85188c2ecf20Sopenharmony_ci if (!(ring->netdev->features & NETIF_F_RXCSUM)) 85198c2ecf20Sopenharmony_ci return; 85208c2ecf20Sopenharmony_ci 85218c2ecf20Sopenharmony_ci /* TCP/UDP checksum error bit is set */ 85228c2ecf20Sopenharmony_ci if (igb_test_staterr(rx_desc, 85238c2ecf20Sopenharmony_ci E1000_RXDEXT_STATERR_TCPE | 85248c2ecf20Sopenharmony_ci E1000_RXDEXT_STATERR_IPE)) { 85258c2ecf20Sopenharmony_ci /* work around errata with sctp packets where the TCPE aka 85268c2ecf20Sopenharmony_ci * L4E bit is set incorrectly on 64 byte (60 byte w/o crc) 85278c2ecf20Sopenharmony_ci * packets, (aka let the stack check the crc32c) 85288c2ecf20Sopenharmony_ci */ 85298c2ecf20Sopenharmony_ci if (!((skb->len == 60) && 85308c2ecf20Sopenharmony_ci test_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags))) { 85318c2ecf20Sopenharmony_ci u64_stats_update_begin(&ring->rx_syncp); 85328c2ecf20Sopenharmony_ci ring->rx_stats.csum_err++; 85338c2ecf20Sopenharmony_ci u64_stats_update_end(&ring->rx_syncp); 85348c2ecf20Sopenharmony_ci } 85358c2ecf20Sopenharmony_ci /* let the stack verify checksum errors */ 85368c2ecf20Sopenharmony_ci return; 85378c2ecf20Sopenharmony_ci } 85388c2ecf20Sopenharmony_ci /* It must be a TCP or UDP packet with a valid checksum */ 85398c2ecf20Sopenharmony_ci if (igb_test_staterr(rx_desc, E1000_RXD_STAT_TCPCS | 85408c2ecf20Sopenharmony_ci E1000_RXD_STAT_UDPCS)) 85418c2ecf20Sopenharmony_ci skb->ip_summed = CHECKSUM_UNNECESSARY; 85428c2ecf20Sopenharmony_ci 85438c2ecf20Sopenharmony_ci dev_dbg(ring->dev, "cksum success: bits %08X\n", 85448c2ecf20Sopenharmony_ci le32_to_cpu(rx_desc->wb.upper.status_error)); 85458c2ecf20Sopenharmony_ci} 85468c2ecf20Sopenharmony_ci 85478c2ecf20Sopenharmony_cistatic inline void igb_rx_hash(struct igb_ring *ring, 85488c2ecf20Sopenharmony_ci union e1000_adv_rx_desc *rx_desc, 85498c2ecf20Sopenharmony_ci struct sk_buff *skb) 85508c2ecf20Sopenharmony_ci{ 85518c2ecf20Sopenharmony_ci if (ring->netdev->features & NETIF_F_RXHASH) 85528c2ecf20Sopenharmony_ci skb_set_hash(skb, 85538c2ecf20Sopenharmony_ci le32_to_cpu(rx_desc->wb.lower.hi_dword.rss), 85548c2ecf20Sopenharmony_ci PKT_HASH_TYPE_L3); 85558c2ecf20Sopenharmony_ci} 85568c2ecf20Sopenharmony_ci 85578c2ecf20Sopenharmony_ci/** 85588c2ecf20Sopenharmony_ci * igb_is_non_eop - process handling of non-EOP buffers 85598c2ecf20Sopenharmony_ci * @rx_ring: Rx ring being processed 85608c2ecf20Sopenharmony_ci * @rx_desc: Rx descriptor for current buffer 85618c2ecf20Sopenharmony_ci * 85628c2ecf20Sopenharmony_ci * This function updates next to clean. If the buffer is an EOP buffer 85638c2ecf20Sopenharmony_ci * this function exits returning false, otherwise it will place the 85648c2ecf20Sopenharmony_ci * sk_buff in the next buffer to be chained and return true indicating 85658c2ecf20Sopenharmony_ci * that this is in fact a non-EOP buffer. 85668c2ecf20Sopenharmony_ci **/ 85678c2ecf20Sopenharmony_cistatic bool igb_is_non_eop(struct igb_ring *rx_ring, 85688c2ecf20Sopenharmony_ci union e1000_adv_rx_desc *rx_desc) 85698c2ecf20Sopenharmony_ci{ 85708c2ecf20Sopenharmony_ci u32 ntc = rx_ring->next_to_clean + 1; 85718c2ecf20Sopenharmony_ci 85728c2ecf20Sopenharmony_ci /* fetch, update, and store next to clean */ 85738c2ecf20Sopenharmony_ci ntc = (ntc < rx_ring->count) ? ntc : 0; 85748c2ecf20Sopenharmony_ci rx_ring->next_to_clean = ntc; 85758c2ecf20Sopenharmony_ci 85768c2ecf20Sopenharmony_ci prefetch(IGB_RX_DESC(rx_ring, ntc)); 85778c2ecf20Sopenharmony_ci 85788c2ecf20Sopenharmony_ci if (likely(igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP))) 85798c2ecf20Sopenharmony_ci return false; 85808c2ecf20Sopenharmony_ci 85818c2ecf20Sopenharmony_ci return true; 85828c2ecf20Sopenharmony_ci} 85838c2ecf20Sopenharmony_ci 85848c2ecf20Sopenharmony_ci/** 85858c2ecf20Sopenharmony_ci * igb_cleanup_headers - Correct corrupted or empty headers 85868c2ecf20Sopenharmony_ci * @rx_ring: rx descriptor ring packet is being transacted on 85878c2ecf20Sopenharmony_ci * @rx_desc: pointer to the EOP Rx descriptor 85888c2ecf20Sopenharmony_ci * @skb: pointer to current skb being fixed 85898c2ecf20Sopenharmony_ci * 85908c2ecf20Sopenharmony_ci * Address the case where we are pulling data in on pages only 85918c2ecf20Sopenharmony_ci * and as such no data is present in the skb header. 85928c2ecf20Sopenharmony_ci * 85938c2ecf20Sopenharmony_ci * In addition if skb is not at least 60 bytes we need to pad it so that 85948c2ecf20Sopenharmony_ci * it is large enough to qualify as a valid Ethernet frame. 85958c2ecf20Sopenharmony_ci * 85968c2ecf20Sopenharmony_ci * Returns true if an error was encountered and skb was freed. 85978c2ecf20Sopenharmony_ci **/ 85988c2ecf20Sopenharmony_cistatic bool igb_cleanup_headers(struct igb_ring *rx_ring, 85998c2ecf20Sopenharmony_ci union e1000_adv_rx_desc *rx_desc, 86008c2ecf20Sopenharmony_ci struct sk_buff *skb) 86018c2ecf20Sopenharmony_ci{ 86028c2ecf20Sopenharmony_ci /* XDP packets use error pointer so abort at this point */ 86038c2ecf20Sopenharmony_ci if (IS_ERR(skb)) 86048c2ecf20Sopenharmony_ci return true; 86058c2ecf20Sopenharmony_ci 86068c2ecf20Sopenharmony_ci if (unlikely((igb_test_staterr(rx_desc, 86078c2ecf20Sopenharmony_ci E1000_RXDEXT_ERR_FRAME_ERR_MASK)))) { 86088c2ecf20Sopenharmony_ci struct net_device *netdev = rx_ring->netdev; 86098c2ecf20Sopenharmony_ci if (!(netdev->features & NETIF_F_RXALL)) { 86108c2ecf20Sopenharmony_ci dev_kfree_skb_any(skb); 86118c2ecf20Sopenharmony_ci return true; 86128c2ecf20Sopenharmony_ci } 86138c2ecf20Sopenharmony_ci } 86148c2ecf20Sopenharmony_ci 86158c2ecf20Sopenharmony_ci /* if eth_skb_pad returns an error the skb was freed */ 86168c2ecf20Sopenharmony_ci if (eth_skb_pad(skb)) 86178c2ecf20Sopenharmony_ci return true; 86188c2ecf20Sopenharmony_ci 86198c2ecf20Sopenharmony_ci return false; 86208c2ecf20Sopenharmony_ci} 86218c2ecf20Sopenharmony_ci 86228c2ecf20Sopenharmony_ci/** 86238c2ecf20Sopenharmony_ci * igb_process_skb_fields - Populate skb header fields from Rx descriptor 86248c2ecf20Sopenharmony_ci * @rx_ring: rx descriptor ring packet is being transacted on 86258c2ecf20Sopenharmony_ci * @rx_desc: pointer to the EOP Rx descriptor 86268c2ecf20Sopenharmony_ci * @skb: pointer to current skb being populated 86278c2ecf20Sopenharmony_ci * 86288c2ecf20Sopenharmony_ci * This function checks the ring, descriptor, and packet information in 86298c2ecf20Sopenharmony_ci * order to populate the hash, checksum, VLAN, timestamp, protocol, and 86308c2ecf20Sopenharmony_ci * other fields within the skb. 86318c2ecf20Sopenharmony_ci **/ 86328c2ecf20Sopenharmony_cistatic void igb_process_skb_fields(struct igb_ring *rx_ring, 86338c2ecf20Sopenharmony_ci union e1000_adv_rx_desc *rx_desc, 86348c2ecf20Sopenharmony_ci struct sk_buff *skb) 86358c2ecf20Sopenharmony_ci{ 86368c2ecf20Sopenharmony_ci struct net_device *dev = rx_ring->netdev; 86378c2ecf20Sopenharmony_ci 86388c2ecf20Sopenharmony_ci igb_rx_hash(rx_ring, rx_desc, skb); 86398c2ecf20Sopenharmony_ci 86408c2ecf20Sopenharmony_ci igb_rx_checksum(rx_ring, rx_desc, skb); 86418c2ecf20Sopenharmony_ci 86428c2ecf20Sopenharmony_ci if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS) && 86438c2ecf20Sopenharmony_ci !igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) 86448c2ecf20Sopenharmony_ci igb_ptp_rx_rgtstamp(rx_ring->q_vector, skb); 86458c2ecf20Sopenharmony_ci 86468c2ecf20Sopenharmony_ci if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) && 86478c2ecf20Sopenharmony_ci igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) { 86488c2ecf20Sopenharmony_ci u16 vid; 86498c2ecf20Sopenharmony_ci 86508c2ecf20Sopenharmony_ci if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) && 86518c2ecf20Sopenharmony_ci test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags)) 86528c2ecf20Sopenharmony_ci vid = be16_to_cpu((__force __be16)rx_desc->wb.upper.vlan); 86538c2ecf20Sopenharmony_ci else 86548c2ecf20Sopenharmony_ci vid = le16_to_cpu(rx_desc->wb.upper.vlan); 86558c2ecf20Sopenharmony_ci 86568c2ecf20Sopenharmony_ci __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); 86578c2ecf20Sopenharmony_ci } 86588c2ecf20Sopenharmony_ci 86598c2ecf20Sopenharmony_ci skb_record_rx_queue(skb, rx_ring->queue_index); 86608c2ecf20Sopenharmony_ci 86618c2ecf20Sopenharmony_ci skb->protocol = eth_type_trans(skb, rx_ring->netdev); 86628c2ecf20Sopenharmony_ci} 86638c2ecf20Sopenharmony_ci 86648c2ecf20Sopenharmony_cistatic unsigned int igb_rx_offset(struct igb_ring *rx_ring) 86658c2ecf20Sopenharmony_ci{ 86668c2ecf20Sopenharmony_ci return ring_uses_build_skb(rx_ring) ? IGB_SKB_PAD : 0; 86678c2ecf20Sopenharmony_ci} 86688c2ecf20Sopenharmony_ci 86698c2ecf20Sopenharmony_cistatic struct igb_rx_buffer *igb_get_rx_buffer(struct igb_ring *rx_ring, 86708c2ecf20Sopenharmony_ci const unsigned int size, int *rx_buf_pgcnt) 86718c2ecf20Sopenharmony_ci{ 86728c2ecf20Sopenharmony_ci struct igb_rx_buffer *rx_buffer; 86738c2ecf20Sopenharmony_ci 86748c2ecf20Sopenharmony_ci rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; 86758c2ecf20Sopenharmony_ci *rx_buf_pgcnt = 86768c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 86778c2ecf20Sopenharmony_ci page_count(rx_buffer->page); 86788c2ecf20Sopenharmony_ci#else 86798c2ecf20Sopenharmony_ci 0; 86808c2ecf20Sopenharmony_ci#endif 86818c2ecf20Sopenharmony_ci prefetchw(rx_buffer->page); 86828c2ecf20Sopenharmony_ci 86838c2ecf20Sopenharmony_ci /* we are reusing so sync this buffer for CPU use */ 86848c2ecf20Sopenharmony_ci dma_sync_single_range_for_cpu(rx_ring->dev, 86858c2ecf20Sopenharmony_ci rx_buffer->dma, 86868c2ecf20Sopenharmony_ci rx_buffer->page_offset, 86878c2ecf20Sopenharmony_ci size, 86888c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 86898c2ecf20Sopenharmony_ci 86908c2ecf20Sopenharmony_ci rx_buffer->pagecnt_bias--; 86918c2ecf20Sopenharmony_ci 86928c2ecf20Sopenharmony_ci return rx_buffer; 86938c2ecf20Sopenharmony_ci} 86948c2ecf20Sopenharmony_ci 86958c2ecf20Sopenharmony_cistatic void igb_put_rx_buffer(struct igb_ring *rx_ring, 86968c2ecf20Sopenharmony_ci struct igb_rx_buffer *rx_buffer, int rx_buf_pgcnt) 86978c2ecf20Sopenharmony_ci{ 86988c2ecf20Sopenharmony_ci if (igb_can_reuse_rx_page(rx_buffer, rx_buf_pgcnt)) { 86998c2ecf20Sopenharmony_ci /* hand second half of page back to the ring */ 87008c2ecf20Sopenharmony_ci igb_reuse_rx_page(rx_ring, rx_buffer); 87018c2ecf20Sopenharmony_ci } else { 87028c2ecf20Sopenharmony_ci /* We are not reusing the buffer so unmap it and free 87038c2ecf20Sopenharmony_ci * any references we are holding to it 87048c2ecf20Sopenharmony_ci */ 87058c2ecf20Sopenharmony_ci dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma, 87068c2ecf20Sopenharmony_ci igb_rx_pg_size(rx_ring), DMA_FROM_DEVICE, 87078c2ecf20Sopenharmony_ci IGB_RX_DMA_ATTR); 87088c2ecf20Sopenharmony_ci __page_frag_cache_drain(rx_buffer->page, 87098c2ecf20Sopenharmony_ci rx_buffer->pagecnt_bias); 87108c2ecf20Sopenharmony_ci } 87118c2ecf20Sopenharmony_ci 87128c2ecf20Sopenharmony_ci /* clear contents of rx_buffer */ 87138c2ecf20Sopenharmony_ci rx_buffer->page = NULL; 87148c2ecf20Sopenharmony_ci} 87158c2ecf20Sopenharmony_ci 87168c2ecf20Sopenharmony_cistatic int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) 87178c2ecf20Sopenharmony_ci{ 87188c2ecf20Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 87198c2ecf20Sopenharmony_ci struct igb_ring *rx_ring = q_vector->rx.ring; 87208c2ecf20Sopenharmony_ci struct sk_buff *skb = rx_ring->skb; 87218c2ecf20Sopenharmony_ci unsigned int total_bytes = 0, total_packets = 0; 87228c2ecf20Sopenharmony_ci u16 cleaned_count = igb_desc_unused(rx_ring); 87238c2ecf20Sopenharmony_ci unsigned int xdp_xmit = 0; 87248c2ecf20Sopenharmony_ci struct xdp_buff xdp; 87258c2ecf20Sopenharmony_ci int rx_buf_pgcnt; 87268c2ecf20Sopenharmony_ci 87278c2ecf20Sopenharmony_ci xdp.rxq = &rx_ring->xdp_rxq; 87288c2ecf20Sopenharmony_ci 87298c2ecf20Sopenharmony_ci /* Frame size depend on rx_ring setup when PAGE_SIZE=4K */ 87308c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192) 87318c2ecf20Sopenharmony_ci xdp.frame_sz = igb_rx_frame_truesize(rx_ring, 0); 87328c2ecf20Sopenharmony_ci#endif 87338c2ecf20Sopenharmony_ci 87348c2ecf20Sopenharmony_ci while (likely(total_packets < budget)) { 87358c2ecf20Sopenharmony_ci union e1000_adv_rx_desc *rx_desc; 87368c2ecf20Sopenharmony_ci struct igb_rx_buffer *rx_buffer; 87378c2ecf20Sopenharmony_ci unsigned int size; 87388c2ecf20Sopenharmony_ci 87398c2ecf20Sopenharmony_ci /* return some buffers to hardware, one at a time is too slow */ 87408c2ecf20Sopenharmony_ci if (cleaned_count >= IGB_RX_BUFFER_WRITE) { 87418c2ecf20Sopenharmony_ci igb_alloc_rx_buffers(rx_ring, cleaned_count); 87428c2ecf20Sopenharmony_ci cleaned_count = 0; 87438c2ecf20Sopenharmony_ci } 87448c2ecf20Sopenharmony_ci 87458c2ecf20Sopenharmony_ci rx_desc = IGB_RX_DESC(rx_ring, rx_ring->next_to_clean); 87468c2ecf20Sopenharmony_ci size = le16_to_cpu(rx_desc->wb.upper.length); 87478c2ecf20Sopenharmony_ci if (!size) 87488c2ecf20Sopenharmony_ci break; 87498c2ecf20Sopenharmony_ci 87508c2ecf20Sopenharmony_ci /* This memory barrier is needed to keep us from reading 87518c2ecf20Sopenharmony_ci * any other fields out of the rx_desc until we know the 87528c2ecf20Sopenharmony_ci * descriptor has been written back 87538c2ecf20Sopenharmony_ci */ 87548c2ecf20Sopenharmony_ci dma_rmb(); 87558c2ecf20Sopenharmony_ci 87568c2ecf20Sopenharmony_ci rx_buffer = igb_get_rx_buffer(rx_ring, size, &rx_buf_pgcnt); 87578c2ecf20Sopenharmony_ci 87588c2ecf20Sopenharmony_ci /* retrieve a buffer from the ring */ 87598c2ecf20Sopenharmony_ci if (!skb) { 87608c2ecf20Sopenharmony_ci xdp.data = page_address(rx_buffer->page) + 87618c2ecf20Sopenharmony_ci rx_buffer->page_offset; 87628c2ecf20Sopenharmony_ci xdp.data_meta = xdp.data; 87638c2ecf20Sopenharmony_ci xdp.data_hard_start = xdp.data - 87648c2ecf20Sopenharmony_ci igb_rx_offset(rx_ring); 87658c2ecf20Sopenharmony_ci xdp.data_end = xdp.data + size; 87668c2ecf20Sopenharmony_ci#if (PAGE_SIZE > 4096) 87678c2ecf20Sopenharmony_ci /* At larger PAGE_SIZE, frame_sz depend on len size */ 87688c2ecf20Sopenharmony_ci xdp.frame_sz = igb_rx_frame_truesize(rx_ring, size); 87698c2ecf20Sopenharmony_ci#endif 87708c2ecf20Sopenharmony_ci skb = igb_run_xdp(adapter, rx_ring, &xdp); 87718c2ecf20Sopenharmony_ci } 87728c2ecf20Sopenharmony_ci 87738c2ecf20Sopenharmony_ci if (IS_ERR(skb)) { 87748c2ecf20Sopenharmony_ci unsigned int xdp_res = -PTR_ERR(skb); 87758c2ecf20Sopenharmony_ci 87768c2ecf20Sopenharmony_ci if (xdp_res & (IGB_XDP_TX | IGB_XDP_REDIR)) { 87778c2ecf20Sopenharmony_ci xdp_xmit |= xdp_res; 87788c2ecf20Sopenharmony_ci igb_rx_buffer_flip(rx_ring, rx_buffer, size); 87798c2ecf20Sopenharmony_ci } else { 87808c2ecf20Sopenharmony_ci rx_buffer->pagecnt_bias++; 87818c2ecf20Sopenharmony_ci } 87828c2ecf20Sopenharmony_ci total_packets++; 87838c2ecf20Sopenharmony_ci total_bytes += size; 87848c2ecf20Sopenharmony_ci } else if (skb) 87858c2ecf20Sopenharmony_ci igb_add_rx_frag(rx_ring, rx_buffer, skb, size); 87868c2ecf20Sopenharmony_ci else if (ring_uses_build_skb(rx_ring)) 87878c2ecf20Sopenharmony_ci skb = igb_build_skb(rx_ring, rx_buffer, &xdp, rx_desc); 87888c2ecf20Sopenharmony_ci else 87898c2ecf20Sopenharmony_ci skb = igb_construct_skb(rx_ring, rx_buffer, 87908c2ecf20Sopenharmony_ci &xdp, rx_desc); 87918c2ecf20Sopenharmony_ci 87928c2ecf20Sopenharmony_ci /* exit if we failed to retrieve a buffer */ 87938c2ecf20Sopenharmony_ci if (!skb) { 87948c2ecf20Sopenharmony_ci rx_ring->rx_stats.alloc_failed++; 87958c2ecf20Sopenharmony_ci rx_buffer->pagecnt_bias++; 87968c2ecf20Sopenharmony_ci break; 87978c2ecf20Sopenharmony_ci } 87988c2ecf20Sopenharmony_ci 87998c2ecf20Sopenharmony_ci igb_put_rx_buffer(rx_ring, rx_buffer, rx_buf_pgcnt); 88008c2ecf20Sopenharmony_ci cleaned_count++; 88018c2ecf20Sopenharmony_ci 88028c2ecf20Sopenharmony_ci /* fetch next buffer in frame if non-eop */ 88038c2ecf20Sopenharmony_ci if (igb_is_non_eop(rx_ring, rx_desc)) 88048c2ecf20Sopenharmony_ci continue; 88058c2ecf20Sopenharmony_ci 88068c2ecf20Sopenharmony_ci /* verify the packet layout is correct */ 88078c2ecf20Sopenharmony_ci if (igb_cleanup_headers(rx_ring, rx_desc, skb)) { 88088c2ecf20Sopenharmony_ci skb = NULL; 88098c2ecf20Sopenharmony_ci continue; 88108c2ecf20Sopenharmony_ci } 88118c2ecf20Sopenharmony_ci 88128c2ecf20Sopenharmony_ci /* probably a little skewed due to removing CRC */ 88138c2ecf20Sopenharmony_ci total_bytes += skb->len; 88148c2ecf20Sopenharmony_ci 88158c2ecf20Sopenharmony_ci /* populate checksum, timestamp, VLAN, and protocol */ 88168c2ecf20Sopenharmony_ci igb_process_skb_fields(rx_ring, rx_desc, skb); 88178c2ecf20Sopenharmony_ci 88188c2ecf20Sopenharmony_ci napi_gro_receive(&q_vector->napi, skb); 88198c2ecf20Sopenharmony_ci 88208c2ecf20Sopenharmony_ci /* reset skb pointer */ 88218c2ecf20Sopenharmony_ci skb = NULL; 88228c2ecf20Sopenharmony_ci 88238c2ecf20Sopenharmony_ci /* update budget accounting */ 88248c2ecf20Sopenharmony_ci total_packets++; 88258c2ecf20Sopenharmony_ci } 88268c2ecf20Sopenharmony_ci 88278c2ecf20Sopenharmony_ci /* place incomplete frames back on ring for completion */ 88288c2ecf20Sopenharmony_ci rx_ring->skb = skb; 88298c2ecf20Sopenharmony_ci 88308c2ecf20Sopenharmony_ci if (xdp_xmit & IGB_XDP_REDIR) 88318c2ecf20Sopenharmony_ci xdp_do_flush(); 88328c2ecf20Sopenharmony_ci 88338c2ecf20Sopenharmony_ci if (xdp_xmit & IGB_XDP_TX) { 88348c2ecf20Sopenharmony_ci struct igb_ring *tx_ring = igb_xdp_tx_queue_mapping(adapter); 88358c2ecf20Sopenharmony_ci 88368c2ecf20Sopenharmony_ci igb_xdp_ring_update_tail(tx_ring); 88378c2ecf20Sopenharmony_ci } 88388c2ecf20Sopenharmony_ci 88398c2ecf20Sopenharmony_ci u64_stats_update_begin(&rx_ring->rx_syncp); 88408c2ecf20Sopenharmony_ci rx_ring->rx_stats.packets += total_packets; 88418c2ecf20Sopenharmony_ci rx_ring->rx_stats.bytes += total_bytes; 88428c2ecf20Sopenharmony_ci u64_stats_update_end(&rx_ring->rx_syncp); 88438c2ecf20Sopenharmony_ci q_vector->rx.total_packets += total_packets; 88448c2ecf20Sopenharmony_ci q_vector->rx.total_bytes += total_bytes; 88458c2ecf20Sopenharmony_ci 88468c2ecf20Sopenharmony_ci if (cleaned_count) 88478c2ecf20Sopenharmony_ci igb_alloc_rx_buffers(rx_ring, cleaned_count); 88488c2ecf20Sopenharmony_ci 88498c2ecf20Sopenharmony_ci return total_packets; 88508c2ecf20Sopenharmony_ci} 88518c2ecf20Sopenharmony_ci 88528c2ecf20Sopenharmony_cistatic bool igb_alloc_mapped_page(struct igb_ring *rx_ring, 88538c2ecf20Sopenharmony_ci struct igb_rx_buffer *bi) 88548c2ecf20Sopenharmony_ci{ 88558c2ecf20Sopenharmony_ci struct page *page = bi->page; 88568c2ecf20Sopenharmony_ci dma_addr_t dma; 88578c2ecf20Sopenharmony_ci 88588c2ecf20Sopenharmony_ci /* since we are recycling buffers we should seldom need to alloc */ 88598c2ecf20Sopenharmony_ci if (likely(page)) 88608c2ecf20Sopenharmony_ci return true; 88618c2ecf20Sopenharmony_ci 88628c2ecf20Sopenharmony_ci /* alloc new page for storage */ 88638c2ecf20Sopenharmony_ci page = dev_alloc_pages(igb_rx_pg_order(rx_ring)); 88648c2ecf20Sopenharmony_ci if (unlikely(!page)) { 88658c2ecf20Sopenharmony_ci rx_ring->rx_stats.alloc_failed++; 88668c2ecf20Sopenharmony_ci return false; 88678c2ecf20Sopenharmony_ci } 88688c2ecf20Sopenharmony_ci 88698c2ecf20Sopenharmony_ci /* map page for use */ 88708c2ecf20Sopenharmony_ci dma = dma_map_page_attrs(rx_ring->dev, page, 0, 88718c2ecf20Sopenharmony_ci igb_rx_pg_size(rx_ring), 88728c2ecf20Sopenharmony_ci DMA_FROM_DEVICE, 88738c2ecf20Sopenharmony_ci IGB_RX_DMA_ATTR); 88748c2ecf20Sopenharmony_ci 88758c2ecf20Sopenharmony_ci /* if mapping failed free memory back to system since 88768c2ecf20Sopenharmony_ci * there isn't much point in holding memory we can't use 88778c2ecf20Sopenharmony_ci */ 88788c2ecf20Sopenharmony_ci if (dma_mapping_error(rx_ring->dev, dma)) { 88798c2ecf20Sopenharmony_ci __free_pages(page, igb_rx_pg_order(rx_ring)); 88808c2ecf20Sopenharmony_ci 88818c2ecf20Sopenharmony_ci rx_ring->rx_stats.alloc_failed++; 88828c2ecf20Sopenharmony_ci return false; 88838c2ecf20Sopenharmony_ci } 88848c2ecf20Sopenharmony_ci 88858c2ecf20Sopenharmony_ci bi->dma = dma; 88868c2ecf20Sopenharmony_ci bi->page = page; 88878c2ecf20Sopenharmony_ci bi->page_offset = igb_rx_offset(rx_ring); 88888c2ecf20Sopenharmony_ci page_ref_add(page, USHRT_MAX - 1); 88898c2ecf20Sopenharmony_ci bi->pagecnt_bias = USHRT_MAX; 88908c2ecf20Sopenharmony_ci 88918c2ecf20Sopenharmony_ci return true; 88928c2ecf20Sopenharmony_ci} 88938c2ecf20Sopenharmony_ci 88948c2ecf20Sopenharmony_ci/** 88958c2ecf20Sopenharmony_ci * igb_alloc_rx_buffers - Replace used receive buffers 88968c2ecf20Sopenharmony_ci * @rx_ring: rx descriptor ring to allocate new receive buffers 88978c2ecf20Sopenharmony_ci * @cleaned_count: count of buffers to allocate 88988c2ecf20Sopenharmony_ci **/ 88998c2ecf20Sopenharmony_civoid igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count) 89008c2ecf20Sopenharmony_ci{ 89018c2ecf20Sopenharmony_ci union e1000_adv_rx_desc *rx_desc; 89028c2ecf20Sopenharmony_ci struct igb_rx_buffer *bi; 89038c2ecf20Sopenharmony_ci u16 i = rx_ring->next_to_use; 89048c2ecf20Sopenharmony_ci u16 bufsz; 89058c2ecf20Sopenharmony_ci 89068c2ecf20Sopenharmony_ci /* nothing to do */ 89078c2ecf20Sopenharmony_ci if (!cleaned_count) 89088c2ecf20Sopenharmony_ci return; 89098c2ecf20Sopenharmony_ci 89108c2ecf20Sopenharmony_ci rx_desc = IGB_RX_DESC(rx_ring, i); 89118c2ecf20Sopenharmony_ci bi = &rx_ring->rx_buffer_info[i]; 89128c2ecf20Sopenharmony_ci i -= rx_ring->count; 89138c2ecf20Sopenharmony_ci 89148c2ecf20Sopenharmony_ci bufsz = igb_rx_bufsz(rx_ring); 89158c2ecf20Sopenharmony_ci 89168c2ecf20Sopenharmony_ci do { 89178c2ecf20Sopenharmony_ci if (!igb_alloc_mapped_page(rx_ring, bi)) 89188c2ecf20Sopenharmony_ci break; 89198c2ecf20Sopenharmony_ci 89208c2ecf20Sopenharmony_ci /* sync the buffer for use by the device */ 89218c2ecf20Sopenharmony_ci dma_sync_single_range_for_device(rx_ring->dev, bi->dma, 89228c2ecf20Sopenharmony_ci bi->page_offset, bufsz, 89238c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 89248c2ecf20Sopenharmony_ci 89258c2ecf20Sopenharmony_ci /* Refresh the desc even if buffer_addrs didn't change 89268c2ecf20Sopenharmony_ci * because each write-back erases this info. 89278c2ecf20Sopenharmony_ci */ 89288c2ecf20Sopenharmony_ci rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); 89298c2ecf20Sopenharmony_ci 89308c2ecf20Sopenharmony_ci rx_desc++; 89318c2ecf20Sopenharmony_ci bi++; 89328c2ecf20Sopenharmony_ci i++; 89338c2ecf20Sopenharmony_ci if (unlikely(!i)) { 89348c2ecf20Sopenharmony_ci rx_desc = IGB_RX_DESC(rx_ring, 0); 89358c2ecf20Sopenharmony_ci bi = rx_ring->rx_buffer_info; 89368c2ecf20Sopenharmony_ci i -= rx_ring->count; 89378c2ecf20Sopenharmony_ci } 89388c2ecf20Sopenharmony_ci 89398c2ecf20Sopenharmony_ci /* clear the length for the next_to_use descriptor */ 89408c2ecf20Sopenharmony_ci rx_desc->wb.upper.length = 0; 89418c2ecf20Sopenharmony_ci 89428c2ecf20Sopenharmony_ci cleaned_count--; 89438c2ecf20Sopenharmony_ci } while (cleaned_count); 89448c2ecf20Sopenharmony_ci 89458c2ecf20Sopenharmony_ci i += rx_ring->count; 89468c2ecf20Sopenharmony_ci 89478c2ecf20Sopenharmony_ci if (rx_ring->next_to_use != i) { 89488c2ecf20Sopenharmony_ci /* record the next descriptor to use */ 89498c2ecf20Sopenharmony_ci rx_ring->next_to_use = i; 89508c2ecf20Sopenharmony_ci 89518c2ecf20Sopenharmony_ci /* update next to alloc since we have filled the ring */ 89528c2ecf20Sopenharmony_ci rx_ring->next_to_alloc = i; 89538c2ecf20Sopenharmony_ci 89548c2ecf20Sopenharmony_ci /* Force memory writes to complete before letting h/w 89558c2ecf20Sopenharmony_ci * know there are new descriptors to fetch. (Only 89568c2ecf20Sopenharmony_ci * applicable for weak-ordered memory model archs, 89578c2ecf20Sopenharmony_ci * such as IA-64). 89588c2ecf20Sopenharmony_ci */ 89598c2ecf20Sopenharmony_ci dma_wmb(); 89608c2ecf20Sopenharmony_ci writel(i, rx_ring->tail); 89618c2ecf20Sopenharmony_ci } 89628c2ecf20Sopenharmony_ci} 89638c2ecf20Sopenharmony_ci 89648c2ecf20Sopenharmony_ci/** 89658c2ecf20Sopenharmony_ci * igb_mii_ioctl - 89668c2ecf20Sopenharmony_ci * @netdev: pointer to netdev struct 89678c2ecf20Sopenharmony_ci * @ifr: interface structure 89688c2ecf20Sopenharmony_ci * @cmd: ioctl command to execute 89698c2ecf20Sopenharmony_ci **/ 89708c2ecf20Sopenharmony_cistatic int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) 89718c2ecf20Sopenharmony_ci{ 89728c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 89738c2ecf20Sopenharmony_ci struct mii_ioctl_data *data = if_mii(ifr); 89748c2ecf20Sopenharmony_ci 89758c2ecf20Sopenharmony_ci if (adapter->hw.phy.media_type != e1000_media_type_copper) 89768c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 89778c2ecf20Sopenharmony_ci 89788c2ecf20Sopenharmony_ci switch (cmd) { 89798c2ecf20Sopenharmony_ci case SIOCGMIIPHY: 89808c2ecf20Sopenharmony_ci data->phy_id = adapter->hw.phy.addr; 89818c2ecf20Sopenharmony_ci break; 89828c2ecf20Sopenharmony_ci case SIOCGMIIREG: 89838c2ecf20Sopenharmony_ci if (igb_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, 89848c2ecf20Sopenharmony_ci &data->val_out)) 89858c2ecf20Sopenharmony_ci return -EIO; 89868c2ecf20Sopenharmony_ci break; 89878c2ecf20Sopenharmony_ci case SIOCSMIIREG: 89888c2ecf20Sopenharmony_ci default: 89898c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 89908c2ecf20Sopenharmony_ci } 89918c2ecf20Sopenharmony_ci return 0; 89928c2ecf20Sopenharmony_ci} 89938c2ecf20Sopenharmony_ci 89948c2ecf20Sopenharmony_ci/** 89958c2ecf20Sopenharmony_ci * igb_ioctl - 89968c2ecf20Sopenharmony_ci * @netdev: pointer to netdev struct 89978c2ecf20Sopenharmony_ci * @ifr: interface structure 89988c2ecf20Sopenharmony_ci * @cmd: ioctl command to execute 89998c2ecf20Sopenharmony_ci **/ 90008c2ecf20Sopenharmony_cistatic int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) 90018c2ecf20Sopenharmony_ci{ 90028c2ecf20Sopenharmony_ci switch (cmd) { 90038c2ecf20Sopenharmony_ci case SIOCGMIIPHY: 90048c2ecf20Sopenharmony_ci case SIOCGMIIREG: 90058c2ecf20Sopenharmony_ci case SIOCSMIIREG: 90068c2ecf20Sopenharmony_ci return igb_mii_ioctl(netdev, ifr, cmd); 90078c2ecf20Sopenharmony_ci case SIOCGHWTSTAMP: 90088c2ecf20Sopenharmony_ci return igb_ptp_get_ts_config(netdev, ifr); 90098c2ecf20Sopenharmony_ci case SIOCSHWTSTAMP: 90108c2ecf20Sopenharmony_ci return igb_ptp_set_ts_config(netdev, ifr); 90118c2ecf20Sopenharmony_ci default: 90128c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 90138c2ecf20Sopenharmony_ci } 90148c2ecf20Sopenharmony_ci} 90158c2ecf20Sopenharmony_ci 90168c2ecf20Sopenharmony_civoid igb_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value) 90178c2ecf20Sopenharmony_ci{ 90188c2ecf20Sopenharmony_ci struct igb_adapter *adapter = hw->back; 90198c2ecf20Sopenharmony_ci 90208c2ecf20Sopenharmony_ci pci_read_config_word(adapter->pdev, reg, value); 90218c2ecf20Sopenharmony_ci} 90228c2ecf20Sopenharmony_ci 90238c2ecf20Sopenharmony_civoid igb_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value) 90248c2ecf20Sopenharmony_ci{ 90258c2ecf20Sopenharmony_ci struct igb_adapter *adapter = hw->back; 90268c2ecf20Sopenharmony_ci 90278c2ecf20Sopenharmony_ci pci_write_config_word(adapter->pdev, reg, *value); 90288c2ecf20Sopenharmony_ci} 90298c2ecf20Sopenharmony_ci 90308c2ecf20Sopenharmony_cis32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) 90318c2ecf20Sopenharmony_ci{ 90328c2ecf20Sopenharmony_ci struct igb_adapter *adapter = hw->back; 90338c2ecf20Sopenharmony_ci 90348c2ecf20Sopenharmony_ci if (pcie_capability_read_word(adapter->pdev, reg, value)) 90358c2ecf20Sopenharmony_ci return -E1000_ERR_CONFIG; 90368c2ecf20Sopenharmony_ci 90378c2ecf20Sopenharmony_ci return 0; 90388c2ecf20Sopenharmony_ci} 90398c2ecf20Sopenharmony_ci 90408c2ecf20Sopenharmony_cis32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) 90418c2ecf20Sopenharmony_ci{ 90428c2ecf20Sopenharmony_ci struct igb_adapter *adapter = hw->back; 90438c2ecf20Sopenharmony_ci 90448c2ecf20Sopenharmony_ci if (pcie_capability_write_word(adapter->pdev, reg, *value)) 90458c2ecf20Sopenharmony_ci return -E1000_ERR_CONFIG; 90468c2ecf20Sopenharmony_ci 90478c2ecf20Sopenharmony_ci return 0; 90488c2ecf20Sopenharmony_ci} 90498c2ecf20Sopenharmony_ci 90508c2ecf20Sopenharmony_cistatic void igb_vlan_mode(struct net_device *netdev, netdev_features_t features) 90518c2ecf20Sopenharmony_ci{ 90528c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 90538c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 90548c2ecf20Sopenharmony_ci u32 ctrl, rctl; 90558c2ecf20Sopenharmony_ci bool enable = !!(features & NETIF_F_HW_VLAN_CTAG_RX); 90568c2ecf20Sopenharmony_ci 90578c2ecf20Sopenharmony_ci if (enable) { 90588c2ecf20Sopenharmony_ci /* enable VLAN tag insert/strip */ 90598c2ecf20Sopenharmony_ci ctrl = rd32(E1000_CTRL); 90608c2ecf20Sopenharmony_ci ctrl |= E1000_CTRL_VME; 90618c2ecf20Sopenharmony_ci wr32(E1000_CTRL, ctrl); 90628c2ecf20Sopenharmony_ci 90638c2ecf20Sopenharmony_ci /* Disable CFI check */ 90648c2ecf20Sopenharmony_ci rctl = rd32(E1000_RCTL); 90658c2ecf20Sopenharmony_ci rctl &= ~E1000_RCTL_CFIEN; 90668c2ecf20Sopenharmony_ci wr32(E1000_RCTL, rctl); 90678c2ecf20Sopenharmony_ci } else { 90688c2ecf20Sopenharmony_ci /* disable VLAN tag insert/strip */ 90698c2ecf20Sopenharmony_ci ctrl = rd32(E1000_CTRL); 90708c2ecf20Sopenharmony_ci ctrl &= ~E1000_CTRL_VME; 90718c2ecf20Sopenharmony_ci wr32(E1000_CTRL, ctrl); 90728c2ecf20Sopenharmony_ci } 90738c2ecf20Sopenharmony_ci 90748c2ecf20Sopenharmony_ci igb_set_vf_vlan_strip(adapter, adapter->vfs_allocated_count, enable); 90758c2ecf20Sopenharmony_ci} 90768c2ecf20Sopenharmony_ci 90778c2ecf20Sopenharmony_cistatic int igb_vlan_rx_add_vid(struct net_device *netdev, 90788c2ecf20Sopenharmony_ci __be16 proto, u16 vid) 90798c2ecf20Sopenharmony_ci{ 90808c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 90818c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 90828c2ecf20Sopenharmony_ci int pf_id = adapter->vfs_allocated_count; 90838c2ecf20Sopenharmony_ci 90848c2ecf20Sopenharmony_ci /* add the filter since PF can receive vlans w/o entry in vlvf */ 90858c2ecf20Sopenharmony_ci if (!vid || !(adapter->flags & IGB_FLAG_VLAN_PROMISC)) 90868c2ecf20Sopenharmony_ci igb_vfta_set(hw, vid, pf_id, true, !!vid); 90878c2ecf20Sopenharmony_ci 90888c2ecf20Sopenharmony_ci set_bit(vid, adapter->active_vlans); 90898c2ecf20Sopenharmony_ci 90908c2ecf20Sopenharmony_ci return 0; 90918c2ecf20Sopenharmony_ci} 90928c2ecf20Sopenharmony_ci 90938c2ecf20Sopenharmony_cistatic int igb_vlan_rx_kill_vid(struct net_device *netdev, 90948c2ecf20Sopenharmony_ci __be16 proto, u16 vid) 90958c2ecf20Sopenharmony_ci{ 90968c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 90978c2ecf20Sopenharmony_ci int pf_id = adapter->vfs_allocated_count; 90988c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 90998c2ecf20Sopenharmony_ci 91008c2ecf20Sopenharmony_ci /* remove VID from filter table */ 91018c2ecf20Sopenharmony_ci if (vid && !(adapter->flags & IGB_FLAG_VLAN_PROMISC)) 91028c2ecf20Sopenharmony_ci igb_vfta_set(hw, vid, pf_id, false, true); 91038c2ecf20Sopenharmony_ci 91048c2ecf20Sopenharmony_ci clear_bit(vid, adapter->active_vlans); 91058c2ecf20Sopenharmony_ci 91068c2ecf20Sopenharmony_ci return 0; 91078c2ecf20Sopenharmony_ci} 91088c2ecf20Sopenharmony_ci 91098c2ecf20Sopenharmony_cistatic void igb_restore_vlan(struct igb_adapter *adapter) 91108c2ecf20Sopenharmony_ci{ 91118c2ecf20Sopenharmony_ci u16 vid = 1; 91128c2ecf20Sopenharmony_ci 91138c2ecf20Sopenharmony_ci igb_vlan_mode(adapter->netdev, adapter->netdev->features); 91148c2ecf20Sopenharmony_ci igb_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), 0); 91158c2ecf20Sopenharmony_ci 91168c2ecf20Sopenharmony_ci for_each_set_bit_from(vid, adapter->active_vlans, VLAN_N_VID) 91178c2ecf20Sopenharmony_ci igb_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid); 91188c2ecf20Sopenharmony_ci} 91198c2ecf20Sopenharmony_ci 91208c2ecf20Sopenharmony_ciint igb_set_spd_dplx(struct igb_adapter *adapter, u32 spd, u8 dplx) 91218c2ecf20Sopenharmony_ci{ 91228c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 91238c2ecf20Sopenharmony_ci struct e1000_mac_info *mac = &adapter->hw.mac; 91248c2ecf20Sopenharmony_ci 91258c2ecf20Sopenharmony_ci mac->autoneg = 0; 91268c2ecf20Sopenharmony_ci 91278c2ecf20Sopenharmony_ci /* Make sure dplx is at most 1 bit and lsb of speed is not set 91288c2ecf20Sopenharmony_ci * for the switch() below to work 91298c2ecf20Sopenharmony_ci */ 91308c2ecf20Sopenharmony_ci if ((spd & 1) || (dplx & ~1)) 91318c2ecf20Sopenharmony_ci goto err_inval; 91328c2ecf20Sopenharmony_ci 91338c2ecf20Sopenharmony_ci /* Fiber NIC's only allow 1000 gbps Full duplex 91348c2ecf20Sopenharmony_ci * and 100Mbps Full duplex for 100baseFx sfp 91358c2ecf20Sopenharmony_ci */ 91368c2ecf20Sopenharmony_ci if (adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { 91378c2ecf20Sopenharmony_ci switch (spd + dplx) { 91388c2ecf20Sopenharmony_ci case SPEED_10 + DUPLEX_HALF: 91398c2ecf20Sopenharmony_ci case SPEED_10 + DUPLEX_FULL: 91408c2ecf20Sopenharmony_ci case SPEED_100 + DUPLEX_HALF: 91418c2ecf20Sopenharmony_ci goto err_inval; 91428c2ecf20Sopenharmony_ci default: 91438c2ecf20Sopenharmony_ci break; 91448c2ecf20Sopenharmony_ci } 91458c2ecf20Sopenharmony_ci } 91468c2ecf20Sopenharmony_ci 91478c2ecf20Sopenharmony_ci switch (spd + dplx) { 91488c2ecf20Sopenharmony_ci case SPEED_10 + DUPLEX_HALF: 91498c2ecf20Sopenharmony_ci mac->forced_speed_duplex = ADVERTISE_10_HALF; 91508c2ecf20Sopenharmony_ci break; 91518c2ecf20Sopenharmony_ci case SPEED_10 + DUPLEX_FULL: 91528c2ecf20Sopenharmony_ci mac->forced_speed_duplex = ADVERTISE_10_FULL; 91538c2ecf20Sopenharmony_ci break; 91548c2ecf20Sopenharmony_ci case SPEED_100 + DUPLEX_HALF: 91558c2ecf20Sopenharmony_ci mac->forced_speed_duplex = ADVERTISE_100_HALF; 91568c2ecf20Sopenharmony_ci break; 91578c2ecf20Sopenharmony_ci case SPEED_100 + DUPLEX_FULL: 91588c2ecf20Sopenharmony_ci mac->forced_speed_duplex = ADVERTISE_100_FULL; 91598c2ecf20Sopenharmony_ci break; 91608c2ecf20Sopenharmony_ci case SPEED_1000 + DUPLEX_FULL: 91618c2ecf20Sopenharmony_ci mac->autoneg = 1; 91628c2ecf20Sopenharmony_ci adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; 91638c2ecf20Sopenharmony_ci break; 91648c2ecf20Sopenharmony_ci case SPEED_1000 + DUPLEX_HALF: /* not supported */ 91658c2ecf20Sopenharmony_ci default: 91668c2ecf20Sopenharmony_ci goto err_inval; 91678c2ecf20Sopenharmony_ci } 91688c2ecf20Sopenharmony_ci 91698c2ecf20Sopenharmony_ci /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ 91708c2ecf20Sopenharmony_ci adapter->hw.phy.mdix = AUTO_ALL_MODES; 91718c2ecf20Sopenharmony_ci 91728c2ecf20Sopenharmony_ci return 0; 91738c2ecf20Sopenharmony_ci 91748c2ecf20Sopenharmony_cierr_inval: 91758c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n"); 91768c2ecf20Sopenharmony_ci return -EINVAL; 91778c2ecf20Sopenharmony_ci} 91788c2ecf20Sopenharmony_ci 91798c2ecf20Sopenharmony_cistatic int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, 91808c2ecf20Sopenharmony_ci bool runtime) 91818c2ecf20Sopenharmony_ci{ 91828c2ecf20Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 91838c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 91848c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 91858c2ecf20Sopenharmony_ci u32 ctrl, rctl, status; 91868c2ecf20Sopenharmony_ci u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol; 91878c2ecf20Sopenharmony_ci bool wake; 91888c2ecf20Sopenharmony_ci 91898c2ecf20Sopenharmony_ci rtnl_lock(); 91908c2ecf20Sopenharmony_ci netif_device_detach(netdev); 91918c2ecf20Sopenharmony_ci 91928c2ecf20Sopenharmony_ci if (netif_running(netdev)) 91938c2ecf20Sopenharmony_ci __igb_close(netdev, true); 91948c2ecf20Sopenharmony_ci 91958c2ecf20Sopenharmony_ci igb_ptp_suspend(adapter); 91968c2ecf20Sopenharmony_ci 91978c2ecf20Sopenharmony_ci igb_clear_interrupt_scheme(adapter); 91988c2ecf20Sopenharmony_ci rtnl_unlock(); 91998c2ecf20Sopenharmony_ci 92008c2ecf20Sopenharmony_ci status = rd32(E1000_STATUS); 92018c2ecf20Sopenharmony_ci if (status & E1000_STATUS_LU) 92028c2ecf20Sopenharmony_ci wufc &= ~E1000_WUFC_LNKC; 92038c2ecf20Sopenharmony_ci 92048c2ecf20Sopenharmony_ci if (wufc) { 92058c2ecf20Sopenharmony_ci igb_setup_rctl(adapter); 92068c2ecf20Sopenharmony_ci igb_set_rx_mode(netdev); 92078c2ecf20Sopenharmony_ci 92088c2ecf20Sopenharmony_ci /* turn on all-multi mode if wake on multicast is enabled */ 92098c2ecf20Sopenharmony_ci if (wufc & E1000_WUFC_MC) { 92108c2ecf20Sopenharmony_ci rctl = rd32(E1000_RCTL); 92118c2ecf20Sopenharmony_ci rctl |= E1000_RCTL_MPE; 92128c2ecf20Sopenharmony_ci wr32(E1000_RCTL, rctl); 92138c2ecf20Sopenharmony_ci } 92148c2ecf20Sopenharmony_ci 92158c2ecf20Sopenharmony_ci ctrl = rd32(E1000_CTRL); 92168c2ecf20Sopenharmony_ci ctrl |= E1000_CTRL_ADVD3WUC; 92178c2ecf20Sopenharmony_ci wr32(E1000_CTRL, ctrl); 92188c2ecf20Sopenharmony_ci 92198c2ecf20Sopenharmony_ci /* Allow time for pending master requests to run */ 92208c2ecf20Sopenharmony_ci igb_disable_pcie_master(hw); 92218c2ecf20Sopenharmony_ci 92228c2ecf20Sopenharmony_ci wr32(E1000_WUC, E1000_WUC_PME_EN); 92238c2ecf20Sopenharmony_ci wr32(E1000_WUFC, wufc); 92248c2ecf20Sopenharmony_ci } else { 92258c2ecf20Sopenharmony_ci wr32(E1000_WUC, 0); 92268c2ecf20Sopenharmony_ci wr32(E1000_WUFC, 0); 92278c2ecf20Sopenharmony_ci } 92288c2ecf20Sopenharmony_ci 92298c2ecf20Sopenharmony_ci wake = wufc || adapter->en_mng_pt; 92308c2ecf20Sopenharmony_ci if (!wake) 92318c2ecf20Sopenharmony_ci igb_power_down_link(adapter); 92328c2ecf20Sopenharmony_ci else 92338c2ecf20Sopenharmony_ci igb_power_up_link(adapter); 92348c2ecf20Sopenharmony_ci 92358c2ecf20Sopenharmony_ci if (enable_wake) 92368c2ecf20Sopenharmony_ci *enable_wake = wake; 92378c2ecf20Sopenharmony_ci 92388c2ecf20Sopenharmony_ci /* Release control of h/w to f/w. If f/w is AMT enabled, this 92398c2ecf20Sopenharmony_ci * would have already happened in close and is redundant. 92408c2ecf20Sopenharmony_ci */ 92418c2ecf20Sopenharmony_ci igb_release_hw_control(adapter); 92428c2ecf20Sopenharmony_ci 92438c2ecf20Sopenharmony_ci pci_disable_device(pdev); 92448c2ecf20Sopenharmony_ci 92458c2ecf20Sopenharmony_ci return 0; 92468c2ecf20Sopenharmony_ci} 92478c2ecf20Sopenharmony_ci 92488c2ecf20Sopenharmony_cistatic void igb_deliver_wake_packet(struct net_device *netdev) 92498c2ecf20Sopenharmony_ci{ 92508c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 92518c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 92528c2ecf20Sopenharmony_ci struct sk_buff *skb; 92538c2ecf20Sopenharmony_ci u32 wupl; 92548c2ecf20Sopenharmony_ci 92558c2ecf20Sopenharmony_ci wupl = rd32(E1000_WUPL) & E1000_WUPL_MASK; 92568c2ecf20Sopenharmony_ci 92578c2ecf20Sopenharmony_ci /* WUPM stores only the first 128 bytes of the wake packet. 92588c2ecf20Sopenharmony_ci * Read the packet only if we have the whole thing. 92598c2ecf20Sopenharmony_ci */ 92608c2ecf20Sopenharmony_ci if ((wupl == 0) || (wupl > E1000_WUPM_BYTES)) 92618c2ecf20Sopenharmony_ci return; 92628c2ecf20Sopenharmony_ci 92638c2ecf20Sopenharmony_ci skb = netdev_alloc_skb_ip_align(netdev, E1000_WUPM_BYTES); 92648c2ecf20Sopenharmony_ci if (!skb) 92658c2ecf20Sopenharmony_ci return; 92668c2ecf20Sopenharmony_ci 92678c2ecf20Sopenharmony_ci skb_put(skb, wupl); 92688c2ecf20Sopenharmony_ci 92698c2ecf20Sopenharmony_ci /* Ensure reads are 32-bit aligned */ 92708c2ecf20Sopenharmony_ci wupl = roundup(wupl, 4); 92718c2ecf20Sopenharmony_ci 92728c2ecf20Sopenharmony_ci memcpy_fromio(skb->data, hw->hw_addr + E1000_WUPM_REG(0), wupl); 92738c2ecf20Sopenharmony_ci 92748c2ecf20Sopenharmony_ci skb->protocol = eth_type_trans(skb, netdev); 92758c2ecf20Sopenharmony_ci netif_rx(skb); 92768c2ecf20Sopenharmony_ci} 92778c2ecf20Sopenharmony_ci 92788c2ecf20Sopenharmony_cistatic int __maybe_unused igb_suspend(struct device *dev) 92798c2ecf20Sopenharmony_ci{ 92808c2ecf20Sopenharmony_ci return __igb_shutdown(to_pci_dev(dev), NULL, 0); 92818c2ecf20Sopenharmony_ci} 92828c2ecf20Sopenharmony_ci 92838c2ecf20Sopenharmony_cistatic int __maybe_unused __igb_resume(struct device *dev, bool rpm) 92848c2ecf20Sopenharmony_ci{ 92858c2ecf20Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(dev); 92868c2ecf20Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 92878c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 92888c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 92898c2ecf20Sopenharmony_ci u32 err, val; 92908c2ecf20Sopenharmony_ci 92918c2ecf20Sopenharmony_ci pci_set_power_state(pdev, PCI_D0); 92928c2ecf20Sopenharmony_ci pci_restore_state(pdev); 92938c2ecf20Sopenharmony_ci pci_save_state(pdev); 92948c2ecf20Sopenharmony_ci 92958c2ecf20Sopenharmony_ci if (!pci_device_is_present(pdev)) 92968c2ecf20Sopenharmony_ci return -ENODEV; 92978c2ecf20Sopenharmony_ci err = pci_enable_device_mem(pdev); 92988c2ecf20Sopenharmony_ci if (err) { 92998c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 93008c2ecf20Sopenharmony_ci "igb: Cannot enable PCI device from suspend\n"); 93018c2ecf20Sopenharmony_ci return err; 93028c2ecf20Sopenharmony_ci } 93038c2ecf20Sopenharmony_ci pci_set_master(pdev); 93048c2ecf20Sopenharmony_ci 93058c2ecf20Sopenharmony_ci pci_enable_wake(pdev, PCI_D3hot, 0); 93068c2ecf20Sopenharmony_ci pci_enable_wake(pdev, PCI_D3cold, 0); 93078c2ecf20Sopenharmony_ci 93088c2ecf20Sopenharmony_ci if (igb_init_interrupt_scheme(adapter, true)) { 93098c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); 93108c2ecf20Sopenharmony_ci return -ENOMEM; 93118c2ecf20Sopenharmony_ci } 93128c2ecf20Sopenharmony_ci 93138c2ecf20Sopenharmony_ci igb_reset(adapter); 93148c2ecf20Sopenharmony_ci 93158c2ecf20Sopenharmony_ci /* let the f/w know that the h/w is now under the control of the 93168c2ecf20Sopenharmony_ci * driver. 93178c2ecf20Sopenharmony_ci */ 93188c2ecf20Sopenharmony_ci igb_get_hw_control(adapter); 93198c2ecf20Sopenharmony_ci 93208c2ecf20Sopenharmony_ci val = rd32(E1000_WUS); 93218c2ecf20Sopenharmony_ci if (val & WAKE_PKT_WUS) 93228c2ecf20Sopenharmony_ci igb_deliver_wake_packet(netdev); 93238c2ecf20Sopenharmony_ci 93248c2ecf20Sopenharmony_ci wr32(E1000_WUS, ~0); 93258c2ecf20Sopenharmony_ci 93268c2ecf20Sopenharmony_ci if (!rpm) 93278c2ecf20Sopenharmony_ci rtnl_lock(); 93288c2ecf20Sopenharmony_ci if (!err && netif_running(netdev)) 93298c2ecf20Sopenharmony_ci err = __igb_open(netdev, true); 93308c2ecf20Sopenharmony_ci 93318c2ecf20Sopenharmony_ci if (!err) 93328c2ecf20Sopenharmony_ci netif_device_attach(netdev); 93338c2ecf20Sopenharmony_ci if (!rpm) 93348c2ecf20Sopenharmony_ci rtnl_unlock(); 93358c2ecf20Sopenharmony_ci 93368c2ecf20Sopenharmony_ci return err; 93378c2ecf20Sopenharmony_ci} 93388c2ecf20Sopenharmony_ci 93398c2ecf20Sopenharmony_cistatic int __maybe_unused igb_resume(struct device *dev) 93408c2ecf20Sopenharmony_ci{ 93418c2ecf20Sopenharmony_ci return __igb_resume(dev, false); 93428c2ecf20Sopenharmony_ci} 93438c2ecf20Sopenharmony_ci 93448c2ecf20Sopenharmony_cistatic int __maybe_unused igb_runtime_idle(struct device *dev) 93458c2ecf20Sopenharmony_ci{ 93468c2ecf20Sopenharmony_ci struct net_device *netdev = dev_get_drvdata(dev); 93478c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 93488c2ecf20Sopenharmony_ci 93498c2ecf20Sopenharmony_ci if (!igb_has_link(adapter)) 93508c2ecf20Sopenharmony_ci pm_schedule_suspend(dev, MSEC_PER_SEC * 5); 93518c2ecf20Sopenharmony_ci 93528c2ecf20Sopenharmony_ci return -EBUSY; 93538c2ecf20Sopenharmony_ci} 93548c2ecf20Sopenharmony_ci 93558c2ecf20Sopenharmony_cistatic int __maybe_unused igb_runtime_suspend(struct device *dev) 93568c2ecf20Sopenharmony_ci{ 93578c2ecf20Sopenharmony_ci return __igb_shutdown(to_pci_dev(dev), NULL, 1); 93588c2ecf20Sopenharmony_ci} 93598c2ecf20Sopenharmony_ci 93608c2ecf20Sopenharmony_cistatic int __maybe_unused igb_runtime_resume(struct device *dev) 93618c2ecf20Sopenharmony_ci{ 93628c2ecf20Sopenharmony_ci return __igb_resume(dev, true); 93638c2ecf20Sopenharmony_ci} 93648c2ecf20Sopenharmony_ci 93658c2ecf20Sopenharmony_cistatic void igb_shutdown(struct pci_dev *pdev) 93668c2ecf20Sopenharmony_ci{ 93678c2ecf20Sopenharmony_ci bool wake; 93688c2ecf20Sopenharmony_ci 93698c2ecf20Sopenharmony_ci __igb_shutdown(pdev, &wake, 0); 93708c2ecf20Sopenharmony_ci 93718c2ecf20Sopenharmony_ci if (system_state == SYSTEM_POWER_OFF) { 93728c2ecf20Sopenharmony_ci pci_wake_from_d3(pdev, wake); 93738c2ecf20Sopenharmony_ci pci_set_power_state(pdev, PCI_D3hot); 93748c2ecf20Sopenharmony_ci } 93758c2ecf20Sopenharmony_ci} 93768c2ecf20Sopenharmony_ci 93778c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 93788c2ecf20Sopenharmony_cistatic int igb_sriov_reinit(struct pci_dev *dev) 93798c2ecf20Sopenharmony_ci{ 93808c2ecf20Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(dev); 93818c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 93828c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 93838c2ecf20Sopenharmony_ci 93848c2ecf20Sopenharmony_ci rtnl_lock(); 93858c2ecf20Sopenharmony_ci 93868c2ecf20Sopenharmony_ci if (netif_running(netdev)) 93878c2ecf20Sopenharmony_ci igb_close(netdev); 93888c2ecf20Sopenharmony_ci else 93898c2ecf20Sopenharmony_ci igb_reset(adapter); 93908c2ecf20Sopenharmony_ci 93918c2ecf20Sopenharmony_ci igb_clear_interrupt_scheme(adapter); 93928c2ecf20Sopenharmony_ci 93938c2ecf20Sopenharmony_ci igb_init_queue_configuration(adapter); 93948c2ecf20Sopenharmony_ci 93958c2ecf20Sopenharmony_ci if (igb_init_interrupt_scheme(adapter, true)) { 93968c2ecf20Sopenharmony_ci rtnl_unlock(); 93978c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); 93988c2ecf20Sopenharmony_ci return -ENOMEM; 93998c2ecf20Sopenharmony_ci } 94008c2ecf20Sopenharmony_ci 94018c2ecf20Sopenharmony_ci if (netif_running(netdev)) 94028c2ecf20Sopenharmony_ci igb_open(netdev); 94038c2ecf20Sopenharmony_ci 94048c2ecf20Sopenharmony_ci rtnl_unlock(); 94058c2ecf20Sopenharmony_ci 94068c2ecf20Sopenharmony_ci return 0; 94078c2ecf20Sopenharmony_ci} 94088c2ecf20Sopenharmony_ci 94098c2ecf20Sopenharmony_cistatic int igb_pci_disable_sriov(struct pci_dev *dev) 94108c2ecf20Sopenharmony_ci{ 94118c2ecf20Sopenharmony_ci int err = igb_disable_sriov(dev); 94128c2ecf20Sopenharmony_ci 94138c2ecf20Sopenharmony_ci if (!err) 94148c2ecf20Sopenharmony_ci err = igb_sriov_reinit(dev); 94158c2ecf20Sopenharmony_ci 94168c2ecf20Sopenharmony_ci return err; 94178c2ecf20Sopenharmony_ci} 94188c2ecf20Sopenharmony_ci 94198c2ecf20Sopenharmony_cistatic int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs) 94208c2ecf20Sopenharmony_ci{ 94218c2ecf20Sopenharmony_ci int err = igb_enable_sriov(dev, num_vfs); 94228c2ecf20Sopenharmony_ci 94238c2ecf20Sopenharmony_ci if (err) 94248c2ecf20Sopenharmony_ci goto out; 94258c2ecf20Sopenharmony_ci 94268c2ecf20Sopenharmony_ci err = igb_sriov_reinit(dev); 94278c2ecf20Sopenharmony_ci if (!err) 94288c2ecf20Sopenharmony_ci return num_vfs; 94298c2ecf20Sopenharmony_ci 94308c2ecf20Sopenharmony_ciout: 94318c2ecf20Sopenharmony_ci return err; 94328c2ecf20Sopenharmony_ci} 94338c2ecf20Sopenharmony_ci 94348c2ecf20Sopenharmony_ci#endif 94358c2ecf20Sopenharmony_cistatic int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs) 94368c2ecf20Sopenharmony_ci{ 94378c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 94388c2ecf20Sopenharmony_ci if (num_vfs == 0) 94398c2ecf20Sopenharmony_ci return igb_pci_disable_sriov(dev); 94408c2ecf20Sopenharmony_ci else 94418c2ecf20Sopenharmony_ci return igb_pci_enable_sriov(dev, num_vfs); 94428c2ecf20Sopenharmony_ci#endif 94438c2ecf20Sopenharmony_ci return 0; 94448c2ecf20Sopenharmony_ci} 94458c2ecf20Sopenharmony_ci 94468c2ecf20Sopenharmony_ci/** 94478c2ecf20Sopenharmony_ci * igb_io_error_detected - called when PCI error is detected 94488c2ecf20Sopenharmony_ci * @pdev: Pointer to PCI device 94498c2ecf20Sopenharmony_ci * @state: The current pci connection state 94508c2ecf20Sopenharmony_ci * 94518c2ecf20Sopenharmony_ci * This function is called after a PCI bus error affecting 94528c2ecf20Sopenharmony_ci * this device has been detected. 94538c2ecf20Sopenharmony_ci **/ 94548c2ecf20Sopenharmony_cistatic pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev, 94558c2ecf20Sopenharmony_ci pci_channel_state_t state) 94568c2ecf20Sopenharmony_ci{ 94578c2ecf20Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 94588c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 94598c2ecf20Sopenharmony_ci 94608c2ecf20Sopenharmony_ci if (state == pci_channel_io_normal) { 94618c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, "Non-correctable non-fatal error reported.\n"); 94628c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_CAN_RECOVER; 94638c2ecf20Sopenharmony_ci } 94648c2ecf20Sopenharmony_ci 94658c2ecf20Sopenharmony_ci netif_device_detach(netdev); 94668c2ecf20Sopenharmony_ci 94678c2ecf20Sopenharmony_ci if (state == pci_channel_io_perm_failure) 94688c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_DISCONNECT; 94698c2ecf20Sopenharmony_ci 94708c2ecf20Sopenharmony_ci if (netif_running(netdev)) 94718c2ecf20Sopenharmony_ci igb_down(adapter); 94728c2ecf20Sopenharmony_ci pci_disable_device(pdev); 94738c2ecf20Sopenharmony_ci 94748c2ecf20Sopenharmony_ci /* Request a slot slot reset. */ 94758c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_NEED_RESET; 94768c2ecf20Sopenharmony_ci} 94778c2ecf20Sopenharmony_ci 94788c2ecf20Sopenharmony_ci/** 94798c2ecf20Sopenharmony_ci * igb_io_slot_reset - called after the pci bus has been reset. 94808c2ecf20Sopenharmony_ci * @pdev: Pointer to PCI device 94818c2ecf20Sopenharmony_ci * 94828c2ecf20Sopenharmony_ci * Restart the card from scratch, as if from a cold-boot. Implementation 94838c2ecf20Sopenharmony_ci * resembles the first-half of the __igb_resume routine. 94848c2ecf20Sopenharmony_ci **/ 94858c2ecf20Sopenharmony_cistatic pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) 94868c2ecf20Sopenharmony_ci{ 94878c2ecf20Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 94888c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 94898c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 94908c2ecf20Sopenharmony_ci pci_ers_result_t result; 94918c2ecf20Sopenharmony_ci 94928c2ecf20Sopenharmony_ci if (pci_enable_device_mem(pdev)) { 94938c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 94948c2ecf20Sopenharmony_ci "Cannot re-enable PCI device after reset.\n"); 94958c2ecf20Sopenharmony_ci result = PCI_ERS_RESULT_DISCONNECT; 94968c2ecf20Sopenharmony_ci } else { 94978c2ecf20Sopenharmony_ci pci_set_master(pdev); 94988c2ecf20Sopenharmony_ci pci_restore_state(pdev); 94998c2ecf20Sopenharmony_ci pci_save_state(pdev); 95008c2ecf20Sopenharmony_ci 95018c2ecf20Sopenharmony_ci pci_enable_wake(pdev, PCI_D3hot, 0); 95028c2ecf20Sopenharmony_ci pci_enable_wake(pdev, PCI_D3cold, 0); 95038c2ecf20Sopenharmony_ci 95048c2ecf20Sopenharmony_ci /* In case of PCI error, adapter lose its HW address 95058c2ecf20Sopenharmony_ci * so we should re-assign it here. 95068c2ecf20Sopenharmony_ci */ 95078c2ecf20Sopenharmony_ci hw->hw_addr = adapter->io_addr; 95088c2ecf20Sopenharmony_ci 95098c2ecf20Sopenharmony_ci igb_reset(adapter); 95108c2ecf20Sopenharmony_ci wr32(E1000_WUS, ~0); 95118c2ecf20Sopenharmony_ci result = PCI_ERS_RESULT_RECOVERED; 95128c2ecf20Sopenharmony_ci } 95138c2ecf20Sopenharmony_ci 95148c2ecf20Sopenharmony_ci return result; 95158c2ecf20Sopenharmony_ci} 95168c2ecf20Sopenharmony_ci 95178c2ecf20Sopenharmony_ci/** 95188c2ecf20Sopenharmony_ci * igb_io_resume - called when traffic can start flowing again. 95198c2ecf20Sopenharmony_ci * @pdev: Pointer to PCI device 95208c2ecf20Sopenharmony_ci * 95218c2ecf20Sopenharmony_ci * This callback is called when the error recovery driver tells us that 95228c2ecf20Sopenharmony_ci * its OK to resume normal operation. Implementation resembles the 95238c2ecf20Sopenharmony_ci * second-half of the __igb_resume routine. 95248c2ecf20Sopenharmony_ci */ 95258c2ecf20Sopenharmony_cistatic void igb_io_resume(struct pci_dev *pdev) 95268c2ecf20Sopenharmony_ci{ 95278c2ecf20Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 95288c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 95298c2ecf20Sopenharmony_ci 95308c2ecf20Sopenharmony_ci if (netif_running(netdev)) { 95318c2ecf20Sopenharmony_ci if (igb_up(adapter)) { 95328c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "igb_up failed after reset\n"); 95338c2ecf20Sopenharmony_ci return; 95348c2ecf20Sopenharmony_ci } 95358c2ecf20Sopenharmony_ci } 95368c2ecf20Sopenharmony_ci 95378c2ecf20Sopenharmony_ci netif_device_attach(netdev); 95388c2ecf20Sopenharmony_ci 95398c2ecf20Sopenharmony_ci /* let the f/w know that the h/w is now under the control of the 95408c2ecf20Sopenharmony_ci * driver. 95418c2ecf20Sopenharmony_ci */ 95428c2ecf20Sopenharmony_ci igb_get_hw_control(adapter); 95438c2ecf20Sopenharmony_ci} 95448c2ecf20Sopenharmony_ci 95458c2ecf20Sopenharmony_ci/** 95468c2ecf20Sopenharmony_ci * igb_rar_set_index - Sync RAL[index] and RAH[index] registers with MAC table 95478c2ecf20Sopenharmony_ci * @adapter: Pointer to adapter structure 95488c2ecf20Sopenharmony_ci * @index: Index of the RAR entry which need to be synced with MAC table 95498c2ecf20Sopenharmony_ci **/ 95508c2ecf20Sopenharmony_cistatic void igb_rar_set_index(struct igb_adapter *adapter, u32 index) 95518c2ecf20Sopenharmony_ci{ 95528c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 95538c2ecf20Sopenharmony_ci u32 rar_low, rar_high; 95548c2ecf20Sopenharmony_ci u8 *addr = adapter->mac_table[index].addr; 95558c2ecf20Sopenharmony_ci 95568c2ecf20Sopenharmony_ci /* HW expects these to be in network order when they are plugged 95578c2ecf20Sopenharmony_ci * into the registers which are little endian. In order to guarantee 95588c2ecf20Sopenharmony_ci * that ordering we need to do an leXX_to_cpup here in order to be 95598c2ecf20Sopenharmony_ci * ready for the byteswap that occurs with writel 95608c2ecf20Sopenharmony_ci */ 95618c2ecf20Sopenharmony_ci rar_low = le32_to_cpup((__le32 *)(addr)); 95628c2ecf20Sopenharmony_ci rar_high = le16_to_cpup((__le16 *)(addr + 4)); 95638c2ecf20Sopenharmony_ci 95648c2ecf20Sopenharmony_ci /* Indicate to hardware the Address is Valid. */ 95658c2ecf20Sopenharmony_ci if (adapter->mac_table[index].state & IGB_MAC_STATE_IN_USE) { 95668c2ecf20Sopenharmony_ci if (is_valid_ether_addr(addr)) 95678c2ecf20Sopenharmony_ci rar_high |= E1000_RAH_AV; 95688c2ecf20Sopenharmony_ci 95698c2ecf20Sopenharmony_ci if (adapter->mac_table[index].state & IGB_MAC_STATE_SRC_ADDR) 95708c2ecf20Sopenharmony_ci rar_high |= E1000_RAH_ASEL_SRC_ADDR; 95718c2ecf20Sopenharmony_ci 95728c2ecf20Sopenharmony_ci switch (hw->mac.type) { 95738c2ecf20Sopenharmony_ci case e1000_82575: 95748c2ecf20Sopenharmony_ci case e1000_i210: 95758c2ecf20Sopenharmony_ci if (adapter->mac_table[index].state & 95768c2ecf20Sopenharmony_ci IGB_MAC_STATE_QUEUE_STEERING) 95778c2ecf20Sopenharmony_ci rar_high |= E1000_RAH_QSEL_ENABLE; 95788c2ecf20Sopenharmony_ci 95798c2ecf20Sopenharmony_ci rar_high |= E1000_RAH_POOL_1 * 95808c2ecf20Sopenharmony_ci adapter->mac_table[index].queue; 95818c2ecf20Sopenharmony_ci break; 95828c2ecf20Sopenharmony_ci default: 95838c2ecf20Sopenharmony_ci rar_high |= E1000_RAH_POOL_1 << 95848c2ecf20Sopenharmony_ci adapter->mac_table[index].queue; 95858c2ecf20Sopenharmony_ci break; 95868c2ecf20Sopenharmony_ci } 95878c2ecf20Sopenharmony_ci } 95888c2ecf20Sopenharmony_ci 95898c2ecf20Sopenharmony_ci wr32(E1000_RAL(index), rar_low); 95908c2ecf20Sopenharmony_ci wrfl(); 95918c2ecf20Sopenharmony_ci wr32(E1000_RAH(index), rar_high); 95928c2ecf20Sopenharmony_ci wrfl(); 95938c2ecf20Sopenharmony_ci} 95948c2ecf20Sopenharmony_ci 95958c2ecf20Sopenharmony_cistatic int igb_set_vf_mac(struct igb_adapter *adapter, 95968c2ecf20Sopenharmony_ci int vf, unsigned char *mac_addr) 95978c2ecf20Sopenharmony_ci{ 95988c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 95998c2ecf20Sopenharmony_ci /* VF MAC addresses start at end of receive addresses and moves 96008c2ecf20Sopenharmony_ci * towards the first, as a result a collision should not be possible 96018c2ecf20Sopenharmony_ci */ 96028c2ecf20Sopenharmony_ci int rar_entry = hw->mac.rar_entry_count - (vf + 1); 96038c2ecf20Sopenharmony_ci unsigned char *vf_mac_addr = adapter->vf_data[vf].vf_mac_addresses; 96048c2ecf20Sopenharmony_ci 96058c2ecf20Sopenharmony_ci ether_addr_copy(vf_mac_addr, mac_addr); 96068c2ecf20Sopenharmony_ci ether_addr_copy(adapter->mac_table[rar_entry].addr, mac_addr); 96078c2ecf20Sopenharmony_ci adapter->mac_table[rar_entry].queue = vf; 96088c2ecf20Sopenharmony_ci adapter->mac_table[rar_entry].state |= IGB_MAC_STATE_IN_USE; 96098c2ecf20Sopenharmony_ci igb_rar_set_index(adapter, rar_entry); 96108c2ecf20Sopenharmony_ci 96118c2ecf20Sopenharmony_ci return 0; 96128c2ecf20Sopenharmony_ci} 96138c2ecf20Sopenharmony_ci 96148c2ecf20Sopenharmony_cistatic int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) 96158c2ecf20Sopenharmony_ci{ 96168c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 96178c2ecf20Sopenharmony_ci 96188c2ecf20Sopenharmony_ci if (vf >= adapter->vfs_allocated_count) 96198c2ecf20Sopenharmony_ci return -EINVAL; 96208c2ecf20Sopenharmony_ci 96218c2ecf20Sopenharmony_ci /* Setting the VF MAC to 0 reverts the IGB_VF_FLAG_PF_SET_MAC 96228c2ecf20Sopenharmony_ci * flag and allows to overwrite the MAC via VF netdev. This 96238c2ecf20Sopenharmony_ci * is necessary to allow libvirt a way to restore the original 96248c2ecf20Sopenharmony_ci * MAC after unbinding vfio-pci and reloading igbvf after shutting 96258c2ecf20Sopenharmony_ci * down a VM. 96268c2ecf20Sopenharmony_ci */ 96278c2ecf20Sopenharmony_ci if (is_zero_ether_addr(mac)) { 96288c2ecf20Sopenharmony_ci adapter->vf_data[vf].flags &= ~IGB_VF_FLAG_PF_SET_MAC; 96298c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, 96308c2ecf20Sopenharmony_ci "remove administratively set MAC on VF %d\n", 96318c2ecf20Sopenharmony_ci vf); 96328c2ecf20Sopenharmony_ci } else if (is_valid_ether_addr(mac)) { 96338c2ecf20Sopenharmony_ci adapter->vf_data[vf].flags |= IGB_VF_FLAG_PF_SET_MAC; 96348c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n", 96358c2ecf20Sopenharmony_ci mac, vf); 96368c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, 96378c2ecf20Sopenharmony_ci "Reload the VF driver to make this change effective."); 96388c2ecf20Sopenharmony_ci /* Generate additional warning if PF is down */ 96398c2ecf20Sopenharmony_ci if (test_bit(__IGB_DOWN, &adapter->state)) { 96408c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, 96418c2ecf20Sopenharmony_ci "The VF MAC address has been set, but the PF device is not up.\n"); 96428c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, 96438c2ecf20Sopenharmony_ci "Bring the PF device up before attempting to use the VF device.\n"); 96448c2ecf20Sopenharmony_ci } 96458c2ecf20Sopenharmony_ci } else { 96468c2ecf20Sopenharmony_ci return -EINVAL; 96478c2ecf20Sopenharmony_ci } 96488c2ecf20Sopenharmony_ci return igb_set_vf_mac(adapter, vf, mac); 96498c2ecf20Sopenharmony_ci} 96508c2ecf20Sopenharmony_ci 96518c2ecf20Sopenharmony_cistatic int igb_link_mbps(int internal_link_speed) 96528c2ecf20Sopenharmony_ci{ 96538c2ecf20Sopenharmony_ci switch (internal_link_speed) { 96548c2ecf20Sopenharmony_ci case SPEED_100: 96558c2ecf20Sopenharmony_ci return 100; 96568c2ecf20Sopenharmony_ci case SPEED_1000: 96578c2ecf20Sopenharmony_ci return 1000; 96588c2ecf20Sopenharmony_ci default: 96598c2ecf20Sopenharmony_ci return 0; 96608c2ecf20Sopenharmony_ci } 96618c2ecf20Sopenharmony_ci} 96628c2ecf20Sopenharmony_ci 96638c2ecf20Sopenharmony_cistatic void igb_set_vf_rate_limit(struct e1000_hw *hw, int vf, int tx_rate, 96648c2ecf20Sopenharmony_ci int link_speed) 96658c2ecf20Sopenharmony_ci{ 96668c2ecf20Sopenharmony_ci int rf_dec, rf_int; 96678c2ecf20Sopenharmony_ci u32 bcnrc_val; 96688c2ecf20Sopenharmony_ci 96698c2ecf20Sopenharmony_ci if (tx_rate != 0) { 96708c2ecf20Sopenharmony_ci /* Calculate the rate factor values to set */ 96718c2ecf20Sopenharmony_ci rf_int = link_speed / tx_rate; 96728c2ecf20Sopenharmony_ci rf_dec = (link_speed - (rf_int * tx_rate)); 96738c2ecf20Sopenharmony_ci rf_dec = (rf_dec * BIT(E1000_RTTBCNRC_RF_INT_SHIFT)) / 96748c2ecf20Sopenharmony_ci tx_rate; 96758c2ecf20Sopenharmony_ci 96768c2ecf20Sopenharmony_ci bcnrc_val = E1000_RTTBCNRC_RS_ENA; 96778c2ecf20Sopenharmony_ci bcnrc_val |= ((rf_int << E1000_RTTBCNRC_RF_INT_SHIFT) & 96788c2ecf20Sopenharmony_ci E1000_RTTBCNRC_RF_INT_MASK); 96798c2ecf20Sopenharmony_ci bcnrc_val |= (rf_dec & E1000_RTTBCNRC_RF_DEC_MASK); 96808c2ecf20Sopenharmony_ci } else { 96818c2ecf20Sopenharmony_ci bcnrc_val = 0; 96828c2ecf20Sopenharmony_ci } 96838c2ecf20Sopenharmony_ci 96848c2ecf20Sopenharmony_ci wr32(E1000_RTTDQSEL, vf); /* vf X uses queue X */ 96858c2ecf20Sopenharmony_ci /* Set global transmit compensation time to the MMW_SIZE in RTTBCNRM 96868c2ecf20Sopenharmony_ci * register. MMW_SIZE=0x014 if 9728-byte jumbo is supported. 96878c2ecf20Sopenharmony_ci */ 96888c2ecf20Sopenharmony_ci wr32(E1000_RTTBCNRM, 0x14); 96898c2ecf20Sopenharmony_ci wr32(E1000_RTTBCNRC, bcnrc_val); 96908c2ecf20Sopenharmony_ci} 96918c2ecf20Sopenharmony_ci 96928c2ecf20Sopenharmony_cistatic void igb_check_vf_rate_limit(struct igb_adapter *adapter) 96938c2ecf20Sopenharmony_ci{ 96948c2ecf20Sopenharmony_ci int actual_link_speed, i; 96958c2ecf20Sopenharmony_ci bool reset_rate = false; 96968c2ecf20Sopenharmony_ci 96978c2ecf20Sopenharmony_ci /* VF TX rate limit was not set or not supported */ 96988c2ecf20Sopenharmony_ci if ((adapter->vf_rate_link_speed == 0) || 96998c2ecf20Sopenharmony_ci (adapter->hw.mac.type != e1000_82576)) 97008c2ecf20Sopenharmony_ci return; 97018c2ecf20Sopenharmony_ci 97028c2ecf20Sopenharmony_ci actual_link_speed = igb_link_mbps(adapter->link_speed); 97038c2ecf20Sopenharmony_ci if (actual_link_speed != adapter->vf_rate_link_speed) { 97048c2ecf20Sopenharmony_ci reset_rate = true; 97058c2ecf20Sopenharmony_ci adapter->vf_rate_link_speed = 0; 97068c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, 97078c2ecf20Sopenharmony_ci "Link speed has been changed. VF Transmit rate is disabled\n"); 97088c2ecf20Sopenharmony_ci } 97098c2ecf20Sopenharmony_ci 97108c2ecf20Sopenharmony_ci for (i = 0; i < adapter->vfs_allocated_count; i++) { 97118c2ecf20Sopenharmony_ci if (reset_rate) 97128c2ecf20Sopenharmony_ci adapter->vf_data[i].tx_rate = 0; 97138c2ecf20Sopenharmony_ci 97148c2ecf20Sopenharmony_ci igb_set_vf_rate_limit(&adapter->hw, i, 97158c2ecf20Sopenharmony_ci adapter->vf_data[i].tx_rate, 97168c2ecf20Sopenharmony_ci actual_link_speed); 97178c2ecf20Sopenharmony_ci } 97188c2ecf20Sopenharmony_ci} 97198c2ecf20Sopenharmony_ci 97208c2ecf20Sopenharmony_cistatic int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, 97218c2ecf20Sopenharmony_ci int min_tx_rate, int max_tx_rate) 97228c2ecf20Sopenharmony_ci{ 97238c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 97248c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 97258c2ecf20Sopenharmony_ci int actual_link_speed; 97268c2ecf20Sopenharmony_ci 97278c2ecf20Sopenharmony_ci if (hw->mac.type != e1000_82576) 97288c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 97298c2ecf20Sopenharmony_ci 97308c2ecf20Sopenharmony_ci if (min_tx_rate) 97318c2ecf20Sopenharmony_ci return -EINVAL; 97328c2ecf20Sopenharmony_ci 97338c2ecf20Sopenharmony_ci actual_link_speed = igb_link_mbps(adapter->link_speed); 97348c2ecf20Sopenharmony_ci if ((vf >= adapter->vfs_allocated_count) || 97358c2ecf20Sopenharmony_ci (!(rd32(E1000_STATUS) & E1000_STATUS_LU)) || 97368c2ecf20Sopenharmony_ci (max_tx_rate < 0) || 97378c2ecf20Sopenharmony_ci (max_tx_rate > actual_link_speed)) 97388c2ecf20Sopenharmony_ci return -EINVAL; 97398c2ecf20Sopenharmony_ci 97408c2ecf20Sopenharmony_ci adapter->vf_rate_link_speed = actual_link_speed; 97418c2ecf20Sopenharmony_ci adapter->vf_data[vf].tx_rate = (u16)max_tx_rate; 97428c2ecf20Sopenharmony_ci igb_set_vf_rate_limit(hw, vf, max_tx_rate, actual_link_speed); 97438c2ecf20Sopenharmony_ci 97448c2ecf20Sopenharmony_ci return 0; 97458c2ecf20Sopenharmony_ci} 97468c2ecf20Sopenharmony_ci 97478c2ecf20Sopenharmony_cistatic int igb_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, 97488c2ecf20Sopenharmony_ci bool setting) 97498c2ecf20Sopenharmony_ci{ 97508c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 97518c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 97528c2ecf20Sopenharmony_ci u32 reg_val, reg_offset; 97538c2ecf20Sopenharmony_ci 97548c2ecf20Sopenharmony_ci if (!adapter->vfs_allocated_count) 97558c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 97568c2ecf20Sopenharmony_ci 97578c2ecf20Sopenharmony_ci if (vf >= adapter->vfs_allocated_count) 97588c2ecf20Sopenharmony_ci return -EINVAL; 97598c2ecf20Sopenharmony_ci 97608c2ecf20Sopenharmony_ci reg_offset = (hw->mac.type == e1000_82576) ? E1000_DTXSWC : E1000_TXSWC; 97618c2ecf20Sopenharmony_ci reg_val = rd32(reg_offset); 97628c2ecf20Sopenharmony_ci if (setting) 97638c2ecf20Sopenharmony_ci reg_val |= (BIT(vf) | 97648c2ecf20Sopenharmony_ci BIT(vf + E1000_DTXSWC_VLAN_SPOOF_SHIFT)); 97658c2ecf20Sopenharmony_ci else 97668c2ecf20Sopenharmony_ci reg_val &= ~(BIT(vf) | 97678c2ecf20Sopenharmony_ci BIT(vf + E1000_DTXSWC_VLAN_SPOOF_SHIFT)); 97688c2ecf20Sopenharmony_ci wr32(reg_offset, reg_val); 97698c2ecf20Sopenharmony_ci 97708c2ecf20Sopenharmony_ci adapter->vf_data[vf].spoofchk_enabled = setting; 97718c2ecf20Sopenharmony_ci return 0; 97728c2ecf20Sopenharmony_ci} 97738c2ecf20Sopenharmony_ci 97748c2ecf20Sopenharmony_cistatic int igb_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting) 97758c2ecf20Sopenharmony_ci{ 97768c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 97778c2ecf20Sopenharmony_ci 97788c2ecf20Sopenharmony_ci if (vf >= adapter->vfs_allocated_count) 97798c2ecf20Sopenharmony_ci return -EINVAL; 97808c2ecf20Sopenharmony_ci if (adapter->vf_data[vf].trusted == setting) 97818c2ecf20Sopenharmony_ci return 0; 97828c2ecf20Sopenharmony_ci 97838c2ecf20Sopenharmony_ci adapter->vf_data[vf].trusted = setting; 97848c2ecf20Sopenharmony_ci 97858c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, "VF %u is %strusted\n", 97868c2ecf20Sopenharmony_ci vf, setting ? "" : "not "); 97878c2ecf20Sopenharmony_ci return 0; 97888c2ecf20Sopenharmony_ci} 97898c2ecf20Sopenharmony_ci 97908c2ecf20Sopenharmony_cistatic int igb_ndo_get_vf_config(struct net_device *netdev, 97918c2ecf20Sopenharmony_ci int vf, struct ifla_vf_info *ivi) 97928c2ecf20Sopenharmony_ci{ 97938c2ecf20Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 97948c2ecf20Sopenharmony_ci if (vf >= adapter->vfs_allocated_count) 97958c2ecf20Sopenharmony_ci return -EINVAL; 97968c2ecf20Sopenharmony_ci ivi->vf = vf; 97978c2ecf20Sopenharmony_ci memcpy(&ivi->mac, adapter->vf_data[vf].vf_mac_addresses, ETH_ALEN); 97988c2ecf20Sopenharmony_ci ivi->max_tx_rate = adapter->vf_data[vf].tx_rate; 97998c2ecf20Sopenharmony_ci ivi->min_tx_rate = 0; 98008c2ecf20Sopenharmony_ci ivi->vlan = adapter->vf_data[vf].pf_vlan; 98018c2ecf20Sopenharmony_ci ivi->qos = adapter->vf_data[vf].pf_qos; 98028c2ecf20Sopenharmony_ci ivi->spoofchk = adapter->vf_data[vf].spoofchk_enabled; 98038c2ecf20Sopenharmony_ci ivi->trusted = adapter->vf_data[vf].trusted; 98048c2ecf20Sopenharmony_ci return 0; 98058c2ecf20Sopenharmony_ci} 98068c2ecf20Sopenharmony_ci 98078c2ecf20Sopenharmony_cistatic void igb_vmm_control(struct igb_adapter *adapter) 98088c2ecf20Sopenharmony_ci{ 98098c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 98108c2ecf20Sopenharmony_ci u32 reg; 98118c2ecf20Sopenharmony_ci 98128c2ecf20Sopenharmony_ci switch (hw->mac.type) { 98138c2ecf20Sopenharmony_ci case e1000_82575: 98148c2ecf20Sopenharmony_ci case e1000_i210: 98158c2ecf20Sopenharmony_ci case e1000_i211: 98168c2ecf20Sopenharmony_ci case e1000_i354: 98178c2ecf20Sopenharmony_ci default: 98188c2ecf20Sopenharmony_ci /* replication is not supported for 82575 */ 98198c2ecf20Sopenharmony_ci return; 98208c2ecf20Sopenharmony_ci case e1000_82576: 98218c2ecf20Sopenharmony_ci /* notify HW that the MAC is adding vlan tags */ 98228c2ecf20Sopenharmony_ci reg = rd32(E1000_DTXCTL); 98238c2ecf20Sopenharmony_ci reg |= E1000_DTXCTL_VLAN_ADDED; 98248c2ecf20Sopenharmony_ci wr32(E1000_DTXCTL, reg); 98258c2ecf20Sopenharmony_ci fallthrough; 98268c2ecf20Sopenharmony_ci case e1000_82580: 98278c2ecf20Sopenharmony_ci /* enable replication vlan tag stripping */ 98288c2ecf20Sopenharmony_ci reg = rd32(E1000_RPLOLR); 98298c2ecf20Sopenharmony_ci reg |= E1000_RPLOLR_STRVLAN; 98308c2ecf20Sopenharmony_ci wr32(E1000_RPLOLR, reg); 98318c2ecf20Sopenharmony_ci fallthrough; 98328c2ecf20Sopenharmony_ci case e1000_i350: 98338c2ecf20Sopenharmony_ci /* none of the above registers are supported by i350 */ 98348c2ecf20Sopenharmony_ci break; 98358c2ecf20Sopenharmony_ci } 98368c2ecf20Sopenharmony_ci 98378c2ecf20Sopenharmony_ci if (adapter->vfs_allocated_count) { 98388c2ecf20Sopenharmony_ci igb_vmdq_set_loopback_pf(hw, true); 98398c2ecf20Sopenharmony_ci igb_vmdq_set_replication_pf(hw, true); 98408c2ecf20Sopenharmony_ci igb_vmdq_set_anti_spoofing_pf(hw, true, 98418c2ecf20Sopenharmony_ci adapter->vfs_allocated_count); 98428c2ecf20Sopenharmony_ci } else { 98438c2ecf20Sopenharmony_ci igb_vmdq_set_loopback_pf(hw, false); 98448c2ecf20Sopenharmony_ci igb_vmdq_set_replication_pf(hw, false); 98458c2ecf20Sopenharmony_ci } 98468c2ecf20Sopenharmony_ci} 98478c2ecf20Sopenharmony_ci 98488c2ecf20Sopenharmony_cistatic void igb_init_dmac(struct igb_adapter *adapter, u32 pba) 98498c2ecf20Sopenharmony_ci{ 98508c2ecf20Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 98518c2ecf20Sopenharmony_ci u32 dmac_thr; 98528c2ecf20Sopenharmony_ci u16 hwm; 98538c2ecf20Sopenharmony_ci u32 reg; 98548c2ecf20Sopenharmony_ci 98558c2ecf20Sopenharmony_ci if (hw->mac.type > e1000_82580) { 98568c2ecf20Sopenharmony_ci if (adapter->flags & IGB_FLAG_DMAC) { 98578c2ecf20Sopenharmony_ci /* force threshold to 0. */ 98588c2ecf20Sopenharmony_ci wr32(E1000_DMCTXTH, 0); 98598c2ecf20Sopenharmony_ci 98608c2ecf20Sopenharmony_ci /* DMA Coalescing high water mark needs to be greater 98618c2ecf20Sopenharmony_ci * than the Rx threshold. Set hwm to PBA - max frame 98628c2ecf20Sopenharmony_ci * size in 16B units, capping it at PBA - 6KB. 98638c2ecf20Sopenharmony_ci */ 98648c2ecf20Sopenharmony_ci hwm = 64 * (pba - 6); 98658c2ecf20Sopenharmony_ci reg = rd32(E1000_FCRTC); 98668c2ecf20Sopenharmony_ci reg &= ~E1000_FCRTC_RTH_COAL_MASK; 98678c2ecf20Sopenharmony_ci reg |= ((hwm << E1000_FCRTC_RTH_COAL_SHIFT) 98688c2ecf20Sopenharmony_ci & E1000_FCRTC_RTH_COAL_MASK); 98698c2ecf20Sopenharmony_ci wr32(E1000_FCRTC, reg); 98708c2ecf20Sopenharmony_ci 98718c2ecf20Sopenharmony_ci /* Set the DMA Coalescing Rx threshold to PBA - 2 * max 98728c2ecf20Sopenharmony_ci * frame size, capping it at PBA - 10KB. 98738c2ecf20Sopenharmony_ci */ 98748c2ecf20Sopenharmony_ci dmac_thr = pba - 10; 98758c2ecf20Sopenharmony_ci reg = rd32(E1000_DMACR); 98768c2ecf20Sopenharmony_ci reg &= ~E1000_DMACR_DMACTHR_MASK; 98778c2ecf20Sopenharmony_ci reg |= ((dmac_thr << E1000_DMACR_DMACTHR_SHIFT) 98788c2ecf20Sopenharmony_ci & E1000_DMACR_DMACTHR_MASK); 98798c2ecf20Sopenharmony_ci 98808c2ecf20Sopenharmony_ci /* transition to L0x or L1 if available..*/ 98818c2ecf20Sopenharmony_ci reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK); 98828c2ecf20Sopenharmony_ci 98838c2ecf20Sopenharmony_ci /* watchdog timer= +-1000 usec in 32usec intervals */ 98848c2ecf20Sopenharmony_ci reg |= (1000 >> 5); 98858c2ecf20Sopenharmony_ci 98868c2ecf20Sopenharmony_ci /* Disable BMC-to-OS Watchdog Enable */ 98878c2ecf20Sopenharmony_ci if (hw->mac.type != e1000_i354) 98888c2ecf20Sopenharmony_ci reg &= ~E1000_DMACR_DC_BMC2OSW_EN; 98898c2ecf20Sopenharmony_ci wr32(E1000_DMACR, reg); 98908c2ecf20Sopenharmony_ci 98918c2ecf20Sopenharmony_ci /* no lower threshold to disable 98928c2ecf20Sopenharmony_ci * coalescing(smart fifb)-UTRESH=0 98938c2ecf20Sopenharmony_ci */ 98948c2ecf20Sopenharmony_ci wr32(E1000_DMCRTRH, 0); 98958c2ecf20Sopenharmony_ci 98968c2ecf20Sopenharmony_ci reg = (IGB_DMCTLX_DCFLUSH_DIS | 0x4); 98978c2ecf20Sopenharmony_ci 98988c2ecf20Sopenharmony_ci wr32(E1000_DMCTLX, reg); 98998c2ecf20Sopenharmony_ci 99008c2ecf20Sopenharmony_ci /* free space in tx packet buffer to wake from 99018c2ecf20Sopenharmony_ci * DMA coal 99028c2ecf20Sopenharmony_ci */ 99038c2ecf20Sopenharmony_ci wr32(E1000_DMCTXTH, (IGB_MIN_TXPBSIZE - 99048c2ecf20Sopenharmony_ci (IGB_TX_BUF_4096 + adapter->max_frame_size)) >> 6); 99058c2ecf20Sopenharmony_ci } 99068c2ecf20Sopenharmony_ci 99078c2ecf20Sopenharmony_ci if (hw->mac.type >= e1000_i210 || 99088c2ecf20Sopenharmony_ci (adapter->flags & IGB_FLAG_DMAC)) { 99098c2ecf20Sopenharmony_ci reg = rd32(E1000_PCIEMISC); 99108c2ecf20Sopenharmony_ci reg |= E1000_PCIEMISC_LX_DECISION; 99118c2ecf20Sopenharmony_ci wr32(E1000_PCIEMISC, reg); 99128c2ecf20Sopenharmony_ci } /* endif adapter->dmac is not disabled */ 99138c2ecf20Sopenharmony_ci } else if (hw->mac.type == e1000_82580) { 99148c2ecf20Sopenharmony_ci u32 reg = rd32(E1000_PCIEMISC); 99158c2ecf20Sopenharmony_ci 99168c2ecf20Sopenharmony_ci wr32(E1000_PCIEMISC, reg & ~E1000_PCIEMISC_LX_DECISION); 99178c2ecf20Sopenharmony_ci wr32(E1000_DMACR, 0); 99188c2ecf20Sopenharmony_ci } 99198c2ecf20Sopenharmony_ci} 99208c2ecf20Sopenharmony_ci 99218c2ecf20Sopenharmony_ci/** 99228c2ecf20Sopenharmony_ci * igb_read_i2c_byte - Reads 8 bit word over I2C 99238c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 99248c2ecf20Sopenharmony_ci * @byte_offset: byte offset to read 99258c2ecf20Sopenharmony_ci * @dev_addr: device address 99268c2ecf20Sopenharmony_ci * @data: value read 99278c2ecf20Sopenharmony_ci * 99288c2ecf20Sopenharmony_ci * Performs byte read operation over I2C interface at 99298c2ecf20Sopenharmony_ci * a specified device address. 99308c2ecf20Sopenharmony_ci **/ 99318c2ecf20Sopenharmony_cis32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset, 99328c2ecf20Sopenharmony_ci u8 dev_addr, u8 *data) 99338c2ecf20Sopenharmony_ci{ 99348c2ecf20Sopenharmony_ci struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); 99358c2ecf20Sopenharmony_ci struct i2c_client *this_client = adapter->i2c_client; 99368c2ecf20Sopenharmony_ci s32 status; 99378c2ecf20Sopenharmony_ci u16 swfw_mask = 0; 99388c2ecf20Sopenharmony_ci 99398c2ecf20Sopenharmony_ci if (!this_client) 99408c2ecf20Sopenharmony_ci return E1000_ERR_I2C; 99418c2ecf20Sopenharmony_ci 99428c2ecf20Sopenharmony_ci swfw_mask = E1000_SWFW_PHY0_SM; 99438c2ecf20Sopenharmony_ci 99448c2ecf20Sopenharmony_ci if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) 99458c2ecf20Sopenharmony_ci return E1000_ERR_SWFW_SYNC; 99468c2ecf20Sopenharmony_ci 99478c2ecf20Sopenharmony_ci status = i2c_smbus_read_byte_data(this_client, byte_offset); 99488c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swfw_mask); 99498c2ecf20Sopenharmony_ci 99508c2ecf20Sopenharmony_ci if (status < 0) 99518c2ecf20Sopenharmony_ci return E1000_ERR_I2C; 99528c2ecf20Sopenharmony_ci else { 99538c2ecf20Sopenharmony_ci *data = status; 99548c2ecf20Sopenharmony_ci return 0; 99558c2ecf20Sopenharmony_ci } 99568c2ecf20Sopenharmony_ci} 99578c2ecf20Sopenharmony_ci 99588c2ecf20Sopenharmony_ci/** 99598c2ecf20Sopenharmony_ci * igb_write_i2c_byte - Writes 8 bit word over I2C 99608c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 99618c2ecf20Sopenharmony_ci * @byte_offset: byte offset to write 99628c2ecf20Sopenharmony_ci * @dev_addr: device address 99638c2ecf20Sopenharmony_ci * @data: value to write 99648c2ecf20Sopenharmony_ci * 99658c2ecf20Sopenharmony_ci * Performs byte write operation over I2C interface at 99668c2ecf20Sopenharmony_ci * a specified device address. 99678c2ecf20Sopenharmony_ci **/ 99688c2ecf20Sopenharmony_cis32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, 99698c2ecf20Sopenharmony_ci u8 dev_addr, u8 data) 99708c2ecf20Sopenharmony_ci{ 99718c2ecf20Sopenharmony_ci struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); 99728c2ecf20Sopenharmony_ci struct i2c_client *this_client = adapter->i2c_client; 99738c2ecf20Sopenharmony_ci s32 status; 99748c2ecf20Sopenharmony_ci u16 swfw_mask = E1000_SWFW_PHY0_SM; 99758c2ecf20Sopenharmony_ci 99768c2ecf20Sopenharmony_ci if (!this_client) 99778c2ecf20Sopenharmony_ci return E1000_ERR_I2C; 99788c2ecf20Sopenharmony_ci 99798c2ecf20Sopenharmony_ci if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) 99808c2ecf20Sopenharmony_ci return E1000_ERR_SWFW_SYNC; 99818c2ecf20Sopenharmony_ci status = i2c_smbus_write_byte_data(this_client, byte_offset, data); 99828c2ecf20Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swfw_mask); 99838c2ecf20Sopenharmony_ci 99848c2ecf20Sopenharmony_ci if (status) 99858c2ecf20Sopenharmony_ci return E1000_ERR_I2C; 99868c2ecf20Sopenharmony_ci else 99878c2ecf20Sopenharmony_ci return 0; 99888c2ecf20Sopenharmony_ci 99898c2ecf20Sopenharmony_ci} 99908c2ecf20Sopenharmony_ci 99918c2ecf20Sopenharmony_ciint igb_reinit_queues(struct igb_adapter *adapter) 99928c2ecf20Sopenharmony_ci{ 99938c2ecf20Sopenharmony_ci struct net_device *netdev = adapter->netdev; 99948c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 99958c2ecf20Sopenharmony_ci int err = 0; 99968c2ecf20Sopenharmony_ci 99978c2ecf20Sopenharmony_ci if (netif_running(netdev)) 99988c2ecf20Sopenharmony_ci igb_close(netdev); 99998c2ecf20Sopenharmony_ci 100008c2ecf20Sopenharmony_ci igb_reset_interrupt_capability(adapter); 100018c2ecf20Sopenharmony_ci 100028c2ecf20Sopenharmony_ci if (igb_init_interrupt_scheme(adapter, true)) { 100038c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); 100048c2ecf20Sopenharmony_ci return -ENOMEM; 100058c2ecf20Sopenharmony_ci } 100068c2ecf20Sopenharmony_ci 100078c2ecf20Sopenharmony_ci if (netif_running(netdev)) 100088c2ecf20Sopenharmony_ci err = igb_open(netdev); 100098c2ecf20Sopenharmony_ci 100108c2ecf20Sopenharmony_ci return err; 100118c2ecf20Sopenharmony_ci} 100128c2ecf20Sopenharmony_ci 100138c2ecf20Sopenharmony_cistatic void igb_nfc_filter_exit(struct igb_adapter *adapter) 100148c2ecf20Sopenharmony_ci{ 100158c2ecf20Sopenharmony_ci struct igb_nfc_filter *rule; 100168c2ecf20Sopenharmony_ci 100178c2ecf20Sopenharmony_ci spin_lock(&adapter->nfc_lock); 100188c2ecf20Sopenharmony_ci 100198c2ecf20Sopenharmony_ci hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) 100208c2ecf20Sopenharmony_ci igb_erase_filter(adapter, rule); 100218c2ecf20Sopenharmony_ci 100228c2ecf20Sopenharmony_ci hlist_for_each_entry(rule, &adapter->cls_flower_list, nfc_node) 100238c2ecf20Sopenharmony_ci igb_erase_filter(adapter, rule); 100248c2ecf20Sopenharmony_ci 100258c2ecf20Sopenharmony_ci spin_unlock(&adapter->nfc_lock); 100268c2ecf20Sopenharmony_ci} 100278c2ecf20Sopenharmony_ci 100288c2ecf20Sopenharmony_cistatic void igb_nfc_filter_restore(struct igb_adapter *adapter) 100298c2ecf20Sopenharmony_ci{ 100308c2ecf20Sopenharmony_ci struct igb_nfc_filter *rule; 100318c2ecf20Sopenharmony_ci 100328c2ecf20Sopenharmony_ci spin_lock(&adapter->nfc_lock); 100338c2ecf20Sopenharmony_ci 100348c2ecf20Sopenharmony_ci hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) 100358c2ecf20Sopenharmony_ci igb_add_filter(adapter, rule); 100368c2ecf20Sopenharmony_ci 100378c2ecf20Sopenharmony_ci spin_unlock(&adapter->nfc_lock); 100388c2ecf20Sopenharmony_ci} 100398c2ecf20Sopenharmony_ci/* igb_main.c */ 10040