162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 2007 - 2018 Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/module.h> 762306a36Sopenharmony_ci#include <linux/types.h> 862306a36Sopenharmony_ci#include <linux/init.h> 962306a36Sopenharmony_ci#include <linux/bitops.h> 1062306a36Sopenharmony_ci#include <linux/vmalloc.h> 1162306a36Sopenharmony_ci#include <linux/pagemap.h> 1262306a36Sopenharmony_ci#include <linux/netdevice.h> 1362306a36Sopenharmony_ci#include <linux/ipv6.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci#include <net/checksum.h> 1662306a36Sopenharmony_ci#include <net/ip6_checksum.h> 1762306a36Sopenharmony_ci#include <net/pkt_sched.h> 1862306a36Sopenharmony_ci#include <net/pkt_cls.h> 1962306a36Sopenharmony_ci#include <linux/net_tstamp.h> 2062306a36Sopenharmony_ci#include <linux/mii.h> 2162306a36Sopenharmony_ci#include <linux/ethtool.h> 2262306a36Sopenharmony_ci#include <linux/if.h> 2362306a36Sopenharmony_ci#include <linux/if_vlan.h> 2462306a36Sopenharmony_ci#include <linux/pci.h> 2562306a36Sopenharmony_ci#include <linux/delay.h> 2662306a36Sopenharmony_ci#include <linux/interrupt.h> 2762306a36Sopenharmony_ci#include <linux/ip.h> 2862306a36Sopenharmony_ci#include <linux/tcp.h> 2962306a36Sopenharmony_ci#include <linux/sctp.h> 3062306a36Sopenharmony_ci#include <linux/if_ether.h> 3162306a36Sopenharmony_ci#include <linux/prefetch.h> 3262306a36Sopenharmony_ci#include <linux/bpf.h> 3362306a36Sopenharmony_ci#include <linux/bpf_trace.h> 3462306a36Sopenharmony_ci#include <linux/pm_runtime.h> 3562306a36Sopenharmony_ci#include <linux/etherdevice.h> 3662306a36Sopenharmony_ci#ifdef CONFIG_IGB_DCA 3762306a36Sopenharmony_ci#include <linux/dca.h> 3862306a36Sopenharmony_ci#endif 3962306a36Sopenharmony_ci#include <linux/i2c.h> 4062306a36Sopenharmony_ci#include "igb.h" 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cienum queue_mode { 4362306a36Sopenharmony_ci QUEUE_MODE_STRICT_PRIORITY, 4462306a36Sopenharmony_ci QUEUE_MODE_STREAM_RESERVATION, 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cienum tx_queue_prio { 4862306a36Sopenharmony_ci TX_QUEUE_PRIO_HIGH, 4962306a36Sopenharmony_ci TX_QUEUE_PRIO_LOW, 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cichar igb_driver_name[] = "igb"; 5362306a36Sopenharmony_cistatic const char igb_driver_string[] = 5462306a36Sopenharmony_ci "Intel(R) Gigabit Ethernet Network Driver"; 5562306a36Sopenharmony_cistatic const char igb_copyright[] = 5662306a36Sopenharmony_ci "Copyright (c) 2007-2014 Intel Corporation."; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic const struct e1000_info *igb_info_tbl[] = { 5962306a36Sopenharmony_ci [board_82575] = &e1000_82575_info, 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic const struct pci_device_id igb_pci_tbl[] = { 6362306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_1GBPS) }, 6462306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_SGMII) }, 6562306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_2_5GBPS) }, 6662306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I211_COPPER), board_82575 }, 6762306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER), board_82575 }, 6862306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_FIBER), board_82575 }, 6962306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES), board_82575 }, 7062306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SGMII), board_82575 }, 7162306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER_FLASHLESS), board_82575 }, 7262306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES_FLASHLESS), board_82575 }, 7362306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_COPPER), board_82575 }, 7462306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_FIBER), board_82575 }, 7562306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SERDES), board_82575 }, 7662306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SGMII), board_82575 }, 7762306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER), board_82575 }, 7862306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_FIBER), board_82575 }, 7962306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_QUAD_FIBER), board_82575 }, 8062306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES), board_82575 }, 8162306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII), board_82575 }, 8262306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 }, 8362306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII), board_82575 }, 8462306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES), board_82575 }, 8562306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_BACKPLANE), board_82575 }, 8662306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SFP), board_82575 }, 8762306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 }, 8862306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 }, 8962306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES), board_82575 }, 9062306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER), board_82575 }, 9162306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES), board_82575 }, 9262306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES_QUAD), board_82575 }, 9362306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER_ET2), board_82575 }, 9462306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER), board_82575 }, 9562306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER), board_82575 }, 9662306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES), board_82575 }, 9762306a36Sopenharmony_ci { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER), board_82575 }, 9862306a36Sopenharmony_ci /* required last entry */ 9962306a36Sopenharmony_ci {0, } 10062306a36Sopenharmony_ci}; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, igb_pci_tbl); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic int igb_setup_all_tx_resources(struct igb_adapter *); 10562306a36Sopenharmony_cistatic int igb_setup_all_rx_resources(struct igb_adapter *); 10662306a36Sopenharmony_cistatic void igb_free_all_tx_resources(struct igb_adapter *); 10762306a36Sopenharmony_cistatic void igb_free_all_rx_resources(struct igb_adapter *); 10862306a36Sopenharmony_cistatic void igb_setup_mrqc(struct igb_adapter *); 10962306a36Sopenharmony_cistatic int igb_probe(struct pci_dev *, const struct pci_device_id *); 11062306a36Sopenharmony_cistatic void igb_remove(struct pci_dev *pdev); 11162306a36Sopenharmony_cistatic void igb_init_queue_configuration(struct igb_adapter *adapter); 11262306a36Sopenharmony_cistatic int igb_sw_init(struct igb_adapter *); 11362306a36Sopenharmony_ciint igb_open(struct net_device *); 11462306a36Sopenharmony_ciint igb_close(struct net_device *); 11562306a36Sopenharmony_cistatic void igb_configure(struct igb_adapter *); 11662306a36Sopenharmony_cistatic void igb_configure_tx(struct igb_adapter *); 11762306a36Sopenharmony_cistatic void igb_configure_rx(struct igb_adapter *); 11862306a36Sopenharmony_cistatic void igb_clean_all_tx_rings(struct igb_adapter *); 11962306a36Sopenharmony_cistatic void igb_clean_all_rx_rings(struct igb_adapter *); 12062306a36Sopenharmony_cistatic void igb_clean_tx_ring(struct igb_ring *); 12162306a36Sopenharmony_cistatic void igb_clean_rx_ring(struct igb_ring *); 12262306a36Sopenharmony_cistatic void igb_set_rx_mode(struct net_device *); 12362306a36Sopenharmony_cistatic void igb_update_phy_info(struct timer_list *); 12462306a36Sopenharmony_cistatic void igb_watchdog(struct timer_list *); 12562306a36Sopenharmony_cistatic void igb_watchdog_task(struct work_struct *); 12662306a36Sopenharmony_cistatic netdev_tx_t igb_xmit_frame(struct sk_buff *skb, struct net_device *); 12762306a36Sopenharmony_cistatic void igb_get_stats64(struct net_device *dev, 12862306a36Sopenharmony_ci struct rtnl_link_stats64 *stats); 12962306a36Sopenharmony_cistatic int igb_change_mtu(struct net_device *, int); 13062306a36Sopenharmony_cistatic int igb_set_mac(struct net_device *, void *); 13162306a36Sopenharmony_cistatic void igb_set_uta(struct igb_adapter *adapter, bool set); 13262306a36Sopenharmony_cistatic irqreturn_t igb_intr(int irq, void *); 13362306a36Sopenharmony_cistatic irqreturn_t igb_intr_msi(int irq, void *); 13462306a36Sopenharmony_cistatic irqreturn_t igb_msix_other(int irq, void *); 13562306a36Sopenharmony_cistatic irqreturn_t igb_msix_ring(int irq, void *); 13662306a36Sopenharmony_ci#ifdef CONFIG_IGB_DCA 13762306a36Sopenharmony_cistatic void igb_update_dca(struct igb_q_vector *); 13862306a36Sopenharmony_cistatic void igb_setup_dca(struct igb_adapter *); 13962306a36Sopenharmony_ci#endif /* CONFIG_IGB_DCA */ 14062306a36Sopenharmony_cistatic int igb_poll(struct napi_struct *, int); 14162306a36Sopenharmony_cistatic bool igb_clean_tx_irq(struct igb_q_vector *, int); 14262306a36Sopenharmony_cistatic int igb_clean_rx_irq(struct igb_q_vector *, int); 14362306a36Sopenharmony_cistatic int igb_ioctl(struct net_device *, struct ifreq *, int cmd); 14462306a36Sopenharmony_cistatic void igb_tx_timeout(struct net_device *, unsigned int txqueue); 14562306a36Sopenharmony_cistatic void igb_reset_task(struct work_struct *); 14662306a36Sopenharmony_cistatic void igb_vlan_mode(struct net_device *netdev, 14762306a36Sopenharmony_ci netdev_features_t features); 14862306a36Sopenharmony_cistatic int igb_vlan_rx_add_vid(struct net_device *, __be16, u16); 14962306a36Sopenharmony_cistatic int igb_vlan_rx_kill_vid(struct net_device *, __be16, u16); 15062306a36Sopenharmony_cistatic void igb_restore_vlan(struct igb_adapter *); 15162306a36Sopenharmony_cistatic void igb_rar_set_index(struct igb_adapter *, u32); 15262306a36Sopenharmony_cistatic void igb_ping_all_vfs(struct igb_adapter *); 15362306a36Sopenharmony_cistatic void igb_msg_task(struct igb_adapter *); 15462306a36Sopenharmony_cistatic void igb_vmm_control(struct igb_adapter *); 15562306a36Sopenharmony_cistatic int igb_set_vf_mac(struct igb_adapter *, int, unsigned char *); 15662306a36Sopenharmony_cistatic void igb_flush_mac_table(struct igb_adapter *); 15762306a36Sopenharmony_cistatic int igb_available_rars(struct igb_adapter *, u8); 15862306a36Sopenharmony_cistatic void igb_set_default_mac_filter(struct igb_adapter *); 15962306a36Sopenharmony_cistatic int igb_uc_sync(struct net_device *, const unsigned char *); 16062306a36Sopenharmony_cistatic int igb_uc_unsync(struct net_device *, const unsigned char *); 16162306a36Sopenharmony_cistatic void igb_restore_vf_multicasts(struct igb_adapter *adapter); 16262306a36Sopenharmony_cistatic int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac); 16362306a36Sopenharmony_cistatic int igb_ndo_set_vf_vlan(struct net_device *netdev, 16462306a36Sopenharmony_ci int vf, u16 vlan, u8 qos, __be16 vlan_proto); 16562306a36Sopenharmony_cistatic int igb_ndo_set_vf_bw(struct net_device *, int, int, int); 16662306a36Sopenharmony_cistatic int igb_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, 16762306a36Sopenharmony_ci bool setting); 16862306a36Sopenharmony_cistatic int igb_ndo_set_vf_trust(struct net_device *netdev, int vf, 16962306a36Sopenharmony_ci bool setting); 17062306a36Sopenharmony_cistatic int igb_ndo_get_vf_config(struct net_device *netdev, int vf, 17162306a36Sopenharmony_ci struct ifla_vf_info *ivi); 17262306a36Sopenharmony_cistatic void igb_check_vf_rate_limit(struct igb_adapter *); 17362306a36Sopenharmony_cistatic void igb_nfc_filter_exit(struct igb_adapter *adapter); 17462306a36Sopenharmony_cistatic void igb_nfc_filter_restore(struct igb_adapter *adapter); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 17762306a36Sopenharmony_cistatic int igb_vf_configure(struct igb_adapter *adapter, int vf); 17862306a36Sopenharmony_cistatic int igb_disable_sriov(struct pci_dev *dev, bool reinit); 17962306a36Sopenharmony_ci#endif 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic int igb_suspend(struct device *); 18262306a36Sopenharmony_cistatic int igb_resume(struct device *); 18362306a36Sopenharmony_cistatic int igb_runtime_suspend(struct device *dev); 18462306a36Sopenharmony_cistatic int igb_runtime_resume(struct device *dev); 18562306a36Sopenharmony_cistatic int igb_runtime_idle(struct device *dev); 18662306a36Sopenharmony_ci#ifdef CONFIG_PM 18762306a36Sopenharmony_cistatic const struct dev_pm_ops igb_pm_ops = { 18862306a36Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(igb_suspend, igb_resume) 18962306a36Sopenharmony_ci SET_RUNTIME_PM_OPS(igb_runtime_suspend, igb_runtime_resume, 19062306a36Sopenharmony_ci igb_runtime_idle) 19162306a36Sopenharmony_ci}; 19262306a36Sopenharmony_ci#endif 19362306a36Sopenharmony_cistatic void igb_shutdown(struct pci_dev *); 19462306a36Sopenharmony_cistatic int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs); 19562306a36Sopenharmony_ci#ifdef CONFIG_IGB_DCA 19662306a36Sopenharmony_cistatic int igb_notify_dca(struct notifier_block *, unsigned long, void *); 19762306a36Sopenharmony_cistatic struct notifier_block dca_notifier = { 19862306a36Sopenharmony_ci .notifier_call = igb_notify_dca, 19962306a36Sopenharmony_ci .next = NULL, 20062306a36Sopenharmony_ci .priority = 0 20162306a36Sopenharmony_ci}; 20262306a36Sopenharmony_ci#endif 20362306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 20462306a36Sopenharmony_cistatic unsigned int max_vfs; 20562306a36Sopenharmony_cimodule_param(max_vfs, uint, 0); 20662306a36Sopenharmony_ciMODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate per physical function"); 20762306a36Sopenharmony_ci#endif /* CONFIG_PCI_IOV */ 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic pci_ers_result_t igb_io_error_detected(struct pci_dev *, 21062306a36Sopenharmony_ci pci_channel_state_t); 21162306a36Sopenharmony_cistatic pci_ers_result_t igb_io_slot_reset(struct pci_dev *); 21262306a36Sopenharmony_cistatic void igb_io_resume(struct pci_dev *); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cistatic const struct pci_error_handlers igb_err_handler = { 21562306a36Sopenharmony_ci .error_detected = igb_io_error_detected, 21662306a36Sopenharmony_ci .slot_reset = igb_io_slot_reset, 21762306a36Sopenharmony_ci .resume = igb_io_resume, 21862306a36Sopenharmony_ci}; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic void igb_init_dmac(struct igb_adapter *adapter, u32 pba); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic struct pci_driver igb_driver = { 22362306a36Sopenharmony_ci .name = igb_driver_name, 22462306a36Sopenharmony_ci .id_table = igb_pci_tbl, 22562306a36Sopenharmony_ci .probe = igb_probe, 22662306a36Sopenharmony_ci .remove = igb_remove, 22762306a36Sopenharmony_ci#ifdef CONFIG_PM 22862306a36Sopenharmony_ci .driver.pm = &igb_pm_ops, 22962306a36Sopenharmony_ci#endif 23062306a36Sopenharmony_ci .shutdown = igb_shutdown, 23162306a36Sopenharmony_ci .sriov_configure = igb_pci_sriov_configure, 23262306a36Sopenharmony_ci .err_handler = &igb_err_handler 23362306a36Sopenharmony_ci}; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ciMODULE_AUTHOR("Intel Corporation, <e1000-devel@lists.sourceforge.net>"); 23662306a36Sopenharmony_ciMODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver"); 23762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) 24062306a36Sopenharmony_cistatic int debug = -1; 24162306a36Sopenharmony_cimodule_param(debug, int, 0); 24262306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistruct igb_reg_info { 24562306a36Sopenharmony_ci u32 ofs; 24662306a36Sopenharmony_ci char *name; 24762306a36Sopenharmony_ci}; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic const struct igb_reg_info igb_reg_info_tbl[] = { 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* General Registers */ 25262306a36Sopenharmony_ci {E1000_CTRL, "CTRL"}, 25362306a36Sopenharmony_ci {E1000_STATUS, "STATUS"}, 25462306a36Sopenharmony_ci {E1000_CTRL_EXT, "CTRL_EXT"}, 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* Interrupt Registers */ 25762306a36Sopenharmony_ci {E1000_ICR, "ICR"}, 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci /* RX Registers */ 26062306a36Sopenharmony_ci {E1000_RCTL, "RCTL"}, 26162306a36Sopenharmony_ci {E1000_RDLEN(0), "RDLEN"}, 26262306a36Sopenharmony_ci {E1000_RDH(0), "RDH"}, 26362306a36Sopenharmony_ci {E1000_RDT(0), "RDT"}, 26462306a36Sopenharmony_ci {E1000_RXDCTL(0), "RXDCTL"}, 26562306a36Sopenharmony_ci {E1000_RDBAL(0), "RDBAL"}, 26662306a36Sopenharmony_ci {E1000_RDBAH(0), "RDBAH"}, 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* TX Registers */ 26962306a36Sopenharmony_ci {E1000_TCTL, "TCTL"}, 27062306a36Sopenharmony_ci {E1000_TDBAL(0), "TDBAL"}, 27162306a36Sopenharmony_ci {E1000_TDBAH(0), "TDBAH"}, 27262306a36Sopenharmony_ci {E1000_TDLEN(0), "TDLEN"}, 27362306a36Sopenharmony_ci {E1000_TDH(0), "TDH"}, 27462306a36Sopenharmony_ci {E1000_TDT(0), "TDT"}, 27562306a36Sopenharmony_ci {E1000_TXDCTL(0), "TXDCTL"}, 27662306a36Sopenharmony_ci {E1000_TDFH, "TDFH"}, 27762306a36Sopenharmony_ci {E1000_TDFT, "TDFT"}, 27862306a36Sopenharmony_ci {E1000_TDFHS, "TDFHS"}, 27962306a36Sopenharmony_ci {E1000_TDFPC, "TDFPC"}, 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* List Terminator */ 28262306a36Sopenharmony_ci {} 28362306a36Sopenharmony_ci}; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci/* igb_regdump - register printout routine */ 28662306a36Sopenharmony_cistatic void igb_regdump(struct e1000_hw *hw, struct igb_reg_info *reginfo) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci int n = 0; 28962306a36Sopenharmony_ci char rname[16]; 29062306a36Sopenharmony_ci u32 regs[8]; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci switch (reginfo->ofs) { 29362306a36Sopenharmony_ci case E1000_RDLEN(0): 29462306a36Sopenharmony_ci for (n = 0; n < 4; n++) 29562306a36Sopenharmony_ci regs[n] = rd32(E1000_RDLEN(n)); 29662306a36Sopenharmony_ci break; 29762306a36Sopenharmony_ci case E1000_RDH(0): 29862306a36Sopenharmony_ci for (n = 0; n < 4; n++) 29962306a36Sopenharmony_ci regs[n] = rd32(E1000_RDH(n)); 30062306a36Sopenharmony_ci break; 30162306a36Sopenharmony_ci case E1000_RDT(0): 30262306a36Sopenharmony_ci for (n = 0; n < 4; n++) 30362306a36Sopenharmony_ci regs[n] = rd32(E1000_RDT(n)); 30462306a36Sopenharmony_ci break; 30562306a36Sopenharmony_ci case E1000_RXDCTL(0): 30662306a36Sopenharmony_ci for (n = 0; n < 4; n++) 30762306a36Sopenharmony_ci regs[n] = rd32(E1000_RXDCTL(n)); 30862306a36Sopenharmony_ci break; 30962306a36Sopenharmony_ci case E1000_RDBAL(0): 31062306a36Sopenharmony_ci for (n = 0; n < 4; n++) 31162306a36Sopenharmony_ci regs[n] = rd32(E1000_RDBAL(n)); 31262306a36Sopenharmony_ci break; 31362306a36Sopenharmony_ci case E1000_RDBAH(0): 31462306a36Sopenharmony_ci for (n = 0; n < 4; n++) 31562306a36Sopenharmony_ci regs[n] = rd32(E1000_RDBAH(n)); 31662306a36Sopenharmony_ci break; 31762306a36Sopenharmony_ci case E1000_TDBAL(0): 31862306a36Sopenharmony_ci for (n = 0; n < 4; n++) 31962306a36Sopenharmony_ci regs[n] = rd32(E1000_TDBAL(n)); 32062306a36Sopenharmony_ci break; 32162306a36Sopenharmony_ci case E1000_TDBAH(0): 32262306a36Sopenharmony_ci for (n = 0; n < 4; n++) 32362306a36Sopenharmony_ci regs[n] = rd32(E1000_TDBAH(n)); 32462306a36Sopenharmony_ci break; 32562306a36Sopenharmony_ci case E1000_TDLEN(0): 32662306a36Sopenharmony_ci for (n = 0; n < 4; n++) 32762306a36Sopenharmony_ci regs[n] = rd32(E1000_TDLEN(n)); 32862306a36Sopenharmony_ci break; 32962306a36Sopenharmony_ci case E1000_TDH(0): 33062306a36Sopenharmony_ci for (n = 0; n < 4; n++) 33162306a36Sopenharmony_ci regs[n] = rd32(E1000_TDH(n)); 33262306a36Sopenharmony_ci break; 33362306a36Sopenharmony_ci case E1000_TDT(0): 33462306a36Sopenharmony_ci for (n = 0; n < 4; n++) 33562306a36Sopenharmony_ci regs[n] = rd32(E1000_TDT(n)); 33662306a36Sopenharmony_ci break; 33762306a36Sopenharmony_ci case E1000_TXDCTL(0): 33862306a36Sopenharmony_ci for (n = 0; n < 4; n++) 33962306a36Sopenharmony_ci regs[n] = rd32(E1000_TXDCTL(n)); 34062306a36Sopenharmony_ci break; 34162306a36Sopenharmony_ci default: 34262306a36Sopenharmony_ci pr_info("%-15s %08x\n", reginfo->name, rd32(reginfo->ofs)); 34362306a36Sopenharmony_ci return; 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]"); 34762306a36Sopenharmony_ci pr_info("%-15s %08x %08x %08x %08x\n", rname, regs[0], regs[1], 34862306a36Sopenharmony_ci regs[2], regs[3]); 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci/* igb_dump - Print registers, Tx-rings and Rx-rings */ 35262306a36Sopenharmony_cistatic void igb_dump(struct igb_adapter *adapter) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 35562306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 35662306a36Sopenharmony_ci struct igb_reg_info *reginfo; 35762306a36Sopenharmony_ci struct igb_ring *tx_ring; 35862306a36Sopenharmony_ci union e1000_adv_tx_desc *tx_desc; 35962306a36Sopenharmony_ci struct my_u0 { __le64 a; __le64 b; } *u0; 36062306a36Sopenharmony_ci struct igb_ring *rx_ring; 36162306a36Sopenharmony_ci union e1000_adv_rx_desc *rx_desc; 36262306a36Sopenharmony_ci u32 staterr; 36362306a36Sopenharmony_ci u16 i, n; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci if (!netif_msg_hw(adapter)) 36662306a36Sopenharmony_ci return; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci /* Print netdevice Info */ 36962306a36Sopenharmony_ci if (netdev) { 37062306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, "Net device Info\n"); 37162306a36Sopenharmony_ci pr_info("Device Name state trans_start\n"); 37262306a36Sopenharmony_ci pr_info("%-15s %016lX %016lX\n", netdev->name, 37362306a36Sopenharmony_ci netdev->state, dev_trans_start(netdev)); 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci /* Print Registers */ 37762306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, "Register Dump\n"); 37862306a36Sopenharmony_ci pr_info(" Register Name Value\n"); 37962306a36Sopenharmony_ci for (reginfo = (struct igb_reg_info *)igb_reg_info_tbl; 38062306a36Sopenharmony_ci reginfo->name; reginfo++) { 38162306a36Sopenharmony_ci igb_regdump(hw, reginfo); 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci /* Print TX Ring Summary */ 38562306a36Sopenharmony_ci if (!netdev || !netif_running(netdev)) 38662306a36Sopenharmony_ci goto exit; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, "TX Rings Summary\n"); 38962306a36Sopenharmony_ci pr_info("Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n"); 39062306a36Sopenharmony_ci for (n = 0; n < adapter->num_tx_queues; n++) { 39162306a36Sopenharmony_ci struct igb_tx_buffer *buffer_info; 39262306a36Sopenharmony_ci tx_ring = adapter->tx_ring[n]; 39362306a36Sopenharmony_ci buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean]; 39462306a36Sopenharmony_ci pr_info(" %5d %5X %5X %016llX %04X %p %016llX\n", 39562306a36Sopenharmony_ci n, tx_ring->next_to_use, tx_ring->next_to_clean, 39662306a36Sopenharmony_ci (u64)dma_unmap_addr(buffer_info, dma), 39762306a36Sopenharmony_ci dma_unmap_len(buffer_info, len), 39862306a36Sopenharmony_ci buffer_info->next_to_watch, 39962306a36Sopenharmony_ci (u64)buffer_info->time_stamp); 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci /* Print TX Rings */ 40362306a36Sopenharmony_ci if (!netif_msg_tx_done(adapter)) 40462306a36Sopenharmony_ci goto rx_ring_summary; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, "TX Rings Dump\n"); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci /* Transmit Descriptor Formats 40962306a36Sopenharmony_ci * 41062306a36Sopenharmony_ci * Advanced Transmit Descriptor 41162306a36Sopenharmony_ci * +--------------------------------------------------------------+ 41262306a36Sopenharmony_ci * 0 | Buffer Address [63:0] | 41362306a36Sopenharmony_ci * +--------------------------------------------------------------+ 41462306a36Sopenharmony_ci * 8 | PAYLEN | PORTS |CC|IDX | STA | DCMD |DTYP|MAC|RSV| DTALEN | 41562306a36Sopenharmony_ci * +--------------------------------------------------------------+ 41662306a36Sopenharmony_ci * 63 46 45 40 39 38 36 35 32 31 24 15 0 41762306a36Sopenharmony_ci */ 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci for (n = 0; n < adapter->num_tx_queues; n++) { 42062306a36Sopenharmony_ci tx_ring = adapter->tx_ring[n]; 42162306a36Sopenharmony_ci pr_info("------------------------------------\n"); 42262306a36Sopenharmony_ci pr_info("TX QUEUE INDEX = %d\n", tx_ring->queue_index); 42362306a36Sopenharmony_ci pr_info("------------------------------------\n"); 42462306a36Sopenharmony_ci pr_info("T [desc] [address 63:0 ] [PlPOCIStDDM Ln] [bi->dma ] leng ntw timestamp bi->skb\n"); 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { 42762306a36Sopenharmony_ci const char *next_desc; 42862306a36Sopenharmony_ci struct igb_tx_buffer *buffer_info; 42962306a36Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, i); 43062306a36Sopenharmony_ci buffer_info = &tx_ring->tx_buffer_info[i]; 43162306a36Sopenharmony_ci u0 = (struct my_u0 *)tx_desc; 43262306a36Sopenharmony_ci if (i == tx_ring->next_to_use && 43362306a36Sopenharmony_ci i == tx_ring->next_to_clean) 43462306a36Sopenharmony_ci next_desc = " NTC/U"; 43562306a36Sopenharmony_ci else if (i == tx_ring->next_to_use) 43662306a36Sopenharmony_ci next_desc = " NTU"; 43762306a36Sopenharmony_ci else if (i == tx_ring->next_to_clean) 43862306a36Sopenharmony_ci next_desc = " NTC"; 43962306a36Sopenharmony_ci else 44062306a36Sopenharmony_ci next_desc = ""; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci pr_info("T [0x%03X] %016llX %016llX %016llX %04X %p %016llX %p%s\n", 44362306a36Sopenharmony_ci i, le64_to_cpu(u0->a), 44462306a36Sopenharmony_ci le64_to_cpu(u0->b), 44562306a36Sopenharmony_ci (u64)dma_unmap_addr(buffer_info, dma), 44662306a36Sopenharmony_ci dma_unmap_len(buffer_info, len), 44762306a36Sopenharmony_ci buffer_info->next_to_watch, 44862306a36Sopenharmony_ci (u64)buffer_info->time_stamp, 44962306a36Sopenharmony_ci buffer_info->skb, next_desc); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci if (netif_msg_pktdata(adapter) && buffer_info->skb) 45262306a36Sopenharmony_ci print_hex_dump(KERN_INFO, "", 45362306a36Sopenharmony_ci DUMP_PREFIX_ADDRESS, 45462306a36Sopenharmony_ci 16, 1, buffer_info->skb->data, 45562306a36Sopenharmony_ci dma_unmap_len(buffer_info, len), 45662306a36Sopenharmony_ci true); 45762306a36Sopenharmony_ci } 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci /* Print RX Rings Summary */ 46162306a36Sopenharmony_cirx_ring_summary: 46262306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, "RX Rings Summary\n"); 46362306a36Sopenharmony_ci pr_info("Queue [NTU] [NTC]\n"); 46462306a36Sopenharmony_ci for (n = 0; n < adapter->num_rx_queues; n++) { 46562306a36Sopenharmony_ci rx_ring = adapter->rx_ring[n]; 46662306a36Sopenharmony_ci pr_info(" %5d %5X %5X\n", 46762306a36Sopenharmony_ci n, rx_ring->next_to_use, rx_ring->next_to_clean); 46862306a36Sopenharmony_ci } 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci /* Print RX Rings */ 47162306a36Sopenharmony_ci if (!netif_msg_rx_status(adapter)) 47262306a36Sopenharmony_ci goto exit; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, "RX Rings Dump\n"); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci /* Advanced Receive Descriptor (Read) Format 47762306a36Sopenharmony_ci * 63 1 0 47862306a36Sopenharmony_ci * +-----------------------------------------------------+ 47962306a36Sopenharmony_ci * 0 | Packet Buffer Address [63:1] |A0/NSE| 48062306a36Sopenharmony_ci * +----------------------------------------------+------+ 48162306a36Sopenharmony_ci * 8 | Header Buffer Address [63:1] | DD | 48262306a36Sopenharmony_ci * +-----------------------------------------------------+ 48362306a36Sopenharmony_ci * 48462306a36Sopenharmony_ci * 48562306a36Sopenharmony_ci * Advanced Receive Descriptor (Write-Back) Format 48662306a36Sopenharmony_ci * 48762306a36Sopenharmony_ci * 63 48 47 32 31 30 21 20 17 16 4 3 0 48862306a36Sopenharmony_ci * +------------------------------------------------------+ 48962306a36Sopenharmony_ci * 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS | 49062306a36Sopenharmony_ci * | Checksum Ident | | | | Type | Type | 49162306a36Sopenharmony_ci * +------------------------------------------------------+ 49262306a36Sopenharmony_ci * 8 | VLAN Tag | Length | Extended Error | Extended Status | 49362306a36Sopenharmony_ci * +------------------------------------------------------+ 49462306a36Sopenharmony_ci * 63 48 47 32 31 20 19 0 49562306a36Sopenharmony_ci */ 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci for (n = 0; n < adapter->num_rx_queues; n++) { 49862306a36Sopenharmony_ci rx_ring = adapter->rx_ring[n]; 49962306a36Sopenharmony_ci pr_info("------------------------------------\n"); 50062306a36Sopenharmony_ci pr_info("RX QUEUE INDEX = %d\n", rx_ring->queue_index); 50162306a36Sopenharmony_ci pr_info("------------------------------------\n"); 50262306a36Sopenharmony_ci pr_info("R [desc] [ PktBuf A0] [ HeadBuf DD] [bi->dma ] [bi->skb] <-- Adv Rx Read format\n"); 50362306a36Sopenharmony_ci pr_info("RWB[desc] [PcsmIpSHl PtRs] [vl er S cks ln] ---------------- [bi->skb] <-- Adv Rx Write-Back format\n"); 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci for (i = 0; i < rx_ring->count; i++) { 50662306a36Sopenharmony_ci const char *next_desc; 50762306a36Sopenharmony_ci struct igb_rx_buffer *buffer_info; 50862306a36Sopenharmony_ci buffer_info = &rx_ring->rx_buffer_info[i]; 50962306a36Sopenharmony_ci rx_desc = IGB_RX_DESC(rx_ring, i); 51062306a36Sopenharmony_ci u0 = (struct my_u0 *)rx_desc; 51162306a36Sopenharmony_ci staterr = le32_to_cpu(rx_desc->wb.upper.status_error); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci if (i == rx_ring->next_to_use) 51462306a36Sopenharmony_ci next_desc = " NTU"; 51562306a36Sopenharmony_ci else if (i == rx_ring->next_to_clean) 51662306a36Sopenharmony_ci next_desc = " NTC"; 51762306a36Sopenharmony_ci else 51862306a36Sopenharmony_ci next_desc = ""; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci if (staterr & E1000_RXD_STAT_DD) { 52162306a36Sopenharmony_ci /* Descriptor Done */ 52262306a36Sopenharmony_ci pr_info("%s[0x%03X] %016llX %016llX ---------------- %s\n", 52362306a36Sopenharmony_ci "RWB", i, 52462306a36Sopenharmony_ci le64_to_cpu(u0->a), 52562306a36Sopenharmony_ci le64_to_cpu(u0->b), 52662306a36Sopenharmony_ci next_desc); 52762306a36Sopenharmony_ci } else { 52862306a36Sopenharmony_ci pr_info("%s[0x%03X] %016llX %016llX %016llX %s\n", 52962306a36Sopenharmony_ci "R ", i, 53062306a36Sopenharmony_ci le64_to_cpu(u0->a), 53162306a36Sopenharmony_ci le64_to_cpu(u0->b), 53262306a36Sopenharmony_ci (u64)buffer_info->dma, 53362306a36Sopenharmony_ci next_desc); 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci if (netif_msg_pktdata(adapter) && 53662306a36Sopenharmony_ci buffer_info->dma && buffer_info->page) { 53762306a36Sopenharmony_ci print_hex_dump(KERN_INFO, "", 53862306a36Sopenharmony_ci DUMP_PREFIX_ADDRESS, 53962306a36Sopenharmony_ci 16, 1, 54062306a36Sopenharmony_ci page_address(buffer_info->page) + 54162306a36Sopenharmony_ci buffer_info->page_offset, 54262306a36Sopenharmony_ci igb_rx_bufsz(rx_ring), true); 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci } 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ciexit: 54962306a36Sopenharmony_ci return; 55062306a36Sopenharmony_ci} 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci/** 55362306a36Sopenharmony_ci * igb_get_i2c_data - Reads the I2C SDA data bit 55462306a36Sopenharmony_ci * @data: opaque pointer to adapter struct 55562306a36Sopenharmony_ci * 55662306a36Sopenharmony_ci * Returns the I2C data bit value 55762306a36Sopenharmony_ci **/ 55862306a36Sopenharmony_cistatic int igb_get_i2c_data(void *data) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci struct igb_adapter *adapter = (struct igb_adapter *)data; 56162306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 56262306a36Sopenharmony_ci s32 i2cctl = rd32(E1000_I2CPARAMS); 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci return !!(i2cctl & E1000_I2C_DATA_IN); 56562306a36Sopenharmony_ci} 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci/** 56862306a36Sopenharmony_ci * igb_set_i2c_data - Sets the I2C data bit 56962306a36Sopenharmony_ci * @data: pointer to hardware structure 57062306a36Sopenharmony_ci * @state: I2C data value (0 or 1) to set 57162306a36Sopenharmony_ci * 57262306a36Sopenharmony_ci * Sets the I2C data bit 57362306a36Sopenharmony_ci **/ 57462306a36Sopenharmony_cistatic void igb_set_i2c_data(void *data, int state) 57562306a36Sopenharmony_ci{ 57662306a36Sopenharmony_ci struct igb_adapter *adapter = (struct igb_adapter *)data; 57762306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 57862306a36Sopenharmony_ci s32 i2cctl = rd32(E1000_I2CPARAMS); 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci if (state) { 58162306a36Sopenharmony_ci i2cctl |= E1000_I2C_DATA_OUT | E1000_I2C_DATA_OE_N; 58262306a36Sopenharmony_ci } else { 58362306a36Sopenharmony_ci i2cctl &= ~E1000_I2C_DATA_OE_N; 58462306a36Sopenharmony_ci i2cctl &= ~E1000_I2C_DATA_OUT; 58562306a36Sopenharmony_ci } 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci wr32(E1000_I2CPARAMS, i2cctl); 58862306a36Sopenharmony_ci wrfl(); 58962306a36Sopenharmony_ci} 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci/** 59262306a36Sopenharmony_ci * igb_set_i2c_clk - Sets the I2C SCL clock 59362306a36Sopenharmony_ci * @data: pointer to hardware structure 59462306a36Sopenharmony_ci * @state: state to set clock 59562306a36Sopenharmony_ci * 59662306a36Sopenharmony_ci * Sets the I2C clock line to state 59762306a36Sopenharmony_ci **/ 59862306a36Sopenharmony_cistatic void igb_set_i2c_clk(void *data, int state) 59962306a36Sopenharmony_ci{ 60062306a36Sopenharmony_ci struct igb_adapter *adapter = (struct igb_adapter *)data; 60162306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 60262306a36Sopenharmony_ci s32 i2cctl = rd32(E1000_I2CPARAMS); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci if (state) { 60562306a36Sopenharmony_ci i2cctl |= E1000_I2C_CLK_OUT | E1000_I2C_CLK_OE_N; 60662306a36Sopenharmony_ci } else { 60762306a36Sopenharmony_ci i2cctl &= ~E1000_I2C_CLK_OUT; 60862306a36Sopenharmony_ci i2cctl &= ~E1000_I2C_CLK_OE_N; 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci wr32(E1000_I2CPARAMS, i2cctl); 61162306a36Sopenharmony_ci wrfl(); 61262306a36Sopenharmony_ci} 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci/** 61562306a36Sopenharmony_ci * igb_get_i2c_clk - Gets the I2C SCL clock state 61662306a36Sopenharmony_ci * @data: pointer to hardware structure 61762306a36Sopenharmony_ci * 61862306a36Sopenharmony_ci * Gets the I2C clock state 61962306a36Sopenharmony_ci **/ 62062306a36Sopenharmony_cistatic int igb_get_i2c_clk(void *data) 62162306a36Sopenharmony_ci{ 62262306a36Sopenharmony_ci struct igb_adapter *adapter = (struct igb_adapter *)data; 62362306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 62462306a36Sopenharmony_ci s32 i2cctl = rd32(E1000_I2CPARAMS); 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci return !!(i2cctl & E1000_I2C_CLK_IN); 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_cistatic const struct i2c_algo_bit_data igb_i2c_algo = { 63062306a36Sopenharmony_ci .setsda = igb_set_i2c_data, 63162306a36Sopenharmony_ci .setscl = igb_set_i2c_clk, 63262306a36Sopenharmony_ci .getsda = igb_get_i2c_data, 63362306a36Sopenharmony_ci .getscl = igb_get_i2c_clk, 63462306a36Sopenharmony_ci .udelay = 5, 63562306a36Sopenharmony_ci .timeout = 20, 63662306a36Sopenharmony_ci}; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci/** 63962306a36Sopenharmony_ci * igb_get_hw_dev - return device 64062306a36Sopenharmony_ci * @hw: pointer to hardware structure 64162306a36Sopenharmony_ci * 64262306a36Sopenharmony_ci * used by hardware layer to print debugging information 64362306a36Sopenharmony_ci **/ 64462306a36Sopenharmony_cistruct net_device *igb_get_hw_dev(struct e1000_hw *hw) 64562306a36Sopenharmony_ci{ 64662306a36Sopenharmony_ci struct igb_adapter *adapter = hw->back; 64762306a36Sopenharmony_ci return adapter->netdev; 64862306a36Sopenharmony_ci} 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci/** 65162306a36Sopenharmony_ci * igb_init_module - Driver Registration Routine 65262306a36Sopenharmony_ci * 65362306a36Sopenharmony_ci * igb_init_module is the first routine called when the driver is 65462306a36Sopenharmony_ci * loaded. All it does is register with the PCI subsystem. 65562306a36Sopenharmony_ci **/ 65662306a36Sopenharmony_cistatic int __init igb_init_module(void) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci int ret; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci pr_info("%s\n", igb_driver_string); 66162306a36Sopenharmony_ci pr_info("%s\n", igb_copyright); 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci#ifdef CONFIG_IGB_DCA 66462306a36Sopenharmony_ci dca_register_notify(&dca_notifier); 66562306a36Sopenharmony_ci#endif 66662306a36Sopenharmony_ci ret = pci_register_driver(&igb_driver); 66762306a36Sopenharmony_ci return ret; 66862306a36Sopenharmony_ci} 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_cimodule_init(igb_init_module); 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci/** 67362306a36Sopenharmony_ci * igb_exit_module - Driver Exit Cleanup Routine 67462306a36Sopenharmony_ci * 67562306a36Sopenharmony_ci * igb_exit_module is called just before the driver is removed 67662306a36Sopenharmony_ci * from memory. 67762306a36Sopenharmony_ci **/ 67862306a36Sopenharmony_cistatic void __exit igb_exit_module(void) 67962306a36Sopenharmony_ci{ 68062306a36Sopenharmony_ci#ifdef CONFIG_IGB_DCA 68162306a36Sopenharmony_ci dca_unregister_notify(&dca_notifier); 68262306a36Sopenharmony_ci#endif 68362306a36Sopenharmony_ci pci_unregister_driver(&igb_driver); 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_cimodule_exit(igb_exit_module); 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci#define Q_IDX_82576(i) (((i & 0x1) << 3) + (i >> 1)) 68962306a36Sopenharmony_ci/** 69062306a36Sopenharmony_ci * igb_cache_ring_register - Descriptor ring to register mapping 69162306a36Sopenharmony_ci * @adapter: board private structure to initialize 69262306a36Sopenharmony_ci * 69362306a36Sopenharmony_ci * Once we know the feature-set enabled for the device, we'll cache 69462306a36Sopenharmony_ci * the register offset the descriptor ring is assigned to. 69562306a36Sopenharmony_ci **/ 69662306a36Sopenharmony_cistatic void igb_cache_ring_register(struct igb_adapter *adapter) 69762306a36Sopenharmony_ci{ 69862306a36Sopenharmony_ci int i = 0, j = 0; 69962306a36Sopenharmony_ci u32 rbase_offset = adapter->vfs_allocated_count; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci switch (adapter->hw.mac.type) { 70262306a36Sopenharmony_ci case e1000_82576: 70362306a36Sopenharmony_ci /* The queues are allocated for virtualization such that VF 0 70462306a36Sopenharmony_ci * is allocated queues 0 and 8, VF 1 queues 1 and 9, etc. 70562306a36Sopenharmony_ci * In order to avoid collision we start at the first free queue 70662306a36Sopenharmony_ci * and continue consuming queues in the same sequence 70762306a36Sopenharmony_ci */ 70862306a36Sopenharmony_ci if (adapter->vfs_allocated_count) { 70962306a36Sopenharmony_ci for (; i < adapter->rss_queues; i++) 71062306a36Sopenharmony_ci adapter->rx_ring[i]->reg_idx = rbase_offset + 71162306a36Sopenharmony_ci Q_IDX_82576(i); 71262306a36Sopenharmony_ci } 71362306a36Sopenharmony_ci fallthrough; 71462306a36Sopenharmony_ci case e1000_82575: 71562306a36Sopenharmony_ci case e1000_82580: 71662306a36Sopenharmony_ci case e1000_i350: 71762306a36Sopenharmony_ci case e1000_i354: 71862306a36Sopenharmony_ci case e1000_i210: 71962306a36Sopenharmony_ci case e1000_i211: 72062306a36Sopenharmony_ci default: 72162306a36Sopenharmony_ci for (; i < adapter->num_rx_queues; i++) 72262306a36Sopenharmony_ci adapter->rx_ring[i]->reg_idx = rbase_offset + i; 72362306a36Sopenharmony_ci for (; j < adapter->num_tx_queues; j++) 72462306a36Sopenharmony_ci adapter->tx_ring[j]->reg_idx = rbase_offset + j; 72562306a36Sopenharmony_ci break; 72662306a36Sopenharmony_ci } 72762306a36Sopenharmony_ci} 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ciu32 igb_rd32(struct e1000_hw *hw, u32 reg) 73062306a36Sopenharmony_ci{ 73162306a36Sopenharmony_ci struct igb_adapter *igb = container_of(hw, struct igb_adapter, hw); 73262306a36Sopenharmony_ci u8 __iomem *hw_addr = READ_ONCE(hw->hw_addr); 73362306a36Sopenharmony_ci u32 value = 0; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci if (E1000_REMOVED(hw_addr)) 73662306a36Sopenharmony_ci return ~value; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci value = readl(&hw_addr[reg]); 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci /* reads should not return all F's */ 74162306a36Sopenharmony_ci if (!(~value) && (!reg || !(~readl(hw_addr)))) { 74262306a36Sopenharmony_ci struct net_device *netdev = igb->netdev; 74362306a36Sopenharmony_ci hw->hw_addr = NULL; 74462306a36Sopenharmony_ci netdev_err(netdev, "PCIe link lost\n"); 74562306a36Sopenharmony_ci WARN(pci_device_is_present(igb->pdev), 74662306a36Sopenharmony_ci "igb: Failed to read reg 0x%x!\n", reg); 74762306a36Sopenharmony_ci } 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci return value; 75062306a36Sopenharmony_ci} 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci/** 75362306a36Sopenharmony_ci * igb_write_ivar - configure ivar for given MSI-X vector 75462306a36Sopenharmony_ci * @hw: pointer to the HW structure 75562306a36Sopenharmony_ci * @msix_vector: vector number we are allocating to a given ring 75662306a36Sopenharmony_ci * @index: row index of IVAR register to write within IVAR table 75762306a36Sopenharmony_ci * @offset: column offset of in IVAR, should be multiple of 8 75862306a36Sopenharmony_ci * 75962306a36Sopenharmony_ci * This function is intended to handle the writing of the IVAR register 76062306a36Sopenharmony_ci * for adapters 82576 and newer. The IVAR table consists of 2 columns, 76162306a36Sopenharmony_ci * each containing an cause allocation for an Rx and Tx ring, and a 76262306a36Sopenharmony_ci * variable number of rows depending on the number of queues supported. 76362306a36Sopenharmony_ci **/ 76462306a36Sopenharmony_cistatic void igb_write_ivar(struct e1000_hw *hw, int msix_vector, 76562306a36Sopenharmony_ci int index, int offset) 76662306a36Sopenharmony_ci{ 76762306a36Sopenharmony_ci u32 ivar = array_rd32(E1000_IVAR0, index); 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci /* clear any bits that are currently set */ 77062306a36Sopenharmony_ci ivar &= ~((u32)0xFF << offset); 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci /* write vector and valid bit */ 77362306a36Sopenharmony_ci ivar |= (msix_vector | E1000_IVAR_VALID) << offset; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci array_wr32(E1000_IVAR0, index, ivar); 77662306a36Sopenharmony_ci} 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci#define IGB_N0_QUEUE -1 77962306a36Sopenharmony_cistatic void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) 78062306a36Sopenharmony_ci{ 78162306a36Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 78262306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 78362306a36Sopenharmony_ci int rx_queue = IGB_N0_QUEUE; 78462306a36Sopenharmony_ci int tx_queue = IGB_N0_QUEUE; 78562306a36Sopenharmony_ci u32 msixbm = 0; 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci if (q_vector->rx.ring) 78862306a36Sopenharmony_ci rx_queue = q_vector->rx.ring->reg_idx; 78962306a36Sopenharmony_ci if (q_vector->tx.ring) 79062306a36Sopenharmony_ci tx_queue = q_vector->tx.ring->reg_idx; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci switch (hw->mac.type) { 79362306a36Sopenharmony_ci case e1000_82575: 79462306a36Sopenharmony_ci /* The 82575 assigns vectors using a bitmask, which matches the 79562306a36Sopenharmony_ci * bitmask for the EICR/EIMS/EIMC registers. To assign one 79662306a36Sopenharmony_ci * or more queues to a vector, we write the appropriate bits 79762306a36Sopenharmony_ci * into the MSIXBM register for that vector. 79862306a36Sopenharmony_ci */ 79962306a36Sopenharmony_ci if (rx_queue > IGB_N0_QUEUE) 80062306a36Sopenharmony_ci msixbm = E1000_EICR_RX_QUEUE0 << rx_queue; 80162306a36Sopenharmony_ci if (tx_queue > IGB_N0_QUEUE) 80262306a36Sopenharmony_ci msixbm |= E1000_EICR_TX_QUEUE0 << tx_queue; 80362306a36Sopenharmony_ci if (!(adapter->flags & IGB_FLAG_HAS_MSIX) && msix_vector == 0) 80462306a36Sopenharmony_ci msixbm |= E1000_EIMS_OTHER; 80562306a36Sopenharmony_ci array_wr32(E1000_MSIXBM(0), msix_vector, msixbm); 80662306a36Sopenharmony_ci q_vector->eims_value = msixbm; 80762306a36Sopenharmony_ci break; 80862306a36Sopenharmony_ci case e1000_82576: 80962306a36Sopenharmony_ci /* 82576 uses a table that essentially consists of 2 columns 81062306a36Sopenharmony_ci * with 8 rows. The ordering is column-major so we use the 81162306a36Sopenharmony_ci * lower 3 bits as the row index, and the 4th bit as the 81262306a36Sopenharmony_ci * column offset. 81362306a36Sopenharmony_ci */ 81462306a36Sopenharmony_ci if (rx_queue > IGB_N0_QUEUE) 81562306a36Sopenharmony_ci igb_write_ivar(hw, msix_vector, 81662306a36Sopenharmony_ci rx_queue & 0x7, 81762306a36Sopenharmony_ci (rx_queue & 0x8) << 1); 81862306a36Sopenharmony_ci if (tx_queue > IGB_N0_QUEUE) 81962306a36Sopenharmony_ci igb_write_ivar(hw, msix_vector, 82062306a36Sopenharmony_ci tx_queue & 0x7, 82162306a36Sopenharmony_ci ((tx_queue & 0x8) << 1) + 8); 82262306a36Sopenharmony_ci q_vector->eims_value = BIT(msix_vector); 82362306a36Sopenharmony_ci break; 82462306a36Sopenharmony_ci case e1000_82580: 82562306a36Sopenharmony_ci case e1000_i350: 82662306a36Sopenharmony_ci case e1000_i354: 82762306a36Sopenharmony_ci case e1000_i210: 82862306a36Sopenharmony_ci case e1000_i211: 82962306a36Sopenharmony_ci /* On 82580 and newer adapters the scheme is similar to 82576 83062306a36Sopenharmony_ci * however instead of ordering column-major we have things 83162306a36Sopenharmony_ci * ordered row-major. So we traverse the table by using 83262306a36Sopenharmony_ci * bit 0 as the column offset, and the remaining bits as the 83362306a36Sopenharmony_ci * row index. 83462306a36Sopenharmony_ci */ 83562306a36Sopenharmony_ci if (rx_queue > IGB_N0_QUEUE) 83662306a36Sopenharmony_ci igb_write_ivar(hw, msix_vector, 83762306a36Sopenharmony_ci rx_queue >> 1, 83862306a36Sopenharmony_ci (rx_queue & 0x1) << 4); 83962306a36Sopenharmony_ci if (tx_queue > IGB_N0_QUEUE) 84062306a36Sopenharmony_ci igb_write_ivar(hw, msix_vector, 84162306a36Sopenharmony_ci tx_queue >> 1, 84262306a36Sopenharmony_ci ((tx_queue & 0x1) << 4) + 8); 84362306a36Sopenharmony_ci q_vector->eims_value = BIT(msix_vector); 84462306a36Sopenharmony_ci break; 84562306a36Sopenharmony_ci default: 84662306a36Sopenharmony_ci BUG(); 84762306a36Sopenharmony_ci break; 84862306a36Sopenharmony_ci } 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci /* add q_vector eims value to global eims_enable_mask */ 85162306a36Sopenharmony_ci adapter->eims_enable_mask |= q_vector->eims_value; 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci /* configure q_vector to set itr on first interrupt */ 85462306a36Sopenharmony_ci q_vector->set_itr = 1; 85562306a36Sopenharmony_ci} 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci/** 85862306a36Sopenharmony_ci * igb_configure_msix - Configure MSI-X hardware 85962306a36Sopenharmony_ci * @adapter: board private structure to initialize 86062306a36Sopenharmony_ci * 86162306a36Sopenharmony_ci * igb_configure_msix sets up the hardware to properly 86262306a36Sopenharmony_ci * generate MSI-X interrupts. 86362306a36Sopenharmony_ci **/ 86462306a36Sopenharmony_cistatic void igb_configure_msix(struct igb_adapter *adapter) 86562306a36Sopenharmony_ci{ 86662306a36Sopenharmony_ci u32 tmp; 86762306a36Sopenharmony_ci int i, vector = 0; 86862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci adapter->eims_enable_mask = 0; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci /* set vector for other causes, i.e. link changes */ 87362306a36Sopenharmony_ci switch (hw->mac.type) { 87462306a36Sopenharmony_ci case e1000_82575: 87562306a36Sopenharmony_ci tmp = rd32(E1000_CTRL_EXT); 87662306a36Sopenharmony_ci /* enable MSI-X PBA support*/ 87762306a36Sopenharmony_ci tmp |= E1000_CTRL_EXT_PBA_CLR; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci /* Auto-Mask interrupts upon ICR read. */ 88062306a36Sopenharmony_ci tmp |= E1000_CTRL_EXT_EIAME; 88162306a36Sopenharmony_ci tmp |= E1000_CTRL_EXT_IRCA; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, tmp); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci /* enable msix_other interrupt */ 88662306a36Sopenharmony_ci array_wr32(E1000_MSIXBM(0), vector++, E1000_EIMS_OTHER); 88762306a36Sopenharmony_ci adapter->eims_other = E1000_EIMS_OTHER; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci break; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci case e1000_82576: 89262306a36Sopenharmony_ci case e1000_82580: 89362306a36Sopenharmony_ci case e1000_i350: 89462306a36Sopenharmony_ci case e1000_i354: 89562306a36Sopenharmony_ci case e1000_i210: 89662306a36Sopenharmony_ci case e1000_i211: 89762306a36Sopenharmony_ci /* Turn on MSI-X capability first, or our settings 89862306a36Sopenharmony_ci * won't stick. And it will take days to debug. 89962306a36Sopenharmony_ci */ 90062306a36Sopenharmony_ci wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE | 90162306a36Sopenharmony_ci E1000_GPIE_PBA | E1000_GPIE_EIAME | 90262306a36Sopenharmony_ci E1000_GPIE_NSICR); 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci /* enable msix_other interrupt */ 90562306a36Sopenharmony_ci adapter->eims_other = BIT(vector); 90662306a36Sopenharmony_ci tmp = (vector++ | E1000_IVAR_VALID) << 8; 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci wr32(E1000_IVAR_MISC, tmp); 90962306a36Sopenharmony_ci break; 91062306a36Sopenharmony_ci default: 91162306a36Sopenharmony_ci /* do nothing, since nothing else supports MSI-X */ 91262306a36Sopenharmony_ci break; 91362306a36Sopenharmony_ci } /* switch (hw->mac.type) */ 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci adapter->eims_enable_mask |= adapter->eims_other; 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) 91862306a36Sopenharmony_ci igb_assign_vector(adapter->q_vector[i], vector++); 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci wrfl(); 92162306a36Sopenharmony_ci} 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci/** 92462306a36Sopenharmony_ci * igb_request_msix - Initialize MSI-X interrupts 92562306a36Sopenharmony_ci * @adapter: board private structure to initialize 92662306a36Sopenharmony_ci * 92762306a36Sopenharmony_ci * igb_request_msix allocates MSI-X vectors and requests interrupts from the 92862306a36Sopenharmony_ci * kernel. 92962306a36Sopenharmony_ci **/ 93062306a36Sopenharmony_cistatic int igb_request_msix(struct igb_adapter *adapter) 93162306a36Sopenharmony_ci{ 93262306a36Sopenharmony_ci unsigned int num_q_vectors = adapter->num_q_vectors; 93362306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 93462306a36Sopenharmony_ci int i, err = 0, vector = 0, free_vector = 0; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci err = request_irq(adapter->msix_entries[vector].vector, 93762306a36Sopenharmony_ci igb_msix_other, 0, netdev->name, adapter); 93862306a36Sopenharmony_ci if (err) 93962306a36Sopenharmony_ci goto err_out; 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci if (num_q_vectors > MAX_Q_VECTORS) { 94262306a36Sopenharmony_ci num_q_vectors = MAX_Q_VECTORS; 94362306a36Sopenharmony_ci dev_warn(&adapter->pdev->dev, 94462306a36Sopenharmony_ci "The number of queue vectors (%d) is higher than max allowed (%d)\n", 94562306a36Sopenharmony_ci adapter->num_q_vectors, MAX_Q_VECTORS); 94662306a36Sopenharmony_ci } 94762306a36Sopenharmony_ci for (i = 0; i < num_q_vectors; i++) { 94862306a36Sopenharmony_ci struct igb_q_vector *q_vector = adapter->q_vector[i]; 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci vector++; 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci q_vector->itr_register = adapter->io_addr + E1000_EITR(vector); 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci if (q_vector->rx.ring && q_vector->tx.ring) 95562306a36Sopenharmony_ci sprintf(q_vector->name, "%s-TxRx-%u", netdev->name, 95662306a36Sopenharmony_ci q_vector->rx.ring->queue_index); 95762306a36Sopenharmony_ci else if (q_vector->tx.ring) 95862306a36Sopenharmony_ci sprintf(q_vector->name, "%s-tx-%u", netdev->name, 95962306a36Sopenharmony_ci q_vector->tx.ring->queue_index); 96062306a36Sopenharmony_ci else if (q_vector->rx.ring) 96162306a36Sopenharmony_ci sprintf(q_vector->name, "%s-rx-%u", netdev->name, 96262306a36Sopenharmony_ci q_vector->rx.ring->queue_index); 96362306a36Sopenharmony_ci else 96462306a36Sopenharmony_ci sprintf(q_vector->name, "%s-unused", netdev->name); 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci err = request_irq(adapter->msix_entries[vector].vector, 96762306a36Sopenharmony_ci igb_msix_ring, 0, q_vector->name, 96862306a36Sopenharmony_ci q_vector); 96962306a36Sopenharmony_ci if (err) 97062306a36Sopenharmony_ci goto err_free; 97162306a36Sopenharmony_ci } 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci igb_configure_msix(adapter); 97462306a36Sopenharmony_ci return 0; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_cierr_free: 97762306a36Sopenharmony_ci /* free already assigned IRQs */ 97862306a36Sopenharmony_ci free_irq(adapter->msix_entries[free_vector++].vector, adapter); 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci vector--; 98162306a36Sopenharmony_ci for (i = 0; i < vector; i++) { 98262306a36Sopenharmony_ci free_irq(adapter->msix_entries[free_vector++].vector, 98362306a36Sopenharmony_ci adapter->q_vector[i]); 98462306a36Sopenharmony_ci } 98562306a36Sopenharmony_cierr_out: 98662306a36Sopenharmony_ci return err; 98762306a36Sopenharmony_ci} 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci/** 99062306a36Sopenharmony_ci * igb_free_q_vector - Free memory allocated for specific interrupt vector 99162306a36Sopenharmony_ci * @adapter: board private structure to initialize 99262306a36Sopenharmony_ci * @v_idx: Index of vector to be freed 99362306a36Sopenharmony_ci * 99462306a36Sopenharmony_ci * This function frees the memory allocated to the q_vector. 99562306a36Sopenharmony_ci **/ 99662306a36Sopenharmony_cistatic void igb_free_q_vector(struct igb_adapter *adapter, int v_idx) 99762306a36Sopenharmony_ci{ 99862306a36Sopenharmony_ci struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci adapter->q_vector[v_idx] = NULL; 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci /* igb_get_stats64() might access the rings on this vector, 100362306a36Sopenharmony_ci * we must wait a grace period before freeing it. 100462306a36Sopenharmony_ci */ 100562306a36Sopenharmony_ci if (q_vector) 100662306a36Sopenharmony_ci kfree_rcu(q_vector, rcu); 100762306a36Sopenharmony_ci} 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci/** 101062306a36Sopenharmony_ci * igb_reset_q_vector - Reset config for interrupt vector 101162306a36Sopenharmony_ci * @adapter: board private structure to initialize 101262306a36Sopenharmony_ci * @v_idx: Index of vector to be reset 101362306a36Sopenharmony_ci * 101462306a36Sopenharmony_ci * If NAPI is enabled it will delete any references to the 101562306a36Sopenharmony_ci * NAPI struct. This is preparation for igb_free_q_vector. 101662306a36Sopenharmony_ci **/ 101762306a36Sopenharmony_cistatic void igb_reset_q_vector(struct igb_adapter *adapter, int v_idx) 101862306a36Sopenharmony_ci{ 101962306a36Sopenharmony_ci struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci /* Coming from igb_set_interrupt_capability, the vectors are not yet 102262306a36Sopenharmony_ci * allocated. So, q_vector is NULL so we should stop here. 102362306a36Sopenharmony_ci */ 102462306a36Sopenharmony_ci if (!q_vector) 102562306a36Sopenharmony_ci return; 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci if (q_vector->tx.ring) 102862306a36Sopenharmony_ci adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL; 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci if (q_vector->rx.ring) 103162306a36Sopenharmony_ci adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL; 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci netif_napi_del(&q_vector->napi); 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci} 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_cistatic void igb_reset_interrupt_capability(struct igb_adapter *adapter) 103862306a36Sopenharmony_ci{ 103962306a36Sopenharmony_ci int v_idx = adapter->num_q_vectors; 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) 104262306a36Sopenharmony_ci pci_disable_msix(adapter->pdev); 104362306a36Sopenharmony_ci else if (adapter->flags & IGB_FLAG_HAS_MSI) 104462306a36Sopenharmony_ci pci_disable_msi(adapter->pdev); 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci while (v_idx--) 104762306a36Sopenharmony_ci igb_reset_q_vector(adapter, v_idx); 104862306a36Sopenharmony_ci} 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci/** 105162306a36Sopenharmony_ci * igb_free_q_vectors - Free memory allocated for interrupt vectors 105262306a36Sopenharmony_ci * @adapter: board private structure to initialize 105362306a36Sopenharmony_ci * 105462306a36Sopenharmony_ci * This function frees the memory allocated to the q_vectors. In addition if 105562306a36Sopenharmony_ci * NAPI is enabled it will delete any references to the NAPI struct prior 105662306a36Sopenharmony_ci * to freeing the q_vector. 105762306a36Sopenharmony_ci **/ 105862306a36Sopenharmony_cistatic void igb_free_q_vectors(struct igb_adapter *adapter) 105962306a36Sopenharmony_ci{ 106062306a36Sopenharmony_ci int v_idx = adapter->num_q_vectors; 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci adapter->num_tx_queues = 0; 106362306a36Sopenharmony_ci adapter->num_rx_queues = 0; 106462306a36Sopenharmony_ci adapter->num_q_vectors = 0; 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci while (v_idx--) { 106762306a36Sopenharmony_ci igb_reset_q_vector(adapter, v_idx); 106862306a36Sopenharmony_ci igb_free_q_vector(adapter, v_idx); 106962306a36Sopenharmony_ci } 107062306a36Sopenharmony_ci} 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci/** 107362306a36Sopenharmony_ci * igb_clear_interrupt_scheme - reset the device to a state of no interrupts 107462306a36Sopenharmony_ci * @adapter: board private structure to initialize 107562306a36Sopenharmony_ci * 107662306a36Sopenharmony_ci * This function resets the device so that it has 0 Rx queues, Tx queues, and 107762306a36Sopenharmony_ci * MSI-X interrupts allocated. 107862306a36Sopenharmony_ci */ 107962306a36Sopenharmony_cistatic void igb_clear_interrupt_scheme(struct igb_adapter *adapter) 108062306a36Sopenharmony_ci{ 108162306a36Sopenharmony_ci igb_free_q_vectors(adapter); 108262306a36Sopenharmony_ci igb_reset_interrupt_capability(adapter); 108362306a36Sopenharmony_ci} 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci/** 108662306a36Sopenharmony_ci * igb_set_interrupt_capability - set MSI or MSI-X if supported 108762306a36Sopenharmony_ci * @adapter: board private structure to initialize 108862306a36Sopenharmony_ci * @msix: boolean value of MSIX capability 108962306a36Sopenharmony_ci * 109062306a36Sopenharmony_ci * Attempt to configure interrupts using the best available 109162306a36Sopenharmony_ci * capabilities of the hardware and kernel. 109262306a36Sopenharmony_ci **/ 109362306a36Sopenharmony_cistatic void igb_set_interrupt_capability(struct igb_adapter *adapter, bool msix) 109462306a36Sopenharmony_ci{ 109562306a36Sopenharmony_ci int err; 109662306a36Sopenharmony_ci int numvecs, i; 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci if (!msix) 109962306a36Sopenharmony_ci goto msi_only; 110062306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_HAS_MSIX; 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci /* Number of supported queues. */ 110362306a36Sopenharmony_ci adapter->num_rx_queues = adapter->rss_queues; 110462306a36Sopenharmony_ci if (adapter->vfs_allocated_count) 110562306a36Sopenharmony_ci adapter->num_tx_queues = 1; 110662306a36Sopenharmony_ci else 110762306a36Sopenharmony_ci adapter->num_tx_queues = adapter->rss_queues; 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci /* start with one vector for every Rx queue */ 111062306a36Sopenharmony_ci numvecs = adapter->num_rx_queues; 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci /* if Tx handler is separate add 1 for every Tx queue */ 111362306a36Sopenharmony_ci if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS)) 111462306a36Sopenharmony_ci numvecs += adapter->num_tx_queues; 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci /* store the number of vectors reserved for queues */ 111762306a36Sopenharmony_ci adapter->num_q_vectors = numvecs; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci /* add 1 vector for link status interrupts */ 112062306a36Sopenharmony_ci numvecs++; 112162306a36Sopenharmony_ci for (i = 0; i < numvecs; i++) 112262306a36Sopenharmony_ci adapter->msix_entries[i].entry = i; 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci err = pci_enable_msix_range(adapter->pdev, 112562306a36Sopenharmony_ci adapter->msix_entries, 112662306a36Sopenharmony_ci numvecs, 112762306a36Sopenharmony_ci numvecs); 112862306a36Sopenharmony_ci if (err > 0) 112962306a36Sopenharmony_ci return; 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci igb_reset_interrupt_capability(adapter); 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci /* If we can't do MSI-X, try MSI */ 113462306a36Sopenharmony_cimsi_only: 113562306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_HAS_MSIX; 113662306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 113762306a36Sopenharmony_ci /* disable SR-IOV for non MSI-X configurations */ 113862306a36Sopenharmony_ci if (adapter->vf_data) { 113962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 114062306a36Sopenharmony_ci /* disable iov and allow time for transactions to clear */ 114162306a36Sopenharmony_ci pci_disable_sriov(adapter->pdev); 114262306a36Sopenharmony_ci msleep(500); 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci kfree(adapter->vf_mac_list); 114562306a36Sopenharmony_ci adapter->vf_mac_list = NULL; 114662306a36Sopenharmony_ci kfree(adapter->vf_data); 114762306a36Sopenharmony_ci adapter->vf_data = NULL; 114862306a36Sopenharmony_ci wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ); 114962306a36Sopenharmony_ci wrfl(); 115062306a36Sopenharmony_ci msleep(100); 115162306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, "IOV Disabled\n"); 115262306a36Sopenharmony_ci } 115362306a36Sopenharmony_ci#endif 115462306a36Sopenharmony_ci adapter->vfs_allocated_count = 0; 115562306a36Sopenharmony_ci adapter->rss_queues = 1; 115662306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_QUEUE_PAIRS; 115762306a36Sopenharmony_ci adapter->num_rx_queues = 1; 115862306a36Sopenharmony_ci adapter->num_tx_queues = 1; 115962306a36Sopenharmony_ci adapter->num_q_vectors = 1; 116062306a36Sopenharmony_ci if (!pci_enable_msi(adapter->pdev)) 116162306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_HAS_MSI; 116262306a36Sopenharmony_ci} 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_cistatic void igb_add_ring(struct igb_ring *ring, 116562306a36Sopenharmony_ci struct igb_ring_container *head) 116662306a36Sopenharmony_ci{ 116762306a36Sopenharmony_ci head->ring = ring; 116862306a36Sopenharmony_ci head->count++; 116962306a36Sopenharmony_ci} 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci/** 117262306a36Sopenharmony_ci * igb_alloc_q_vector - Allocate memory for a single interrupt vector 117362306a36Sopenharmony_ci * @adapter: board private structure to initialize 117462306a36Sopenharmony_ci * @v_count: q_vectors allocated on adapter, used for ring interleaving 117562306a36Sopenharmony_ci * @v_idx: index of vector in adapter struct 117662306a36Sopenharmony_ci * @txr_count: total number of Tx rings to allocate 117762306a36Sopenharmony_ci * @txr_idx: index of first Tx ring to allocate 117862306a36Sopenharmony_ci * @rxr_count: total number of Rx rings to allocate 117962306a36Sopenharmony_ci * @rxr_idx: index of first Rx ring to allocate 118062306a36Sopenharmony_ci * 118162306a36Sopenharmony_ci * We allocate one q_vector. If allocation fails we return -ENOMEM. 118262306a36Sopenharmony_ci **/ 118362306a36Sopenharmony_cistatic int igb_alloc_q_vector(struct igb_adapter *adapter, 118462306a36Sopenharmony_ci int v_count, int v_idx, 118562306a36Sopenharmony_ci int txr_count, int txr_idx, 118662306a36Sopenharmony_ci int rxr_count, int rxr_idx) 118762306a36Sopenharmony_ci{ 118862306a36Sopenharmony_ci struct igb_q_vector *q_vector; 118962306a36Sopenharmony_ci struct igb_ring *ring; 119062306a36Sopenharmony_ci int ring_count; 119162306a36Sopenharmony_ci size_t size; 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci /* igb only supports 1 Tx and/or 1 Rx queue per vector */ 119462306a36Sopenharmony_ci if (txr_count > 1 || rxr_count > 1) 119562306a36Sopenharmony_ci return -ENOMEM; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci ring_count = txr_count + rxr_count; 119862306a36Sopenharmony_ci size = kmalloc_size_roundup(struct_size(q_vector, ring, ring_count)); 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci /* allocate q_vector and rings */ 120162306a36Sopenharmony_ci q_vector = adapter->q_vector[v_idx]; 120262306a36Sopenharmony_ci if (!q_vector) { 120362306a36Sopenharmony_ci q_vector = kzalloc(size, GFP_KERNEL); 120462306a36Sopenharmony_ci } else if (size > ksize(q_vector)) { 120562306a36Sopenharmony_ci struct igb_q_vector *new_q_vector; 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci new_q_vector = kzalloc(size, GFP_KERNEL); 120862306a36Sopenharmony_ci if (new_q_vector) 120962306a36Sopenharmony_ci kfree_rcu(q_vector, rcu); 121062306a36Sopenharmony_ci q_vector = new_q_vector; 121162306a36Sopenharmony_ci } else { 121262306a36Sopenharmony_ci memset(q_vector, 0, size); 121362306a36Sopenharmony_ci } 121462306a36Sopenharmony_ci if (!q_vector) 121562306a36Sopenharmony_ci return -ENOMEM; 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci /* initialize NAPI */ 121862306a36Sopenharmony_ci netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll); 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci /* tie q_vector and adapter together */ 122162306a36Sopenharmony_ci adapter->q_vector[v_idx] = q_vector; 122262306a36Sopenharmony_ci q_vector->adapter = adapter; 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci /* initialize work limits */ 122562306a36Sopenharmony_ci q_vector->tx.work_limit = adapter->tx_work_limit; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci /* initialize ITR configuration */ 122862306a36Sopenharmony_ci q_vector->itr_register = adapter->io_addr + E1000_EITR(0); 122962306a36Sopenharmony_ci q_vector->itr_val = IGB_START_ITR; 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci /* initialize pointer to rings */ 123262306a36Sopenharmony_ci ring = q_vector->ring; 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci /* intialize ITR */ 123562306a36Sopenharmony_ci if (rxr_count) { 123662306a36Sopenharmony_ci /* rx or rx/tx vector */ 123762306a36Sopenharmony_ci if (!adapter->rx_itr_setting || adapter->rx_itr_setting > 3) 123862306a36Sopenharmony_ci q_vector->itr_val = adapter->rx_itr_setting; 123962306a36Sopenharmony_ci } else { 124062306a36Sopenharmony_ci /* tx only vector */ 124162306a36Sopenharmony_ci if (!adapter->tx_itr_setting || adapter->tx_itr_setting > 3) 124262306a36Sopenharmony_ci q_vector->itr_val = adapter->tx_itr_setting; 124362306a36Sopenharmony_ci } 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci if (txr_count) { 124662306a36Sopenharmony_ci /* assign generic ring traits */ 124762306a36Sopenharmony_ci ring->dev = &adapter->pdev->dev; 124862306a36Sopenharmony_ci ring->netdev = adapter->netdev; 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci /* configure backlink on ring */ 125162306a36Sopenharmony_ci ring->q_vector = q_vector; 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci /* update q_vector Tx values */ 125462306a36Sopenharmony_ci igb_add_ring(ring, &q_vector->tx); 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci /* For 82575, context index must be unique per ring. */ 125762306a36Sopenharmony_ci if (adapter->hw.mac.type == e1000_82575) 125862306a36Sopenharmony_ci set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags); 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci /* apply Tx specific ring traits */ 126162306a36Sopenharmony_ci ring->count = adapter->tx_ring_count; 126262306a36Sopenharmony_ci ring->queue_index = txr_idx; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci ring->cbs_enable = false; 126562306a36Sopenharmony_ci ring->idleslope = 0; 126662306a36Sopenharmony_ci ring->sendslope = 0; 126762306a36Sopenharmony_ci ring->hicredit = 0; 126862306a36Sopenharmony_ci ring->locredit = 0; 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci u64_stats_init(&ring->tx_syncp); 127162306a36Sopenharmony_ci u64_stats_init(&ring->tx_syncp2); 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci /* assign ring to adapter */ 127462306a36Sopenharmony_ci adapter->tx_ring[txr_idx] = ring; 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci /* push pointer to next ring */ 127762306a36Sopenharmony_ci ring++; 127862306a36Sopenharmony_ci } 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci if (rxr_count) { 128162306a36Sopenharmony_ci /* assign generic ring traits */ 128262306a36Sopenharmony_ci ring->dev = &adapter->pdev->dev; 128362306a36Sopenharmony_ci ring->netdev = adapter->netdev; 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_ci /* configure backlink on ring */ 128662306a36Sopenharmony_ci ring->q_vector = q_vector; 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci /* update q_vector Rx values */ 128962306a36Sopenharmony_ci igb_add_ring(ring, &q_vector->rx); 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci /* set flag indicating ring supports SCTP checksum offload */ 129262306a36Sopenharmony_ci if (adapter->hw.mac.type >= e1000_82576) 129362306a36Sopenharmony_ci set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags); 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci /* On i350, i354, i210, and i211, loopback VLAN packets 129662306a36Sopenharmony_ci * have the tag byte-swapped. 129762306a36Sopenharmony_ci */ 129862306a36Sopenharmony_ci if (adapter->hw.mac.type >= e1000_i350) 129962306a36Sopenharmony_ci set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags); 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci /* apply Rx specific ring traits */ 130262306a36Sopenharmony_ci ring->count = adapter->rx_ring_count; 130362306a36Sopenharmony_ci ring->queue_index = rxr_idx; 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci u64_stats_init(&ring->rx_syncp); 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci /* assign ring to adapter */ 130862306a36Sopenharmony_ci adapter->rx_ring[rxr_idx] = ring; 130962306a36Sopenharmony_ci } 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci return 0; 131262306a36Sopenharmony_ci} 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci/** 131662306a36Sopenharmony_ci * igb_alloc_q_vectors - Allocate memory for interrupt vectors 131762306a36Sopenharmony_ci * @adapter: board private structure to initialize 131862306a36Sopenharmony_ci * 131962306a36Sopenharmony_ci * We allocate one q_vector per queue interrupt. If allocation fails we 132062306a36Sopenharmony_ci * return -ENOMEM. 132162306a36Sopenharmony_ci **/ 132262306a36Sopenharmony_cistatic int igb_alloc_q_vectors(struct igb_adapter *adapter) 132362306a36Sopenharmony_ci{ 132462306a36Sopenharmony_ci int q_vectors = adapter->num_q_vectors; 132562306a36Sopenharmony_ci int rxr_remaining = adapter->num_rx_queues; 132662306a36Sopenharmony_ci int txr_remaining = adapter->num_tx_queues; 132762306a36Sopenharmony_ci int rxr_idx = 0, txr_idx = 0, v_idx = 0; 132862306a36Sopenharmony_ci int err; 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci if (q_vectors >= (rxr_remaining + txr_remaining)) { 133162306a36Sopenharmony_ci for (; rxr_remaining; v_idx++) { 133262306a36Sopenharmony_ci err = igb_alloc_q_vector(adapter, q_vectors, v_idx, 133362306a36Sopenharmony_ci 0, 0, 1, rxr_idx); 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci if (err) 133662306a36Sopenharmony_ci goto err_out; 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci /* update counts and index */ 133962306a36Sopenharmony_ci rxr_remaining--; 134062306a36Sopenharmony_ci rxr_idx++; 134162306a36Sopenharmony_ci } 134262306a36Sopenharmony_ci } 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci for (; v_idx < q_vectors; v_idx++) { 134562306a36Sopenharmony_ci int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx); 134662306a36Sopenharmony_ci int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx); 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci err = igb_alloc_q_vector(adapter, q_vectors, v_idx, 134962306a36Sopenharmony_ci tqpv, txr_idx, rqpv, rxr_idx); 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci if (err) 135262306a36Sopenharmony_ci goto err_out; 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci /* update counts and index */ 135562306a36Sopenharmony_ci rxr_remaining -= rqpv; 135662306a36Sopenharmony_ci txr_remaining -= tqpv; 135762306a36Sopenharmony_ci rxr_idx++; 135862306a36Sopenharmony_ci txr_idx++; 135962306a36Sopenharmony_ci } 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci return 0; 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_cierr_out: 136462306a36Sopenharmony_ci adapter->num_tx_queues = 0; 136562306a36Sopenharmony_ci adapter->num_rx_queues = 0; 136662306a36Sopenharmony_ci adapter->num_q_vectors = 0; 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci while (v_idx--) 136962306a36Sopenharmony_ci igb_free_q_vector(adapter, v_idx); 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci return -ENOMEM; 137262306a36Sopenharmony_ci} 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci/** 137562306a36Sopenharmony_ci * igb_init_interrupt_scheme - initialize interrupts, allocate queues/vectors 137662306a36Sopenharmony_ci * @adapter: board private structure to initialize 137762306a36Sopenharmony_ci * @msix: boolean value of MSIX capability 137862306a36Sopenharmony_ci * 137962306a36Sopenharmony_ci * This function initializes the interrupts and allocates all of the queues. 138062306a36Sopenharmony_ci **/ 138162306a36Sopenharmony_cistatic int igb_init_interrupt_scheme(struct igb_adapter *adapter, bool msix) 138262306a36Sopenharmony_ci{ 138362306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 138462306a36Sopenharmony_ci int err; 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci igb_set_interrupt_capability(adapter, msix); 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci err = igb_alloc_q_vectors(adapter); 138962306a36Sopenharmony_ci if (err) { 139062306a36Sopenharmony_ci dev_err(&pdev->dev, "Unable to allocate memory for vectors\n"); 139162306a36Sopenharmony_ci goto err_alloc_q_vectors; 139262306a36Sopenharmony_ci } 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci igb_cache_ring_register(adapter); 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci return 0; 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_cierr_alloc_q_vectors: 139962306a36Sopenharmony_ci igb_reset_interrupt_capability(adapter); 140062306a36Sopenharmony_ci return err; 140162306a36Sopenharmony_ci} 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci/** 140462306a36Sopenharmony_ci * igb_request_irq - initialize interrupts 140562306a36Sopenharmony_ci * @adapter: board private structure to initialize 140662306a36Sopenharmony_ci * 140762306a36Sopenharmony_ci * Attempts to configure interrupts using the best available 140862306a36Sopenharmony_ci * capabilities of the hardware and kernel. 140962306a36Sopenharmony_ci **/ 141062306a36Sopenharmony_cistatic int igb_request_irq(struct igb_adapter *adapter) 141162306a36Sopenharmony_ci{ 141262306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 141362306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 141462306a36Sopenharmony_ci int err = 0; 141562306a36Sopenharmony_ci 141662306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) { 141762306a36Sopenharmony_ci err = igb_request_msix(adapter); 141862306a36Sopenharmony_ci if (!err) 141962306a36Sopenharmony_ci goto request_done; 142062306a36Sopenharmony_ci /* fall back to MSI */ 142162306a36Sopenharmony_ci igb_free_all_tx_resources(adapter); 142262306a36Sopenharmony_ci igb_free_all_rx_resources(adapter); 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_ci igb_clear_interrupt_scheme(adapter); 142562306a36Sopenharmony_ci err = igb_init_interrupt_scheme(adapter, false); 142662306a36Sopenharmony_ci if (err) 142762306a36Sopenharmony_ci goto request_done; 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci igb_setup_all_tx_resources(adapter); 143062306a36Sopenharmony_ci igb_setup_all_rx_resources(adapter); 143162306a36Sopenharmony_ci igb_configure(adapter); 143262306a36Sopenharmony_ci } 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci igb_assign_vector(adapter->q_vector[0], 0); 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSI) { 143762306a36Sopenharmony_ci err = request_irq(pdev->irq, igb_intr_msi, 0, 143862306a36Sopenharmony_ci netdev->name, adapter); 143962306a36Sopenharmony_ci if (!err) 144062306a36Sopenharmony_ci goto request_done; 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci /* fall back to legacy interrupts */ 144362306a36Sopenharmony_ci igb_reset_interrupt_capability(adapter); 144462306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_HAS_MSI; 144562306a36Sopenharmony_ci } 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci err = request_irq(pdev->irq, igb_intr, IRQF_SHARED, 144862306a36Sopenharmony_ci netdev->name, adapter); 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci if (err) 145162306a36Sopenharmony_ci dev_err(&pdev->dev, "Error %d getting interrupt\n", 145262306a36Sopenharmony_ci err); 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_cirequest_done: 145562306a36Sopenharmony_ci return err; 145662306a36Sopenharmony_ci} 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_cistatic void igb_free_irq(struct igb_adapter *adapter) 145962306a36Sopenharmony_ci{ 146062306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) { 146162306a36Sopenharmony_ci int vector = 0, i; 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci free_irq(adapter->msix_entries[vector++].vector, adapter); 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) 146662306a36Sopenharmony_ci free_irq(adapter->msix_entries[vector++].vector, 146762306a36Sopenharmony_ci adapter->q_vector[i]); 146862306a36Sopenharmony_ci } else { 146962306a36Sopenharmony_ci free_irq(adapter->pdev->irq, adapter); 147062306a36Sopenharmony_ci } 147162306a36Sopenharmony_ci} 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci/** 147462306a36Sopenharmony_ci * igb_irq_disable - Mask off interrupt generation on the NIC 147562306a36Sopenharmony_ci * @adapter: board private structure 147662306a36Sopenharmony_ci **/ 147762306a36Sopenharmony_cistatic void igb_irq_disable(struct igb_adapter *adapter) 147862306a36Sopenharmony_ci{ 147962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci /* we need to be careful when disabling interrupts. The VFs are also 148262306a36Sopenharmony_ci * mapped into these registers and so clearing the bits can cause 148362306a36Sopenharmony_ci * issues on the VF drivers so we only need to clear what we set 148462306a36Sopenharmony_ci */ 148562306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) { 148662306a36Sopenharmony_ci u32 regval = rd32(E1000_EIAM); 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci wr32(E1000_EIAM, regval & ~adapter->eims_enable_mask); 148962306a36Sopenharmony_ci wr32(E1000_EIMC, adapter->eims_enable_mask); 149062306a36Sopenharmony_ci regval = rd32(E1000_EIAC); 149162306a36Sopenharmony_ci wr32(E1000_EIAC, regval & ~adapter->eims_enable_mask); 149262306a36Sopenharmony_ci } 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci wr32(E1000_IAM, 0); 149562306a36Sopenharmony_ci wr32(E1000_IMC, ~0); 149662306a36Sopenharmony_ci wrfl(); 149762306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) { 149862306a36Sopenharmony_ci int i; 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) 150162306a36Sopenharmony_ci synchronize_irq(adapter->msix_entries[i].vector); 150262306a36Sopenharmony_ci } else { 150362306a36Sopenharmony_ci synchronize_irq(adapter->pdev->irq); 150462306a36Sopenharmony_ci } 150562306a36Sopenharmony_ci} 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci/** 150862306a36Sopenharmony_ci * igb_irq_enable - Enable default interrupt generation settings 150962306a36Sopenharmony_ci * @adapter: board private structure 151062306a36Sopenharmony_ci **/ 151162306a36Sopenharmony_cistatic void igb_irq_enable(struct igb_adapter *adapter) 151262306a36Sopenharmony_ci{ 151362306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) { 151662306a36Sopenharmony_ci u32 ims = E1000_IMS_LSC | E1000_IMS_DOUTSYNC | E1000_IMS_DRSTA; 151762306a36Sopenharmony_ci u32 regval = rd32(E1000_EIAC); 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci wr32(E1000_EIAC, regval | adapter->eims_enable_mask); 152062306a36Sopenharmony_ci regval = rd32(E1000_EIAM); 152162306a36Sopenharmony_ci wr32(E1000_EIAM, regval | adapter->eims_enable_mask); 152262306a36Sopenharmony_ci wr32(E1000_EIMS, adapter->eims_enable_mask); 152362306a36Sopenharmony_ci if (adapter->vfs_allocated_count) { 152462306a36Sopenharmony_ci wr32(E1000_MBVFIMR, 0xFF); 152562306a36Sopenharmony_ci ims |= E1000_IMS_VMMB; 152662306a36Sopenharmony_ci } 152762306a36Sopenharmony_ci wr32(E1000_IMS, ims); 152862306a36Sopenharmony_ci } else { 152962306a36Sopenharmony_ci wr32(E1000_IMS, IMS_ENABLE_MASK | 153062306a36Sopenharmony_ci E1000_IMS_DRSTA); 153162306a36Sopenharmony_ci wr32(E1000_IAM, IMS_ENABLE_MASK | 153262306a36Sopenharmony_ci E1000_IMS_DRSTA); 153362306a36Sopenharmony_ci } 153462306a36Sopenharmony_ci} 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_cistatic void igb_update_mng_vlan(struct igb_adapter *adapter) 153762306a36Sopenharmony_ci{ 153862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 153962306a36Sopenharmony_ci u16 pf_id = adapter->vfs_allocated_count; 154062306a36Sopenharmony_ci u16 vid = adapter->hw.mng_cookie.vlan_id; 154162306a36Sopenharmony_ci u16 old_vid = adapter->mng_vlan_id; 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci if (hw->mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) { 154462306a36Sopenharmony_ci /* add VID to filter table */ 154562306a36Sopenharmony_ci igb_vfta_set(hw, vid, pf_id, true, true); 154662306a36Sopenharmony_ci adapter->mng_vlan_id = vid; 154762306a36Sopenharmony_ci } else { 154862306a36Sopenharmony_ci adapter->mng_vlan_id = IGB_MNG_VLAN_NONE; 154962306a36Sopenharmony_ci } 155062306a36Sopenharmony_ci 155162306a36Sopenharmony_ci if ((old_vid != (u16)IGB_MNG_VLAN_NONE) && 155262306a36Sopenharmony_ci (vid != old_vid) && 155362306a36Sopenharmony_ci !test_bit(old_vid, adapter->active_vlans)) { 155462306a36Sopenharmony_ci /* remove VID from filter table */ 155562306a36Sopenharmony_ci igb_vfta_set(hw, vid, pf_id, false, true); 155662306a36Sopenharmony_ci } 155762306a36Sopenharmony_ci} 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci/** 156062306a36Sopenharmony_ci * igb_release_hw_control - release control of the h/w to f/w 156162306a36Sopenharmony_ci * @adapter: address of board private structure 156262306a36Sopenharmony_ci * 156362306a36Sopenharmony_ci * igb_release_hw_control resets CTRL_EXT:DRV_LOAD bit. 156462306a36Sopenharmony_ci * For ASF and Pass Through versions of f/w this means that the 156562306a36Sopenharmony_ci * driver is no longer loaded. 156662306a36Sopenharmony_ci **/ 156762306a36Sopenharmony_cistatic void igb_release_hw_control(struct igb_adapter *adapter) 156862306a36Sopenharmony_ci{ 156962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 157062306a36Sopenharmony_ci u32 ctrl_ext; 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci /* Let firmware take over control of h/w */ 157362306a36Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 157462306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, 157562306a36Sopenharmony_ci ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); 157662306a36Sopenharmony_ci} 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci/** 157962306a36Sopenharmony_ci * igb_get_hw_control - get control of the h/w from f/w 158062306a36Sopenharmony_ci * @adapter: address of board private structure 158162306a36Sopenharmony_ci * 158262306a36Sopenharmony_ci * igb_get_hw_control sets CTRL_EXT:DRV_LOAD bit. 158362306a36Sopenharmony_ci * For ASF and Pass Through versions of f/w this means that 158462306a36Sopenharmony_ci * the driver is loaded. 158562306a36Sopenharmony_ci **/ 158662306a36Sopenharmony_cistatic void igb_get_hw_control(struct igb_adapter *adapter) 158762306a36Sopenharmony_ci{ 158862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 158962306a36Sopenharmony_ci u32 ctrl_ext; 159062306a36Sopenharmony_ci 159162306a36Sopenharmony_ci /* Let firmware know the driver has taken over */ 159262306a36Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 159362306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, 159462306a36Sopenharmony_ci ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); 159562306a36Sopenharmony_ci} 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_cistatic void enable_fqtss(struct igb_adapter *adapter, bool enable) 159862306a36Sopenharmony_ci{ 159962306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 160062306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 160162306a36Sopenharmony_ci 160262306a36Sopenharmony_ci WARN_ON(hw->mac.type != e1000_i210); 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci if (enable) 160562306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_FQTSS; 160662306a36Sopenharmony_ci else 160762306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_FQTSS; 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci if (netif_running(netdev)) 161062306a36Sopenharmony_ci schedule_work(&adapter->reset_task); 161162306a36Sopenharmony_ci} 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_cistatic bool is_fqtss_enabled(struct igb_adapter *adapter) 161462306a36Sopenharmony_ci{ 161562306a36Sopenharmony_ci return (adapter->flags & IGB_FLAG_FQTSS) ? true : false; 161662306a36Sopenharmony_ci} 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_cistatic void set_tx_desc_fetch_prio(struct e1000_hw *hw, int queue, 161962306a36Sopenharmony_ci enum tx_queue_prio prio) 162062306a36Sopenharmony_ci{ 162162306a36Sopenharmony_ci u32 val; 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci WARN_ON(hw->mac.type != e1000_i210); 162462306a36Sopenharmony_ci WARN_ON(queue < 0 || queue > 4); 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci val = rd32(E1000_I210_TXDCTL(queue)); 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci if (prio == TX_QUEUE_PRIO_HIGH) 162962306a36Sopenharmony_ci val |= E1000_TXDCTL_PRIORITY; 163062306a36Sopenharmony_ci else 163162306a36Sopenharmony_ci val &= ~E1000_TXDCTL_PRIORITY; 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci wr32(E1000_I210_TXDCTL(queue), val); 163462306a36Sopenharmony_ci} 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_cistatic void set_queue_mode(struct e1000_hw *hw, int queue, enum queue_mode mode) 163762306a36Sopenharmony_ci{ 163862306a36Sopenharmony_ci u32 val; 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci WARN_ON(hw->mac.type != e1000_i210); 164162306a36Sopenharmony_ci WARN_ON(queue < 0 || queue > 1); 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci val = rd32(E1000_I210_TQAVCC(queue)); 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci if (mode == QUEUE_MODE_STREAM_RESERVATION) 164662306a36Sopenharmony_ci val |= E1000_TQAVCC_QUEUEMODE; 164762306a36Sopenharmony_ci else 164862306a36Sopenharmony_ci val &= ~E1000_TQAVCC_QUEUEMODE; 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci wr32(E1000_I210_TQAVCC(queue), val); 165162306a36Sopenharmony_ci} 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_cistatic bool is_any_cbs_enabled(struct igb_adapter *adapter) 165462306a36Sopenharmony_ci{ 165562306a36Sopenharmony_ci int i; 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 165862306a36Sopenharmony_ci if (adapter->tx_ring[i]->cbs_enable) 165962306a36Sopenharmony_ci return true; 166062306a36Sopenharmony_ci } 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci return false; 166362306a36Sopenharmony_ci} 166462306a36Sopenharmony_ci 166562306a36Sopenharmony_cistatic bool is_any_txtime_enabled(struct igb_adapter *adapter) 166662306a36Sopenharmony_ci{ 166762306a36Sopenharmony_ci int i; 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 167062306a36Sopenharmony_ci if (adapter->tx_ring[i]->launchtime_enable) 167162306a36Sopenharmony_ci return true; 167262306a36Sopenharmony_ci } 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci return false; 167562306a36Sopenharmony_ci} 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci/** 167862306a36Sopenharmony_ci * igb_config_tx_modes - Configure "Qav Tx mode" features on igb 167962306a36Sopenharmony_ci * @adapter: pointer to adapter struct 168062306a36Sopenharmony_ci * @queue: queue number 168162306a36Sopenharmony_ci * 168262306a36Sopenharmony_ci * Configure CBS and Launchtime for a given hardware queue. 168362306a36Sopenharmony_ci * Parameters are retrieved from the correct Tx ring, so 168462306a36Sopenharmony_ci * igb_save_cbs_params() and igb_save_txtime_params() should be used 168562306a36Sopenharmony_ci * for setting those correctly prior to this function being called. 168662306a36Sopenharmony_ci **/ 168762306a36Sopenharmony_cistatic void igb_config_tx_modes(struct igb_adapter *adapter, int queue) 168862306a36Sopenharmony_ci{ 168962306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 169062306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 169162306a36Sopenharmony_ci struct igb_ring *ring; 169262306a36Sopenharmony_ci u32 tqavcc, tqavctrl; 169362306a36Sopenharmony_ci u16 value; 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_ci WARN_ON(hw->mac.type != e1000_i210); 169662306a36Sopenharmony_ci WARN_ON(queue < 0 || queue > 1); 169762306a36Sopenharmony_ci ring = adapter->tx_ring[queue]; 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci /* If any of the Qav features is enabled, configure queues as SR and 170062306a36Sopenharmony_ci * with HIGH PRIO. If none is, then configure them with LOW PRIO and 170162306a36Sopenharmony_ci * as SP. 170262306a36Sopenharmony_ci */ 170362306a36Sopenharmony_ci if (ring->cbs_enable || ring->launchtime_enable) { 170462306a36Sopenharmony_ci set_tx_desc_fetch_prio(hw, queue, TX_QUEUE_PRIO_HIGH); 170562306a36Sopenharmony_ci set_queue_mode(hw, queue, QUEUE_MODE_STREAM_RESERVATION); 170662306a36Sopenharmony_ci } else { 170762306a36Sopenharmony_ci set_tx_desc_fetch_prio(hw, queue, TX_QUEUE_PRIO_LOW); 170862306a36Sopenharmony_ci set_queue_mode(hw, queue, QUEUE_MODE_STRICT_PRIORITY); 170962306a36Sopenharmony_ci } 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci /* If CBS is enabled, set DataTranARB and config its parameters. */ 171262306a36Sopenharmony_ci if (ring->cbs_enable || queue == 0) { 171362306a36Sopenharmony_ci /* i210 does not allow the queue 0 to be in the Strict 171462306a36Sopenharmony_ci * Priority mode while the Qav mode is enabled, so, 171562306a36Sopenharmony_ci * instead of disabling strict priority mode, we give 171662306a36Sopenharmony_ci * queue 0 the maximum of credits possible. 171762306a36Sopenharmony_ci * 171862306a36Sopenharmony_ci * See section 8.12.19 of the i210 datasheet, "Note: 171962306a36Sopenharmony_ci * Queue0 QueueMode must be set to 1b when 172062306a36Sopenharmony_ci * TransmitMode is set to Qav." 172162306a36Sopenharmony_ci */ 172262306a36Sopenharmony_ci if (queue == 0 && !ring->cbs_enable) { 172362306a36Sopenharmony_ci /* max "linkspeed" idleslope in kbps */ 172462306a36Sopenharmony_ci ring->idleslope = 1000000; 172562306a36Sopenharmony_ci ring->hicredit = ETH_FRAME_LEN; 172662306a36Sopenharmony_ci } 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci /* Always set data transfer arbitration to credit-based 172962306a36Sopenharmony_ci * shaper algorithm on TQAVCTRL if CBS is enabled for any of 173062306a36Sopenharmony_ci * the queues. 173162306a36Sopenharmony_ci */ 173262306a36Sopenharmony_ci tqavctrl = rd32(E1000_I210_TQAVCTRL); 173362306a36Sopenharmony_ci tqavctrl |= E1000_TQAVCTRL_DATATRANARB; 173462306a36Sopenharmony_ci wr32(E1000_I210_TQAVCTRL, tqavctrl); 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ci /* According to i210 datasheet section 7.2.7.7, we should set 173762306a36Sopenharmony_ci * the 'idleSlope' field from TQAVCC register following the 173862306a36Sopenharmony_ci * equation: 173962306a36Sopenharmony_ci * 174062306a36Sopenharmony_ci * For 100 Mbps link speed: 174162306a36Sopenharmony_ci * 174262306a36Sopenharmony_ci * value = BW * 0x7735 * 0.2 (E1) 174362306a36Sopenharmony_ci * 174462306a36Sopenharmony_ci * For 1000Mbps link speed: 174562306a36Sopenharmony_ci * 174662306a36Sopenharmony_ci * value = BW * 0x7735 * 2 (E2) 174762306a36Sopenharmony_ci * 174862306a36Sopenharmony_ci * E1 and E2 can be merged into one equation as shown below. 174962306a36Sopenharmony_ci * Note that 'link-speed' is in Mbps. 175062306a36Sopenharmony_ci * 175162306a36Sopenharmony_ci * value = BW * 0x7735 * 2 * link-speed 175262306a36Sopenharmony_ci * -------------- (E3) 175362306a36Sopenharmony_ci * 1000 175462306a36Sopenharmony_ci * 175562306a36Sopenharmony_ci * 'BW' is the percentage bandwidth out of full link speed 175662306a36Sopenharmony_ci * which can be found with the following equation. Note that 175762306a36Sopenharmony_ci * idleSlope here is the parameter from this function which 175862306a36Sopenharmony_ci * is in kbps. 175962306a36Sopenharmony_ci * 176062306a36Sopenharmony_ci * BW = idleSlope 176162306a36Sopenharmony_ci * ----------------- (E4) 176262306a36Sopenharmony_ci * link-speed * 1000 176362306a36Sopenharmony_ci * 176462306a36Sopenharmony_ci * That said, we can come up with a generic equation to 176562306a36Sopenharmony_ci * calculate the value we should set it TQAVCC register by 176662306a36Sopenharmony_ci * replacing 'BW' in E3 by E4. The resulting equation is: 176762306a36Sopenharmony_ci * 176862306a36Sopenharmony_ci * value = idleSlope * 0x7735 * 2 * link-speed 176962306a36Sopenharmony_ci * ----------------- -------------- (E5) 177062306a36Sopenharmony_ci * link-speed * 1000 1000 177162306a36Sopenharmony_ci * 177262306a36Sopenharmony_ci * 'link-speed' is present in both sides of the fraction so 177362306a36Sopenharmony_ci * it is canceled out. The final equation is the following: 177462306a36Sopenharmony_ci * 177562306a36Sopenharmony_ci * value = idleSlope * 61034 177662306a36Sopenharmony_ci * ----------------- (E6) 177762306a36Sopenharmony_ci * 1000000 177862306a36Sopenharmony_ci * 177962306a36Sopenharmony_ci * NOTE: For i210, given the above, we can see that idleslope 178062306a36Sopenharmony_ci * is represented in 16.38431 kbps units by the value at 178162306a36Sopenharmony_ci * the TQAVCC register (1Gbps / 61034), which reduces 178262306a36Sopenharmony_ci * the granularity for idleslope increments. 178362306a36Sopenharmony_ci * For instance, if you want to configure a 2576kbps 178462306a36Sopenharmony_ci * idleslope, the value to be written on the register 178562306a36Sopenharmony_ci * would have to be 157.23. If rounded down, you end 178662306a36Sopenharmony_ci * up with less bandwidth available than originally 178762306a36Sopenharmony_ci * required (~2572 kbps). If rounded up, you end up 178862306a36Sopenharmony_ci * with a higher bandwidth (~2589 kbps). Below the 178962306a36Sopenharmony_ci * approach we take is to always round up the 179062306a36Sopenharmony_ci * calculated value, so the resulting bandwidth might 179162306a36Sopenharmony_ci * be slightly higher for some configurations. 179262306a36Sopenharmony_ci */ 179362306a36Sopenharmony_ci value = DIV_ROUND_UP_ULL(ring->idleslope * 61034ULL, 1000000); 179462306a36Sopenharmony_ci 179562306a36Sopenharmony_ci tqavcc = rd32(E1000_I210_TQAVCC(queue)); 179662306a36Sopenharmony_ci tqavcc &= ~E1000_TQAVCC_IDLESLOPE_MASK; 179762306a36Sopenharmony_ci tqavcc |= value; 179862306a36Sopenharmony_ci wr32(E1000_I210_TQAVCC(queue), tqavcc); 179962306a36Sopenharmony_ci 180062306a36Sopenharmony_ci wr32(E1000_I210_TQAVHC(queue), 180162306a36Sopenharmony_ci 0x80000000 + ring->hicredit * 0x7735); 180262306a36Sopenharmony_ci } else { 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_ci /* Set idleSlope to zero. */ 180562306a36Sopenharmony_ci tqavcc = rd32(E1000_I210_TQAVCC(queue)); 180662306a36Sopenharmony_ci tqavcc &= ~E1000_TQAVCC_IDLESLOPE_MASK; 180762306a36Sopenharmony_ci wr32(E1000_I210_TQAVCC(queue), tqavcc); 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci /* Set hiCredit to zero. */ 181062306a36Sopenharmony_ci wr32(E1000_I210_TQAVHC(queue), 0); 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci /* If CBS is not enabled for any queues anymore, then return to 181362306a36Sopenharmony_ci * the default state of Data Transmission Arbitration on 181462306a36Sopenharmony_ci * TQAVCTRL. 181562306a36Sopenharmony_ci */ 181662306a36Sopenharmony_ci if (!is_any_cbs_enabled(adapter)) { 181762306a36Sopenharmony_ci tqavctrl = rd32(E1000_I210_TQAVCTRL); 181862306a36Sopenharmony_ci tqavctrl &= ~E1000_TQAVCTRL_DATATRANARB; 181962306a36Sopenharmony_ci wr32(E1000_I210_TQAVCTRL, tqavctrl); 182062306a36Sopenharmony_ci } 182162306a36Sopenharmony_ci } 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci /* If LaunchTime is enabled, set DataTranTIM. */ 182462306a36Sopenharmony_ci if (ring->launchtime_enable) { 182562306a36Sopenharmony_ci /* Always set DataTranTIM on TQAVCTRL if LaunchTime is enabled 182662306a36Sopenharmony_ci * for any of the SR queues, and configure fetchtime delta. 182762306a36Sopenharmony_ci * XXX NOTE: 182862306a36Sopenharmony_ci * - LaunchTime will be enabled for all SR queues. 182962306a36Sopenharmony_ci * - A fixed offset can be added relative to the launch 183062306a36Sopenharmony_ci * time of all packets if configured at reg LAUNCH_OS0. 183162306a36Sopenharmony_ci * We are keeping it as 0 for now (default value). 183262306a36Sopenharmony_ci */ 183362306a36Sopenharmony_ci tqavctrl = rd32(E1000_I210_TQAVCTRL); 183462306a36Sopenharmony_ci tqavctrl |= E1000_TQAVCTRL_DATATRANTIM | 183562306a36Sopenharmony_ci E1000_TQAVCTRL_FETCHTIME_DELTA; 183662306a36Sopenharmony_ci wr32(E1000_I210_TQAVCTRL, tqavctrl); 183762306a36Sopenharmony_ci } else { 183862306a36Sopenharmony_ci /* If Launchtime is not enabled for any SR queues anymore, 183962306a36Sopenharmony_ci * then clear DataTranTIM on TQAVCTRL and clear fetchtime delta, 184062306a36Sopenharmony_ci * effectively disabling Launchtime. 184162306a36Sopenharmony_ci */ 184262306a36Sopenharmony_ci if (!is_any_txtime_enabled(adapter)) { 184362306a36Sopenharmony_ci tqavctrl = rd32(E1000_I210_TQAVCTRL); 184462306a36Sopenharmony_ci tqavctrl &= ~E1000_TQAVCTRL_DATATRANTIM; 184562306a36Sopenharmony_ci tqavctrl &= ~E1000_TQAVCTRL_FETCHTIME_DELTA; 184662306a36Sopenharmony_ci wr32(E1000_I210_TQAVCTRL, tqavctrl); 184762306a36Sopenharmony_ci } 184862306a36Sopenharmony_ci } 184962306a36Sopenharmony_ci 185062306a36Sopenharmony_ci /* XXX: In i210 controller the sendSlope and loCredit parameters from 185162306a36Sopenharmony_ci * CBS are not configurable by software so we don't do any 'controller 185262306a36Sopenharmony_ci * configuration' in respect to these parameters. 185362306a36Sopenharmony_ci */ 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ci netdev_dbg(netdev, "Qav Tx mode: cbs %s, launchtime %s, queue %d idleslope %d sendslope %d hiCredit %d locredit %d\n", 185662306a36Sopenharmony_ci ring->cbs_enable ? "enabled" : "disabled", 185762306a36Sopenharmony_ci ring->launchtime_enable ? "enabled" : "disabled", 185862306a36Sopenharmony_ci queue, 185962306a36Sopenharmony_ci ring->idleslope, ring->sendslope, 186062306a36Sopenharmony_ci ring->hicredit, ring->locredit); 186162306a36Sopenharmony_ci} 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_cistatic int igb_save_txtime_params(struct igb_adapter *adapter, int queue, 186462306a36Sopenharmony_ci bool enable) 186562306a36Sopenharmony_ci{ 186662306a36Sopenharmony_ci struct igb_ring *ring; 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci if (queue < 0 || queue > adapter->num_tx_queues) 186962306a36Sopenharmony_ci return -EINVAL; 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci ring = adapter->tx_ring[queue]; 187262306a36Sopenharmony_ci ring->launchtime_enable = enable; 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci return 0; 187562306a36Sopenharmony_ci} 187662306a36Sopenharmony_ci 187762306a36Sopenharmony_cistatic int igb_save_cbs_params(struct igb_adapter *adapter, int queue, 187862306a36Sopenharmony_ci bool enable, int idleslope, int sendslope, 187962306a36Sopenharmony_ci int hicredit, int locredit) 188062306a36Sopenharmony_ci{ 188162306a36Sopenharmony_ci struct igb_ring *ring; 188262306a36Sopenharmony_ci 188362306a36Sopenharmony_ci if (queue < 0 || queue > adapter->num_tx_queues) 188462306a36Sopenharmony_ci return -EINVAL; 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci ring = adapter->tx_ring[queue]; 188762306a36Sopenharmony_ci 188862306a36Sopenharmony_ci ring->cbs_enable = enable; 188962306a36Sopenharmony_ci ring->idleslope = idleslope; 189062306a36Sopenharmony_ci ring->sendslope = sendslope; 189162306a36Sopenharmony_ci ring->hicredit = hicredit; 189262306a36Sopenharmony_ci ring->locredit = locredit; 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci return 0; 189562306a36Sopenharmony_ci} 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci/** 189862306a36Sopenharmony_ci * igb_setup_tx_mode - Switch to/from Qav Tx mode when applicable 189962306a36Sopenharmony_ci * @adapter: pointer to adapter struct 190062306a36Sopenharmony_ci * 190162306a36Sopenharmony_ci * Configure TQAVCTRL register switching the controller's Tx mode 190262306a36Sopenharmony_ci * if FQTSS mode is enabled or disabled. Additionally, will issue 190362306a36Sopenharmony_ci * a call to igb_config_tx_modes() per queue so any previously saved 190462306a36Sopenharmony_ci * Tx parameters are applied. 190562306a36Sopenharmony_ci **/ 190662306a36Sopenharmony_cistatic void igb_setup_tx_mode(struct igb_adapter *adapter) 190762306a36Sopenharmony_ci{ 190862306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 190962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 191062306a36Sopenharmony_ci u32 val; 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci /* Only i210 controller supports changing the transmission mode. */ 191362306a36Sopenharmony_ci if (hw->mac.type != e1000_i210) 191462306a36Sopenharmony_ci return; 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ci if (is_fqtss_enabled(adapter)) { 191762306a36Sopenharmony_ci int i, max_queue; 191862306a36Sopenharmony_ci 191962306a36Sopenharmony_ci /* Configure TQAVCTRL register: set transmit mode to 'Qav', 192062306a36Sopenharmony_ci * set data fetch arbitration to 'round robin', set SP_WAIT_SR 192162306a36Sopenharmony_ci * so SP queues wait for SR ones. 192262306a36Sopenharmony_ci */ 192362306a36Sopenharmony_ci val = rd32(E1000_I210_TQAVCTRL); 192462306a36Sopenharmony_ci val |= E1000_TQAVCTRL_XMIT_MODE | E1000_TQAVCTRL_SP_WAIT_SR; 192562306a36Sopenharmony_ci val &= ~E1000_TQAVCTRL_DATAFETCHARB; 192662306a36Sopenharmony_ci wr32(E1000_I210_TQAVCTRL, val); 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci /* Configure Tx and Rx packet buffers sizes as described in 192962306a36Sopenharmony_ci * i210 datasheet section 7.2.7.7. 193062306a36Sopenharmony_ci */ 193162306a36Sopenharmony_ci val = rd32(E1000_TXPBS); 193262306a36Sopenharmony_ci val &= ~I210_TXPBSIZE_MASK; 193362306a36Sopenharmony_ci val |= I210_TXPBSIZE_PB0_6KB | I210_TXPBSIZE_PB1_6KB | 193462306a36Sopenharmony_ci I210_TXPBSIZE_PB2_6KB | I210_TXPBSIZE_PB3_6KB; 193562306a36Sopenharmony_ci wr32(E1000_TXPBS, val); 193662306a36Sopenharmony_ci 193762306a36Sopenharmony_ci val = rd32(E1000_RXPBS); 193862306a36Sopenharmony_ci val &= ~I210_RXPBSIZE_MASK; 193962306a36Sopenharmony_ci val |= I210_RXPBSIZE_PB_30KB; 194062306a36Sopenharmony_ci wr32(E1000_RXPBS, val); 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_ci /* Section 8.12.9 states that MAX_TPKT_SIZE from DTXMXPKTSZ 194362306a36Sopenharmony_ci * register should not exceed the buffer size programmed in 194462306a36Sopenharmony_ci * TXPBS. The smallest buffer size programmed in TXPBS is 4kB 194562306a36Sopenharmony_ci * so according to the datasheet we should set MAX_TPKT_SIZE to 194662306a36Sopenharmony_ci * 4kB / 64. 194762306a36Sopenharmony_ci * 194862306a36Sopenharmony_ci * However, when we do so, no frame from queue 2 and 3 are 194962306a36Sopenharmony_ci * transmitted. It seems the MAX_TPKT_SIZE should not be great 195062306a36Sopenharmony_ci * or _equal_ to the buffer size programmed in TXPBS. For this 195162306a36Sopenharmony_ci * reason, we set MAX_ TPKT_SIZE to (4kB - 1) / 64. 195262306a36Sopenharmony_ci */ 195362306a36Sopenharmony_ci val = (4096 - 1) / 64; 195462306a36Sopenharmony_ci wr32(E1000_I210_DTXMXPKTSZ, val); 195562306a36Sopenharmony_ci 195662306a36Sopenharmony_ci /* Since FQTSS mode is enabled, apply any CBS configuration 195762306a36Sopenharmony_ci * previously set. If no previous CBS configuration has been 195862306a36Sopenharmony_ci * done, then the initial configuration is applied, which means 195962306a36Sopenharmony_ci * CBS is disabled. 196062306a36Sopenharmony_ci */ 196162306a36Sopenharmony_ci max_queue = (adapter->num_tx_queues < I210_SR_QUEUES_NUM) ? 196262306a36Sopenharmony_ci adapter->num_tx_queues : I210_SR_QUEUES_NUM; 196362306a36Sopenharmony_ci 196462306a36Sopenharmony_ci for (i = 0; i < max_queue; i++) { 196562306a36Sopenharmony_ci igb_config_tx_modes(adapter, i); 196662306a36Sopenharmony_ci } 196762306a36Sopenharmony_ci } else { 196862306a36Sopenharmony_ci wr32(E1000_RXPBS, I210_RXPBSIZE_DEFAULT); 196962306a36Sopenharmony_ci wr32(E1000_TXPBS, I210_TXPBSIZE_DEFAULT); 197062306a36Sopenharmony_ci wr32(E1000_I210_DTXMXPKTSZ, I210_DTXMXPKTSZ_DEFAULT); 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci val = rd32(E1000_I210_TQAVCTRL); 197362306a36Sopenharmony_ci /* According to Section 8.12.21, the other flags we've set when 197462306a36Sopenharmony_ci * enabling FQTSS are not relevant when disabling FQTSS so we 197562306a36Sopenharmony_ci * don't set they here. 197662306a36Sopenharmony_ci */ 197762306a36Sopenharmony_ci val &= ~E1000_TQAVCTRL_XMIT_MODE; 197862306a36Sopenharmony_ci wr32(E1000_I210_TQAVCTRL, val); 197962306a36Sopenharmony_ci } 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_ci netdev_dbg(netdev, "FQTSS %s\n", (is_fqtss_enabled(adapter)) ? 198262306a36Sopenharmony_ci "enabled" : "disabled"); 198362306a36Sopenharmony_ci} 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ci/** 198662306a36Sopenharmony_ci * igb_configure - configure the hardware for RX and TX 198762306a36Sopenharmony_ci * @adapter: private board structure 198862306a36Sopenharmony_ci **/ 198962306a36Sopenharmony_cistatic void igb_configure(struct igb_adapter *adapter) 199062306a36Sopenharmony_ci{ 199162306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 199262306a36Sopenharmony_ci int i; 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci igb_get_hw_control(adapter); 199562306a36Sopenharmony_ci igb_set_rx_mode(netdev); 199662306a36Sopenharmony_ci igb_setup_tx_mode(adapter); 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci igb_restore_vlan(adapter); 199962306a36Sopenharmony_ci 200062306a36Sopenharmony_ci igb_setup_tctl(adapter); 200162306a36Sopenharmony_ci igb_setup_mrqc(adapter); 200262306a36Sopenharmony_ci igb_setup_rctl(adapter); 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_ci igb_nfc_filter_restore(adapter); 200562306a36Sopenharmony_ci igb_configure_tx(adapter); 200662306a36Sopenharmony_ci igb_configure_rx(adapter); 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_ci igb_rx_fifo_flush_82575(&adapter->hw); 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci /* call igb_desc_unused which always leaves 201162306a36Sopenharmony_ci * at least 1 descriptor unused to make sure 201262306a36Sopenharmony_ci * next_to_use != next_to_clean 201362306a36Sopenharmony_ci */ 201462306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 201562306a36Sopenharmony_ci struct igb_ring *ring = adapter->rx_ring[i]; 201662306a36Sopenharmony_ci igb_alloc_rx_buffers(ring, igb_desc_unused(ring)); 201762306a36Sopenharmony_ci } 201862306a36Sopenharmony_ci} 201962306a36Sopenharmony_ci 202062306a36Sopenharmony_ci/** 202162306a36Sopenharmony_ci * igb_power_up_link - Power up the phy/serdes link 202262306a36Sopenharmony_ci * @adapter: address of board private structure 202362306a36Sopenharmony_ci **/ 202462306a36Sopenharmony_civoid igb_power_up_link(struct igb_adapter *adapter) 202562306a36Sopenharmony_ci{ 202662306a36Sopenharmony_ci igb_reset_phy(&adapter->hw); 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci if (adapter->hw.phy.media_type == e1000_media_type_copper) 202962306a36Sopenharmony_ci igb_power_up_phy_copper(&adapter->hw); 203062306a36Sopenharmony_ci else 203162306a36Sopenharmony_ci igb_power_up_serdes_link_82575(&adapter->hw); 203262306a36Sopenharmony_ci 203362306a36Sopenharmony_ci igb_setup_link(&adapter->hw); 203462306a36Sopenharmony_ci} 203562306a36Sopenharmony_ci 203662306a36Sopenharmony_ci/** 203762306a36Sopenharmony_ci * igb_power_down_link - Power down the phy/serdes link 203862306a36Sopenharmony_ci * @adapter: address of board private structure 203962306a36Sopenharmony_ci */ 204062306a36Sopenharmony_cistatic void igb_power_down_link(struct igb_adapter *adapter) 204162306a36Sopenharmony_ci{ 204262306a36Sopenharmony_ci if (adapter->hw.phy.media_type == e1000_media_type_copper) 204362306a36Sopenharmony_ci igb_power_down_phy_copper_82575(&adapter->hw); 204462306a36Sopenharmony_ci else 204562306a36Sopenharmony_ci igb_shutdown_serdes_link_82575(&adapter->hw); 204662306a36Sopenharmony_ci} 204762306a36Sopenharmony_ci 204862306a36Sopenharmony_ci/** 204962306a36Sopenharmony_ci * igb_check_swap_media - Detect and switch function for Media Auto Sense 205062306a36Sopenharmony_ci * @adapter: address of the board private structure 205162306a36Sopenharmony_ci **/ 205262306a36Sopenharmony_cistatic void igb_check_swap_media(struct igb_adapter *adapter) 205362306a36Sopenharmony_ci{ 205462306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 205562306a36Sopenharmony_ci u32 ctrl_ext, connsw; 205662306a36Sopenharmony_ci bool swap_now = false; 205762306a36Sopenharmony_ci 205862306a36Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 205962306a36Sopenharmony_ci connsw = rd32(E1000_CONNSW); 206062306a36Sopenharmony_ci 206162306a36Sopenharmony_ci /* need to live swap if current media is copper and we have fiber/serdes 206262306a36Sopenharmony_ci * to go to. 206362306a36Sopenharmony_ci */ 206462306a36Sopenharmony_ci 206562306a36Sopenharmony_ci if ((hw->phy.media_type == e1000_media_type_copper) && 206662306a36Sopenharmony_ci (!(connsw & E1000_CONNSW_AUTOSENSE_EN))) { 206762306a36Sopenharmony_ci swap_now = true; 206862306a36Sopenharmony_ci } else if ((hw->phy.media_type != e1000_media_type_copper) && 206962306a36Sopenharmony_ci !(connsw & E1000_CONNSW_SERDESD)) { 207062306a36Sopenharmony_ci /* copper signal takes time to appear */ 207162306a36Sopenharmony_ci if (adapter->copper_tries < 4) { 207262306a36Sopenharmony_ci adapter->copper_tries++; 207362306a36Sopenharmony_ci connsw |= E1000_CONNSW_AUTOSENSE_CONF; 207462306a36Sopenharmony_ci wr32(E1000_CONNSW, connsw); 207562306a36Sopenharmony_ci return; 207662306a36Sopenharmony_ci } else { 207762306a36Sopenharmony_ci adapter->copper_tries = 0; 207862306a36Sopenharmony_ci if ((connsw & E1000_CONNSW_PHYSD) && 207962306a36Sopenharmony_ci (!(connsw & E1000_CONNSW_PHY_PDN))) { 208062306a36Sopenharmony_ci swap_now = true; 208162306a36Sopenharmony_ci connsw &= ~E1000_CONNSW_AUTOSENSE_CONF; 208262306a36Sopenharmony_ci wr32(E1000_CONNSW, connsw); 208362306a36Sopenharmony_ci } 208462306a36Sopenharmony_ci } 208562306a36Sopenharmony_ci } 208662306a36Sopenharmony_ci 208762306a36Sopenharmony_ci if (!swap_now) 208862306a36Sopenharmony_ci return; 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_ci switch (hw->phy.media_type) { 209162306a36Sopenharmony_ci case e1000_media_type_copper: 209262306a36Sopenharmony_ci netdev_info(adapter->netdev, 209362306a36Sopenharmony_ci "MAS: changing media to fiber/serdes\n"); 209462306a36Sopenharmony_ci ctrl_ext |= 209562306a36Sopenharmony_ci E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; 209662306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_MEDIA_RESET; 209762306a36Sopenharmony_ci adapter->copper_tries = 0; 209862306a36Sopenharmony_ci break; 209962306a36Sopenharmony_ci case e1000_media_type_internal_serdes: 210062306a36Sopenharmony_ci case e1000_media_type_fiber: 210162306a36Sopenharmony_ci netdev_info(adapter->netdev, 210262306a36Sopenharmony_ci "MAS: changing media to copper\n"); 210362306a36Sopenharmony_ci ctrl_ext &= 210462306a36Sopenharmony_ci ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; 210562306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_MEDIA_RESET; 210662306a36Sopenharmony_ci break; 210762306a36Sopenharmony_ci default: 210862306a36Sopenharmony_ci /* shouldn't get here during regular operation */ 210962306a36Sopenharmony_ci netdev_err(adapter->netdev, 211062306a36Sopenharmony_ci "AMS: Invalid media type found, returning\n"); 211162306a36Sopenharmony_ci break; 211262306a36Sopenharmony_ci } 211362306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, ctrl_ext); 211462306a36Sopenharmony_ci} 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci/** 211762306a36Sopenharmony_ci * igb_up - Open the interface and prepare it to handle traffic 211862306a36Sopenharmony_ci * @adapter: board private structure 211962306a36Sopenharmony_ci **/ 212062306a36Sopenharmony_ciint igb_up(struct igb_adapter *adapter) 212162306a36Sopenharmony_ci{ 212262306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 212362306a36Sopenharmony_ci int i; 212462306a36Sopenharmony_ci 212562306a36Sopenharmony_ci /* hardware has been reset, we need to reload some things */ 212662306a36Sopenharmony_ci igb_configure(adapter); 212762306a36Sopenharmony_ci 212862306a36Sopenharmony_ci clear_bit(__IGB_DOWN, &adapter->state); 212962306a36Sopenharmony_ci 213062306a36Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) 213162306a36Sopenharmony_ci napi_enable(&(adapter->q_vector[i]->napi)); 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) 213462306a36Sopenharmony_ci igb_configure_msix(adapter); 213562306a36Sopenharmony_ci else 213662306a36Sopenharmony_ci igb_assign_vector(adapter->q_vector[0], 0); 213762306a36Sopenharmony_ci 213862306a36Sopenharmony_ci /* Clear any pending interrupts. */ 213962306a36Sopenharmony_ci rd32(E1000_TSICR); 214062306a36Sopenharmony_ci rd32(E1000_ICR); 214162306a36Sopenharmony_ci igb_irq_enable(adapter); 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci /* notify VFs that reset has been completed */ 214462306a36Sopenharmony_ci if (adapter->vfs_allocated_count) { 214562306a36Sopenharmony_ci u32 reg_data = rd32(E1000_CTRL_EXT); 214662306a36Sopenharmony_ci 214762306a36Sopenharmony_ci reg_data |= E1000_CTRL_EXT_PFRSTD; 214862306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, reg_data); 214962306a36Sopenharmony_ci } 215062306a36Sopenharmony_ci 215162306a36Sopenharmony_ci netif_tx_start_all_queues(adapter->netdev); 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci /* start the watchdog. */ 215462306a36Sopenharmony_ci hw->mac.get_link_status = 1; 215562306a36Sopenharmony_ci schedule_work(&adapter->watchdog_task); 215662306a36Sopenharmony_ci 215762306a36Sopenharmony_ci if ((adapter->flags & IGB_FLAG_EEE) && 215862306a36Sopenharmony_ci (!hw->dev_spec._82575.eee_disable)) 215962306a36Sopenharmony_ci adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T; 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci return 0; 216262306a36Sopenharmony_ci} 216362306a36Sopenharmony_ci 216462306a36Sopenharmony_civoid igb_down(struct igb_adapter *adapter) 216562306a36Sopenharmony_ci{ 216662306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 216762306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 216862306a36Sopenharmony_ci u32 tctl, rctl; 216962306a36Sopenharmony_ci int i; 217062306a36Sopenharmony_ci 217162306a36Sopenharmony_ci /* signal that we're down so the interrupt handler does not 217262306a36Sopenharmony_ci * reschedule our watchdog timer 217362306a36Sopenharmony_ci */ 217462306a36Sopenharmony_ci set_bit(__IGB_DOWN, &adapter->state); 217562306a36Sopenharmony_ci 217662306a36Sopenharmony_ci /* disable receives in the hardware */ 217762306a36Sopenharmony_ci rctl = rd32(E1000_RCTL); 217862306a36Sopenharmony_ci wr32(E1000_RCTL, rctl & ~E1000_RCTL_EN); 217962306a36Sopenharmony_ci /* flush and sleep below */ 218062306a36Sopenharmony_ci 218162306a36Sopenharmony_ci igb_nfc_filter_exit(adapter); 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_ci netif_carrier_off(netdev); 218462306a36Sopenharmony_ci netif_tx_stop_all_queues(netdev); 218562306a36Sopenharmony_ci 218662306a36Sopenharmony_ci /* disable transmits in the hardware */ 218762306a36Sopenharmony_ci tctl = rd32(E1000_TCTL); 218862306a36Sopenharmony_ci tctl &= ~E1000_TCTL_EN; 218962306a36Sopenharmony_ci wr32(E1000_TCTL, tctl); 219062306a36Sopenharmony_ci /* flush both disables and wait for them to finish */ 219162306a36Sopenharmony_ci wrfl(); 219262306a36Sopenharmony_ci usleep_range(10000, 11000); 219362306a36Sopenharmony_ci 219462306a36Sopenharmony_ci igb_irq_disable(adapter); 219562306a36Sopenharmony_ci 219662306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) { 219962306a36Sopenharmony_ci if (adapter->q_vector[i]) { 220062306a36Sopenharmony_ci napi_synchronize(&adapter->q_vector[i]->napi); 220162306a36Sopenharmony_ci napi_disable(&adapter->q_vector[i]->napi); 220262306a36Sopenharmony_ci } 220362306a36Sopenharmony_ci } 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_ci del_timer_sync(&adapter->watchdog_timer); 220662306a36Sopenharmony_ci del_timer_sync(&adapter->phy_info_timer); 220762306a36Sopenharmony_ci 220862306a36Sopenharmony_ci /* record the stats before reset*/ 220962306a36Sopenharmony_ci spin_lock(&adapter->stats64_lock); 221062306a36Sopenharmony_ci igb_update_stats(adapter); 221162306a36Sopenharmony_ci spin_unlock(&adapter->stats64_lock); 221262306a36Sopenharmony_ci 221362306a36Sopenharmony_ci adapter->link_speed = 0; 221462306a36Sopenharmony_ci adapter->link_duplex = 0; 221562306a36Sopenharmony_ci 221662306a36Sopenharmony_ci if (!pci_channel_offline(adapter->pdev)) 221762306a36Sopenharmony_ci igb_reset(adapter); 221862306a36Sopenharmony_ci 221962306a36Sopenharmony_ci /* clear VLAN promisc flag so VFTA will be updated if necessary */ 222062306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_VLAN_PROMISC; 222162306a36Sopenharmony_ci 222262306a36Sopenharmony_ci igb_clean_all_tx_rings(adapter); 222362306a36Sopenharmony_ci igb_clean_all_rx_rings(adapter); 222462306a36Sopenharmony_ci#ifdef CONFIG_IGB_DCA 222562306a36Sopenharmony_ci 222662306a36Sopenharmony_ci /* since we reset the hardware DCA settings were cleared */ 222762306a36Sopenharmony_ci igb_setup_dca(adapter); 222862306a36Sopenharmony_ci#endif 222962306a36Sopenharmony_ci} 223062306a36Sopenharmony_ci 223162306a36Sopenharmony_civoid igb_reinit_locked(struct igb_adapter *adapter) 223262306a36Sopenharmony_ci{ 223362306a36Sopenharmony_ci while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) 223462306a36Sopenharmony_ci usleep_range(1000, 2000); 223562306a36Sopenharmony_ci igb_down(adapter); 223662306a36Sopenharmony_ci igb_up(adapter); 223762306a36Sopenharmony_ci clear_bit(__IGB_RESETTING, &adapter->state); 223862306a36Sopenharmony_ci} 223962306a36Sopenharmony_ci 224062306a36Sopenharmony_ci/** igb_enable_mas - Media Autosense re-enable after swap 224162306a36Sopenharmony_ci * 224262306a36Sopenharmony_ci * @adapter: adapter struct 224362306a36Sopenharmony_ci **/ 224462306a36Sopenharmony_cistatic void igb_enable_mas(struct igb_adapter *adapter) 224562306a36Sopenharmony_ci{ 224662306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 224762306a36Sopenharmony_ci u32 connsw = rd32(E1000_CONNSW); 224862306a36Sopenharmony_ci 224962306a36Sopenharmony_ci /* configure for SerDes media detect */ 225062306a36Sopenharmony_ci if ((hw->phy.media_type == e1000_media_type_copper) && 225162306a36Sopenharmony_ci (!(connsw & E1000_CONNSW_SERDESD))) { 225262306a36Sopenharmony_ci connsw |= E1000_CONNSW_ENRGSRC; 225362306a36Sopenharmony_ci connsw |= E1000_CONNSW_AUTOSENSE_EN; 225462306a36Sopenharmony_ci wr32(E1000_CONNSW, connsw); 225562306a36Sopenharmony_ci wrfl(); 225662306a36Sopenharmony_ci } 225762306a36Sopenharmony_ci} 225862306a36Sopenharmony_ci 225962306a36Sopenharmony_ci#ifdef CONFIG_IGB_HWMON 226062306a36Sopenharmony_ci/** 226162306a36Sopenharmony_ci * igb_set_i2c_bb - Init I2C interface 226262306a36Sopenharmony_ci * @hw: pointer to hardware structure 226362306a36Sopenharmony_ci **/ 226462306a36Sopenharmony_cistatic void igb_set_i2c_bb(struct e1000_hw *hw) 226562306a36Sopenharmony_ci{ 226662306a36Sopenharmony_ci u32 ctrl_ext; 226762306a36Sopenharmony_ci s32 i2cctl; 226862306a36Sopenharmony_ci 226962306a36Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 227062306a36Sopenharmony_ci ctrl_ext |= E1000_CTRL_I2C_ENA; 227162306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, ctrl_ext); 227262306a36Sopenharmony_ci wrfl(); 227362306a36Sopenharmony_ci 227462306a36Sopenharmony_ci i2cctl = rd32(E1000_I2CPARAMS); 227562306a36Sopenharmony_ci i2cctl |= E1000_I2CBB_EN 227662306a36Sopenharmony_ci | E1000_I2C_CLK_OE_N 227762306a36Sopenharmony_ci | E1000_I2C_DATA_OE_N; 227862306a36Sopenharmony_ci wr32(E1000_I2CPARAMS, i2cctl); 227962306a36Sopenharmony_ci wrfl(); 228062306a36Sopenharmony_ci} 228162306a36Sopenharmony_ci#endif 228262306a36Sopenharmony_ci 228362306a36Sopenharmony_civoid igb_reset(struct igb_adapter *adapter) 228462306a36Sopenharmony_ci{ 228562306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 228662306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 228762306a36Sopenharmony_ci struct e1000_mac_info *mac = &hw->mac; 228862306a36Sopenharmony_ci struct e1000_fc_info *fc = &hw->fc; 228962306a36Sopenharmony_ci u32 pba, hwm; 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci /* Repartition Pba for greater than 9k mtu 229262306a36Sopenharmony_ci * To take effect CTRL.RST is required. 229362306a36Sopenharmony_ci */ 229462306a36Sopenharmony_ci switch (mac->type) { 229562306a36Sopenharmony_ci case e1000_i350: 229662306a36Sopenharmony_ci case e1000_i354: 229762306a36Sopenharmony_ci case e1000_82580: 229862306a36Sopenharmony_ci pba = rd32(E1000_RXPBS); 229962306a36Sopenharmony_ci pba = igb_rxpbs_adjust_82580(pba); 230062306a36Sopenharmony_ci break; 230162306a36Sopenharmony_ci case e1000_82576: 230262306a36Sopenharmony_ci pba = rd32(E1000_RXPBS); 230362306a36Sopenharmony_ci pba &= E1000_RXPBS_SIZE_MASK_82576; 230462306a36Sopenharmony_ci break; 230562306a36Sopenharmony_ci case e1000_82575: 230662306a36Sopenharmony_ci case e1000_i210: 230762306a36Sopenharmony_ci case e1000_i211: 230862306a36Sopenharmony_ci default: 230962306a36Sopenharmony_ci pba = E1000_PBA_34K; 231062306a36Sopenharmony_ci break; 231162306a36Sopenharmony_ci } 231262306a36Sopenharmony_ci 231362306a36Sopenharmony_ci if (mac->type == e1000_82575) { 231462306a36Sopenharmony_ci u32 min_rx_space, min_tx_space, needed_tx_space; 231562306a36Sopenharmony_ci 231662306a36Sopenharmony_ci /* write Rx PBA so that hardware can report correct Tx PBA */ 231762306a36Sopenharmony_ci wr32(E1000_PBA, pba); 231862306a36Sopenharmony_ci 231962306a36Sopenharmony_ci /* To maintain wire speed transmits, the Tx FIFO should be 232062306a36Sopenharmony_ci * large enough to accommodate two full transmit packets, 232162306a36Sopenharmony_ci * rounded up to the next 1KB and expressed in KB. Likewise, 232262306a36Sopenharmony_ci * the Rx FIFO should be large enough to accommodate at least 232362306a36Sopenharmony_ci * one full receive packet and is similarly rounded up and 232462306a36Sopenharmony_ci * expressed in KB. 232562306a36Sopenharmony_ci */ 232662306a36Sopenharmony_ci min_rx_space = DIV_ROUND_UP(MAX_JUMBO_FRAME_SIZE, 1024); 232762306a36Sopenharmony_ci 232862306a36Sopenharmony_ci /* The Tx FIFO also stores 16 bytes of information about the Tx 232962306a36Sopenharmony_ci * but don't include Ethernet FCS because hardware appends it. 233062306a36Sopenharmony_ci * We only need to round down to the nearest 512 byte block 233162306a36Sopenharmony_ci * count since the value we care about is 2 frames, not 1. 233262306a36Sopenharmony_ci */ 233362306a36Sopenharmony_ci min_tx_space = adapter->max_frame_size; 233462306a36Sopenharmony_ci min_tx_space += sizeof(union e1000_adv_tx_desc) - ETH_FCS_LEN; 233562306a36Sopenharmony_ci min_tx_space = DIV_ROUND_UP(min_tx_space, 512); 233662306a36Sopenharmony_ci 233762306a36Sopenharmony_ci /* upper 16 bits has Tx packet buffer allocation size in KB */ 233862306a36Sopenharmony_ci needed_tx_space = min_tx_space - (rd32(E1000_PBA) >> 16); 233962306a36Sopenharmony_ci 234062306a36Sopenharmony_ci /* If current Tx allocation is less than the min Tx FIFO size, 234162306a36Sopenharmony_ci * and the min Tx FIFO size is less than the current Rx FIFO 234262306a36Sopenharmony_ci * allocation, take space away from current Rx allocation. 234362306a36Sopenharmony_ci */ 234462306a36Sopenharmony_ci if (needed_tx_space < pba) { 234562306a36Sopenharmony_ci pba -= needed_tx_space; 234662306a36Sopenharmony_ci 234762306a36Sopenharmony_ci /* if short on Rx space, Rx wins and must trump Tx 234862306a36Sopenharmony_ci * adjustment 234962306a36Sopenharmony_ci */ 235062306a36Sopenharmony_ci if (pba < min_rx_space) 235162306a36Sopenharmony_ci pba = min_rx_space; 235262306a36Sopenharmony_ci } 235362306a36Sopenharmony_ci 235462306a36Sopenharmony_ci /* adjust PBA for jumbo frames */ 235562306a36Sopenharmony_ci wr32(E1000_PBA, pba); 235662306a36Sopenharmony_ci } 235762306a36Sopenharmony_ci 235862306a36Sopenharmony_ci /* flow control settings 235962306a36Sopenharmony_ci * The high water mark must be low enough to fit one full frame 236062306a36Sopenharmony_ci * after transmitting the pause frame. As such we must have enough 236162306a36Sopenharmony_ci * space to allow for us to complete our current transmit and then 236262306a36Sopenharmony_ci * receive the frame that is in progress from the link partner. 236362306a36Sopenharmony_ci * Set it to: 236462306a36Sopenharmony_ci * - the full Rx FIFO size minus one full Tx plus one full Rx frame 236562306a36Sopenharmony_ci */ 236662306a36Sopenharmony_ci hwm = (pba << 10) - (adapter->max_frame_size + MAX_JUMBO_FRAME_SIZE); 236762306a36Sopenharmony_ci 236862306a36Sopenharmony_ci fc->high_water = hwm & 0xFFFFFFF0; /* 16-byte granularity */ 236962306a36Sopenharmony_ci fc->low_water = fc->high_water - 16; 237062306a36Sopenharmony_ci fc->pause_time = 0xFFFF; 237162306a36Sopenharmony_ci fc->send_xon = 1; 237262306a36Sopenharmony_ci fc->current_mode = fc->requested_mode; 237362306a36Sopenharmony_ci 237462306a36Sopenharmony_ci /* disable receive for all VFs and wait one second */ 237562306a36Sopenharmony_ci if (adapter->vfs_allocated_count) { 237662306a36Sopenharmony_ci int i; 237762306a36Sopenharmony_ci 237862306a36Sopenharmony_ci for (i = 0 ; i < adapter->vfs_allocated_count; i++) 237962306a36Sopenharmony_ci adapter->vf_data[i].flags &= IGB_VF_FLAG_PF_SET_MAC; 238062306a36Sopenharmony_ci 238162306a36Sopenharmony_ci /* ping all the active vfs to let them know we are going down */ 238262306a36Sopenharmony_ci igb_ping_all_vfs(adapter); 238362306a36Sopenharmony_ci 238462306a36Sopenharmony_ci /* disable transmits and receives */ 238562306a36Sopenharmony_ci wr32(E1000_VFRE, 0); 238662306a36Sopenharmony_ci wr32(E1000_VFTE, 0); 238762306a36Sopenharmony_ci } 238862306a36Sopenharmony_ci 238962306a36Sopenharmony_ci /* Allow time for pending master requests to run */ 239062306a36Sopenharmony_ci hw->mac.ops.reset_hw(hw); 239162306a36Sopenharmony_ci wr32(E1000_WUC, 0); 239262306a36Sopenharmony_ci 239362306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_MEDIA_RESET) { 239462306a36Sopenharmony_ci /* need to resetup here after media swap */ 239562306a36Sopenharmony_ci adapter->ei.get_invariants(hw); 239662306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_MEDIA_RESET; 239762306a36Sopenharmony_ci } 239862306a36Sopenharmony_ci if ((mac->type == e1000_82575 || mac->type == e1000_i350) && 239962306a36Sopenharmony_ci (adapter->flags & IGB_FLAG_MAS_ENABLE)) { 240062306a36Sopenharmony_ci igb_enable_mas(adapter); 240162306a36Sopenharmony_ci } 240262306a36Sopenharmony_ci if (hw->mac.ops.init_hw(hw)) 240362306a36Sopenharmony_ci dev_err(&pdev->dev, "Hardware Error\n"); 240462306a36Sopenharmony_ci 240562306a36Sopenharmony_ci /* RAR registers were cleared during init_hw, clear mac table */ 240662306a36Sopenharmony_ci igb_flush_mac_table(adapter); 240762306a36Sopenharmony_ci __dev_uc_unsync(adapter->netdev, NULL); 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci /* Recover default RAR entry */ 241062306a36Sopenharmony_ci igb_set_default_mac_filter(adapter); 241162306a36Sopenharmony_ci 241262306a36Sopenharmony_ci /* Flow control settings reset on hardware reset, so guarantee flow 241362306a36Sopenharmony_ci * control is off when forcing speed. 241462306a36Sopenharmony_ci */ 241562306a36Sopenharmony_ci if (!hw->mac.autoneg) 241662306a36Sopenharmony_ci igb_force_mac_fc(hw); 241762306a36Sopenharmony_ci 241862306a36Sopenharmony_ci igb_init_dmac(adapter, pba); 241962306a36Sopenharmony_ci#ifdef CONFIG_IGB_HWMON 242062306a36Sopenharmony_ci /* Re-initialize the thermal sensor on i350 devices. */ 242162306a36Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) { 242262306a36Sopenharmony_ci if (mac->type == e1000_i350 && hw->bus.func == 0) { 242362306a36Sopenharmony_ci /* If present, re-initialize the external thermal sensor 242462306a36Sopenharmony_ci * interface. 242562306a36Sopenharmony_ci */ 242662306a36Sopenharmony_ci if (adapter->ets) 242762306a36Sopenharmony_ci igb_set_i2c_bb(hw); 242862306a36Sopenharmony_ci mac->ops.init_thermal_sensor_thresh(hw); 242962306a36Sopenharmony_ci } 243062306a36Sopenharmony_ci } 243162306a36Sopenharmony_ci#endif 243262306a36Sopenharmony_ci /* Re-establish EEE setting */ 243362306a36Sopenharmony_ci if (hw->phy.media_type == e1000_media_type_copper) { 243462306a36Sopenharmony_ci switch (mac->type) { 243562306a36Sopenharmony_ci case e1000_i350: 243662306a36Sopenharmony_ci case e1000_i210: 243762306a36Sopenharmony_ci case e1000_i211: 243862306a36Sopenharmony_ci igb_set_eee_i350(hw, true, true); 243962306a36Sopenharmony_ci break; 244062306a36Sopenharmony_ci case e1000_i354: 244162306a36Sopenharmony_ci igb_set_eee_i354(hw, true, true); 244262306a36Sopenharmony_ci break; 244362306a36Sopenharmony_ci default: 244462306a36Sopenharmony_ci break; 244562306a36Sopenharmony_ci } 244662306a36Sopenharmony_ci } 244762306a36Sopenharmony_ci if (!netif_running(adapter->netdev)) 244862306a36Sopenharmony_ci igb_power_down_link(adapter); 244962306a36Sopenharmony_ci 245062306a36Sopenharmony_ci igb_update_mng_vlan(adapter); 245162306a36Sopenharmony_ci 245262306a36Sopenharmony_ci /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ 245362306a36Sopenharmony_ci wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE); 245462306a36Sopenharmony_ci 245562306a36Sopenharmony_ci /* Re-enable PTP, where applicable. */ 245662306a36Sopenharmony_ci if (adapter->ptp_flags & IGB_PTP_ENABLED) 245762306a36Sopenharmony_ci igb_ptp_reset(adapter); 245862306a36Sopenharmony_ci 245962306a36Sopenharmony_ci igb_get_phy_info(hw); 246062306a36Sopenharmony_ci} 246162306a36Sopenharmony_ci 246262306a36Sopenharmony_cistatic netdev_features_t igb_fix_features(struct net_device *netdev, 246362306a36Sopenharmony_ci netdev_features_t features) 246462306a36Sopenharmony_ci{ 246562306a36Sopenharmony_ci /* Since there is no support for separate Rx/Tx vlan accel 246662306a36Sopenharmony_ci * enable/disable make sure Tx flag is always in same state as Rx. 246762306a36Sopenharmony_ci */ 246862306a36Sopenharmony_ci if (features & NETIF_F_HW_VLAN_CTAG_RX) 246962306a36Sopenharmony_ci features |= NETIF_F_HW_VLAN_CTAG_TX; 247062306a36Sopenharmony_ci else 247162306a36Sopenharmony_ci features &= ~NETIF_F_HW_VLAN_CTAG_TX; 247262306a36Sopenharmony_ci 247362306a36Sopenharmony_ci return features; 247462306a36Sopenharmony_ci} 247562306a36Sopenharmony_ci 247662306a36Sopenharmony_cistatic int igb_set_features(struct net_device *netdev, 247762306a36Sopenharmony_ci netdev_features_t features) 247862306a36Sopenharmony_ci{ 247962306a36Sopenharmony_ci netdev_features_t changed = netdev->features ^ features; 248062306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 248162306a36Sopenharmony_ci 248262306a36Sopenharmony_ci if (changed & NETIF_F_HW_VLAN_CTAG_RX) 248362306a36Sopenharmony_ci igb_vlan_mode(netdev, features); 248462306a36Sopenharmony_ci 248562306a36Sopenharmony_ci if (!(changed & (NETIF_F_RXALL | NETIF_F_NTUPLE))) 248662306a36Sopenharmony_ci return 0; 248762306a36Sopenharmony_ci 248862306a36Sopenharmony_ci if (!(features & NETIF_F_NTUPLE)) { 248962306a36Sopenharmony_ci struct hlist_node *node2; 249062306a36Sopenharmony_ci struct igb_nfc_filter *rule; 249162306a36Sopenharmony_ci 249262306a36Sopenharmony_ci spin_lock(&adapter->nfc_lock); 249362306a36Sopenharmony_ci hlist_for_each_entry_safe(rule, node2, 249462306a36Sopenharmony_ci &adapter->nfc_filter_list, nfc_node) { 249562306a36Sopenharmony_ci igb_erase_filter(adapter, rule); 249662306a36Sopenharmony_ci hlist_del(&rule->nfc_node); 249762306a36Sopenharmony_ci kfree(rule); 249862306a36Sopenharmony_ci } 249962306a36Sopenharmony_ci spin_unlock(&adapter->nfc_lock); 250062306a36Sopenharmony_ci adapter->nfc_filter_count = 0; 250162306a36Sopenharmony_ci } 250262306a36Sopenharmony_ci 250362306a36Sopenharmony_ci netdev->features = features; 250462306a36Sopenharmony_ci 250562306a36Sopenharmony_ci if (netif_running(netdev)) 250662306a36Sopenharmony_ci igb_reinit_locked(adapter); 250762306a36Sopenharmony_ci else 250862306a36Sopenharmony_ci igb_reset(adapter); 250962306a36Sopenharmony_ci 251062306a36Sopenharmony_ci return 1; 251162306a36Sopenharmony_ci} 251262306a36Sopenharmony_ci 251362306a36Sopenharmony_cistatic int igb_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], 251462306a36Sopenharmony_ci struct net_device *dev, 251562306a36Sopenharmony_ci const unsigned char *addr, u16 vid, 251662306a36Sopenharmony_ci u16 flags, 251762306a36Sopenharmony_ci struct netlink_ext_ack *extack) 251862306a36Sopenharmony_ci{ 251962306a36Sopenharmony_ci /* guarantee we can provide a unique filter for the unicast address */ 252062306a36Sopenharmony_ci if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) { 252162306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(dev); 252262306a36Sopenharmony_ci int vfn = adapter->vfs_allocated_count; 252362306a36Sopenharmony_ci 252462306a36Sopenharmony_ci if (netdev_uc_count(dev) >= igb_available_rars(adapter, vfn)) 252562306a36Sopenharmony_ci return -ENOMEM; 252662306a36Sopenharmony_ci } 252762306a36Sopenharmony_ci 252862306a36Sopenharmony_ci return ndo_dflt_fdb_add(ndm, tb, dev, addr, vid, flags); 252962306a36Sopenharmony_ci} 253062306a36Sopenharmony_ci 253162306a36Sopenharmony_ci#define IGB_MAX_MAC_HDR_LEN 127 253262306a36Sopenharmony_ci#define IGB_MAX_NETWORK_HDR_LEN 511 253362306a36Sopenharmony_ci 253462306a36Sopenharmony_cistatic netdev_features_t 253562306a36Sopenharmony_ciigb_features_check(struct sk_buff *skb, struct net_device *dev, 253662306a36Sopenharmony_ci netdev_features_t features) 253762306a36Sopenharmony_ci{ 253862306a36Sopenharmony_ci unsigned int network_hdr_len, mac_hdr_len; 253962306a36Sopenharmony_ci 254062306a36Sopenharmony_ci /* Make certain the headers can be described by a context descriptor */ 254162306a36Sopenharmony_ci mac_hdr_len = skb_network_header(skb) - skb->data; 254262306a36Sopenharmony_ci if (unlikely(mac_hdr_len > IGB_MAX_MAC_HDR_LEN)) 254362306a36Sopenharmony_ci return features & ~(NETIF_F_HW_CSUM | 254462306a36Sopenharmony_ci NETIF_F_SCTP_CRC | 254562306a36Sopenharmony_ci NETIF_F_GSO_UDP_L4 | 254662306a36Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_TX | 254762306a36Sopenharmony_ci NETIF_F_TSO | 254862306a36Sopenharmony_ci NETIF_F_TSO6); 254962306a36Sopenharmony_ci 255062306a36Sopenharmony_ci network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb); 255162306a36Sopenharmony_ci if (unlikely(network_hdr_len > IGB_MAX_NETWORK_HDR_LEN)) 255262306a36Sopenharmony_ci return features & ~(NETIF_F_HW_CSUM | 255362306a36Sopenharmony_ci NETIF_F_SCTP_CRC | 255462306a36Sopenharmony_ci NETIF_F_GSO_UDP_L4 | 255562306a36Sopenharmony_ci NETIF_F_TSO | 255662306a36Sopenharmony_ci NETIF_F_TSO6); 255762306a36Sopenharmony_ci 255862306a36Sopenharmony_ci /* We can only support IPV4 TSO in tunnels if we can mangle the 255962306a36Sopenharmony_ci * inner IP ID field, so strip TSO if MANGLEID is not supported. 256062306a36Sopenharmony_ci */ 256162306a36Sopenharmony_ci if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID)) 256262306a36Sopenharmony_ci features &= ~NETIF_F_TSO; 256362306a36Sopenharmony_ci 256462306a36Sopenharmony_ci return features; 256562306a36Sopenharmony_ci} 256662306a36Sopenharmony_ci 256762306a36Sopenharmony_cistatic void igb_offload_apply(struct igb_adapter *adapter, s32 queue) 256862306a36Sopenharmony_ci{ 256962306a36Sopenharmony_ci if (!is_fqtss_enabled(adapter)) { 257062306a36Sopenharmony_ci enable_fqtss(adapter, true); 257162306a36Sopenharmony_ci return; 257262306a36Sopenharmony_ci } 257362306a36Sopenharmony_ci 257462306a36Sopenharmony_ci igb_config_tx_modes(adapter, queue); 257562306a36Sopenharmony_ci 257662306a36Sopenharmony_ci if (!is_any_cbs_enabled(adapter) && !is_any_txtime_enabled(adapter)) 257762306a36Sopenharmony_ci enable_fqtss(adapter, false); 257862306a36Sopenharmony_ci} 257962306a36Sopenharmony_ci 258062306a36Sopenharmony_cistatic int igb_offload_cbs(struct igb_adapter *adapter, 258162306a36Sopenharmony_ci struct tc_cbs_qopt_offload *qopt) 258262306a36Sopenharmony_ci{ 258362306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 258462306a36Sopenharmony_ci int err; 258562306a36Sopenharmony_ci 258662306a36Sopenharmony_ci /* CBS offloading is only supported by i210 controller. */ 258762306a36Sopenharmony_ci if (hw->mac.type != e1000_i210) 258862306a36Sopenharmony_ci return -EOPNOTSUPP; 258962306a36Sopenharmony_ci 259062306a36Sopenharmony_ci /* CBS offloading is only supported by queue 0 and queue 1. */ 259162306a36Sopenharmony_ci if (qopt->queue < 0 || qopt->queue > 1) 259262306a36Sopenharmony_ci return -EINVAL; 259362306a36Sopenharmony_ci 259462306a36Sopenharmony_ci err = igb_save_cbs_params(adapter, qopt->queue, qopt->enable, 259562306a36Sopenharmony_ci qopt->idleslope, qopt->sendslope, 259662306a36Sopenharmony_ci qopt->hicredit, qopt->locredit); 259762306a36Sopenharmony_ci if (err) 259862306a36Sopenharmony_ci return err; 259962306a36Sopenharmony_ci 260062306a36Sopenharmony_ci igb_offload_apply(adapter, qopt->queue); 260162306a36Sopenharmony_ci 260262306a36Sopenharmony_ci return 0; 260362306a36Sopenharmony_ci} 260462306a36Sopenharmony_ci 260562306a36Sopenharmony_ci#define ETHER_TYPE_FULL_MASK ((__force __be16)~0) 260662306a36Sopenharmony_ci#define VLAN_PRIO_FULL_MASK (0x07) 260762306a36Sopenharmony_ci 260862306a36Sopenharmony_cistatic int igb_parse_cls_flower(struct igb_adapter *adapter, 260962306a36Sopenharmony_ci struct flow_cls_offload *f, 261062306a36Sopenharmony_ci int traffic_class, 261162306a36Sopenharmony_ci struct igb_nfc_filter *input) 261262306a36Sopenharmony_ci{ 261362306a36Sopenharmony_ci struct flow_rule *rule = flow_cls_offload_flow_rule(f); 261462306a36Sopenharmony_ci struct flow_dissector *dissector = rule->match.dissector; 261562306a36Sopenharmony_ci struct netlink_ext_ack *extack = f->common.extack; 261662306a36Sopenharmony_ci 261762306a36Sopenharmony_ci if (dissector->used_keys & 261862306a36Sopenharmony_ci ~(BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | 261962306a36Sopenharmony_ci BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | 262062306a36Sopenharmony_ci BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 262162306a36Sopenharmony_ci BIT_ULL(FLOW_DISSECTOR_KEY_VLAN))) { 262262306a36Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, 262362306a36Sopenharmony_ci "Unsupported key used, only BASIC, CONTROL, ETH_ADDRS and VLAN are supported"); 262462306a36Sopenharmony_ci return -EOPNOTSUPP; 262562306a36Sopenharmony_ci } 262662306a36Sopenharmony_ci 262762306a36Sopenharmony_ci if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { 262862306a36Sopenharmony_ci struct flow_match_eth_addrs match; 262962306a36Sopenharmony_ci 263062306a36Sopenharmony_ci flow_rule_match_eth_addrs(rule, &match); 263162306a36Sopenharmony_ci if (!is_zero_ether_addr(match.mask->dst)) { 263262306a36Sopenharmony_ci if (!is_broadcast_ether_addr(match.mask->dst)) { 263362306a36Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, "Only full masks are supported for destination MAC address"); 263462306a36Sopenharmony_ci return -EINVAL; 263562306a36Sopenharmony_ci } 263662306a36Sopenharmony_ci 263762306a36Sopenharmony_ci input->filter.match_flags |= 263862306a36Sopenharmony_ci IGB_FILTER_FLAG_DST_MAC_ADDR; 263962306a36Sopenharmony_ci ether_addr_copy(input->filter.dst_addr, match.key->dst); 264062306a36Sopenharmony_ci } 264162306a36Sopenharmony_ci 264262306a36Sopenharmony_ci if (!is_zero_ether_addr(match.mask->src)) { 264362306a36Sopenharmony_ci if (!is_broadcast_ether_addr(match.mask->src)) { 264462306a36Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, "Only full masks are supported for source MAC address"); 264562306a36Sopenharmony_ci return -EINVAL; 264662306a36Sopenharmony_ci } 264762306a36Sopenharmony_ci 264862306a36Sopenharmony_ci input->filter.match_flags |= 264962306a36Sopenharmony_ci IGB_FILTER_FLAG_SRC_MAC_ADDR; 265062306a36Sopenharmony_ci ether_addr_copy(input->filter.src_addr, match.key->src); 265162306a36Sopenharmony_ci } 265262306a36Sopenharmony_ci } 265362306a36Sopenharmony_ci 265462306a36Sopenharmony_ci if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { 265562306a36Sopenharmony_ci struct flow_match_basic match; 265662306a36Sopenharmony_ci 265762306a36Sopenharmony_ci flow_rule_match_basic(rule, &match); 265862306a36Sopenharmony_ci if (match.mask->n_proto) { 265962306a36Sopenharmony_ci if (match.mask->n_proto != ETHER_TYPE_FULL_MASK) { 266062306a36Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, "Only full mask is supported for EtherType filter"); 266162306a36Sopenharmony_ci return -EINVAL; 266262306a36Sopenharmony_ci } 266362306a36Sopenharmony_ci 266462306a36Sopenharmony_ci input->filter.match_flags |= IGB_FILTER_FLAG_ETHER_TYPE; 266562306a36Sopenharmony_ci input->filter.etype = match.key->n_proto; 266662306a36Sopenharmony_ci } 266762306a36Sopenharmony_ci } 266862306a36Sopenharmony_ci 266962306a36Sopenharmony_ci if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { 267062306a36Sopenharmony_ci struct flow_match_vlan match; 267162306a36Sopenharmony_ci 267262306a36Sopenharmony_ci flow_rule_match_vlan(rule, &match); 267362306a36Sopenharmony_ci if (match.mask->vlan_priority) { 267462306a36Sopenharmony_ci if (match.mask->vlan_priority != VLAN_PRIO_FULL_MASK) { 267562306a36Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, "Only full mask is supported for VLAN priority"); 267662306a36Sopenharmony_ci return -EINVAL; 267762306a36Sopenharmony_ci } 267862306a36Sopenharmony_ci 267962306a36Sopenharmony_ci input->filter.match_flags |= IGB_FILTER_FLAG_VLAN_TCI; 268062306a36Sopenharmony_ci input->filter.vlan_tci = 268162306a36Sopenharmony_ci (__force __be16)match.key->vlan_priority; 268262306a36Sopenharmony_ci } 268362306a36Sopenharmony_ci } 268462306a36Sopenharmony_ci 268562306a36Sopenharmony_ci input->action = traffic_class; 268662306a36Sopenharmony_ci input->cookie = f->cookie; 268762306a36Sopenharmony_ci 268862306a36Sopenharmony_ci return 0; 268962306a36Sopenharmony_ci} 269062306a36Sopenharmony_ci 269162306a36Sopenharmony_cistatic int igb_configure_clsflower(struct igb_adapter *adapter, 269262306a36Sopenharmony_ci struct flow_cls_offload *cls_flower) 269362306a36Sopenharmony_ci{ 269462306a36Sopenharmony_ci struct netlink_ext_ack *extack = cls_flower->common.extack; 269562306a36Sopenharmony_ci struct igb_nfc_filter *filter, *f; 269662306a36Sopenharmony_ci int err, tc; 269762306a36Sopenharmony_ci 269862306a36Sopenharmony_ci tc = tc_classid_to_hwtc(adapter->netdev, cls_flower->classid); 269962306a36Sopenharmony_ci if (tc < 0) { 270062306a36Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, "Invalid traffic class"); 270162306a36Sopenharmony_ci return -EINVAL; 270262306a36Sopenharmony_ci } 270362306a36Sopenharmony_ci 270462306a36Sopenharmony_ci filter = kzalloc(sizeof(*filter), GFP_KERNEL); 270562306a36Sopenharmony_ci if (!filter) 270662306a36Sopenharmony_ci return -ENOMEM; 270762306a36Sopenharmony_ci 270862306a36Sopenharmony_ci err = igb_parse_cls_flower(adapter, cls_flower, tc, filter); 270962306a36Sopenharmony_ci if (err < 0) 271062306a36Sopenharmony_ci goto err_parse; 271162306a36Sopenharmony_ci 271262306a36Sopenharmony_ci spin_lock(&adapter->nfc_lock); 271362306a36Sopenharmony_ci 271462306a36Sopenharmony_ci hlist_for_each_entry(f, &adapter->nfc_filter_list, nfc_node) { 271562306a36Sopenharmony_ci if (!memcmp(&f->filter, &filter->filter, sizeof(f->filter))) { 271662306a36Sopenharmony_ci err = -EEXIST; 271762306a36Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, 271862306a36Sopenharmony_ci "This filter is already set in ethtool"); 271962306a36Sopenharmony_ci goto err_locked; 272062306a36Sopenharmony_ci } 272162306a36Sopenharmony_ci } 272262306a36Sopenharmony_ci 272362306a36Sopenharmony_ci hlist_for_each_entry(f, &adapter->cls_flower_list, nfc_node) { 272462306a36Sopenharmony_ci if (!memcmp(&f->filter, &filter->filter, sizeof(f->filter))) { 272562306a36Sopenharmony_ci err = -EEXIST; 272662306a36Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, 272762306a36Sopenharmony_ci "This filter is already set in cls_flower"); 272862306a36Sopenharmony_ci goto err_locked; 272962306a36Sopenharmony_ci } 273062306a36Sopenharmony_ci } 273162306a36Sopenharmony_ci 273262306a36Sopenharmony_ci err = igb_add_filter(adapter, filter); 273362306a36Sopenharmony_ci if (err < 0) { 273462306a36Sopenharmony_ci NL_SET_ERR_MSG_MOD(extack, "Could not add filter to the adapter"); 273562306a36Sopenharmony_ci goto err_locked; 273662306a36Sopenharmony_ci } 273762306a36Sopenharmony_ci 273862306a36Sopenharmony_ci hlist_add_head(&filter->nfc_node, &adapter->cls_flower_list); 273962306a36Sopenharmony_ci 274062306a36Sopenharmony_ci spin_unlock(&adapter->nfc_lock); 274162306a36Sopenharmony_ci 274262306a36Sopenharmony_ci return 0; 274362306a36Sopenharmony_ci 274462306a36Sopenharmony_cierr_locked: 274562306a36Sopenharmony_ci spin_unlock(&adapter->nfc_lock); 274662306a36Sopenharmony_ci 274762306a36Sopenharmony_cierr_parse: 274862306a36Sopenharmony_ci kfree(filter); 274962306a36Sopenharmony_ci 275062306a36Sopenharmony_ci return err; 275162306a36Sopenharmony_ci} 275262306a36Sopenharmony_ci 275362306a36Sopenharmony_cistatic int igb_delete_clsflower(struct igb_adapter *adapter, 275462306a36Sopenharmony_ci struct flow_cls_offload *cls_flower) 275562306a36Sopenharmony_ci{ 275662306a36Sopenharmony_ci struct igb_nfc_filter *filter; 275762306a36Sopenharmony_ci int err; 275862306a36Sopenharmony_ci 275962306a36Sopenharmony_ci spin_lock(&adapter->nfc_lock); 276062306a36Sopenharmony_ci 276162306a36Sopenharmony_ci hlist_for_each_entry(filter, &adapter->cls_flower_list, nfc_node) 276262306a36Sopenharmony_ci if (filter->cookie == cls_flower->cookie) 276362306a36Sopenharmony_ci break; 276462306a36Sopenharmony_ci 276562306a36Sopenharmony_ci if (!filter) { 276662306a36Sopenharmony_ci err = -ENOENT; 276762306a36Sopenharmony_ci goto out; 276862306a36Sopenharmony_ci } 276962306a36Sopenharmony_ci 277062306a36Sopenharmony_ci err = igb_erase_filter(adapter, filter); 277162306a36Sopenharmony_ci if (err < 0) 277262306a36Sopenharmony_ci goto out; 277362306a36Sopenharmony_ci 277462306a36Sopenharmony_ci hlist_del(&filter->nfc_node); 277562306a36Sopenharmony_ci kfree(filter); 277662306a36Sopenharmony_ci 277762306a36Sopenharmony_ciout: 277862306a36Sopenharmony_ci spin_unlock(&adapter->nfc_lock); 277962306a36Sopenharmony_ci 278062306a36Sopenharmony_ci return err; 278162306a36Sopenharmony_ci} 278262306a36Sopenharmony_ci 278362306a36Sopenharmony_cistatic int igb_setup_tc_cls_flower(struct igb_adapter *adapter, 278462306a36Sopenharmony_ci struct flow_cls_offload *cls_flower) 278562306a36Sopenharmony_ci{ 278662306a36Sopenharmony_ci switch (cls_flower->command) { 278762306a36Sopenharmony_ci case FLOW_CLS_REPLACE: 278862306a36Sopenharmony_ci return igb_configure_clsflower(adapter, cls_flower); 278962306a36Sopenharmony_ci case FLOW_CLS_DESTROY: 279062306a36Sopenharmony_ci return igb_delete_clsflower(adapter, cls_flower); 279162306a36Sopenharmony_ci case FLOW_CLS_STATS: 279262306a36Sopenharmony_ci return -EOPNOTSUPP; 279362306a36Sopenharmony_ci default: 279462306a36Sopenharmony_ci return -EOPNOTSUPP; 279562306a36Sopenharmony_ci } 279662306a36Sopenharmony_ci} 279762306a36Sopenharmony_ci 279862306a36Sopenharmony_cistatic int igb_setup_tc_block_cb(enum tc_setup_type type, void *type_data, 279962306a36Sopenharmony_ci void *cb_priv) 280062306a36Sopenharmony_ci{ 280162306a36Sopenharmony_ci struct igb_adapter *adapter = cb_priv; 280262306a36Sopenharmony_ci 280362306a36Sopenharmony_ci if (!tc_cls_can_offload_and_chain0(adapter->netdev, type_data)) 280462306a36Sopenharmony_ci return -EOPNOTSUPP; 280562306a36Sopenharmony_ci 280662306a36Sopenharmony_ci switch (type) { 280762306a36Sopenharmony_ci case TC_SETUP_CLSFLOWER: 280862306a36Sopenharmony_ci return igb_setup_tc_cls_flower(adapter, type_data); 280962306a36Sopenharmony_ci 281062306a36Sopenharmony_ci default: 281162306a36Sopenharmony_ci return -EOPNOTSUPP; 281262306a36Sopenharmony_ci } 281362306a36Sopenharmony_ci} 281462306a36Sopenharmony_ci 281562306a36Sopenharmony_cistatic int igb_offload_txtime(struct igb_adapter *adapter, 281662306a36Sopenharmony_ci struct tc_etf_qopt_offload *qopt) 281762306a36Sopenharmony_ci{ 281862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 281962306a36Sopenharmony_ci int err; 282062306a36Sopenharmony_ci 282162306a36Sopenharmony_ci /* Launchtime offloading is only supported by i210 controller. */ 282262306a36Sopenharmony_ci if (hw->mac.type != e1000_i210) 282362306a36Sopenharmony_ci return -EOPNOTSUPP; 282462306a36Sopenharmony_ci 282562306a36Sopenharmony_ci /* Launchtime offloading is only supported by queues 0 and 1. */ 282662306a36Sopenharmony_ci if (qopt->queue < 0 || qopt->queue > 1) 282762306a36Sopenharmony_ci return -EINVAL; 282862306a36Sopenharmony_ci 282962306a36Sopenharmony_ci err = igb_save_txtime_params(adapter, qopt->queue, qopt->enable); 283062306a36Sopenharmony_ci if (err) 283162306a36Sopenharmony_ci return err; 283262306a36Sopenharmony_ci 283362306a36Sopenharmony_ci igb_offload_apply(adapter, qopt->queue); 283462306a36Sopenharmony_ci 283562306a36Sopenharmony_ci return 0; 283662306a36Sopenharmony_ci} 283762306a36Sopenharmony_ci 283862306a36Sopenharmony_cistatic int igb_tc_query_caps(struct igb_adapter *adapter, 283962306a36Sopenharmony_ci struct tc_query_caps_base *base) 284062306a36Sopenharmony_ci{ 284162306a36Sopenharmony_ci switch (base->type) { 284262306a36Sopenharmony_ci case TC_SETUP_QDISC_TAPRIO: { 284362306a36Sopenharmony_ci struct tc_taprio_caps *caps = base->caps; 284462306a36Sopenharmony_ci 284562306a36Sopenharmony_ci caps->broken_mqprio = true; 284662306a36Sopenharmony_ci 284762306a36Sopenharmony_ci return 0; 284862306a36Sopenharmony_ci } 284962306a36Sopenharmony_ci default: 285062306a36Sopenharmony_ci return -EOPNOTSUPP; 285162306a36Sopenharmony_ci } 285262306a36Sopenharmony_ci} 285362306a36Sopenharmony_ci 285462306a36Sopenharmony_cistatic LIST_HEAD(igb_block_cb_list); 285562306a36Sopenharmony_ci 285662306a36Sopenharmony_cistatic int igb_setup_tc(struct net_device *dev, enum tc_setup_type type, 285762306a36Sopenharmony_ci void *type_data) 285862306a36Sopenharmony_ci{ 285962306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(dev); 286062306a36Sopenharmony_ci 286162306a36Sopenharmony_ci switch (type) { 286262306a36Sopenharmony_ci case TC_QUERY_CAPS: 286362306a36Sopenharmony_ci return igb_tc_query_caps(adapter, type_data); 286462306a36Sopenharmony_ci case TC_SETUP_QDISC_CBS: 286562306a36Sopenharmony_ci return igb_offload_cbs(adapter, type_data); 286662306a36Sopenharmony_ci case TC_SETUP_BLOCK: 286762306a36Sopenharmony_ci return flow_block_cb_setup_simple(type_data, 286862306a36Sopenharmony_ci &igb_block_cb_list, 286962306a36Sopenharmony_ci igb_setup_tc_block_cb, 287062306a36Sopenharmony_ci adapter, adapter, true); 287162306a36Sopenharmony_ci 287262306a36Sopenharmony_ci case TC_SETUP_QDISC_ETF: 287362306a36Sopenharmony_ci return igb_offload_txtime(adapter, type_data); 287462306a36Sopenharmony_ci 287562306a36Sopenharmony_ci default: 287662306a36Sopenharmony_ci return -EOPNOTSUPP; 287762306a36Sopenharmony_ci } 287862306a36Sopenharmony_ci} 287962306a36Sopenharmony_ci 288062306a36Sopenharmony_cistatic int igb_xdp_setup(struct net_device *dev, struct netdev_bpf *bpf) 288162306a36Sopenharmony_ci{ 288262306a36Sopenharmony_ci int i, frame_size = dev->mtu + IGB_ETH_PKT_HDR_PAD; 288362306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(dev); 288462306a36Sopenharmony_ci struct bpf_prog *prog = bpf->prog, *old_prog; 288562306a36Sopenharmony_ci bool running = netif_running(dev); 288662306a36Sopenharmony_ci bool need_reset; 288762306a36Sopenharmony_ci 288862306a36Sopenharmony_ci /* verify igb ring attributes are sufficient for XDP */ 288962306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 289062306a36Sopenharmony_ci struct igb_ring *ring = adapter->rx_ring[i]; 289162306a36Sopenharmony_ci 289262306a36Sopenharmony_ci if (frame_size > igb_rx_bufsz(ring)) { 289362306a36Sopenharmony_ci NL_SET_ERR_MSG_MOD(bpf->extack, 289462306a36Sopenharmony_ci "The RX buffer size is too small for the frame size"); 289562306a36Sopenharmony_ci netdev_warn(dev, "XDP RX buffer size %d is too small for the frame size %d\n", 289662306a36Sopenharmony_ci igb_rx_bufsz(ring), frame_size); 289762306a36Sopenharmony_ci return -EINVAL; 289862306a36Sopenharmony_ci } 289962306a36Sopenharmony_ci } 290062306a36Sopenharmony_ci 290162306a36Sopenharmony_ci old_prog = xchg(&adapter->xdp_prog, prog); 290262306a36Sopenharmony_ci need_reset = (!!prog != !!old_prog); 290362306a36Sopenharmony_ci 290462306a36Sopenharmony_ci /* device is up and bpf is added/removed, must setup the RX queues */ 290562306a36Sopenharmony_ci if (need_reset && running) { 290662306a36Sopenharmony_ci igb_close(dev); 290762306a36Sopenharmony_ci } else { 290862306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) 290962306a36Sopenharmony_ci (void)xchg(&adapter->rx_ring[i]->xdp_prog, 291062306a36Sopenharmony_ci adapter->xdp_prog); 291162306a36Sopenharmony_ci } 291262306a36Sopenharmony_ci 291362306a36Sopenharmony_ci if (old_prog) 291462306a36Sopenharmony_ci bpf_prog_put(old_prog); 291562306a36Sopenharmony_ci 291662306a36Sopenharmony_ci /* bpf is just replaced, RXQ and MTU are already setup */ 291762306a36Sopenharmony_ci if (!need_reset) { 291862306a36Sopenharmony_ci return 0; 291962306a36Sopenharmony_ci } else { 292062306a36Sopenharmony_ci if (prog) 292162306a36Sopenharmony_ci xdp_features_set_redirect_target(dev, true); 292262306a36Sopenharmony_ci else 292362306a36Sopenharmony_ci xdp_features_clear_redirect_target(dev); 292462306a36Sopenharmony_ci } 292562306a36Sopenharmony_ci 292662306a36Sopenharmony_ci if (running) 292762306a36Sopenharmony_ci igb_open(dev); 292862306a36Sopenharmony_ci 292962306a36Sopenharmony_ci return 0; 293062306a36Sopenharmony_ci} 293162306a36Sopenharmony_ci 293262306a36Sopenharmony_cistatic int igb_xdp(struct net_device *dev, struct netdev_bpf *xdp) 293362306a36Sopenharmony_ci{ 293462306a36Sopenharmony_ci switch (xdp->command) { 293562306a36Sopenharmony_ci case XDP_SETUP_PROG: 293662306a36Sopenharmony_ci return igb_xdp_setup(dev, xdp); 293762306a36Sopenharmony_ci default: 293862306a36Sopenharmony_ci return -EINVAL; 293962306a36Sopenharmony_ci } 294062306a36Sopenharmony_ci} 294162306a36Sopenharmony_ci 294262306a36Sopenharmony_cistatic void igb_xdp_ring_update_tail(struct igb_ring *ring) 294362306a36Sopenharmony_ci{ 294462306a36Sopenharmony_ci /* Force memory writes to complete before letting h/w know there 294562306a36Sopenharmony_ci * are new descriptors to fetch. 294662306a36Sopenharmony_ci */ 294762306a36Sopenharmony_ci wmb(); 294862306a36Sopenharmony_ci writel(ring->next_to_use, ring->tail); 294962306a36Sopenharmony_ci} 295062306a36Sopenharmony_ci 295162306a36Sopenharmony_cistatic struct igb_ring *igb_xdp_tx_queue_mapping(struct igb_adapter *adapter) 295262306a36Sopenharmony_ci{ 295362306a36Sopenharmony_ci unsigned int r_idx = smp_processor_id(); 295462306a36Sopenharmony_ci 295562306a36Sopenharmony_ci if (r_idx >= adapter->num_tx_queues) 295662306a36Sopenharmony_ci r_idx = r_idx % adapter->num_tx_queues; 295762306a36Sopenharmony_ci 295862306a36Sopenharmony_ci return adapter->tx_ring[r_idx]; 295962306a36Sopenharmony_ci} 296062306a36Sopenharmony_ci 296162306a36Sopenharmony_cistatic int igb_xdp_xmit_back(struct igb_adapter *adapter, struct xdp_buff *xdp) 296262306a36Sopenharmony_ci{ 296362306a36Sopenharmony_ci struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); 296462306a36Sopenharmony_ci int cpu = smp_processor_id(); 296562306a36Sopenharmony_ci struct igb_ring *tx_ring; 296662306a36Sopenharmony_ci struct netdev_queue *nq; 296762306a36Sopenharmony_ci u32 ret; 296862306a36Sopenharmony_ci 296962306a36Sopenharmony_ci if (unlikely(!xdpf)) 297062306a36Sopenharmony_ci return IGB_XDP_CONSUMED; 297162306a36Sopenharmony_ci 297262306a36Sopenharmony_ci /* During program transitions its possible adapter->xdp_prog is assigned 297362306a36Sopenharmony_ci * but ring has not been configured yet. In this case simply abort xmit. 297462306a36Sopenharmony_ci */ 297562306a36Sopenharmony_ci tx_ring = adapter->xdp_prog ? igb_xdp_tx_queue_mapping(adapter) : NULL; 297662306a36Sopenharmony_ci if (unlikely(!tx_ring)) 297762306a36Sopenharmony_ci return IGB_XDP_CONSUMED; 297862306a36Sopenharmony_ci 297962306a36Sopenharmony_ci nq = txring_txq(tx_ring); 298062306a36Sopenharmony_ci __netif_tx_lock(nq, cpu); 298162306a36Sopenharmony_ci /* Avoid transmit queue timeout since we share it with the slow path */ 298262306a36Sopenharmony_ci txq_trans_cond_update(nq); 298362306a36Sopenharmony_ci ret = igb_xmit_xdp_ring(adapter, tx_ring, xdpf); 298462306a36Sopenharmony_ci __netif_tx_unlock(nq); 298562306a36Sopenharmony_ci 298662306a36Sopenharmony_ci return ret; 298762306a36Sopenharmony_ci} 298862306a36Sopenharmony_ci 298962306a36Sopenharmony_cistatic int igb_xdp_xmit(struct net_device *dev, int n, 299062306a36Sopenharmony_ci struct xdp_frame **frames, u32 flags) 299162306a36Sopenharmony_ci{ 299262306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(dev); 299362306a36Sopenharmony_ci int cpu = smp_processor_id(); 299462306a36Sopenharmony_ci struct igb_ring *tx_ring; 299562306a36Sopenharmony_ci struct netdev_queue *nq; 299662306a36Sopenharmony_ci int nxmit = 0; 299762306a36Sopenharmony_ci int i; 299862306a36Sopenharmony_ci 299962306a36Sopenharmony_ci if (unlikely(test_bit(__IGB_DOWN, &adapter->state))) 300062306a36Sopenharmony_ci return -ENETDOWN; 300162306a36Sopenharmony_ci 300262306a36Sopenharmony_ci if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) 300362306a36Sopenharmony_ci return -EINVAL; 300462306a36Sopenharmony_ci 300562306a36Sopenharmony_ci /* During program transitions its possible adapter->xdp_prog is assigned 300662306a36Sopenharmony_ci * but ring has not been configured yet. In this case simply abort xmit. 300762306a36Sopenharmony_ci */ 300862306a36Sopenharmony_ci tx_ring = adapter->xdp_prog ? igb_xdp_tx_queue_mapping(adapter) : NULL; 300962306a36Sopenharmony_ci if (unlikely(!tx_ring)) 301062306a36Sopenharmony_ci return -ENXIO; 301162306a36Sopenharmony_ci 301262306a36Sopenharmony_ci nq = txring_txq(tx_ring); 301362306a36Sopenharmony_ci __netif_tx_lock(nq, cpu); 301462306a36Sopenharmony_ci 301562306a36Sopenharmony_ci /* Avoid transmit queue timeout since we share it with the slow path */ 301662306a36Sopenharmony_ci txq_trans_cond_update(nq); 301762306a36Sopenharmony_ci 301862306a36Sopenharmony_ci for (i = 0; i < n; i++) { 301962306a36Sopenharmony_ci struct xdp_frame *xdpf = frames[i]; 302062306a36Sopenharmony_ci int err; 302162306a36Sopenharmony_ci 302262306a36Sopenharmony_ci err = igb_xmit_xdp_ring(adapter, tx_ring, xdpf); 302362306a36Sopenharmony_ci if (err != IGB_XDP_TX) 302462306a36Sopenharmony_ci break; 302562306a36Sopenharmony_ci nxmit++; 302662306a36Sopenharmony_ci } 302762306a36Sopenharmony_ci 302862306a36Sopenharmony_ci __netif_tx_unlock(nq); 302962306a36Sopenharmony_ci 303062306a36Sopenharmony_ci if (unlikely(flags & XDP_XMIT_FLUSH)) 303162306a36Sopenharmony_ci igb_xdp_ring_update_tail(tx_ring); 303262306a36Sopenharmony_ci 303362306a36Sopenharmony_ci return nxmit; 303462306a36Sopenharmony_ci} 303562306a36Sopenharmony_ci 303662306a36Sopenharmony_cistatic const struct net_device_ops igb_netdev_ops = { 303762306a36Sopenharmony_ci .ndo_open = igb_open, 303862306a36Sopenharmony_ci .ndo_stop = igb_close, 303962306a36Sopenharmony_ci .ndo_start_xmit = igb_xmit_frame, 304062306a36Sopenharmony_ci .ndo_get_stats64 = igb_get_stats64, 304162306a36Sopenharmony_ci .ndo_set_rx_mode = igb_set_rx_mode, 304262306a36Sopenharmony_ci .ndo_set_mac_address = igb_set_mac, 304362306a36Sopenharmony_ci .ndo_change_mtu = igb_change_mtu, 304462306a36Sopenharmony_ci .ndo_eth_ioctl = igb_ioctl, 304562306a36Sopenharmony_ci .ndo_tx_timeout = igb_tx_timeout, 304662306a36Sopenharmony_ci .ndo_validate_addr = eth_validate_addr, 304762306a36Sopenharmony_ci .ndo_vlan_rx_add_vid = igb_vlan_rx_add_vid, 304862306a36Sopenharmony_ci .ndo_vlan_rx_kill_vid = igb_vlan_rx_kill_vid, 304962306a36Sopenharmony_ci .ndo_set_vf_mac = igb_ndo_set_vf_mac, 305062306a36Sopenharmony_ci .ndo_set_vf_vlan = igb_ndo_set_vf_vlan, 305162306a36Sopenharmony_ci .ndo_set_vf_rate = igb_ndo_set_vf_bw, 305262306a36Sopenharmony_ci .ndo_set_vf_spoofchk = igb_ndo_set_vf_spoofchk, 305362306a36Sopenharmony_ci .ndo_set_vf_trust = igb_ndo_set_vf_trust, 305462306a36Sopenharmony_ci .ndo_get_vf_config = igb_ndo_get_vf_config, 305562306a36Sopenharmony_ci .ndo_fix_features = igb_fix_features, 305662306a36Sopenharmony_ci .ndo_set_features = igb_set_features, 305762306a36Sopenharmony_ci .ndo_fdb_add = igb_ndo_fdb_add, 305862306a36Sopenharmony_ci .ndo_features_check = igb_features_check, 305962306a36Sopenharmony_ci .ndo_setup_tc = igb_setup_tc, 306062306a36Sopenharmony_ci .ndo_bpf = igb_xdp, 306162306a36Sopenharmony_ci .ndo_xdp_xmit = igb_xdp_xmit, 306262306a36Sopenharmony_ci}; 306362306a36Sopenharmony_ci 306462306a36Sopenharmony_ci/** 306562306a36Sopenharmony_ci * igb_set_fw_version - Configure version string for ethtool 306662306a36Sopenharmony_ci * @adapter: adapter struct 306762306a36Sopenharmony_ci **/ 306862306a36Sopenharmony_civoid igb_set_fw_version(struct igb_adapter *adapter) 306962306a36Sopenharmony_ci{ 307062306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 307162306a36Sopenharmony_ci struct e1000_fw_version fw; 307262306a36Sopenharmony_ci 307362306a36Sopenharmony_ci igb_get_fw_version(hw, &fw); 307462306a36Sopenharmony_ci 307562306a36Sopenharmony_ci switch (hw->mac.type) { 307662306a36Sopenharmony_ci case e1000_i210: 307762306a36Sopenharmony_ci case e1000_i211: 307862306a36Sopenharmony_ci if (!(igb_get_flash_presence_i210(hw))) { 307962306a36Sopenharmony_ci snprintf(adapter->fw_version, 308062306a36Sopenharmony_ci sizeof(adapter->fw_version), 308162306a36Sopenharmony_ci "%2d.%2d-%d", 308262306a36Sopenharmony_ci fw.invm_major, fw.invm_minor, 308362306a36Sopenharmony_ci fw.invm_img_type); 308462306a36Sopenharmony_ci break; 308562306a36Sopenharmony_ci } 308662306a36Sopenharmony_ci fallthrough; 308762306a36Sopenharmony_ci default: 308862306a36Sopenharmony_ci /* if option is rom valid, display its version too */ 308962306a36Sopenharmony_ci if (fw.or_valid) { 309062306a36Sopenharmony_ci snprintf(adapter->fw_version, 309162306a36Sopenharmony_ci sizeof(adapter->fw_version), 309262306a36Sopenharmony_ci "%d.%d, 0x%08x, %d.%d.%d", 309362306a36Sopenharmony_ci fw.eep_major, fw.eep_minor, fw.etrack_id, 309462306a36Sopenharmony_ci fw.or_major, fw.or_build, fw.or_patch); 309562306a36Sopenharmony_ci /* no option rom */ 309662306a36Sopenharmony_ci } else if (fw.etrack_id != 0X0000) { 309762306a36Sopenharmony_ci snprintf(adapter->fw_version, 309862306a36Sopenharmony_ci sizeof(adapter->fw_version), 309962306a36Sopenharmony_ci "%d.%d, 0x%08x", 310062306a36Sopenharmony_ci fw.eep_major, fw.eep_minor, fw.etrack_id); 310162306a36Sopenharmony_ci } else { 310262306a36Sopenharmony_ci snprintf(adapter->fw_version, 310362306a36Sopenharmony_ci sizeof(adapter->fw_version), 310462306a36Sopenharmony_ci "%d.%d.%d", 310562306a36Sopenharmony_ci fw.eep_major, fw.eep_minor, fw.eep_build); 310662306a36Sopenharmony_ci } 310762306a36Sopenharmony_ci break; 310862306a36Sopenharmony_ci } 310962306a36Sopenharmony_ci} 311062306a36Sopenharmony_ci 311162306a36Sopenharmony_ci/** 311262306a36Sopenharmony_ci * igb_init_mas - init Media Autosense feature if enabled in the NVM 311362306a36Sopenharmony_ci * 311462306a36Sopenharmony_ci * @adapter: adapter struct 311562306a36Sopenharmony_ci **/ 311662306a36Sopenharmony_cistatic void igb_init_mas(struct igb_adapter *adapter) 311762306a36Sopenharmony_ci{ 311862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 311962306a36Sopenharmony_ci u16 eeprom_data; 312062306a36Sopenharmony_ci 312162306a36Sopenharmony_ci hw->nvm.ops.read(hw, NVM_COMPAT, 1, &eeprom_data); 312262306a36Sopenharmony_ci switch (hw->bus.func) { 312362306a36Sopenharmony_ci case E1000_FUNC_0: 312462306a36Sopenharmony_ci if (eeprom_data & IGB_MAS_ENABLE_0) { 312562306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_MAS_ENABLE; 312662306a36Sopenharmony_ci netdev_info(adapter->netdev, 312762306a36Sopenharmony_ci "MAS: Enabling Media Autosense for port %d\n", 312862306a36Sopenharmony_ci hw->bus.func); 312962306a36Sopenharmony_ci } 313062306a36Sopenharmony_ci break; 313162306a36Sopenharmony_ci case E1000_FUNC_1: 313262306a36Sopenharmony_ci if (eeprom_data & IGB_MAS_ENABLE_1) { 313362306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_MAS_ENABLE; 313462306a36Sopenharmony_ci netdev_info(adapter->netdev, 313562306a36Sopenharmony_ci "MAS: Enabling Media Autosense for port %d\n", 313662306a36Sopenharmony_ci hw->bus.func); 313762306a36Sopenharmony_ci } 313862306a36Sopenharmony_ci break; 313962306a36Sopenharmony_ci case E1000_FUNC_2: 314062306a36Sopenharmony_ci if (eeprom_data & IGB_MAS_ENABLE_2) { 314162306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_MAS_ENABLE; 314262306a36Sopenharmony_ci netdev_info(adapter->netdev, 314362306a36Sopenharmony_ci "MAS: Enabling Media Autosense for port %d\n", 314462306a36Sopenharmony_ci hw->bus.func); 314562306a36Sopenharmony_ci } 314662306a36Sopenharmony_ci break; 314762306a36Sopenharmony_ci case E1000_FUNC_3: 314862306a36Sopenharmony_ci if (eeprom_data & IGB_MAS_ENABLE_3) { 314962306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_MAS_ENABLE; 315062306a36Sopenharmony_ci netdev_info(adapter->netdev, 315162306a36Sopenharmony_ci "MAS: Enabling Media Autosense for port %d\n", 315262306a36Sopenharmony_ci hw->bus.func); 315362306a36Sopenharmony_ci } 315462306a36Sopenharmony_ci break; 315562306a36Sopenharmony_ci default: 315662306a36Sopenharmony_ci /* Shouldn't get here */ 315762306a36Sopenharmony_ci netdev_err(adapter->netdev, 315862306a36Sopenharmony_ci "MAS: Invalid port configuration, returning\n"); 315962306a36Sopenharmony_ci break; 316062306a36Sopenharmony_ci } 316162306a36Sopenharmony_ci} 316262306a36Sopenharmony_ci 316362306a36Sopenharmony_ci/** 316462306a36Sopenharmony_ci * igb_init_i2c - Init I2C interface 316562306a36Sopenharmony_ci * @adapter: pointer to adapter structure 316662306a36Sopenharmony_ci **/ 316762306a36Sopenharmony_cistatic s32 igb_init_i2c(struct igb_adapter *adapter) 316862306a36Sopenharmony_ci{ 316962306a36Sopenharmony_ci s32 status = 0; 317062306a36Sopenharmony_ci 317162306a36Sopenharmony_ci /* I2C interface supported on i350 devices */ 317262306a36Sopenharmony_ci if (adapter->hw.mac.type != e1000_i350) 317362306a36Sopenharmony_ci return 0; 317462306a36Sopenharmony_ci 317562306a36Sopenharmony_ci /* Initialize the i2c bus which is controlled by the registers. 317662306a36Sopenharmony_ci * This bus will use the i2c_algo_bit structure that implements 317762306a36Sopenharmony_ci * the protocol through toggling of the 4 bits in the register. 317862306a36Sopenharmony_ci */ 317962306a36Sopenharmony_ci adapter->i2c_adap.owner = THIS_MODULE; 318062306a36Sopenharmony_ci adapter->i2c_algo = igb_i2c_algo; 318162306a36Sopenharmony_ci adapter->i2c_algo.data = adapter; 318262306a36Sopenharmony_ci adapter->i2c_adap.algo_data = &adapter->i2c_algo; 318362306a36Sopenharmony_ci adapter->i2c_adap.dev.parent = &adapter->pdev->dev; 318462306a36Sopenharmony_ci strscpy(adapter->i2c_adap.name, "igb BB", 318562306a36Sopenharmony_ci sizeof(adapter->i2c_adap.name)); 318662306a36Sopenharmony_ci status = i2c_bit_add_bus(&adapter->i2c_adap); 318762306a36Sopenharmony_ci return status; 318862306a36Sopenharmony_ci} 318962306a36Sopenharmony_ci 319062306a36Sopenharmony_ci/** 319162306a36Sopenharmony_ci * igb_probe - Device Initialization Routine 319262306a36Sopenharmony_ci * @pdev: PCI device information struct 319362306a36Sopenharmony_ci * @ent: entry in igb_pci_tbl 319462306a36Sopenharmony_ci * 319562306a36Sopenharmony_ci * Returns 0 on success, negative on failure 319662306a36Sopenharmony_ci * 319762306a36Sopenharmony_ci * igb_probe initializes an adapter identified by a pci_dev structure. 319862306a36Sopenharmony_ci * The OS initialization, configuring of the adapter private structure, 319962306a36Sopenharmony_ci * and a hardware reset occur. 320062306a36Sopenharmony_ci **/ 320162306a36Sopenharmony_cistatic int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 320262306a36Sopenharmony_ci{ 320362306a36Sopenharmony_ci struct net_device *netdev; 320462306a36Sopenharmony_ci struct igb_adapter *adapter; 320562306a36Sopenharmony_ci struct e1000_hw *hw; 320662306a36Sopenharmony_ci u16 eeprom_data = 0; 320762306a36Sopenharmony_ci s32 ret_val; 320862306a36Sopenharmony_ci static int global_quad_port_a; /* global quad port a indication */ 320962306a36Sopenharmony_ci const struct e1000_info *ei = igb_info_tbl[ent->driver_data]; 321062306a36Sopenharmony_ci u8 part_str[E1000_PBANUM_LENGTH]; 321162306a36Sopenharmony_ci int err; 321262306a36Sopenharmony_ci 321362306a36Sopenharmony_ci /* Catch broken hardware that put the wrong VF device ID in 321462306a36Sopenharmony_ci * the PCIe SR-IOV capability. 321562306a36Sopenharmony_ci */ 321662306a36Sopenharmony_ci if (pdev->is_virtfn) { 321762306a36Sopenharmony_ci WARN(1, KERN_ERR "%s (%x:%x) should not be a VF!\n", 321862306a36Sopenharmony_ci pci_name(pdev), pdev->vendor, pdev->device); 321962306a36Sopenharmony_ci return -EINVAL; 322062306a36Sopenharmony_ci } 322162306a36Sopenharmony_ci 322262306a36Sopenharmony_ci err = pci_enable_device_mem(pdev); 322362306a36Sopenharmony_ci if (err) 322462306a36Sopenharmony_ci return err; 322562306a36Sopenharmony_ci 322662306a36Sopenharmony_ci err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 322762306a36Sopenharmony_ci if (err) { 322862306a36Sopenharmony_ci dev_err(&pdev->dev, 322962306a36Sopenharmony_ci "No usable DMA configuration, aborting\n"); 323062306a36Sopenharmony_ci goto err_dma; 323162306a36Sopenharmony_ci } 323262306a36Sopenharmony_ci 323362306a36Sopenharmony_ci err = pci_request_mem_regions(pdev, igb_driver_name); 323462306a36Sopenharmony_ci if (err) 323562306a36Sopenharmony_ci goto err_pci_reg; 323662306a36Sopenharmony_ci 323762306a36Sopenharmony_ci pci_set_master(pdev); 323862306a36Sopenharmony_ci pci_save_state(pdev); 323962306a36Sopenharmony_ci 324062306a36Sopenharmony_ci err = -ENOMEM; 324162306a36Sopenharmony_ci netdev = alloc_etherdev_mq(sizeof(struct igb_adapter), 324262306a36Sopenharmony_ci IGB_MAX_TX_QUEUES); 324362306a36Sopenharmony_ci if (!netdev) 324462306a36Sopenharmony_ci goto err_alloc_etherdev; 324562306a36Sopenharmony_ci 324662306a36Sopenharmony_ci SET_NETDEV_DEV(netdev, &pdev->dev); 324762306a36Sopenharmony_ci 324862306a36Sopenharmony_ci pci_set_drvdata(pdev, netdev); 324962306a36Sopenharmony_ci adapter = netdev_priv(netdev); 325062306a36Sopenharmony_ci adapter->netdev = netdev; 325162306a36Sopenharmony_ci adapter->pdev = pdev; 325262306a36Sopenharmony_ci hw = &adapter->hw; 325362306a36Sopenharmony_ci hw->back = adapter; 325462306a36Sopenharmony_ci adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); 325562306a36Sopenharmony_ci 325662306a36Sopenharmony_ci err = -EIO; 325762306a36Sopenharmony_ci adapter->io_addr = pci_iomap(pdev, 0, 0); 325862306a36Sopenharmony_ci if (!adapter->io_addr) 325962306a36Sopenharmony_ci goto err_ioremap; 326062306a36Sopenharmony_ci /* hw->hw_addr can be altered, we'll use adapter->io_addr for unmap */ 326162306a36Sopenharmony_ci hw->hw_addr = adapter->io_addr; 326262306a36Sopenharmony_ci 326362306a36Sopenharmony_ci netdev->netdev_ops = &igb_netdev_ops; 326462306a36Sopenharmony_ci igb_set_ethtool_ops(netdev); 326562306a36Sopenharmony_ci netdev->watchdog_timeo = 5 * HZ; 326662306a36Sopenharmony_ci 326762306a36Sopenharmony_ci strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); 326862306a36Sopenharmony_ci 326962306a36Sopenharmony_ci netdev->mem_start = pci_resource_start(pdev, 0); 327062306a36Sopenharmony_ci netdev->mem_end = pci_resource_end(pdev, 0); 327162306a36Sopenharmony_ci 327262306a36Sopenharmony_ci /* PCI config space info */ 327362306a36Sopenharmony_ci hw->vendor_id = pdev->vendor; 327462306a36Sopenharmony_ci hw->device_id = pdev->device; 327562306a36Sopenharmony_ci hw->revision_id = pdev->revision; 327662306a36Sopenharmony_ci hw->subsystem_vendor_id = pdev->subsystem_vendor; 327762306a36Sopenharmony_ci hw->subsystem_device_id = pdev->subsystem_device; 327862306a36Sopenharmony_ci 327962306a36Sopenharmony_ci /* Copy the default MAC, PHY and NVM function pointers */ 328062306a36Sopenharmony_ci memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops)); 328162306a36Sopenharmony_ci memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops)); 328262306a36Sopenharmony_ci memcpy(&hw->nvm.ops, ei->nvm_ops, sizeof(hw->nvm.ops)); 328362306a36Sopenharmony_ci /* Initialize skew-specific constants */ 328462306a36Sopenharmony_ci err = ei->get_invariants(hw); 328562306a36Sopenharmony_ci if (err) 328662306a36Sopenharmony_ci goto err_sw_init; 328762306a36Sopenharmony_ci 328862306a36Sopenharmony_ci /* setup the private structure */ 328962306a36Sopenharmony_ci err = igb_sw_init(adapter); 329062306a36Sopenharmony_ci if (err) 329162306a36Sopenharmony_ci goto err_sw_init; 329262306a36Sopenharmony_ci 329362306a36Sopenharmony_ci igb_get_bus_info_pcie(hw); 329462306a36Sopenharmony_ci 329562306a36Sopenharmony_ci hw->phy.autoneg_wait_to_complete = false; 329662306a36Sopenharmony_ci 329762306a36Sopenharmony_ci /* Copper options */ 329862306a36Sopenharmony_ci if (hw->phy.media_type == e1000_media_type_copper) { 329962306a36Sopenharmony_ci hw->phy.mdix = AUTO_ALL_MODES; 330062306a36Sopenharmony_ci hw->phy.disable_polarity_correction = false; 330162306a36Sopenharmony_ci hw->phy.ms_type = e1000_ms_hw_default; 330262306a36Sopenharmony_ci } 330362306a36Sopenharmony_ci 330462306a36Sopenharmony_ci if (igb_check_reset_block(hw)) 330562306a36Sopenharmony_ci dev_info(&pdev->dev, 330662306a36Sopenharmony_ci "PHY reset is blocked due to SOL/IDER session.\n"); 330762306a36Sopenharmony_ci 330862306a36Sopenharmony_ci /* features is initialized to 0 in allocation, it might have bits 330962306a36Sopenharmony_ci * set by igb_sw_init so we should use an or instead of an 331062306a36Sopenharmony_ci * assignment. 331162306a36Sopenharmony_ci */ 331262306a36Sopenharmony_ci netdev->features |= NETIF_F_SG | 331362306a36Sopenharmony_ci NETIF_F_TSO | 331462306a36Sopenharmony_ci NETIF_F_TSO6 | 331562306a36Sopenharmony_ci NETIF_F_RXHASH | 331662306a36Sopenharmony_ci NETIF_F_RXCSUM | 331762306a36Sopenharmony_ci NETIF_F_HW_CSUM; 331862306a36Sopenharmony_ci 331962306a36Sopenharmony_ci if (hw->mac.type >= e1000_82576) 332062306a36Sopenharmony_ci netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_GSO_UDP_L4; 332162306a36Sopenharmony_ci 332262306a36Sopenharmony_ci if (hw->mac.type >= e1000_i350) 332362306a36Sopenharmony_ci netdev->features |= NETIF_F_HW_TC; 332462306a36Sopenharmony_ci 332562306a36Sopenharmony_ci#define IGB_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \ 332662306a36Sopenharmony_ci NETIF_F_GSO_GRE_CSUM | \ 332762306a36Sopenharmony_ci NETIF_F_GSO_IPXIP4 | \ 332862306a36Sopenharmony_ci NETIF_F_GSO_IPXIP6 | \ 332962306a36Sopenharmony_ci NETIF_F_GSO_UDP_TUNNEL | \ 333062306a36Sopenharmony_ci NETIF_F_GSO_UDP_TUNNEL_CSUM) 333162306a36Sopenharmony_ci 333262306a36Sopenharmony_ci netdev->gso_partial_features = IGB_GSO_PARTIAL_FEATURES; 333362306a36Sopenharmony_ci netdev->features |= NETIF_F_GSO_PARTIAL | IGB_GSO_PARTIAL_FEATURES; 333462306a36Sopenharmony_ci 333562306a36Sopenharmony_ci /* copy netdev features into list of user selectable features */ 333662306a36Sopenharmony_ci netdev->hw_features |= netdev->features | 333762306a36Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_RX | 333862306a36Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_TX | 333962306a36Sopenharmony_ci NETIF_F_RXALL; 334062306a36Sopenharmony_ci 334162306a36Sopenharmony_ci if (hw->mac.type >= e1000_i350) 334262306a36Sopenharmony_ci netdev->hw_features |= NETIF_F_NTUPLE; 334362306a36Sopenharmony_ci 334462306a36Sopenharmony_ci netdev->features |= NETIF_F_HIGHDMA; 334562306a36Sopenharmony_ci 334662306a36Sopenharmony_ci netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID; 334762306a36Sopenharmony_ci netdev->mpls_features |= NETIF_F_HW_CSUM; 334862306a36Sopenharmony_ci netdev->hw_enc_features |= netdev->vlan_features; 334962306a36Sopenharmony_ci 335062306a36Sopenharmony_ci /* set this bit last since it cannot be part of vlan_features */ 335162306a36Sopenharmony_ci netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | 335262306a36Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_RX | 335362306a36Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_TX; 335462306a36Sopenharmony_ci 335562306a36Sopenharmony_ci netdev->priv_flags |= IFF_SUPP_NOFCS; 335662306a36Sopenharmony_ci 335762306a36Sopenharmony_ci netdev->priv_flags |= IFF_UNICAST_FLT; 335862306a36Sopenharmony_ci netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT; 335962306a36Sopenharmony_ci 336062306a36Sopenharmony_ci /* MTU range: 68 - 9216 */ 336162306a36Sopenharmony_ci netdev->min_mtu = ETH_MIN_MTU; 336262306a36Sopenharmony_ci netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; 336362306a36Sopenharmony_ci 336462306a36Sopenharmony_ci adapter->en_mng_pt = igb_enable_mng_pass_thru(hw); 336562306a36Sopenharmony_ci 336662306a36Sopenharmony_ci /* before reading the NVM, reset the controller to put the device in a 336762306a36Sopenharmony_ci * known good starting state 336862306a36Sopenharmony_ci */ 336962306a36Sopenharmony_ci hw->mac.ops.reset_hw(hw); 337062306a36Sopenharmony_ci 337162306a36Sopenharmony_ci /* make sure the NVM is good , i211/i210 parts can have special NVM 337262306a36Sopenharmony_ci * that doesn't contain a checksum 337362306a36Sopenharmony_ci */ 337462306a36Sopenharmony_ci switch (hw->mac.type) { 337562306a36Sopenharmony_ci case e1000_i210: 337662306a36Sopenharmony_ci case e1000_i211: 337762306a36Sopenharmony_ci if (igb_get_flash_presence_i210(hw)) { 337862306a36Sopenharmony_ci if (hw->nvm.ops.validate(hw) < 0) { 337962306a36Sopenharmony_ci dev_err(&pdev->dev, 338062306a36Sopenharmony_ci "The NVM Checksum Is Not Valid\n"); 338162306a36Sopenharmony_ci err = -EIO; 338262306a36Sopenharmony_ci goto err_eeprom; 338362306a36Sopenharmony_ci } 338462306a36Sopenharmony_ci } 338562306a36Sopenharmony_ci break; 338662306a36Sopenharmony_ci default: 338762306a36Sopenharmony_ci if (hw->nvm.ops.validate(hw) < 0) { 338862306a36Sopenharmony_ci dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); 338962306a36Sopenharmony_ci err = -EIO; 339062306a36Sopenharmony_ci goto err_eeprom; 339162306a36Sopenharmony_ci } 339262306a36Sopenharmony_ci break; 339362306a36Sopenharmony_ci } 339462306a36Sopenharmony_ci 339562306a36Sopenharmony_ci if (eth_platform_get_mac_address(&pdev->dev, hw->mac.addr)) { 339662306a36Sopenharmony_ci /* copy the MAC address out of the NVM */ 339762306a36Sopenharmony_ci if (hw->mac.ops.read_mac_addr(hw)) 339862306a36Sopenharmony_ci dev_err(&pdev->dev, "NVM Read Error\n"); 339962306a36Sopenharmony_ci } 340062306a36Sopenharmony_ci 340162306a36Sopenharmony_ci eth_hw_addr_set(netdev, hw->mac.addr); 340262306a36Sopenharmony_ci 340362306a36Sopenharmony_ci if (!is_valid_ether_addr(netdev->dev_addr)) { 340462306a36Sopenharmony_ci dev_err(&pdev->dev, "Invalid MAC Address\n"); 340562306a36Sopenharmony_ci err = -EIO; 340662306a36Sopenharmony_ci goto err_eeprom; 340762306a36Sopenharmony_ci } 340862306a36Sopenharmony_ci 340962306a36Sopenharmony_ci igb_set_default_mac_filter(adapter); 341062306a36Sopenharmony_ci 341162306a36Sopenharmony_ci /* get firmware version for ethtool -i */ 341262306a36Sopenharmony_ci igb_set_fw_version(adapter); 341362306a36Sopenharmony_ci 341462306a36Sopenharmony_ci /* configure RXPBSIZE and TXPBSIZE */ 341562306a36Sopenharmony_ci if (hw->mac.type == e1000_i210) { 341662306a36Sopenharmony_ci wr32(E1000_RXPBS, I210_RXPBSIZE_DEFAULT); 341762306a36Sopenharmony_ci wr32(E1000_TXPBS, I210_TXPBSIZE_DEFAULT); 341862306a36Sopenharmony_ci } 341962306a36Sopenharmony_ci 342062306a36Sopenharmony_ci timer_setup(&adapter->watchdog_timer, igb_watchdog, 0); 342162306a36Sopenharmony_ci timer_setup(&adapter->phy_info_timer, igb_update_phy_info, 0); 342262306a36Sopenharmony_ci 342362306a36Sopenharmony_ci INIT_WORK(&adapter->reset_task, igb_reset_task); 342462306a36Sopenharmony_ci INIT_WORK(&adapter->watchdog_task, igb_watchdog_task); 342562306a36Sopenharmony_ci 342662306a36Sopenharmony_ci /* Initialize link properties that are user-changeable */ 342762306a36Sopenharmony_ci adapter->fc_autoneg = true; 342862306a36Sopenharmony_ci hw->mac.autoneg = true; 342962306a36Sopenharmony_ci hw->phy.autoneg_advertised = 0x2f; 343062306a36Sopenharmony_ci 343162306a36Sopenharmony_ci hw->fc.requested_mode = e1000_fc_default; 343262306a36Sopenharmony_ci hw->fc.current_mode = e1000_fc_default; 343362306a36Sopenharmony_ci 343462306a36Sopenharmony_ci igb_validate_mdi_setting(hw); 343562306a36Sopenharmony_ci 343662306a36Sopenharmony_ci /* By default, support wake on port A */ 343762306a36Sopenharmony_ci if (hw->bus.func == 0) 343862306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_WOL_SUPPORTED; 343962306a36Sopenharmony_ci 344062306a36Sopenharmony_ci /* Check the NVM for wake support on non-port A ports */ 344162306a36Sopenharmony_ci if (hw->mac.type >= e1000_82580) 344262306a36Sopenharmony_ci hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + 344362306a36Sopenharmony_ci NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, 344462306a36Sopenharmony_ci &eeprom_data); 344562306a36Sopenharmony_ci else if (hw->bus.func == 1) 344662306a36Sopenharmony_ci hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); 344762306a36Sopenharmony_ci 344862306a36Sopenharmony_ci if (eeprom_data & IGB_EEPROM_APME) 344962306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_WOL_SUPPORTED; 345062306a36Sopenharmony_ci 345162306a36Sopenharmony_ci /* now that we have the eeprom settings, apply the special cases where 345262306a36Sopenharmony_ci * the eeprom may be wrong or the board simply won't support wake on 345362306a36Sopenharmony_ci * lan on a particular port 345462306a36Sopenharmony_ci */ 345562306a36Sopenharmony_ci switch (pdev->device) { 345662306a36Sopenharmony_ci case E1000_DEV_ID_82575GB_QUAD_COPPER: 345762306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; 345862306a36Sopenharmony_ci break; 345962306a36Sopenharmony_ci case E1000_DEV_ID_82575EB_FIBER_SERDES: 346062306a36Sopenharmony_ci case E1000_DEV_ID_82576_FIBER: 346162306a36Sopenharmony_ci case E1000_DEV_ID_82576_SERDES: 346262306a36Sopenharmony_ci /* Wake events only supported on port A for dual fiber 346362306a36Sopenharmony_ci * regardless of eeprom setting 346462306a36Sopenharmony_ci */ 346562306a36Sopenharmony_ci if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1) 346662306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; 346762306a36Sopenharmony_ci break; 346862306a36Sopenharmony_ci case E1000_DEV_ID_82576_QUAD_COPPER: 346962306a36Sopenharmony_ci case E1000_DEV_ID_82576_QUAD_COPPER_ET2: 347062306a36Sopenharmony_ci /* if quad port adapter, disable WoL on all but port A */ 347162306a36Sopenharmony_ci if (global_quad_port_a != 0) 347262306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; 347362306a36Sopenharmony_ci else 347462306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_QUAD_PORT_A; 347562306a36Sopenharmony_ci /* Reset for multiple quad port adapters */ 347662306a36Sopenharmony_ci if (++global_quad_port_a == 4) 347762306a36Sopenharmony_ci global_quad_port_a = 0; 347862306a36Sopenharmony_ci break; 347962306a36Sopenharmony_ci default: 348062306a36Sopenharmony_ci /* If the device can't wake, don't set software support */ 348162306a36Sopenharmony_ci if (!device_can_wakeup(&adapter->pdev->dev)) 348262306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; 348362306a36Sopenharmony_ci } 348462306a36Sopenharmony_ci 348562306a36Sopenharmony_ci /* initialize the wol settings based on the eeprom settings */ 348662306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_WOL_SUPPORTED) 348762306a36Sopenharmony_ci adapter->wol |= E1000_WUFC_MAG; 348862306a36Sopenharmony_ci 348962306a36Sopenharmony_ci /* Some vendors want WoL disabled by default, but still supported */ 349062306a36Sopenharmony_ci if ((hw->mac.type == e1000_i350) && 349162306a36Sopenharmony_ci (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)) { 349262306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_WOL_SUPPORTED; 349362306a36Sopenharmony_ci adapter->wol = 0; 349462306a36Sopenharmony_ci } 349562306a36Sopenharmony_ci 349662306a36Sopenharmony_ci /* Some vendors want the ability to Use the EEPROM setting as 349762306a36Sopenharmony_ci * enable/disable only, and not for capability 349862306a36Sopenharmony_ci */ 349962306a36Sopenharmony_ci if (((hw->mac.type == e1000_i350) || 350062306a36Sopenharmony_ci (hw->mac.type == e1000_i354)) && 350162306a36Sopenharmony_ci (pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)) { 350262306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_WOL_SUPPORTED; 350362306a36Sopenharmony_ci adapter->wol = 0; 350462306a36Sopenharmony_ci } 350562306a36Sopenharmony_ci if (hw->mac.type == e1000_i350) { 350662306a36Sopenharmony_ci if (((pdev->subsystem_device == 0x5001) || 350762306a36Sopenharmony_ci (pdev->subsystem_device == 0x5002)) && 350862306a36Sopenharmony_ci (hw->bus.func == 0)) { 350962306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_WOL_SUPPORTED; 351062306a36Sopenharmony_ci adapter->wol = 0; 351162306a36Sopenharmony_ci } 351262306a36Sopenharmony_ci if (pdev->subsystem_device == 0x1F52) 351362306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_WOL_SUPPORTED; 351462306a36Sopenharmony_ci } 351562306a36Sopenharmony_ci 351662306a36Sopenharmony_ci device_set_wakeup_enable(&adapter->pdev->dev, 351762306a36Sopenharmony_ci adapter->flags & IGB_FLAG_WOL_SUPPORTED); 351862306a36Sopenharmony_ci 351962306a36Sopenharmony_ci /* reset the hardware with the new settings */ 352062306a36Sopenharmony_ci igb_reset(adapter); 352162306a36Sopenharmony_ci 352262306a36Sopenharmony_ci /* Init the I2C interface */ 352362306a36Sopenharmony_ci err = igb_init_i2c(adapter); 352462306a36Sopenharmony_ci if (err) { 352562306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to init i2c interface\n"); 352662306a36Sopenharmony_ci goto err_eeprom; 352762306a36Sopenharmony_ci } 352862306a36Sopenharmony_ci 352962306a36Sopenharmony_ci /* let the f/w know that the h/w is now under the control of the 353062306a36Sopenharmony_ci * driver. 353162306a36Sopenharmony_ci */ 353262306a36Sopenharmony_ci igb_get_hw_control(adapter); 353362306a36Sopenharmony_ci 353462306a36Sopenharmony_ci strcpy(netdev->name, "eth%d"); 353562306a36Sopenharmony_ci err = register_netdev(netdev); 353662306a36Sopenharmony_ci if (err) 353762306a36Sopenharmony_ci goto err_register; 353862306a36Sopenharmony_ci 353962306a36Sopenharmony_ci /* carrier off reporting is important to ethtool even BEFORE open */ 354062306a36Sopenharmony_ci netif_carrier_off(netdev); 354162306a36Sopenharmony_ci 354262306a36Sopenharmony_ci#ifdef CONFIG_IGB_DCA 354362306a36Sopenharmony_ci if (dca_add_requester(&pdev->dev) == 0) { 354462306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_DCA_ENABLED; 354562306a36Sopenharmony_ci dev_info(&pdev->dev, "DCA enabled\n"); 354662306a36Sopenharmony_ci igb_setup_dca(adapter); 354762306a36Sopenharmony_ci } 354862306a36Sopenharmony_ci 354962306a36Sopenharmony_ci#endif 355062306a36Sopenharmony_ci#ifdef CONFIG_IGB_HWMON 355162306a36Sopenharmony_ci /* Initialize the thermal sensor on i350 devices. */ 355262306a36Sopenharmony_ci if (hw->mac.type == e1000_i350 && hw->bus.func == 0) { 355362306a36Sopenharmony_ci u16 ets_word; 355462306a36Sopenharmony_ci 355562306a36Sopenharmony_ci /* Read the NVM to determine if this i350 device supports an 355662306a36Sopenharmony_ci * external thermal sensor. 355762306a36Sopenharmony_ci */ 355862306a36Sopenharmony_ci hw->nvm.ops.read(hw, NVM_ETS_CFG, 1, &ets_word); 355962306a36Sopenharmony_ci if (ets_word != 0x0000 && ets_word != 0xFFFF) 356062306a36Sopenharmony_ci adapter->ets = true; 356162306a36Sopenharmony_ci else 356262306a36Sopenharmony_ci adapter->ets = false; 356362306a36Sopenharmony_ci /* Only enable I2C bit banging if an external thermal 356462306a36Sopenharmony_ci * sensor is supported. 356562306a36Sopenharmony_ci */ 356662306a36Sopenharmony_ci if (adapter->ets) 356762306a36Sopenharmony_ci igb_set_i2c_bb(hw); 356862306a36Sopenharmony_ci hw->mac.ops.init_thermal_sensor_thresh(hw); 356962306a36Sopenharmony_ci if (igb_sysfs_init(adapter)) 357062306a36Sopenharmony_ci dev_err(&pdev->dev, 357162306a36Sopenharmony_ci "failed to allocate sysfs resources\n"); 357262306a36Sopenharmony_ci } else { 357362306a36Sopenharmony_ci adapter->ets = false; 357462306a36Sopenharmony_ci } 357562306a36Sopenharmony_ci#endif 357662306a36Sopenharmony_ci /* Check if Media Autosense is enabled */ 357762306a36Sopenharmony_ci adapter->ei = *ei; 357862306a36Sopenharmony_ci if (hw->dev_spec._82575.mas_capable) 357962306a36Sopenharmony_ci igb_init_mas(adapter); 358062306a36Sopenharmony_ci 358162306a36Sopenharmony_ci /* do hw tstamp init after resetting */ 358262306a36Sopenharmony_ci igb_ptp_init(adapter); 358362306a36Sopenharmony_ci 358462306a36Sopenharmony_ci dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n"); 358562306a36Sopenharmony_ci /* print bus type/speed/width info, not applicable to i354 */ 358662306a36Sopenharmony_ci if (hw->mac.type != e1000_i354) { 358762306a36Sopenharmony_ci dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n", 358862306a36Sopenharmony_ci netdev->name, 358962306a36Sopenharmony_ci ((hw->bus.speed == e1000_bus_speed_2500) ? "2.5Gb/s" : 359062306a36Sopenharmony_ci (hw->bus.speed == e1000_bus_speed_5000) ? "5.0Gb/s" : 359162306a36Sopenharmony_ci "unknown"), 359262306a36Sopenharmony_ci ((hw->bus.width == e1000_bus_width_pcie_x4) ? 359362306a36Sopenharmony_ci "Width x4" : 359462306a36Sopenharmony_ci (hw->bus.width == e1000_bus_width_pcie_x2) ? 359562306a36Sopenharmony_ci "Width x2" : 359662306a36Sopenharmony_ci (hw->bus.width == e1000_bus_width_pcie_x1) ? 359762306a36Sopenharmony_ci "Width x1" : "unknown"), netdev->dev_addr); 359862306a36Sopenharmony_ci } 359962306a36Sopenharmony_ci 360062306a36Sopenharmony_ci if ((hw->mac.type == e1000_82576 && 360162306a36Sopenharmony_ci rd32(E1000_EECD) & E1000_EECD_PRES) || 360262306a36Sopenharmony_ci (hw->mac.type >= e1000_i210 || 360362306a36Sopenharmony_ci igb_get_flash_presence_i210(hw))) { 360462306a36Sopenharmony_ci ret_val = igb_read_part_string(hw, part_str, 360562306a36Sopenharmony_ci E1000_PBANUM_LENGTH); 360662306a36Sopenharmony_ci } else { 360762306a36Sopenharmony_ci ret_val = -E1000_ERR_INVM_VALUE_NOT_FOUND; 360862306a36Sopenharmony_ci } 360962306a36Sopenharmony_ci 361062306a36Sopenharmony_ci if (ret_val) 361162306a36Sopenharmony_ci strcpy(part_str, "Unknown"); 361262306a36Sopenharmony_ci dev_info(&pdev->dev, "%s: PBA No: %s\n", netdev->name, part_str); 361362306a36Sopenharmony_ci dev_info(&pdev->dev, 361462306a36Sopenharmony_ci "Using %s interrupts. %d rx queue(s), %d tx queue(s)\n", 361562306a36Sopenharmony_ci (adapter->flags & IGB_FLAG_HAS_MSIX) ? "MSI-X" : 361662306a36Sopenharmony_ci (adapter->flags & IGB_FLAG_HAS_MSI) ? "MSI" : "legacy", 361762306a36Sopenharmony_ci adapter->num_rx_queues, adapter->num_tx_queues); 361862306a36Sopenharmony_ci if (hw->phy.media_type == e1000_media_type_copper) { 361962306a36Sopenharmony_ci switch (hw->mac.type) { 362062306a36Sopenharmony_ci case e1000_i350: 362162306a36Sopenharmony_ci case e1000_i210: 362262306a36Sopenharmony_ci case e1000_i211: 362362306a36Sopenharmony_ci /* Enable EEE for internal copper PHY devices */ 362462306a36Sopenharmony_ci err = igb_set_eee_i350(hw, true, true); 362562306a36Sopenharmony_ci if ((!err) && 362662306a36Sopenharmony_ci (!hw->dev_spec._82575.eee_disable)) { 362762306a36Sopenharmony_ci adapter->eee_advert = 362862306a36Sopenharmony_ci MDIO_EEE_100TX | MDIO_EEE_1000T; 362962306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_EEE; 363062306a36Sopenharmony_ci } 363162306a36Sopenharmony_ci break; 363262306a36Sopenharmony_ci case e1000_i354: 363362306a36Sopenharmony_ci if ((rd32(E1000_CTRL_EXT) & 363462306a36Sopenharmony_ci E1000_CTRL_EXT_LINK_MODE_SGMII)) { 363562306a36Sopenharmony_ci err = igb_set_eee_i354(hw, true, true); 363662306a36Sopenharmony_ci if ((!err) && 363762306a36Sopenharmony_ci (!hw->dev_spec._82575.eee_disable)) { 363862306a36Sopenharmony_ci adapter->eee_advert = 363962306a36Sopenharmony_ci MDIO_EEE_100TX | MDIO_EEE_1000T; 364062306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_EEE; 364162306a36Sopenharmony_ci } 364262306a36Sopenharmony_ci } 364362306a36Sopenharmony_ci break; 364462306a36Sopenharmony_ci default: 364562306a36Sopenharmony_ci break; 364662306a36Sopenharmony_ci } 364762306a36Sopenharmony_ci } 364862306a36Sopenharmony_ci 364962306a36Sopenharmony_ci dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NO_DIRECT_COMPLETE); 365062306a36Sopenharmony_ci 365162306a36Sopenharmony_ci pm_runtime_put_noidle(&pdev->dev); 365262306a36Sopenharmony_ci return 0; 365362306a36Sopenharmony_ci 365462306a36Sopenharmony_cierr_register: 365562306a36Sopenharmony_ci igb_release_hw_control(adapter); 365662306a36Sopenharmony_ci memset(&adapter->i2c_adap, 0, sizeof(adapter->i2c_adap)); 365762306a36Sopenharmony_cierr_eeprom: 365862306a36Sopenharmony_ci if (!igb_check_reset_block(hw)) 365962306a36Sopenharmony_ci igb_reset_phy(hw); 366062306a36Sopenharmony_ci 366162306a36Sopenharmony_ci if (hw->flash_address) 366262306a36Sopenharmony_ci iounmap(hw->flash_address); 366362306a36Sopenharmony_cierr_sw_init: 366462306a36Sopenharmony_ci kfree(adapter->mac_table); 366562306a36Sopenharmony_ci kfree(adapter->shadow_vfta); 366662306a36Sopenharmony_ci igb_clear_interrupt_scheme(adapter); 366762306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 366862306a36Sopenharmony_ci igb_disable_sriov(pdev, false); 366962306a36Sopenharmony_ci#endif 367062306a36Sopenharmony_ci pci_iounmap(pdev, adapter->io_addr); 367162306a36Sopenharmony_cierr_ioremap: 367262306a36Sopenharmony_ci free_netdev(netdev); 367362306a36Sopenharmony_cierr_alloc_etherdev: 367462306a36Sopenharmony_ci pci_release_mem_regions(pdev); 367562306a36Sopenharmony_cierr_pci_reg: 367662306a36Sopenharmony_cierr_dma: 367762306a36Sopenharmony_ci pci_disable_device(pdev); 367862306a36Sopenharmony_ci return err; 367962306a36Sopenharmony_ci} 368062306a36Sopenharmony_ci 368162306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 368262306a36Sopenharmony_cistatic int igb_sriov_reinit(struct pci_dev *dev) 368362306a36Sopenharmony_ci{ 368462306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(dev); 368562306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 368662306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 368762306a36Sopenharmony_ci 368862306a36Sopenharmony_ci rtnl_lock(); 368962306a36Sopenharmony_ci 369062306a36Sopenharmony_ci if (netif_running(netdev)) 369162306a36Sopenharmony_ci igb_close(netdev); 369262306a36Sopenharmony_ci else 369362306a36Sopenharmony_ci igb_reset(adapter); 369462306a36Sopenharmony_ci 369562306a36Sopenharmony_ci igb_clear_interrupt_scheme(adapter); 369662306a36Sopenharmony_ci 369762306a36Sopenharmony_ci igb_init_queue_configuration(adapter); 369862306a36Sopenharmony_ci 369962306a36Sopenharmony_ci if (igb_init_interrupt_scheme(adapter, true)) { 370062306a36Sopenharmony_ci rtnl_unlock(); 370162306a36Sopenharmony_ci dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); 370262306a36Sopenharmony_ci return -ENOMEM; 370362306a36Sopenharmony_ci } 370462306a36Sopenharmony_ci 370562306a36Sopenharmony_ci if (netif_running(netdev)) 370662306a36Sopenharmony_ci igb_open(netdev); 370762306a36Sopenharmony_ci 370862306a36Sopenharmony_ci rtnl_unlock(); 370962306a36Sopenharmony_ci 371062306a36Sopenharmony_ci return 0; 371162306a36Sopenharmony_ci} 371262306a36Sopenharmony_ci 371362306a36Sopenharmony_cistatic int igb_disable_sriov(struct pci_dev *pdev, bool reinit) 371462306a36Sopenharmony_ci{ 371562306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 371662306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 371762306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 371862306a36Sopenharmony_ci unsigned long flags; 371962306a36Sopenharmony_ci 372062306a36Sopenharmony_ci /* reclaim resources allocated to VFs */ 372162306a36Sopenharmony_ci if (adapter->vf_data) { 372262306a36Sopenharmony_ci /* disable iov and allow time for transactions to clear */ 372362306a36Sopenharmony_ci if (pci_vfs_assigned(pdev)) { 372462306a36Sopenharmony_ci dev_warn(&pdev->dev, 372562306a36Sopenharmony_ci "Cannot deallocate SR-IOV virtual functions while they are assigned - VFs will not be deallocated\n"); 372662306a36Sopenharmony_ci return -EPERM; 372762306a36Sopenharmony_ci } else { 372862306a36Sopenharmony_ci pci_disable_sriov(pdev); 372962306a36Sopenharmony_ci msleep(500); 373062306a36Sopenharmony_ci } 373162306a36Sopenharmony_ci spin_lock_irqsave(&adapter->vfs_lock, flags); 373262306a36Sopenharmony_ci kfree(adapter->vf_mac_list); 373362306a36Sopenharmony_ci adapter->vf_mac_list = NULL; 373462306a36Sopenharmony_ci kfree(adapter->vf_data); 373562306a36Sopenharmony_ci adapter->vf_data = NULL; 373662306a36Sopenharmony_ci adapter->vfs_allocated_count = 0; 373762306a36Sopenharmony_ci spin_unlock_irqrestore(&adapter->vfs_lock, flags); 373862306a36Sopenharmony_ci wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ); 373962306a36Sopenharmony_ci wrfl(); 374062306a36Sopenharmony_ci msleep(100); 374162306a36Sopenharmony_ci dev_info(&pdev->dev, "IOV Disabled\n"); 374262306a36Sopenharmony_ci 374362306a36Sopenharmony_ci /* Re-enable DMA Coalescing flag since IOV is turned off */ 374462306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_DMAC; 374562306a36Sopenharmony_ci } 374662306a36Sopenharmony_ci 374762306a36Sopenharmony_ci return reinit ? igb_sriov_reinit(pdev) : 0; 374862306a36Sopenharmony_ci} 374962306a36Sopenharmony_ci 375062306a36Sopenharmony_cistatic int igb_enable_sriov(struct pci_dev *pdev, int num_vfs, bool reinit) 375162306a36Sopenharmony_ci{ 375262306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 375362306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 375462306a36Sopenharmony_ci int old_vfs = pci_num_vf(pdev); 375562306a36Sopenharmony_ci struct vf_mac_filter *mac_list; 375662306a36Sopenharmony_ci int err = 0; 375762306a36Sopenharmony_ci int num_vf_mac_filters, i; 375862306a36Sopenharmony_ci 375962306a36Sopenharmony_ci if (!(adapter->flags & IGB_FLAG_HAS_MSIX) || num_vfs > 7) { 376062306a36Sopenharmony_ci err = -EPERM; 376162306a36Sopenharmony_ci goto out; 376262306a36Sopenharmony_ci } 376362306a36Sopenharmony_ci if (!num_vfs) 376462306a36Sopenharmony_ci goto out; 376562306a36Sopenharmony_ci 376662306a36Sopenharmony_ci if (old_vfs) { 376762306a36Sopenharmony_ci dev_info(&pdev->dev, "%d pre-allocated VFs found - override max_vfs setting of %d\n", 376862306a36Sopenharmony_ci old_vfs, max_vfs); 376962306a36Sopenharmony_ci adapter->vfs_allocated_count = old_vfs; 377062306a36Sopenharmony_ci } else 377162306a36Sopenharmony_ci adapter->vfs_allocated_count = num_vfs; 377262306a36Sopenharmony_ci 377362306a36Sopenharmony_ci adapter->vf_data = kcalloc(adapter->vfs_allocated_count, 377462306a36Sopenharmony_ci sizeof(struct vf_data_storage), GFP_KERNEL); 377562306a36Sopenharmony_ci 377662306a36Sopenharmony_ci /* if allocation failed then we do not support SR-IOV */ 377762306a36Sopenharmony_ci if (!adapter->vf_data) { 377862306a36Sopenharmony_ci adapter->vfs_allocated_count = 0; 377962306a36Sopenharmony_ci err = -ENOMEM; 378062306a36Sopenharmony_ci goto out; 378162306a36Sopenharmony_ci } 378262306a36Sopenharmony_ci 378362306a36Sopenharmony_ci /* Due to the limited number of RAR entries calculate potential 378462306a36Sopenharmony_ci * number of MAC filters available for the VFs. Reserve entries 378562306a36Sopenharmony_ci * for PF default MAC, PF MAC filters and at least one RAR entry 378662306a36Sopenharmony_ci * for each VF for VF MAC. 378762306a36Sopenharmony_ci */ 378862306a36Sopenharmony_ci num_vf_mac_filters = adapter->hw.mac.rar_entry_count - 378962306a36Sopenharmony_ci (1 + IGB_PF_MAC_FILTERS_RESERVED + 379062306a36Sopenharmony_ci adapter->vfs_allocated_count); 379162306a36Sopenharmony_ci 379262306a36Sopenharmony_ci adapter->vf_mac_list = kcalloc(num_vf_mac_filters, 379362306a36Sopenharmony_ci sizeof(struct vf_mac_filter), 379462306a36Sopenharmony_ci GFP_KERNEL); 379562306a36Sopenharmony_ci 379662306a36Sopenharmony_ci mac_list = adapter->vf_mac_list; 379762306a36Sopenharmony_ci INIT_LIST_HEAD(&adapter->vf_macs.l); 379862306a36Sopenharmony_ci 379962306a36Sopenharmony_ci if (adapter->vf_mac_list) { 380062306a36Sopenharmony_ci /* Initialize list of VF MAC filters */ 380162306a36Sopenharmony_ci for (i = 0; i < num_vf_mac_filters; i++) { 380262306a36Sopenharmony_ci mac_list->vf = -1; 380362306a36Sopenharmony_ci mac_list->free = true; 380462306a36Sopenharmony_ci list_add(&mac_list->l, &adapter->vf_macs.l); 380562306a36Sopenharmony_ci mac_list++; 380662306a36Sopenharmony_ci } 380762306a36Sopenharmony_ci } else { 380862306a36Sopenharmony_ci /* If we could not allocate memory for the VF MAC filters 380962306a36Sopenharmony_ci * we can continue without this feature but warn user. 381062306a36Sopenharmony_ci */ 381162306a36Sopenharmony_ci dev_err(&pdev->dev, 381262306a36Sopenharmony_ci "Unable to allocate memory for VF MAC filter list\n"); 381362306a36Sopenharmony_ci } 381462306a36Sopenharmony_ci 381562306a36Sopenharmony_ci dev_info(&pdev->dev, "%d VFs allocated\n", 381662306a36Sopenharmony_ci adapter->vfs_allocated_count); 381762306a36Sopenharmony_ci for (i = 0; i < adapter->vfs_allocated_count; i++) 381862306a36Sopenharmony_ci igb_vf_configure(adapter, i); 381962306a36Sopenharmony_ci 382062306a36Sopenharmony_ci /* DMA Coalescing is not supported in IOV mode. */ 382162306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_DMAC; 382262306a36Sopenharmony_ci 382362306a36Sopenharmony_ci if (reinit) { 382462306a36Sopenharmony_ci err = igb_sriov_reinit(pdev); 382562306a36Sopenharmony_ci if (err) 382662306a36Sopenharmony_ci goto err_out; 382762306a36Sopenharmony_ci } 382862306a36Sopenharmony_ci 382962306a36Sopenharmony_ci /* only call pci_enable_sriov() if no VFs are allocated already */ 383062306a36Sopenharmony_ci if (!old_vfs) { 383162306a36Sopenharmony_ci err = pci_enable_sriov(pdev, adapter->vfs_allocated_count); 383262306a36Sopenharmony_ci if (err) 383362306a36Sopenharmony_ci goto err_out; 383462306a36Sopenharmony_ci } 383562306a36Sopenharmony_ci 383662306a36Sopenharmony_ci goto out; 383762306a36Sopenharmony_ci 383862306a36Sopenharmony_cierr_out: 383962306a36Sopenharmony_ci kfree(adapter->vf_mac_list); 384062306a36Sopenharmony_ci adapter->vf_mac_list = NULL; 384162306a36Sopenharmony_ci kfree(adapter->vf_data); 384262306a36Sopenharmony_ci adapter->vf_data = NULL; 384362306a36Sopenharmony_ci adapter->vfs_allocated_count = 0; 384462306a36Sopenharmony_ciout: 384562306a36Sopenharmony_ci return err; 384662306a36Sopenharmony_ci} 384762306a36Sopenharmony_ci 384862306a36Sopenharmony_ci#endif 384962306a36Sopenharmony_ci/** 385062306a36Sopenharmony_ci * igb_remove_i2c - Cleanup I2C interface 385162306a36Sopenharmony_ci * @adapter: pointer to adapter structure 385262306a36Sopenharmony_ci **/ 385362306a36Sopenharmony_cistatic void igb_remove_i2c(struct igb_adapter *adapter) 385462306a36Sopenharmony_ci{ 385562306a36Sopenharmony_ci /* free the adapter bus structure */ 385662306a36Sopenharmony_ci i2c_del_adapter(&adapter->i2c_adap); 385762306a36Sopenharmony_ci} 385862306a36Sopenharmony_ci 385962306a36Sopenharmony_ci/** 386062306a36Sopenharmony_ci * igb_remove - Device Removal Routine 386162306a36Sopenharmony_ci * @pdev: PCI device information struct 386262306a36Sopenharmony_ci * 386362306a36Sopenharmony_ci * igb_remove is called by the PCI subsystem to alert the driver 386462306a36Sopenharmony_ci * that it should release a PCI device. The could be caused by a 386562306a36Sopenharmony_ci * Hot-Plug event, or because the driver is going to be removed from 386662306a36Sopenharmony_ci * memory. 386762306a36Sopenharmony_ci **/ 386862306a36Sopenharmony_cistatic void igb_remove(struct pci_dev *pdev) 386962306a36Sopenharmony_ci{ 387062306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 387162306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 387262306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 387362306a36Sopenharmony_ci 387462306a36Sopenharmony_ci pm_runtime_get_noresume(&pdev->dev); 387562306a36Sopenharmony_ci#ifdef CONFIG_IGB_HWMON 387662306a36Sopenharmony_ci igb_sysfs_exit(adapter); 387762306a36Sopenharmony_ci#endif 387862306a36Sopenharmony_ci igb_remove_i2c(adapter); 387962306a36Sopenharmony_ci igb_ptp_stop(adapter); 388062306a36Sopenharmony_ci /* The watchdog timer may be rescheduled, so explicitly 388162306a36Sopenharmony_ci * disable watchdog from being rescheduled. 388262306a36Sopenharmony_ci */ 388362306a36Sopenharmony_ci set_bit(__IGB_DOWN, &adapter->state); 388462306a36Sopenharmony_ci del_timer_sync(&adapter->watchdog_timer); 388562306a36Sopenharmony_ci del_timer_sync(&adapter->phy_info_timer); 388662306a36Sopenharmony_ci 388762306a36Sopenharmony_ci cancel_work_sync(&adapter->reset_task); 388862306a36Sopenharmony_ci cancel_work_sync(&adapter->watchdog_task); 388962306a36Sopenharmony_ci 389062306a36Sopenharmony_ci#ifdef CONFIG_IGB_DCA 389162306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_DCA_ENABLED) { 389262306a36Sopenharmony_ci dev_info(&pdev->dev, "DCA disabled\n"); 389362306a36Sopenharmony_ci dca_remove_requester(&pdev->dev); 389462306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_DCA_ENABLED; 389562306a36Sopenharmony_ci wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_DISABLE); 389662306a36Sopenharmony_ci } 389762306a36Sopenharmony_ci#endif 389862306a36Sopenharmony_ci 389962306a36Sopenharmony_ci /* Release control of h/w to f/w. If f/w is AMT enabled, this 390062306a36Sopenharmony_ci * would have already happened in close and is redundant. 390162306a36Sopenharmony_ci */ 390262306a36Sopenharmony_ci igb_release_hw_control(adapter); 390362306a36Sopenharmony_ci 390462306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 390562306a36Sopenharmony_ci igb_disable_sriov(pdev, false); 390662306a36Sopenharmony_ci#endif 390762306a36Sopenharmony_ci 390862306a36Sopenharmony_ci unregister_netdev(netdev); 390962306a36Sopenharmony_ci 391062306a36Sopenharmony_ci igb_clear_interrupt_scheme(adapter); 391162306a36Sopenharmony_ci 391262306a36Sopenharmony_ci pci_iounmap(pdev, adapter->io_addr); 391362306a36Sopenharmony_ci if (hw->flash_address) 391462306a36Sopenharmony_ci iounmap(hw->flash_address); 391562306a36Sopenharmony_ci pci_release_mem_regions(pdev); 391662306a36Sopenharmony_ci 391762306a36Sopenharmony_ci kfree(adapter->mac_table); 391862306a36Sopenharmony_ci kfree(adapter->shadow_vfta); 391962306a36Sopenharmony_ci free_netdev(netdev); 392062306a36Sopenharmony_ci 392162306a36Sopenharmony_ci pci_disable_device(pdev); 392262306a36Sopenharmony_ci} 392362306a36Sopenharmony_ci 392462306a36Sopenharmony_ci/** 392562306a36Sopenharmony_ci * igb_probe_vfs - Initialize vf data storage and add VFs to pci config space 392662306a36Sopenharmony_ci * @adapter: board private structure to initialize 392762306a36Sopenharmony_ci * 392862306a36Sopenharmony_ci * This function initializes the vf specific data storage and then attempts to 392962306a36Sopenharmony_ci * allocate the VFs. The reason for ordering it this way is because it is much 393062306a36Sopenharmony_ci * mor expensive time wise to disable SR-IOV than it is to allocate and free 393162306a36Sopenharmony_ci * the memory for the VFs. 393262306a36Sopenharmony_ci **/ 393362306a36Sopenharmony_cistatic void igb_probe_vfs(struct igb_adapter *adapter) 393462306a36Sopenharmony_ci{ 393562306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 393662306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 393762306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 393862306a36Sopenharmony_ci 393962306a36Sopenharmony_ci /* Virtualization features not supported on i210 and 82580 family. */ 394062306a36Sopenharmony_ci if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211) || 394162306a36Sopenharmony_ci (hw->mac.type == e1000_82580)) 394262306a36Sopenharmony_ci return; 394362306a36Sopenharmony_ci 394462306a36Sopenharmony_ci /* Of the below we really only want the effect of getting 394562306a36Sopenharmony_ci * IGB_FLAG_HAS_MSIX set (if available), without which 394662306a36Sopenharmony_ci * igb_enable_sriov() has no effect. 394762306a36Sopenharmony_ci */ 394862306a36Sopenharmony_ci igb_set_interrupt_capability(adapter, true); 394962306a36Sopenharmony_ci igb_reset_interrupt_capability(adapter); 395062306a36Sopenharmony_ci 395162306a36Sopenharmony_ci pci_sriov_set_totalvfs(pdev, 7); 395262306a36Sopenharmony_ci igb_enable_sriov(pdev, max_vfs, false); 395362306a36Sopenharmony_ci 395462306a36Sopenharmony_ci#endif /* CONFIG_PCI_IOV */ 395562306a36Sopenharmony_ci} 395662306a36Sopenharmony_ci 395762306a36Sopenharmony_ciunsigned int igb_get_max_rss_queues(struct igb_adapter *adapter) 395862306a36Sopenharmony_ci{ 395962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 396062306a36Sopenharmony_ci unsigned int max_rss_queues; 396162306a36Sopenharmony_ci 396262306a36Sopenharmony_ci /* Determine the maximum number of RSS queues supported. */ 396362306a36Sopenharmony_ci switch (hw->mac.type) { 396462306a36Sopenharmony_ci case e1000_i211: 396562306a36Sopenharmony_ci max_rss_queues = IGB_MAX_RX_QUEUES_I211; 396662306a36Sopenharmony_ci break; 396762306a36Sopenharmony_ci case e1000_82575: 396862306a36Sopenharmony_ci case e1000_i210: 396962306a36Sopenharmony_ci max_rss_queues = IGB_MAX_RX_QUEUES_82575; 397062306a36Sopenharmony_ci break; 397162306a36Sopenharmony_ci case e1000_i350: 397262306a36Sopenharmony_ci /* I350 cannot do RSS and SR-IOV at the same time */ 397362306a36Sopenharmony_ci if (!!adapter->vfs_allocated_count) { 397462306a36Sopenharmony_ci max_rss_queues = 1; 397562306a36Sopenharmony_ci break; 397662306a36Sopenharmony_ci } 397762306a36Sopenharmony_ci fallthrough; 397862306a36Sopenharmony_ci case e1000_82576: 397962306a36Sopenharmony_ci if (!!adapter->vfs_allocated_count) { 398062306a36Sopenharmony_ci max_rss_queues = 2; 398162306a36Sopenharmony_ci break; 398262306a36Sopenharmony_ci } 398362306a36Sopenharmony_ci fallthrough; 398462306a36Sopenharmony_ci case e1000_82580: 398562306a36Sopenharmony_ci case e1000_i354: 398662306a36Sopenharmony_ci default: 398762306a36Sopenharmony_ci max_rss_queues = IGB_MAX_RX_QUEUES; 398862306a36Sopenharmony_ci break; 398962306a36Sopenharmony_ci } 399062306a36Sopenharmony_ci 399162306a36Sopenharmony_ci return max_rss_queues; 399262306a36Sopenharmony_ci} 399362306a36Sopenharmony_ci 399462306a36Sopenharmony_cistatic void igb_init_queue_configuration(struct igb_adapter *adapter) 399562306a36Sopenharmony_ci{ 399662306a36Sopenharmony_ci u32 max_rss_queues; 399762306a36Sopenharmony_ci 399862306a36Sopenharmony_ci max_rss_queues = igb_get_max_rss_queues(adapter); 399962306a36Sopenharmony_ci adapter->rss_queues = min_t(u32, max_rss_queues, num_online_cpus()); 400062306a36Sopenharmony_ci 400162306a36Sopenharmony_ci igb_set_flag_queue_pairs(adapter, max_rss_queues); 400262306a36Sopenharmony_ci} 400362306a36Sopenharmony_ci 400462306a36Sopenharmony_civoid igb_set_flag_queue_pairs(struct igb_adapter *adapter, 400562306a36Sopenharmony_ci const u32 max_rss_queues) 400662306a36Sopenharmony_ci{ 400762306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 400862306a36Sopenharmony_ci 400962306a36Sopenharmony_ci /* Determine if we need to pair queues. */ 401062306a36Sopenharmony_ci switch (hw->mac.type) { 401162306a36Sopenharmony_ci case e1000_82575: 401262306a36Sopenharmony_ci case e1000_i211: 401362306a36Sopenharmony_ci /* Device supports enough interrupts without queue pairing. */ 401462306a36Sopenharmony_ci break; 401562306a36Sopenharmony_ci case e1000_82576: 401662306a36Sopenharmony_ci case e1000_82580: 401762306a36Sopenharmony_ci case e1000_i350: 401862306a36Sopenharmony_ci case e1000_i354: 401962306a36Sopenharmony_ci case e1000_i210: 402062306a36Sopenharmony_ci default: 402162306a36Sopenharmony_ci /* If rss_queues > half of max_rss_queues, pair the queues in 402262306a36Sopenharmony_ci * order to conserve interrupts due to limited supply. 402362306a36Sopenharmony_ci */ 402462306a36Sopenharmony_ci if (adapter->rss_queues > (max_rss_queues / 2)) 402562306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_QUEUE_PAIRS; 402662306a36Sopenharmony_ci else 402762306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_QUEUE_PAIRS; 402862306a36Sopenharmony_ci break; 402962306a36Sopenharmony_ci } 403062306a36Sopenharmony_ci} 403162306a36Sopenharmony_ci 403262306a36Sopenharmony_ci/** 403362306a36Sopenharmony_ci * igb_sw_init - Initialize general software structures (struct igb_adapter) 403462306a36Sopenharmony_ci * @adapter: board private structure to initialize 403562306a36Sopenharmony_ci * 403662306a36Sopenharmony_ci * igb_sw_init initializes the Adapter private data structure. 403762306a36Sopenharmony_ci * Fields are initialized based on PCI device information and 403862306a36Sopenharmony_ci * OS network device settings (MTU size). 403962306a36Sopenharmony_ci **/ 404062306a36Sopenharmony_cistatic int igb_sw_init(struct igb_adapter *adapter) 404162306a36Sopenharmony_ci{ 404262306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 404362306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 404462306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 404562306a36Sopenharmony_ci 404662306a36Sopenharmony_ci pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); 404762306a36Sopenharmony_ci 404862306a36Sopenharmony_ci /* set default ring sizes */ 404962306a36Sopenharmony_ci adapter->tx_ring_count = IGB_DEFAULT_TXD; 405062306a36Sopenharmony_ci adapter->rx_ring_count = IGB_DEFAULT_RXD; 405162306a36Sopenharmony_ci 405262306a36Sopenharmony_ci /* set default ITR values */ 405362306a36Sopenharmony_ci adapter->rx_itr_setting = IGB_DEFAULT_ITR; 405462306a36Sopenharmony_ci adapter->tx_itr_setting = IGB_DEFAULT_ITR; 405562306a36Sopenharmony_ci 405662306a36Sopenharmony_ci /* set default work limits */ 405762306a36Sopenharmony_ci adapter->tx_work_limit = IGB_DEFAULT_TX_WORK; 405862306a36Sopenharmony_ci 405962306a36Sopenharmony_ci adapter->max_frame_size = netdev->mtu + IGB_ETH_PKT_HDR_PAD; 406062306a36Sopenharmony_ci adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; 406162306a36Sopenharmony_ci 406262306a36Sopenharmony_ci spin_lock_init(&adapter->nfc_lock); 406362306a36Sopenharmony_ci spin_lock_init(&adapter->stats64_lock); 406462306a36Sopenharmony_ci 406562306a36Sopenharmony_ci /* init spinlock to avoid concurrency of VF resources */ 406662306a36Sopenharmony_ci spin_lock_init(&adapter->vfs_lock); 406762306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 406862306a36Sopenharmony_ci switch (hw->mac.type) { 406962306a36Sopenharmony_ci case e1000_82576: 407062306a36Sopenharmony_ci case e1000_i350: 407162306a36Sopenharmony_ci if (max_vfs > 7) { 407262306a36Sopenharmony_ci dev_warn(&pdev->dev, 407362306a36Sopenharmony_ci "Maximum of 7 VFs per PF, using max\n"); 407462306a36Sopenharmony_ci max_vfs = adapter->vfs_allocated_count = 7; 407562306a36Sopenharmony_ci } else 407662306a36Sopenharmony_ci adapter->vfs_allocated_count = max_vfs; 407762306a36Sopenharmony_ci if (adapter->vfs_allocated_count) 407862306a36Sopenharmony_ci dev_warn(&pdev->dev, 407962306a36Sopenharmony_ci "Enabling SR-IOV VFs using the module parameter is deprecated - please use the pci sysfs interface.\n"); 408062306a36Sopenharmony_ci break; 408162306a36Sopenharmony_ci default: 408262306a36Sopenharmony_ci break; 408362306a36Sopenharmony_ci } 408462306a36Sopenharmony_ci#endif /* CONFIG_PCI_IOV */ 408562306a36Sopenharmony_ci 408662306a36Sopenharmony_ci /* Assume MSI-X interrupts, will be checked during IRQ allocation */ 408762306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_HAS_MSIX; 408862306a36Sopenharmony_ci 408962306a36Sopenharmony_ci adapter->mac_table = kcalloc(hw->mac.rar_entry_count, 409062306a36Sopenharmony_ci sizeof(struct igb_mac_addr), 409162306a36Sopenharmony_ci GFP_KERNEL); 409262306a36Sopenharmony_ci if (!adapter->mac_table) 409362306a36Sopenharmony_ci return -ENOMEM; 409462306a36Sopenharmony_ci 409562306a36Sopenharmony_ci igb_probe_vfs(adapter); 409662306a36Sopenharmony_ci 409762306a36Sopenharmony_ci igb_init_queue_configuration(adapter); 409862306a36Sopenharmony_ci 409962306a36Sopenharmony_ci /* Setup and initialize a copy of the hw vlan table array */ 410062306a36Sopenharmony_ci adapter->shadow_vfta = kcalloc(E1000_VLAN_FILTER_TBL_SIZE, sizeof(u32), 410162306a36Sopenharmony_ci GFP_KERNEL); 410262306a36Sopenharmony_ci if (!adapter->shadow_vfta) 410362306a36Sopenharmony_ci return -ENOMEM; 410462306a36Sopenharmony_ci 410562306a36Sopenharmony_ci /* This call may decrease the number of queues */ 410662306a36Sopenharmony_ci if (igb_init_interrupt_scheme(adapter, true)) { 410762306a36Sopenharmony_ci dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); 410862306a36Sopenharmony_ci return -ENOMEM; 410962306a36Sopenharmony_ci } 411062306a36Sopenharmony_ci 411162306a36Sopenharmony_ci /* Explicitly disable IRQ since the NIC can be in any state. */ 411262306a36Sopenharmony_ci igb_irq_disable(adapter); 411362306a36Sopenharmony_ci 411462306a36Sopenharmony_ci if (hw->mac.type >= e1000_i350) 411562306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_DMAC; 411662306a36Sopenharmony_ci 411762306a36Sopenharmony_ci set_bit(__IGB_DOWN, &adapter->state); 411862306a36Sopenharmony_ci return 0; 411962306a36Sopenharmony_ci} 412062306a36Sopenharmony_ci 412162306a36Sopenharmony_ci/** 412262306a36Sopenharmony_ci * __igb_open - Called when a network interface is made active 412362306a36Sopenharmony_ci * @netdev: network interface device structure 412462306a36Sopenharmony_ci * @resuming: indicates whether we are in a resume call 412562306a36Sopenharmony_ci * 412662306a36Sopenharmony_ci * Returns 0 on success, negative value on failure 412762306a36Sopenharmony_ci * 412862306a36Sopenharmony_ci * The open entry point is called when a network interface is made 412962306a36Sopenharmony_ci * active by the system (IFF_UP). At this point all resources needed 413062306a36Sopenharmony_ci * for transmit and receive operations are allocated, the interrupt 413162306a36Sopenharmony_ci * handler is registered with the OS, the watchdog timer is started, 413262306a36Sopenharmony_ci * and the stack is notified that the interface is ready. 413362306a36Sopenharmony_ci **/ 413462306a36Sopenharmony_cistatic int __igb_open(struct net_device *netdev, bool resuming) 413562306a36Sopenharmony_ci{ 413662306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 413762306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 413862306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 413962306a36Sopenharmony_ci int err; 414062306a36Sopenharmony_ci int i; 414162306a36Sopenharmony_ci 414262306a36Sopenharmony_ci /* disallow open during test */ 414362306a36Sopenharmony_ci if (test_bit(__IGB_TESTING, &adapter->state)) { 414462306a36Sopenharmony_ci WARN_ON(resuming); 414562306a36Sopenharmony_ci return -EBUSY; 414662306a36Sopenharmony_ci } 414762306a36Sopenharmony_ci 414862306a36Sopenharmony_ci if (!resuming) 414962306a36Sopenharmony_ci pm_runtime_get_sync(&pdev->dev); 415062306a36Sopenharmony_ci 415162306a36Sopenharmony_ci netif_carrier_off(netdev); 415262306a36Sopenharmony_ci 415362306a36Sopenharmony_ci /* allocate transmit descriptors */ 415462306a36Sopenharmony_ci err = igb_setup_all_tx_resources(adapter); 415562306a36Sopenharmony_ci if (err) 415662306a36Sopenharmony_ci goto err_setup_tx; 415762306a36Sopenharmony_ci 415862306a36Sopenharmony_ci /* allocate receive descriptors */ 415962306a36Sopenharmony_ci err = igb_setup_all_rx_resources(adapter); 416062306a36Sopenharmony_ci if (err) 416162306a36Sopenharmony_ci goto err_setup_rx; 416262306a36Sopenharmony_ci 416362306a36Sopenharmony_ci igb_power_up_link(adapter); 416462306a36Sopenharmony_ci 416562306a36Sopenharmony_ci /* before we allocate an interrupt, we must be ready to handle it. 416662306a36Sopenharmony_ci * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt 416762306a36Sopenharmony_ci * as soon as we call pci_request_irq, so we have to setup our 416862306a36Sopenharmony_ci * clean_rx handler before we do so. 416962306a36Sopenharmony_ci */ 417062306a36Sopenharmony_ci igb_configure(adapter); 417162306a36Sopenharmony_ci 417262306a36Sopenharmony_ci err = igb_request_irq(adapter); 417362306a36Sopenharmony_ci if (err) 417462306a36Sopenharmony_ci goto err_req_irq; 417562306a36Sopenharmony_ci 417662306a36Sopenharmony_ci /* Notify the stack of the actual queue counts. */ 417762306a36Sopenharmony_ci err = netif_set_real_num_tx_queues(adapter->netdev, 417862306a36Sopenharmony_ci adapter->num_tx_queues); 417962306a36Sopenharmony_ci if (err) 418062306a36Sopenharmony_ci goto err_set_queues; 418162306a36Sopenharmony_ci 418262306a36Sopenharmony_ci err = netif_set_real_num_rx_queues(adapter->netdev, 418362306a36Sopenharmony_ci adapter->num_rx_queues); 418462306a36Sopenharmony_ci if (err) 418562306a36Sopenharmony_ci goto err_set_queues; 418662306a36Sopenharmony_ci 418762306a36Sopenharmony_ci /* From here on the code is the same as igb_up() */ 418862306a36Sopenharmony_ci clear_bit(__IGB_DOWN, &adapter->state); 418962306a36Sopenharmony_ci 419062306a36Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) 419162306a36Sopenharmony_ci napi_enable(&(adapter->q_vector[i]->napi)); 419262306a36Sopenharmony_ci 419362306a36Sopenharmony_ci /* Clear any pending interrupts. */ 419462306a36Sopenharmony_ci rd32(E1000_TSICR); 419562306a36Sopenharmony_ci rd32(E1000_ICR); 419662306a36Sopenharmony_ci 419762306a36Sopenharmony_ci igb_irq_enable(adapter); 419862306a36Sopenharmony_ci 419962306a36Sopenharmony_ci /* notify VFs that reset has been completed */ 420062306a36Sopenharmony_ci if (adapter->vfs_allocated_count) { 420162306a36Sopenharmony_ci u32 reg_data = rd32(E1000_CTRL_EXT); 420262306a36Sopenharmony_ci 420362306a36Sopenharmony_ci reg_data |= E1000_CTRL_EXT_PFRSTD; 420462306a36Sopenharmony_ci wr32(E1000_CTRL_EXT, reg_data); 420562306a36Sopenharmony_ci } 420662306a36Sopenharmony_ci 420762306a36Sopenharmony_ci netif_tx_start_all_queues(netdev); 420862306a36Sopenharmony_ci 420962306a36Sopenharmony_ci if (!resuming) 421062306a36Sopenharmony_ci pm_runtime_put(&pdev->dev); 421162306a36Sopenharmony_ci 421262306a36Sopenharmony_ci /* start the watchdog. */ 421362306a36Sopenharmony_ci hw->mac.get_link_status = 1; 421462306a36Sopenharmony_ci schedule_work(&adapter->watchdog_task); 421562306a36Sopenharmony_ci 421662306a36Sopenharmony_ci return 0; 421762306a36Sopenharmony_ci 421862306a36Sopenharmony_cierr_set_queues: 421962306a36Sopenharmony_ci igb_free_irq(adapter); 422062306a36Sopenharmony_cierr_req_irq: 422162306a36Sopenharmony_ci igb_release_hw_control(adapter); 422262306a36Sopenharmony_ci igb_power_down_link(adapter); 422362306a36Sopenharmony_ci igb_free_all_rx_resources(adapter); 422462306a36Sopenharmony_cierr_setup_rx: 422562306a36Sopenharmony_ci igb_free_all_tx_resources(adapter); 422662306a36Sopenharmony_cierr_setup_tx: 422762306a36Sopenharmony_ci igb_reset(adapter); 422862306a36Sopenharmony_ci if (!resuming) 422962306a36Sopenharmony_ci pm_runtime_put(&pdev->dev); 423062306a36Sopenharmony_ci 423162306a36Sopenharmony_ci return err; 423262306a36Sopenharmony_ci} 423362306a36Sopenharmony_ci 423462306a36Sopenharmony_ciint igb_open(struct net_device *netdev) 423562306a36Sopenharmony_ci{ 423662306a36Sopenharmony_ci return __igb_open(netdev, false); 423762306a36Sopenharmony_ci} 423862306a36Sopenharmony_ci 423962306a36Sopenharmony_ci/** 424062306a36Sopenharmony_ci * __igb_close - Disables a network interface 424162306a36Sopenharmony_ci * @netdev: network interface device structure 424262306a36Sopenharmony_ci * @suspending: indicates we are in a suspend call 424362306a36Sopenharmony_ci * 424462306a36Sopenharmony_ci * Returns 0, this is not allowed to fail 424562306a36Sopenharmony_ci * 424662306a36Sopenharmony_ci * The close entry point is called when an interface is de-activated 424762306a36Sopenharmony_ci * by the OS. The hardware is still under the driver's control, but 424862306a36Sopenharmony_ci * needs to be disabled. A global MAC reset is issued to stop the 424962306a36Sopenharmony_ci * hardware, and all transmit and receive resources are freed. 425062306a36Sopenharmony_ci **/ 425162306a36Sopenharmony_cistatic int __igb_close(struct net_device *netdev, bool suspending) 425262306a36Sopenharmony_ci{ 425362306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 425462306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 425562306a36Sopenharmony_ci 425662306a36Sopenharmony_ci WARN_ON(test_bit(__IGB_RESETTING, &adapter->state)); 425762306a36Sopenharmony_ci 425862306a36Sopenharmony_ci if (!suspending) 425962306a36Sopenharmony_ci pm_runtime_get_sync(&pdev->dev); 426062306a36Sopenharmony_ci 426162306a36Sopenharmony_ci igb_down(adapter); 426262306a36Sopenharmony_ci igb_free_irq(adapter); 426362306a36Sopenharmony_ci 426462306a36Sopenharmony_ci igb_free_all_tx_resources(adapter); 426562306a36Sopenharmony_ci igb_free_all_rx_resources(adapter); 426662306a36Sopenharmony_ci 426762306a36Sopenharmony_ci if (!suspending) 426862306a36Sopenharmony_ci pm_runtime_put_sync(&pdev->dev); 426962306a36Sopenharmony_ci return 0; 427062306a36Sopenharmony_ci} 427162306a36Sopenharmony_ci 427262306a36Sopenharmony_ciint igb_close(struct net_device *netdev) 427362306a36Sopenharmony_ci{ 427462306a36Sopenharmony_ci if (netif_device_present(netdev) || netdev->dismantle) 427562306a36Sopenharmony_ci return __igb_close(netdev, false); 427662306a36Sopenharmony_ci return 0; 427762306a36Sopenharmony_ci} 427862306a36Sopenharmony_ci 427962306a36Sopenharmony_ci/** 428062306a36Sopenharmony_ci * igb_setup_tx_resources - allocate Tx resources (Descriptors) 428162306a36Sopenharmony_ci * @tx_ring: tx descriptor ring (for a specific queue) to setup 428262306a36Sopenharmony_ci * 428362306a36Sopenharmony_ci * Return 0 on success, negative on failure 428462306a36Sopenharmony_ci **/ 428562306a36Sopenharmony_ciint igb_setup_tx_resources(struct igb_ring *tx_ring) 428662306a36Sopenharmony_ci{ 428762306a36Sopenharmony_ci struct device *dev = tx_ring->dev; 428862306a36Sopenharmony_ci int size; 428962306a36Sopenharmony_ci 429062306a36Sopenharmony_ci size = sizeof(struct igb_tx_buffer) * tx_ring->count; 429162306a36Sopenharmony_ci 429262306a36Sopenharmony_ci tx_ring->tx_buffer_info = vmalloc(size); 429362306a36Sopenharmony_ci if (!tx_ring->tx_buffer_info) 429462306a36Sopenharmony_ci goto err; 429562306a36Sopenharmony_ci 429662306a36Sopenharmony_ci /* round up to nearest 4K */ 429762306a36Sopenharmony_ci tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc); 429862306a36Sopenharmony_ci tx_ring->size = ALIGN(tx_ring->size, 4096); 429962306a36Sopenharmony_ci 430062306a36Sopenharmony_ci tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size, 430162306a36Sopenharmony_ci &tx_ring->dma, GFP_KERNEL); 430262306a36Sopenharmony_ci if (!tx_ring->desc) 430362306a36Sopenharmony_ci goto err; 430462306a36Sopenharmony_ci 430562306a36Sopenharmony_ci tx_ring->next_to_use = 0; 430662306a36Sopenharmony_ci tx_ring->next_to_clean = 0; 430762306a36Sopenharmony_ci 430862306a36Sopenharmony_ci return 0; 430962306a36Sopenharmony_ci 431062306a36Sopenharmony_cierr: 431162306a36Sopenharmony_ci vfree(tx_ring->tx_buffer_info); 431262306a36Sopenharmony_ci tx_ring->tx_buffer_info = NULL; 431362306a36Sopenharmony_ci dev_err(dev, "Unable to allocate memory for the Tx descriptor ring\n"); 431462306a36Sopenharmony_ci return -ENOMEM; 431562306a36Sopenharmony_ci} 431662306a36Sopenharmony_ci 431762306a36Sopenharmony_ci/** 431862306a36Sopenharmony_ci * igb_setup_all_tx_resources - wrapper to allocate Tx resources 431962306a36Sopenharmony_ci * (Descriptors) for all queues 432062306a36Sopenharmony_ci * @adapter: board private structure 432162306a36Sopenharmony_ci * 432262306a36Sopenharmony_ci * Return 0 on success, negative on failure 432362306a36Sopenharmony_ci **/ 432462306a36Sopenharmony_cistatic int igb_setup_all_tx_resources(struct igb_adapter *adapter) 432562306a36Sopenharmony_ci{ 432662306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 432762306a36Sopenharmony_ci int i, err = 0; 432862306a36Sopenharmony_ci 432962306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 433062306a36Sopenharmony_ci err = igb_setup_tx_resources(adapter->tx_ring[i]); 433162306a36Sopenharmony_ci if (err) { 433262306a36Sopenharmony_ci dev_err(&pdev->dev, 433362306a36Sopenharmony_ci "Allocation for Tx Queue %u failed\n", i); 433462306a36Sopenharmony_ci for (i--; i >= 0; i--) 433562306a36Sopenharmony_ci igb_free_tx_resources(adapter->tx_ring[i]); 433662306a36Sopenharmony_ci break; 433762306a36Sopenharmony_ci } 433862306a36Sopenharmony_ci } 433962306a36Sopenharmony_ci 434062306a36Sopenharmony_ci return err; 434162306a36Sopenharmony_ci} 434262306a36Sopenharmony_ci 434362306a36Sopenharmony_ci/** 434462306a36Sopenharmony_ci * igb_setup_tctl - configure the transmit control registers 434562306a36Sopenharmony_ci * @adapter: Board private structure 434662306a36Sopenharmony_ci **/ 434762306a36Sopenharmony_civoid igb_setup_tctl(struct igb_adapter *adapter) 434862306a36Sopenharmony_ci{ 434962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 435062306a36Sopenharmony_ci u32 tctl; 435162306a36Sopenharmony_ci 435262306a36Sopenharmony_ci /* disable queue 0 which is enabled by default on 82575 and 82576 */ 435362306a36Sopenharmony_ci wr32(E1000_TXDCTL(0), 0); 435462306a36Sopenharmony_ci 435562306a36Sopenharmony_ci /* Program the Transmit Control Register */ 435662306a36Sopenharmony_ci tctl = rd32(E1000_TCTL); 435762306a36Sopenharmony_ci tctl &= ~E1000_TCTL_CT; 435862306a36Sopenharmony_ci tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | 435962306a36Sopenharmony_ci (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); 436062306a36Sopenharmony_ci 436162306a36Sopenharmony_ci igb_config_collision_dist(hw); 436262306a36Sopenharmony_ci 436362306a36Sopenharmony_ci /* Enable transmits */ 436462306a36Sopenharmony_ci tctl |= E1000_TCTL_EN; 436562306a36Sopenharmony_ci 436662306a36Sopenharmony_ci wr32(E1000_TCTL, tctl); 436762306a36Sopenharmony_ci} 436862306a36Sopenharmony_ci 436962306a36Sopenharmony_ci/** 437062306a36Sopenharmony_ci * igb_configure_tx_ring - Configure transmit ring after Reset 437162306a36Sopenharmony_ci * @adapter: board private structure 437262306a36Sopenharmony_ci * @ring: tx ring to configure 437362306a36Sopenharmony_ci * 437462306a36Sopenharmony_ci * Configure a transmit ring after a reset. 437562306a36Sopenharmony_ci **/ 437662306a36Sopenharmony_civoid igb_configure_tx_ring(struct igb_adapter *adapter, 437762306a36Sopenharmony_ci struct igb_ring *ring) 437862306a36Sopenharmony_ci{ 437962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 438062306a36Sopenharmony_ci u32 txdctl = 0; 438162306a36Sopenharmony_ci u64 tdba = ring->dma; 438262306a36Sopenharmony_ci int reg_idx = ring->reg_idx; 438362306a36Sopenharmony_ci 438462306a36Sopenharmony_ci wr32(E1000_TDLEN(reg_idx), 438562306a36Sopenharmony_ci ring->count * sizeof(union e1000_adv_tx_desc)); 438662306a36Sopenharmony_ci wr32(E1000_TDBAL(reg_idx), 438762306a36Sopenharmony_ci tdba & 0x00000000ffffffffULL); 438862306a36Sopenharmony_ci wr32(E1000_TDBAH(reg_idx), tdba >> 32); 438962306a36Sopenharmony_ci 439062306a36Sopenharmony_ci ring->tail = adapter->io_addr + E1000_TDT(reg_idx); 439162306a36Sopenharmony_ci wr32(E1000_TDH(reg_idx), 0); 439262306a36Sopenharmony_ci writel(0, ring->tail); 439362306a36Sopenharmony_ci 439462306a36Sopenharmony_ci txdctl |= IGB_TX_PTHRESH; 439562306a36Sopenharmony_ci txdctl |= IGB_TX_HTHRESH << 8; 439662306a36Sopenharmony_ci txdctl |= IGB_TX_WTHRESH << 16; 439762306a36Sopenharmony_ci 439862306a36Sopenharmony_ci /* reinitialize tx_buffer_info */ 439962306a36Sopenharmony_ci memset(ring->tx_buffer_info, 0, 440062306a36Sopenharmony_ci sizeof(struct igb_tx_buffer) * ring->count); 440162306a36Sopenharmony_ci 440262306a36Sopenharmony_ci txdctl |= E1000_TXDCTL_QUEUE_ENABLE; 440362306a36Sopenharmony_ci wr32(E1000_TXDCTL(reg_idx), txdctl); 440462306a36Sopenharmony_ci} 440562306a36Sopenharmony_ci 440662306a36Sopenharmony_ci/** 440762306a36Sopenharmony_ci * igb_configure_tx - Configure transmit Unit after Reset 440862306a36Sopenharmony_ci * @adapter: board private structure 440962306a36Sopenharmony_ci * 441062306a36Sopenharmony_ci * Configure the Tx unit of the MAC after a reset. 441162306a36Sopenharmony_ci **/ 441262306a36Sopenharmony_cistatic void igb_configure_tx(struct igb_adapter *adapter) 441362306a36Sopenharmony_ci{ 441462306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 441562306a36Sopenharmony_ci int i; 441662306a36Sopenharmony_ci 441762306a36Sopenharmony_ci /* disable the queues */ 441862306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 441962306a36Sopenharmony_ci wr32(E1000_TXDCTL(adapter->tx_ring[i]->reg_idx), 0); 442062306a36Sopenharmony_ci 442162306a36Sopenharmony_ci wrfl(); 442262306a36Sopenharmony_ci usleep_range(10000, 20000); 442362306a36Sopenharmony_ci 442462306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 442562306a36Sopenharmony_ci igb_configure_tx_ring(adapter, adapter->tx_ring[i]); 442662306a36Sopenharmony_ci} 442762306a36Sopenharmony_ci 442862306a36Sopenharmony_ci/** 442962306a36Sopenharmony_ci * igb_setup_rx_resources - allocate Rx resources (Descriptors) 443062306a36Sopenharmony_ci * @rx_ring: Rx descriptor ring (for a specific queue) to setup 443162306a36Sopenharmony_ci * 443262306a36Sopenharmony_ci * Returns 0 on success, negative on failure 443362306a36Sopenharmony_ci **/ 443462306a36Sopenharmony_ciint igb_setup_rx_resources(struct igb_ring *rx_ring) 443562306a36Sopenharmony_ci{ 443662306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(rx_ring->netdev); 443762306a36Sopenharmony_ci struct device *dev = rx_ring->dev; 443862306a36Sopenharmony_ci int size, res; 443962306a36Sopenharmony_ci 444062306a36Sopenharmony_ci /* XDP RX-queue info */ 444162306a36Sopenharmony_ci if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq)) 444262306a36Sopenharmony_ci xdp_rxq_info_unreg(&rx_ring->xdp_rxq); 444362306a36Sopenharmony_ci res = xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev, 444462306a36Sopenharmony_ci rx_ring->queue_index, 0); 444562306a36Sopenharmony_ci if (res < 0) { 444662306a36Sopenharmony_ci dev_err(dev, "Failed to register xdp_rxq index %u\n", 444762306a36Sopenharmony_ci rx_ring->queue_index); 444862306a36Sopenharmony_ci return res; 444962306a36Sopenharmony_ci } 445062306a36Sopenharmony_ci 445162306a36Sopenharmony_ci size = sizeof(struct igb_rx_buffer) * rx_ring->count; 445262306a36Sopenharmony_ci 445362306a36Sopenharmony_ci rx_ring->rx_buffer_info = vmalloc(size); 445462306a36Sopenharmony_ci if (!rx_ring->rx_buffer_info) 445562306a36Sopenharmony_ci goto err; 445662306a36Sopenharmony_ci 445762306a36Sopenharmony_ci /* Round up to nearest 4K */ 445862306a36Sopenharmony_ci rx_ring->size = rx_ring->count * sizeof(union e1000_adv_rx_desc); 445962306a36Sopenharmony_ci rx_ring->size = ALIGN(rx_ring->size, 4096); 446062306a36Sopenharmony_ci 446162306a36Sopenharmony_ci rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size, 446262306a36Sopenharmony_ci &rx_ring->dma, GFP_KERNEL); 446362306a36Sopenharmony_ci if (!rx_ring->desc) 446462306a36Sopenharmony_ci goto err; 446562306a36Sopenharmony_ci 446662306a36Sopenharmony_ci rx_ring->next_to_alloc = 0; 446762306a36Sopenharmony_ci rx_ring->next_to_clean = 0; 446862306a36Sopenharmony_ci rx_ring->next_to_use = 0; 446962306a36Sopenharmony_ci 447062306a36Sopenharmony_ci rx_ring->xdp_prog = adapter->xdp_prog; 447162306a36Sopenharmony_ci 447262306a36Sopenharmony_ci return 0; 447362306a36Sopenharmony_ci 447462306a36Sopenharmony_cierr: 447562306a36Sopenharmony_ci xdp_rxq_info_unreg(&rx_ring->xdp_rxq); 447662306a36Sopenharmony_ci vfree(rx_ring->rx_buffer_info); 447762306a36Sopenharmony_ci rx_ring->rx_buffer_info = NULL; 447862306a36Sopenharmony_ci dev_err(dev, "Unable to allocate memory for the Rx descriptor ring\n"); 447962306a36Sopenharmony_ci return -ENOMEM; 448062306a36Sopenharmony_ci} 448162306a36Sopenharmony_ci 448262306a36Sopenharmony_ci/** 448362306a36Sopenharmony_ci * igb_setup_all_rx_resources - wrapper to allocate Rx resources 448462306a36Sopenharmony_ci * (Descriptors) for all queues 448562306a36Sopenharmony_ci * @adapter: board private structure 448662306a36Sopenharmony_ci * 448762306a36Sopenharmony_ci * Return 0 on success, negative on failure 448862306a36Sopenharmony_ci **/ 448962306a36Sopenharmony_cistatic int igb_setup_all_rx_resources(struct igb_adapter *adapter) 449062306a36Sopenharmony_ci{ 449162306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 449262306a36Sopenharmony_ci int i, err = 0; 449362306a36Sopenharmony_ci 449462306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 449562306a36Sopenharmony_ci err = igb_setup_rx_resources(adapter->rx_ring[i]); 449662306a36Sopenharmony_ci if (err) { 449762306a36Sopenharmony_ci dev_err(&pdev->dev, 449862306a36Sopenharmony_ci "Allocation for Rx Queue %u failed\n", i); 449962306a36Sopenharmony_ci for (i--; i >= 0; i--) 450062306a36Sopenharmony_ci igb_free_rx_resources(adapter->rx_ring[i]); 450162306a36Sopenharmony_ci break; 450262306a36Sopenharmony_ci } 450362306a36Sopenharmony_ci } 450462306a36Sopenharmony_ci 450562306a36Sopenharmony_ci return err; 450662306a36Sopenharmony_ci} 450762306a36Sopenharmony_ci 450862306a36Sopenharmony_ci/** 450962306a36Sopenharmony_ci * igb_setup_mrqc - configure the multiple receive queue control registers 451062306a36Sopenharmony_ci * @adapter: Board private structure 451162306a36Sopenharmony_ci **/ 451262306a36Sopenharmony_cistatic void igb_setup_mrqc(struct igb_adapter *adapter) 451362306a36Sopenharmony_ci{ 451462306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 451562306a36Sopenharmony_ci u32 mrqc, rxcsum; 451662306a36Sopenharmony_ci u32 j, num_rx_queues; 451762306a36Sopenharmony_ci u32 rss_key[10]; 451862306a36Sopenharmony_ci 451962306a36Sopenharmony_ci netdev_rss_key_fill(rss_key, sizeof(rss_key)); 452062306a36Sopenharmony_ci for (j = 0; j < 10; j++) 452162306a36Sopenharmony_ci wr32(E1000_RSSRK(j), rss_key[j]); 452262306a36Sopenharmony_ci 452362306a36Sopenharmony_ci num_rx_queues = adapter->rss_queues; 452462306a36Sopenharmony_ci 452562306a36Sopenharmony_ci switch (hw->mac.type) { 452662306a36Sopenharmony_ci case e1000_82576: 452762306a36Sopenharmony_ci /* 82576 supports 2 RSS queues for SR-IOV */ 452862306a36Sopenharmony_ci if (adapter->vfs_allocated_count) 452962306a36Sopenharmony_ci num_rx_queues = 2; 453062306a36Sopenharmony_ci break; 453162306a36Sopenharmony_ci default: 453262306a36Sopenharmony_ci break; 453362306a36Sopenharmony_ci } 453462306a36Sopenharmony_ci 453562306a36Sopenharmony_ci if (adapter->rss_indir_tbl_init != num_rx_queues) { 453662306a36Sopenharmony_ci for (j = 0; j < IGB_RETA_SIZE; j++) 453762306a36Sopenharmony_ci adapter->rss_indir_tbl[j] = 453862306a36Sopenharmony_ci (j * num_rx_queues) / IGB_RETA_SIZE; 453962306a36Sopenharmony_ci adapter->rss_indir_tbl_init = num_rx_queues; 454062306a36Sopenharmony_ci } 454162306a36Sopenharmony_ci igb_write_rss_indir_tbl(adapter); 454262306a36Sopenharmony_ci 454362306a36Sopenharmony_ci /* Disable raw packet checksumming so that RSS hash is placed in 454462306a36Sopenharmony_ci * descriptor on writeback. No need to enable TCP/UDP/IP checksum 454562306a36Sopenharmony_ci * offloads as they are enabled by default 454662306a36Sopenharmony_ci */ 454762306a36Sopenharmony_ci rxcsum = rd32(E1000_RXCSUM); 454862306a36Sopenharmony_ci rxcsum |= E1000_RXCSUM_PCSD; 454962306a36Sopenharmony_ci 455062306a36Sopenharmony_ci if (adapter->hw.mac.type >= e1000_82576) 455162306a36Sopenharmony_ci /* Enable Receive Checksum Offload for SCTP */ 455262306a36Sopenharmony_ci rxcsum |= E1000_RXCSUM_CRCOFL; 455362306a36Sopenharmony_ci 455462306a36Sopenharmony_ci /* Don't need to set TUOFL or IPOFL, they default to 1 */ 455562306a36Sopenharmony_ci wr32(E1000_RXCSUM, rxcsum); 455662306a36Sopenharmony_ci 455762306a36Sopenharmony_ci /* Generate RSS hash based on packet types, TCP/UDP 455862306a36Sopenharmony_ci * port numbers and/or IPv4/v6 src and dst addresses 455962306a36Sopenharmony_ci */ 456062306a36Sopenharmony_ci mrqc = E1000_MRQC_RSS_FIELD_IPV4 | 456162306a36Sopenharmony_ci E1000_MRQC_RSS_FIELD_IPV4_TCP | 456262306a36Sopenharmony_ci E1000_MRQC_RSS_FIELD_IPV6 | 456362306a36Sopenharmony_ci E1000_MRQC_RSS_FIELD_IPV6_TCP | 456462306a36Sopenharmony_ci E1000_MRQC_RSS_FIELD_IPV6_TCP_EX; 456562306a36Sopenharmony_ci 456662306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP) 456762306a36Sopenharmony_ci mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP; 456862306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP) 456962306a36Sopenharmony_ci mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP; 457062306a36Sopenharmony_ci 457162306a36Sopenharmony_ci /* If VMDq is enabled then we set the appropriate mode for that, else 457262306a36Sopenharmony_ci * we default to RSS so that an RSS hash is calculated per packet even 457362306a36Sopenharmony_ci * if we are only using one queue 457462306a36Sopenharmony_ci */ 457562306a36Sopenharmony_ci if (adapter->vfs_allocated_count) { 457662306a36Sopenharmony_ci if (hw->mac.type > e1000_82575) { 457762306a36Sopenharmony_ci /* Set the default pool for the PF's first queue */ 457862306a36Sopenharmony_ci u32 vtctl = rd32(E1000_VT_CTL); 457962306a36Sopenharmony_ci 458062306a36Sopenharmony_ci vtctl &= ~(E1000_VT_CTL_DEFAULT_POOL_MASK | 458162306a36Sopenharmony_ci E1000_VT_CTL_DISABLE_DEF_POOL); 458262306a36Sopenharmony_ci vtctl |= adapter->vfs_allocated_count << 458362306a36Sopenharmony_ci E1000_VT_CTL_DEFAULT_POOL_SHIFT; 458462306a36Sopenharmony_ci wr32(E1000_VT_CTL, vtctl); 458562306a36Sopenharmony_ci } 458662306a36Sopenharmony_ci if (adapter->rss_queues > 1) 458762306a36Sopenharmony_ci mrqc |= E1000_MRQC_ENABLE_VMDQ_RSS_MQ; 458862306a36Sopenharmony_ci else 458962306a36Sopenharmony_ci mrqc |= E1000_MRQC_ENABLE_VMDQ; 459062306a36Sopenharmony_ci } else { 459162306a36Sopenharmony_ci mrqc |= E1000_MRQC_ENABLE_RSS_MQ; 459262306a36Sopenharmony_ci } 459362306a36Sopenharmony_ci igb_vmm_control(adapter); 459462306a36Sopenharmony_ci 459562306a36Sopenharmony_ci wr32(E1000_MRQC, mrqc); 459662306a36Sopenharmony_ci} 459762306a36Sopenharmony_ci 459862306a36Sopenharmony_ci/** 459962306a36Sopenharmony_ci * igb_setup_rctl - configure the receive control registers 460062306a36Sopenharmony_ci * @adapter: Board private structure 460162306a36Sopenharmony_ci **/ 460262306a36Sopenharmony_civoid igb_setup_rctl(struct igb_adapter *adapter) 460362306a36Sopenharmony_ci{ 460462306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 460562306a36Sopenharmony_ci u32 rctl; 460662306a36Sopenharmony_ci 460762306a36Sopenharmony_ci rctl = rd32(E1000_RCTL); 460862306a36Sopenharmony_ci 460962306a36Sopenharmony_ci rctl &= ~(3 << E1000_RCTL_MO_SHIFT); 461062306a36Sopenharmony_ci rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); 461162306a36Sopenharmony_ci 461262306a36Sopenharmony_ci rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF | 461362306a36Sopenharmony_ci (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT); 461462306a36Sopenharmony_ci 461562306a36Sopenharmony_ci /* enable stripping of CRC. It's unlikely this will break BMC 461662306a36Sopenharmony_ci * redirection as it did with e1000. Newer features require 461762306a36Sopenharmony_ci * that the HW strips the CRC. 461862306a36Sopenharmony_ci */ 461962306a36Sopenharmony_ci rctl |= E1000_RCTL_SECRC; 462062306a36Sopenharmony_ci 462162306a36Sopenharmony_ci /* disable store bad packets and clear size bits. */ 462262306a36Sopenharmony_ci rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256); 462362306a36Sopenharmony_ci 462462306a36Sopenharmony_ci /* enable LPE to allow for reception of jumbo frames */ 462562306a36Sopenharmony_ci rctl |= E1000_RCTL_LPE; 462662306a36Sopenharmony_ci 462762306a36Sopenharmony_ci /* disable queue 0 to prevent tail write w/o re-config */ 462862306a36Sopenharmony_ci wr32(E1000_RXDCTL(0), 0); 462962306a36Sopenharmony_ci 463062306a36Sopenharmony_ci /* Attention!!! For SR-IOV PF driver operations you must enable 463162306a36Sopenharmony_ci * queue drop for all VF and PF queues to prevent head of line blocking 463262306a36Sopenharmony_ci * if an un-trusted VF does not provide descriptors to hardware. 463362306a36Sopenharmony_ci */ 463462306a36Sopenharmony_ci if (adapter->vfs_allocated_count) { 463562306a36Sopenharmony_ci /* set all queue drop enable bits */ 463662306a36Sopenharmony_ci wr32(E1000_QDE, ALL_QUEUES); 463762306a36Sopenharmony_ci } 463862306a36Sopenharmony_ci 463962306a36Sopenharmony_ci /* This is useful for sniffing bad packets. */ 464062306a36Sopenharmony_ci if (adapter->netdev->features & NETIF_F_RXALL) { 464162306a36Sopenharmony_ci /* UPE and MPE will be handled by normal PROMISC logic 464262306a36Sopenharmony_ci * in e1000e_set_rx_mode 464362306a36Sopenharmony_ci */ 464462306a36Sopenharmony_ci rctl |= (E1000_RCTL_SBP | /* Receive bad packets */ 464562306a36Sopenharmony_ci E1000_RCTL_BAM | /* RX All Bcast Pkts */ 464662306a36Sopenharmony_ci E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */ 464762306a36Sopenharmony_ci 464862306a36Sopenharmony_ci rctl &= ~(E1000_RCTL_DPF | /* Allow filtered pause */ 464962306a36Sopenharmony_ci E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */ 465062306a36Sopenharmony_ci /* Do not mess with E1000_CTRL_VME, it affects transmit as well, 465162306a36Sopenharmony_ci * and that breaks VLANs. 465262306a36Sopenharmony_ci */ 465362306a36Sopenharmony_ci } 465462306a36Sopenharmony_ci 465562306a36Sopenharmony_ci wr32(E1000_RCTL, rctl); 465662306a36Sopenharmony_ci} 465762306a36Sopenharmony_ci 465862306a36Sopenharmony_cistatic inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size, 465962306a36Sopenharmony_ci int vfn) 466062306a36Sopenharmony_ci{ 466162306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 466262306a36Sopenharmony_ci u32 vmolr; 466362306a36Sopenharmony_ci 466462306a36Sopenharmony_ci if (size > MAX_JUMBO_FRAME_SIZE) 466562306a36Sopenharmony_ci size = MAX_JUMBO_FRAME_SIZE; 466662306a36Sopenharmony_ci 466762306a36Sopenharmony_ci vmolr = rd32(E1000_VMOLR(vfn)); 466862306a36Sopenharmony_ci vmolr &= ~E1000_VMOLR_RLPML_MASK; 466962306a36Sopenharmony_ci vmolr |= size | E1000_VMOLR_LPE; 467062306a36Sopenharmony_ci wr32(E1000_VMOLR(vfn), vmolr); 467162306a36Sopenharmony_ci 467262306a36Sopenharmony_ci return 0; 467362306a36Sopenharmony_ci} 467462306a36Sopenharmony_ci 467562306a36Sopenharmony_cistatic inline void igb_set_vf_vlan_strip(struct igb_adapter *adapter, 467662306a36Sopenharmony_ci int vfn, bool enable) 467762306a36Sopenharmony_ci{ 467862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 467962306a36Sopenharmony_ci u32 val, reg; 468062306a36Sopenharmony_ci 468162306a36Sopenharmony_ci if (hw->mac.type < e1000_82576) 468262306a36Sopenharmony_ci return; 468362306a36Sopenharmony_ci 468462306a36Sopenharmony_ci if (hw->mac.type == e1000_i350) 468562306a36Sopenharmony_ci reg = E1000_DVMOLR(vfn); 468662306a36Sopenharmony_ci else 468762306a36Sopenharmony_ci reg = E1000_VMOLR(vfn); 468862306a36Sopenharmony_ci 468962306a36Sopenharmony_ci val = rd32(reg); 469062306a36Sopenharmony_ci if (enable) 469162306a36Sopenharmony_ci val |= E1000_VMOLR_STRVLAN; 469262306a36Sopenharmony_ci else 469362306a36Sopenharmony_ci val &= ~(E1000_VMOLR_STRVLAN); 469462306a36Sopenharmony_ci wr32(reg, val); 469562306a36Sopenharmony_ci} 469662306a36Sopenharmony_ci 469762306a36Sopenharmony_cistatic inline void igb_set_vmolr(struct igb_adapter *adapter, 469862306a36Sopenharmony_ci int vfn, bool aupe) 469962306a36Sopenharmony_ci{ 470062306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 470162306a36Sopenharmony_ci u32 vmolr; 470262306a36Sopenharmony_ci 470362306a36Sopenharmony_ci /* This register exists only on 82576 and newer so if we are older then 470462306a36Sopenharmony_ci * we should exit and do nothing 470562306a36Sopenharmony_ci */ 470662306a36Sopenharmony_ci if (hw->mac.type < e1000_82576) 470762306a36Sopenharmony_ci return; 470862306a36Sopenharmony_ci 470962306a36Sopenharmony_ci vmolr = rd32(E1000_VMOLR(vfn)); 471062306a36Sopenharmony_ci if (aupe) 471162306a36Sopenharmony_ci vmolr |= E1000_VMOLR_AUPE; /* Accept untagged packets */ 471262306a36Sopenharmony_ci else 471362306a36Sopenharmony_ci vmolr &= ~(E1000_VMOLR_AUPE); /* Tagged packets ONLY */ 471462306a36Sopenharmony_ci 471562306a36Sopenharmony_ci /* clear all bits that might not be set */ 471662306a36Sopenharmony_ci vmolr &= ~(E1000_VMOLR_BAM | E1000_VMOLR_RSSE); 471762306a36Sopenharmony_ci 471862306a36Sopenharmony_ci if (adapter->rss_queues > 1 && vfn == adapter->vfs_allocated_count) 471962306a36Sopenharmony_ci vmolr |= E1000_VMOLR_RSSE; /* enable RSS */ 472062306a36Sopenharmony_ci /* for VMDq only allow the VFs and pool 0 to accept broadcast and 472162306a36Sopenharmony_ci * multicast packets 472262306a36Sopenharmony_ci */ 472362306a36Sopenharmony_ci if (vfn <= adapter->vfs_allocated_count) 472462306a36Sopenharmony_ci vmolr |= E1000_VMOLR_BAM; /* Accept broadcast */ 472562306a36Sopenharmony_ci 472662306a36Sopenharmony_ci wr32(E1000_VMOLR(vfn), vmolr); 472762306a36Sopenharmony_ci} 472862306a36Sopenharmony_ci 472962306a36Sopenharmony_ci/** 473062306a36Sopenharmony_ci * igb_setup_srrctl - configure the split and replication receive control 473162306a36Sopenharmony_ci * registers 473262306a36Sopenharmony_ci * @adapter: Board private structure 473362306a36Sopenharmony_ci * @ring: receive ring to be configured 473462306a36Sopenharmony_ci **/ 473562306a36Sopenharmony_civoid igb_setup_srrctl(struct igb_adapter *adapter, struct igb_ring *ring) 473662306a36Sopenharmony_ci{ 473762306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 473862306a36Sopenharmony_ci int reg_idx = ring->reg_idx; 473962306a36Sopenharmony_ci u32 srrctl = 0; 474062306a36Sopenharmony_ci 474162306a36Sopenharmony_ci srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT; 474262306a36Sopenharmony_ci if (ring_uses_large_buffer(ring)) 474362306a36Sopenharmony_ci srrctl |= IGB_RXBUFFER_3072 >> E1000_SRRCTL_BSIZEPKT_SHIFT; 474462306a36Sopenharmony_ci else 474562306a36Sopenharmony_ci srrctl |= IGB_RXBUFFER_2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; 474662306a36Sopenharmony_ci srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; 474762306a36Sopenharmony_ci if (hw->mac.type >= e1000_82580) 474862306a36Sopenharmony_ci srrctl |= E1000_SRRCTL_TIMESTAMP; 474962306a36Sopenharmony_ci /* Only set Drop Enable if VFs allocated, or we are supporting multiple 475062306a36Sopenharmony_ci * queues and rx flow control is disabled 475162306a36Sopenharmony_ci */ 475262306a36Sopenharmony_ci if (adapter->vfs_allocated_count || 475362306a36Sopenharmony_ci (!(hw->fc.current_mode & e1000_fc_rx_pause) && 475462306a36Sopenharmony_ci adapter->num_rx_queues > 1)) 475562306a36Sopenharmony_ci srrctl |= E1000_SRRCTL_DROP_EN; 475662306a36Sopenharmony_ci 475762306a36Sopenharmony_ci wr32(E1000_SRRCTL(reg_idx), srrctl); 475862306a36Sopenharmony_ci} 475962306a36Sopenharmony_ci 476062306a36Sopenharmony_ci/** 476162306a36Sopenharmony_ci * igb_configure_rx_ring - Configure a receive ring after Reset 476262306a36Sopenharmony_ci * @adapter: board private structure 476362306a36Sopenharmony_ci * @ring: receive ring to be configured 476462306a36Sopenharmony_ci * 476562306a36Sopenharmony_ci * Configure the Rx unit of the MAC after a reset. 476662306a36Sopenharmony_ci **/ 476762306a36Sopenharmony_civoid igb_configure_rx_ring(struct igb_adapter *adapter, 476862306a36Sopenharmony_ci struct igb_ring *ring) 476962306a36Sopenharmony_ci{ 477062306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 477162306a36Sopenharmony_ci union e1000_adv_rx_desc *rx_desc; 477262306a36Sopenharmony_ci u64 rdba = ring->dma; 477362306a36Sopenharmony_ci int reg_idx = ring->reg_idx; 477462306a36Sopenharmony_ci u32 rxdctl = 0; 477562306a36Sopenharmony_ci 477662306a36Sopenharmony_ci xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq); 477762306a36Sopenharmony_ci WARN_ON(xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, 477862306a36Sopenharmony_ci MEM_TYPE_PAGE_SHARED, NULL)); 477962306a36Sopenharmony_ci 478062306a36Sopenharmony_ci /* disable the queue */ 478162306a36Sopenharmony_ci wr32(E1000_RXDCTL(reg_idx), 0); 478262306a36Sopenharmony_ci 478362306a36Sopenharmony_ci /* Set DMA base address registers */ 478462306a36Sopenharmony_ci wr32(E1000_RDBAL(reg_idx), 478562306a36Sopenharmony_ci rdba & 0x00000000ffffffffULL); 478662306a36Sopenharmony_ci wr32(E1000_RDBAH(reg_idx), rdba >> 32); 478762306a36Sopenharmony_ci wr32(E1000_RDLEN(reg_idx), 478862306a36Sopenharmony_ci ring->count * sizeof(union e1000_adv_rx_desc)); 478962306a36Sopenharmony_ci 479062306a36Sopenharmony_ci /* initialize head and tail */ 479162306a36Sopenharmony_ci ring->tail = adapter->io_addr + E1000_RDT(reg_idx); 479262306a36Sopenharmony_ci wr32(E1000_RDH(reg_idx), 0); 479362306a36Sopenharmony_ci writel(0, ring->tail); 479462306a36Sopenharmony_ci 479562306a36Sopenharmony_ci /* set descriptor configuration */ 479662306a36Sopenharmony_ci igb_setup_srrctl(adapter, ring); 479762306a36Sopenharmony_ci 479862306a36Sopenharmony_ci /* set filtering for VMDQ pools */ 479962306a36Sopenharmony_ci igb_set_vmolr(adapter, reg_idx & 0x7, true); 480062306a36Sopenharmony_ci 480162306a36Sopenharmony_ci rxdctl |= IGB_RX_PTHRESH; 480262306a36Sopenharmony_ci rxdctl |= IGB_RX_HTHRESH << 8; 480362306a36Sopenharmony_ci rxdctl |= IGB_RX_WTHRESH << 16; 480462306a36Sopenharmony_ci 480562306a36Sopenharmony_ci /* initialize rx_buffer_info */ 480662306a36Sopenharmony_ci memset(ring->rx_buffer_info, 0, 480762306a36Sopenharmony_ci sizeof(struct igb_rx_buffer) * ring->count); 480862306a36Sopenharmony_ci 480962306a36Sopenharmony_ci /* initialize Rx descriptor 0 */ 481062306a36Sopenharmony_ci rx_desc = IGB_RX_DESC(ring, 0); 481162306a36Sopenharmony_ci rx_desc->wb.upper.length = 0; 481262306a36Sopenharmony_ci 481362306a36Sopenharmony_ci /* enable receive descriptor fetching */ 481462306a36Sopenharmony_ci rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; 481562306a36Sopenharmony_ci wr32(E1000_RXDCTL(reg_idx), rxdctl); 481662306a36Sopenharmony_ci} 481762306a36Sopenharmony_ci 481862306a36Sopenharmony_cistatic void igb_set_rx_buffer_len(struct igb_adapter *adapter, 481962306a36Sopenharmony_ci struct igb_ring *rx_ring) 482062306a36Sopenharmony_ci{ 482162306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 482262306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 482362306a36Sopenharmony_ci#endif 482462306a36Sopenharmony_ci 482562306a36Sopenharmony_ci /* set build_skb and buffer size flags */ 482662306a36Sopenharmony_ci clear_ring_build_skb_enabled(rx_ring); 482762306a36Sopenharmony_ci clear_ring_uses_large_buffer(rx_ring); 482862306a36Sopenharmony_ci 482962306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_RX_LEGACY) 483062306a36Sopenharmony_ci return; 483162306a36Sopenharmony_ci 483262306a36Sopenharmony_ci set_ring_build_skb_enabled(rx_ring); 483362306a36Sopenharmony_ci 483462306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 483562306a36Sopenharmony_ci if (adapter->max_frame_size > IGB_MAX_FRAME_BUILD_SKB || 483662306a36Sopenharmony_ci rd32(E1000_RCTL) & E1000_RCTL_SBP) 483762306a36Sopenharmony_ci set_ring_uses_large_buffer(rx_ring); 483862306a36Sopenharmony_ci#endif 483962306a36Sopenharmony_ci} 484062306a36Sopenharmony_ci 484162306a36Sopenharmony_ci/** 484262306a36Sopenharmony_ci * igb_configure_rx - Configure receive Unit after Reset 484362306a36Sopenharmony_ci * @adapter: board private structure 484462306a36Sopenharmony_ci * 484562306a36Sopenharmony_ci * Configure the Rx unit of the MAC after a reset. 484662306a36Sopenharmony_ci **/ 484762306a36Sopenharmony_cistatic void igb_configure_rx(struct igb_adapter *adapter) 484862306a36Sopenharmony_ci{ 484962306a36Sopenharmony_ci int i; 485062306a36Sopenharmony_ci 485162306a36Sopenharmony_ci /* set the correct pool for the PF default MAC address in entry 0 */ 485262306a36Sopenharmony_ci igb_set_default_mac_filter(adapter); 485362306a36Sopenharmony_ci 485462306a36Sopenharmony_ci /* Setup the HW Rx Head and Tail Descriptor Pointers and 485562306a36Sopenharmony_ci * the Base and Length of the Rx Descriptor Ring 485662306a36Sopenharmony_ci */ 485762306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 485862306a36Sopenharmony_ci struct igb_ring *rx_ring = adapter->rx_ring[i]; 485962306a36Sopenharmony_ci 486062306a36Sopenharmony_ci igb_set_rx_buffer_len(adapter, rx_ring); 486162306a36Sopenharmony_ci igb_configure_rx_ring(adapter, rx_ring); 486262306a36Sopenharmony_ci } 486362306a36Sopenharmony_ci} 486462306a36Sopenharmony_ci 486562306a36Sopenharmony_ci/** 486662306a36Sopenharmony_ci * igb_free_tx_resources - Free Tx Resources per Queue 486762306a36Sopenharmony_ci * @tx_ring: Tx descriptor ring for a specific queue 486862306a36Sopenharmony_ci * 486962306a36Sopenharmony_ci * Free all transmit software resources 487062306a36Sopenharmony_ci **/ 487162306a36Sopenharmony_civoid igb_free_tx_resources(struct igb_ring *tx_ring) 487262306a36Sopenharmony_ci{ 487362306a36Sopenharmony_ci igb_clean_tx_ring(tx_ring); 487462306a36Sopenharmony_ci 487562306a36Sopenharmony_ci vfree(tx_ring->tx_buffer_info); 487662306a36Sopenharmony_ci tx_ring->tx_buffer_info = NULL; 487762306a36Sopenharmony_ci 487862306a36Sopenharmony_ci /* if not set, then don't free */ 487962306a36Sopenharmony_ci if (!tx_ring->desc) 488062306a36Sopenharmony_ci return; 488162306a36Sopenharmony_ci 488262306a36Sopenharmony_ci dma_free_coherent(tx_ring->dev, tx_ring->size, 488362306a36Sopenharmony_ci tx_ring->desc, tx_ring->dma); 488462306a36Sopenharmony_ci 488562306a36Sopenharmony_ci tx_ring->desc = NULL; 488662306a36Sopenharmony_ci} 488762306a36Sopenharmony_ci 488862306a36Sopenharmony_ci/** 488962306a36Sopenharmony_ci * igb_free_all_tx_resources - Free Tx Resources for All Queues 489062306a36Sopenharmony_ci * @adapter: board private structure 489162306a36Sopenharmony_ci * 489262306a36Sopenharmony_ci * Free all transmit software resources 489362306a36Sopenharmony_ci **/ 489462306a36Sopenharmony_cistatic void igb_free_all_tx_resources(struct igb_adapter *adapter) 489562306a36Sopenharmony_ci{ 489662306a36Sopenharmony_ci int i; 489762306a36Sopenharmony_ci 489862306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 489962306a36Sopenharmony_ci if (adapter->tx_ring[i]) 490062306a36Sopenharmony_ci igb_free_tx_resources(adapter->tx_ring[i]); 490162306a36Sopenharmony_ci} 490262306a36Sopenharmony_ci 490362306a36Sopenharmony_ci/** 490462306a36Sopenharmony_ci * igb_clean_tx_ring - Free Tx Buffers 490562306a36Sopenharmony_ci * @tx_ring: ring to be cleaned 490662306a36Sopenharmony_ci **/ 490762306a36Sopenharmony_cistatic void igb_clean_tx_ring(struct igb_ring *tx_ring) 490862306a36Sopenharmony_ci{ 490962306a36Sopenharmony_ci u16 i = tx_ring->next_to_clean; 491062306a36Sopenharmony_ci struct igb_tx_buffer *tx_buffer = &tx_ring->tx_buffer_info[i]; 491162306a36Sopenharmony_ci 491262306a36Sopenharmony_ci while (i != tx_ring->next_to_use) { 491362306a36Sopenharmony_ci union e1000_adv_tx_desc *eop_desc, *tx_desc; 491462306a36Sopenharmony_ci 491562306a36Sopenharmony_ci /* Free all the Tx ring sk_buffs or xdp frames */ 491662306a36Sopenharmony_ci if (tx_buffer->type == IGB_TYPE_SKB) 491762306a36Sopenharmony_ci dev_kfree_skb_any(tx_buffer->skb); 491862306a36Sopenharmony_ci else 491962306a36Sopenharmony_ci xdp_return_frame(tx_buffer->xdpf); 492062306a36Sopenharmony_ci 492162306a36Sopenharmony_ci /* unmap skb header data */ 492262306a36Sopenharmony_ci dma_unmap_single(tx_ring->dev, 492362306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 492462306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 492562306a36Sopenharmony_ci DMA_TO_DEVICE); 492662306a36Sopenharmony_ci 492762306a36Sopenharmony_ci /* check for eop_desc to determine the end of the packet */ 492862306a36Sopenharmony_ci eop_desc = tx_buffer->next_to_watch; 492962306a36Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, i); 493062306a36Sopenharmony_ci 493162306a36Sopenharmony_ci /* unmap remaining buffers */ 493262306a36Sopenharmony_ci while (tx_desc != eop_desc) { 493362306a36Sopenharmony_ci tx_buffer++; 493462306a36Sopenharmony_ci tx_desc++; 493562306a36Sopenharmony_ci i++; 493662306a36Sopenharmony_ci if (unlikely(i == tx_ring->count)) { 493762306a36Sopenharmony_ci i = 0; 493862306a36Sopenharmony_ci tx_buffer = tx_ring->tx_buffer_info; 493962306a36Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, 0); 494062306a36Sopenharmony_ci } 494162306a36Sopenharmony_ci 494262306a36Sopenharmony_ci /* unmap any remaining paged data */ 494362306a36Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) 494462306a36Sopenharmony_ci dma_unmap_page(tx_ring->dev, 494562306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 494662306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 494762306a36Sopenharmony_ci DMA_TO_DEVICE); 494862306a36Sopenharmony_ci } 494962306a36Sopenharmony_ci 495062306a36Sopenharmony_ci tx_buffer->next_to_watch = NULL; 495162306a36Sopenharmony_ci 495262306a36Sopenharmony_ci /* move us one more past the eop_desc for start of next pkt */ 495362306a36Sopenharmony_ci tx_buffer++; 495462306a36Sopenharmony_ci i++; 495562306a36Sopenharmony_ci if (unlikely(i == tx_ring->count)) { 495662306a36Sopenharmony_ci i = 0; 495762306a36Sopenharmony_ci tx_buffer = tx_ring->tx_buffer_info; 495862306a36Sopenharmony_ci } 495962306a36Sopenharmony_ci } 496062306a36Sopenharmony_ci 496162306a36Sopenharmony_ci /* reset BQL for queue */ 496262306a36Sopenharmony_ci netdev_tx_reset_queue(txring_txq(tx_ring)); 496362306a36Sopenharmony_ci 496462306a36Sopenharmony_ci /* reset next_to_use and next_to_clean */ 496562306a36Sopenharmony_ci tx_ring->next_to_use = 0; 496662306a36Sopenharmony_ci tx_ring->next_to_clean = 0; 496762306a36Sopenharmony_ci} 496862306a36Sopenharmony_ci 496962306a36Sopenharmony_ci/** 497062306a36Sopenharmony_ci * igb_clean_all_tx_rings - Free Tx Buffers for all queues 497162306a36Sopenharmony_ci * @adapter: board private structure 497262306a36Sopenharmony_ci **/ 497362306a36Sopenharmony_cistatic void igb_clean_all_tx_rings(struct igb_adapter *adapter) 497462306a36Sopenharmony_ci{ 497562306a36Sopenharmony_ci int i; 497662306a36Sopenharmony_ci 497762306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 497862306a36Sopenharmony_ci if (adapter->tx_ring[i]) 497962306a36Sopenharmony_ci igb_clean_tx_ring(adapter->tx_ring[i]); 498062306a36Sopenharmony_ci} 498162306a36Sopenharmony_ci 498262306a36Sopenharmony_ci/** 498362306a36Sopenharmony_ci * igb_free_rx_resources - Free Rx Resources 498462306a36Sopenharmony_ci * @rx_ring: ring to clean the resources from 498562306a36Sopenharmony_ci * 498662306a36Sopenharmony_ci * Free all receive software resources 498762306a36Sopenharmony_ci **/ 498862306a36Sopenharmony_civoid igb_free_rx_resources(struct igb_ring *rx_ring) 498962306a36Sopenharmony_ci{ 499062306a36Sopenharmony_ci igb_clean_rx_ring(rx_ring); 499162306a36Sopenharmony_ci 499262306a36Sopenharmony_ci rx_ring->xdp_prog = NULL; 499362306a36Sopenharmony_ci xdp_rxq_info_unreg(&rx_ring->xdp_rxq); 499462306a36Sopenharmony_ci vfree(rx_ring->rx_buffer_info); 499562306a36Sopenharmony_ci rx_ring->rx_buffer_info = NULL; 499662306a36Sopenharmony_ci 499762306a36Sopenharmony_ci /* if not set, then don't free */ 499862306a36Sopenharmony_ci if (!rx_ring->desc) 499962306a36Sopenharmony_ci return; 500062306a36Sopenharmony_ci 500162306a36Sopenharmony_ci dma_free_coherent(rx_ring->dev, rx_ring->size, 500262306a36Sopenharmony_ci rx_ring->desc, rx_ring->dma); 500362306a36Sopenharmony_ci 500462306a36Sopenharmony_ci rx_ring->desc = NULL; 500562306a36Sopenharmony_ci} 500662306a36Sopenharmony_ci 500762306a36Sopenharmony_ci/** 500862306a36Sopenharmony_ci * igb_free_all_rx_resources - Free Rx Resources for All Queues 500962306a36Sopenharmony_ci * @adapter: board private structure 501062306a36Sopenharmony_ci * 501162306a36Sopenharmony_ci * Free all receive software resources 501262306a36Sopenharmony_ci **/ 501362306a36Sopenharmony_cistatic void igb_free_all_rx_resources(struct igb_adapter *adapter) 501462306a36Sopenharmony_ci{ 501562306a36Sopenharmony_ci int i; 501662306a36Sopenharmony_ci 501762306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) 501862306a36Sopenharmony_ci if (adapter->rx_ring[i]) 501962306a36Sopenharmony_ci igb_free_rx_resources(adapter->rx_ring[i]); 502062306a36Sopenharmony_ci} 502162306a36Sopenharmony_ci 502262306a36Sopenharmony_ci/** 502362306a36Sopenharmony_ci * igb_clean_rx_ring - Free Rx Buffers per Queue 502462306a36Sopenharmony_ci * @rx_ring: ring to free buffers from 502562306a36Sopenharmony_ci **/ 502662306a36Sopenharmony_cistatic void igb_clean_rx_ring(struct igb_ring *rx_ring) 502762306a36Sopenharmony_ci{ 502862306a36Sopenharmony_ci u16 i = rx_ring->next_to_clean; 502962306a36Sopenharmony_ci 503062306a36Sopenharmony_ci dev_kfree_skb(rx_ring->skb); 503162306a36Sopenharmony_ci rx_ring->skb = NULL; 503262306a36Sopenharmony_ci 503362306a36Sopenharmony_ci /* Free all the Rx ring sk_buffs */ 503462306a36Sopenharmony_ci while (i != rx_ring->next_to_alloc) { 503562306a36Sopenharmony_ci struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i]; 503662306a36Sopenharmony_ci 503762306a36Sopenharmony_ci /* Invalidate cache lines that may have been written to by 503862306a36Sopenharmony_ci * device so that we avoid corrupting memory. 503962306a36Sopenharmony_ci */ 504062306a36Sopenharmony_ci dma_sync_single_range_for_cpu(rx_ring->dev, 504162306a36Sopenharmony_ci buffer_info->dma, 504262306a36Sopenharmony_ci buffer_info->page_offset, 504362306a36Sopenharmony_ci igb_rx_bufsz(rx_ring), 504462306a36Sopenharmony_ci DMA_FROM_DEVICE); 504562306a36Sopenharmony_ci 504662306a36Sopenharmony_ci /* free resources associated with mapping */ 504762306a36Sopenharmony_ci dma_unmap_page_attrs(rx_ring->dev, 504862306a36Sopenharmony_ci buffer_info->dma, 504962306a36Sopenharmony_ci igb_rx_pg_size(rx_ring), 505062306a36Sopenharmony_ci DMA_FROM_DEVICE, 505162306a36Sopenharmony_ci IGB_RX_DMA_ATTR); 505262306a36Sopenharmony_ci __page_frag_cache_drain(buffer_info->page, 505362306a36Sopenharmony_ci buffer_info->pagecnt_bias); 505462306a36Sopenharmony_ci 505562306a36Sopenharmony_ci i++; 505662306a36Sopenharmony_ci if (i == rx_ring->count) 505762306a36Sopenharmony_ci i = 0; 505862306a36Sopenharmony_ci } 505962306a36Sopenharmony_ci 506062306a36Sopenharmony_ci rx_ring->next_to_alloc = 0; 506162306a36Sopenharmony_ci rx_ring->next_to_clean = 0; 506262306a36Sopenharmony_ci rx_ring->next_to_use = 0; 506362306a36Sopenharmony_ci} 506462306a36Sopenharmony_ci 506562306a36Sopenharmony_ci/** 506662306a36Sopenharmony_ci * igb_clean_all_rx_rings - Free Rx Buffers for all queues 506762306a36Sopenharmony_ci * @adapter: board private structure 506862306a36Sopenharmony_ci **/ 506962306a36Sopenharmony_cistatic void igb_clean_all_rx_rings(struct igb_adapter *adapter) 507062306a36Sopenharmony_ci{ 507162306a36Sopenharmony_ci int i; 507262306a36Sopenharmony_ci 507362306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) 507462306a36Sopenharmony_ci if (adapter->rx_ring[i]) 507562306a36Sopenharmony_ci igb_clean_rx_ring(adapter->rx_ring[i]); 507662306a36Sopenharmony_ci} 507762306a36Sopenharmony_ci 507862306a36Sopenharmony_ci/** 507962306a36Sopenharmony_ci * igb_set_mac - Change the Ethernet Address of the NIC 508062306a36Sopenharmony_ci * @netdev: network interface device structure 508162306a36Sopenharmony_ci * @p: pointer to an address structure 508262306a36Sopenharmony_ci * 508362306a36Sopenharmony_ci * Returns 0 on success, negative on failure 508462306a36Sopenharmony_ci **/ 508562306a36Sopenharmony_cistatic int igb_set_mac(struct net_device *netdev, void *p) 508662306a36Sopenharmony_ci{ 508762306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 508862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 508962306a36Sopenharmony_ci struct sockaddr *addr = p; 509062306a36Sopenharmony_ci 509162306a36Sopenharmony_ci if (!is_valid_ether_addr(addr->sa_data)) 509262306a36Sopenharmony_ci return -EADDRNOTAVAIL; 509362306a36Sopenharmony_ci 509462306a36Sopenharmony_ci eth_hw_addr_set(netdev, addr->sa_data); 509562306a36Sopenharmony_ci memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); 509662306a36Sopenharmony_ci 509762306a36Sopenharmony_ci /* set the correct pool for the new PF MAC address in entry 0 */ 509862306a36Sopenharmony_ci igb_set_default_mac_filter(adapter); 509962306a36Sopenharmony_ci 510062306a36Sopenharmony_ci return 0; 510162306a36Sopenharmony_ci} 510262306a36Sopenharmony_ci 510362306a36Sopenharmony_ci/** 510462306a36Sopenharmony_ci * igb_write_mc_addr_list - write multicast addresses to MTA 510562306a36Sopenharmony_ci * @netdev: network interface device structure 510662306a36Sopenharmony_ci * 510762306a36Sopenharmony_ci * Writes multicast address list to the MTA hash table. 510862306a36Sopenharmony_ci * Returns: -ENOMEM on failure 510962306a36Sopenharmony_ci * 0 on no addresses written 511062306a36Sopenharmony_ci * X on writing X addresses to MTA 511162306a36Sopenharmony_ci **/ 511262306a36Sopenharmony_cistatic int igb_write_mc_addr_list(struct net_device *netdev) 511362306a36Sopenharmony_ci{ 511462306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 511562306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 511662306a36Sopenharmony_ci struct netdev_hw_addr *ha; 511762306a36Sopenharmony_ci u8 *mta_list; 511862306a36Sopenharmony_ci int i; 511962306a36Sopenharmony_ci 512062306a36Sopenharmony_ci if (netdev_mc_empty(netdev)) { 512162306a36Sopenharmony_ci /* nothing to program, so clear mc list */ 512262306a36Sopenharmony_ci igb_update_mc_addr_list(hw, NULL, 0); 512362306a36Sopenharmony_ci igb_restore_vf_multicasts(adapter); 512462306a36Sopenharmony_ci return 0; 512562306a36Sopenharmony_ci } 512662306a36Sopenharmony_ci 512762306a36Sopenharmony_ci mta_list = kcalloc(netdev_mc_count(netdev), 6, GFP_ATOMIC); 512862306a36Sopenharmony_ci if (!mta_list) 512962306a36Sopenharmony_ci return -ENOMEM; 513062306a36Sopenharmony_ci 513162306a36Sopenharmony_ci /* The shared function expects a packed array of only addresses. */ 513262306a36Sopenharmony_ci i = 0; 513362306a36Sopenharmony_ci netdev_for_each_mc_addr(ha, netdev) 513462306a36Sopenharmony_ci memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); 513562306a36Sopenharmony_ci 513662306a36Sopenharmony_ci igb_update_mc_addr_list(hw, mta_list, i); 513762306a36Sopenharmony_ci kfree(mta_list); 513862306a36Sopenharmony_ci 513962306a36Sopenharmony_ci return netdev_mc_count(netdev); 514062306a36Sopenharmony_ci} 514162306a36Sopenharmony_ci 514262306a36Sopenharmony_cistatic int igb_vlan_promisc_enable(struct igb_adapter *adapter) 514362306a36Sopenharmony_ci{ 514462306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 514562306a36Sopenharmony_ci u32 i, pf_id; 514662306a36Sopenharmony_ci 514762306a36Sopenharmony_ci switch (hw->mac.type) { 514862306a36Sopenharmony_ci case e1000_i210: 514962306a36Sopenharmony_ci case e1000_i211: 515062306a36Sopenharmony_ci case e1000_i350: 515162306a36Sopenharmony_ci /* VLAN filtering needed for VLAN prio filter */ 515262306a36Sopenharmony_ci if (adapter->netdev->features & NETIF_F_NTUPLE) 515362306a36Sopenharmony_ci break; 515462306a36Sopenharmony_ci fallthrough; 515562306a36Sopenharmony_ci case e1000_82576: 515662306a36Sopenharmony_ci case e1000_82580: 515762306a36Sopenharmony_ci case e1000_i354: 515862306a36Sopenharmony_ci /* VLAN filtering needed for pool filtering */ 515962306a36Sopenharmony_ci if (adapter->vfs_allocated_count) 516062306a36Sopenharmony_ci break; 516162306a36Sopenharmony_ci fallthrough; 516262306a36Sopenharmony_ci default: 516362306a36Sopenharmony_ci return 1; 516462306a36Sopenharmony_ci } 516562306a36Sopenharmony_ci 516662306a36Sopenharmony_ci /* We are already in VLAN promisc, nothing to do */ 516762306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_VLAN_PROMISC) 516862306a36Sopenharmony_ci return 0; 516962306a36Sopenharmony_ci 517062306a36Sopenharmony_ci if (!adapter->vfs_allocated_count) 517162306a36Sopenharmony_ci goto set_vfta; 517262306a36Sopenharmony_ci 517362306a36Sopenharmony_ci /* Add PF to all active pools */ 517462306a36Sopenharmony_ci pf_id = adapter->vfs_allocated_count + E1000_VLVF_POOLSEL_SHIFT; 517562306a36Sopenharmony_ci 517662306a36Sopenharmony_ci for (i = E1000_VLVF_ARRAY_SIZE; --i;) { 517762306a36Sopenharmony_ci u32 vlvf = rd32(E1000_VLVF(i)); 517862306a36Sopenharmony_ci 517962306a36Sopenharmony_ci vlvf |= BIT(pf_id); 518062306a36Sopenharmony_ci wr32(E1000_VLVF(i), vlvf); 518162306a36Sopenharmony_ci } 518262306a36Sopenharmony_ci 518362306a36Sopenharmony_ciset_vfta: 518462306a36Sopenharmony_ci /* Set all bits in the VLAN filter table array */ 518562306a36Sopenharmony_ci for (i = E1000_VLAN_FILTER_TBL_SIZE; i--;) 518662306a36Sopenharmony_ci hw->mac.ops.write_vfta(hw, i, ~0U); 518762306a36Sopenharmony_ci 518862306a36Sopenharmony_ci /* Set flag so we don't redo unnecessary work */ 518962306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_VLAN_PROMISC; 519062306a36Sopenharmony_ci 519162306a36Sopenharmony_ci return 0; 519262306a36Sopenharmony_ci} 519362306a36Sopenharmony_ci 519462306a36Sopenharmony_ci#define VFTA_BLOCK_SIZE 8 519562306a36Sopenharmony_cistatic void igb_scrub_vfta(struct igb_adapter *adapter, u32 vfta_offset) 519662306a36Sopenharmony_ci{ 519762306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 519862306a36Sopenharmony_ci u32 vfta[VFTA_BLOCK_SIZE] = { 0 }; 519962306a36Sopenharmony_ci u32 vid_start = vfta_offset * 32; 520062306a36Sopenharmony_ci u32 vid_end = vid_start + (VFTA_BLOCK_SIZE * 32); 520162306a36Sopenharmony_ci u32 i, vid, word, bits, pf_id; 520262306a36Sopenharmony_ci 520362306a36Sopenharmony_ci /* guarantee that we don't scrub out management VLAN */ 520462306a36Sopenharmony_ci vid = adapter->mng_vlan_id; 520562306a36Sopenharmony_ci if (vid >= vid_start && vid < vid_end) 520662306a36Sopenharmony_ci vfta[(vid - vid_start) / 32] |= BIT(vid % 32); 520762306a36Sopenharmony_ci 520862306a36Sopenharmony_ci if (!adapter->vfs_allocated_count) 520962306a36Sopenharmony_ci goto set_vfta; 521062306a36Sopenharmony_ci 521162306a36Sopenharmony_ci pf_id = adapter->vfs_allocated_count + E1000_VLVF_POOLSEL_SHIFT; 521262306a36Sopenharmony_ci 521362306a36Sopenharmony_ci for (i = E1000_VLVF_ARRAY_SIZE; --i;) { 521462306a36Sopenharmony_ci u32 vlvf = rd32(E1000_VLVF(i)); 521562306a36Sopenharmony_ci 521662306a36Sopenharmony_ci /* pull VLAN ID from VLVF */ 521762306a36Sopenharmony_ci vid = vlvf & VLAN_VID_MASK; 521862306a36Sopenharmony_ci 521962306a36Sopenharmony_ci /* only concern ourselves with a certain range */ 522062306a36Sopenharmony_ci if (vid < vid_start || vid >= vid_end) 522162306a36Sopenharmony_ci continue; 522262306a36Sopenharmony_ci 522362306a36Sopenharmony_ci if (vlvf & E1000_VLVF_VLANID_ENABLE) { 522462306a36Sopenharmony_ci /* record VLAN ID in VFTA */ 522562306a36Sopenharmony_ci vfta[(vid - vid_start) / 32] |= BIT(vid % 32); 522662306a36Sopenharmony_ci 522762306a36Sopenharmony_ci /* if PF is part of this then continue */ 522862306a36Sopenharmony_ci if (test_bit(vid, adapter->active_vlans)) 522962306a36Sopenharmony_ci continue; 523062306a36Sopenharmony_ci } 523162306a36Sopenharmony_ci 523262306a36Sopenharmony_ci /* remove PF from the pool */ 523362306a36Sopenharmony_ci bits = ~BIT(pf_id); 523462306a36Sopenharmony_ci bits &= rd32(E1000_VLVF(i)); 523562306a36Sopenharmony_ci wr32(E1000_VLVF(i), bits); 523662306a36Sopenharmony_ci } 523762306a36Sopenharmony_ci 523862306a36Sopenharmony_ciset_vfta: 523962306a36Sopenharmony_ci /* extract values from active_vlans and write back to VFTA */ 524062306a36Sopenharmony_ci for (i = VFTA_BLOCK_SIZE; i--;) { 524162306a36Sopenharmony_ci vid = (vfta_offset + i) * 32; 524262306a36Sopenharmony_ci word = vid / BITS_PER_LONG; 524362306a36Sopenharmony_ci bits = vid % BITS_PER_LONG; 524462306a36Sopenharmony_ci 524562306a36Sopenharmony_ci vfta[i] |= adapter->active_vlans[word] >> bits; 524662306a36Sopenharmony_ci 524762306a36Sopenharmony_ci hw->mac.ops.write_vfta(hw, vfta_offset + i, vfta[i]); 524862306a36Sopenharmony_ci } 524962306a36Sopenharmony_ci} 525062306a36Sopenharmony_ci 525162306a36Sopenharmony_cistatic void igb_vlan_promisc_disable(struct igb_adapter *adapter) 525262306a36Sopenharmony_ci{ 525362306a36Sopenharmony_ci u32 i; 525462306a36Sopenharmony_ci 525562306a36Sopenharmony_ci /* We are not in VLAN promisc, nothing to do */ 525662306a36Sopenharmony_ci if (!(adapter->flags & IGB_FLAG_VLAN_PROMISC)) 525762306a36Sopenharmony_ci return; 525862306a36Sopenharmony_ci 525962306a36Sopenharmony_ci /* Set flag so we don't redo unnecessary work */ 526062306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_VLAN_PROMISC; 526162306a36Sopenharmony_ci 526262306a36Sopenharmony_ci for (i = 0; i < E1000_VLAN_FILTER_TBL_SIZE; i += VFTA_BLOCK_SIZE) 526362306a36Sopenharmony_ci igb_scrub_vfta(adapter, i); 526462306a36Sopenharmony_ci} 526562306a36Sopenharmony_ci 526662306a36Sopenharmony_ci/** 526762306a36Sopenharmony_ci * igb_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set 526862306a36Sopenharmony_ci * @netdev: network interface device structure 526962306a36Sopenharmony_ci * 527062306a36Sopenharmony_ci * The set_rx_mode entry point is called whenever the unicast or multicast 527162306a36Sopenharmony_ci * address lists or the network interface flags are updated. This routine is 527262306a36Sopenharmony_ci * responsible for configuring the hardware for proper unicast, multicast, 527362306a36Sopenharmony_ci * promiscuous mode, and all-multi behavior. 527462306a36Sopenharmony_ci **/ 527562306a36Sopenharmony_cistatic void igb_set_rx_mode(struct net_device *netdev) 527662306a36Sopenharmony_ci{ 527762306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 527862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 527962306a36Sopenharmony_ci unsigned int vfn = adapter->vfs_allocated_count; 528062306a36Sopenharmony_ci u32 rctl = 0, vmolr = 0, rlpml = MAX_JUMBO_FRAME_SIZE; 528162306a36Sopenharmony_ci int count; 528262306a36Sopenharmony_ci 528362306a36Sopenharmony_ci /* Check for Promiscuous and All Multicast modes */ 528462306a36Sopenharmony_ci if (netdev->flags & IFF_PROMISC) { 528562306a36Sopenharmony_ci rctl |= E1000_RCTL_UPE | E1000_RCTL_MPE; 528662306a36Sopenharmony_ci vmolr |= E1000_VMOLR_MPME; 528762306a36Sopenharmony_ci 528862306a36Sopenharmony_ci /* enable use of UTA filter to force packets to default pool */ 528962306a36Sopenharmony_ci if (hw->mac.type == e1000_82576) 529062306a36Sopenharmony_ci vmolr |= E1000_VMOLR_ROPE; 529162306a36Sopenharmony_ci } else { 529262306a36Sopenharmony_ci if (netdev->flags & IFF_ALLMULTI) { 529362306a36Sopenharmony_ci rctl |= E1000_RCTL_MPE; 529462306a36Sopenharmony_ci vmolr |= E1000_VMOLR_MPME; 529562306a36Sopenharmony_ci } else { 529662306a36Sopenharmony_ci /* Write addresses to the MTA, if the attempt fails 529762306a36Sopenharmony_ci * then we should just turn on promiscuous mode so 529862306a36Sopenharmony_ci * that we can at least receive multicast traffic 529962306a36Sopenharmony_ci */ 530062306a36Sopenharmony_ci count = igb_write_mc_addr_list(netdev); 530162306a36Sopenharmony_ci if (count < 0) { 530262306a36Sopenharmony_ci rctl |= E1000_RCTL_MPE; 530362306a36Sopenharmony_ci vmolr |= E1000_VMOLR_MPME; 530462306a36Sopenharmony_ci } else if (count) { 530562306a36Sopenharmony_ci vmolr |= E1000_VMOLR_ROMPE; 530662306a36Sopenharmony_ci } 530762306a36Sopenharmony_ci } 530862306a36Sopenharmony_ci } 530962306a36Sopenharmony_ci 531062306a36Sopenharmony_ci /* Write addresses to available RAR registers, if there is not 531162306a36Sopenharmony_ci * sufficient space to store all the addresses then enable 531262306a36Sopenharmony_ci * unicast promiscuous mode 531362306a36Sopenharmony_ci */ 531462306a36Sopenharmony_ci if (__dev_uc_sync(netdev, igb_uc_sync, igb_uc_unsync)) { 531562306a36Sopenharmony_ci rctl |= E1000_RCTL_UPE; 531662306a36Sopenharmony_ci vmolr |= E1000_VMOLR_ROPE; 531762306a36Sopenharmony_ci } 531862306a36Sopenharmony_ci 531962306a36Sopenharmony_ci /* enable VLAN filtering by default */ 532062306a36Sopenharmony_ci rctl |= E1000_RCTL_VFE; 532162306a36Sopenharmony_ci 532262306a36Sopenharmony_ci /* disable VLAN filtering for modes that require it */ 532362306a36Sopenharmony_ci if ((netdev->flags & IFF_PROMISC) || 532462306a36Sopenharmony_ci (netdev->features & NETIF_F_RXALL)) { 532562306a36Sopenharmony_ci /* if we fail to set all rules then just clear VFE */ 532662306a36Sopenharmony_ci if (igb_vlan_promisc_enable(adapter)) 532762306a36Sopenharmony_ci rctl &= ~E1000_RCTL_VFE; 532862306a36Sopenharmony_ci } else { 532962306a36Sopenharmony_ci igb_vlan_promisc_disable(adapter); 533062306a36Sopenharmony_ci } 533162306a36Sopenharmony_ci 533262306a36Sopenharmony_ci /* update state of unicast, multicast, and VLAN filtering modes */ 533362306a36Sopenharmony_ci rctl |= rd32(E1000_RCTL) & ~(E1000_RCTL_UPE | E1000_RCTL_MPE | 533462306a36Sopenharmony_ci E1000_RCTL_VFE); 533562306a36Sopenharmony_ci wr32(E1000_RCTL, rctl); 533662306a36Sopenharmony_ci 533762306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 533862306a36Sopenharmony_ci if (!adapter->vfs_allocated_count) { 533962306a36Sopenharmony_ci if (adapter->max_frame_size <= IGB_MAX_FRAME_BUILD_SKB) 534062306a36Sopenharmony_ci rlpml = IGB_MAX_FRAME_BUILD_SKB; 534162306a36Sopenharmony_ci } 534262306a36Sopenharmony_ci#endif 534362306a36Sopenharmony_ci wr32(E1000_RLPML, rlpml); 534462306a36Sopenharmony_ci 534562306a36Sopenharmony_ci /* In order to support SR-IOV and eventually VMDq it is necessary to set 534662306a36Sopenharmony_ci * the VMOLR to enable the appropriate modes. Without this workaround 534762306a36Sopenharmony_ci * we will have issues with VLAN tag stripping not being done for frames 534862306a36Sopenharmony_ci * that are only arriving because we are the default pool 534962306a36Sopenharmony_ci */ 535062306a36Sopenharmony_ci if ((hw->mac.type < e1000_82576) || (hw->mac.type > e1000_i350)) 535162306a36Sopenharmony_ci return; 535262306a36Sopenharmony_ci 535362306a36Sopenharmony_ci /* set UTA to appropriate mode */ 535462306a36Sopenharmony_ci igb_set_uta(adapter, !!(vmolr & E1000_VMOLR_ROPE)); 535562306a36Sopenharmony_ci 535662306a36Sopenharmony_ci vmolr |= rd32(E1000_VMOLR(vfn)) & 535762306a36Sopenharmony_ci ~(E1000_VMOLR_ROPE | E1000_VMOLR_MPME | E1000_VMOLR_ROMPE); 535862306a36Sopenharmony_ci 535962306a36Sopenharmony_ci /* enable Rx jumbo frames, restrict as needed to support build_skb */ 536062306a36Sopenharmony_ci vmolr &= ~E1000_VMOLR_RLPML_MASK; 536162306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 536262306a36Sopenharmony_ci if (adapter->max_frame_size <= IGB_MAX_FRAME_BUILD_SKB) 536362306a36Sopenharmony_ci vmolr |= IGB_MAX_FRAME_BUILD_SKB; 536462306a36Sopenharmony_ci else 536562306a36Sopenharmony_ci#endif 536662306a36Sopenharmony_ci vmolr |= MAX_JUMBO_FRAME_SIZE; 536762306a36Sopenharmony_ci vmolr |= E1000_VMOLR_LPE; 536862306a36Sopenharmony_ci 536962306a36Sopenharmony_ci wr32(E1000_VMOLR(vfn), vmolr); 537062306a36Sopenharmony_ci 537162306a36Sopenharmony_ci igb_restore_vf_multicasts(adapter); 537262306a36Sopenharmony_ci} 537362306a36Sopenharmony_ci 537462306a36Sopenharmony_cistatic void igb_check_wvbr(struct igb_adapter *adapter) 537562306a36Sopenharmony_ci{ 537662306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 537762306a36Sopenharmony_ci u32 wvbr = 0; 537862306a36Sopenharmony_ci 537962306a36Sopenharmony_ci switch (hw->mac.type) { 538062306a36Sopenharmony_ci case e1000_82576: 538162306a36Sopenharmony_ci case e1000_i350: 538262306a36Sopenharmony_ci wvbr = rd32(E1000_WVBR); 538362306a36Sopenharmony_ci if (!wvbr) 538462306a36Sopenharmony_ci return; 538562306a36Sopenharmony_ci break; 538662306a36Sopenharmony_ci default: 538762306a36Sopenharmony_ci break; 538862306a36Sopenharmony_ci } 538962306a36Sopenharmony_ci 539062306a36Sopenharmony_ci adapter->wvbr |= wvbr; 539162306a36Sopenharmony_ci} 539262306a36Sopenharmony_ci 539362306a36Sopenharmony_ci#define IGB_STAGGERED_QUEUE_OFFSET 8 539462306a36Sopenharmony_ci 539562306a36Sopenharmony_cistatic void igb_spoof_check(struct igb_adapter *adapter) 539662306a36Sopenharmony_ci{ 539762306a36Sopenharmony_ci int j; 539862306a36Sopenharmony_ci 539962306a36Sopenharmony_ci if (!adapter->wvbr) 540062306a36Sopenharmony_ci return; 540162306a36Sopenharmony_ci 540262306a36Sopenharmony_ci for (j = 0; j < adapter->vfs_allocated_count; j++) { 540362306a36Sopenharmony_ci if (adapter->wvbr & BIT(j) || 540462306a36Sopenharmony_ci adapter->wvbr & BIT(j + IGB_STAGGERED_QUEUE_OFFSET)) { 540562306a36Sopenharmony_ci dev_warn(&adapter->pdev->dev, 540662306a36Sopenharmony_ci "Spoof event(s) detected on VF %d\n", j); 540762306a36Sopenharmony_ci adapter->wvbr &= 540862306a36Sopenharmony_ci ~(BIT(j) | 540962306a36Sopenharmony_ci BIT(j + IGB_STAGGERED_QUEUE_OFFSET)); 541062306a36Sopenharmony_ci } 541162306a36Sopenharmony_ci } 541262306a36Sopenharmony_ci} 541362306a36Sopenharmony_ci 541462306a36Sopenharmony_ci/* Need to wait a few seconds after link up to get diagnostic information from 541562306a36Sopenharmony_ci * the phy 541662306a36Sopenharmony_ci */ 541762306a36Sopenharmony_cistatic void igb_update_phy_info(struct timer_list *t) 541862306a36Sopenharmony_ci{ 541962306a36Sopenharmony_ci struct igb_adapter *adapter = from_timer(adapter, t, phy_info_timer); 542062306a36Sopenharmony_ci igb_get_phy_info(&adapter->hw); 542162306a36Sopenharmony_ci} 542262306a36Sopenharmony_ci 542362306a36Sopenharmony_ci/** 542462306a36Sopenharmony_ci * igb_has_link - check shared code for link and determine up/down 542562306a36Sopenharmony_ci * @adapter: pointer to driver private info 542662306a36Sopenharmony_ci **/ 542762306a36Sopenharmony_cibool igb_has_link(struct igb_adapter *adapter) 542862306a36Sopenharmony_ci{ 542962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 543062306a36Sopenharmony_ci bool link_active = false; 543162306a36Sopenharmony_ci 543262306a36Sopenharmony_ci /* get_link_status is set on LSC (link status) interrupt or 543362306a36Sopenharmony_ci * rx sequence error interrupt. get_link_status will stay 543462306a36Sopenharmony_ci * false until the e1000_check_for_link establishes link 543562306a36Sopenharmony_ci * for copper adapters ONLY 543662306a36Sopenharmony_ci */ 543762306a36Sopenharmony_ci switch (hw->phy.media_type) { 543862306a36Sopenharmony_ci case e1000_media_type_copper: 543962306a36Sopenharmony_ci if (!hw->mac.get_link_status) 544062306a36Sopenharmony_ci return true; 544162306a36Sopenharmony_ci fallthrough; 544262306a36Sopenharmony_ci case e1000_media_type_internal_serdes: 544362306a36Sopenharmony_ci hw->mac.ops.check_for_link(hw); 544462306a36Sopenharmony_ci link_active = !hw->mac.get_link_status; 544562306a36Sopenharmony_ci break; 544662306a36Sopenharmony_ci default: 544762306a36Sopenharmony_ci case e1000_media_type_unknown: 544862306a36Sopenharmony_ci break; 544962306a36Sopenharmony_ci } 545062306a36Sopenharmony_ci 545162306a36Sopenharmony_ci if (((hw->mac.type == e1000_i210) || 545262306a36Sopenharmony_ci (hw->mac.type == e1000_i211)) && 545362306a36Sopenharmony_ci (hw->phy.id == I210_I_PHY_ID)) { 545462306a36Sopenharmony_ci if (!netif_carrier_ok(adapter->netdev)) { 545562306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; 545662306a36Sopenharmony_ci } else if (!(adapter->flags & IGB_FLAG_NEED_LINK_UPDATE)) { 545762306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_NEED_LINK_UPDATE; 545862306a36Sopenharmony_ci adapter->link_check_timeout = jiffies; 545962306a36Sopenharmony_ci } 546062306a36Sopenharmony_ci } 546162306a36Sopenharmony_ci 546262306a36Sopenharmony_ci return link_active; 546362306a36Sopenharmony_ci} 546462306a36Sopenharmony_ci 546562306a36Sopenharmony_cistatic bool igb_thermal_sensor_event(struct e1000_hw *hw, u32 event) 546662306a36Sopenharmony_ci{ 546762306a36Sopenharmony_ci bool ret = false; 546862306a36Sopenharmony_ci u32 ctrl_ext, thstat; 546962306a36Sopenharmony_ci 547062306a36Sopenharmony_ci /* check for thermal sensor event on i350 copper only */ 547162306a36Sopenharmony_ci if (hw->mac.type == e1000_i350) { 547262306a36Sopenharmony_ci thstat = rd32(E1000_THSTAT); 547362306a36Sopenharmony_ci ctrl_ext = rd32(E1000_CTRL_EXT); 547462306a36Sopenharmony_ci 547562306a36Sopenharmony_ci if ((hw->phy.media_type == e1000_media_type_copper) && 547662306a36Sopenharmony_ci !(ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII)) 547762306a36Sopenharmony_ci ret = !!(thstat & event); 547862306a36Sopenharmony_ci } 547962306a36Sopenharmony_ci 548062306a36Sopenharmony_ci return ret; 548162306a36Sopenharmony_ci} 548262306a36Sopenharmony_ci 548362306a36Sopenharmony_ci/** 548462306a36Sopenharmony_ci * igb_check_lvmmc - check for malformed packets received 548562306a36Sopenharmony_ci * and indicated in LVMMC register 548662306a36Sopenharmony_ci * @adapter: pointer to adapter 548762306a36Sopenharmony_ci **/ 548862306a36Sopenharmony_cistatic void igb_check_lvmmc(struct igb_adapter *adapter) 548962306a36Sopenharmony_ci{ 549062306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 549162306a36Sopenharmony_ci u32 lvmmc; 549262306a36Sopenharmony_ci 549362306a36Sopenharmony_ci lvmmc = rd32(E1000_LVMMC); 549462306a36Sopenharmony_ci if (lvmmc) { 549562306a36Sopenharmony_ci if (unlikely(net_ratelimit())) { 549662306a36Sopenharmony_ci netdev_warn(adapter->netdev, 549762306a36Sopenharmony_ci "malformed Tx packet detected and dropped, LVMMC:0x%08x\n", 549862306a36Sopenharmony_ci lvmmc); 549962306a36Sopenharmony_ci } 550062306a36Sopenharmony_ci } 550162306a36Sopenharmony_ci} 550262306a36Sopenharmony_ci 550362306a36Sopenharmony_ci/** 550462306a36Sopenharmony_ci * igb_watchdog - Timer Call-back 550562306a36Sopenharmony_ci * @t: pointer to timer_list containing our private info pointer 550662306a36Sopenharmony_ci **/ 550762306a36Sopenharmony_cistatic void igb_watchdog(struct timer_list *t) 550862306a36Sopenharmony_ci{ 550962306a36Sopenharmony_ci struct igb_adapter *adapter = from_timer(adapter, t, watchdog_timer); 551062306a36Sopenharmony_ci /* Do the rest outside of interrupt context */ 551162306a36Sopenharmony_ci schedule_work(&adapter->watchdog_task); 551262306a36Sopenharmony_ci} 551362306a36Sopenharmony_ci 551462306a36Sopenharmony_cistatic void igb_watchdog_task(struct work_struct *work) 551562306a36Sopenharmony_ci{ 551662306a36Sopenharmony_ci struct igb_adapter *adapter = container_of(work, 551762306a36Sopenharmony_ci struct igb_adapter, 551862306a36Sopenharmony_ci watchdog_task); 551962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 552062306a36Sopenharmony_ci struct e1000_phy_info *phy = &hw->phy; 552162306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 552262306a36Sopenharmony_ci u32 link; 552362306a36Sopenharmony_ci int i; 552462306a36Sopenharmony_ci u32 connsw; 552562306a36Sopenharmony_ci u16 phy_data, retry_count = 20; 552662306a36Sopenharmony_ci 552762306a36Sopenharmony_ci link = igb_has_link(adapter); 552862306a36Sopenharmony_ci 552962306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) { 553062306a36Sopenharmony_ci if (time_after(jiffies, (adapter->link_check_timeout + HZ))) 553162306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; 553262306a36Sopenharmony_ci else 553362306a36Sopenharmony_ci link = false; 553462306a36Sopenharmony_ci } 553562306a36Sopenharmony_ci 553662306a36Sopenharmony_ci /* Force link down if we have fiber to swap to */ 553762306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_MAS_ENABLE) { 553862306a36Sopenharmony_ci if (hw->phy.media_type == e1000_media_type_copper) { 553962306a36Sopenharmony_ci connsw = rd32(E1000_CONNSW); 554062306a36Sopenharmony_ci if (!(connsw & E1000_CONNSW_AUTOSENSE_EN)) 554162306a36Sopenharmony_ci link = 0; 554262306a36Sopenharmony_ci } 554362306a36Sopenharmony_ci } 554462306a36Sopenharmony_ci if (link) { 554562306a36Sopenharmony_ci /* Perform a reset if the media type changed. */ 554662306a36Sopenharmony_ci if (hw->dev_spec._82575.media_changed) { 554762306a36Sopenharmony_ci hw->dev_spec._82575.media_changed = false; 554862306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_MEDIA_RESET; 554962306a36Sopenharmony_ci igb_reset(adapter); 555062306a36Sopenharmony_ci } 555162306a36Sopenharmony_ci /* Cancel scheduled suspend requests. */ 555262306a36Sopenharmony_ci pm_runtime_resume(netdev->dev.parent); 555362306a36Sopenharmony_ci 555462306a36Sopenharmony_ci if (!netif_carrier_ok(netdev)) { 555562306a36Sopenharmony_ci u32 ctrl; 555662306a36Sopenharmony_ci 555762306a36Sopenharmony_ci hw->mac.ops.get_speed_and_duplex(hw, 555862306a36Sopenharmony_ci &adapter->link_speed, 555962306a36Sopenharmony_ci &adapter->link_duplex); 556062306a36Sopenharmony_ci 556162306a36Sopenharmony_ci ctrl = rd32(E1000_CTRL); 556262306a36Sopenharmony_ci /* Links status message must follow this format */ 556362306a36Sopenharmony_ci netdev_info(netdev, 556462306a36Sopenharmony_ci "igb: %s NIC Link is Up %d Mbps %s Duplex, Flow Control: %s\n", 556562306a36Sopenharmony_ci netdev->name, 556662306a36Sopenharmony_ci adapter->link_speed, 556762306a36Sopenharmony_ci adapter->link_duplex == FULL_DUPLEX ? 556862306a36Sopenharmony_ci "Full" : "Half", 556962306a36Sopenharmony_ci (ctrl & E1000_CTRL_TFCE) && 557062306a36Sopenharmony_ci (ctrl & E1000_CTRL_RFCE) ? "RX/TX" : 557162306a36Sopenharmony_ci (ctrl & E1000_CTRL_RFCE) ? "RX" : 557262306a36Sopenharmony_ci (ctrl & E1000_CTRL_TFCE) ? "TX" : "None"); 557362306a36Sopenharmony_ci 557462306a36Sopenharmony_ci /* disable EEE if enabled */ 557562306a36Sopenharmony_ci if ((adapter->flags & IGB_FLAG_EEE) && 557662306a36Sopenharmony_ci (adapter->link_duplex == HALF_DUPLEX)) { 557762306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, 557862306a36Sopenharmony_ci "EEE Disabled: unsupported at half duplex. Re-enable using ethtool when at full duplex.\n"); 557962306a36Sopenharmony_ci adapter->hw.dev_spec._82575.eee_disable = true; 558062306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_EEE; 558162306a36Sopenharmony_ci } 558262306a36Sopenharmony_ci 558362306a36Sopenharmony_ci /* check if SmartSpeed worked */ 558462306a36Sopenharmony_ci igb_check_downshift(hw); 558562306a36Sopenharmony_ci if (phy->speed_downgraded) 558662306a36Sopenharmony_ci netdev_warn(netdev, "Link Speed was downgraded by SmartSpeed\n"); 558762306a36Sopenharmony_ci 558862306a36Sopenharmony_ci /* check for thermal sensor event */ 558962306a36Sopenharmony_ci if (igb_thermal_sensor_event(hw, 559062306a36Sopenharmony_ci E1000_THSTAT_LINK_THROTTLE)) 559162306a36Sopenharmony_ci netdev_info(netdev, "The network adapter link speed was downshifted because it overheated\n"); 559262306a36Sopenharmony_ci 559362306a36Sopenharmony_ci /* adjust timeout factor according to speed/duplex */ 559462306a36Sopenharmony_ci adapter->tx_timeout_factor = 1; 559562306a36Sopenharmony_ci switch (adapter->link_speed) { 559662306a36Sopenharmony_ci case SPEED_10: 559762306a36Sopenharmony_ci adapter->tx_timeout_factor = 14; 559862306a36Sopenharmony_ci break; 559962306a36Sopenharmony_ci case SPEED_100: 560062306a36Sopenharmony_ci /* maybe add some timeout factor ? */ 560162306a36Sopenharmony_ci break; 560262306a36Sopenharmony_ci } 560362306a36Sopenharmony_ci 560462306a36Sopenharmony_ci if (adapter->link_speed != SPEED_1000 || 560562306a36Sopenharmony_ci !hw->phy.ops.read_reg) 560662306a36Sopenharmony_ci goto no_wait; 560762306a36Sopenharmony_ci 560862306a36Sopenharmony_ci /* wait for Remote receiver status OK */ 560962306a36Sopenharmony_ciretry_read_status: 561062306a36Sopenharmony_ci if (!igb_read_phy_reg(hw, PHY_1000T_STATUS, 561162306a36Sopenharmony_ci &phy_data)) { 561262306a36Sopenharmony_ci if (!(phy_data & SR_1000T_REMOTE_RX_STATUS) && 561362306a36Sopenharmony_ci retry_count) { 561462306a36Sopenharmony_ci msleep(100); 561562306a36Sopenharmony_ci retry_count--; 561662306a36Sopenharmony_ci goto retry_read_status; 561762306a36Sopenharmony_ci } else if (!retry_count) { 561862306a36Sopenharmony_ci dev_err(&adapter->pdev->dev, "exceed max 2 second\n"); 561962306a36Sopenharmony_ci } 562062306a36Sopenharmony_ci } else { 562162306a36Sopenharmony_ci dev_err(&adapter->pdev->dev, "read 1000Base-T Status Reg\n"); 562262306a36Sopenharmony_ci } 562362306a36Sopenharmony_cino_wait: 562462306a36Sopenharmony_ci netif_carrier_on(netdev); 562562306a36Sopenharmony_ci 562662306a36Sopenharmony_ci igb_ping_all_vfs(adapter); 562762306a36Sopenharmony_ci igb_check_vf_rate_limit(adapter); 562862306a36Sopenharmony_ci 562962306a36Sopenharmony_ci /* link state has changed, schedule phy info update */ 563062306a36Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) 563162306a36Sopenharmony_ci mod_timer(&adapter->phy_info_timer, 563262306a36Sopenharmony_ci round_jiffies(jiffies + 2 * HZ)); 563362306a36Sopenharmony_ci } 563462306a36Sopenharmony_ci } else { 563562306a36Sopenharmony_ci if (netif_carrier_ok(netdev)) { 563662306a36Sopenharmony_ci adapter->link_speed = 0; 563762306a36Sopenharmony_ci adapter->link_duplex = 0; 563862306a36Sopenharmony_ci 563962306a36Sopenharmony_ci /* check for thermal sensor event */ 564062306a36Sopenharmony_ci if (igb_thermal_sensor_event(hw, 564162306a36Sopenharmony_ci E1000_THSTAT_PWR_DOWN)) { 564262306a36Sopenharmony_ci netdev_err(netdev, "The network adapter was stopped because it overheated\n"); 564362306a36Sopenharmony_ci } 564462306a36Sopenharmony_ci 564562306a36Sopenharmony_ci /* Links status message must follow this format */ 564662306a36Sopenharmony_ci netdev_info(netdev, "igb: %s NIC Link is Down\n", 564762306a36Sopenharmony_ci netdev->name); 564862306a36Sopenharmony_ci netif_carrier_off(netdev); 564962306a36Sopenharmony_ci 565062306a36Sopenharmony_ci igb_ping_all_vfs(adapter); 565162306a36Sopenharmony_ci 565262306a36Sopenharmony_ci /* link state has changed, schedule phy info update */ 565362306a36Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) 565462306a36Sopenharmony_ci mod_timer(&adapter->phy_info_timer, 565562306a36Sopenharmony_ci round_jiffies(jiffies + 2 * HZ)); 565662306a36Sopenharmony_ci 565762306a36Sopenharmony_ci /* link is down, time to check for alternate media */ 565862306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_MAS_ENABLE) { 565962306a36Sopenharmony_ci igb_check_swap_media(adapter); 566062306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_MEDIA_RESET) { 566162306a36Sopenharmony_ci schedule_work(&adapter->reset_task); 566262306a36Sopenharmony_ci /* return immediately */ 566362306a36Sopenharmony_ci return; 566462306a36Sopenharmony_ci } 566562306a36Sopenharmony_ci } 566662306a36Sopenharmony_ci pm_schedule_suspend(netdev->dev.parent, 566762306a36Sopenharmony_ci MSEC_PER_SEC * 5); 566862306a36Sopenharmony_ci 566962306a36Sopenharmony_ci /* also check for alternate media here */ 567062306a36Sopenharmony_ci } else if (!netif_carrier_ok(netdev) && 567162306a36Sopenharmony_ci (adapter->flags & IGB_FLAG_MAS_ENABLE)) { 567262306a36Sopenharmony_ci igb_check_swap_media(adapter); 567362306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_MEDIA_RESET) { 567462306a36Sopenharmony_ci schedule_work(&adapter->reset_task); 567562306a36Sopenharmony_ci /* return immediately */ 567662306a36Sopenharmony_ci return; 567762306a36Sopenharmony_ci } 567862306a36Sopenharmony_ci } 567962306a36Sopenharmony_ci } 568062306a36Sopenharmony_ci 568162306a36Sopenharmony_ci spin_lock(&adapter->stats64_lock); 568262306a36Sopenharmony_ci igb_update_stats(adapter); 568362306a36Sopenharmony_ci spin_unlock(&adapter->stats64_lock); 568462306a36Sopenharmony_ci 568562306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 568662306a36Sopenharmony_ci struct igb_ring *tx_ring = adapter->tx_ring[i]; 568762306a36Sopenharmony_ci if (!netif_carrier_ok(netdev)) { 568862306a36Sopenharmony_ci /* We've lost link, so the controller stops DMA, 568962306a36Sopenharmony_ci * but we've got queued Tx work that's never going 569062306a36Sopenharmony_ci * to get done, so reset controller to flush Tx. 569162306a36Sopenharmony_ci * (Do the reset outside of interrupt context). 569262306a36Sopenharmony_ci */ 569362306a36Sopenharmony_ci if (igb_desc_unused(tx_ring) + 1 < tx_ring->count) { 569462306a36Sopenharmony_ci adapter->tx_timeout_count++; 569562306a36Sopenharmony_ci schedule_work(&adapter->reset_task); 569662306a36Sopenharmony_ci /* return immediately since reset is imminent */ 569762306a36Sopenharmony_ci return; 569862306a36Sopenharmony_ci } 569962306a36Sopenharmony_ci } 570062306a36Sopenharmony_ci 570162306a36Sopenharmony_ci /* Force detection of hung controller every watchdog period */ 570262306a36Sopenharmony_ci set_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); 570362306a36Sopenharmony_ci } 570462306a36Sopenharmony_ci 570562306a36Sopenharmony_ci /* Cause software interrupt to ensure Rx ring is cleaned */ 570662306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) { 570762306a36Sopenharmony_ci u32 eics = 0; 570862306a36Sopenharmony_ci 570962306a36Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) 571062306a36Sopenharmony_ci eics |= adapter->q_vector[i]->eims_value; 571162306a36Sopenharmony_ci wr32(E1000_EICS, eics); 571262306a36Sopenharmony_ci } else { 571362306a36Sopenharmony_ci wr32(E1000_ICS, E1000_ICS_RXDMT0); 571462306a36Sopenharmony_ci } 571562306a36Sopenharmony_ci 571662306a36Sopenharmony_ci igb_spoof_check(adapter); 571762306a36Sopenharmony_ci igb_ptp_rx_hang(adapter); 571862306a36Sopenharmony_ci igb_ptp_tx_hang(adapter); 571962306a36Sopenharmony_ci 572062306a36Sopenharmony_ci /* Check LVMMC register on i350/i354 only */ 572162306a36Sopenharmony_ci if ((adapter->hw.mac.type == e1000_i350) || 572262306a36Sopenharmony_ci (adapter->hw.mac.type == e1000_i354)) 572362306a36Sopenharmony_ci igb_check_lvmmc(adapter); 572462306a36Sopenharmony_ci 572562306a36Sopenharmony_ci /* Reset the timer */ 572662306a36Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) { 572762306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) 572862306a36Sopenharmony_ci mod_timer(&adapter->watchdog_timer, 572962306a36Sopenharmony_ci round_jiffies(jiffies + HZ)); 573062306a36Sopenharmony_ci else 573162306a36Sopenharmony_ci mod_timer(&adapter->watchdog_timer, 573262306a36Sopenharmony_ci round_jiffies(jiffies + 2 * HZ)); 573362306a36Sopenharmony_ci } 573462306a36Sopenharmony_ci} 573562306a36Sopenharmony_ci 573662306a36Sopenharmony_cienum latency_range { 573762306a36Sopenharmony_ci lowest_latency = 0, 573862306a36Sopenharmony_ci low_latency = 1, 573962306a36Sopenharmony_ci bulk_latency = 2, 574062306a36Sopenharmony_ci latency_invalid = 255 574162306a36Sopenharmony_ci}; 574262306a36Sopenharmony_ci 574362306a36Sopenharmony_ci/** 574462306a36Sopenharmony_ci * igb_update_ring_itr - update the dynamic ITR value based on packet size 574562306a36Sopenharmony_ci * @q_vector: pointer to q_vector 574662306a36Sopenharmony_ci * 574762306a36Sopenharmony_ci * Stores a new ITR value based on strictly on packet size. This 574862306a36Sopenharmony_ci * algorithm is less sophisticated than that used in igb_update_itr, 574962306a36Sopenharmony_ci * due to the difficulty of synchronizing statistics across multiple 575062306a36Sopenharmony_ci * receive rings. The divisors and thresholds used by this function 575162306a36Sopenharmony_ci * were determined based on theoretical maximum wire speed and testing 575262306a36Sopenharmony_ci * data, in order to minimize response time while increasing bulk 575362306a36Sopenharmony_ci * throughput. 575462306a36Sopenharmony_ci * This functionality is controlled by ethtool's coalescing settings. 575562306a36Sopenharmony_ci * NOTE: This function is called only when operating in a multiqueue 575662306a36Sopenharmony_ci * receive environment. 575762306a36Sopenharmony_ci **/ 575862306a36Sopenharmony_cistatic void igb_update_ring_itr(struct igb_q_vector *q_vector) 575962306a36Sopenharmony_ci{ 576062306a36Sopenharmony_ci int new_val = q_vector->itr_val; 576162306a36Sopenharmony_ci int avg_wire_size = 0; 576262306a36Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 576362306a36Sopenharmony_ci unsigned int packets; 576462306a36Sopenharmony_ci 576562306a36Sopenharmony_ci /* For non-gigabit speeds, just fix the interrupt rate at 4000 576662306a36Sopenharmony_ci * ints/sec - ITR timer value of 120 ticks. 576762306a36Sopenharmony_ci */ 576862306a36Sopenharmony_ci if (adapter->link_speed != SPEED_1000) { 576962306a36Sopenharmony_ci new_val = IGB_4K_ITR; 577062306a36Sopenharmony_ci goto set_itr_val; 577162306a36Sopenharmony_ci } 577262306a36Sopenharmony_ci 577362306a36Sopenharmony_ci packets = q_vector->rx.total_packets; 577462306a36Sopenharmony_ci if (packets) 577562306a36Sopenharmony_ci avg_wire_size = q_vector->rx.total_bytes / packets; 577662306a36Sopenharmony_ci 577762306a36Sopenharmony_ci packets = q_vector->tx.total_packets; 577862306a36Sopenharmony_ci if (packets) 577962306a36Sopenharmony_ci avg_wire_size = max_t(u32, avg_wire_size, 578062306a36Sopenharmony_ci q_vector->tx.total_bytes / packets); 578162306a36Sopenharmony_ci 578262306a36Sopenharmony_ci /* if avg_wire_size isn't set no work was done */ 578362306a36Sopenharmony_ci if (!avg_wire_size) 578462306a36Sopenharmony_ci goto clear_counts; 578562306a36Sopenharmony_ci 578662306a36Sopenharmony_ci /* Add 24 bytes to size to account for CRC, preamble, and gap */ 578762306a36Sopenharmony_ci avg_wire_size += 24; 578862306a36Sopenharmony_ci 578962306a36Sopenharmony_ci /* Don't starve jumbo frames */ 579062306a36Sopenharmony_ci avg_wire_size = min(avg_wire_size, 3000); 579162306a36Sopenharmony_ci 579262306a36Sopenharmony_ci /* Give a little boost to mid-size frames */ 579362306a36Sopenharmony_ci if ((avg_wire_size > 300) && (avg_wire_size < 1200)) 579462306a36Sopenharmony_ci new_val = avg_wire_size / 3; 579562306a36Sopenharmony_ci else 579662306a36Sopenharmony_ci new_val = avg_wire_size / 2; 579762306a36Sopenharmony_ci 579862306a36Sopenharmony_ci /* conservative mode (itr 3) eliminates the lowest_latency setting */ 579962306a36Sopenharmony_ci if (new_val < IGB_20K_ITR && 580062306a36Sopenharmony_ci ((q_vector->rx.ring && adapter->rx_itr_setting == 3) || 580162306a36Sopenharmony_ci (!q_vector->rx.ring && adapter->tx_itr_setting == 3))) 580262306a36Sopenharmony_ci new_val = IGB_20K_ITR; 580362306a36Sopenharmony_ci 580462306a36Sopenharmony_ciset_itr_val: 580562306a36Sopenharmony_ci if (new_val != q_vector->itr_val) { 580662306a36Sopenharmony_ci q_vector->itr_val = new_val; 580762306a36Sopenharmony_ci q_vector->set_itr = 1; 580862306a36Sopenharmony_ci } 580962306a36Sopenharmony_ciclear_counts: 581062306a36Sopenharmony_ci q_vector->rx.total_bytes = 0; 581162306a36Sopenharmony_ci q_vector->rx.total_packets = 0; 581262306a36Sopenharmony_ci q_vector->tx.total_bytes = 0; 581362306a36Sopenharmony_ci q_vector->tx.total_packets = 0; 581462306a36Sopenharmony_ci} 581562306a36Sopenharmony_ci 581662306a36Sopenharmony_ci/** 581762306a36Sopenharmony_ci * igb_update_itr - update the dynamic ITR value based on statistics 581862306a36Sopenharmony_ci * @q_vector: pointer to q_vector 581962306a36Sopenharmony_ci * @ring_container: ring info to update the itr for 582062306a36Sopenharmony_ci * 582162306a36Sopenharmony_ci * Stores a new ITR value based on packets and byte 582262306a36Sopenharmony_ci * counts during the last interrupt. The advantage of per interrupt 582362306a36Sopenharmony_ci * computation is faster updates and more accurate ITR for the current 582462306a36Sopenharmony_ci * traffic pattern. Constants in this function were computed 582562306a36Sopenharmony_ci * based on theoretical maximum wire speed and thresholds were set based 582662306a36Sopenharmony_ci * on testing data as well as attempting to minimize response time 582762306a36Sopenharmony_ci * while increasing bulk throughput. 582862306a36Sopenharmony_ci * This functionality is controlled by ethtool's coalescing settings. 582962306a36Sopenharmony_ci * NOTE: These calculations are only valid when operating in a single- 583062306a36Sopenharmony_ci * queue environment. 583162306a36Sopenharmony_ci **/ 583262306a36Sopenharmony_cistatic void igb_update_itr(struct igb_q_vector *q_vector, 583362306a36Sopenharmony_ci struct igb_ring_container *ring_container) 583462306a36Sopenharmony_ci{ 583562306a36Sopenharmony_ci unsigned int packets = ring_container->total_packets; 583662306a36Sopenharmony_ci unsigned int bytes = ring_container->total_bytes; 583762306a36Sopenharmony_ci u8 itrval = ring_container->itr; 583862306a36Sopenharmony_ci 583962306a36Sopenharmony_ci /* no packets, exit with status unchanged */ 584062306a36Sopenharmony_ci if (packets == 0) 584162306a36Sopenharmony_ci return; 584262306a36Sopenharmony_ci 584362306a36Sopenharmony_ci switch (itrval) { 584462306a36Sopenharmony_ci case lowest_latency: 584562306a36Sopenharmony_ci /* handle TSO and jumbo frames */ 584662306a36Sopenharmony_ci if (bytes/packets > 8000) 584762306a36Sopenharmony_ci itrval = bulk_latency; 584862306a36Sopenharmony_ci else if ((packets < 5) && (bytes > 512)) 584962306a36Sopenharmony_ci itrval = low_latency; 585062306a36Sopenharmony_ci break; 585162306a36Sopenharmony_ci case low_latency: /* 50 usec aka 20000 ints/s */ 585262306a36Sopenharmony_ci if (bytes > 10000) { 585362306a36Sopenharmony_ci /* this if handles the TSO accounting */ 585462306a36Sopenharmony_ci if (bytes/packets > 8000) 585562306a36Sopenharmony_ci itrval = bulk_latency; 585662306a36Sopenharmony_ci else if ((packets < 10) || ((bytes/packets) > 1200)) 585762306a36Sopenharmony_ci itrval = bulk_latency; 585862306a36Sopenharmony_ci else if ((packets > 35)) 585962306a36Sopenharmony_ci itrval = lowest_latency; 586062306a36Sopenharmony_ci } else if (bytes/packets > 2000) { 586162306a36Sopenharmony_ci itrval = bulk_latency; 586262306a36Sopenharmony_ci } else if (packets <= 2 && bytes < 512) { 586362306a36Sopenharmony_ci itrval = lowest_latency; 586462306a36Sopenharmony_ci } 586562306a36Sopenharmony_ci break; 586662306a36Sopenharmony_ci case bulk_latency: /* 250 usec aka 4000 ints/s */ 586762306a36Sopenharmony_ci if (bytes > 25000) { 586862306a36Sopenharmony_ci if (packets > 35) 586962306a36Sopenharmony_ci itrval = low_latency; 587062306a36Sopenharmony_ci } else if (bytes < 1500) { 587162306a36Sopenharmony_ci itrval = low_latency; 587262306a36Sopenharmony_ci } 587362306a36Sopenharmony_ci break; 587462306a36Sopenharmony_ci } 587562306a36Sopenharmony_ci 587662306a36Sopenharmony_ci /* clear work counters since we have the values we need */ 587762306a36Sopenharmony_ci ring_container->total_bytes = 0; 587862306a36Sopenharmony_ci ring_container->total_packets = 0; 587962306a36Sopenharmony_ci 588062306a36Sopenharmony_ci /* write updated itr to ring container */ 588162306a36Sopenharmony_ci ring_container->itr = itrval; 588262306a36Sopenharmony_ci} 588362306a36Sopenharmony_ci 588462306a36Sopenharmony_cistatic void igb_set_itr(struct igb_q_vector *q_vector) 588562306a36Sopenharmony_ci{ 588662306a36Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 588762306a36Sopenharmony_ci u32 new_itr = q_vector->itr_val; 588862306a36Sopenharmony_ci u8 current_itr = 0; 588962306a36Sopenharmony_ci 589062306a36Sopenharmony_ci /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ 589162306a36Sopenharmony_ci if (adapter->link_speed != SPEED_1000) { 589262306a36Sopenharmony_ci current_itr = 0; 589362306a36Sopenharmony_ci new_itr = IGB_4K_ITR; 589462306a36Sopenharmony_ci goto set_itr_now; 589562306a36Sopenharmony_ci } 589662306a36Sopenharmony_ci 589762306a36Sopenharmony_ci igb_update_itr(q_vector, &q_vector->tx); 589862306a36Sopenharmony_ci igb_update_itr(q_vector, &q_vector->rx); 589962306a36Sopenharmony_ci 590062306a36Sopenharmony_ci current_itr = max(q_vector->rx.itr, q_vector->tx.itr); 590162306a36Sopenharmony_ci 590262306a36Sopenharmony_ci /* conservative mode (itr 3) eliminates the lowest_latency setting */ 590362306a36Sopenharmony_ci if (current_itr == lowest_latency && 590462306a36Sopenharmony_ci ((q_vector->rx.ring && adapter->rx_itr_setting == 3) || 590562306a36Sopenharmony_ci (!q_vector->rx.ring && adapter->tx_itr_setting == 3))) 590662306a36Sopenharmony_ci current_itr = low_latency; 590762306a36Sopenharmony_ci 590862306a36Sopenharmony_ci switch (current_itr) { 590962306a36Sopenharmony_ci /* counts and packets in update_itr are dependent on these numbers */ 591062306a36Sopenharmony_ci case lowest_latency: 591162306a36Sopenharmony_ci new_itr = IGB_70K_ITR; /* 70,000 ints/sec */ 591262306a36Sopenharmony_ci break; 591362306a36Sopenharmony_ci case low_latency: 591462306a36Sopenharmony_ci new_itr = IGB_20K_ITR; /* 20,000 ints/sec */ 591562306a36Sopenharmony_ci break; 591662306a36Sopenharmony_ci case bulk_latency: 591762306a36Sopenharmony_ci new_itr = IGB_4K_ITR; /* 4,000 ints/sec */ 591862306a36Sopenharmony_ci break; 591962306a36Sopenharmony_ci default: 592062306a36Sopenharmony_ci break; 592162306a36Sopenharmony_ci } 592262306a36Sopenharmony_ci 592362306a36Sopenharmony_ciset_itr_now: 592462306a36Sopenharmony_ci if (new_itr != q_vector->itr_val) { 592562306a36Sopenharmony_ci /* this attempts to bias the interrupt rate towards Bulk 592662306a36Sopenharmony_ci * by adding intermediate steps when interrupt rate is 592762306a36Sopenharmony_ci * increasing 592862306a36Sopenharmony_ci */ 592962306a36Sopenharmony_ci new_itr = new_itr > q_vector->itr_val ? 593062306a36Sopenharmony_ci max((new_itr * q_vector->itr_val) / 593162306a36Sopenharmony_ci (new_itr + (q_vector->itr_val >> 2)), 593262306a36Sopenharmony_ci new_itr) : new_itr; 593362306a36Sopenharmony_ci /* Don't write the value here; it resets the adapter's 593462306a36Sopenharmony_ci * internal timer, and causes us to delay far longer than 593562306a36Sopenharmony_ci * we should between interrupts. Instead, we write the ITR 593662306a36Sopenharmony_ci * value at the beginning of the next interrupt so the timing 593762306a36Sopenharmony_ci * ends up being correct. 593862306a36Sopenharmony_ci */ 593962306a36Sopenharmony_ci q_vector->itr_val = new_itr; 594062306a36Sopenharmony_ci q_vector->set_itr = 1; 594162306a36Sopenharmony_ci } 594262306a36Sopenharmony_ci} 594362306a36Sopenharmony_ci 594462306a36Sopenharmony_cistatic void igb_tx_ctxtdesc(struct igb_ring *tx_ring, 594562306a36Sopenharmony_ci struct igb_tx_buffer *first, 594662306a36Sopenharmony_ci u32 vlan_macip_lens, u32 type_tucmd, 594762306a36Sopenharmony_ci u32 mss_l4len_idx) 594862306a36Sopenharmony_ci{ 594962306a36Sopenharmony_ci struct e1000_adv_tx_context_desc *context_desc; 595062306a36Sopenharmony_ci u16 i = tx_ring->next_to_use; 595162306a36Sopenharmony_ci struct timespec64 ts; 595262306a36Sopenharmony_ci 595362306a36Sopenharmony_ci context_desc = IGB_TX_CTXTDESC(tx_ring, i); 595462306a36Sopenharmony_ci 595562306a36Sopenharmony_ci i++; 595662306a36Sopenharmony_ci tx_ring->next_to_use = (i < tx_ring->count) ? i : 0; 595762306a36Sopenharmony_ci 595862306a36Sopenharmony_ci /* set bits to identify this as an advanced context descriptor */ 595962306a36Sopenharmony_ci type_tucmd |= E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT; 596062306a36Sopenharmony_ci 596162306a36Sopenharmony_ci /* For 82575, context index must be unique per ring. */ 596262306a36Sopenharmony_ci if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) 596362306a36Sopenharmony_ci mss_l4len_idx |= tx_ring->reg_idx << 4; 596462306a36Sopenharmony_ci 596562306a36Sopenharmony_ci context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); 596662306a36Sopenharmony_ci context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); 596762306a36Sopenharmony_ci context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); 596862306a36Sopenharmony_ci 596962306a36Sopenharmony_ci /* We assume there is always a valid tx time available. Invalid times 597062306a36Sopenharmony_ci * should have been handled by the upper layers. 597162306a36Sopenharmony_ci */ 597262306a36Sopenharmony_ci if (tx_ring->launchtime_enable) { 597362306a36Sopenharmony_ci ts = ktime_to_timespec64(first->skb->tstamp); 597462306a36Sopenharmony_ci skb_txtime_consumed(first->skb); 597562306a36Sopenharmony_ci context_desc->seqnum_seed = cpu_to_le32(ts.tv_nsec / 32); 597662306a36Sopenharmony_ci } else { 597762306a36Sopenharmony_ci context_desc->seqnum_seed = 0; 597862306a36Sopenharmony_ci } 597962306a36Sopenharmony_ci} 598062306a36Sopenharmony_ci 598162306a36Sopenharmony_cistatic int igb_tso(struct igb_ring *tx_ring, 598262306a36Sopenharmony_ci struct igb_tx_buffer *first, 598362306a36Sopenharmony_ci u8 *hdr_len) 598462306a36Sopenharmony_ci{ 598562306a36Sopenharmony_ci u32 vlan_macip_lens, type_tucmd, mss_l4len_idx; 598662306a36Sopenharmony_ci struct sk_buff *skb = first->skb; 598762306a36Sopenharmony_ci union { 598862306a36Sopenharmony_ci struct iphdr *v4; 598962306a36Sopenharmony_ci struct ipv6hdr *v6; 599062306a36Sopenharmony_ci unsigned char *hdr; 599162306a36Sopenharmony_ci } ip; 599262306a36Sopenharmony_ci union { 599362306a36Sopenharmony_ci struct tcphdr *tcp; 599462306a36Sopenharmony_ci struct udphdr *udp; 599562306a36Sopenharmony_ci unsigned char *hdr; 599662306a36Sopenharmony_ci } l4; 599762306a36Sopenharmony_ci u32 paylen, l4_offset; 599862306a36Sopenharmony_ci int err; 599962306a36Sopenharmony_ci 600062306a36Sopenharmony_ci if (skb->ip_summed != CHECKSUM_PARTIAL) 600162306a36Sopenharmony_ci return 0; 600262306a36Sopenharmony_ci 600362306a36Sopenharmony_ci if (!skb_is_gso(skb)) 600462306a36Sopenharmony_ci return 0; 600562306a36Sopenharmony_ci 600662306a36Sopenharmony_ci err = skb_cow_head(skb, 0); 600762306a36Sopenharmony_ci if (err < 0) 600862306a36Sopenharmony_ci return err; 600962306a36Sopenharmony_ci 601062306a36Sopenharmony_ci ip.hdr = skb_network_header(skb); 601162306a36Sopenharmony_ci l4.hdr = skb_checksum_start(skb); 601262306a36Sopenharmony_ci 601362306a36Sopenharmony_ci /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ 601462306a36Sopenharmony_ci type_tucmd = (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ? 601562306a36Sopenharmony_ci E1000_ADVTXD_TUCMD_L4T_UDP : E1000_ADVTXD_TUCMD_L4T_TCP; 601662306a36Sopenharmony_ci 601762306a36Sopenharmony_ci /* initialize outer IP header fields */ 601862306a36Sopenharmony_ci if (ip.v4->version == 4) { 601962306a36Sopenharmony_ci unsigned char *csum_start = skb_checksum_start(skb); 602062306a36Sopenharmony_ci unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4); 602162306a36Sopenharmony_ci 602262306a36Sopenharmony_ci /* IP header will have to cancel out any data that 602362306a36Sopenharmony_ci * is not a part of the outer IP header 602462306a36Sopenharmony_ci */ 602562306a36Sopenharmony_ci ip.v4->check = csum_fold(csum_partial(trans_start, 602662306a36Sopenharmony_ci csum_start - trans_start, 602762306a36Sopenharmony_ci 0)); 602862306a36Sopenharmony_ci type_tucmd |= E1000_ADVTXD_TUCMD_IPV4; 602962306a36Sopenharmony_ci 603062306a36Sopenharmony_ci ip.v4->tot_len = 0; 603162306a36Sopenharmony_ci first->tx_flags |= IGB_TX_FLAGS_TSO | 603262306a36Sopenharmony_ci IGB_TX_FLAGS_CSUM | 603362306a36Sopenharmony_ci IGB_TX_FLAGS_IPV4; 603462306a36Sopenharmony_ci } else { 603562306a36Sopenharmony_ci ip.v6->payload_len = 0; 603662306a36Sopenharmony_ci first->tx_flags |= IGB_TX_FLAGS_TSO | 603762306a36Sopenharmony_ci IGB_TX_FLAGS_CSUM; 603862306a36Sopenharmony_ci } 603962306a36Sopenharmony_ci 604062306a36Sopenharmony_ci /* determine offset of inner transport header */ 604162306a36Sopenharmony_ci l4_offset = l4.hdr - skb->data; 604262306a36Sopenharmony_ci 604362306a36Sopenharmony_ci /* remove payload length from inner checksum */ 604462306a36Sopenharmony_ci paylen = skb->len - l4_offset; 604562306a36Sopenharmony_ci if (type_tucmd & E1000_ADVTXD_TUCMD_L4T_TCP) { 604662306a36Sopenharmony_ci /* compute length of segmentation header */ 604762306a36Sopenharmony_ci *hdr_len = (l4.tcp->doff * 4) + l4_offset; 604862306a36Sopenharmony_ci csum_replace_by_diff(&l4.tcp->check, 604962306a36Sopenharmony_ci (__force __wsum)htonl(paylen)); 605062306a36Sopenharmony_ci } else { 605162306a36Sopenharmony_ci /* compute length of segmentation header */ 605262306a36Sopenharmony_ci *hdr_len = sizeof(*l4.udp) + l4_offset; 605362306a36Sopenharmony_ci csum_replace_by_diff(&l4.udp->check, 605462306a36Sopenharmony_ci (__force __wsum)htonl(paylen)); 605562306a36Sopenharmony_ci } 605662306a36Sopenharmony_ci 605762306a36Sopenharmony_ci /* update gso size and bytecount with header size */ 605862306a36Sopenharmony_ci first->gso_segs = skb_shinfo(skb)->gso_segs; 605962306a36Sopenharmony_ci first->bytecount += (first->gso_segs - 1) * *hdr_len; 606062306a36Sopenharmony_ci 606162306a36Sopenharmony_ci /* MSS L4LEN IDX */ 606262306a36Sopenharmony_ci mss_l4len_idx = (*hdr_len - l4_offset) << E1000_ADVTXD_L4LEN_SHIFT; 606362306a36Sopenharmony_ci mss_l4len_idx |= skb_shinfo(skb)->gso_size << E1000_ADVTXD_MSS_SHIFT; 606462306a36Sopenharmony_ci 606562306a36Sopenharmony_ci /* VLAN MACLEN IPLEN */ 606662306a36Sopenharmony_ci vlan_macip_lens = l4.hdr - ip.hdr; 606762306a36Sopenharmony_ci vlan_macip_lens |= (ip.hdr - skb->data) << E1000_ADVTXD_MACLEN_SHIFT; 606862306a36Sopenharmony_ci vlan_macip_lens |= first->tx_flags & IGB_TX_FLAGS_VLAN_MASK; 606962306a36Sopenharmony_ci 607062306a36Sopenharmony_ci igb_tx_ctxtdesc(tx_ring, first, vlan_macip_lens, 607162306a36Sopenharmony_ci type_tucmd, mss_l4len_idx); 607262306a36Sopenharmony_ci 607362306a36Sopenharmony_ci return 1; 607462306a36Sopenharmony_ci} 607562306a36Sopenharmony_ci 607662306a36Sopenharmony_cistatic void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first) 607762306a36Sopenharmony_ci{ 607862306a36Sopenharmony_ci struct sk_buff *skb = first->skb; 607962306a36Sopenharmony_ci u32 vlan_macip_lens = 0; 608062306a36Sopenharmony_ci u32 type_tucmd = 0; 608162306a36Sopenharmony_ci 608262306a36Sopenharmony_ci if (skb->ip_summed != CHECKSUM_PARTIAL) { 608362306a36Sopenharmony_cicsum_failed: 608462306a36Sopenharmony_ci if (!(first->tx_flags & IGB_TX_FLAGS_VLAN) && 608562306a36Sopenharmony_ci !tx_ring->launchtime_enable) 608662306a36Sopenharmony_ci return; 608762306a36Sopenharmony_ci goto no_csum; 608862306a36Sopenharmony_ci } 608962306a36Sopenharmony_ci 609062306a36Sopenharmony_ci switch (skb->csum_offset) { 609162306a36Sopenharmony_ci case offsetof(struct tcphdr, check): 609262306a36Sopenharmony_ci type_tucmd = E1000_ADVTXD_TUCMD_L4T_TCP; 609362306a36Sopenharmony_ci fallthrough; 609462306a36Sopenharmony_ci case offsetof(struct udphdr, check): 609562306a36Sopenharmony_ci break; 609662306a36Sopenharmony_ci case offsetof(struct sctphdr, checksum): 609762306a36Sopenharmony_ci /* validate that this is actually an SCTP request */ 609862306a36Sopenharmony_ci if (skb_csum_is_sctp(skb)) { 609962306a36Sopenharmony_ci type_tucmd = E1000_ADVTXD_TUCMD_L4T_SCTP; 610062306a36Sopenharmony_ci break; 610162306a36Sopenharmony_ci } 610262306a36Sopenharmony_ci fallthrough; 610362306a36Sopenharmony_ci default: 610462306a36Sopenharmony_ci skb_checksum_help(skb); 610562306a36Sopenharmony_ci goto csum_failed; 610662306a36Sopenharmony_ci } 610762306a36Sopenharmony_ci 610862306a36Sopenharmony_ci /* update TX checksum flag */ 610962306a36Sopenharmony_ci first->tx_flags |= IGB_TX_FLAGS_CSUM; 611062306a36Sopenharmony_ci vlan_macip_lens = skb_checksum_start_offset(skb) - 611162306a36Sopenharmony_ci skb_network_offset(skb); 611262306a36Sopenharmony_cino_csum: 611362306a36Sopenharmony_ci vlan_macip_lens |= skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT; 611462306a36Sopenharmony_ci vlan_macip_lens |= first->tx_flags & IGB_TX_FLAGS_VLAN_MASK; 611562306a36Sopenharmony_ci 611662306a36Sopenharmony_ci igb_tx_ctxtdesc(tx_ring, first, vlan_macip_lens, type_tucmd, 0); 611762306a36Sopenharmony_ci} 611862306a36Sopenharmony_ci 611962306a36Sopenharmony_ci#define IGB_SET_FLAG(_input, _flag, _result) \ 612062306a36Sopenharmony_ci ((_flag <= _result) ? \ 612162306a36Sopenharmony_ci ((u32)(_input & _flag) * (_result / _flag)) : \ 612262306a36Sopenharmony_ci ((u32)(_input & _flag) / (_flag / _result))) 612362306a36Sopenharmony_ci 612462306a36Sopenharmony_cistatic u32 igb_tx_cmd_type(struct sk_buff *skb, u32 tx_flags) 612562306a36Sopenharmony_ci{ 612662306a36Sopenharmony_ci /* set type for advanced descriptor with frame checksum insertion */ 612762306a36Sopenharmony_ci u32 cmd_type = E1000_ADVTXD_DTYP_DATA | 612862306a36Sopenharmony_ci E1000_ADVTXD_DCMD_DEXT | 612962306a36Sopenharmony_ci E1000_ADVTXD_DCMD_IFCS; 613062306a36Sopenharmony_ci 613162306a36Sopenharmony_ci /* set HW vlan bit if vlan is present */ 613262306a36Sopenharmony_ci cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_VLAN, 613362306a36Sopenharmony_ci (E1000_ADVTXD_DCMD_VLE)); 613462306a36Sopenharmony_ci 613562306a36Sopenharmony_ci /* set segmentation bits for TSO */ 613662306a36Sopenharmony_ci cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSO, 613762306a36Sopenharmony_ci (E1000_ADVTXD_DCMD_TSE)); 613862306a36Sopenharmony_ci 613962306a36Sopenharmony_ci /* set timestamp bit if present */ 614062306a36Sopenharmony_ci cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSTAMP, 614162306a36Sopenharmony_ci (E1000_ADVTXD_MAC_TSTAMP)); 614262306a36Sopenharmony_ci 614362306a36Sopenharmony_ci /* insert frame checksum */ 614462306a36Sopenharmony_ci cmd_type ^= IGB_SET_FLAG(skb->no_fcs, 1, E1000_ADVTXD_DCMD_IFCS); 614562306a36Sopenharmony_ci 614662306a36Sopenharmony_ci return cmd_type; 614762306a36Sopenharmony_ci} 614862306a36Sopenharmony_ci 614962306a36Sopenharmony_cistatic void igb_tx_olinfo_status(struct igb_ring *tx_ring, 615062306a36Sopenharmony_ci union e1000_adv_tx_desc *tx_desc, 615162306a36Sopenharmony_ci u32 tx_flags, unsigned int paylen) 615262306a36Sopenharmony_ci{ 615362306a36Sopenharmony_ci u32 olinfo_status = paylen << E1000_ADVTXD_PAYLEN_SHIFT; 615462306a36Sopenharmony_ci 615562306a36Sopenharmony_ci /* 82575 requires a unique index per ring */ 615662306a36Sopenharmony_ci if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) 615762306a36Sopenharmony_ci olinfo_status |= tx_ring->reg_idx << 4; 615862306a36Sopenharmony_ci 615962306a36Sopenharmony_ci /* insert L4 checksum */ 616062306a36Sopenharmony_ci olinfo_status |= IGB_SET_FLAG(tx_flags, 616162306a36Sopenharmony_ci IGB_TX_FLAGS_CSUM, 616262306a36Sopenharmony_ci (E1000_TXD_POPTS_TXSM << 8)); 616362306a36Sopenharmony_ci 616462306a36Sopenharmony_ci /* insert IPv4 checksum */ 616562306a36Sopenharmony_ci olinfo_status |= IGB_SET_FLAG(tx_flags, 616662306a36Sopenharmony_ci IGB_TX_FLAGS_IPV4, 616762306a36Sopenharmony_ci (E1000_TXD_POPTS_IXSM << 8)); 616862306a36Sopenharmony_ci 616962306a36Sopenharmony_ci tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); 617062306a36Sopenharmony_ci} 617162306a36Sopenharmony_ci 617262306a36Sopenharmony_cistatic int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size) 617362306a36Sopenharmony_ci{ 617462306a36Sopenharmony_ci struct net_device *netdev = tx_ring->netdev; 617562306a36Sopenharmony_ci 617662306a36Sopenharmony_ci netif_stop_subqueue(netdev, tx_ring->queue_index); 617762306a36Sopenharmony_ci 617862306a36Sopenharmony_ci /* Herbert's original patch had: 617962306a36Sopenharmony_ci * smp_mb__after_netif_stop_queue(); 618062306a36Sopenharmony_ci * but since that doesn't exist yet, just open code it. 618162306a36Sopenharmony_ci */ 618262306a36Sopenharmony_ci smp_mb(); 618362306a36Sopenharmony_ci 618462306a36Sopenharmony_ci /* We need to check again in a case another CPU has just 618562306a36Sopenharmony_ci * made room available. 618662306a36Sopenharmony_ci */ 618762306a36Sopenharmony_ci if (igb_desc_unused(tx_ring) < size) 618862306a36Sopenharmony_ci return -EBUSY; 618962306a36Sopenharmony_ci 619062306a36Sopenharmony_ci /* A reprieve! */ 619162306a36Sopenharmony_ci netif_wake_subqueue(netdev, tx_ring->queue_index); 619262306a36Sopenharmony_ci 619362306a36Sopenharmony_ci u64_stats_update_begin(&tx_ring->tx_syncp2); 619462306a36Sopenharmony_ci tx_ring->tx_stats.restart_queue2++; 619562306a36Sopenharmony_ci u64_stats_update_end(&tx_ring->tx_syncp2); 619662306a36Sopenharmony_ci 619762306a36Sopenharmony_ci return 0; 619862306a36Sopenharmony_ci} 619962306a36Sopenharmony_ci 620062306a36Sopenharmony_cistatic inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size) 620162306a36Sopenharmony_ci{ 620262306a36Sopenharmony_ci if (igb_desc_unused(tx_ring) >= size) 620362306a36Sopenharmony_ci return 0; 620462306a36Sopenharmony_ci return __igb_maybe_stop_tx(tx_ring, size); 620562306a36Sopenharmony_ci} 620662306a36Sopenharmony_ci 620762306a36Sopenharmony_cistatic int igb_tx_map(struct igb_ring *tx_ring, 620862306a36Sopenharmony_ci struct igb_tx_buffer *first, 620962306a36Sopenharmony_ci const u8 hdr_len) 621062306a36Sopenharmony_ci{ 621162306a36Sopenharmony_ci struct sk_buff *skb = first->skb; 621262306a36Sopenharmony_ci struct igb_tx_buffer *tx_buffer; 621362306a36Sopenharmony_ci union e1000_adv_tx_desc *tx_desc; 621462306a36Sopenharmony_ci skb_frag_t *frag; 621562306a36Sopenharmony_ci dma_addr_t dma; 621662306a36Sopenharmony_ci unsigned int data_len, size; 621762306a36Sopenharmony_ci u32 tx_flags = first->tx_flags; 621862306a36Sopenharmony_ci u32 cmd_type = igb_tx_cmd_type(skb, tx_flags); 621962306a36Sopenharmony_ci u16 i = tx_ring->next_to_use; 622062306a36Sopenharmony_ci 622162306a36Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, i); 622262306a36Sopenharmony_ci 622362306a36Sopenharmony_ci igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, skb->len - hdr_len); 622462306a36Sopenharmony_ci 622562306a36Sopenharmony_ci size = skb_headlen(skb); 622662306a36Sopenharmony_ci data_len = skb->data_len; 622762306a36Sopenharmony_ci 622862306a36Sopenharmony_ci dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE); 622962306a36Sopenharmony_ci 623062306a36Sopenharmony_ci tx_buffer = first; 623162306a36Sopenharmony_ci 623262306a36Sopenharmony_ci for (frag = &skb_shinfo(skb)->frags[0];; frag++) { 623362306a36Sopenharmony_ci if (dma_mapping_error(tx_ring->dev, dma)) 623462306a36Sopenharmony_ci goto dma_error; 623562306a36Sopenharmony_ci 623662306a36Sopenharmony_ci /* record length, and DMA address */ 623762306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, size); 623862306a36Sopenharmony_ci dma_unmap_addr_set(tx_buffer, dma, dma); 623962306a36Sopenharmony_ci 624062306a36Sopenharmony_ci tx_desc->read.buffer_addr = cpu_to_le64(dma); 624162306a36Sopenharmony_ci 624262306a36Sopenharmony_ci while (unlikely(size > IGB_MAX_DATA_PER_TXD)) { 624362306a36Sopenharmony_ci tx_desc->read.cmd_type_len = 624462306a36Sopenharmony_ci cpu_to_le32(cmd_type ^ IGB_MAX_DATA_PER_TXD); 624562306a36Sopenharmony_ci 624662306a36Sopenharmony_ci i++; 624762306a36Sopenharmony_ci tx_desc++; 624862306a36Sopenharmony_ci if (i == tx_ring->count) { 624962306a36Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, 0); 625062306a36Sopenharmony_ci i = 0; 625162306a36Sopenharmony_ci } 625262306a36Sopenharmony_ci tx_desc->read.olinfo_status = 0; 625362306a36Sopenharmony_ci 625462306a36Sopenharmony_ci dma += IGB_MAX_DATA_PER_TXD; 625562306a36Sopenharmony_ci size -= IGB_MAX_DATA_PER_TXD; 625662306a36Sopenharmony_ci 625762306a36Sopenharmony_ci tx_desc->read.buffer_addr = cpu_to_le64(dma); 625862306a36Sopenharmony_ci } 625962306a36Sopenharmony_ci 626062306a36Sopenharmony_ci if (likely(!data_len)) 626162306a36Sopenharmony_ci break; 626262306a36Sopenharmony_ci 626362306a36Sopenharmony_ci tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type ^ size); 626462306a36Sopenharmony_ci 626562306a36Sopenharmony_ci i++; 626662306a36Sopenharmony_ci tx_desc++; 626762306a36Sopenharmony_ci if (i == tx_ring->count) { 626862306a36Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, 0); 626962306a36Sopenharmony_ci i = 0; 627062306a36Sopenharmony_ci } 627162306a36Sopenharmony_ci tx_desc->read.olinfo_status = 0; 627262306a36Sopenharmony_ci 627362306a36Sopenharmony_ci size = skb_frag_size(frag); 627462306a36Sopenharmony_ci data_len -= size; 627562306a36Sopenharmony_ci 627662306a36Sopenharmony_ci dma = skb_frag_dma_map(tx_ring->dev, frag, 0, 627762306a36Sopenharmony_ci size, DMA_TO_DEVICE); 627862306a36Sopenharmony_ci 627962306a36Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[i]; 628062306a36Sopenharmony_ci } 628162306a36Sopenharmony_ci 628262306a36Sopenharmony_ci /* write last descriptor with RS and EOP bits */ 628362306a36Sopenharmony_ci cmd_type |= size | IGB_TXD_DCMD; 628462306a36Sopenharmony_ci tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); 628562306a36Sopenharmony_ci 628662306a36Sopenharmony_ci netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); 628762306a36Sopenharmony_ci 628862306a36Sopenharmony_ci /* set the timestamp */ 628962306a36Sopenharmony_ci first->time_stamp = jiffies; 629062306a36Sopenharmony_ci 629162306a36Sopenharmony_ci skb_tx_timestamp(skb); 629262306a36Sopenharmony_ci 629362306a36Sopenharmony_ci /* Force memory writes to complete before letting h/w know there 629462306a36Sopenharmony_ci * are new descriptors to fetch. (Only applicable for weak-ordered 629562306a36Sopenharmony_ci * memory model archs, such as IA-64). 629662306a36Sopenharmony_ci * 629762306a36Sopenharmony_ci * We also need this memory barrier to make certain all of the 629862306a36Sopenharmony_ci * status bits have been updated before next_to_watch is written. 629962306a36Sopenharmony_ci */ 630062306a36Sopenharmony_ci dma_wmb(); 630162306a36Sopenharmony_ci 630262306a36Sopenharmony_ci /* set next_to_watch value indicating a packet is present */ 630362306a36Sopenharmony_ci first->next_to_watch = tx_desc; 630462306a36Sopenharmony_ci 630562306a36Sopenharmony_ci i++; 630662306a36Sopenharmony_ci if (i == tx_ring->count) 630762306a36Sopenharmony_ci i = 0; 630862306a36Sopenharmony_ci 630962306a36Sopenharmony_ci tx_ring->next_to_use = i; 631062306a36Sopenharmony_ci 631162306a36Sopenharmony_ci /* Make sure there is space in the ring for the next send. */ 631262306a36Sopenharmony_ci igb_maybe_stop_tx(tx_ring, DESC_NEEDED); 631362306a36Sopenharmony_ci 631462306a36Sopenharmony_ci if (netif_xmit_stopped(txring_txq(tx_ring)) || !netdev_xmit_more()) { 631562306a36Sopenharmony_ci writel(i, tx_ring->tail); 631662306a36Sopenharmony_ci } 631762306a36Sopenharmony_ci return 0; 631862306a36Sopenharmony_ci 631962306a36Sopenharmony_cidma_error: 632062306a36Sopenharmony_ci dev_err(tx_ring->dev, "TX DMA map failed\n"); 632162306a36Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[i]; 632262306a36Sopenharmony_ci 632362306a36Sopenharmony_ci /* clear dma mappings for failed tx_buffer_info map */ 632462306a36Sopenharmony_ci while (tx_buffer != first) { 632562306a36Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) 632662306a36Sopenharmony_ci dma_unmap_page(tx_ring->dev, 632762306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 632862306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 632962306a36Sopenharmony_ci DMA_TO_DEVICE); 633062306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 633162306a36Sopenharmony_ci 633262306a36Sopenharmony_ci if (i-- == 0) 633362306a36Sopenharmony_ci i += tx_ring->count; 633462306a36Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[i]; 633562306a36Sopenharmony_ci } 633662306a36Sopenharmony_ci 633762306a36Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) 633862306a36Sopenharmony_ci dma_unmap_single(tx_ring->dev, 633962306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 634062306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 634162306a36Sopenharmony_ci DMA_TO_DEVICE); 634262306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 634362306a36Sopenharmony_ci 634462306a36Sopenharmony_ci dev_kfree_skb_any(tx_buffer->skb); 634562306a36Sopenharmony_ci tx_buffer->skb = NULL; 634662306a36Sopenharmony_ci 634762306a36Sopenharmony_ci tx_ring->next_to_use = i; 634862306a36Sopenharmony_ci 634962306a36Sopenharmony_ci return -1; 635062306a36Sopenharmony_ci} 635162306a36Sopenharmony_ci 635262306a36Sopenharmony_ciint igb_xmit_xdp_ring(struct igb_adapter *adapter, 635362306a36Sopenharmony_ci struct igb_ring *tx_ring, 635462306a36Sopenharmony_ci struct xdp_frame *xdpf) 635562306a36Sopenharmony_ci{ 635662306a36Sopenharmony_ci struct skb_shared_info *sinfo = xdp_get_shared_info_from_frame(xdpf); 635762306a36Sopenharmony_ci u8 nr_frags = unlikely(xdp_frame_has_frags(xdpf)) ? sinfo->nr_frags : 0; 635862306a36Sopenharmony_ci u16 count, i, index = tx_ring->next_to_use; 635962306a36Sopenharmony_ci struct igb_tx_buffer *tx_head = &tx_ring->tx_buffer_info[index]; 636062306a36Sopenharmony_ci struct igb_tx_buffer *tx_buffer = tx_head; 636162306a36Sopenharmony_ci union e1000_adv_tx_desc *tx_desc = IGB_TX_DESC(tx_ring, index); 636262306a36Sopenharmony_ci u32 len = xdpf->len, cmd_type, olinfo_status; 636362306a36Sopenharmony_ci void *data = xdpf->data; 636462306a36Sopenharmony_ci 636562306a36Sopenharmony_ci count = TXD_USE_COUNT(len); 636662306a36Sopenharmony_ci for (i = 0; i < nr_frags; i++) 636762306a36Sopenharmony_ci count += TXD_USE_COUNT(skb_frag_size(&sinfo->frags[i])); 636862306a36Sopenharmony_ci 636962306a36Sopenharmony_ci if (igb_maybe_stop_tx(tx_ring, count + 3)) 637062306a36Sopenharmony_ci return IGB_XDP_CONSUMED; 637162306a36Sopenharmony_ci 637262306a36Sopenharmony_ci i = 0; 637362306a36Sopenharmony_ci /* record the location of the first descriptor for this packet */ 637462306a36Sopenharmony_ci tx_head->bytecount = xdp_get_frame_len(xdpf); 637562306a36Sopenharmony_ci tx_head->type = IGB_TYPE_XDP; 637662306a36Sopenharmony_ci tx_head->gso_segs = 1; 637762306a36Sopenharmony_ci tx_head->xdpf = xdpf; 637862306a36Sopenharmony_ci 637962306a36Sopenharmony_ci olinfo_status = tx_head->bytecount << E1000_ADVTXD_PAYLEN_SHIFT; 638062306a36Sopenharmony_ci /* 82575 requires a unique index per ring */ 638162306a36Sopenharmony_ci if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) 638262306a36Sopenharmony_ci olinfo_status |= tx_ring->reg_idx << 4; 638362306a36Sopenharmony_ci tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); 638462306a36Sopenharmony_ci 638562306a36Sopenharmony_ci for (;;) { 638662306a36Sopenharmony_ci dma_addr_t dma; 638762306a36Sopenharmony_ci 638862306a36Sopenharmony_ci dma = dma_map_single(tx_ring->dev, data, len, DMA_TO_DEVICE); 638962306a36Sopenharmony_ci if (dma_mapping_error(tx_ring->dev, dma)) 639062306a36Sopenharmony_ci goto unmap; 639162306a36Sopenharmony_ci 639262306a36Sopenharmony_ci /* record length, and DMA address */ 639362306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, len); 639462306a36Sopenharmony_ci dma_unmap_addr_set(tx_buffer, dma, dma); 639562306a36Sopenharmony_ci 639662306a36Sopenharmony_ci /* put descriptor type bits */ 639762306a36Sopenharmony_ci cmd_type = E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_DEXT | 639862306a36Sopenharmony_ci E1000_ADVTXD_DCMD_IFCS | len; 639962306a36Sopenharmony_ci 640062306a36Sopenharmony_ci tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); 640162306a36Sopenharmony_ci tx_desc->read.buffer_addr = cpu_to_le64(dma); 640262306a36Sopenharmony_ci 640362306a36Sopenharmony_ci tx_buffer->protocol = 0; 640462306a36Sopenharmony_ci 640562306a36Sopenharmony_ci if (++index == tx_ring->count) 640662306a36Sopenharmony_ci index = 0; 640762306a36Sopenharmony_ci 640862306a36Sopenharmony_ci if (i == nr_frags) 640962306a36Sopenharmony_ci break; 641062306a36Sopenharmony_ci 641162306a36Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[index]; 641262306a36Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, index); 641362306a36Sopenharmony_ci tx_desc->read.olinfo_status = 0; 641462306a36Sopenharmony_ci 641562306a36Sopenharmony_ci data = skb_frag_address(&sinfo->frags[i]); 641662306a36Sopenharmony_ci len = skb_frag_size(&sinfo->frags[i]); 641762306a36Sopenharmony_ci i++; 641862306a36Sopenharmony_ci } 641962306a36Sopenharmony_ci tx_desc->read.cmd_type_len |= cpu_to_le32(IGB_TXD_DCMD); 642062306a36Sopenharmony_ci 642162306a36Sopenharmony_ci netdev_tx_sent_queue(txring_txq(tx_ring), tx_head->bytecount); 642262306a36Sopenharmony_ci /* set the timestamp */ 642362306a36Sopenharmony_ci tx_head->time_stamp = jiffies; 642462306a36Sopenharmony_ci 642562306a36Sopenharmony_ci /* Avoid any potential race with xdp_xmit and cleanup */ 642662306a36Sopenharmony_ci smp_wmb(); 642762306a36Sopenharmony_ci 642862306a36Sopenharmony_ci /* set next_to_watch value indicating a packet is present */ 642962306a36Sopenharmony_ci tx_head->next_to_watch = tx_desc; 643062306a36Sopenharmony_ci tx_ring->next_to_use = index; 643162306a36Sopenharmony_ci 643262306a36Sopenharmony_ci /* Make sure there is space in the ring for the next send. */ 643362306a36Sopenharmony_ci igb_maybe_stop_tx(tx_ring, DESC_NEEDED); 643462306a36Sopenharmony_ci 643562306a36Sopenharmony_ci if (netif_xmit_stopped(txring_txq(tx_ring)) || !netdev_xmit_more()) 643662306a36Sopenharmony_ci writel(index, tx_ring->tail); 643762306a36Sopenharmony_ci 643862306a36Sopenharmony_ci return IGB_XDP_TX; 643962306a36Sopenharmony_ci 644062306a36Sopenharmony_ciunmap: 644162306a36Sopenharmony_ci for (;;) { 644262306a36Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[index]; 644362306a36Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) 644462306a36Sopenharmony_ci dma_unmap_page(tx_ring->dev, 644562306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 644662306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 644762306a36Sopenharmony_ci DMA_TO_DEVICE); 644862306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 644962306a36Sopenharmony_ci if (tx_buffer == tx_head) 645062306a36Sopenharmony_ci break; 645162306a36Sopenharmony_ci 645262306a36Sopenharmony_ci if (!index) 645362306a36Sopenharmony_ci index += tx_ring->count; 645462306a36Sopenharmony_ci index--; 645562306a36Sopenharmony_ci } 645662306a36Sopenharmony_ci 645762306a36Sopenharmony_ci return IGB_XDP_CONSUMED; 645862306a36Sopenharmony_ci} 645962306a36Sopenharmony_ci 646062306a36Sopenharmony_cinetdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, 646162306a36Sopenharmony_ci struct igb_ring *tx_ring) 646262306a36Sopenharmony_ci{ 646362306a36Sopenharmony_ci struct igb_tx_buffer *first; 646462306a36Sopenharmony_ci int tso; 646562306a36Sopenharmony_ci u32 tx_flags = 0; 646662306a36Sopenharmony_ci unsigned short f; 646762306a36Sopenharmony_ci u16 count = TXD_USE_COUNT(skb_headlen(skb)); 646862306a36Sopenharmony_ci __be16 protocol = vlan_get_protocol(skb); 646962306a36Sopenharmony_ci u8 hdr_len = 0; 647062306a36Sopenharmony_ci 647162306a36Sopenharmony_ci /* need: 1 descriptor per page * PAGE_SIZE/IGB_MAX_DATA_PER_TXD, 647262306a36Sopenharmony_ci * + 1 desc for skb_headlen/IGB_MAX_DATA_PER_TXD, 647362306a36Sopenharmony_ci * + 2 desc gap to keep tail from touching head, 647462306a36Sopenharmony_ci * + 1 desc for context descriptor, 647562306a36Sopenharmony_ci * otherwise try next time 647662306a36Sopenharmony_ci */ 647762306a36Sopenharmony_ci for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) 647862306a36Sopenharmony_ci count += TXD_USE_COUNT(skb_frag_size( 647962306a36Sopenharmony_ci &skb_shinfo(skb)->frags[f])); 648062306a36Sopenharmony_ci 648162306a36Sopenharmony_ci if (igb_maybe_stop_tx(tx_ring, count + 3)) { 648262306a36Sopenharmony_ci /* this is a hard error */ 648362306a36Sopenharmony_ci return NETDEV_TX_BUSY; 648462306a36Sopenharmony_ci } 648562306a36Sopenharmony_ci 648662306a36Sopenharmony_ci /* record the location of the first descriptor for this packet */ 648762306a36Sopenharmony_ci first = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; 648862306a36Sopenharmony_ci first->type = IGB_TYPE_SKB; 648962306a36Sopenharmony_ci first->skb = skb; 649062306a36Sopenharmony_ci first->bytecount = skb->len; 649162306a36Sopenharmony_ci first->gso_segs = 1; 649262306a36Sopenharmony_ci 649362306a36Sopenharmony_ci if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { 649462306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); 649562306a36Sopenharmony_ci 649662306a36Sopenharmony_ci if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON && 649762306a36Sopenharmony_ci !test_and_set_bit_lock(__IGB_PTP_TX_IN_PROGRESS, 649862306a36Sopenharmony_ci &adapter->state)) { 649962306a36Sopenharmony_ci skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 650062306a36Sopenharmony_ci tx_flags |= IGB_TX_FLAGS_TSTAMP; 650162306a36Sopenharmony_ci 650262306a36Sopenharmony_ci adapter->ptp_tx_skb = skb_get(skb); 650362306a36Sopenharmony_ci adapter->ptp_tx_start = jiffies; 650462306a36Sopenharmony_ci if (adapter->hw.mac.type == e1000_82576) 650562306a36Sopenharmony_ci schedule_work(&adapter->ptp_tx_work); 650662306a36Sopenharmony_ci } else { 650762306a36Sopenharmony_ci adapter->tx_hwtstamp_skipped++; 650862306a36Sopenharmony_ci } 650962306a36Sopenharmony_ci } 651062306a36Sopenharmony_ci 651162306a36Sopenharmony_ci if (skb_vlan_tag_present(skb)) { 651262306a36Sopenharmony_ci tx_flags |= IGB_TX_FLAGS_VLAN; 651362306a36Sopenharmony_ci tx_flags |= (skb_vlan_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT); 651462306a36Sopenharmony_ci } 651562306a36Sopenharmony_ci 651662306a36Sopenharmony_ci /* record initial flags and protocol */ 651762306a36Sopenharmony_ci first->tx_flags = tx_flags; 651862306a36Sopenharmony_ci first->protocol = protocol; 651962306a36Sopenharmony_ci 652062306a36Sopenharmony_ci tso = igb_tso(tx_ring, first, &hdr_len); 652162306a36Sopenharmony_ci if (tso < 0) 652262306a36Sopenharmony_ci goto out_drop; 652362306a36Sopenharmony_ci else if (!tso) 652462306a36Sopenharmony_ci igb_tx_csum(tx_ring, first); 652562306a36Sopenharmony_ci 652662306a36Sopenharmony_ci if (igb_tx_map(tx_ring, first, hdr_len)) 652762306a36Sopenharmony_ci goto cleanup_tx_tstamp; 652862306a36Sopenharmony_ci 652962306a36Sopenharmony_ci return NETDEV_TX_OK; 653062306a36Sopenharmony_ci 653162306a36Sopenharmony_ciout_drop: 653262306a36Sopenharmony_ci dev_kfree_skb_any(first->skb); 653362306a36Sopenharmony_ci first->skb = NULL; 653462306a36Sopenharmony_cicleanup_tx_tstamp: 653562306a36Sopenharmony_ci if (unlikely(tx_flags & IGB_TX_FLAGS_TSTAMP)) { 653662306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); 653762306a36Sopenharmony_ci 653862306a36Sopenharmony_ci dev_kfree_skb_any(adapter->ptp_tx_skb); 653962306a36Sopenharmony_ci adapter->ptp_tx_skb = NULL; 654062306a36Sopenharmony_ci if (adapter->hw.mac.type == e1000_82576) 654162306a36Sopenharmony_ci cancel_work_sync(&adapter->ptp_tx_work); 654262306a36Sopenharmony_ci clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); 654362306a36Sopenharmony_ci } 654462306a36Sopenharmony_ci 654562306a36Sopenharmony_ci return NETDEV_TX_OK; 654662306a36Sopenharmony_ci} 654762306a36Sopenharmony_ci 654862306a36Sopenharmony_cistatic inline struct igb_ring *igb_tx_queue_mapping(struct igb_adapter *adapter, 654962306a36Sopenharmony_ci struct sk_buff *skb) 655062306a36Sopenharmony_ci{ 655162306a36Sopenharmony_ci unsigned int r_idx = skb->queue_mapping; 655262306a36Sopenharmony_ci 655362306a36Sopenharmony_ci if (r_idx >= adapter->num_tx_queues) 655462306a36Sopenharmony_ci r_idx = r_idx % adapter->num_tx_queues; 655562306a36Sopenharmony_ci 655662306a36Sopenharmony_ci return adapter->tx_ring[r_idx]; 655762306a36Sopenharmony_ci} 655862306a36Sopenharmony_ci 655962306a36Sopenharmony_cistatic netdev_tx_t igb_xmit_frame(struct sk_buff *skb, 656062306a36Sopenharmony_ci struct net_device *netdev) 656162306a36Sopenharmony_ci{ 656262306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 656362306a36Sopenharmony_ci 656462306a36Sopenharmony_ci /* The minimum packet size with TCTL.PSP set is 17 so pad the skb 656562306a36Sopenharmony_ci * in order to meet this minimum size requirement. 656662306a36Sopenharmony_ci */ 656762306a36Sopenharmony_ci if (skb_put_padto(skb, 17)) 656862306a36Sopenharmony_ci return NETDEV_TX_OK; 656962306a36Sopenharmony_ci 657062306a36Sopenharmony_ci return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb)); 657162306a36Sopenharmony_ci} 657262306a36Sopenharmony_ci 657362306a36Sopenharmony_ci/** 657462306a36Sopenharmony_ci * igb_tx_timeout - Respond to a Tx Hang 657562306a36Sopenharmony_ci * @netdev: network interface device structure 657662306a36Sopenharmony_ci * @txqueue: number of the Tx queue that hung (unused) 657762306a36Sopenharmony_ci **/ 657862306a36Sopenharmony_cistatic void igb_tx_timeout(struct net_device *netdev, unsigned int __always_unused txqueue) 657962306a36Sopenharmony_ci{ 658062306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 658162306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 658262306a36Sopenharmony_ci 658362306a36Sopenharmony_ci /* Do the reset outside of interrupt context */ 658462306a36Sopenharmony_ci adapter->tx_timeout_count++; 658562306a36Sopenharmony_ci 658662306a36Sopenharmony_ci if (hw->mac.type >= e1000_82580) 658762306a36Sopenharmony_ci hw->dev_spec._82575.global_device_reset = true; 658862306a36Sopenharmony_ci 658962306a36Sopenharmony_ci schedule_work(&adapter->reset_task); 659062306a36Sopenharmony_ci wr32(E1000_EICS, 659162306a36Sopenharmony_ci (adapter->eims_enable_mask & ~adapter->eims_other)); 659262306a36Sopenharmony_ci} 659362306a36Sopenharmony_ci 659462306a36Sopenharmony_cistatic void igb_reset_task(struct work_struct *work) 659562306a36Sopenharmony_ci{ 659662306a36Sopenharmony_ci struct igb_adapter *adapter; 659762306a36Sopenharmony_ci adapter = container_of(work, struct igb_adapter, reset_task); 659862306a36Sopenharmony_ci 659962306a36Sopenharmony_ci rtnl_lock(); 660062306a36Sopenharmony_ci /* If we're already down or resetting, just bail */ 660162306a36Sopenharmony_ci if (test_bit(__IGB_DOWN, &adapter->state) || 660262306a36Sopenharmony_ci test_bit(__IGB_RESETTING, &adapter->state)) { 660362306a36Sopenharmony_ci rtnl_unlock(); 660462306a36Sopenharmony_ci return; 660562306a36Sopenharmony_ci } 660662306a36Sopenharmony_ci 660762306a36Sopenharmony_ci igb_dump(adapter); 660862306a36Sopenharmony_ci netdev_err(adapter->netdev, "Reset adapter\n"); 660962306a36Sopenharmony_ci igb_reinit_locked(adapter); 661062306a36Sopenharmony_ci rtnl_unlock(); 661162306a36Sopenharmony_ci} 661262306a36Sopenharmony_ci 661362306a36Sopenharmony_ci/** 661462306a36Sopenharmony_ci * igb_get_stats64 - Get System Network Statistics 661562306a36Sopenharmony_ci * @netdev: network interface device structure 661662306a36Sopenharmony_ci * @stats: rtnl_link_stats64 pointer 661762306a36Sopenharmony_ci **/ 661862306a36Sopenharmony_cistatic void igb_get_stats64(struct net_device *netdev, 661962306a36Sopenharmony_ci struct rtnl_link_stats64 *stats) 662062306a36Sopenharmony_ci{ 662162306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 662262306a36Sopenharmony_ci 662362306a36Sopenharmony_ci spin_lock(&adapter->stats64_lock); 662462306a36Sopenharmony_ci igb_update_stats(adapter); 662562306a36Sopenharmony_ci memcpy(stats, &adapter->stats64, sizeof(*stats)); 662662306a36Sopenharmony_ci spin_unlock(&adapter->stats64_lock); 662762306a36Sopenharmony_ci} 662862306a36Sopenharmony_ci 662962306a36Sopenharmony_ci/** 663062306a36Sopenharmony_ci * igb_change_mtu - Change the Maximum Transfer Unit 663162306a36Sopenharmony_ci * @netdev: network interface device structure 663262306a36Sopenharmony_ci * @new_mtu: new value for maximum frame size 663362306a36Sopenharmony_ci * 663462306a36Sopenharmony_ci * Returns 0 on success, negative on failure 663562306a36Sopenharmony_ci **/ 663662306a36Sopenharmony_cistatic int igb_change_mtu(struct net_device *netdev, int new_mtu) 663762306a36Sopenharmony_ci{ 663862306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 663962306a36Sopenharmony_ci int max_frame = new_mtu + IGB_ETH_PKT_HDR_PAD; 664062306a36Sopenharmony_ci 664162306a36Sopenharmony_ci if (adapter->xdp_prog) { 664262306a36Sopenharmony_ci int i; 664362306a36Sopenharmony_ci 664462306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 664562306a36Sopenharmony_ci struct igb_ring *ring = adapter->rx_ring[i]; 664662306a36Sopenharmony_ci 664762306a36Sopenharmony_ci if (max_frame > igb_rx_bufsz(ring)) { 664862306a36Sopenharmony_ci netdev_warn(adapter->netdev, 664962306a36Sopenharmony_ci "Requested MTU size is not supported with XDP. Max frame size is %d\n", 665062306a36Sopenharmony_ci max_frame); 665162306a36Sopenharmony_ci return -EINVAL; 665262306a36Sopenharmony_ci } 665362306a36Sopenharmony_ci } 665462306a36Sopenharmony_ci } 665562306a36Sopenharmony_ci 665662306a36Sopenharmony_ci /* adjust max frame to be at least the size of a standard frame */ 665762306a36Sopenharmony_ci if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN)) 665862306a36Sopenharmony_ci max_frame = ETH_FRAME_LEN + ETH_FCS_LEN; 665962306a36Sopenharmony_ci 666062306a36Sopenharmony_ci while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) 666162306a36Sopenharmony_ci usleep_range(1000, 2000); 666262306a36Sopenharmony_ci 666362306a36Sopenharmony_ci /* igb_down has a dependency on max_frame_size */ 666462306a36Sopenharmony_ci adapter->max_frame_size = max_frame; 666562306a36Sopenharmony_ci 666662306a36Sopenharmony_ci if (netif_running(netdev)) 666762306a36Sopenharmony_ci igb_down(adapter); 666862306a36Sopenharmony_ci 666962306a36Sopenharmony_ci netdev_dbg(netdev, "changing MTU from %d to %d\n", 667062306a36Sopenharmony_ci netdev->mtu, new_mtu); 667162306a36Sopenharmony_ci netdev->mtu = new_mtu; 667262306a36Sopenharmony_ci 667362306a36Sopenharmony_ci if (netif_running(netdev)) 667462306a36Sopenharmony_ci igb_up(adapter); 667562306a36Sopenharmony_ci else 667662306a36Sopenharmony_ci igb_reset(adapter); 667762306a36Sopenharmony_ci 667862306a36Sopenharmony_ci clear_bit(__IGB_RESETTING, &adapter->state); 667962306a36Sopenharmony_ci 668062306a36Sopenharmony_ci return 0; 668162306a36Sopenharmony_ci} 668262306a36Sopenharmony_ci 668362306a36Sopenharmony_ci/** 668462306a36Sopenharmony_ci * igb_update_stats - Update the board statistics counters 668562306a36Sopenharmony_ci * @adapter: board private structure 668662306a36Sopenharmony_ci **/ 668762306a36Sopenharmony_civoid igb_update_stats(struct igb_adapter *adapter) 668862306a36Sopenharmony_ci{ 668962306a36Sopenharmony_ci struct rtnl_link_stats64 *net_stats = &adapter->stats64; 669062306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 669162306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 669262306a36Sopenharmony_ci u32 reg, mpc; 669362306a36Sopenharmony_ci int i; 669462306a36Sopenharmony_ci u64 bytes, packets; 669562306a36Sopenharmony_ci unsigned int start; 669662306a36Sopenharmony_ci u64 _bytes, _packets; 669762306a36Sopenharmony_ci 669862306a36Sopenharmony_ci /* Prevent stats update while adapter is being reset, or if the pci 669962306a36Sopenharmony_ci * connection is down. 670062306a36Sopenharmony_ci */ 670162306a36Sopenharmony_ci if (adapter->link_speed == 0) 670262306a36Sopenharmony_ci return; 670362306a36Sopenharmony_ci if (pci_channel_offline(pdev)) 670462306a36Sopenharmony_ci return; 670562306a36Sopenharmony_ci 670662306a36Sopenharmony_ci bytes = 0; 670762306a36Sopenharmony_ci packets = 0; 670862306a36Sopenharmony_ci 670962306a36Sopenharmony_ci rcu_read_lock(); 671062306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 671162306a36Sopenharmony_ci struct igb_ring *ring = adapter->rx_ring[i]; 671262306a36Sopenharmony_ci u32 rqdpc = rd32(E1000_RQDPC(i)); 671362306a36Sopenharmony_ci if (hw->mac.type >= e1000_i210) 671462306a36Sopenharmony_ci wr32(E1000_RQDPC(i), 0); 671562306a36Sopenharmony_ci 671662306a36Sopenharmony_ci if (rqdpc) { 671762306a36Sopenharmony_ci ring->rx_stats.drops += rqdpc; 671862306a36Sopenharmony_ci net_stats->rx_fifo_errors += rqdpc; 671962306a36Sopenharmony_ci } 672062306a36Sopenharmony_ci 672162306a36Sopenharmony_ci do { 672262306a36Sopenharmony_ci start = u64_stats_fetch_begin(&ring->rx_syncp); 672362306a36Sopenharmony_ci _bytes = ring->rx_stats.bytes; 672462306a36Sopenharmony_ci _packets = ring->rx_stats.packets; 672562306a36Sopenharmony_ci } while (u64_stats_fetch_retry(&ring->rx_syncp, start)); 672662306a36Sopenharmony_ci bytes += _bytes; 672762306a36Sopenharmony_ci packets += _packets; 672862306a36Sopenharmony_ci } 672962306a36Sopenharmony_ci 673062306a36Sopenharmony_ci net_stats->rx_bytes = bytes; 673162306a36Sopenharmony_ci net_stats->rx_packets = packets; 673262306a36Sopenharmony_ci 673362306a36Sopenharmony_ci bytes = 0; 673462306a36Sopenharmony_ci packets = 0; 673562306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 673662306a36Sopenharmony_ci struct igb_ring *ring = adapter->tx_ring[i]; 673762306a36Sopenharmony_ci do { 673862306a36Sopenharmony_ci start = u64_stats_fetch_begin(&ring->tx_syncp); 673962306a36Sopenharmony_ci _bytes = ring->tx_stats.bytes; 674062306a36Sopenharmony_ci _packets = ring->tx_stats.packets; 674162306a36Sopenharmony_ci } while (u64_stats_fetch_retry(&ring->tx_syncp, start)); 674262306a36Sopenharmony_ci bytes += _bytes; 674362306a36Sopenharmony_ci packets += _packets; 674462306a36Sopenharmony_ci } 674562306a36Sopenharmony_ci net_stats->tx_bytes = bytes; 674662306a36Sopenharmony_ci net_stats->tx_packets = packets; 674762306a36Sopenharmony_ci rcu_read_unlock(); 674862306a36Sopenharmony_ci 674962306a36Sopenharmony_ci /* read stats registers */ 675062306a36Sopenharmony_ci adapter->stats.crcerrs += rd32(E1000_CRCERRS); 675162306a36Sopenharmony_ci adapter->stats.gprc += rd32(E1000_GPRC); 675262306a36Sopenharmony_ci adapter->stats.gorc += rd32(E1000_GORCL); 675362306a36Sopenharmony_ci rd32(E1000_GORCH); /* clear GORCL */ 675462306a36Sopenharmony_ci adapter->stats.bprc += rd32(E1000_BPRC); 675562306a36Sopenharmony_ci adapter->stats.mprc += rd32(E1000_MPRC); 675662306a36Sopenharmony_ci adapter->stats.roc += rd32(E1000_ROC); 675762306a36Sopenharmony_ci 675862306a36Sopenharmony_ci adapter->stats.prc64 += rd32(E1000_PRC64); 675962306a36Sopenharmony_ci adapter->stats.prc127 += rd32(E1000_PRC127); 676062306a36Sopenharmony_ci adapter->stats.prc255 += rd32(E1000_PRC255); 676162306a36Sopenharmony_ci adapter->stats.prc511 += rd32(E1000_PRC511); 676262306a36Sopenharmony_ci adapter->stats.prc1023 += rd32(E1000_PRC1023); 676362306a36Sopenharmony_ci adapter->stats.prc1522 += rd32(E1000_PRC1522); 676462306a36Sopenharmony_ci adapter->stats.symerrs += rd32(E1000_SYMERRS); 676562306a36Sopenharmony_ci adapter->stats.sec += rd32(E1000_SEC); 676662306a36Sopenharmony_ci 676762306a36Sopenharmony_ci mpc = rd32(E1000_MPC); 676862306a36Sopenharmony_ci adapter->stats.mpc += mpc; 676962306a36Sopenharmony_ci net_stats->rx_fifo_errors += mpc; 677062306a36Sopenharmony_ci adapter->stats.scc += rd32(E1000_SCC); 677162306a36Sopenharmony_ci adapter->stats.ecol += rd32(E1000_ECOL); 677262306a36Sopenharmony_ci adapter->stats.mcc += rd32(E1000_MCC); 677362306a36Sopenharmony_ci adapter->stats.latecol += rd32(E1000_LATECOL); 677462306a36Sopenharmony_ci adapter->stats.dc += rd32(E1000_DC); 677562306a36Sopenharmony_ci adapter->stats.rlec += rd32(E1000_RLEC); 677662306a36Sopenharmony_ci adapter->stats.xonrxc += rd32(E1000_XONRXC); 677762306a36Sopenharmony_ci adapter->stats.xontxc += rd32(E1000_XONTXC); 677862306a36Sopenharmony_ci adapter->stats.xoffrxc += rd32(E1000_XOFFRXC); 677962306a36Sopenharmony_ci adapter->stats.xofftxc += rd32(E1000_XOFFTXC); 678062306a36Sopenharmony_ci adapter->stats.fcruc += rd32(E1000_FCRUC); 678162306a36Sopenharmony_ci adapter->stats.gptc += rd32(E1000_GPTC); 678262306a36Sopenharmony_ci adapter->stats.gotc += rd32(E1000_GOTCL); 678362306a36Sopenharmony_ci rd32(E1000_GOTCH); /* clear GOTCL */ 678462306a36Sopenharmony_ci adapter->stats.rnbc += rd32(E1000_RNBC); 678562306a36Sopenharmony_ci adapter->stats.ruc += rd32(E1000_RUC); 678662306a36Sopenharmony_ci adapter->stats.rfc += rd32(E1000_RFC); 678762306a36Sopenharmony_ci adapter->stats.rjc += rd32(E1000_RJC); 678862306a36Sopenharmony_ci adapter->stats.tor += rd32(E1000_TORH); 678962306a36Sopenharmony_ci adapter->stats.tot += rd32(E1000_TOTH); 679062306a36Sopenharmony_ci adapter->stats.tpr += rd32(E1000_TPR); 679162306a36Sopenharmony_ci 679262306a36Sopenharmony_ci adapter->stats.ptc64 += rd32(E1000_PTC64); 679362306a36Sopenharmony_ci adapter->stats.ptc127 += rd32(E1000_PTC127); 679462306a36Sopenharmony_ci adapter->stats.ptc255 += rd32(E1000_PTC255); 679562306a36Sopenharmony_ci adapter->stats.ptc511 += rd32(E1000_PTC511); 679662306a36Sopenharmony_ci adapter->stats.ptc1023 += rd32(E1000_PTC1023); 679762306a36Sopenharmony_ci adapter->stats.ptc1522 += rd32(E1000_PTC1522); 679862306a36Sopenharmony_ci 679962306a36Sopenharmony_ci adapter->stats.mptc += rd32(E1000_MPTC); 680062306a36Sopenharmony_ci adapter->stats.bptc += rd32(E1000_BPTC); 680162306a36Sopenharmony_ci 680262306a36Sopenharmony_ci adapter->stats.tpt += rd32(E1000_TPT); 680362306a36Sopenharmony_ci adapter->stats.colc += rd32(E1000_COLC); 680462306a36Sopenharmony_ci 680562306a36Sopenharmony_ci adapter->stats.algnerrc += rd32(E1000_ALGNERRC); 680662306a36Sopenharmony_ci /* read internal phy specific stats */ 680762306a36Sopenharmony_ci reg = rd32(E1000_CTRL_EXT); 680862306a36Sopenharmony_ci if (!(reg & E1000_CTRL_EXT_LINK_MODE_MASK)) { 680962306a36Sopenharmony_ci adapter->stats.rxerrc += rd32(E1000_RXERRC); 681062306a36Sopenharmony_ci 681162306a36Sopenharmony_ci /* this stat has invalid values on i210/i211 */ 681262306a36Sopenharmony_ci if ((hw->mac.type != e1000_i210) && 681362306a36Sopenharmony_ci (hw->mac.type != e1000_i211)) 681462306a36Sopenharmony_ci adapter->stats.tncrs += rd32(E1000_TNCRS); 681562306a36Sopenharmony_ci } 681662306a36Sopenharmony_ci 681762306a36Sopenharmony_ci adapter->stats.tsctc += rd32(E1000_TSCTC); 681862306a36Sopenharmony_ci adapter->stats.tsctfc += rd32(E1000_TSCTFC); 681962306a36Sopenharmony_ci 682062306a36Sopenharmony_ci adapter->stats.iac += rd32(E1000_IAC); 682162306a36Sopenharmony_ci adapter->stats.icrxoc += rd32(E1000_ICRXOC); 682262306a36Sopenharmony_ci adapter->stats.icrxptc += rd32(E1000_ICRXPTC); 682362306a36Sopenharmony_ci adapter->stats.icrxatc += rd32(E1000_ICRXATC); 682462306a36Sopenharmony_ci adapter->stats.ictxptc += rd32(E1000_ICTXPTC); 682562306a36Sopenharmony_ci adapter->stats.ictxatc += rd32(E1000_ICTXATC); 682662306a36Sopenharmony_ci adapter->stats.ictxqec += rd32(E1000_ICTXQEC); 682762306a36Sopenharmony_ci adapter->stats.ictxqmtc += rd32(E1000_ICTXQMTC); 682862306a36Sopenharmony_ci adapter->stats.icrxdmtc += rd32(E1000_ICRXDMTC); 682962306a36Sopenharmony_ci 683062306a36Sopenharmony_ci /* Fill out the OS statistics structure */ 683162306a36Sopenharmony_ci net_stats->multicast = adapter->stats.mprc; 683262306a36Sopenharmony_ci net_stats->collisions = adapter->stats.colc; 683362306a36Sopenharmony_ci 683462306a36Sopenharmony_ci /* Rx Errors */ 683562306a36Sopenharmony_ci 683662306a36Sopenharmony_ci /* RLEC on some newer hardware can be incorrect so build 683762306a36Sopenharmony_ci * our own version based on RUC and ROC 683862306a36Sopenharmony_ci */ 683962306a36Sopenharmony_ci net_stats->rx_errors = adapter->stats.rxerrc + 684062306a36Sopenharmony_ci adapter->stats.crcerrs + adapter->stats.algnerrc + 684162306a36Sopenharmony_ci adapter->stats.ruc + adapter->stats.roc + 684262306a36Sopenharmony_ci adapter->stats.cexterr; 684362306a36Sopenharmony_ci net_stats->rx_length_errors = adapter->stats.ruc + 684462306a36Sopenharmony_ci adapter->stats.roc; 684562306a36Sopenharmony_ci net_stats->rx_crc_errors = adapter->stats.crcerrs; 684662306a36Sopenharmony_ci net_stats->rx_frame_errors = adapter->stats.algnerrc; 684762306a36Sopenharmony_ci net_stats->rx_missed_errors = adapter->stats.mpc; 684862306a36Sopenharmony_ci 684962306a36Sopenharmony_ci /* Tx Errors */ 685062306a36Sopenharmony_ci net_stats->tx_errors = adapter->stats.ecol + 685162306a36Sopenharmony_ci adapter->stats.latecol; 685262306a36Sopenharmony_ci net_stats->tx_aborted_errors = adapter->stats.ecol; 685362306a36Sopenharmony_ci net_stats->tx_window_errors = adapter->stats.latecol; 685462306a36Sopenharmony_ci net_stats->tx_carrier_errors = adapter->stats.tncrs; 685562306a36Sopenharmony_ci 685662306a36Sopenharmony_ci /* Tx Dropped needs to be maintained elsewhere */ 685762306a36Sopenharmony_ci 685862306a36Sopenharmony_ci /* Management Stats */ 685962306a36Sopenharmony_ci adapter->stats.mgptc += rd32(E1000_MGTPTC); 686062306a36Sopenharmony_ci adapter->stats.mgprc += rd32(E1000_MGTPRC); 686162306a36Sopenharmony_ci adapter->stats.mgpdc += rd32(E1000_MGTPDC); 686262306a36Sopenharmony_ci 686362306a36Sopenharmony_ci /* OS2BMC Stats */ 686462306a36Sopenharmony_ci reg = rd32(E1000_MANC); 686562306a36Sopenharmony_ci if (reg & E1000_MANC_EN_BMC2OS) { 686662306a36Sopenharmony_ci adapter->stats.o2bgptc += rd32(E1000_O2BGPTC); 686762306a36Sopenharmony_ci adapter->stats.o2bspc += rd32(E1000_O2BSPC); 686862306a36Sopenharmony_ci adapter->stats.b2ospc += rd32(E1000_B2OSPC); 686962306a36Sopenharmony_ci adapter->stats.b2ogprc += rd32(E1000_B2OGPRC); 687062306a36Sopenharmony_ci } 687162306a36Sopenharmony_ci} 687262306a36Sopenharmony_ci 687362306a36Sopenharmony_cistatic void igb_perout(struct igb_adapter *adapter, int tsintr_tt) 687462306a36Sopenharmony_ci{ 687562306a36Sopenharmony_ci int pin = ptp_find_pin(adapter->ptp_clock, PTP_PF_PEROUT, tsintr_tt); 687662306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 687762306a36Sopenharmony_ci struct timespec64 ts; 687862306a36Sopenharmony_ci u32 tsauxc; 687962306a36Sopenharmony_ci 688062306a36Sopenharmony_ci if (pin < 0 || pin >= IGB_N_SDP) 688162306a36Sopenharmony_ci return; 688262306a36Sopenharmony_ci 688362306a36Sopenharmony_ci spin_lock(&adapter->tmreg_lock); 688462306a36Sopenharmony_ci 688562306a36Sopenharmony_ci if (hw->mac.type == e1000_82580 || 688662306a36Sopenharmony_ci hw->mac.type == e1000_i354 || 688762306a36Sopenharmony_ci hw->mac.type == e1000_i350) { 688862306a36Sopenharmony_ci s64 ns = timespec64_to_ns(&adapter->perout[tsintr_tt].period); 688962306a36Sopenharmony_ci u32 systiml, systimh, level_mask, level, rem; 689062306a36Sopenharmony_ci u64 systim, now; 689162306a36Sopenharmony_ci 689262306a36Sopenharmony_ci /* read systim registers in sequence */ 689362306a36Sopenharmony_ci rd32(E1000_SYSTIMR); 689462306a36Sopenharmony_ci systiml = rd32(E1000_SYSTIML); 689562306a36Sopenharmony_ci systimh = rd32(E1000_SYSTIMH); 689662306a36Sopenharmony_ci systim = (((u64)(systimh & 0xFF)) << 32) | ((u64)systiml); 689762306a36Sopenharmony_ci now = timecounter_cyc2time(&adapter->tc, systim); 689862306a36Sopenharmony_ci 689962306a36Sopenharmony_ci if (pin < 2) { 690062306a36Sopenharmony_ci level_mask = (tsintr_tt == 1) ? 0x80000 : 0x40000; 690162306a36Sopenharmony_ci level = (rd32(E1000_CTRL) & level_mask) ? 1 : 0; 690262306a36Sopenharmony_ci } else { 690362306a36Sopenharmony_ci level_mask = (tsintr_tt == 1) ? 0x80 : 0x40; 690462306a36Sopenharmony_ci level = (rd32(E1000_CTRL_EXT) & level_mask) ? 1 : 0; 690562306a36Sopenharmony_ci } 690662306a36Sopenharmony_ci 690762306a36Sopenharmony_ci div_u64_rem(now, ns, &rem); 690862306a36Sopenharmony_ci systim = systim + (ns - rem); 690962306a36Sopenharmony_ci 691062306a36Sopenharmony_ci /* synchronize pin level with rising/falling edges */ 691162306a36Sopenharmony_ci div_u64_rem(now, ns << 1, &rem); 691262306a36Sopenharmony_ci if (rem < ns) { 691362306a36Sopenharmony_ci /* first half of period */ 691462306a36Sopenharmony_ci if (level == 0) { 691562306a36Sopenharmony_ci /* output is already low, skip this period */ 691662306a36Sopenharmony_ci systim += ns; 691762306a36Sopenharmony_ci pr_notice("igb: periodic output on %s missed falling edge\n", 691862306a36Sopenharmony_ci adapter->sdp_config[pin].name); 691962306a36Sopenharmony_ci } 692062306a36Sopenharmony_ci } else { 692162306a36Sopenharmony_ci /* second half of period */ 692262306a36Sopenharmony_ci if (level == 1) { 692362306a36Sopenharmony_ci /* output is already high, skip this period */ 692462306a36Sopenharmony_ci systim += ns; 692562306a36Sopenharmony_ci pr_notice("igb: periodic output on %s missed rising edge\n", 692662306a36Sopenharmony_ci adapter->sdp_config[pin].name); 692762306a36Sopenharmony_ci } 692862306a36Sopenharmony_ci } 692962306a36Sopenharmony_ci 693062306a36Sopenharmony_ci /* for this chip family tv_sec is the upper part of the binary value, 693162306a36Sopenharmony_ci * so not seconds 693262306a36Sopenharmony_ci */ 693362306a36Sopenharmony_ci ts.tv_nsec = (u32)systim; 693462306a36Sopenharmony_ci ts.tv_sec = ((u32)(systim >> 32)) & 0xFF; 693562306a36Sopenharmony_ci } else { 693662306a36Sopenharmony_ci ts = timespec64_add(adapter->perout[tsintr_tt].start, 693762306a36Sopenharmony_ci adapter->perout[tsintr_tt].period); 693862306a36Sopenharmony_ci } 693962306a36Sopenharmony_ci 694062306a36Sopenharmony_ci /* u32 conversion of tv_sec is safe until y2106 */ 694162306a36Sopenharmony_ci wr32((tsintr_tt == 1) ? E1000_TRGTTIML1 : E1000_TRGTTIML0, ts.tv_nsec); 694262306a36Sopenharmony_ci wr32((tsintr_tt == 1) ? E1000_TRGTTIMH1 : E1000_TRGTTIMH0, (u32)ts.tv_sec); 694362306a36Sopenharmony_ci tsauxc = rd32(E1000_TSAUXC); 694462306a36Sopenharmony_ci tsauxc |= TSAUXC_EN_TT0; 694562306a36Sopenharmony_ci wr32(E1000_TSAUXC, tsauxc); 694662306a36Sopenharmony_ci adapter->perout[tsintr_tt].start = ts; 694762306a36Sopenharmony_ci 694862306a36Sopenharmony_ci spin_unlock(&adapter->tmreg_lock); 694962306a36Sopenharmony_ci} 695062306a36Sopenharmony_ci 695162306a36Sopenharmony_cistatic void igb_extts(struct igb_adapter *adapter, int tsintr_tt) 695262306a36Sopenharmony_ci{ 695362306a36Sopenharmony_ci int pin = ptp_find_pin(adapter->ptp_clock, PTP_PF_EXTTS, tsintr_tt); 695462306a36Sopenharmony_ci int auxstmpl = (tsintr_tt == 1) ? E1000_AUXSTMPL1 : E1000_AUXSTMPL0; 695562306a36Sopenharmony_ci int auxstmph = (tsintr_tt == 1) ? E1000_AUXSTMPH1 : E1000_AUXSTMPH0; 695662306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 695762306a36Sopenharmony_ci struct ptp_clock_event event; 695862306a36Sopenharmony_ci struct timespec64 ts; 695962306a36Sopenharmony_ci unsigned long flags; 696062306a36Sopenharmony_ci 696162306a36Sopenharmony_ci if (pin < 0 || pin >= IGB_N_SDP) 696262306a36Sopenharmony_ci return; 696362306a36Sopenharmony_ci 696462306a36Sopenharmony_ci if (hw->mac.type == e1000_82580 || 696562306a36Sopenharmony_ci hw->mac.type == e1000_i354 || 696662306a36Sopenharmony_ci hw->mac.type == e1000_i350) { 696762306a36Sopenharmony_ci u64 ns = rd32(auxstmpl); 696862306a36Sopenharmony_ci 696962306a36Sopenharmony_ci ns += ((u64)(rd32(auxstmph) & 0xFF)) << 32; 697062306a36Sopenharmony_ci spin_lock_irqsave(&adapter->tmreg_lock, flags); 697162306a36Sopenharmony_ci ns = timecounter_cyc2time(&adapter->tc, ns); 697262306a36Sopenharmony_ci spin_unlock_irqrestore(&adapter->tmreg_lock, flags); 697362306a36Sopenharmony_ci ts = ns_to_timespec64(ns); 697462306a36Sopenharmony_ci } else { 697562306a36Sopenharmony_ci ts.tv_nsec = rd32(auxstmpl); 697662306a36Sopenharmony_ci ts.tv_sec = rd32(auxstmph); 697762306a36Sopenharmony_ci } 697862306a36Sopenharmony_ci 697962306a36Sopenharmony_ci event.type = PTP_CLOCK_EXTTS; 698062306a36Sopenharmony_ci event.index = tsintr_tt; 698162306a36Sopenharmony_ci event.timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec; 698262306a36Sopenharmony_ci ptp_clock_event(adapter->ptp_clock, &event); 698362306a36Sopenharmony_ci} 698462306a36Sopenharmony_ci 698562306a36Sopenharmony_cistatic void igb_tsync_interrupt(struct igb_adapter *adapter) 698662306a36Sopenharmony_ci{ 698762306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 698862306a36Sopenharmony_ci u32 tsicr = rd32(E1000_TSICR); 698962306a36Sopenharmony_ci struct ptp_clock_event event; 699062306a36Sopenharmony_ci 699162306a36Sopenharmony_ci if (tsicr & TSINTR_SYS_WRAP) { 699262306a36Sopenharmony_ci event.type = PTP_CLOCK_PPS; 699362306a36Sopenharmony_ci if (adapter->ptp_caps.pps) 699462306a36Sopenharmony_ci ptp_clock_event(adapter->ptp_clock, &event); 699562306a36Sopenharmony_ci } 699662306a36Sopenharmony_ci 699762306a36Sopenharmony_ci if (tsicr & E1000_TSICR_TXTS) { 699862306a36Sopenharmony_ci /* retrieve hardware timestamp */ 699962306a36Sopenharmony_ci schedule_work(&adapter->ptp_tx_work); 700062306a36Sopenharmony_ci } 700162306a36Sopenharmony_ci 700262306a36Sopenharmony_ci if (tsicr & TSINTR_TT0) 700362306a36Sopenharmony_ci igb_perout(adapter, 0); 700462306a36Sopenharmony_ci 700562306a36Sopenharmony_ci if (tsicr & TSINTR_TT1) 700662306a36Sopenharmony_ci igb_perout(adapter, 1); 700762306a36Sopenharmony_ci 700862306a36Sopenharmony_ci if (tsicr & TSINTR_AUTT0) 700962306a36Sopenharmony_ci igb_extts(adapter, 0); 701062306a36Sopenharmony_ci 701162306a36Sopenharmony_ci if (tsicr & TSINTR_AUTT1) 701262306a36Sopenharmony_ci igb_extts(adapter, 1); 701362306a36Sopenharmony_ci} 701462306a36Sopenharmony_ci 701562306a36Sopenharmony_cistatic irqreturn_t igb_msix_other(int irq, void *data) 701662306a36Sopenharmony_ci{ 701762306a36Sopenharmony_ci struct igb_adapter *adapter = data; 701862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 701962306a36Sopenharmony_ci u32 icr = rd32(E1000_ICR); 702062306a36Sopenharmony_ci /* reading ICR causes bit 31 of EICR to be cleared */ 702162306a36Sopenharmony_ci 702262306a36Sopenharmony_ci if (icr & E1000_ICR_DRSTA) 702362306a36Sopenharmony_ci schedule_work(&adapter->reset_task); 702462306a36Sopenharmony_ci 702562306a36Sopenharmony_ci if (icr & E1000_ICR_DOUTSYNC) { 702662306a36Sopenharmony_ci /* HW is reporting DMA is out of sync */ 702762306a36Sopenharmony_ci adapter->stats.doosync++; 702862306a36Sopenharmony_ci /* The DMA Out of Sync is also indication of a spoof event 702962306a36Sopenharmony_ci * in IOV mode. Check the Wrong VM Behavior register to 703062306a36Sopenharmony_ci * see if it is really a spoof event. 703162306a36Sopenharmony_ci */ 703262306a36Sopenharmony_ci igb_check_wvbr(adapter); 703362306a36Sopenharmony_ci } 703462306a36Sopenharmony_ci 703562306a36Sopenharmony_ci /* Check for a mailbox event */ 703662306a36Sopenharmony_ci if (icr & E1000_ICR_VMMB) 703762306a36Sopenharmony_ci igb_msg_task(adapter); 703862306a36Sopenharmony_ci 703962306a36Sopenharmony_ci if (icr & E1000_ICR_LSC) { 704062306a36Sopenharmony_ci hw->mac.get_link_status = 1; 704162306a36Sopenharmony_ci /* guard against interrupt when we're going down */ 704262306a36Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) 704362306a36Sopenharmony_ci mod_timer(&adapter->watchdog_timer, jiffies + 1); 704462306a36Sopenharmony_ci } 704562306a36Sopenharmony_ci 704662306a36Sopenharmony_ci if (icr & E1000_ICR_TS) 704762306a36Sopenharmony_ci igb_tsync_interrupt(adapter); 704862306a36Sopenharmony_ci 704962306a36Sopenharmony_ci wr32(E1000_EIMS, adapter->eims_other); 705062306a36Sopenharmony_ci 705162306a36Sopenharmony_ci return IRQ_HANDLED; 705262306a36Sopenharmony_ci} 705362306a36Sopenharmony_ci 705462306a36Sopenharmony_cistatic void igb_write_itr(struct igb_q_vector *q_vector) 705562306a36Sopenharmony_ci{ 705662306a36Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 705762306a36Sopenharmony_ci u32 itr_val = q_vector->itr_val & 0x7FFC; 705862306a36Sopenharmony_ci 705962306a36Sopenharmony_ci if (!q_vector->set_itr) 706062306a36Sopenharmony_ci return; 706162306a36Sopenharmony_ci 706262306a36Sopenharmony_ci if (!itr_val) 706362306a36Sopenharmony_ci itr_val = 0x4; 706462306a36Sopenharmony_ci 706562306a36Sopenharmony_ci if (adapter->hw.mac.type == e1000_82575) 706662306a36Sopenharmony_ci itr_val |= itr_val << 16; 706762306a36Sopenharmony_ci else 706862306a36Sopenharmony_ci itr_val |= E1000_EITR_CNT_IGNR; 706962306a36Sopenharmony_ci 707062306a36Sopenharmony_ci writel(itr_val, q_vector->itr_register); 707162306a36Sopenharmony_ci q_vector->set_itr = 0; 707262306a36Sopenharmony_ci} 707362306a36Sopenharmony_ci 707462306a36Sopenharmony_cistatic irqreturn_t igb_msix_ring(int irq, void *data) 707562306a36Sopenharmony_ci{ 707662306a36Sopenharmony_ci struct igb_q_vector *q_vector = data; 707762306a36Sopenharmony_ci 707862306a36Sopenharmony_ci /* Write the ITR value calculated from the previous interrupt. */ 707962306a36Sopenharmony_ci igb_write_itr(q_vector); 708062306a36Sopenharmony_ci 708162306a36Sopenharmony_ci napi_schedule(&q_vector->napi); 708262306a36Sopenharmony_ci 708362306a36Sopenharmony_ci return IRQ_HANDLED; 708462306a36Sopenharmony_ci} 708562306a36Sopenharmony_ci 708662306a36Sopenharmony_ci#ifdef CONFIG_IGB_DCA 708762306a36Sopenharmony_cistatic void igb_update_tx_dca(struct igb_adapter *adapter, 708862306a36Sopenharmony_ci struct igb_ring *tx_ring, 708962306a36Sopenharmony_ci int cpu) 709062306a36Sopenharmony_ci{ 709162306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 709262306a36Sopenharmony_ci u32 txctrl = dca3_get_tag(tx_ring->dev, cpu); 709362306a36Sopenharmony_ci 709462306a36Sopenharmony_ci if (hw->mac.type != e1000_82575) 709562306a36Sopenharmony_ci txctrl <<= E1000_DCA_TXCTRL_CPUID_SHIFT; 709662306a36Sopenharmony_ci 709762306a36Sopenharmony_ci /* We can enable relaxed ordering for reads, but not writes when 709862306a36Sopenharmony_ci * DCA is enabled. This is due to a known issue in some chipsets 709962306a36Sopenharmony_ci * which will cause the DCA tag to be cleared. 710062306a36Sopenharmony_ci */ 710162306a36Sopenharmony_ci txctrl |= E1000_DCA_TXCTRL_DESC_RRO_EN | 710262306a36Sopenharmony_ci E1000_DCA_TXCTRL_DATA_RRO_EN | 710362306a36Sopenharmony_ci E1000_DCA_TXCTRL_DESC_DCA_EN; 710462306a36Sopenharmony_ci 710562306a36Sopenharmony_ci wr32(E1000_DCA_TXCTRL(tx_ring->reg_idx), txctrl); 710662306a36Sopenharmony_ci} 710762306a36Sopenharmony_ci 710862306a36Sopenharmony_cistatic void igb_update_rx_dca(struct igb_adapter *adapter, 710962306a36Sopenharmony_ci struct igb_ring *rx_ring, 711062306a36Sopenharmony_ci int cpu) 711162306a36Sopenharmony_ci{ 711262306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 711362306a36Sopenharmony_ci u32 rxctrl = dca3_get_tag(&adapter->pdev->dev, cpu); 711462306a36Sopenharmony_ci 711562306a36Sopenharmony_ci if (hw->mac.type != e1000_82575) 711662306a36Sopenharmony_ci rxctrl <<= E1000_DCA_RXCTRL_CPUID_SHIFT; 711762306a36Sopenharmony_ci 711862306a36Sopenharmony_ci /* We can enable relaxed ordering for reads, but not writes when 711962306a36Sopenharmony_ci * DCA is enabled. This is due to a known issue in some chipsets 712062306a36Sopenharmony_ci * which will cause the DCA tag to be cleared. 712162306a36Sopenharmony_ci */ 712262306a36Sopenharmony_ci rxctrl |= E1000_DCA_RXCTRL_DESC_RRO_EN | 712362306a36Sopenharmony_ci E1000_DCA_RXCTRL_DESC_DCA_EN; 712462306a36Sopenharmony_ci 712562306a36Sopenharmony_ci wr32(E1000_DCA_RXCTRL(rx_ring->reg_idx), rxctrl); 712662306a36Sopenharmony_ci} 712762306a36Sopenharmony_ci 712862306a36Sopenharmony_cistatic void igb_update_dca(struct igb_q_vector *q_vector) 712962306a36Sopenharmony_ci{ 713062306a36Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 713162306a36Sopenharmony_ci int cpu = get_cpu(); 713262306a36Sopenharmony_ci 713362306a36Sopenharmony_ci if (q_vector->cpu == cpu) 713462306a36Sopenharmony_ci goto out_no_update; 713562306a36Sopenharmony_ci 713662306a36Sopenharmony_ci if (q_vector->tx.ring) 713762306a36Sopenharmony_ci igb_update_tx_dca(adapter, q_vector->tx.ring, cpu); 713862306a36Sopenharmony_ci 713962306a36Sopenharmony_ci if (q_vector->rx.ring) 714062306a36Sopenharmony_ci igb_update_rx_dca(adapter, q_vector->rx.ring, cpu); 714162306a36Sopenharmony_ci 714262306a36Sopenharmony_ci q_vector->cpu = cpu; 714362306a36Sopenharmony_ciout_no_update: 714462306a36Sopenharmony_ci put_cpu(); 714562306a36Sopenharmony_ci} 714662306a36Sopenharmony_ci 714762306a36Sopenharmony_cistatic void igb_setup_dca(struct igb_adapter *adapter) 714862306a36Sopenharmony_ci{ 714962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 715062306a36Sopenharmony_ci int i; 715162306a36Sopenharmony_ci 715262306a36Sopenharmony_ci if (!(adapter->flags & IGB_FLAG_DCA_ENABLED)) 715362306a36Sopenharmony_ci return; 715462306a36Sopenharmony_ci 715562306a36Sopenharmony_ci /* Always use CB2 mode, difference is masked in the CB driver. */ 715662306a36Sopenharmony_ci wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2); 715762306a36Sopenharmony_ci 715862306a36Sopenharmony_ci for (i = 0; i < adapter->num_q_vectors; i++) { 715962306a36Sopenharmony_ci adapter->q_vector[i]->cpu = -1; 716062306a36Sopenharmony_ci igb_update_dca(adapter->q_vector[i]); 716162306a36Sopenharmony_ci } 716262306a36Sopenharmony_ci} 716362306a36Sopenharmony_ci 716462306a36Sopenharmony_cistatic int __igb_notify_dca(struct device *dev, void *data) 716562306a36Sopenharmony_ci{ 716662306a36Sopenharmony_ci struct net_device *netdev = dev_get_drvdata(dev); 716762306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 716862306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 716962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 717062306a36Sopenharmony_ci unsigned long event = *(unsigned long *)data; 717162306a36Sopenharmony_ci 717262306a36Sopenharmony_ci switch (event) { 717362306a36Sopenharmony_ci case DCA_PROVIDER_ADD: 717462306a36Sopenharmony_ci /* if already enabled, don't do it again */ 717562306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_DCA_ENABLED) 717662306a36Sopenharmony_ci break; 717762306a36Sopenharmony_ci if (dca_add_requester(dev) == 0) { 717862306a36Sopenharmony_ci adapter->flags |= IGB_FLAG_DCA_ENABLED; 717962306a36Sopenharmony_ci dev_info(&pdev->dev, "DCA enabled\n"); 718062306a36Sopenharmony_ci igb_setup_dca(adapter); 718162306a36Sopenharmony_ci break; 718262306a36Sopenharmony_ci } 718362306a36Sopenharmony_ci fallthrough; /* since DCA is disabled. */ 718462306a36Sopenharmony_ci case DCA_PROVIDER_REMOVE: 718562306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_DCA_ENABLED) { 718662306a36Sopenharmony_ci /* without this a class_device is left 718762306a36Sopenharmony_ci * hanging around in the sysfs model 718862306a36Sopenharmony_ci */ 718962306a36Sopenharmony_ci dca_remove_requester(dev); 719062306a36Sopenharmony_ci dev_info(&pdev->dev, "DCA disabled\n"); 719162306a36Sopenharmony_ci adapter->flags &= ~IGB_FLAG_DCA_ENABLED; 719262306a36Sopenharmony_ci wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_DISABLE); 719362306a36Sopenharmony_ci } 719462306a36Sopenharmony_ci break; 719562306a36Sopenharmony_ci } 719662306a36Sopenharmony_ci 719762306a36Sopenharmony_ci return 0; 719862306a36Sopenharmony_ci} 719962306a36Sopenharmony_ci 720062306a36Sopenharmony_cistatic int igb_notify_dca(struct notifier_block *nb, unsigned long event, 720162306a36Sopenharmony_ci void *p) 720262306a36Sopenharmony_ci{ 720362306a36Sopenharmony_ci int ret_val; 720462306a36Sopenharmony_ci 720562306a36Sopenharmony_ci ret_val = driver_for_each_device(&igb_driver.driver, NULL, &event, 720662306a36Sopenharmony_ci __igb_notify_dca); 720762306a36Sopenharmony_ci 720862306a36Sopenharmony_ci return ret_val ? NOTIFY_BAD : NOTIFY_DONE; 720962306a36Sopenharmony_ci} 721062306a36Sopenharmony_ci#endif /* CONFIG_IGB_DCA */ 721162306a36Sopenharmony_ci 721262306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 721362306a36Sopenharmony_cistatic int igb_vf_configure(struct igb_adapter *adapter, int vf) 721462306a36Sopenharmony_ci{ 721562306a36Sopenharmony_ci unsigned char mac_addr[ETH_ALEN]; 721662306a36Sopenharmony_ci 721762306a36Sopenharmony_ci eth_zero_addr(mac_addr); 721862306a36Sopenharmony_ci igb_set_vf_mac(adapter, vf, mac_addr); 721962306a36Sopenharmony_ci 722062306a36Sopenharmony_ci /* By default spoof check is enabled for all VFs */ 722162306a36Sopenharmony_ci adapter->vf_data[vf].spoofchk_enabled = true; 722262306a36Sopenharmony_ci 722362306a36Sopenharmony_ci /* By default VFs are not trusted */ 722462306a36Sopenharmony_ci adapter->vf_data[vf].trusted = false; 722562306a36Sopenharmony_ci 722662306a36Sopenharmony_ci return 0; 722762306a36Sopenharmony_ci} 722862306a36Sopenharmony_ci 722962306a36Sopenharmony_ci#endif 723062306a36Sopenharmony_cistatic void igb_ping_all_vfs(struct igb_adapter *adapter) 723162306a36Sopenharmony_ci{ 723262306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 723362306a36Sopenharmony_ci u32 ping; 723462306a36Sopenharmony_ci int i; 723562306a36Sopenharmony_ci 723662306a36Sopenharmony_ci for (i = 0 ; i < adapter->vfs_allocated_count; i++) { 723762306a36Sopenharmony_ci ping = E1000_PF_CONTROL_MSG; 723862306a36Sopenharmony_ci if (adapter->vf_data[i].flags & IGB_VF_FLAG_CTS) 723962306a36Sopenharmony_ci ping |= E1000_VT_MSGTYPE_CTS; 724062306a36Sopenharmony_ci igb_write_mbx(hw, &ping, 1, i); 724162306a36Sopenharmony_ci } 724262306a36Sopenharmony_ci} 724362306a36Sopenharmony_ci 724462306a36Sopenharmony_cistatic int igb_set_vf_promisc(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) 724562306a36Sopenharmony_ci{ 724662306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 724762306a36Sopenharmony_ci u32 vmolr = rd32(E1000_VMOLR(vf)); 724862306a36Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 724962306a36Sopenharmony_ci 725062306a36Sopenharmony_ci vf_data->flags &= ~(IGB_VF_FLAG_UNI_PROMISC | 725162306a36Sopenharmony_ci IGB_VF_FLAG_MULTI_PROMISC); 725262306a36Sopenharmony_ci vmolr &= ~(E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE | E1000_VMOLR_MPME); 725362306a36Sopenharmony_ci 725462306a36Sopenharmony_ci if (*msgbuf & E1000_VF_SET_PROMISC_MULTICAST) { 725562306a36Sopenharmony_ci vmolr |= E1000_VMOLR_MPME; 725662306a36Sopenharmony_ci vf_data->flags |= IGB_VF_FLAG_MULTI_PROMISC; 725762306a36Sopenharmony_ci *msgbuf &= ~E1000_VF_SET_PROMISC_MULTICAST; 725862306a36Sopenharmony_ci } else { 725962306a36Sopenharmony_ci /* if we have hashes and we are clearing a multicast promisc 726062306a36Sopenharmony_ci * flag we need to write the hashes to the MTA as this step 726162306a36Sopenharmony_ci * was previously skipped 726262306a36Sopenharmony_ci */ 726362306a36Sopenharmony_ci if (vf_data->num_vf_mc_hashes > 30) { 726462306a36Sopenharmony_ci vmolr |= E1000_VMOLR_MPME; 726562306a36Sopenharmony_ci } else if (vf_data->num_vf_mc_hashes) { 726662306a36Sopenharmony_ci int j; 726762306a36Sopenharmony_ci 726862306a36Sopenharmony_ci vmolr |= E1000_VMOLR_ROMPE; 726962306a36Sopenharmony_ci for (j = 0; j < vf_data->num_vf_mc_hashes; j++) 727062306a36Sopenharmony_ci igb_mta_set(hw, vf_data->vf_mc_hashes[j]); 727162306a36Sopenharmony_ci } 727262306a36Sopenharmony_ci } 727362306a36Sopenharmony_ci 727462306a36Sopenharmony_ci wr32(E1000_VMOLR(vf), vmolr); 727562306a36Sopenharmony_ci 727662306a36Sopenharmony_ci /* there are flags left unprocessed, likely not supported */ 727762306a36Sopenharmony_ci if (*msgbuf & E1000_VT_MSGINFO_MASK) 727862306a36Sopenharmony_ci return -EINVAL; 727962306a36Sopenharmony_ci 728062306a36Sopenharmony_ci return 0; 728162306a36Sopenharmony_ci} 728262306a36Sopenharmony_ci 728362306a36Sopenharmony_cistatic int igb_set_vf_multicasts(struct igb_adapter *adapter, 728462306a36Sopenharmony_ci u32 *msgbuf, u32 vf) 728562306a36Sopenharmony_ci{ 728662306a36Sopenharmony_ci int n = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; 728762306a36Sopenharmony_ci u16 *hash_list = (u16 *)&msgbuf[1]; 728862306a36Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 728962306a36Sopenharmony_ci int i; 729062306a36Sopenharmony_ci 729162306a36Sopenharmony_ci /* salt away the number of multicast addresses assigned 729262306a36Sopenharmony_ci * to this VF for later use to restore when the PF multi cast 729362306a36Sopenharmony_ci * list changes 729462306a36Sopenharmony_ci */ 729562306a36Sopenharmony_ci vf_data->num_vf_mc_hashes = n; 729662306a36Sopenharmony_ci 729762306a36Sopenharmony_ci /* only up to 30 hash values supported */ 729862306a36Sopenharmony_ci if (n > 30) 729962306a36Sopenharmony_ci n = 30; 730062306a36Sopenharmony_ci 730162306a36Sopenharmony_ci /* store the hashes for later use */ 730262306a36Sopenharmony_ci for (i = 0; i < n; i++) 730362306a36Sopenharmony_ci vf_data->vf_mc_hashes[i] = hash_list[i]; 730462306a36Sopenharmony_ci 730562306a36Sopenharmony_ci /* Flush and reset the mta with the new values */ 730662306a36Sopenharmony_ci igb_set_rx_mode(adapter->netdev); 730762306a36Sopenharmony_ci 730862306a36Sopenharmony_ci return 0; 730962306a36Sopenharmony_ci} 731062306a36Sopenharmony_ci 731162306a36Sopenharmony_cistatic void igb_restore_vf_multicasts(struct igb_adapter *adapter) 731262306a36Sopenharmony_ci{ 731362306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 731462306a36Sopenharmony_ci struct vf_data_storage *vf_data; 731562306a36Sopenharmony_ci int i, j; 731662306a36Sopenharmony_ci 731762306a36Sopenharmony_ci for (i = 0; i < adapter->vfs_allocated_count; i++) { 731862306a36Sopenharmony_ci u32 vmolr = rd32(E1000_VMOLR(i)); 731962306a36Sopenharmony_ci 732062306a36Sopenharmony_ci vmolr &= ~(E1000_VMOLR_ROMPE | E1000_VMOLR_MPME); 732162306a36Sopenharmony_ci 732262306a36Sopenharmony_ci vf_data = &adapter->vf_data[i]; 732362306a36Sopenharmony_ci 732462306a36Sopenharmony_ci if ((vf_data->num_vf_mc_hashes > 30) || 732562306a36Sopenharmony_ci (vf_data->flags & IGB_VF_FLAG_MULTI_PROMISC)) { 732662306a36Sopenharmony_ci vmolr |= E1000_VMOLR_MPME; 732762306a36Sopenharmony_ci } else if (vf_data->num_vf_mc_hashes) { 732862306a36Sopenharmony_ci vmolr |= E1000_VMOLR_ROMPE; 732962306a36Sopenharmony_ci for (j = 0; j < vf_data->num_vf_mc_hashes; j++) 733062306a36Sopenharmony_ci igb_mta_set(hw, vf_data->vf_mc_hashes[j]); 733162306a36Sopenharmony_ci } 733262306a36Sopenharmony_ci wr32(E1000_VMOLR(i), vmolr); 733362306a36Sopenharmony_ci } 733462306a36Sopenharmony_ci} 733562306a36Sopenharmony_ci 733662306a36Sopenharmony_cistatic void igb_clear_vf_vfta(struct igb_adapter *adapter, u32 vf) 733762306a36Sopenharmony_ci{ 733862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 733962306a36Sopenharmony_ci u32 pool_mask, vlvf_mask, i; 734062306a36Sopenharmony_ci 734162306a36Sopenharmony_ci /* create mask for VF and other pools */ 734262306a36Sopenharmony_ci pool_mask = E1000_VLVF_POOLSEL_MASK; 734362306a36Sopenharmony_ci vlvf_mask = BIT(E1000_VLVF_POOLSEL_SHIFT + vf); 734462306a36Sopenharmony_ci 734562306a36Sopenharmony_ci /* drop PF from pool bits */ 734662306a36Sopenharmony_ci pool_mask &= ~BIT(E1000_VLVF_POOLSEL_SHIFT + 734762306a36Sopenharmony_ci adapter->vfs_allocated_count); 734862306a36Sopenharmony_ci 734962306a36Sopenharmony_ci /* Find the vlan filter for this id */ 735062306a36Sopenharmony_ci for (i = E1000_VLVF_ARRAY_SIZE; i--;) { 735162306a36Sopenharmony_ci u32 vlvf = rd32(E1000_VLVF(i)); 735262306a36Sopenharmony_ci u32 vfta_mask, vid, vfta; 735362306a36Sopenharmony_ci 735462306a36Sopenharmony_ci /* remove the vf from the pool */ 735562306a36Sopenharmony_ci if (!(vlvf & vlvf_mask)) 735662306a36Sopenharmony_ci continue; 735762306a36Sopenharmony_ci 735862306a36Sopenharmony_ci /* clear out bit from VLVF */ 735962306a36Sopenharmony_ci vlvf ^= vlvf_mask; 736062306a36Sopenharmony_ci 736162306a36Sopenharmony_ci /* if other pools are present, just remove ourselves */ 736262306a36Sopenharmony_ci if (vlvf & pool_mask) 736362306a36Sopenharmony_ci goto update_vlvfb; 736462306a36Sopenharmony_ci 736562306a36Sopenharmony_ci /* if PF is present, leave VFTA */ 736662306a36Sopenharmony_ci if (vlvf & E1000_VLVF_POOLSEL_MASK) 736762306a36Sopenharmony_ci goto update_vlvf; 736862306a36Sopenharmony_ci 736962306a36Sopenharmony_ci vid = vlvf & E1000_VLVF_VLANID_MASK; 737062306a36Sopenharmony_ci vfta_mask = BIT(vid % 32); 737162306a36Sopenharmony_ci 737262306a36Sopenharmony_ci /* clear bit from VFTA */ 737362306a36Sopenharmony_ci vfta = adapter->shadow_vfta[vid / 32]; 737462306a36Sopenharmony_ci if (vfta & vfta_mask) 737562306a36Sopenharmony_ci hw->mac.ops.write_vfta(hw, vid / 32, vfta ^ vfta_mask); 737662306a36Sopenharmony_ciupdate_vlvf: 737762306a36Sopenharmony_ci /* clear pool selection enable */ 737862306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_VLAN_PROMISC) 737962306a36Sopenharmony_ci vlvf &= E1000_VLVF_POOLSEL_MASK; 738062306a36Sopenharmony_ci else 738162306a36Sopenharmony_ci vlvf = 0; 738262306a36Sopenharmony_ciupdate_vlvfb: 738362306a36Sopenharmony_ci /* clear pool bits */ 738462306a36Sopenharmony_ci wr32(E1000_VLVF(i), vlvf); 738562306a36Sopenharmony_ci } 738662306a36Sopenharmony_ci} 738762306a36Sopenharmony_ci 738862306a36Sopenharmony_cistatic int igb_find_vlvf_entry(struct e1000_hw *hw, u32 vlan) 738962306a36Sopenharmony_ci{ 739062306a36Sopenharmony_ci u32 vlvf; 739162306a36Sopenharmony_ci int idx; 739262306a36Sopenharmony_ci 739362306a36Sopenharmony_ci /* short cut the special case */ 739462306a36Sopenharmony_ci if (vlan == 0) 739562306a36Sopenharmony_ci return 0; 739662306a36Sopenharmony_ci 739762306a36Sopenharmony_ci /* Search for the VLAN id in the VLVF entries */ 739862306a36Sopenharmony_ci for (idx = E1000_VLVF_ARRAY_SIZE; --idx;) { 739962306a36Sopenharmony_ci vlvf = rd32(E1000_VLVF(idx)); 740062306a36Sopenharmony_ci if ((vlvf & VLAN_VID_MASK) == vlan) 740162306a36Sopenharmony_ci break; 740262306a36Sopenharmony_ci } 740362306a36Sopenharmony_ci 740462306a36Sopenharmony_ci return idx; 740562306a36Sopenharmony_ci} 740662306a36Sopenharmony_ci 740762306a36Sopenharmony_cistatic void igb_update_pf_vlvf(struct igb_adapter *adapter, u32 vid) 740862306a36Sopenharmony_ci{ 740962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 741062306a36Sopenharmony_ci u32 bits, pf_id; 741162306a36Sopenharmony_ci int idx; 741262306a36Sopenharmony_ci 741362306a36Sopenharmony_ci idx = igb_find_vlvf_entry(hw, vid); 741462306a36Sopenharmony_ci if (!idx) 741562306a36Sopenharmony_ci return; 741662306a36Sopenharmony_ci 741762306a36Sopenharmony_ci /* See if any other pools are set for this VLAN filter 741862306a36Sopenharmony_ci * entry other than the PF. 741962306a36Sopenharmony_ci */ 742062306a36Sopenharmony_ci pf_id = adapter->vfs_allocated_count + E1000_VLVF_POOLSEL_SHIFT; 742162306a36Sopenharmony_ci bits = ~BIT(pf_id) & E1000_VLVF_POOLSEL_MASK; 742262306a36Sopenharmony_ci bits &= rd32(E1000_VLVF(idx)); 742362306a36Sopenharmony_ci 742462306a36Sopenharmony_ci /* Disable the filter so this falls into the default pool. */ 742562306a36Sopenharmony_ci if (!bits) { 742662306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_VLAN_PROMISC) 742762306a36Sopenharmony_ci wr32(E1000_VLVF(idx), BIT(pf_id)); 742862306a36Sopenharmony_ci else 742962306a36Sopenharmony_ci wr32(E1000_VLVF(idx), 0); 743062306a36Sopenharmony_ci } 743162306a36Sopenharmony_ci} 743262306a36Sopenharmony_ci 743362306a36Sopenharmony_cistatic s32 igb_set_vf_vlan(struct igb_adapter *adapter, u32 vid, 743462306a36Sopenharmony_ci bool add, u32 vf) 743562306a36Sopenharmony_ci{ 743662306a36Sopenharmony_ci int pf_id = adapter->vfs_allocated_count; 743762306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 743862306a36Sopenharmony_ci int err; 743962306a36Sopenharmony_ci 744062306a36Sopenharmony_ci /* If VLAN overlaps with one the PF is currently monitoring make 744162306a36Sopenharmony_ci * sure that we are able to allocate a VLVF entry. This may be 744262306a36Sopenharmony_ci * redundant but it guarantees PF will maintain visibility to 744362306a36Sopenharmony_ci * the VLAN. 744462306a36Sopenharmony_ci */ 744562306a36Sopenharmony_ci if (add && test_bit(vid, adapter->active_vlans)) { 744662306a36Sopenharmony_ci err = igb_vfta_set(hw, vid, pf_id, true, false); 744762306a36Sopenharmony_ci if (err) 744862306a36Sopenharmony_ci return err; 744962306a36Sopenharmony_ci } 745062306a36Sopenharmony_ci 745162306a36Sopenharmony_ci err = igb_vfta_set(hw, vid, vf, add, false); 745262306a36Sopenharmony_ci 745362306a36Sopenharmony_ci if (add && !err) 745462306a36Sopenharmony_ci return err; 745562306a36Sopenharmony_ci 745662306a36Sopenharmony_ci /* If we failed to add the VF VLAN or we are removing the VF VLAN 745762306a36Sopenharmony_ci * we may need to drop the PF pool bit in order to allow us to free 745862306a36Sopenharmony_ci * up the VLVF resources. 745962306a36Sopenharmony_ci */ 746062306a36Sopenharmony_ci if (test_bit(vid, adapter->active_vlans) || 746162306a36Sopenharmony_ci (adapter->flags & IGB_FLAG_VLAN_PROMISC)) 746262306a36Sopenharmony_ci igb_update_pf_vlvf(adapter, vid); 746362306a36Sopenharmony_ci 746462306a36Sopenharmony_ci return err; 746562306a36Sopenharmony_ci} 746662306a36Sopenharmony_ci 746762306a36Sopenharmony_cistatic void igb_set_vmvir(struct igb_adapter *adapter, u32 vid, u32 vf) 746862306a36Sopenharmony_ci{ 746962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 747062306a36Sopenharmony_ci 747162306a36Sopenharmony_ci if (vid) 747262306a36Sopenharmony_ci wr32(E1000_VMVIR(vf), (vid | E1000_VMVIR_VLANA_DEFAULT)); 747362306a36Sopenharmony_ci else 747462306a36Sopenharmony_ci wr32(E1000_VMVIR(vf), 0); 747562306a36Sopenharmony_ci} 747662306a36Sopenharmony_ci 747762306a36Sopenharmony_cistatic int igb_enable_port_vlan(struct igb_adapter *adapter, int vf, 747862306a36Sopenharmony_ci u16 vlan, u8 qos) 747962306a36Sopenharmony_ci{ 748062306a36Sopenharmony_ci int err; 748162306a36Sopenharmony_ci 748262306a36Sopenharmony_ci err = igb_set_vf_vlan(adapter, vlan, true, vf); 748362306a36Sopenharmony_ci if (err) 748462306a36Sopenharmony_ci return err; 748562306a36Sopenharmony_ci 748662306a36Sopenharmony_ci igb_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf); 748762306a36Sopenharmony_ci igb_set_vmolr(adapter, vf, !vlan); 748862306a36Sopenharmony_ci 748962306a36Sopenharmony_ci /* revoke access to previous VLAN */ 749062306a36Sopenharmony_ci if (vlan != adapter->vf_data[vf].pf_vlan) 749162306a36Sopenharmony_ci igb_set_vf_vlan(adapter, adapter->vf_data[vf].pf_vlan, 749262306a36Sopenharmony_ci false, vf); 749362306a36Sopenharmony_ci 749462306a36Sopenharmony_ci adapter->vf_data[vf].pf_vlan = vlan; 749562306a36Sopenharmony_ci adapter->vf_data[vf].pf_qos = qos; 749662306a36Sopenharmony_ci igb_set_vf_vlan_strip(adapter, vf, true); 749762306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, 749862306a36Sopenharmony_ci "Setting VLAN %d, QOS 0x%x on VF %d\n", vlan, qos, vf); 749962306a36Sopenharmony_ci if (test_bit(__IGB_DOWN, &adapter->state)) { 750062306a36Sopenharmony_ci dev_warn(&adapter->pdev->dev, 750162306a36Sopenharmony_ci "The VF VLAN has been set, but the PF device is not up.\n"); 750262306a36Sopenharmony_ci dev_warn(&adapter->pdev->dev, 750362306a36Sopenharmony_ci "Bring the PF device up before attempting to use the VF device.\n"); 750462306a36Sopenharmony_ci } 750562306a36Sopenharmony_ci 750662306a36Sopenharmony_ci return err; 750762306a36Sopenharmony_ci} 750862306a36Sopenharmony_ci 750962306a36Sopenharmony_cistatic int igb_disable_port_vlan(struct igb_adapter *adapter, int vf) 751062306a36Sopenharmony_ci{ 751162306a36Sopenharmony_ci /* Restore tagless access via VLAN 0 */ 751262306a36Sopenharmony_ci igb_set_vf_vlan(adapter, 0, true, vf); 751362306a36Sopenharmony_ci 751462306a36Sopenharmony_ci igb_set_vmvir(adapter, 0, vf); 751562306a36Sopenharmony_ci igb_set_vmolr(adapter, vf, true); 751662306a36Sopenharmony_ci 751762306a36Sopenharmony_ci /* Remove any PF assigned VLAN */ 751862306a36Sopenharmony_ci if (adapter->vf_data[vf].pf_vlan) 751962306a36Sopenharmony_ci igb_set_vf_vlan(adapter, adapter->vf_data[vf].pf_vlan, 752062306a36Sopenharmony_ci false, vf); 752162306a36Sopenharmony_ci 752262306a36Sopenharmony_ci adapter->vf_data[vf].pf_vlan = 0; 752362306a36Sopenharmony_ci adapter->vf_data[vf].pf_qos = 0; 752462306a36Sopenharmony_ci igb_set_vf_vlan_strip(adapter, vf, false); 752562306a36Sopenharmony_ci 752662306a36Sopenharmony_ci return 0; 752762306a36Sopenharmony_ci} 752862306a36Sopenharmony_ci 752962306a36Sopenharmony_cistatic int igb_ndo_set_vf_vlan(struct net_device *netdev, int vf, 753062306a36Sopenharmony_ci u16 vlan, u8 qos, __be16 vlan_proto) 753162306a36Sopenharmony_ci{ 753262306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 753362306a36Sopenharmony_ci 753462306a36Sopenharmony_ci if ((vf >= adapter->vfs_allocated_count) || (vlan > 4095) || (qos > 7)) 753562306a36Sopenharmony_ci return -EINVAL; 753662306a36Sopenharmony_ci 753762306a36Sopenharmony_ci if (vlan_proto != htons(ETH_P_8021Q)) 753862306a36Sopenharmony_ci return -EPROTONOSUPPORT; 753962306a36Sopenharmony_ci 754062306a36Sopenharmony_ci return (vlan || qos) ? igb_enable_port_vlan(adapter, vf, vlan, qos) : 754162306a36Sopenharmony_ci igb_disable_port_vlan(adapter, vf); 754262306a36Sopenharmony_ci} 754362306a36Sopenharmony_ci 754462306a36Sopenharmony_cistatic int igb_set_vf_vlan_msg(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) 754562306a36Sopenharmony_ci{ 754662306a36Sopenharmony_ci int add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; 754762306a36Sopenharmony_ci int vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK); 754862306a36Sopenharmony_ci int ret; 754962306a36Sopenharmony_ci 755062306a36Sopenharmony_ci if (adapter->vf_data[vf].pf_vlan) 755162306a36Sopenharmony_ci return -1; 755262306a36Sopenharmony_ci 755362306a36Sopenharmony_ci /* VLAN 0 is a special case, don't allow it to be removed */ 755462306a36Sopenharmony_ci if (!vid && !add) 755562306a36Sopenharmony_ci return 0; 755662306a36Sopenharmony_ci 755762306a36Sopenharmony_ci ret = igb_set_vf_vlan(adapter, vid, !!add, vf); 755862306a36Sopenharmony_ci if (!ret) 755962306a36Sopenharmony_ci igb_set_vf_vlan_strip(adapter, vf, !!vid); 756062306a36Sopenharmony_ci return ret; 756162306a36Sopenharmony_ci} 756262306a36Sopenharmony_ci 756362306a36Sopenharmony_cistatic inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf) 756462306a36Sopenharmony_ci{ 756562306a36Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 756662306a36Sopenharmony_ci 756762306a36Sopenharmony_ci /* clear flags - except flag that indicates PF has set the MAC */ 756862306a36Sopenharmony_ci vf_data->flags &= IGB_VF_FLAG_PF_SET_MAC; 756962306a36Sopenharmony_ci vf_data->last_nack = jiffies; 757062306a36Sopenharmony_ci 757162306a36Sopenharmony_ci /* reset vlans for device */ 757262306a36Sopenharmony_ci igb_clear_vf_vfta(adapter, vf); 757362306a36Sopenharmony_ci igb_set_vf_vlan(adapter, vf_data->pf_vlan, true, vf); 757462306a36Sopenharmony_ci igb_set_vmvir(adapter, vf_data->pf_vlan | 757562306a36Sopenharmony_ci (vf_data->pf_qos << VLAN_PRIO_SHIFT), vf); 757662306a36Sopenharmony_ci igb_set_vmolr(adapter, vf, !vf_data->pf_vlan); 757762306a36Sopenharmony_ci igb_set_vf_vlan_strip(adapter, vf, !!(vf_data->pf_vlan)); 757862306a36Sopenharmony_ci 757962306a36Sopenharmony_ci /* reset multicast table array for vf */ 758062306a36Sopenharmony_ci adapter->vf_data[vf].num_vf_mc_hashes = 0; 758162306a36Sopenharmony_ci 758262306a36Sopenharmony_ci /* Flush and reset the mta with the new values */ 758362306a36Sopenharmony_ci igb_set_rx_mode(adapter->netdev); 758462306a36Sopenharmony_ci} 758562306a36Sopenharmony_ci 758662306a36Sopenharmony_cistatic void igb_vf_reset_event(struct igb_adapter *adapter, u32 vf) 758762306a36Sopenharmony_ci{ 758862306a36Sopenharmony_ci unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; 758962306a36Sopenharmony_ci 759062306a36Sopenharmony_ci /* clear mac address as we were hotplug removed/added */ 759162306a36Sopenharmony_ci if (!(adapter->vf_data[vf].flags & IGB_VF_FLAG_PF_SET_MAC)) 759262306a36Sopenharmony_ci eth_zero_addr(vf_mac); 759362306a36Sopenharmony_ci 759462306a36Sopenharmony_ci /* process remaining reset events */ 759562306a36Sopenharmony_ci igb_vf_reset(adapter, vf); 759662306a36Sopenharmony_ci} 759762306a36Sopenharmony_ci 759862306a36Sopenharmony_cistatic void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) 759962306a36Sopenharmony_ci{ 760062306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 760162306a36Sopenharmony_ci unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; 760262306a36Sopenharmony_ci u32 reg, msgbuf[3] = {}; 760362306a36Sopenharmony_ci u8 *addr = (u8 *)(&msgbuf[1]); 760462306a36Sopenharmony_ci 760562306a36Sopenharmony_ci /* process all the same items cleared in a function level reset */ 760662306a36Sopenharmony_ci igb_vf_reset(adapter, vf); 760762306a36Sopenharmony_ci 760862306a36Sopenharmony_ci /* set vf mac address */ 760962306a36Sopenharmony_ci igb_set_vf_mac(adapter, vf, vf_mac); 761062306a36Sopenharmony_ci 761162306a36Sopenharmony_ci /* enable transmit and receive for vf */ 761262306a36Sopenharmony_ci reg = rd32(E1000_VFTE); 761362306a36Sopenharmony_ci wr32(E1000_VFTE, reg | BIT(vf)); 761462306a36Sopenharmony_ci reg = rd32(E1000_VFRE); 761562306a36Sopenharmony_ci wr32(E1000_VFRE, reg | BIT(vf)); 761662306a36Sopenharmony_ci 761762306a36Sopenharmony_ci adapter->vf_data[vf].flags |= IGB_VF_FLAG_CTS; 761862306a36Sopenharmony_ci 761962306a36Sopenharmony_ci /* reply to reset with ack and vf mac address */ 762062306a36Sopenharmony_ci if (!is_zero_ether_addr(vf_mac)) { 762162306a36Sopenharmony_ci msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; 762262306a36Sopenharmony_ci memcpy(addr, vf_mac, ETH_ALEN); 762362306a36Sopenharmony_ci } else { 762462306a36Sopenharmony_ci msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_NACK; 762562306a36Sopenharmony_ci } 762662306a36Sopenharmony_ci igb_write_mbx(hw, msgbuf, 3, vf); 762762306a36Sopenharmony_ci} 762862306a36Sopenharmony_ci 762962306a36Sopenharmony_cistatic void igb_flush_mac_table(struct igb_adapter *adapter) 763062306a36Sopenharmony_ci{ 763162306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 763262306a36Sopenharmony_ci int i; 763362306a36Sopenharmony_ci 763462306a36Sopenharmony_ci for (i = 0; i < hw->mac.rar_entry_count; i++) { 763562306a36Sopenharmony_ci adapter->mac_table[i].state &= ~IGB_MAC_STATE_IN_USE; 763662306a36Sopenharmony_ci eth_zero_addr(adapter->mac_table[i].addr); 763762306a36Sopenharmony_ci adapter->mac_table[i].queue = 0; 763862306a36Sopenharmony_ci igb_rar_set_index(adapter, i); 763962306a36Sopenharmony_ci } 764062306a36Sopenharmony_ci} 764162306a36Sopenharmony_ci 764262306a36Sopenharmony_cistatic int igb_available_rars(struct igb_adapter *adapter, u8 queue) 764362306a36Sopenharmony_ci{ 764462306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 764562306a36Sopenharmony_ci /* do not count rar entries reserved for VFs MAC addresses */ 764662306a36Sopenharmony_ci int rar_entries = hw->mac.rar_entry_count - 764762306a36Sopenharmony_ci adapter->vfs_allocated_count; 764862306a36Sopenharmony_ci int i, count = 0; 764962306a36Sopenharmony_ci 765062306a36Sopenharmony_ci for (i = 0; i < rar_entries; i++) { 765162306a36Sopenharmony_ci /* do not count default entries */ 765262306a36Sopenharmony_ci if (adapter->mac_table[i].state & IGB_MAC_STATE_DEFAULT) 765362306a36Sopenharmony_ci continue; 765462306a36Sopenharmony_ci 765562306a36Sopenharmony_ci /* do not count "in use" entries for different queues */ 765662306a36Sopenharmony_ci if ((adapter->mac_table[i].state & IGB_MAC_STATE_IN_USE) && 765762306a36Sopenharmony_ci (adapter->mac_table[i].queue != queue)) 765862306a36Sopenharmony_ci continue; 765962306a36Sopenharmony_ci 766062306a36Sopenharmony_ci count++; 766162306a36Sopenharmony_ci } 766262306a36Sopenharmony_ci 766362306a36Sopenharmony_ci return count; 766462306a36Sopenharmony_ci} 766562306a36Sopenharmony_ci 766662306a36Sopenharmony_ci/* Set default MAC address for the PF in the first RAR entry */ 766762306a36Sopenharmony_cistatic void igb_set_default_mac_filter(struct igb_adapter *adapter) 766862306a36Sopenharmony_ci{ 766962306a36Sopenharmony_ci struct igb_mac_addr *mac_table = &adapter->mac_table[0]; 767062306a36Sopenharmony_ci 767162306a36Sopenharmony_ci ether_addr_copy(mac_table->addr, adapter->hw.mac.addr); 767262306a36Sopenharmony_ci mac_table->queue = adapter->vfs_allocated_count; 767362306a36Sopenharmony_ci mac_table->state = IGB_MAC_STATE_DEFAULT | IGB_MAC_STATE_IN_USE; 767462306a36Sopenharmony_ci 767562306a36Sopenharmony_ci igb_rar_set_index(adapter, 0); 767662306a36Sopenharmony_ci} 767762306a36Sopenharmony_ci 767862306a36Sopenharmony_ci/* If the filter to be added and an already existing filter express 767962306a36Sopenharmony_ci * the same address and address type, it should be possible to only 768062306a36Sopenharmony_ci * override the other configurations, for example the queue to steer 768162306a36Sopenharmony_ci * traffic. 768262306a36Sopenharmony_ci */ 768362306a36Sopenharmony_cistatic bool igb_mac_entry_can_be_used(const struct igb_mac_addr *entry, 768462306a36Sopenharmony_ci const u8 *addr, const u8 flags) 768562306a36Sopenharmony_ci{ 768662306a36Sopenharmony_ci if (!(entry->state & IGB_MAC_STATE_IN_USE)) 768762306a36Sopenharmony_ci return true; 768862306a36Sopenharmony_ci 768962306a36Sopenharmony_ci if ((entry->state & IGB_MAC_STATE_SRC_ADDR) != 769062306a36Sopenharmony_ci (flags & IGB_MAC_STATE_SRC_ADDR)) 769162306a36Sopenharmony_ci return false; 769262306a36Sopenharmony_ci 769362306a36Sopenharmony_ci if (!ether_addr_equal(addr, entry->addr)) 769462306a36Sopenharmony_ci return false; 769562306a36Sopenharmony_ci 769662306a36Sopenharmony_ci return true; 769762306a36Sopenharmony_ci} 769862306a36Sopenharmony_ci 769962306a36Sopenharmony_ci/* Add a MAC filter for 'addr' directing matching traffic to 'queue', 770062306a36Sopenharmony_ci * 'flags' is used to indicate what kind of match is made, match is by 770162306a36Sopenharmony_ci * default for the destination address, if matching by source address 770262306a36Sopenharmony_ci * is desired the flag IGB_MAC_STATE_SRC_ADDR can be used. 770362306a36Sopenharmony_ci */ 770462306a36Sopenharmony_cistatic int igb_add_mac_filter_flags(struct igb_adapter *adapter, 770562306a36Sopenharmony_ci const u8 *addr, const u8 queue, 770662306a36Sopenharmony_ci const u8 flags) 770762306a36Sopenharmony_ci{ 770862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 770962306a36Sopenharmony_ci int rar_entries = hw->mac.rar_entry_count - 771062306a36Sopenharmony_ci adapter->vfs_allocated_count; 771162306a36Sopenharmony_ci int i; 771262306a36Sopenharmony_ci 771362306a36Sopenharmony_ci if (is_zero_ether_addr(addr)) 771462306a36Sopenharmony_ci return -EINVAL; 771562306a36Sopenharmony_ci 771662306a36Sopenharmony_ci /* Search for the first empty entry in the MAC table. 771762306a36Sopenharmony_ci * Do not touch entries at the end of the table reserved for the VF MAC 771862306a36Sopenharmony_ci * addresses. 771962306a36Sopenharmony_ci */ 772062306a36Sopenharmony_ci for (i = 0; i < rar_entries; i++) { 772162306a36Sopenharmony_ci if (!igb_mac_entry_can_be_used(&adapter->mac_table[i], 772262306a36Sopenharmony_ci addr, flags)) 772362306a36Sopenharmony_ci continue; 772462306a36Sopenharmony_ci 772562306a36Sopenharmony_ci ether_addr_copy(adapter->mac_table[i].addr, addr); 772662306a36Sopenharmony_ci adapter->mac_table[i].queue = queue; 772762306a36Sopenharmony_ci adapter->mac_table[i].state |= IGB_MAC_STATE_IN_USE | flags; 772862306a36Sopenharmony_ci 772962306a36Sopenharmony_ci igb_rar_set_index(adapter, i); 773062306a36Sopenharmony_ci return i; 773162306a36Sopenharmony_ci } 773262306a36Sopenharmony_ci 773362306a36Sopenharmony_ci return -ENOSPC; 773462306a36Sopenharmony_ci} 773562306a36Sopenharmony_ci 773662306a36Sopenharmony_cistatic int igb_add_mac_filter(struct igb_adapter *adapter, const u8 *addr, 773762306a36Sopenharmony_ci const u8 queue) 773862306a36Sopenharmony_ci{ 773962306a36Sopenharmony_ci return igb_add_mac_filter_flags(adapter, addr, queue, 0); 774062306a36Sopenharmony_ci} 774162306a36Sopenharmony_ci 774262306a36Sopenharmony_ci/* Remove a MAC filter for 'addr' directing matching traffic to 774362306a36Sopenharmony_ci * 'queue', 'flags' is used to indicate what kind of match need to be 774462306a36Sopenharmony_ci * removed, match is by default for the destination address, if 774562306a36Sopenharmony_ci * matching by source address is to be removed the flag 774662306a36Sopenharmony_ci * IGB_MAC_STATE_SRC_ADDR can be used. 774762306a36Sopenharmony_ci */ 774862306a36Sopenharmony_cistatic int igb_del_mac_filter_flags(struct igb_adapter *adapter, 774962306a36Sopenharmony_ci const u8 *addr, const u8 queue, 775062306a36Sopenharmony_ci const u8 flags) 775162306a36Sopenharmony_ci{ 775262306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 775362306a36Sopenharmony_ci int rar_entries = hw->mac.rar_entry_count - 775462306a36Sopenharmony_ci adapter->vfs_allocated_count; 775562306a36Sopenharmony_ci int i; 775662306a36Sopenharmony_ci 775762306a36Sopenharmony_ci if (is_zero_ether_addr(addr)) 775862306a36Sopenharmony_ci return -EINVAL; 775962306a36Sopenharmony_ci 776062306a36Sopenharmony_ci /* Search for matching entry in the MAC table based on given address 776162306a36Sopenharmony_ci * and queue. Do not touch entries at the end of the table reserved 776262306a36Sopenharmony_ci * for the VF MAC addresses. 776362306a36Sopenharmony_ci */ 776462306a36Sopenharmony_ci for (i = 0; i < rar_entries; i++) { 776562306a36Sopenharmony_ci if (!(adapter->mac_table[i].state & IGB_MAC_STATE_IN_USE)) 776662306a36Sopenharmony_ci continue; 776762306a36Sopenharmony_ci if ((adapter->mac_table[i].state & flags) != flags) 776862306a36Sopenharmony_ci continue; 776962306a36Sopenharmony_ci if (adapter->mac_table[i].queue != queue) 777062306a36Sopenharmony_ci continue; 777162306a36Sopenharmony_ci if (!ether_addr_equal(adapter->mac_table[i].addr, addr)) 777262306a36Sopenharmony_ci continue; 777362306a36Sopenharmony_ci 777462306a36Sopenharmony_ci /* When a filter for the default address is "deleted", 777562306a36Sopenharmony_ci * we return it to its initial configuration 777662306a36Sopenharmony_ci */ 777762306a36Sopenharmony_ci if (adapter->mac_table[i].state & IGB_MAC_STATE_DEFAULT) { 777862306a36Sopenharmony_ci adapter->mac_table[i].state = 777962306a36Sopenharmony_ci IGB_MAC_STATE_DEFAULT | IGB_MAC_STATE_IN_USE; 778062306a36Sopenharmony_ci adapter->mac_table[i].queue = 778162306a36Sopenharmony_ci adapter->vfs_allocated_count; 778262306a36Sopenharmony_ci } else { 778362306a36Sopenharmony_ci adapter->mac_table[i].state = 0; 778462306a36Sopenharmony_ci adapter->mac_table[i].queue = 0; 778562306a36Sopenharmony_ci eth_zero_addr(adapter->mac_table[i].addr); 778662306a36Sopenharmony_ci } 778762306a36Sopenharmony_ci 778862306a36Sopenharmony_ci igb_rar_set_index(adapter, i); 778962306a36Sopenharmony_ci return 0; 779062306a36Sopenharmony_ci } 779162306a36Sopenharmony_ci 779262306a36Sopenharmony_ci return -ENOENT; 779362306a36Sopenharmony_ci} 779462306a36Sopenharmony_ci 779562306a36Sopenharmony_cistatic int igb_del_mac_filter(struct igb_adapter *adapter, const u8 *addr, 779662306a36Sopenharmony_ci const u8 queue) 779762306a36Sopenharmony_ci{ 779862306a36Sopenharmony_ci return igb_del_mac_filter_flags(adapter, addr, queue, 0); 779962306a36Sopenharmony_ci} 780062306a36Sopenharmony_ci 780162306a36Sopenharmony_ciint igb_add_mac_steering_filter(struct igb_adapter *adapter, 780262306a36Sopenharmony_ci const u8 *addr, u8 queue, u8 flags) 780362306a36Sopenharmony_ci{ 780462306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 780562306a36Sopenharmony_ci 780662306a36Sopenharmony_ci /* In theory, this should be supported on 82575 as well, but 780762306a36Sopenharmony_ci * that part wasn't easily accessible during development. 780862306a36Sopenharmony_ci */ 780962306a36Sopenharmony_ci if (hw->mac.type != e1000_i210) 781062306a36Sopenharmony_ci return -EOPNOTSUPP; 781162306a36Sopenharmony_ci 781262306a36Sopenharmony_ci return igb_add_mac_filter_flags(adapter, addr, queue, 781362306a36Sopenharmony_ci IGB_MAC_STATE_QUEUE_STEERING | flags); 781462306a36Sopenharmony_ci} 781562306a36Sopenharmony_ci 781662306a36Sopenharmony_ciint igb_del_mac_steering_filter(struct igb_adapter *adapter, 781762306a36Sopenharmony_ci const u8 *addr, u8 queue, u8 flags) 781862306a36Sopenharmony_ci{ 781962306a36Sopenharmony_ci return igb_del_mac_filter_flags(adapter, addr, queue, 782062306a36Sopenharmony_ci IGB_MAC_STATE_QUEUE_STEERING | flags); 782162306a36Sopenharmony_ci} 782262306a36Sopenharmony_ci 782362306a36Sopenharmony_cistatic int igb_uc_sync(struct net_device *netdev, const unsigned char *addr) 782462306a36Sopenharmony_ci{ 782562306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 782662306a36Sopenharmony_ci int ret; 782762306a36Sopenharmony_ci 782862306a36Sopenharmony_ci ret = igb_add_mac_filter(adapter, addr, adapter->vfs_allocated_count); 782962306a36Sopenharmony_ci 783062306a36Sopenharmony_ci return min_t(int, ret, 0); 783162306a36Sopenharmony_ci} 783262306a36Sopenharmony_ci 783362306a36Sopenharmony_cistatic int igb_uc_unsync(struct net_device *netdev, const unsigned char *addr) 783462306a36Sopenharmony_ci{ 783562306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 783662306a36Sopenharmony_ci 783762306a36Sopenharmony_ci igb_del_mac_filter(adapter, addr, adapter->vfs_allocated_count); 783862306a36Sopenharmony_ci 783962306a36Sopenharmony_ci return 0; 784062306a36Sopenharmony_ci} 784162306a36Sopenharmony_ci 784262306a36Sopenharmony_cistatic int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf, 784362306a36Sopenharmony_ci const u32 info, const u8 *addr) 784462306a36Sopenharmony_ci{ 784562306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 784662306a36Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 784762306a36Sopenharmony_ci struct list_head *pos; 784862306a36Sopenharmony_ci struct vf_mac_filter *entry = NULL; 784962306a36Sopenharmony_ci int ret = 0; 785062306a36Sopenharmony_ci 785162306a36Sopenharmony_ci if ((vf_data->flags & IGB_VF_FLAG_PF_SET_MAC) && 785262306a36Sopenharmony_ci !vf_data->trusted) { 785362306a36Sopenharmony_ci dev_warn(&pdev->dev, 785462306a36Sopenharmony_ci "VF %d requested MAC filter but is administratively denied\n", 785562306a36Sopenharmony_ci vf); 785662306a36Sopenharmony_ci return -EINVAL; 785762306a36Sopenharmony_ci } 785862306a36Sopenharmony_ci if (!is_valid_ether_addr(addr)) { 785962306a36Sopenharmony_ci dev_warn(&pdev->dev, 786062306a36Sopenharmony_ci "VF %d attempted to set invalid MAC filter\n", 786162306a36Sopenharmony_ci vf); 786262306a36Sopenharmony_ci return -EINVAL; 786362306a36Sopenharmony_ci } 786462306a36Sopenharmony_ci 786562306a36Sopenharmony_ci switch (info) { 786662306a36Sopenharmony_ci case E1000_VF_MAC_FILTER_CLR: 786762306a36Sopenharmony_ci /* remove all unicast MAC filters related to the current VF */ 786862306a36Sopenharmony_ci list_for_each(pos, &adapter->vf_macs.l) { 786962306a36Sopenharmony_ci entry = list_entry(pos, struct vf_mac_filter, l); 787062306a36Sopenharmony_ci if (entry->vf == vf) { 787162306a36Sopenharmony_ci entry->vf = -1; 787262306a36Sopenharmony_ci entry->free = true; 787362306a36Sopenharmony_ci igb_del_mac_filter(adapter, entry->vf_mac, vf); 787462306a36Sopenharmony_ci } 787562306a36Sopenharmony_ci } 787662306a36Sopenharmony_ci break; 787762306a36Sopenharmony_ci case E1000_VF_MAC_FILTER_ADD: 787862306a36Sopenharmony_ci /* try to find empty slot in the list */ 787962306a36Sopenharmony_ci list_for_each(pos, &adapter->vf_macs.l) { 788062306a36Sopenharmony_ci entry = list_entry(pos, struct vf_mac_filter, l); 788162306a36Sopenharmony_ci if (entry->free) 788262306a36Sopenharmony_ci break; 788362306a36Sopenharmony_ci } 788462306a36Sopenharmony_ci 788562306a36Sopenharmony_ci if (entry && entry->free) { 788662306a36Sopenharmony_ci entry->free = false; 788762306a36Sopenharmony_ci entry->vf = vf; 788862306a36Sopenharmony_ci ether_addr_copy(entry->vf_mac, addr); 788962306a36Sopenharmony_ci 789062306a36Sopenharmony_ci ret = igb_add_mac_filter(adapter, addr, vf); 789162306a36Sopenharmony_ci ret = min_t(int, ret, 0); 789262306a36Sopenharmony_ci } else { 789362306a36Sopenharmony_ci ret = -ENOSPC; 789462306a36Sopenharmony_ci } 789562306a36Sopenharmony_ci 789662306a36Sopenharmony_ci if (ret == -ENOSPC) 789762306a36Sopenharmony_ci dev_warn(&pdev->dev, 789862306a36Sopenharmony_ci "VF %d has requested MAC filter but there is no space for it\n", 789962306a36Sopenharmony_ci vf); 790062306a36Sopenharmony_ci break; 790162306a36Sopenharmony_ci default: 790262306a36Sopenharmony_ci ret = -EINVAL; 790362306a36Sopenharmony_ci break; 790462306a36Sopenharmony_ci } 790562306a36Sopenharmony_ci 790662306a36Sopenharmony_ci return ret; 790762306a36Sopenharmony_ci} 790862306a36Sopenharmony_ci 790962306a36Sopenharmony_cistatic int igb_set_vf_mac_addr(struct igb_adapter *adapter, u32 *msg, int vf) 791062306a36Sopenharmony_ci{ 791162306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 791262306a36Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 791362306a36Sopenharmony_ci u32 info = msg[0] & E1000_VT_MSGINFO_MASK; 791462306a36Sopenharmony_ci 791562306a36Sopenharmony_ci /* The VF MAC Address is stored in a packed array of bytes 791662306a36Sopenharmony_ci * starting at the second 32 bit word of the msg array 791762306a36Sopenharmony_ci */ 791862306a36Sopenharmony_ci unsigned char *addr = (unsigned char *)&msg[1]; 791962306a36Sopenharmony_ci int ret = 0; 792062306a36Sopenharmony_ci 792162306a36Sopenharmony_ci if (!info) { 792262306a36Sopenharmony_ci if ((vf_data->flags & IGB_VF_FLAG_PF_SET_MAC) && 792362306a36Sopenharmony_ci !vf_data->trusted) { 792462306a36Sopenharmony_ci dev_warn(&pdev->dev, 792562306a36Sopenharmony_ci "VF %d attempted to override administratively set MAC address\nReload the VF driver to resume operations\n", 792662306a36Sopenharmony_ci vf); 792762306a36Sopenharmony_ci return -EINVAL; 792862306a36Sopenharmony_ci } 792962306a36Sopenharmony_ci 793062306a36Sopenharmony_ci if (!is_valid_ether_addr(addr)) { 793162306a36Sopenharmony_ci dev_warn(&pdev->dev, 793262306a36Sopenharmony_ci "VF %d attempted to set invalid MAC\n", 793362306a36Sopenharmony_ci vf); 793462306a36Sopenharmony_ci return -EINVAL; 793562306a36Sopenharmony_ci } 793662306a36Sopenharmony_ci 793762306a36Sopenharmony_ci ret = igb_set_vf_mac(adapter, vf, addr); 793862306a36Sopenharmony_ci } else { 793962306a36Sopenharmony_ci ret = igb_set_vf_mac_filter(adapter, vf, info, addr); 794062306a36Sopenharmony_ci } 794162306a36Sopenharmony_ci 794262306a36Sopenharmony_ci return ret; 794362306a36Sopenharmony_ci} 794462306a36Sopenharmony_ci 794562306a36Sopenharmony_cistatic void igb_rcv_ack_from_vf(struct igb_adapter *adapter, u32 vf) 794662306a36Sopenharmony_ci{ 794762306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 794862306a36Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 794962306a36Sopenharmony_ci u32 msg = E1000_VT_MSGTYPE_NACK; 795062306a36Sopenharmony_ci 795162306a36Sopenharmony_ci /* if device isn't clear to send it shouldn't be reading either */ 795262306a36Sopenharmony_ci if (!(vf_data->flags & IGB_VF_FLAG_CTS) && 795362306a36Sopenharmony_ci time_after(jiffies, vf_data->last_nack + (2 * HZ))) { 795462306a36Sopenharmony_ci igb_write_mbx(hw, &msg, 1, vf); 795562306a36Sopenharmony_ci vf_data->last_nack = jiffies; 795662306a36Sopenharmony_ci } 795762306a36Sopenharmony_ci} 795862306a36Sopenharmony_ci 795962306a36Sopenharmony_cistatic void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) 796062306a36Sopenharmony_ci{ 796162306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 796262306a36Sopenharmony_ci u32 msgbuf[E1000_VFMAILBOX_SIZE]; 796362306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 796462306a36Sopenharmony_ci struct vf_data_storage *vf_data = &adapter->vf_data[vf]; 796562306a36Sopenharmony_ci s32 retval; 796662306a36Sopenharmony_ci 796762306a36Sopenharmony_ci retval = igb_read_mbx(hw, msgbuf, E1000_VFMAILBOX_SIZE, vf, false); 796862306a36Sopenharmony_ci 796962306a36Sopenharmony_ci if (retval) { 797062306a36Sopenharmony_ci /* if receive failed revoke VF CTS stats and restart init */ 797162306a36Sopenharmony_ci dev_err(&pdev->dev, "Error receiving message from VF\n"); 797262306a36Sopenharmony_ci vf_data->flags &= ~IGB_VF_FLAG_CTS; 797362306a36Sopenharmony_ci if (!time_after(jiffies, vf_data->last_nack + (2 * HZ))) 797462306a36Sopenharmony_ci goto unlock; 797562306a36Sopenharmony_ci goto out; 797662306a36Sopenharmony_ci } 797762306a36Sopenharmony_ci 797862306a36Sopenharmony_ci /* this is a message we already processed, do nothing */ 797962306a36Sopenharmony_ci if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK)) 798062306a36Sopenharmony_ci goto unlock; 798162306a36Sopenharmony_ci 798262306a36Sopenharmony_ci /* until the vf completes a reset it should not be 798362306a36Sopenharmony_ci * allowed to start any configuration. 798462306a36Sopenharmony_ci */ 798562306a36Sopenharmony_ci if (msgbuf[0] == E1000_VF_RESET) { 798662306a36Sopenharmony_ci /* unlocks mailbox */ 798762306a36Sopenharmony_ci igb_vf_reset_msg(adapter, vf); 798862306a36Sopenharmony_ci return; 798962306a36Sopenharmony_ci } 799062306a36Sopenharmony_ci 799162306a36Sopenharmony_ci if (!(vf_data->flags & IGB_VF_FLAG_CTS)) { 799262306a36Sopenharmony_ci if (!time_after(jiffies, vf_data->last_nack + (2 * HZ))) 799362306a36Sopenharmony_ci goto unlock; 799462306a36Sopenharmony_ci retval = -1; 799562306a36Sopenharmony_ci goto out; 799662306a36Sopenharmony_ci } 799762306a36Sopenharmony_ci 799862306a36Sopenharmony_ci switch ((msgbuf[0] & 0xFFFF)) { 799962306a36Sopenharmony_ci case E1000_VF_SET_MAC_ADDR: 800062306a36Sopenharmony_ci retval = igb_set_vf_mac_addr(adapter, msgbuf, vf); 800162306a36Sopenharmony_ci break; 800262306a36Sopenharmony_ci case E1000_VF_SET_PROMISC: 800362306a36Sopenharmony_ci retval = igb_set_vf_promisc(adapter, msgbuf, vf); 800462306a36Sopenharmony_ci break; 800562306a36Sopenharmony_ci case E1000_VF_SET_MULTICAST: 800662306a36Sopenharmony_ci retval = igb_set_vf_multicasts(adapter, msgbuf, vf); 800762306a36Sopenharmony_ci break; 800862306a36Sopenharmony_ci case E1000_VF_SET_LPE: 800962306a36Sopenharmony_ci retval = igb_set_vf_rlpml(adapter, msgbuf[1], vf); 801062306a36Sopenharmony_ci break; 801162306a36Sopenharmony_ci case E1000_VF_SET_VLAN: 801262306a36Sopenharmony_ci retval = -1; 801362306a36Sopenharmony_ci if (vf_data->pf_vlan) 801462306a36Sopenharmony_ci dev_warn(&pdev->dev, 801562306a36Sopenharmony_ci "VF %d attempted to override administratively set VLAN tag\nReload the VF driver to resume operations\n", 801662306a36Sopenharmony_ci vf); 801762306a36Sopenharmony_ci else 801862306a36Sopenharmony_ci retval = igb_set_vf_vlan_msg(adapter, msgbuf, vf); 801962306a36Sopenharmony_ci break; 802062306a36Sopenharmony_ci default: 802162306a36Sopenharmony_ci dev_err(&pdev->dev, "Unhandled Msg %08x\n", msgbuf[0]); 802262306a36Sopenharmony_ci retval = -1; 802362306a36Sopenharmony_ci break; 802462306a36Sopenharmony_ci } 802562306a36Sopenharmony_ci 802662306a36Sopenharmony_ci msgbuf[0] |= E1000_VT_MSGTYPE_CTS; 802762306a36Sopenharmony_ciout: 802862306a36Sopenharmony_ci /* notify the VF of the results of what it sent us */ 802962306a36Sopenharmony_ci if (retval) 803062306a36Sopenharmony_ci msgbuf[0] |= E1000_VT_MSGTYPE_NACK; 803162306a36Sopenharmony_ci else 803262306a36Sopenharmony_ci msgbuf[0] |= E1000_VT_MSGTYPE_ACK; 803362306a36Sopenharmony_ci 803462306a36Sopenharmony_ci /* unlocks mailbox */ 803562306a36Sopenharmony_ci igb_write_mbx(hw, msgbuf, 1, vf); 803662306a36Sopenharmony_ci return; 803762306a36Sopenharmony_ci 803862306a36Sopenharmony_ciunlock: 803962306a36Sopenharmony_ci igb_unlock_mbx(hw, vf); 804062306a36Sopenharmony_ci} 804162306a36Sopenharmony_ci 804262306a36Sopenharmony_cistatic void igb_msg_task(struct igb_adapter *adapter) 804362306a36Sopenharmony_ci{ 804462306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 804562306a36Sopenharmony_ci unsigned long flags; 804662306a36Sopenharmony_ci u32 vf; 804762306a36Sopenharmony_ci 804862306a36Sopenharmony_ci spin_lock_irqsave(&adapter->vfs_lock, flags); 804962306a36Sopenharmony_ci for (vf = 0; vf < adapter->vfs_allocated_count; vf++) { 805062306a36Sopenharmony_ci /* process any reset requests */ 805162306a36Sopenharmony_ci if (!igb_check_for_rst(hw, vf)) 805262306a36Sopenharmony_ci igb_vf_reset_event(adapter, vf); 805362306a36Sopenharmony_ci 805462306a36Sopenharmony_ci /* process any messages pending */ 805562306a36Sopenharmony_ci if (!igb_check_for_msg(hw, vf)) 805662306a36Sopenharmony_ci igb_rcv_msg_from_vf(adapter, vf); 805762306a36Sopenharmony_ci 805862306a36Sopenharmony_ci /* process any acks */ 805962306a36Sopenharmony_ci if (!igb_check_for_ack(hw, vf)) 806062306a36Sopenharmony_ci igb_rcv_ack_from_vf(adapter, vf); 806162306a36Sopenharmony_ci } 806262306a36Sopenharmony_ci spin_unlock_irqrestore(&adapter->vfs_lock, flags); 806362306a36Sopenharmony_ci} 806462306a36Sopenharmony_ci 806562306a36Sopenharmony_ci/** 806662306a36Sopenharmony_ci * igb_set_uta - Set unicast filter table address 806762306a36Sopenharmony_ci * @adapter: board private structure 806862306a36Sopenharmony_ci * @set: boolean indicating if we are setting or clearing bits 806962306a36Sopenharmony_ci * 807062306a36Sopenharmony_ci * The unicast table address is a register array of 32-bit registers. 807162306a36Sopenharmony_ci * The table is meant to be used in a way similar to how the MTA is used 807262306a36Sopenharmony_ci * however due to certain limitations in the hardware it is necessary to 807362306a36Sopenharmony_ci * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscuous 807462306a36Sopenharmony_ci * enable bit to allow vlan tag stripping when promiscuous mode is enabled 807562306a36Sopenharmony_ci **/ 807662306a36Sopenharmony_cistatic void igb_set_uta(struct igb_adapter *adapter, bool set) 807762306a36Sopenharmony_ci{ 807862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 807962306a36Sopenharmony_ci u32 uta = set ? ~0 : 0; 808062306a36Sopenharmony_ci int i; 808162306a36Sopenharmony_ci 808262306a36Sopenharmony_ci /* we only need to do this if VMDq is enabled */ 808362306a36Sopenharmony_ci if (!adapter->vfs_allocated_count) 808462306a36Sopenharmony_ci return; 808562306a36Sopenharmony_ci 808662306a36Sopenharmony_ci for (i = hw->mac.uta_reg_count; i--;) 808762306a36Sopenharmony_ci array_wr32(E1000_UTA, i, uta); 808862306a36Sopenharmony_ci} 808962306a36Sopenharmony_ci 809062306a36Sopenharmony_ci/** 809162306a36Sopenharmony_ci * igb_intr_msi - Interrupt Handler 809262306a36Sopenharmony_ci * @irq: interrupt number 809362306a36Sopenharmony_ci * @data: pointer to a network interface device structure 809462306a36Sopenharmony_ci **/ 809562306a36Sopenharmony_cistatic irqreturn_t igb_intr_msi(int irq, void *data) 809662306a36Sopenharmony_ci{ 809762306a36Sopenharmony_ci struct igb_adapter *adapter = data; 809862306a36Sopenharmony_ci struct igb_q_vector *q_vector = adapter->q_vector[0]; 809962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 810062306a36Sopenharmony_ci /* read ICR disables interrupts using IAM */ 810162306a36Sopenharmony_ci u32 icr = rd32(E1000_ICR); 810262306a36Sopenharmony_ci 810362306a36Sopenharmony_ci igb_write_itr(q_vector); 810462306a36Sopenharmony_ci 810562306a36Sopenharmony_ci if (icr & E1000_ICR_DRSTA) 810662306a36Sopenharmony_ci schedule_work(&adapter->reset_task); 810762306a36Sopenharmony_ci 810862306a36Sopenharmony_ci if (icr & E1000_ICR_DOUTSYNC) { 810962306a36Sopenharmony_ci /* HW is reporting DMA is out of sync */ 811062306a36Sopenharmony_ci adapter->stats.doosync++; 811162306a36Sopenharmony_ci } 811262306a36Sopenharmony_ci 811362306a36Sopenharmony_ci if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 811462306a36Sopenharmony_ci hw->mac.get_link_status = 1; 811562306a36Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) 811662306a36Sopenharmony_ci mod_timer(&adapter->watchdog_timer, jiffies + 1); 811762306a36Sopenharmony_ci } 811862306a36Sopenharmony_ci 811962306a36Sopenharmony_ci if (icr & E1000_ICR_TS) 812062306a36Sopenharmony_ci igb_tsync_interrupt(adapter); 812162306a36Sopenharmony_ci 812262306a36Sopenharmony_ci napi_schedule(&q_vector->napi); 812362306a36Sopenharmony_ci 812462306a36Sopenharmony_ci return IRQ_HANDLED; 812562306a36Sopenharmony_ci} 812662306a36Sopenharmony_ci 812762306a36Sopenharmony_ci/** 812862306a36Sopenharmony_ci * igb_intr - Legacy Interrupt Handler 812962306a36Sopenharmony_ci * @irq: interrupt number 813062306a36Sopenharmony_ci * @data: pointer to a network interface device structure 813162306a36Sopenharmony_ci **/ 813262306a36Sopenharmony_cistatic irqreturn_t igb_intr(int irq, void *data) 813362306a36Sopenharmony_ci{ 813462306a36Sopenharmony_ci struct igb_adapter *adapter = data; 813562306a36Sopenharmony_ci struct igb_q_vector *q_vector = adapter->q_vector[0]; 813662306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 813762306a36Sopenharmony_ci /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No 813862306a36Sopenharmony_ci * need for the IMC write 813962306a36Sopenharmony_ci */ 814062306a36Sopenharmony_ci u32 icr = rd32(E1000_ICR); 814162306a36Sopenharmony_ci 814262306a36Sopenharmony_ci /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is 814362306a36Sopenharmony_ci * not set, then the adapter didn't send an interrupt 814462306a36Sopenharmony_ci */ 814562306a36Sopenharmony_ci if (!(icr & E1000_ICR_INT_ASSERTED)) 814662306a36Sopenharmony_ci return IRQ_NONE; 814762306a36Sopenharmony_ci 814862306a36Sopenharmony_ci igb_write_itr(q_vector); 814962306a36Sopenharmony_ci 815062306a36Sopenharmony_ci if (icr & E1000_ICR_DRSTA) 815162306a36Sopenharmony_ci schedule_work(&adapter->reset_task); 815262306a36Sopenharmony_ci 815362306a36Sopenharmony_ci if (icr & E1000_ICR_DOUTSYNC) { 815462306a36Sopenharmony_ci /* HW is reporting DMA is out of sync */ 815562306a36Sopenharmony_ci adapter->stats.doosync++; 815662306a36Sopenharmony_ci } 815762306a36Sopenharmony_ci 815862306a36Sopenharmony_ci if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { 815962306a36Sopenharmony_ci hw->mac.get_link_status = 1; 816062306a36Sopenharmony_ci /* guard against interrupt when we're going down */ 816162306a36Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) 816262306a36Sopenharmony_ci mod_timer(&adapter->watchdog_timer, jiffies + 1); 816362306a36Sopenharmony_ci } 816462306a36Sopenharmony_ci 816562306a36Sopenharmony_ci if (icr & E1000_ICR_TS) 816662306a36Sopenharmony_ci igb_tsync_interrupt(adapter); 816762306a36Sopenharmony_ci 816862306a36Sopenharmony_ci napi_schedule(&q_vector->napi); 816962306a36Sopenharmony_ci 817062306a36Sopenharmony_ci return IRQ_HANDLED; 817162306a36Sopenharmony_ci} 817262306a36Sopenharmony_ci 817362306a36Sopenharmony_cistatic void igb_ring_irq_enable(struct igb_q_vector *q_vector) 817462306a36Sopenharmony_ci{ 817562306a36Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 817662306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 817762306a36Sopenharmony_ci 817862306a36Sopenharmony_ci if ((q_vector->rx.ring && (adapter->rx_itr_setting & 3)) || 817962306a36Sopenharmony_ci (!q_vector->rx.ring && (adapter->tx_itr_setting & 3))) { 818062306a36Sopenharmony_ci if ((adapter->num_q_vectors == 1) && !adapter->vf_data) 818162306a36Sopenharmony_ci igb_set_itr(q_vector); 818262306a36Sopenharmony_ci else 818362306a36Sopenharmony_ci igb_update_ring_itr(q_vector); 818462306a36Sopenharmony_ci } 818562306a36Sopenharmony_ci 818662306a36Sopenharmony_ci if (!test_bit(__IGB_DOWN, &adapter->state)) { 818762306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_HAS_MSIX) 818862306a36Sopenharmony_ci wr32(E1000_EIMS, q_vector->eims_value); 818962306a36Sopenharmony_ci else 819062306a36Sopenharmony_ci igb_irq_enable(adapter); 819162306a36Sopenharmony_ci } 819262306a36Sopenharmony_ci} 819362306a36Sopenharmony_ci 819462306a36Sopenharmony_ci/** 819562306a36Sopenharmony_ci * igb_poll - NAPI Rx polling callback 819662306a36Sopenharmony_ci * @napi: napi polling structure 819762306a36Sopenharmony_ci * @budget: count of how many packets we should handle 819862306a36Sopenharmony_ci **/ 819962306a36Sopenharmony_cistatic int igb_poll(struct napi_struct *napi, int budget) 820062306a36Sopenharmony_ci{ 820162306a36Sopenharmony_ci struct igb_q_vector *q_vector = container_of(napi, 820262306a36Sopenharmony_ci struct igb_q_vector, 820362306a36Sopenharmony_ci napi); 820462306a36Sopenharmony_ci bool clean_complete = true; 820562306a36Sopenharmony_ci int work_done = 0; 820662306a36Sopenharmony_ci 820762306a36Sopenharmony_ci#ifdef CONFIG_IGB_DCA 820862306a36Sopenharmony_ci if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED) 820962306a36Sopenharmony_ci igb_update_dca(q_vector); 821062306a36Sopenharmony_ci#endif 821162306a36Sopenharmony_ci if (q_vector->tx.ring) 821262306a36Sopenharmony_ci clean_complete = igb_clean_tx_irq(q_vector, budget); 821362306a36Sopenharmony_ci 821462306a36Sopenharmony_ci if (q_vector->rx.ring) { 821562306a36Sopenharmony_ci int cleaned = igb_clean_rx_irq(q_vector, budget); 821662306a36Sopenharmony_ci 821762306a36Sopenharmony_ci work_done += cleaned; 821862306a36Sopenharmony_ci if (cleaned >= budget) 821962306a36Sopenharmony_ci clean_complete = false; 822062306a36Sopenharmony_ci } 822162306a36Sopenharmony_ci 822262306a36Sopenharmony_ci /* If all work not completed, return budget and keep polling */ 822362306a36Sopenharmony_ci if (!clean_complete) 822462306a36Sopenharmony_ci return budget; 822562306a36Sopenharmony_ci 822662306a36Sopenharmony_ci /* Exit the polling mode, but don't re-enable interrupts if stack might 822762306a36Sopenharmony_ci * poll us due to busy-polling 822862306a36Sopenharmony_ci */ 822962306a36Sopenharmony_ci if (likely(napi_complete_done(napi, work_done))) 823062306a36Sopenharmony_ci igb_ring_irq_enable(q_vector); 823162306a36Sopenharmony_ci 823262306a36Sopenharmony_ci return work_done; 823362306a36Sopenharmony_ci} 823462306a36Sopenharmony_ci 823562306a36Sopenharmony_ci/** 823662306a36Sopenharmony_ci * igb_clean_tx_irq - Reclaim resources after transmit completes 823762306a36Sopenharmony_ci * @q_vector: pointer to q_vector containing needed info 823862306a36Sopenharmony_ci * @napi_budget: Used to determine if we are in netpoll 823962306a36Sopenharmony_ci * 824062306a36Sopenharmony_ci * returns true if ring is completely cleaned 824162306a36Sopenharmony_ci **/ 824262306a36Sopenharmony_cistatic bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget) 824362306a36Sopenharmony_ci{ 824462306a36Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 824562306a36Sopenharmony_ci struct igb_ring *tx_ring = q_vector->tx.ring; 824662306a36Sopenharmony_ci struct igb_tx_buffer *tx_buffer; 824762306a36Sopenharmony_ci union e1000_adv_tx_desc *tx_desc; 824862306a36Sopenharmony_ci unsigned int total_bytes = 0, total_packets = 0; 824962306a36Sopenharmony_ci unsigned int budget = q_vector->tx.work_limit; 825062306a36Sopenharmony_ci unsigned int i = tx_ring->next_to_clean; 825162306a36Sopenharmony_ci 825262306a36Sopenharmony_ci if (test_bit(__IGB_DOWN, &adapter->state)) 825362306a36Sopenharmony_ci return true; 825462306a36Sopenharmony_ci 825562306a36Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[i]; 825662306a36Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, i); 825762306a36Sopenharmony_ci i -= tx_ring->count; 825862306a36Sopenharmony_ci 825962306a36Sopenharmony_ci do { 826062306a36Sopenharmony_ci union e1000_adv_tx_desc *eop_desc = tx_buffer->next_to_watch; 826162306a36Sopenharmony_ci 826262306a36Sopenharmony_ci /* if next_to_watch is not set then there is no work pending */ 826362306a36Sopenharmony_ci if (!eop_desc) 826462306a36Sopenharmony_ci break; 826562306a36Sopenharmony_ci 826662306a36Sopenharmony_ci /* prevent any other reads prior to eop_desc */ 826762306a36Sopenharmony_ci smp_rmb(); 826862306a36Sopenharmony_ci 826962306a36Sopenharmony_ci /* if DD is not set pending work has not been completed */ 827062306a36Sopenharmony_ci if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) 827162306a36Sopenharmony_ci break; 827262306a36Sopenharmony_ci 827362306a36Sopenharmony_ci /* clear next_to_watch to prevent false hangs */ 827462306a36Sopenharmony_ci tx_buffer->next_to_watch = NULL; 827562306a36Sopenharmony_ci 827662306a36Sopenharmony_ci /* update the statistics for this packet */ 827762306a36Sopenharmony_ci total_bytes += tx_buffer->bytecount; 827862306a36Sopenharmony_ci total_packets += tx_buffer->gso_segs; 827962306a36Sopenharmony_ci 828062306a36Sopenharmony_ci /* free the skb */ 828162306a36Sopenharmony_ci if (tx_buffer->type == IGB_TYPE_SKB) 828262306a36Sopenharmony_ci napi_consume_skb(tx_buffer->skb, napi_budget); 828362306a36Sopenharmony_ci else 828462306a36Sopenharmony_ci xdp_return_frame(tx_buffer->xdpf); 828562306a36Sopenharmony_ci 828662306a36Sopenharmony_ci /* unmap skb header data */ 828762306a36Sopenharmony_ci dma_unmap_single(tx_ring->dev, 828862306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 828962306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 829062306a36Sopenharmony_ci DMA_TO_DEVICE); 829162306a36Sopenharmony_ci 829262306a36Sopenharmony_ci /* clear tx_buffer data */ 829362306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 829462306a36Sopenharmony_ci 829562306a36Sopenharmony_ci /* clear last DMA location and unmap remaining buffers */ 829662306a36Sopenharmony_ci while (tx_desc != eop_desc) { 829762306a36Sopenharmony_ci tx_buffer++; 829862306a36Sopenharmony_ci tx_desc++; 829962306a36Sopenharmony_ci i++; 830062306a36Sopenharmony_ci if (unlikely(!i)) { 830162306a36Sopenharmony_ci i -= tx_ring->count; 830262306a36Sopenharmony_ci tx_buffer = tx_ring->tx_buffer_info; 830362306a36Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, 0); 830462306a36Sopenharmony_ci } 830562306a36Sopenharmony_ci 830662306a36Sopenharmony_ci /* unmap any remaining paged data */ 830762306a36Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) { 830862306a36Sopenharmony_ci dma_unmap_page(tx_ring->dev, 830962306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 831062306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 831162306a36Sopenharmony_ci DMA_TO_DEVICE); 831262306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 831362306a36Sopenharmony_ci } 831462306a36Sopenharmony_ci } 831562306a36Sopenharmony_ci 831662306a36Sopenharmony_ci /* move us one more past the eop_desc for start of next pkt */ 831762306a36Sopenharmony_ci tx_buffer++; 831862306a36Sopenharmony_ci tx_desc++; 831962306a36Sopenharmony_ci i++; 832062306a36Sopenharmony_ci if (unlikely(!i)) { 832162306a36Sopenharmony_ci i -= tx_ring->count; 832262306a36Sopenharmony_ci tx_buffer = tx_ring->tx_buffer_info; 832362306a36Sopenharmony_ci tx_desc = IGB_TX_DESC(tx_ring, 0); 832462306a36Sopenharmony_ci } 832562306a36Sopenharmony_ci 832662306a36Sopenharmony_ci /* issue prefetch for next Tx descriptor */ 832762306a36Sopenharmony_ci prefetch(tx_desc); 832862306a36Sopenharmony_ci 832962306a36Sopenharmony_ci /* update budget accounting */ 833062306a36Sopenharmony_ci budget--; 833162306a36Sopenharmony_ci } while (likely(budget)); 833262306a36Sopenharmony_ci 833362306a36Sopenharmony_ci netdev_tx_completed_queue(txring_txq(tx_ring), 833462306a36Sopenharmony_ci total_packets, total_bytes); 833562306a36Sopenharmony_ci i += tx_ring->count; 833662306a36Sopenharmony_ci tx_ring->next_to_clean = i; 833762306a36Sopenharmony_ci u64_stats_update_begin(&tx_ring->tx_syncp); 833862306a36Sopenharmony_ci tx_ring->tx_stats.bytes += total_bytes; 833962306a36Sopenharmony_ci tx_ring->tx_stats.packets += total_packets; 834062306a36Sopenharmony_ci u64_stats_update_end(&tx_ring->tx_syncp); 834162306a36Sopenharmony_ci q_vector->tx.total_bytes += total_bytes; 834262306a36Sopenharmony_ci q_vector->tx.total_packets += total_packets; 834362306a36Sopenharmony_ci 834462306a36Sopenharmony_ci if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { 834562306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 834662306a36Sopenharmony_ci 834762306a36Sopenharmony_ci /* Detect a transmit hang in hardware, this serializes the 834862306a36Sopenharmony_ci * check with the clearing of time_stamp and movement of i 834962306a36Sopenharmony_ci */ 835062306a36Sopenharmony_ci clear_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); 835162306a36Sopenharmony_ci if (tx_buffer->next_to_watch && 835262306a36Sopenharmony_ci time_after(jiffies, tx_buffer->time_stamp + 835362306a36Sopenharmony_ci (adapter->tx_timeout_factor * HZ)) && 835462306a36Sopenharmony_ci !(rd32(E1000_STATUS) & E1000_STATUS_TXOFF)) { 835562306a36Sopenharmony_ci 835662306a36Sopenharmony_ci /* detected Tx unit hang */ 835762306a36Sopenharmony_ci dev_err(tx_ring->dev, 835862306a36Sopenharmony_ci "Detected Tx Unit Hang\n" 835962306a36Sopenharmony_ci " Tx Queue <%d>\n" 836062306a36Sopenharmony_ci " TDH <%x>\n" 836162306a36Sopenharmony_ci " TDT <%x>\n" 836262306a36Sopenharmony_ci " next_to_use <%x>\n" 836362306a36Sopenharmony_ci " next_to_clean <%x>\n" 836462306a36Sopenharmony_ci "buffer_info[next_to_clean]\n" 836562306a36Sopenharmony_ci " time_stamp <%lx>\n" 836662306a36Sopenharmony_ci " next_to_watch <%p>\n" 836762306a36Sopenharmony_ci " jiffies <%lx>\n" 836862306a36Sopenharmony_ci " desc.status <%x>\n", 836962306a36Sopenharmony_ci tx_ring->queue_index, 837062306a36Sopenharmony_ci rd32(E1000_TDH(tx_ring->reg_idx)), 837162306a36Sopenharmony_ci readl(tx_ring->tail), 837262306a36Sopenharmony_ci tx_ring->next_to_use, 837362306a36Sopenharmony_ci tx_ring->next_to_clean, 837462306a36Sopenharmony_ci tx_buffer->time_stamp, 837562306a36Sopenharmony_ci tx_buffer->next_to_watch, 837662306a36Sopenharmony_ci jiffies, 837762306a36Sopenharmony_ci tx_buffer->next_to_watch->wb.status); 837862306a36Sopenharmony_ci netif_stop_subqueue(tx_ring->netdev, 837962306a36Sopenharmony_ci tx_ring->queue_index); 838062306a36Sopenharmony_ci 838162306a36Sopenharmony_ci /* we are about to reset, no point in enabling stuff */ 838262306a36Sopenharmony_ci return true; 838362306a36Sopenharmony_ci } 838462306a36Sopenharmony_ci } 838562306a36Sopenharmony_ci 838662306a36Sopenharmony_ci#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) 838762306a36Sopenharmony_ci if (unlikely(total_packets && 838862306a36Sopenharmony_ci netif_carrier_ok(tx_ring->netdev) && 838962306a36Sopenharmony_ci igb_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) { 839062306a36Sopenharmony_ci /* Make sure that anybody stopping the queue after this 839162306a36Sopenharmony_ci * sees the new next_to_clean. 839262306a36Sopenharmony_ci */ 839362306a36Sopenharmony_ci smp_mb(); 839462306a36Sopenharmony_ci if (__netif_subqueue_stopped(tx_ring->netdev, 839562306a36Sopenharmony_ci tx_ring->queue_index) && 839662306a36Sopenharmony_ci !(test_bit(__IGB_DOWN, &adapter->state))) { 839762306a36Sopenharmony_ci netif_wake_subqueue(tx_ring->netdev, 839862306a36Sopenharmony_ci tx_ring->queue_index); 839962306a36Sopenharmony_ci 840062306a36Sopenharmony_ci u64_stats_update_begin(&tx_ring->tx_syncp); 840162306a36Sopenharmony_ci tx_ring->tx_stats.restart_queue++; 840262306a36Sopenharmony_ci u64_stats_update_end(&tx_ring->tx_syncp); 840362306a36Sopenharmony_ci } 840462306a36Sopenharmony_ci } 840562306a36Sopenharmony_ci 840662306a36Sopenharmony_ci return !!budget; 840762306a36Sopenharmony_ci} 840862306a36Sopenharmony_ci 840962306a36Sopenharmony_ci/** 841062306a36Sopenharmony_ci * igb_reuse_rx_page - page flip buffer and store it back on the ring 841162306a36Sopenharmony_ci * @rx_ring: rx descriptor ring to store buffers on 841262306a36Sopenharmony_ci * @old_buff: donor buffer to have page reused 841362306a36Sopenharmony_ci * 841462306a36Sopenharmony_ci * Synchronizes page for reuse by the adapter 841562306a36Sopenharmony_ci **/ 841662306a36Sopenharmony_cistatic void igb_reuse_rx_page(struct igb_ring *rx_ring, 841762306a36Sopenharmony_ci struct igb_rx_buffer *old_buff) 841862306a36Sopenharmony_ci{ 841962306a36Sopenharmony_ci struct igb_rx_buffer *new_buff; 842062306a36Sopenharmony_ci u16 nta = rx_ring->next_to_alloc; 842162306a36Sopenharmony_ci 842262306a36Sopenharmony_ci new_buff = &rx_ring->rx_buffer_info[nta]; 842362306a36Sopenharmony_ci 842462306a36Sopenharmony_ci /* update, and store next to alloc */ 842562306a36Sopenharmony_ci nta++; 842662306a36Sopenharmony_ci rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0; 842762306a36Sopenharmony_ci 842862306a36Sopenharmony_ci /* Transfer page from old buffer to new buffer. 842962306a36Sopenharmony_ci * Move each member individually to avoid possible store 843062306a36Sopenharmony_ci * forwarding stalls. 843162306a36Sopenharmony_ci */ 843262306a36Sopenharmony_ci new_buff->dma = old_buff->dma; 843362306a36Sopenharmony_ci new_buff->page = old_buff->page; 843462306a36Sopenharmony_ci new_buff->page_offset = old_buff->page_offset; 843562306a36Sopenharmony_ci new_buff->pagecnt_bias = old_buff->pagecnt_bias; 843662306a36Sopenharmony_ci} 843762306a36Sopenharmony_ci 843862306a36Sopenharmony_cistatic bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer, 843962306a36Sopenharmony_ci int rx_buf_pgcnt) 844062306a36Sopenharmony_ci{ 844162306a36Sopenharmony_ci unsigned int pagecnt_bias = rx_buffer->pagecnt_bias; 844262306a36Sopenharmony_ci struct page *page = rx_buffer->page; 844362306a36Sopenharmony_ci 844462306a36Sopenharmony_ci /* avoid re-using remote and pfmemalloc pages */ 844562306a36Sopenharmony_ci if (!dev_page_is_reusable(page)) 844662306a36Sopenharmony_ci return false; 844762306a36Sopenharmony_ci 844862306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 844962306a36Sopenharmony_ci /* if we are only owner of page we can reuse it */ 845062306a36Sopenharmony_ci if (unlikely((rx_buf_pgcnt - pagecnt_bias) > 1)) 845162306a36Sopenharmony_ci return false; 845262306a36Sopenharmony_ci#else 845362306a36Sopenharmony_ci#define IGB_LAST_OFFSET \ 845462306a36Sopenharmony_ci (SKB_WITH_OVERHEAD(PAGE_SIZE) - IGB_RXBUFFER_2048) 845562306a36Sopenharmony_ci 845662306a36Sopenharmony_ci if (rx_buffer->page_offset > IGB_LAST_OFFSET) 845762306a36Sopenharmony_ci return false; 845862306a36Sopenharmony_ci#endif 845962306a36Sopenharmony_ci 846062306a36Sopenharmony_ci /* If we have drained the page fragment pool we need to update 846162306a36Sopenharmony_ci * the pagecnt_bias and page count so that we fully restock the 846262306a36Sopenharmony_ci * number of references the driver holds. 846362306a36Sopenharmony_ci */ 846462306a36Sopenharmony_ci if (unlikely(pagecnt_bias == 1)) { 846562306a36Sopenharmony_ci page_ref_add(page, USHRT_MAX - 1); 846662306a36Sopenharmony_ci rx_buffer->pagecnt_bias = USHRT_MAX; 846762306a36Sopenharmony_ci } 846862306a36Sopenharmony_ci 846962306a36Sopenharmony_ci return true; 847062306a36Sopenharmony_ci} 847162306a36Sopenharmony_ci 847262306a36Sopenharmony_ci/** 847362306a36Sopenharmony_ci * igb_add_rx_frag - Add contents of Rx buffer to sk_buff 847462306a36Sopenharmony_ci * @rx_ring: rx descriptor ring to transact packets on 847562306a36Sopenharmony_ci * @rx_buffer: buffer containing page to add 847662306a36Sopenharmony_ci * @skb: sk_buff to place the data into 847762306a36Sopenharmony_ci * @size: size of buffer to be added 847862306a36Sopenharmony_ci * 847962306a36Sopenharmony_ci * This function will add the data contained in rx_buffer->page to the skb. 848062306a36Sopenharmony_ci **/ 848162306a36Sopenharmony_cistatic void igb_add_rx_frag(struct igb_ring *rx_ring, 848262306a36Sopenharmony_ci struct igb_rx_buffer *rx_buffer, 848362306a36Sopenharmony_ci struct sk_buff *skb, 848462306a36Sopenharmony_ci unsigned int size) 848562306a36Sopenharmony_ci{ 848662306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 848762306a36Sopenharmony_ci unsigned int truesize = igb_rx_pg_size(rx_ring) / 2; 848862306a36Sopenharmony_ci#else 848962306a36Sopenharmony_ci unsigned int truesize = ring_uses_build_skb(rx_ring) ? 849062306a36Sopenharmony_ci SKB_DATA_ALIGN(IGB_SKB_PAD + size) : 849162306a36Sopenharmony_ci SKB_DATA_ALIGN(size); 849262306a36Sopenharmony_ci#endif 849362306a36Sopenharmony_ci skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page, 849462306a36Sopenharmony_ci rx_buffer->page_offset, size, truesize); 849562306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 849662306a36Sopenharmony_ci rx_buffer->page_offset ^= truesize; 849762306a36Sopenharmony_ci#else 849862306a36Sopenharmony_ci rx_buffer->page_offset += truesize; 849962306a36Sopenharmony_ci#endif 850062306a36Sopenharmony_ci} 850162306a36Sopenharmony_ci 850262306a36Sopenharmony_cistatic struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring, 850362306a36Sopenharmony_ci struct igb_rx_buffer *rx_buffer, 850462306a36Sopenharmony_ci struct xdp_buff *xdp, 850562306a36Sopenharmony_ci ktime_t timestamp) 850662306a36Sopenharmony_ci{ 850762306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 850862306a36Sopenharmony_ci unsigned int truesize = igb_rx_pg_size(rx_ring) / 2; 850962306a36Sopenharmony_ci#else 851062306a36Sopenharmony_ci unsigned int truesize = SKB_DATA_ALIGN(xdp->data_end - 851162306a36Sopenharmony_ci xdp->data_hard_start); 851262306a36Sopenharmony_ci#endif 851362306a36Sopenharmony_ci unsigned int size = xdp->data_end - xdp->data; 851462306a36Sopenharmony_ci unsigned int headlen; 851562306a36Sopenharmony_ci struct sk_buff *skb; 851662306a36Sopenharmony_ci 851762306a36Sopenharmony_ci /* prefetch first cache line of first page */ 851862306a36Sopenharmony_ci net_prefetch(xdp->data); 851962306a36Sopenharmony_ci 852062306a36Sopenharmony_ci /* allocate a skb to store the frags */ 852162306a36Sopenharmony_ci skb = napi_alloc_skb(&rx_ring->q_vector->napi, IGB_RX_HDR_LEN); 852262306a36Sopenharmony_ci if (unlikely(!skb)) 852362306a36Sopenharmony_ci return NULL; 852462306a36Sopenharmony_ci 852562306a36Sopenharmony_ci if (timestamp) 852662306a36Sopenharmony_ci skb_hwtstamps(skb)->hwtstamp = timestamp; 852762306a36Sopenharmony_ci 852862306a36Sopenharmony_ci /* Determine available headroom for copy */ 852962306a36Sopenharmony_ci headlen = size; 853062306a36Sopenharmony_ci if (headlen > IGB_RX_HDR_LEN) 853162306a36Sopenharmony_ci headlen = eth_get_headlen(skb->dev, xdp->data, IGB_RX_HDR_LEN); 853262306a36Sopenharmony_ci 853362306a36Sopenharmony_ci /* align pull length to size of long to optimize memcpy performance */ 853462306a36Sopenharmony_ci memcpy(__skb_put(skb, headlen), xdp->data, ALIGN(headlen, sizeof(long))); 853562306a36Sopenharmony_ci 853662306a36Sopenharmony_ci /* update all of the pointers */ 853762306a36Sopenharmony_ci size -= headlen; 853862306a36Sopenharmony_ci if (size) { 853962306a36Sopenharmony_ci skb_add_rx_frag(skb, 0, rx_buffer->page, 854062306a36Sopenharmony_ci (xdp->data + headlen) - page_address(rx_buffer->page), 854162306a36Sopenharmony_ci size, truesize); 854262306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 854362306a36Sopenharmony_ci rx_buffer->page_offset ^= truesize; 854462306a36Sopenharmony_ci#else 854562306a36Sopenharmony_ci rx_buffer->page_offset += truesize; 854662306a36Sopenharmony_ci#endif 854762306a36Sopenharmony_ci } else { 854862306a36Sopenharmony_ci rx_buffer->pagecnt_bias++; 854962306a36Sopenharmony_ci } 855062306a36Sopenharmony_ci 855162306a36Sopenharmony_ci return skb; 855262306a36Sopenharmony_ci} 855362306a36Sopenharmony_ci 855462306a36Sopenharmony_cistatic struct sk_buff *igb_build_skb(struct igb_ring *rx_ring, 855562306a36Sopenharmony_ci struct igb_rx_buffer *rx_buffer, 855662306a36Sopenharmony_ci struct xdp_buff *xdp, 855762306a36Sopenharmony_ci ktime_t timestamp) 855862306a36Sopenharmony_ci{ 855962306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 856062306a36Sopenharmony_ci unsigned int truesize = igb_rx_pg_size(rx_ring) / 2; 856162306a36Sopenharmony_ci#else 856262306a36Sopenharmony_ci unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + 856362306a36Sopenharmony_ci SKB_DATA_ALIGN(xdp->data_end - 856462306a36Sopenharmony_ci xdp->data_hard_start); 856562306a36Sopenharmony_ci#endif 856662306a36Sopenharmony_ci unsigned int metasize = xdp->data - xdp->data_meta; 856762306a36Sopenharmony_ci struct sk_buff *skb; 856862306a36Sopenharmony_ci 856962306a36Sopenharmony_ci /* prefetch first cache line of first page */ 857062306a36Sopenharmony_ci net_prefetch(xdp->data_meta); 857162306a36Sopenharmony_ci 857262306a36Sopenharmony_ci /* build an skb around the page buffer */ 857362306a36Sopenharmony_ci skb = napi_build_skb(xdp->data_hard_start, truesize); 857462306a36Sopenharmony_ci if (unlikely(!skb)) 857562306a36Sopenharmony_ci return NULL; 857662306a36Sopenharmony_ci 857762306a36Sopenharmony_ci /* update pointers within the skb to store the data */ 857862306a36Sopenharmony_ci skb_reserve(skb, xdp->data - xdp->data_hard_start); 857962306a36Sopenharmony_ci __skb_put(skb, xdp->data_end - xdp->data); 858062306a36Sopenharmony_ci 858162306a36Sopenharmony_ci if (metasize) 858262306a36Sopenharmony_ci skb_metadata_set(skb, metasize); 858362306a36Sopenharmony_ci 858462306a36Sopenharmony_ci if (timestamp) 858562306a36Sopenharmony_ci skb_hwtstamps(skb)->hwtstamp = timestamp; 858662306a36Sopenharmony_ci 858762306a36Sopenharmony_ci /* update buffer offset */ 858862306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 858962306a36Sopenharmony_ci rx_buffer->page_offset ^= truesize; 859062306a36Sopenharmony_ci#else 859162306a36Sopenharmony_ci rx_buffer->page_offset += truesize; 859262306a36Sopenharmony_ci#endif 859362306a36Sopenharmony_ci 859462306a36Sopenharmony_ci return skb; 859562306a36Sopenharmony_ci} 859662306a36Sopenharmony_ci 859762306a36Sopenharmony_cistatic struct sk_buff *igb_run_xdp(struct igb_adapter *adapter, 859862306a36Sopenharmony_ci struct igb_ring *rx_ring, 859962306a36Sopenharmony_ci struct xdp_buff *xdp) 860062306a36Sopenharmony_ci{ 860162306a36Sopenharmony_ci int err, result = IGB_XDP_PASS; 860262306a36Sopenharmony_ci struct bpf_prog *xdp_prog; 860362306a36Sopenharmony_ci u32 act; 860462306a36Sopenharmony_ci 860562306a36Sopenharmony_ci xdp_prog = READ_ONCE(rx_ring->xdp_prog); 860662306a36Sopenharmony_ci 860762306a36Sopenharmony_ci if (!xdp_prog) 860862306a36Sopenharmony_ci goto xdp_out; 860962306a36Sopenharmony_ci 861062306a36Sopenharmony_ci prefetchw(xdp->data_hard_start); /* xdp_frame write */ 861162306a36Sopenharmony_ci 861262306a36Sopenharmony_ci act = bpf_prog_run_xdp(xdp_prog, xdp); 861362306a36Sopenharmony_ci switch (act) { 861462306a36Sopenharmony_ci case XDP_PASS: 861562306a36Sopenharmony_ci break; 861662306a36Sopenharmony_ci case XDP_TX: 861762306a36Sopenharmony_ci result = igb_xdp_xmit_back(adapter, xdp); 861862306a36Sopenharmony_ci if (result == IGB_XDP_CONSUMED) 861962306a36Sopenharmony_ci goto out_failure; 862062306a36Sopenharmony_ci break; 862162306a36Sopenharmony_ci case XDP_REDIRECT: 862262306a36Sopenharmony_ci err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog); 862362306a36Sopenharmony_ci if (err) 862462306a36Sopenharmony_ci goto out_failure; 862562306a36Sopenharmony_ci result = IGB_XDP_REDIR; 862662306a36Sopenharmony_ci break; 862762306a36Sopenharmony_ci default: 862862306a36Sopenharmony_ci bpf_warn_invalid_xdp_action(adapter->netdev, xdp_prog, act); 862962306a36Sopenharmony_ci fallthrough; 863062306a36Sopenharmony_ci case XDP_ABORTED: 863162306a36Sopenharmony_ciout_failure: 863262306a36Sopenharmony_ci trace_xdp_exception(rx_ring->netdev, xdp_prog, act); 863362306a36Sopenharmony_ci fallthrough; 863462306a36Sopenharmony_ci case XDP_DROP: 863562306a36Sopenharmony_ci result = IGB_XDP_CONSUMED; 863662306a36Sopenharmony_ci break; 863762306a36Sopenharmony_ci } 863862306a36Sopenharmony_cixdp_out: 863962306a36Sopenharmony_ci return ERR_PTR(-result); 864062306a36Sopenharmony_ci} 864162306a36Sopenharmony_ci 864262306a36Sopenharmony_cistatic unsigned int igb_rx_frame_truesize(struct igb_ring *rx_ring, 864362306a36Sopenharmony_ci unsigned int size) 864462306a36Sopenharmony_ci{ 864562306a36Sopenharmony_ci unsigned int truesize; 864662306a36Sopenharmony_ci 864762306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 864862306a36Sopenharmony_ci truesize = igb_rx_pg_size(rx_ring) / 2; /* Must be power-of-2 */ 864962306a36Sopenharmony_ci#else 865062306a36Sopenharmony_ci truesize = ring_uses_build_skb(rx_ring) ? 865162306a36Sopenharmony_ci SKB_DATA_ALIGN(IGB_SKB_PAD + size) + 865262306a36Sopenharmony_ci SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : 865362306a36Sopenharmony_ci SKB_DATA_ALIGN(size); 865462306a36Sopenharmony_ci#endif 865562306a36Sopenharmony_ci return truesize; 865662306a36Sopenharmony_ci} 865762306a36Sopenharmony_ci 865862306a36Sopenharmony_cistatic void igb_rx_buffer_flip(struct igb_ring *rx_ring, 865962306a36Sopenharmony_ci struct igb_rx_buffer *rx_buffer, 866062306a36Sopenharmony_ci unsigned int size) 866162306a36Sopenharmony_ci{ 866262306a36Sopenharmony_ci unsigned int truesize = igb_rx_frame_truesize(rx_ring, size); 866362306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 866462306a36Sopenharmony_ci rx_buffer->page_offset ^= truesize; 866562306a36Sopenharmony_ci#else 866662306a36Sopenharmony_ci rx_buffer->page_offset += truesize; 866762306a36Sopenharmony_ci#endif 866862306a36Sopenharmony_ci} 866962306a36Sopenharmony_ci 867062306a36Sopenharmony_cistatic inline void igb_rx_checksum(struct igb_ring *ring, 867162306a36Sopenharmony_ci union e1000_adv_rx_desc *rx_desc, 867262306a36Sopenharmony_ci struct sk_buff *skb) 867362306a36Sopenharmony_ci{ 867462306a36Sopenharmony_ci skb_checksum_none_assert(skb); 867562306a36Sopenharmony_ci 867662306a36Sopenharmony_ci /* Ignore Checksum bit is set */ 867762306a36Sopenharmony_ci if (igb_test_staterr(rx_desc, E1000_RXD_STAT_IXSM)) 867862306a36Sopenharmony_ci return; 867962306a36Sopenharmony_ci 868062306a36Sopenharmony_ci /* Rx checksum disabled via ethtool */ 868162306a36Sopenharmony_ci if (!(ring->netdev->features & NETIF_F_RXCSUM)) 868262306a36Sopenharmony_ci return; 868362306a36Sopenharmony_ci 868462306a36Sopenharmony_ci /* TCP/UDP checksum error bit is set */ 868562306a36Sopenharmony_ci if (igb_test_staterr(rx_desc, 868662306a36Sopenharmony_ci E1000_RXDEXT_STATERR_TCPE | 868762306a36Sopenharmony_ci E1000_RXDEXT_STATERR_IPE)) { 868862306a36Sopenharmony_ci /* work around errata with sctp packets where the TCPE aka 868962306a36Sopenharmony_ci * L4E bit is set incorrectly on 64 byte (60 byte w/o crc) 869062306a36Sopenharmony_ci * packets, (aka let the stack check the crc32c) 869162306a36Sopenharmony_ci */ 869262306a36Sopenharmony_ci if (!((skb->len == 60) && 869362306a36Sopenharmony_ci test_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags))) { 869462306a36Sopenharmony_ci u64_stats_update_begin(&ring->rx_syncp); 869562306a36Sopenharmony_ci ring->rx_stats.csum_err++; 869662306a36Sopenharmony_ci u64_stats_update_end(&ring->rx_syncp); 869762306a36Sopenharmony_ci } 869862306a36Sopenharmony_ci /* let the stack verify checksum errors */ 869962306a36Sopenharmony_ci return; 870062306a36Sopenharmony_ci } 870162306a36Sopenharmony_ci /* It must be a TCP or UDP packet with a valid checksum */ 870262306a36Sopenharmony_ci if (igb_test_staterr(rx_desc, E1000_RXD_STAT_TCPCS | 870362306a36Sopenharmony_ci E1000_RXD_STAT_UDPCS)) 870462306a36Sopenharmony_ci skb->ip_summed = CHECKSUM_UNNECESSARY; 870562306a36Sopenharmony_ci 870662306a36Sopenharmony_ci dev_dbg(ring->dev, "cksum success: bits %08X\n", 870762306a36Sopenharmony_ci le32_to_cpu(rx_desc->wb.upper.status_error)); 870862306a36Sopenharmony_ci} 870962306a36Sopenharmony_ci 871062306a36Sopenharmony_cistatic inline void igb_rx_hash(struct igb_ring *ring, 871162306a36Sopenharmony_ci union e1000_adv_rx_desc *rx_desc, 871262306a36Sopenharmony_ci struct sk_buff *skb) 871362306a36Sopenharmony_ci{ 871462306a36Sopenharmony_ci if (ring->netdev->features & NETIF_F_RXHASH) 871562306a36Sopenharmony_ci skb_set_hash(skb, 871662306a36Sopenharmony_ci le32_to_cpu(rx_desc->wb.lower.hi_dword.rss), 871762306a36Sopenharmony_ci PKT_HASH_TYPE_L3); 871862306a36Sopenharmony_ci} 871962306a36Sopenharmony_ci 872062306a36Sopenharmony_ci/** 872162306a36Sopenharmony_ci * igb_is_non_eop - process handling of non-EOP buffers 872262306a36Sopenharmony_ci * @rx_ring: Rx ring being processed 872362306a36Sopenharmony_ci * @rx_desc: Rx descriptor for current buffer 872462306a36Sopenharmony_ci * 872562306a36Sopenharmony_ci * This function updates next to clean. If the buffer is an EOP buffer 872662306a36Sopenharmony_ci * this function exits returning false, otherwise it will place the 872762306a36Sopenharmony_ci * sk_buff in the next buffer to be chained and return true indicating 872862306a36Sopenharmony_ci * that this is in fact a non-EOP buffer. 872962306a36Sopenharmony_ci **/ 873062306a36Sopenharmony_cistatic bool igb_is_non_eop(struct igb_ring *rx_ring, 873162306a36Sopenharmony_ci union e1000_adv_rx_desc *rx_desc) 873262306a36Sopenharmony_ci{ 873362306a36Sopenharmony_ci u32 ntc = rx_ring->next_to_clean + 1; 873462306a36Sopenharmony_ci 873562306a36Sopenharmony_ci /* fetch, update, and store next to clean */ 873662306a36Sopenharmony_ci ntc = (ntc < rx_ring->count) ? ntc : 0; 873762306a36Sopenharmony_ci rx_ring->next_to_clean = ntc; 873862306a36Sopenharmony_ci 873962306a36Sopenharmony_ci prefetch(IGB_RX_DESC(rx_ring, ntc)); 874062306a36Sopenharmony_ci 874162306a36Sopenharmony_ci if (likely(igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP))) 874262306a36Sopenharmony_ci return false; 874362306a36Sopenharmony_ci 874462306a36Sopenharmony_ci return true; 874562306a36Sopenharmony_ci} 874662306a36Sopenharmony_ci 874762306a36Sopenharmony_ci/** 874862306a36Sopenharmony_ci * igb_cleanup_headers - Correct corrupted or empty headers 874962306a36Sopenharmony_ci * @rx_ring: rx descriptor ring packet is being transacted on 875062306a36Sopenharmony_ci * @rx_desc: pointer to the EOP Rx descriptor 875162306a36Sopenharmony_ci * @skb: pointer to current skb being fixed 875262306a36Sopenharmony_ci * 875362306a36Sopenharmony_ci * Address the case where we are pulling data in on pages only 875462306a36Sopenharmony_ci * and as such no data is present in the skb header. 875562306a36Sopenharmony_ci * 875662306a36Sopenharmony_ci * In addition if skb is not at least 60 bytes we need to pad it so that 875762306a36Sopenharmony_ci * it is large enough to qualify as a valid Ethernet frame. 875862306a36Sopenharmony_ci * 875962306a36Sopenharmony_ci * Returns true if an error was encountered and skb was freed. 876062306a36Sopenharmony_ci **/ 876162306a36Sopenharmony_cistatic bool igb_cleanup_headers(struct igb_ring *rx_ring, 876262306a36Sopenharmony_ci union e1000_adv_rx_desc *rx_desc, 876362306a36Sopenharmony_ci struct sk_buff *skb) 876462306a36Sopenharmony_ci{ 876562306a36Sopenharmony_ci /* XDP packets use error pointer so abort at this point */ 876662306a36Sopenharmony_ci if (IS_ERR(skb)) 876762306a36Sopenharmony_ci return true; 876862306a36Sopenharmony_ci 876962306a36Sopenharmony_ci if (unlikely((igb_test_staterr(rx_desc, 877062306a36Sopenharmony_ci E1000_RXDEXT_ERR_FRAME_ERR_MASK)))) { 877162306a36Sopenharmony_ci struct net_device *netdev = rx_ring->netdev; 877262306a36Sopenharmony_ci if (!(netdev->features & NETIF_F_RXALL)) { 877362306a36Sopenharmony_ci dev_kfree_skb_any(skb); 877462306a36Sopenharmony_ci return true; 877562306a36Sopenharmony_ci } 877662306a36Sopenharmony_ci } 877762306a36Sopenharmony_ci 877862306a36Sopenharmony_ci /* if eth_skb_pad returns an error the skb was freed */ 877962306a36Sopenharmony_ci if (eth_skb_pad(skb)) 878062306a36Sopenharmony_ci return true; 878162306a36Sopenharmony_ci 878262306a36Sopenharmony_ci return false; 878362306a36Sopenharmony_ci} 878462306a36Sopenharmony_ci 878562306a36Sopenharmony_ci/** 878662306a36Sopenharmony_ci * igb_process_skb_fields - Populate skb header fields from Rx descriptor 878762306a36Sopenharmony_ci * @rx_ring: rx descriptor ring packet is being transacted on 878862306a36Sopenharmony_ci * @rx_desc: pointer to the EOP Rx descriptor 878962306a36Sopenharmony_ci * @skb: pointer to current skb being populated 879062306a36Sopenharmony_ci * 879162306a36Sopenharmony_ci * This function checks the ring, descriptor, and packet information in 879262306a36Sopenharmony_ci * order to populate the hash, checksum, VLAN, timestamp, protocol, and 879362306a36Sopenharmony_ci * other fields within the skb. 879462306a36Sopenharmony_ci **/ 879562306a36Sopenharmony_cistatic void igb_process_skb_fields(struct igb_ring *rx_ring, 879662306a36Sopenharmony_ci union e1000_adv_rx_desc *rx_desc, 879762306a36Sopenharmony_ci struct sk_buff *skb) 879862306a36Sopenharmony_ci{ 879962306a36Sopenharmony_ci struct net_device *dev = rx_ring->netdev; 880062306a36Sopenharmony_ci 880162306a36Sopenharmony_ci igb_rx_hash(rx_ring, rx_desc, skb); 880262306a36Sopenharmony_ci 880362306a36Sopenharmony_ci igb_rx_checksum(rx_ring, rx_desc, skb); 880462306a36Sopenharmony_ci 880562306a36Sopenharmony_ci if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS) && 880662306a36Sopenharmony_ci !igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) 880762306a36Sopenharmony_ci igb_ptp_rx_rgtstamp(rx_ring->q_vector, skb); 880862306a36Sopenharmony_ci 880962306a36Sopenharmony_ci if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) && 881062306a36Sopenharmony_ci igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) { 881162306a36Sopenharmony_ci u16 vid; 881262306a36Sopenharmony_ci 881362306a36Sopenharmony_ci if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) && 881462306a36Sopenharmony_ci test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags)) 881562306a36Sopenharmony_ci vid = be16_to_cpu((__force __be16)rx_desc->wb.upper.vlan); 881662306a36Sopenharmony_ci else 881762306a36Sopenharmony_ci vid = le16_to_cpu(rx_desc->wb.upper.vlan); 881862306a36Sopenharmony_ci 881962306a36Sopenharmony_ci __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); 882062306a36Sopenharmony_ci } 882162306a36Sopenharmony_ci 882262306a36Sopenharmony_ci skb_record_rx_queue(skb, rx_ring->queue_index); 882362306a36Sopenharmony_ci 882462306a36Sopenharmony_ci skb->protocol = eth_type_trans(skb, rx_ring->netdev); 882562306a36Sopenharmony_ci} 882662306a36Sopenharmony_ci 882762306a36Sopenharmony_cistatic unsigned int igb_rx_offset(struct igb_ring *rx_ring) 882862306a36Sopenharmony_ci{ 882962306a36Sopenharmony_ci return ring_uses_build_skb(rx_ring) ? IGB_SKB_PAD : 0; 883062306a36Sopenharmony_ci} 883162306a36Sopenharmony_ci 883262306a36Sopenharmony_cistatic struct igb_rx_buffer *igb_get_rx_buffer(struct igb_ring *rx_ring, 883362306a36Sopenharmony_ci const unsigned int size, int *rx_buf_pgcnt) 883462306a36Sopenharmony_ci{ 883562306a36Sopenharmony_ci struct igb_rx_buffer *rx_buffer; 883662306a36Sopenharmony_ci 883762306a36Sopenharmony_ci rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; 883862306a36Sopenharmony_ci *rx_buf_pgcnt = 883962306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 884062306a36Sopenharmony_ci page_count(rx_buffer->page); 884162306a36Sopenharmony_ci#else 884262306a36Sopenharmony_ci 0; 884362306a36Sopenharmony_ci#endif 884462306a36Sopenharmony_ci prefetchw(rx_buffer->page); 884562306a36Sopenharmony_ci 884662306a36Sopenharmony_ci /* we are reusing so sync this buffer for CPU use */ 884762306a36Sopenharmony_ci dma_sync_single_range_for_cpu(rx_ring->dev, 884862306a36Sopenharmony_ci rx_buffer->dma, 884962306a36Sopenharmony_ci rx_buffer->page_offset, 885062306a36Sopenharmony_ci size, 885162306a36Sopenharmony_ci DMA_FROM_DEVICE); 885262306a36Sopenharmony_ci 885362306a36Sopenharmony_ci rx_buffer->pagecnt_bias--; 885462306a36Sopenharmony_ci 885562306a36Sopenharmony_ci return rx_buffer; 885662306a36Sopenharmony_ci} 885762306a36Sopenharmony_ci 885862306a36Sopenharmony_cistatic void igb_put_rx_buffer(struct igb_ring *rx_ring, 885962306a36Sopenharmony_ci struct igb_rx_buffer *rx_buffer, int rx_buf_pgcnt) 886062306a36Sopenharmony_ci{ 886162306a36Sopenharmony_ci if (igb_can_reuse_rx_page(rx_buffer, rx_buf_pgcnt)) { 886262306a36Sopenharmony_ci /* hand second half of page back to the ring */ 886362306a36Sopenharmony_ci igb_reuse_rx_page(rx_ring, rx_buffer); 886462306a36Sopenharmony_ci } else { 886562306a36Sopenharmony_ci /* We are not reusing the buffer so unmap it and free 886662306a36Sopenharmony_ci * any references we are holding to it 886762306a36Sopenharmony_ci */ 886862306a36Sopenharmony_ci dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma, 886962306a36Sopenharmony_ci igb_rx_pg_size(rx_ring), DMA_FROM_DEVICE, 887062306a36Sopenharmony_ci IGB_RX_DMA_ATTR); 887162306a36Sopenharmony_ci __page_frag_cache_drain(rx_buffer->page, 887262306a36Sopenharmony_ci rx_buffer->pagecnt_bias); 887362306a36Sopenharmony_ci } 887462306a36Sopenharmony_ci 887562306a36Sopenharmony_ci /* clear contents of rx_buffer */ 887662306a36Sopenharmony_ci rx_buffer->page = NULL; 887762306a36Sopenharmony_ci} 887862306a36Sopenharmony_ci 887962306a36Sopenharmony_cistatic int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) 888062306a36Sopenharmony_ci{ 888162306a36Sopenharmony_ci struct igb_adapter *adapter = q_vector->adapter; 888262306a36Sopenharmony_ci struct igb_ring *rx_ring = q_vector->rx.ring; 888362306a36Sopenharmony_ci struct sk_buff *skb = rx_ring->skb; 888462306a36Sopenharmony_ci unsigned int total_bytes = 0, total_packets = 0; 888562306a36Sopenharmony_ci u16 cleaned_count = igb_desc_unused(rx_ring); 888662306a36Sopenharmony_ci unsigned int xdp_xmit = 0; 888762306a36Sopenharmony_ci struct xdp_buff xdp; 888862306a36Sopenharmony_ci u32 frame_sz = 0; 888962306a36Sopenharmony_ci int rx_buf_pgcnt; 889062306a36Sopenharmony_ci 889162306a36Sopenharmony_ci /* Frame size depend on rx_ring setup when PAGE_SIZE=4K */ 889262306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 889362306a36Sopenharmony_ci frame_sz = igb_rx_frame_truesize(rx_ring, 0); 889462306a36Sopenharmony_ci#endif 889562306a36Sopenharmony_ci xdp_init_buff(&xdp, frame_sz, &rx_ring->xdp_rxq); 889662306a36Sopenharmony_ci 889762306a36Sopenharmony_ci while (likely(total_packets < budget)) { 889862306a36Sopenharmony_ci union e1000_adv_rx_desc *rx_desc; 889962306a36Sopenharmony_ci struct igb_rx_buffer *rx_buffer; 890062306a36Sopenharmony_ci ktime_t timestamp = 0; 890162306a36Sopenharmony_ci int pkt_offset = 0; 890262306a36Sopenharmony_ci unsigned int size; 890362306a36Sopenharmony_ci void *pktbuf; 890462306a36Sopenharmony_ci 890562306a36Sopenharmony_ci /* return some buffers to hardware, one at a time is too slow */ 890662306a36Sopenharmony_ci if (cleaned_count >= IGB_RX_BUFFER_WRITE) { 890762306a36Sopenharmony_ci igb_alloc_rx_buffers(rx_ring, cleaned_count); 890862306a36Sopenharmony_ci cleaned_count = 0; 890962306a36Sopenharmony_ci } 891062306a36Sopenharmony_ci 891162306a36Sopenharmony_ci rx_desc = IGB_RX_DESC(rx_ring, rx_ring->next_to_clean); 891262306a36Sopenharmony_ci size = le16_to_cpu(rx_desc->wb.upper.length); 891362306a36Sopenharmony_ci if (!size) 891462306a36Sopenharmony_ci break; 891562306a36Sopenharmony_ci 891662306a36Sopenharmony_ci /* This memory barrier is needed to keep us from reading 891762306a36Sopenharmony_ci * any other fields out of the rx_desc until we know the 891862306a36Sopenharmony_ci * descriptor has been written back 891962306a36Sopenharmony_ci */ 892062306a36Sopenharmony_ci dma_rmb(); 892162306a36Sopenharmony_ci 892262306a36Sopenharmony_ci rx_buffer = igb_get_rx_buffer(rx_ring, size, &rx_buf_pgcnt); 892362306a36Sopenharmony_ci pktbuf = page_address(rx_buffer->page) + rx_buffer->page_offset; 892462306a36Sopenharmony_ci 892562306a36Sopenharmony_ci /* pull rx packet timestamp if available and valid */ 892662306a36Sopenharmony_ci if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { 892762306a36Sopenharmony_ci int ts_hdr_len; 892862306a36Sopenharmony_ci 892962306a36Sopenharmony_ci ts_hdr_len = igb_ptp_rx_pktstamp(rx_ring->q_vector, 893062306a36Sopenharmony_ci pktbuf, ×tamp); 893162306a36Sopenharmony_ci 893262306a36Sopenharmony_ci pkt_offset += ts_hdr_len; 893362306a36Sopenharmony_ci size -= ts_hdr_len; 893462306a36Sopenharmony_ci } 893562306a36Sopenharmony_ci 893662306a36Sopenharmony_ci /* retrieve a buffer from the ring */ 893762306a36Sopenharmony_ci if (!skb) { 893862306a36Sopenharmony_ci unsigned char *hard_start = pktbuf - igb_rx_offset(rx_ring); 893962306a36Sopenharmony_ci unsigned int offset = pkt_offset + igb_rx_offset(rx_ring); 894062306a36Sopenharmony_ci 894162306a36Sopenharmony_ci xdp_prepare_buff(&xdp, hard_start, offset, size, true); 894262306a36Sopenharmony_ci xdp_buff_clear_frags_flag(&xdp); 894362306a36Sopenharmony_ci#if (PAGE_SIZE > 4096) 894462306a36Sopenharmony_ci /* At larger PAGE_SIZE, frame_sz depend on len size */ 894562306a36Sopenharmony_ci xdp.frame_sz = igb_rx_frame_truesize(rx_ring, size); 894662306a36Sopenharmony_ci#endif 894762306a36Sopenharmony_ci skb = igb_run_xdp(adapter, rx_ring, &xdp); 894862306a36Sopenharmony_ci } 894962306a36Sopenharmony_ci 895062306a36Sopenharmony_ci if (IS_ERR(skb)) { 895162306a36Sopenharmony_ci unsigned int xdp_res = -PTR_ERR(skb); 895262306a36Sopenharmony_ci 895362306a36Sopenharmony_ci if (xdp_res & (IGB_XDP_TX | IGB_XDP_REDIR)) { 895462306a36Sopenharmony_ci xdp_xmit |= xdp_res; 895562306a36Sopenharmony_ci igb_rx_buffer_flip(rx_ring, rx_buffer, size); 895662306a36Sopenharmony_ci } else { 895762306a36Sopenharmony_ci rx_buffer->pagecnt_bias++; 895862306a36Sopenharmony_ci } 895962306a36Sopenharmony_ci total_packets++; 896062306a36Sopenharmony_ci total_bytes += size; 896162306a36Sopenharmony_ci } else if (skb) 896262306a36Sopenharmony_ci igb_add_rx_frag(rx_ring, rx_buffer, skb, size); 896362306a36Sopenharmony_ci else if (ring_uses_build_skb(rx_ring)) 896462306a36Sopenharmony_ci skb = igb_build_skb(rx_ring, rx_buffer, &xdp, 896562306a36Sopenharmony_ci timestamp); 896662306a36Sopenharmony_ci else 896762306a36Sopenharmony_ci skb = igb_construct_skb(rx_ring, rx_buffer, 896862306a36Sopenharmony_ci &xdp, timestamp); 896962306a36Sopenharmony_ci 897062306a36Sopenharmony_ci /* exit if we failed to retrieve a buffer */ 897162306a36Sopenharmony_ci if (!skb) { 897262306a36Sopenharmony_ci rx_ring->rx_stats.alloc_failed++; 897362306a36Sopenharmony_ci rx_buffer->pagecnt_bias++; 897462306a36Sopenharmony_ci break; 897562306a36Sopenharmony_ci } 897662306a36Sopenharmony_ci 897762306a36Sopenharmony_ci igb_put_rx_buffer(rx_ring, rx_buffer, rx_buf_pgcnt); 897862306a36Sopenharmony_ci cleaned_count++; 897962306a36Sopenharmony_ci 898062306a36Sopenharmony_ci /* fetch next buffer in frame if non-eop */ 898162306a36Sopenharmony_ci if (igb_is_non_eop(rx_ring, rx_desc)) 898262306a36Sopenharmony_ci continue; 898362306a36Sopenharmony_ci 898462306a36Sopenharmony_ci /* verify the packet layout is correct */ 898562306a36Sopenharmony_ci if (igb_cleanup_headers(rx_ring, rx_desc, skb)) { 898662306a36Sopenharmony_ci skb = NULL; 898762306a36Sopenharmony_ci continue; 898862306a36Sopenharmony_ci } 898962306a36Sopenharmony_ci 899062306a36Sopenharmony_ci /* probably a little skewed due to removing CRC */ 899162306a36Sopenharmony_ci total_bytes += skb->len; 899262306a36Sopenharmony_ci 899362306a36Sopenharmony_ci /* populate checksum, timestamp, VLAN, and protocol */ 899462306a36Sopenharmony_ci igb_process_skb_fields(rx_ring, rx_desc, skb); 899562306a36Sopenharmony_ci 899662306a36Sopenharmony_ci napi_gro_receive(&q_vector->napi, skb); 899762306a36Sopenharmony_ci 899862306a36Sopenharmony_ci /* reset skb pointer */ 899962306a36Sopenharmony_ci skb = NULL; 900062306a36Sopenharmony_ci 900162306a36Sopenharmony_ci /* update budget accounting */ 900262306a36Sopenharmony_ci total_packets++; 900362306a36Sopenharmony_ci } 900462306a36Sopenharmony_ci 900562306a36Sopenharmony_ci /* place incomplete frames back on ring for completion */ 900662306a36Sopenharmony_ci rx_ring->skb = skb; 900762306a36Sopenharmony_ci 900862306a36Sopenharmony_ci if (xdp_xmit & IGB_XDP_REDIR) 900962306a36Sopenharmony_ci xdp_do_flush(); 901062306a36Sopenharmony_ci 901162306a36Sopenharmony_ci if (xdp_xmit & IGB_XDP_TX) { 901262306a36Sopenharmony_ci struct igb_ring *tx_ring = igb_xdp_tx_queue_mapping(adapter); 901362306a36Sopenharmony_ci 901462306a36Sopenharmony_ci igb_xdp_ring_update_tail(tx_ring); 901562306a36Sopenharmony_ci } 901662306a36Sopenharmony_ci 901762306a36Sopenharmony_ci u64_stats_update_begin(&rx_ring->rx_syncp); 901862306a36Sopenharmony_ci rx_ring->rx_stats.packets += total_packets; 901962306a36Sopenharmony_ci rx_ring->rx_stats.bytes += total_bytes; 902062306a36Sopenharmony_ci u64_stats_update_end(&rx_ring->rx_syncp); 902162306a36Sopenharmony_ci q_vector->rx.total_packets += total_packets; 902262306a36Sopenharmony_ci q_vector->rx.total_bytes += total_bytes; 902362306a36Sopenharmony_ci 902462306a36Sopenharmony_ci if (cleaned_count) 902562306a36Sopenharmony_ci igb_alloc_rx_buffers(rx_ring, cleaned_count); 902662306a36Sopenharmony_ci 902762306a36Sopenharmony_ci return total_packets; 902862306a36Sopenharmony_ci} 902962306a36Sopenharmony_ci 903062306a36Sopenharmony_cistatic bool igb_alloc_mapped_page(struct igb_ring *rx_ring, 903162306a36Sopenharmony_ci struct igb_rx_buffer *bi) 903262306a36Sopenharmony_ci{ 903362306a36Sopenharmony_ci struct page *page = bi->page; 903462306a36Sopenharmony_ci dma_addr_t dma; 903562306a36Sopenharmony_ci 903662306a36Sopenharmony_ci /* since we are recycling buffers we should seldom need to alloc */ 903762306a36Sopenharmony_ci if (likely(page)) 903862306a36Sopenharmony_ci return true; 903962306a36Sopenharmony_ci 904062306a36Sopenharmony_ci /* alloc new page for storage */ 904162306a36Sopenharmony_ci page = dev_alloc_pages(igb_rx_pg_order(rx_ring)); 904262306a36Sopenharmony_ci if (unlikely(!page)) { 904362306a36Sopenharmony_ci rx_ring->rx_stats.alloc_failed++; 904462306a36Sopenharmony_ci return false; 904562306a36Sopenharmony_ci } 904662306a36Sopenharmony_ci 904762306a36Sopenharmony_ci /* map page for use */ 904862306a36Sopenharmony_ci dma = dma_map_page_attrs(rx_ring->dev, page, 0, 904962306a36Sopenharmony_ci igb_rx_pg_size(rx_ring), 905062306a36Sopenharmony_ci DMA_FROM_DEVICE, 905162306a36Sopenharmony_ci IGB_RX_DMA_ATTR); 905262306a36Sopenharmony_ci 905362306a36Sopenharmony_ci /* if mapping failed free memory back to system since 905462306a36Sopenharmony_ci * there isn't much point in holding memory we can't use 905562306a36Sopenharmony_ci */ 905662306a36Sopenharmony_ci if (dma_mapping_error(rx_ring->dev, dma)) { 905762306a36Sopenharmony_ci __free_pages(page, igb_rx_pg_order(rx_ring)); 905862306a36Sopenharmony_ci 905962306a36Sopenharmony_ci rx_ring->rx_stats.alloc_failed++; 906062306a36Sopenharmony_ci return false; 906162306a36Sopenharmony_ci } 906262306a36Sopenharmony_ci 906362306a36Sopenharmony_ci bi->dma = dma; 906462306a36Sopenharmony_ci bi->page = page; 906562306a36Sopenharmony_ci bi->page_offset = igb_rx_offset(rx_ring); 906662306a36Sopenharmony_ci page_ref_add(page, USHRT_MAX - 1); 906762306a36Sopenharmony_ci bi->pagecnt_bias = USHRT_MAX; 906862306a36Sopenharmony_ci 906962306a36Sopenharmony_ci return true; 907062306a36Sopenharmony_ci} 907162306a36Sopenharmony_ci 907262306a36Sopenharmony_ci/** 907362306a36Sopenharmony_ci * igb_alloc_rx_buffers - Replace used receive buffers 907462306a36Sopenharmony_ci * @rx_ring: rx descriptor ring to allocate new receive buffers 907562306a36Sopenharmony_ci * @cleaned_count: count of buffers to allocate 907662306a36Sopenharmony_ci **/ 907762306a36Sopenharmony_civoid igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count) 907862306a36Sopenharmony_ci{ 907962306a36Sopenharmony_ci union e1000_adv_rx_desc *rx_desc; 908062306a36Sopenharmony_ci struct igb_rx_buffer *bi; 908162306a36Sopenharmony_ci u16 i = rx_ring->next_to_use; 908262306a36Sopenharmony_ci u16 bufsz; 908362306a36Sopenharmony_ci 908462306a36Sopenharmony_ci /* nothing to do */ 908562306a36Sopenharmony_ci if (!cleaned_count) 908662306a36Sopenharmony_ci return; 908762306a36Sopenharmony_ci 908862306a36Sopenharmony_ci rx_desc = IGB_RX_DESC(rx_ring, i); 908962306a36Sopenharmony_ci bi = &rx_ring->rx_buffer_info[i]; 909062306a36Sopenharmony_ci i -= rx_ring->count; 909162306a36Sopenharmony_ci 909262306a36Sopenharmony_ci bufsz = igb_rx_bufsz(rx_ring); 909362306a36Sopenharmony_ci 909462306a36Sopenharmony_ci do { 909562306a36Sopenharmony_ci if (!igb_alloc_mapped_page(rx_ring, bi)) 909662306a36Sopenharmony_ci break; 909762306a36Sopenharmony_ci 909862306a36Sopenharmony_ci /* sync the buffer for use by the device */ 909962306a36Sopenharmony_ci dma_sync_single_range_for_device(rx_ring->dev, bi->dma, 910062306a36Sopenharmony_ci bi->page_offset, bufsz, 910162306a36Sopenharmony_ci DMA_FROM_DEVICE); 910262306a36Sopenharmony_ci 910362306a36Sopenharmony_ci /* Refresh the desc even if buffer_addrs didn't change 910462306a36Sopenharmony_ci * because each write-back erases this info. 910562306a36Sopenharmony_ci */ 910662306a36Sopenharmony_ci rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); 910762306a36Sopenharmony_ci 910862306a36Sopenharmony_ci rx_desc++; 910962306a36Sopenharmony_ci bi++; 911062306a36Sopenharmony_ci i++; 911162306a36Sopenharmony_ci if (unlikely(!i)) { 911262306a36Sopenharmony_ci rx_desc = IGB_RX_DESC(rx_ring, 0); 911362306a36Sopenharmony_ci bi = rx_ring->rx_buffer_info; 911462306a36Sopenharmony_ci i -= rx_ring->count; 911562306a36Sopenharmony_ci } 911662306a36Sopenharmony_ci 911762306a36Sopenharmony_ci /* clear the length for the next_to_use descriptor */ 911862306a36Sopenharmony_ci rx_desc->wb.upper.length = 0; 911962306a36Sopenharmony_ci 912062306a36Sopenharmony_ci cleaned_count--; 912162306a36Sopenharmony_ci } while (cleaned_count); 912262306a36Sopenharmony_ci 912362306a36Sopenharmony_ci i += rx_ring->count; 912462306a36Sopenharmony_ci 912562306a36Sopenharmony_ci if (rx_ring->next_to_use != i) { 912662306a36Sopenharmony_ci /* record the next descriptor to use */ 912762306a36Sopenharmony_ci rx_ring->next_to_use = i; 912862306a36Sopenharmony_ci 912962306a36Sopenharmony_ci /* update next to alloc since we have filled the ring */ 913062306a36Sopenharmony_ci rx_ring->next_to_alloc = i; 913162306a36Sopenharmony_ci 913262306a36Sopenharmony_ci /* Force memory writes to complete before letting h/w 913362306a36Sopenharmony_ci * know there are new descriptors to fetch. (Only 913462306a36Sopenharmony_ci * applicable for weak-ordered memory model archs, 913562306a36Sopenharmony_ci * such as IA-64). 913662306a36Sopenharmony_ci */ 913762306a36Sopenharmony_ci dma_wmb(); 913862306a36Sopenharmony_ci writel(i, rx_ring->tail); 913962306a36Sopenharmony_ci } 914062306a36Sopenharmony_ci} 914162306a36Sopenharmony_ci 914262306a36Sopenharmony_ci/** 914362306a36Sopenharmony_ci * igb_mii_ioctl - 914462306a36Sopenharmony_ci * @netdev: pointer to netdev struct 914562306a36Sopenharmony_ci * @ifr: interface structure 914662306a36Sopenharmony_ci * @cmd: ioctl command to execute 914762306a36Sopenharmony_ci **/ 914862306a36Sopenharmony_cistatic int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) 914962306a36Sopenharmony_ci{ 915062306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 915162306a36Sopenharmony_ci struct mii_ioctl_data *data = if_mii(ifr); 915262306a36Sopenharmony_ci 915362306a36Sopenharmony_ci if (adapter->hw.phy.media_type != e1000_media_type_copper) 915462306a36Sopenharmony_ci return -EOPNOTSUPP; 915562306a36Sopenharmony_ci 915662306a36Sopenharmony_ci switch (cmd) { 915762306a36Sopenharmony_ci case SIOCGMIIPHY: 915862306a36Sopenharmony_ci data->phy_id = adapter->hw.phy.addr; 915962306a36Sopenharmony_ci break; 916062306a36Sopenharmony_ci case SIOCGMIIREG: 916162306a36Sopenharmony_ci if (igb_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, 916262306a36Sopenharmony_ci &data->val_out)) 916362306a36Sopenharmony_ci return -EIO; 916462306a36Sopenharmony_ci break; 916562306a36Sopenharmony_ci case SIOCSMIIREG: 916662306a36Sopenharmony_ci default: 916762306a36Sopenharmony_ci return -EOPNOTSUPP; 916862306a36Sopenharmony_ci } 916962306a36Sopenharmony_ci return 0; 917062306a36Sopenharmony_ci} 917162306a36Sopenharmony_ci 917262306a36Sopenharmony_ci/** 917362306a36Sopenharmony_ci * igb_ioctl - 917462306a36Sopenharmony_ci * @netdev: pointer to netdev struct 917562306a36Sopenharmony_ci * @ifr: interface structure 917662306a36Sopenharmony_ci * @cmd: ioctl command to execute 917762306a36Sopenharmony_ci **/ 917862306a36Sopenharmony_cistatic int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) 917962306a36Sopenharmony_ci{ 918062306a36Sopenharmony_ci switch (cmd) { 918162306a36Sopenharmony_ci case SIOCGMIIPHY: 918262306a36Sopenharmony_ci case SIOCGMIIREG: 918362306a36Sopenharmony_ci case SIOCSMIIREG: 918462306a36Sopenharmony_ci return igb_mii_ioctl(netdev, ifr, cmd); 918562306a36Sopenharmony_ci case SIOCGHWTSTAMP: 918662306a36Sopenharmony_ci return igb_ptp_get_ts_config(netdev, ifr); 918762306a36Sopenharmony_ci case SIOCSHWTSTAMP: 918862306a36Sopenharmony_ci return igb_ptp_set_ts_config(netdev, ifr); 918962306a36Sopenharmony_ci default: 919062306a36Sopenharmony_ci return -EOPNOTSUPP; 919162306a36Sopenharmony_ci } 919262306a36Sopenharmony_ci} 919362306a36Sopenharmony_ci 919462306a36Sopenharmony_civoid igb_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value) 919562306a36Sopenharmony_ci{ 919662306a36Sopenharmony_ci struct igb_adapter *adapter = hw->back; 919762306a36Sopenharmony_ci 919862306a36Sopenharmony_ci pci_read_config_word(adapter->pdev, reg, value); 919962306a36Sopenharmony_ci} 920062306a36Sopenharmony_ci 920162306a36Sopenharmony_civoid igb_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value) 920262306a36Sopenharmony_ci{ 920362306a36Sopenharmony_ci struct igb_adapter *adapter = hw->back; 920462306a36Sopenharmony_ci 920562306a36Sopenharmony_ci pci_write_config_word(adapter->pdev, reg, *value); 920662306a36Sopenharmony_ci} 920762306a36Sopenharmony_ci 920862306a36Sopenharmony_cis32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) 920962306a36Sopenharmony_ci{ 921062306a36Sopenharmony_ci struct igb_adapter *adapter = hw->back; 921162306a36Sopenharmony_ci 921262306a36Sopenharmony_ci if (pcie_capability_read_word(adapter->pdev, reg, value)) 921362306a36Sopenharmony_ci return -E1000_ERR_CONFIG; 921462306a36Sopenharmony_ci 921562306a36Sopenharmony_ci return 0; 921662306a36Sopenharmony_ci} 921762306a36Sopenharmony_ci 921862306a36Sopenharmony_cis32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) 921962306a36Sopenharmony_ci{ 922062306a36Sopenharmony_ci struct igb_adapter *adapter = hw->back; 922162306a36Sopenharmony_ci 922262306a36Sopenharmony_ci if (pcie_capability_write_word(adapter->pdev, reg, *value)) 922362306a36Sopenharmony_ci return -E1000_ERR_CONFIG; 922462306a36Sopenharmony_ci 922562306a36Sopenharmony_ci return 0; 922662306a36Sopenharmony_ci} 922762306a36Sopenharmony_ci 922862306a36Sopenharmony_cistatic void igb_vlan_mode(struct net_device *netdev, netdev_features_t features) 922962306a36Sopenharmony_ci{ 923062306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 923162306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 923262306a36Sopenharmony_ci u32 ctrl, rctl; 923362306a36Sopenharmony_ci bool enable = !!(features & NETIF_F_HW_VLAN_CTAG_RX); 923462306a36Sopenharmony_ci 923562306a36Sopenharmony_ci if (enable) { 923662306a36Sopenharmony_ci /* enable VLAN tag insert/strip */ 923762306a36Sopenharmony_ci ctrl = rd32(E1000_CTRL); 923862306a36Sopenharmony_ci ctrl |= E1000_CTRL_VME; 923962306a36Sopenharmony_ci wr32(E1000_CTRL, ctrl); 924062306a36Sopenharmony_ci 924162306a36Sopenharmony_ci /* Disable CFI check */ 924262306a36Sopenharmony_ci rctl = rd32(E1000_RCTL); 924362306a36Sopenharmony_ci rctl &= ~E1000_RCTL_CFIEN; 924462306a36Sopenharmony_ci wr32(E1000_RCTL, rctl); 924562306a36Sopenharmony_ci } else { 924662306a36Sopenharmony_ci /* disable VLAN tag insert/strip */ 924762306a36Sopenharmony_ci ctrl = rd32(E1000_CTRL); 924862306a36Sopenharmony_ci ctrl &= ~E1000_CTRL_VME; 924962306a36Sopenharmony_ci wr32(E1000_CTRL, ctrl); 925062306a36Sopenharmony_ci } 925162306a36Sopenharmony_ci 925262306a36Sopenharmony_ci igb_set_vf_vlan_strip(adapter, adapter->vfs_allocated_count, enable); 925362306a36Sopenharmony_ci} 925462306a36Sopenharmony_ci 925562306a36Sopenharmony_cistatic int igb_vlan_rx_add_vid(struct net_device *netdev, 925662306a36Sopenharmony_ci __be16 proto, u16 vid) 925762306a36Sopenharmony_ci{ 925862306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 925962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 926062306a36Sopenharmony_ci int pf_id = adapter->vfs_allocated_count; 926162306a36Sopenharmony_ci 926262306a36Sopenharmony_ci /* add the filter since PF can receive vlans w/o entry in vlvf */ 926362306a36Sopenharmony_ci if (!vid || !(adapter->flags & IGB_FLAG_VLAN_PROMISC)) 926462306a36Sopenharmony_ci igb_vfta_set(hw, vid, pf_id, true, !!vid); 926562306a36Sopenharmony_ci 926662306a36Sopenharmony_ci set_bit(vid, adapter->active_vlans); 926762306a36Sopenharmony_ci 926862306a36Sopenharmony_ci return 0; 926962306a36Sopenharmony_ci} 927062306a36Sopenharmony_ci 927162306a36Sopenharmony_cistatic int igb_vlan_rx_kill_vid(struct net_device *netdev, 927262306a36Sopenharmony_ci __be16 proto, u16 vid) 927362306a36Sopenharmony_ci{ 927462306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 927562306a36Sopenharmony_ci int pf_id = adapter->vfs_allocated_count; 927662306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 927762306a36Sopenharmony_ci 927862306a36Sopenharmony_ci /* remove VID from filter table */ 927962306a36Sopenharmony_ci if (vid && !(adapter->flags & IGB_FLAG_VLAN_PROMISC)) 928062306a36Sopenharmony_ci igb_vfta_set(hw, vid, pf_id, false, true); 928162306a36Sopenharmony_ci 928262306a36Sopenharmony_ci clear_bit(vid, adapter->active_vlans); 928362306a36Sopenharmony_ci 928462306a36Sopenharmony_ci return 0; 928562306a36Sopenharmony_ci} 928662306a36Sopenharmony_ci 928762306a36Sopenharmony_cistatic void igb_restore_vlan(struct igb_adapter *adapter) 928862306a36Sopenharmony_ci{ 928962306a36Sopenharmony_ci u16 vid = 1; 929062306a36Sopenharmony_ci 929162306a36Sopenharmony_ci igb_vlan_mode(adapter->netdev, adapter->netdev->features); 929262306a36Sopenharmony_ci igb_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), 0); 929362306a36Sopenharmony_ci 929462306a36Sopenharmony_ci for_each_set_bit_from(vid, adapter->active_vlans, VLAN_N_VID) 929562306a36Sopenharmony_ci igb_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid); 929662306a36Sopenharmony_ci} 929762306a36Sopenharmony_ci 929862306a36Sopenharmony_ciint igb_set_spd_dplx(struct igb_adapter *adapter, u32 spd, u8 dplx) 929962306a36Sopenharmony_ci{ 930062306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 930162306a36Sopenharmony_ci struct e1000_mac_info *mac = &adapter->hw.mac; 930262306a36Sopenharmony_ci 930362306a36Sopenharmony_ci mac->autoneg = 0; 930462306a36Sopenharmony_ci 930562306a36Sopenharmony_ci /* Make sure dplx is at most 1 bit and lsb of speed is not set 930662306a36Sopenharmony_ci * for the switch() below to work 930762306a36Sopenharmony_ci */ 930862306a36Sopenharmony_ci if ((spd & 1) || (dplx & ~1)) 930962306a36Sopenharmony_ci goto err_inval; 931062306a36Sopenharmony_ci 931162306a36Sopenharmony_ci /* Fiber NIC's only allow 1000 gbps Full duplex 931262306a36Sopenharmony_ci * and 100Mbps Full duplex for 100baseFx sfp 931362306a36Sopenharmony_ci */ 931462306a36Sopenharmony_ci if (adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { 931562306a36Sopenharmony_ci switch (spd + dplx) { 931662306a36Sopenharmony_ci case SPEED_10 + DUPLEX_HALF: 931762306a36Sopenharmony_ci case SPEED_10 + DUPLEX_FULL: 931862306a36Sopenharmony_ci case SPEED_100 + DUPLEX_HALF: 931962306a36Sopenharmony_ci goto err_inval; 932062306a36Sopenharmony_ci default: 932162306a36Sopenharmony_ci break; 932262306a36Sopenharmony_ci } 932362306a36Sopenharmony_ci } 932462306a36Sopenharmony_ci 932562306a36Sopenharmony_ci switch (spd + dplx) { 932662306a36Sopenharmony_ci case SPEED_10 + DUPLEX_HALF: 932762306a36Sopenharmony_ci mac->forced_speed_duplex = ADVERTISE_10_HALF; 932862306a36Sopenharmony_ci break; 932962306a36Sopenharmony_ci case SPEED_10 + DUPLEX_FULL: 933062306a36Sopenharmony_ci mac->forced_speed_duplex = ADVERTISE_10_FULL; 933162306a36Sopenharmony_ci break; 933262306a36Sopenharmony_ci case SPEED_100 + DUPLEX_HALF: 933362306a36Sopenharmony_ci mac->forced_speed_duplex = ADVERTISE_100_HALF; 933462306a36Sopenharmony_ci break; 933562306a36Sopenharmony_ci case SPEED_100 + DUPLEX_FULL: 933662306a36Sopenharmony_ci mac->forced_speed_duplex = ADVERTISE_100_FULL; 933762306a36Sopenharmony_ci break; 933862306a36Sopenharmony_ci case SPEED_1000 + DUPLEX_FULL: 933962306a36Sopenharmony_ci mac->autoneg = 1; 934062306a36Sopenharmony_ci adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; 934162306a36Sopenharmony_ci break; 934262306a36Sopenharmony_ci case SPEED_1000 + DUPLEX_HALF: /* not supported */ 934362306a36Sopenharmony_ci default: 934462306a36Sopenharmony_ci goto err_inval; 934562306a36Sopenharmony_ci } 934662306a36Sopenharmony_ci 934762306a36Sopenharmony_ci /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ 934862306a36Sopenharmony_ci adapter->hw.phy.mdix = AUTO_ALL_MODES; 934962306a36Sopenharmony_ci 935062306a36Sopenharmony_ci return 0; 935162306a36Sopenharmony_ci 935262306a36Sopenharmony_cierr_inval: 935362306a36Sopenharmony_ci dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n"); 935462306a36Sopenharmony_ci return -EINVAL; 935562306a36Sopenharmony_ci} 935662306a36Sopenharmony_ci 935762306a36Sopenharmony_cistatic int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, 935862306a36Sopenharmony_ci bool runtime) 935962306a36Sopenharmony_ci{ 936062306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 936162306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 936262306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 936362306a36Sopenharmony_ci u32 ctrl, rctl, status; 936462306a36Sopenharmony_ci u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol; 936562306a36Sopenharmony_ci bool wake; 936662306a36Sopenharmony_ci 936762306a36Sopenharmony_ci rtnl_lock(); 936862306a36Sopenharmony_ci netif_device_detach(netdev); 936962306a36Sopenharmony_ci 937062306a36Sopenharmony_ci if (netif_running(netdev)) 937162306a36Sopenharmony_ci __igb_close(netdev, true); 937262306a36Sopenharmony_ci 937362306a36Sopenharmony_ci igb_ptp_suspend(adapter); 937462306a36Sopenharmony_ci 937562306a36Sopenharmony_ci igb_clear_interrupt_scheme(adapter); 937662306a36Sopenharmony_ci rtnl_unlock(); 937762306a36Sopenharmony_ci 937862306a36Sopenharmony_ci status = rd32(E1000_STATUS); 937962306a36Sopenharmony_ci if (status & E1000_STATUS_LU) 938062306a36Sopenharmony_ci wufc &= ~E1000_WUFC_LNKC; 938162306a36Sopenharmony_ci 938262306a36Sopenharmony_ci if (wufc) { 938362306a36Sopenharmony_ci igb_setup_rctl(adapter); 938462306a36Sopenharmony_ci igb_set_rx_mode(netdev); 938562306a36Sopenharmony_ci 938662306a36Sopenharmony_ci /* turn on all-multi mode if wake on multicast is enabled */ 938762306a36Sopenharmony_ci if (wufc & E1000_WUFC_MC) { 938862306a36Sopenharmony_ci rctl = rd32(E1000_RCTL); 938962306a36Sopenharmony_ci rctl |= E1000_RCTL_MPE; 939062306a36Sopenharmony_ci wr32(E1000_RCTL, rctl); 939162306a36Sopenharmony_ci } 939262306a36Sopenharmony_ci 939362306a36Sopenharmony_ci ctrl = rd32(E1000_CTRL); 939462306a36Sopenharmony_ci ctrl |= E1000_CTRL_ADVD3WUC; 939562306a36Sopenharmony_ci wr32(E1000_CTRL, ctrl); 939662306a36Sopenharmony_ci 939762306a36Sopenharmony_ci /* Allow time for pending master requests to run */ 939862306a36Sopenharmony_ci igb_disable_pcie_master(hw); 939962306a36Sopenharmony_ci 940062306a36Sopenharmony_ci wr32(E1000_WUC, E1000_WUC_PME_EN); 940162306a36Sopenharmony_ci wr32(E1000_WUFC, wufc); 940262306a36Sopenharmony_ci } else { 940362306a36Sopenharmony_ci wr32(E1000_WUC, 0); 940462306a36Sopenharmony_ci wr32(E1000_WUFC, 0); 940562306a36Sopenharmony_ci } 940662306a36Sopenharmony_ci 940762306a36Sopenharmony_ci wake = wufc || adapter->en_mng_pt; 940862306a36Sopenharmony_ci if (!wake) 940962306a36Sopenharmony_ci igb_power_down_link(adapter); 941062306a36Sopenharmony_ci else 941162306a36Sopenharmony_ci igb_power_up_link(adapter); 941262306a36Sopenharmony_ci 941362306a36Sopenharmony_ci if (enable_wake) 941462306a36Sopenharmony_ci *enable_wake = wake; 941562306a36Sopenharmony_ci 941662306a36Sopenharmony_ci /* Release control of h/w to f/w. If f/w is AMT enabled, this 941762306a36Sopenharmony_ci * would have already happened in close and is redundant. 941862306a36Sopenharmony_ci */ 941962306a36Sopenharmony_ci igb_release_hw_control(adapter); 942062306a36Sopenharmony_ci 942162306a36Sopenharmony_ci pci_disable_device(pdev); 942262306a36Sopenharmony_ci 942362306a36Sopenharmony_ci return 0; 942462306a36Sopenharmony_ci} 942562306a36Sopenharmony_ci 942662306a36Sopenharmony_cistatic void igb_deliver_wake_packet(struct net_device *netdev) 942762306a36Sopenharmony_ci{ 942862306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 942962306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 943062306a36Sopenharmony_ci struct sk_buff *skb; 943162306a36Sopenharmony_ci u32 wupl; 943262306a36Sopenharmony_ci 943362306a36Sopenharmony_ci wupl = rd32(E1000_WUPL) & E1000_WUPL_MASK; 943462306a36Sopenharmony_ci 943562306a36Sopenharmony_ci /* WUPM stores only the first 128 bytes of the wake packet. 943662306a36Sopenharmony_ci * Read the packet only if we have the whole thing. 943762306a36Sopenharmony_ci */ 943862306a36Sopenharmony_ci if ((wupl == 0) || (wupl > E1000_WUPM_BYTES)) 943962306a36Sopenharmony_ci return; 944062306a36Sopenharmony_ci 944162306a36Sopenharmony_ci skb = netdev_alloc_skb_ip_align(netdev, E1000_WUPM_BYTES); 944262306a36Sopenharmony_ci if (!skb) 944362306a36Sopenharmony_ci return; 944462306a36Sopenharmony_ci 944562306a36Sopenharmony_ci skb_put(skb, wupl); 944662306a36Sopenharmony_ci 944762306a36Sopenharmony_ci /* Ensure reads are 32-bit aligned */ 944862306a36Sopenharmony_ci wupl = roundup(wupl, 4); 944962306a36Sopenharmony_ci 945062306a36Sopenharmony_ci memcpy_fromio(skb->data, hw->hw_addr + E1000_WUPM_REG(0), wupl); 945162306a36Sopenharmony_ci 945262306a36Sopenharmony_ci skb->protocol = eth_type_trans(skb, netdev); 945362306a36Sopenharmony_ci netif_rx(skb); 945462306a36Sopenharmony_ci} 945562306a36Sopenharmony_ci 945662306a36Sopenharmony_cistatic int __maybe_unused igb_suspend(struct device *dev) 945762306a36Sopenharmony_ci{ 945862306a36Sopenharmony_ci return __igb_shutdown(to_pci_dev(dev), NULL, 0); 945962306a36Sopenharmony_ci} 946062306a36Sopenharmony_ci 946162306a36Sopenharmony_cistatic int __maybe_unused __igb_resume(struct device *dev, bool rpm) 946262306a36Sopenharmony_ci{ 946362306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(dev); 946462306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 946562306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 946662306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 946762306a36Sopenharmony_ci u32 err, val; 946862306a36Sopenharmony_ci 946962306a36Sopenharmony_ci pci_set_power_state(pdev, PCI_D0); 947062306a36Sopenharmony_ci pci_restore_state(pdev); 947162306a36Sopenharmony_ci pci_save_state(pdev); 947262306a36Sopenharmony_ci 947362306a36Sopenharmony_ci if (!pci_device_is_present(pdev)) 947462306a36Sopenharmony_ci return -ENODEV; 947562306a36Sopenharmony_ci err = pci_enable_device_mem(pdev); 947662306a36Sopenharmony_ci if (err) { 947762306a36Sopenharmony_ci dev_err(&pdev->dev, 947862306a36Sopenharmony_ci "igb: Cannot enable PCI device from suspend\n"); 947962306a36Sopenharmony_ci return err; 948062306a36Sopenharmony_ci } 948162306a36Sopenharmony_ci pci_set_master(pdev); 948262306a36Sopenharmony_ci 948362306a36Sopenharmony_ci pci_enable_wake(pdev, PCI_D3hot, 0); 948462306a36Sopenharmony_ci pci_enable_wake(pdev, PCI_D3cold, 0); 948562306a36Sopenharmony_ci 948662306a36Sopenharmony_ci if (igb_init_interrupt_scheme(adapter, true)) { 948762306a36Sopenharmony_ci dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); 948862306a36Sopenharmony_ci return -ENOMEM; 948962306a36Sopenharmony_ci } 949062306a36Sopenharmony_ci 949162306a36Sopenharmony_ci igb_reset(adapter); 949262306a36Sopenharmony_ci 949362306a36Sopenharmony_ci /* let the f/w know that the h/w is now under the control of the 949462306a36Sopenharmony_ci * driver. 949562306a36Sopenharmony_ci */ 949662306a36Sopenharmony_ci igb_get_hw_control(adapter); 949762306a36Sopenharmony_ci 949862306a36Sopenharmony_ci val = rd32(E1000_WUS); 949962306a36Sopenharmony_ci if (val & WAKE_PKT_WUS) 950062306a36Sopenharmony_ci igb_deliver_wake_packet(netdev); 950162306a36Sopenharmony_ci 950262306a36Sopenharmony_ci wr32(E1000_WUS, ~0); 950362306a36Sopenharmony_ci 950462306a36Sopenharmony_ci if (!rpm) 950562306a36Sopenharmony_ci rtnl_lock(); 950662306a36Sopenharmony_ci if (!err && netif_running(netdev)) 950762306a36Sopenharmony_ci err = __igb_open(netdev, true); 950862306a36Sopenharmony_ci 950962306a36Sopenharmony_ci if (!err) 951062306a36Sopenharmony_ci netif_device_attach(netdev); 951162306a36Sopenharmony_ci if (!rpm) 951262306a36Sopenharmony_ci rtnl_unlock(); 951362306a36Sopenharmony_ci 951462306a36Sopenharmony_ci return err; 951562306a36Sopenharmony_ci} 951662306a36Sopenharmony_ci 951762306a36Sopenharmony_cistatic int __maybe_unused igb_resume(struct device *dev) 951862306a36Sopenharmony_ci{ 951962306a36Sopenharmony_ci return __igb_resume(dev, false); 952062306a36Sopenharmony_ci} 952162306a36Sopenharmony_ci 952262306a36Sopenharmony_cistatic int __maybe_unused igb_runtime_idle(struct device *dev) 952362306a36Sopenharmony_ci{ 952462306a36Sopenharmony_ci struct net_device *netdev = dev_get_drvdata(dev); 952562306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 952662306a36Sopenharmony_ci 952762306a36Sopenharmony_ci if (!igb_has_link(adapter)) 952862306a36Sopenharmony_ci pm_schedule_suspend(dev, MSEC_PER_SEC * 5); 952962306a36Sopenharmony_ci 953062306a36Sopenharmony_ci return -EBUSY; 953162306a36Sopenharmony_ci} 953262306a36Sopenharmony_ci 953362306a36Sopenharmony_cistatic int __maybe_unused igb_runtime_suspend(struct device *dev) 953462306a36Sopenharmony_ci{ 953562306a36Sopenharmony_ci return __igb_shutdown(to_pci_dev(dev), NULL, 1); 953662306a36Sopenharmony_ci} 953762306a36Sopenharmony_ci 953862306a36Sopenharmony_cistatic int __maybe_unused igb_runtime_resume(struct device *dev) 953962306a36Sopenharmony_ci{ 954062306a36Sopenharmony_ci return __igb_resume(dev, true); 954162306a36Sopenharmony_ci} 954262306a36Sopenharmony_ci 954362306a36Sopenharmony_cistatic void igb_shutdown(struct pci_dev *pdev) 954462306a36Sopenharmony_ci{ 954562306a36Sopenharmony_ci bool wake; 954662306a36Sopenharmony_ci 954762306a36Sopenharmony_ci __igb_shutdown(pdev, &wake, 0); 954862306a36Sopenharmony_ci 954962306a36Sopenharmony_ci if (system_state == SYSTEM_POWER_OFF) { 955062306a36Sopenharmony_ci pci_wake_from_d3(pdev, wake); 955162306a36Sopenharmony_ci pci_set_power_state(pdev, PCI_D3hot); 955262306a36Sopenharmony_ci } 955362306a36Sopenharmony_ci} 955462306a36Sopenharmony_ci 955562306a36Sopenharmony_cistatic int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs) 955662306a36Sopenharmony_ci{ 955762306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 955862306a36Sopenharmony_ci int err; 955962306a36Sopenharmony_ci 956062306a36Sopenharmony_ci if (num_vfs == 0) { 956162306a36Sopenharmony_ci return igb_disable_sriov(dev, true); 956262306a36Sopenharmony_ci } else { 956362306a36Sopenharmony_ci err = igb_enable_sriov(dev, num_vfs, true); 956462306a36Sopenharmony_ci return err ? err : num_vfs; 956562306a36Sopenharmony_ci } 956662306a36Sopenharmony_ci#endif 956762306a36Sopenharmony_ci return 0; 956862306a36Sopenharmony_ci} 956962306a36Sopenharmony_ci 957062306a36Sopenharmony_ci/** 957162306a36Sopenharmony_ci * igb_io_error_detected - called when PCI error is detected 957262306a36Sopenharmony_ci * @pdev: Pointer to PCI device 957362306a36Sopenharmony_ci * @state: The current pci connection state 957462306a36Sopenharmony_ci * 957562306a36Sopenharmony_ci * This function is called after a PCI bus error affecting 957662306a36Sopenharmony_ci * this device has been detected. 957762306a36Sopenharmony_ci **/ 957862306a36Sopenharmony_cistatic pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev, 957962306a36Sopenharmony_ci pci_channel_state_t state) 958062306a36Sopenharmony_ci{ 958162306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 958262306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 958362306a36Sopenharmony_ci 958462306a36Sopenharmony_ci if (state == pci_channel_io_normal) { 958562306a36Sopenharmony_ci dev_warn(&pdev->dev, "Non-correctable non-fatal error reported.\n"); 958662306a36Sopenharmony_ci return PCI_ERS_RESULT_CAN_RECOVER; 958762306a36Sopenharmony_ci } 958862306a36Sopenharmony_ci 958962306a36Sopenharmony_ci netif_device_detach(netdev); 959062306a36Sopenharmony_ci 959162306a36Sopenharmony_ci if (state == pci_channel_io_perm_failure) 959262306a36Sopenharmony_ci return PCI_ERS_RESULT_DISCONNECT; 959362306a36Sopenharmony_ci 959462306a36Sopenharmony_ci if (netif_running(netdev)) 959562306a36Sopenharmony_ci igb_down(adapter); 959662306a36Sopenharmony_ci pci_disable_device(pdev); 959762306a36Sopenharmony_ci 959862306a36Sopenharmony_ci /* Request a slot reset. */ 959962306a36Sopenharmony_ci return PCI_ERS_RESULT_NEED_RESET; 960062306a36Sopenharmony_ci} 960162306a36Sopenharmony_ci 960262306a36Sopenharmony_ci/** 960362306a36Sopenharmony_ci * igb_io_slot_reset - called after the pci bus has been reset. 960462306a36Sopenharmony_ci * @pdev: Pointer to PCI device 960562306a36Sopenharmony_ci * 960662306a36Sopenharmony_ci * Restart the card from scratch, as if from a cold-boot. Implementation 960762306a36Sopenharmony_ci * resembles the first-half of the __igb_resume routine. 960862306a36Sopenharmony_ci **/ 960962306a36Sopenharmony_cistatic pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) 961062306a36Sopenharmony_ci{ 961162306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 961262306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 961362306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 961462306a36Sopenharmony_ci pci_ers_result_t result; 961562306a36Sopenharmony_ci 961662306a36Sopenharmony_ci if (pci_enable_device_mem(pdev)) { 961762306a36Sopenharmony_ci dev_err(&pdev->dev, 961862306a36Sopenharmony_ci "Cannot re-enable PCI device after reset.\n"); 961962306a36Sopenharmony_ci result = PCI_ERS_RESULT_DISCONNECT; 962062306a36Sopenharmony_ci } else { 962162306a36Sopenharmony_ci pci_set_master(pdev); 962262306a36Sopenharmony_ci pci_restore_state(pdev); 962362306a36Sopenharmony_ci pci_save_state(pdev); 962462306a36Sopenharmony_ci 962562306a36Sopenharmony_ci pci_enable_wake(pdev, PCI_D3hot, 0); 962662306a36Sopenharmony_ci pci_enable_wake(pdev, PCI_D3cold, 0); 962762306a36Sopenharmony_ci 962862306a36Sopenharmony_ci /* In case of PCI error, adapter lose its HW address 962962306a36Sopenharmony_ci * so we should re-assign it here. 963062306a36Sopenharmony_ci */ 963162306a36Sopenharmony_ci hw->hw_addr = adapter->io_addr; 963262306a36Sopenharmony_ci 963362306a36Sopenharmony_ci igb_reset(adapter); 963462306a36Sopenharmony_ci wr32(E1000_WUS, ~0); 963562306a36Sopenharmony_ci result = PCI_ERS_RESULT_RECOVERED; 963662306a36Sopenharmony_ci } 963762306a36Sopenharmony_ci 963862306a36Sopenharmony_ci return result; 963962306a36Sopenharmony_ci} 964062306a36Sopenharmony_ci 964162306a36Sopenharmony_ci/** 964262306a36Sopenharmony_ci * igb_io_resume - called when traffic can start flowing again. 964362306a36Sopenharmony_ci * @pdev: Pointer to PCI device 964462306a36Sopenharmony_ci * 964562306a36Sopenharmony_ci * This callback is called when the error recovery driver tells us that 964662306a36Sopenharmony_ci * its OK to resume normal operation. Implementation resembles the 964762306a36Sopenharmony_ci * second-half of the __igb_resume routine. 964862306a36Sopenharmony_ci */ 964962306a36Sopenharmony_cistatic void igb_io_resume(struct pci_dev *pdev) 965062306a36Sopenharmony_ci{ 965162306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 965262306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 965362306a36Sopenharmony_ci 965462306a36Sopenharmony_ci if (netif_running(netdev)) { 965562306a36Sopenharmony_ci if (igb_up(adapter)) { 965662306a36Sopenharmony_ci dev_err(&pdev->dev, "igb_up failed after reset\n"); 965762306a36Sopenharmony_ci return; 965862306a36Sopenharmony_ci } 965962306a36Sopenharmony_ci } 966062306a36Sopenharmony_ci 966162306a36Sopenharmony_ci netif_device_attach(netdev); 966262306a36Sopenharmony_ci 966362306a36Sopenharmony_ci /* let the f/w know that the h/w is now under the control of the 966462306a36Sopenharmony_ci * driver. 966562306a36Sopenharmony_ci */ 966662306a36Sopenharmony_ci igb_get_hw_control(adapter); 966762306a36Sopenharmony_ci} 966862306a36Sopenharmony_ci 966962306a36Sopenharmony_ci/** 967062306a36Sopenharmony_ci * igb_rar_set_index - Sync RAL[index] and RAH[index] registers with MAC table 967162306a36Sopenharmony_ci * @adapter: Pointer to adapter structure 967262306a36Sopenharmony_ci * @index: Index of the RAR entry which need to be synced with MAC table 967362306a36Sopenharmony_ci **/ 967462306a36Sopenharmony_cistatic void igb_rar_set_index(struct igb_adapter *adapter, u32 index) 967562306a36Sopenharmony_ci{ 967662306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 967762306a36Sopenharmony_ci u32 rar_low, rar_high; 967862306a36Sopenharmony_ci u8 *addr = adapter->mac_table[index].addr; 967962306a36Sopenharmony_ci 968062306a36Sopenharmony_ci /* HW expects these to be in network order when they are plugged 968162306a36Sopenharmony_ci * into the registers which are little endian. In order to guarantee 968262306a36Sopenharmony_ci * that ordering we need to do an leXX_to_cpup here in order to be 968362306a36Sopenharmony_ci * ready for the byteswap that occurs with writel 968462306a36Sopenharmony_ci */ 968562306a36Sopenharmony_ci rar_low = le32_to_cpup((__le32 *)(addr)); 968662306a36Sopenharmony_ci rar_high = le16_to_cpup((__le16 *)(addr + 4)); 968762306a36Sopenharmony_ci 968862306a36Sopenharmony_ci /* Indicate to hardware the Address is Valid. */ 968962306a36Sopenharmony_ci if (adapter->mac_table[index].state & IGB_MAC_STATE_IN_USE) { 969062306a36Sopenharmony_ci if (is_valid_ether_addr(addr)) 969162306a36Sopenharmony_ci rar_high |= E1000_RAH_AV; 969262306a36Sopenharmony_ci 969362306a36Sopenharmony_ci if (adapter->mac_table[index].state & IGB_MAC_STATE_SRC_ADDR) 969462306a36Sopenharmony_ci rar_high |= E1000_RAH_ASEL_SRC_ADDR; 969562306a36Sopenharmony_ci 969662306a36Sopenharmony_ci switch (hw->mac.type) { 969762306a36Sopenharmony_ci case e1000_82575: 969862306a36Sopenharmony_ci case e1000_i210: 969962306a36Sopenharmony_ci if (adapter->mac_table[index].state & 970062306a36Sopenharmony_ci IGB_MAC_STATE_QUEUE_STEERING) 970162306a36Sopenharmony_ci rar_high |= E1000_RAH_QSEL_ENABLE; 970262306a36Sopenharmony_ci 970362306a36Sopenharmony_ci rar_high |= E1000_RAH_POOL_1 * 970462306a36Sopenharmony_ci adapter->mac_table[index].queue; 970562306a36Sopenharmony_ci break; 970662306a36Sopenharmony_ci default: 970762306a36Sopenharmony_ci rar_high |= E1000_RAH_POOL_1 << 970862306a36Sopenharmony_ci adapter->mac_table[index].queue; 970962306a36Sopenharmony_ci break; 971062306a36Sopenharmony_ci } 971162306a36Sopenharmony_ci } 971262306a36Sopenharmony_ci 971362306a36Sopenharmony_ci wr32(E1000_RAL(index), rar_low); 971462306a36Sopenharmony_ci wrfl(); 971562306a36Sopenharmony_ci wr32(E1000_RAH(index), rar_high); 971662306a36Sopenharmony_ci wrfl(); 971762306a36Sopenharmony_ci} 971862306a36Sopenharmony_ci 971962306a36Sopenharmony_cistatic int igb_set_vf_mac(struct igb_adapter *adapter, 972062306a36Sopenharmony_ci int vf, unsigned char *mac_addr) 972162306a36Sopenharmony_ci{ 972262306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 972362306a36Sopenharmony_ci /* VF MAC addresses start at end of receive addresses and moves 972462306a36Sopenharmony_ci * towards the first, as a result a collision should not be possible 972562306a36Sopenharmony_ci */ 972662306a36Sopenharmony_ci int rar_entry = hw->mac.rar_entry_count - (vf + 1); 972762306a36Sopenharmony_ci unsigned char *vf_mac_addr = adapter->vf_data[vf].vf_mac_addresses; 972862306a36Sopenharmony_ci 972962306a36Sopenharmony_ci ether_addr_copy(vf_mac_addr, mac_addr); 973062306a36Sopenharmony_ci ether_addr_copy(adapter->mac_table[rar_entry].addr, mac_addr); 973162306a36Sopenharmony_ci adapter->mac_table[rar_entry].queue = vf; 973262306a36Sopenharmony_ci adapter->mac_table[rar_entry].state |= IGB_MAC_STATE_IN_USE; 973362306a36Sopenharmony_ci igb_rar_set_index(adapter, rar_entry); 973462306a36Sopenharmony_ci 973562306a36Sopenharmony_ci return 0; 973662306a36Sopenharmony_ci} 973762306a36Sopenharmony_ci 973862306a36Sopenharmony_cistatic int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) 973962306a36Sopenharmony_ci{ 974062306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 974162306a36Sopenharmony_ci 974262306a36Sopenharmony_ci if (vf >= adapter->vfs_allocated_count) 974362306a36Sopenharmony_ci return -EINVAL; 974462306a36Sopenharmony_ci 974562306a36Sopenharmony_ci /* Setting the VF MAC to 0 reverts the IGB_VF_FLAG_PF_SET_MAC 974662306a36Sopenharmony_ci * flag and allows to overwrite the MAC via VF netdev. This 974762306a36Sopenharmony_ci * is necessary to allow libvirt a way to restore the original 974862306a36Sopenharmony_ci * MAC after unbinding vfio-pci and reloading igbvf after shutting 974962306a36Sopenharmony_ci * down a VM. 975062306a36Sopenharmony_ci */ 975162306a36Sopenharmony_ci if (is_zero_ether_addr(mac)) { 975262306a36Sopenharmony_ci adapter->vf_data[vf].flags &= ~IGB_VF_FLAG_PF_SET_MAC; 975362306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, 975462306a36Sopenharmony_ci "remove administratively set MAC on VF %d\n", 975562306a36Sopenharmony_ci vf); 975662306a36Sopenharmony_ci } else if (is_valid_ether_addr(mac)) { 975762306a36Sopenharmony_ci adapter->vf_data[vf].flags |= IGB_VF_FLAG_PF_SET_MAC; 975862306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n", 975962306a36Sopenharmony_ci mac, vf); 976062306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, 976162306a36Sopenharmony_ci "Reload the VF driver to make this change effective."); 976262306a36Sopenharmony_ci /* Generate additional warning if PF is down */ 976362306a36Sopenharmony_ci if (test_bit(__IGB_DOWN, &adapter->state)) { 976462306a36Sopenharmony_ci dev_warn(&adapter->pdev->dev, 976562306a36Sopenharmony_ci "The VF MAC address has been set, but the PF device is not up.\n"); 976662306a36Sopenharmony_ci dev_warn(&adapter->pdev->dev, 976762306a36Sopenharmony_ci "Bring the PF device up before attempting to use the VF device.\n"); 976862306a36Sopenharmony_ci } 976962306a36Sopenharmony_ci } else { 977062306a36Sopenharmony_ci return -EINVAL; 977162306a36Sopenharmony_ci } 977262306a36Sopenharmony_ci return igb_set_vf_mac(adapter, vf, mac); 977362306a36Sopenharmony_ci} 977462306a36Sopenharmony_ci 977562306a36Sopenharmony_cistatic int igb_link_mbps(int internal_link_speed) 977662306a36Sopenharmony_ci{ 977762306a36Sopenharmony_ci switch (internal_link_speed) { 977862306a36Sopenharmony_ci case SPEED_100: 977962306a36Sopenharmony_ci return 100; 978062306a36Sopenharmony_ci case SPEED_1000: 978162306a36Sopenharmony_ci return 1000; 978262306a36Sopenharmony_ci default: 978362306a36Sopenharmony_ci return 0; 978462306a36Sopenharmony_ci } 978562306a36Sopenharmony_ci} 978662306a36Sopenharmony_ci 978762306a36Sopenharmony_cistatic void igb_set_vf_rate_limit(struct e1000_hw *hw, int vf, int tx_rate, 978862306a36Sopenharmony_ci int link_speed) 978962306a36Sopenharmony_ci{ 979062306a36Sopenharmony_ci int rf_dec, rf_int; 979162306a36Sopenharmony_ci u32 bcnrc_val; 979262306a36Sopenharmony_ci 979362306a36Sopenharmony_ci if (tx_rate != 0) { 979462306a36Sopenharmony_ci /* Calculate the rate factor values to set */ 979562306a36Sopenharmony_ci rf_int = link_speed / tx_rate; 979662306a36Sopenharmony_ci rf_dec = (link_speed - (rf_int * tx_rate)); 979762306a36Sopenharmony_ci rf_dec = (rf_dec * BIT(E1000_RTTBCNRC_RF_INT_SHIFT)) / 979862306a36Sopenharmony_ci tx_rate; 979962306a36Sopenharmony_ci 980062306a36Sopenharmony_ci bcnrc_val = E1000_RTTBCNRC_RS_ENA; 980162306a36Sopenharmony_ci bcnrc_val |= ((rf_int << E1000_RTTBCNRC_RF_INT_SHIFT) & 980262306a36Sopenharmony_ci E1000_RTTBCNRC_RF_INT_MASK); 980362306a36Sopenharmony_ci bcnrc_val |= (rf_dec & E1000_RTTBCNRC_RF_DEC_MASK); 980462306a36Sopenharmony_ci } else { 980562306a36Sopenharmony_ci bcnrc_val = 0; 980662306a36Sopenharmony_ci } 980762306a36Sopenharmony_ci 980862306a36Sopenharmony_ci wr32(E1000_RTTDQSEL, vf); /* vf X uses queue X */ 980962306a36Sopenharmony_ci /* Set global transmit compensation time to the MMW_SIZE in RTTBCNRM 981062306a36Sopenharmony_ci * register. MMW_SIZE=0x014 if 9728-byte jumbo is supported. 981162306a36Sopenharmony_ci */ 981262306a36Sopenharmony_ci wr32(E1000_RTTBCNRM, 0x14); 981362306a36Sopenharmony_ci wr32(E1000_RTTBCNRC, bcnrc_val); 981462306a36Sopenharmony_ci} 981562306a36Sopenharmony_ci 981662306a36Sopenharmony_cistatic void igb_check_vf_rate_limit(struct igb_adapter *adapter) 981762306a36Sopenharmony_ci{ 981862306a36Sopenharmony_ci int actual_link_speed, i; 981962306a36Sopenharmony_ci bool reset_rate = false; 982062306a36Sopenharmony_ci 982162306a36Sopenharmony_ci /* VF TX rate limit was not set or not supported */ 982262306a36Sopenharmony_ci if ((adapter->vf_rate_link_speed == 0) || 982362306a36Sopenharmony_ci (adapter->hw.mac.type != e1000_82576)) 982462306a36Sopenharmony_ci return; 982562306a36Sopenharmony_ci 982662306a36Sopenharmony_ci actual_link_speed = igb_link_mbps(adapter->link_speed); 982762306a36Sopenharmony_ci if (actual_link_speed != adapter->vf_rate_link_speed) { 982862306a36Sopenharmony_ci reset_rate = true; 982962306a36Sopenharmony_ci adapter->vf_rate_link_speed = 0; 983062306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, 983162306a36Sopenharmony_ci "Link speed has been changed. VF Transmit rate is disabled\n"); 983262306a36Sopenharmony_ci } 983362306a36Sopenharmony_ci 983462306a36Sopenharmony_ci for (i = 0; i < adapter->vfs_allocated_count; i++) { 983562306a36Sopenharmony_ci if (reset_rate) 983662306a36Sopenharmony_ci adapter->vf_data[i].tx_rate = 0; 983762306a36Sopenharmony_ci 983862306a36Sopenharmony_ci igb_set_vf_rate_limit(&adapter->hw, i, 983962306a36Sopenharmony_ci adapter->vf_data[i].tx_rate, 984062306a36Sopenharmony_ci actual_link_speed); 984162306a36Sopenharmony_ci } 984262306a36Sopenharmony_ci} 984362306a36Sopenharmony_ci 984462306a36Sopenharmony_cistatic int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, 984562306a36Sopenharmony_ci int min_tx_rate, int max_tx_rate) 984662306a36Sopenharmony_ci{ 984762306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 984862306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 984962306a36Sopenharmony_ci int actual_link_speed; 985062306a36Sopenharmony_ci 985162306a36Sopenharmony_ci if (hw->mac.type != e1000_82576) 985262306a36Sopenharmony_ci return -EOPNOTSUPP; 985362306a36Sopenharmony_ci 985462306a36Sopenharmony_ci if (min_tx_rate) 985562306a36Sopenharmony_ci return -EINVAL; 985662306a36Sopenharmony_ci 985762306a36Sopenharmony_ci actual_link_speed = igb_link_mbps(adapter->link_speed); 985862306a36Sopenharmony_ci if ((vf >= adapter->vfs_allocated_count) || 985962306a36Sopenharmony_ci (!(rd32(E1000_STATUS) & E1000_STATUS_LU)) || 986062306a36Sopenharmony_ci (max_tx_rate < 0) || 986162306a36Sopenharmony_ci (max_tx_rate > actual_link_speed)) 986262306a36Sopenharmony_ci return -EINVAL; 986362306a36Sopenharmony_ci 986462306a36Sopenharmony_ci adapter->vf_rate_link_speed = actual_link_speed; 986562306a36Sopenharmony_ci adapter->vf_data[vf].tx_rate = (u16)max_tx_rate; 986662306a36Sopenharmony_ci igb_set_vf_rate_limit(hw, vf, max_tx_rate, actual_link_speed); 986762306a36Sopenharmony_ci 986862306a36Sopenharmony_ci return 0; 986962306a36Sopenharmony_ci} 987062306a36Sopenharmony_ci 987162306a36Sopenharmony_cistatic int igb_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, 987262306a36Sopenharmony_ci bool setting) 987362306a36Sopenharmony_ci{ 987462306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 987562306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 987662306a36Sopenharmony_ci u32 reg_val, reg_offset; 987762306a36Sopenharmony_ci 987862306a36Sopenharmony_ci if (!adapter->vfs_allocated_count) 987962306a36Sopenharmony_ci return -EOPNOTSUPP; 988062306a36Sopenharmony_ci 988162306a36Sopenharmony_ci if (vf >= adapter->vfs_allocated_count) 988262306a36Sopenharmony_ci return -EINVAL; 988362306a36Sopenharmony_ci 988462306a36Sopenharmony_ci reg_offset = (hw->mac.type == e1000_82576) ? E1000_DTXSWC : E1000_TXSWC; 988562306a36Sopenharmony_ci reg_val = rd32(reg_offset); 988662306a36Sopenharmony_ci if (setting) 988762306a36Sopenharmony_ci reg_val |= (BIT(vf) | 988862306a36Sopenharmony_ci BIT(vf + E1000_DTXSWC_VLAN_SPOOF_SHIFT)); 988962306a36Sopenharmony_ci else 989062306a36Sopenharmony_ci reg_val &= ~(BIT(vf) | 989162306a36Sopenharmony_ci BIT(vf + E1000_DTXSWC_VLAN_SPOOF_SHIFT)); 989262306a36Sopenharmony_ci wr32(reg_offset, reg_val); 989362306a36Sopenharmony_ci 989462306a36Sopenharmony_ci adapter->vf_data[vf].spoofchk_enabled = setting; 989562306a36Sopenharmony_ci return 0; 989662306a36Sopenharmony_ci} 989762306a36Sopenharmony_ci 989862306a36Sopenharmony_cistatic int igb_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting) 989962306a36Sopenharmony_ci{ 990062306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 990162306a36Sopenharmony_ci 990262306a36Sopenharmony_ci if (vf >= adapter->vfs_allocated_count) 990362306a36Sopenharmony_ci return -EINVAL; 990462306a36Sopenharmony_ci if (adapter->vf_data[vf].trusted == setting) 990562306a36Sopenharmony_ci return 0; 990662306a36Sopenharmony_ci 990762306a36Sopenharmony_ci adapter->vf_data[vf].trusted = setting; 990862306a36Sopenharmony_ci 990962306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, "VF %u is %strusted\n", 991062306a36Sopenharmony_ci vf, setting ? "" : "not "); 991162306a36Sopenharmony_ci return 0; 991262306a36Sopenharmony_ci} 991362306a36Sopenharmony_ci 991462306a36Sopenharmony_cistatic int igb_ndo_get_vf_config(struct net_device *netdev, 991562306a36Sopenharmony_ci int vf, struct ifla_vf_info *ivi) 991662306a36Sopenharmony_ci{ 991762306a36Sopenharmony_ci struct igb_adapter *adapter = netdev_priv(netdev); 991862306a36Sopenharmony_ci if (vf >= adapter->vfs_allocated_count) 991962306a36Sopenharmony_ci return -EINVAL; 992062306a36Sopenharmony_ci ivi->vf = vf; 992162306a36Sopenharmony_ci memcpy(&ivi->mac, adapter->vf_data[vf].vf_mac_addresses, ETH_ALEN); 992262306a36Sopenharmony_ci ivi->max_tx_rate = adapter->vf_data[vf].tx_rate; 992362306a36Sopenharmony_ci ivi->min_tx_rate = 0; 992462306a36Sopenharmony_ci ivi->vlan = adapter->vf_data[vf].pf_vlan; 992562306a36Sopenharmony_ci ivi->qos = adapter->vf_data[vf].pf_qos; 992662306a36Sopenharmony_ci ivi->spoofchk = adapter->vf_data[vf].spoofchk_enabled; 992762306a36Sopenharmony_ci ivi->trusted = adapter->vf_data[vf].trusted; 992862306a36Sopenharmony_ci return 0; 992962306a36Sopenharmony_ci} 993062306a36Sopenharmony_ci 993162306a36Sopenharmony_cistatic void igb_vmm_control(struct igb_adapter *adapter) 993262306a36Sopenharmony_ci{ 993362306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 993462306a36Sopenharmony_ci u32 reg; 993562306a36Sopenharmony_ci 993662306a36Sopenharmony_ci switch (hw->mac.type) { 993762306a36Sopenharmony_ci case e1000_82575: 993862306a36Sopenharmony_ci case e1000_i210: 993962306a36Sopenharmony_ci case e1000_i211: 994062306a36Sopenharmony_ci case e1000_i354: 994162306a36Sopenharmony_ci default: 994262306a36Sopenharmony_ci /* replication is not supported for 82575 */ 994362306a36Sopenharmony_ci return; 994462306a36Sopenharmony_ci case e1000_82576: 994562306a36Sopenharmony_ci /* notify HW that the MAC is adding vlan tags */ 994662306a36Sopenharmony_ci reg = rd32(E1000_DTXCTL); 994762306a36Sopenharmony_ci reg |= E1000_DTXCTL_VLAN_ADDED; 994862306a36Sopenharmony_ci wr32(E1000_DTXCTL, reg); 994962306a36Sopenharmony_ci fallthrough; 995062306a36Sopenharmony_ci case e1000_82580: 995162306a36Sopenharmony_ci /* enable replication vlan tag stripping */ 995262306a36Sopenharmony_ci reg = rd32(E1000_RPLOLR); 995362306a36Sopenharmony_ci reg |= E1000_RPLOLR_STRVLAN; 995462306a36Sopenharmony_ci wr32(E1000_RPLOLR, reg); 995562306a36Sopenharmony_ci fallthrough; 995662306a36Sopenharmony_ci case e1000_i350: 995762306a36Sopenharmony_ci /* none of the above registers are supported by i350 */ 995862306a36Sopenharmony_ci break; 995962306a36Sopenharmony_ci } 996062306a36Sopenharmony_ci 996162306a36Sopenharmony_ci if (adapter->vfs_allocated_count) { 996262306a36Sopenharmony_ci igb_vmdq_set_loopback_pf(hw, true); 996362306a36Sopenharmony_ci igb_vmdq_set_replication_pf(hw, true); 996462306a36Sopenharmony_ci igb_vmdq_set_anti_spoofing_pf(hw, true, 996562306a36Sopenharmony_ci adapter->vfs_allocated_count); 996662306a36Sopenharmony_ci } else { 996762306a36Sopenharmony_ci igb_vmdq_set_loopback_pf(hw, false); 996862306a36Sopenharmony_ci igb_vmdq_set_replication_pf(hw, false); 996962306a36Sopenharmony_ci } 997062306a36Sopenharmony_ci} 997162306a36Sopenharmony_ci 997262306a36Sopenharmony_cistatic void igb_init_dmac(struct igb_adapter *adapter, u32 pba) 997362306a36Sopenharmony_ci{ 997462306a36Sopenharmony_ci struct e1000_hw *hw = &adapter->hw; 997562306a36Sopenharmony_ci u32 dmac_thr; 997662306a36Sopenharmony_ci u16 hwm; 997762306a36Sopenharmony_ci u32 reg; 997862306a36Sopenharmony_ci 997962306a36Sopenharmony_ci if (hw->mac.type > e1000_82580) { 998062306a36Sopenharmony_ci if (adapter->flags & IGB_FLAG_DMAC) { 998162306a36Sopenharmony_ci /* force threshold to 0. */ 998262306a36Sopenharmony_ci wr32(E1000_DMCTXTH, 0); 998362306a36Sopenharmony_ci 998462306a36Sopenharmony_ci /* DMA Coalescing high water mark needs to be greater 998562306a36Sopenharmony_ci * than the Rx threshold. Set hwm to PBA - max frame 998662306a36Sopenharmony_ci * size in 16B units, capping it at PBA - 6KB. 998762306a36Sopenharmony_ci */ 998862306a36Sopenharmony_ci hwm = 64 * (pba - 6); 998962306a36Sopenharmony_ci reg = rd32(E1000_FCRTC); 999062306a36Sopenharmony_ci reg &= ~E1000_FCRTC_RTH_COAL_MASK; 999162306a36Sopenharmony_ci reg |= ((hwm << E1000_FCRTC_RTH_COAL_SHIFT) 999262306a36Sopenharmony_ci & E1000_FCRTC_RTH_COAL_MASK); 999362306a36Sopenharmony_ci wr32(E1000_FCRTC, reg); 999462306a36Sopenharmony_ci 999562306a36Sopenharmony_ci /* Set the DMA Coalescing Rx threshold to PBA - 2 * max 999662306a36Sopenharmony_ci * frame size, capping it at PBA - 10KB. 999762306a36Sopenharmony_ci */ 999862306a36Sopenharmony_ci dmac_thr = pba - 10; 999962306a36Sopenharmony_ci reg = rd32(E1000_DMACR); 1000062306a36Sopenharmony_ci reg &= ~E1000_DMACR_DMACTHR_MASK; 1000162306a36Sopenharmony_ci reg |= ((dmac_thr << E1000_DMACR_DMACTHR_SHIFT) 1000262306a36Sopenharmony_ci & E1000_DMACR_DMACTHR_MASK); 1000362306a36Sopenharmony_ci 1000462306a36Sopenharmony_ci /* transition to L0x or L1 if available..*/ 1000562306a36Sopenharmony_ci reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK); 1000662306a36Sopenharmony_ci 1000762306a36Sopenharmony_ci /* watchdog timer= +-1000 usec in 32usec intervals */ 1000862306a36Sopenharmony_ci reg |= (1000 >> 5); 1000962306a36Sopenharmony_ci 1001062306a36Sopenharmony_ci /* Disable BMC-to-OS Watchdog Enable */ 1001162306a36Sopenharmony_ci if (hw->mac.type != e1000_i354) 1001262306a36Sopenharmony_ci reg &= ~E1000_DMACR_DC_BMC2OSW_EN; 1001362306a36Sopenharmony_ci wr32(E1000_DMACR, reg); 1001462306a36Sopenharmony_ci 1001562306a36Sopenharmony_ci /* no lower threshold to disable 1001662306a36Sopenharmony_ci * coalescing(smart fifb)-UTRESH=0 1001762306a36Sopenharmony_ci */ 1001862306a36Sopenharmony_ci wr32(E1000_DMCRTRH, 0); 1001962306a36Sopenharmony_ci 1002062306a36Sopenharmony_ci reg = (IGB_DMCTLX_DCFLUSH_DIS | 0x4); 1002162306a36Sopenharmony_ci 1002262306a36Sopenharmony_ci wr32(E1000_DMCTLX, reg); 1002362306a36Sopenharmony_ci 1002462306a36Sopenharmony_ci /* free space in tx packet buffer to wake from 1002562306a36Sopenharmony_ci * DMA coal 1002662306a36Sopenharmony_ci */ 1002762306a36Sopenharmony_ci wr32(E1000_DMCTXTH, (IGB_MIN_TXPBSIZE - 1002862306a36Sopenharmony_ci (IGB_TX_BUF_4096 + adapter->max_frame_size)) >> 6); 1002962306a36Sopenharmony_ci } 1003062306a36Sopenharmony_ci 1003162306a36Sopenharmony_ci if (hw->mac.type >= e1000_i210 || 1003262306a36Sopenharmony_ci (adapter->flags & IGB_FLAG_DMAC)) { 1003362306a36Sopenharmony_ci reg = rd32(E1000_PCIEMISC); 1003462306a36Sopenharmony_ci reg |= E1000_PCIEMISC_LX_DECISION; 1003562306a36Sopenharmony_ci wr32(E1000_PCIEMISC, reg); 1003662306a36Sopenharmony_ci } /* endif adapter->dmac is not disabled */ 1003762306a36Sopenharmony_ci } else if (hw->mac.type == e1000_82580) { 1003862306a36Sopenharmony_ci u32 reg = rd32(E1000_PCIEMISC); 1003962306a36Sopenharmony_ci 1004062306a36Sopenharmony_ci wr32(E1000_PCIEMISC, reg & ~E1000_PCIEMISC_LX_DECISION); 1004162306a36Sopenharmony_ci wr32(E1000_DMACR, 0); 1004262306a36Sopenharmony_ci } 1004362306a36Sopenharmony_ci} 1004462306a36Sopenharmony_ci 1004562306a36Sopenharmony_ci/** 1004662306a36Sopenharmony_ci * igb_read_i2c_byte - Reads 8 bit word over I2C 1004762306a36Sopenharmony_ci * @hw: pointer to hardware structure 1004862306a36Sopenharmony_ci * @byte_offset: byte offset to read 1004962306a36Sopenharmony_ci * @dev_addr: device address 1005062306a36Sopenharmony_ci * @data: value read 1005162306a36Sopenharmony_ci * 1005262306a36Sopenharmony_ci * Performs byte read operation over I2C interface at 1005362306a36Sopenharmony_ci * a specified device address. 1005462306a36Sopenharmony_ci **/ 1005562306a36Sopenharmony_cis32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset, 1005662306a36Sopenharmony_ci u8 dev_addr, u8 *data) 1005762306a36Sopenharmony_ci{ 1005862306a36Sopenharmony_ci struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); 1005962306a36Sopenharmony_ci struct i2c_client *this_client = adapter->i2c_client; 1006062306a36Sopenharmony_ci s32 status; 1006162306a36Sopenharmony_ci u16 swfw_mask = 0; 1006262306a36Sopenharmony_ci 1006362306a36Sopenharmony_ci if (!this_client) 1006462306a36Sopenharmony_ci return E1000_ERR_I2C; 1006562306a36Sopenharmony_ci 1006662306a36Sopenharmony_ci swfw_mask = E1000_SWFW_PHY0_SM; 1006762306a36Sopenharmony_ci 1006862306a36Sopenharmony_ci if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) 1006962306a36Sopenharmony_ci return E1000_ERR_SWFW_SYNC; 1007062306a36Sopenharmony_ci 1007162306a36Sopenharmony_ci status = i2c_smbus_read_byte_data(this_client, byte_offset); 1007262306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swfw_mask); 1007362306a36Sopenharmony_ci 1007462306a36Sopenharmony_ci if (status < 0) 1007562306a36Sopenharmony_ci return E1000_ERR_I2C; 1007662306a36Sopenharmony_ci else { 1007762306a36Sopenharmony_ci *data = status; 1007862306a36Sopenharmony_ci return 0; 1007962306a36Sopenharmony_ci } 1008062306a36Sopenharmony_ci} 1008162306a36Sopenharmony_ci 1008262306a36Sopenharmony_ci/** 1008362306a36Sopenharmony_ci * igb_write_i2c_byte - Writes 8 bit word over I2C 1008462306a36Sopenharmony_ci * @hw: pointer to hardware structure 1008562306a36Sopenharmony_ci * @byte_offset: byte offset to write 1008662306a36Sopenharmony_ci * @dev_addr: device address 1008762306a36Sopenharmony_ci * @data: value to write 1008862306a36Sopenharmony_ci * 1008962306a36Sopenharmony_ci * Performs byte write operation over I2C interface at 1009062306a36Sopenharmony_ci * a specified device address. 1009162306a36Sopenharmony_ci **/ 1009262306a36Sopenharmony_cis32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, 1009362306a36Sopenharmony_ci u8 dev_addr, u8 data) 1009462306a36Sopenharmony_ci{ 1009562306a36Sopenharmony_ci struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); 1009662306a36Sopenharmony_ci struct i2c_client *this_client = adapter->i2c_client; 1009762306a36Sopenharmony_ci s32 status; 1009862306a36Sopenharmony_ci u16 swfw_mask = E1000_SWFW_PHY0_SM; 1009962306a36Sopenharmony_ci 1010062306a36Sopenharmony_ci if (!this_client) 1010162306a36Sopenharmony_ci return E1000_ERR_I2C; 1010262306a36Sopenharmony_ci 1010362306a36Sopenharmony_ci if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) 1010462306a36Sopenharmony_ci return E1000_ERR_SWFW_SYNC; 1010562306a36Sopenharmony_ci status = i2c_smbus_write_byte_data(this_client, byte_offset, data); 1010662306a36Sopenharmony_ci hw->mac.ops.release_swfw_sync(hw, swfw_mask); 1010762306a36Sopenharmony_ci 1010862306a36Sopenharmony_ci if (status) 1010962306a36Sopenharmony_ci return E1000_ERR_I2C; 1011062306a36Sopenharmony_ci else 1011162306a36Sopenharmony_ci return 0; 1011262306a36Sopenharmony_ci 1011362306a36Sopenharmony_ci} 1011462306a36Sopenharmony_ci 1011562306a36Sopenharmony_ciint igb_reinit_queues(struct igb_adapter *adapter) 1011662306a36Sopenharmony_ci{ 1011762306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 1011862306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 1011962306a36Sopenharmony_ci int err = 0; 1012062306a36Sopenharmony_ci 1012162306a36Sopenharmony_ci if (netif_running(netdev)) 1012262306a36Sopenharmony_ci igb_close(netdev); 1012362306a36Sopenharmony_ci 1012462306a36Sopenharmony_ci igb_reset_interrupt_capability(adapter); 1012562306a36Sopenharmony_ci 1012662306a36Sopenharmony_ci if (igb_init_interrupt_scheme(adapter, true)) { 1012762306a36Sopenharmony_ci dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); 1012862306a36Sopenharmony_ci return -ENOMEM; 1012962306a36Sopenharmony_ci } 1013062306a36Sopenharmony_ci 1013162306a36Sopenharmony_ci if (netif_running(netdev)) 1013262306a36Sopenharmony_ci err = igb_open(netdev); 1013362306a36Sopenharmony_ci 1013462306a36Sopenharmony_ci return err; 1013562306a36Sopenharmony_ci} 1013662306a36Sopenharmony_ci 1013762306a36Sopenharmony_cistatic void igb_nfc_filter_exit(struct igb_adapter *adapter) 1013862306a36Sopenharmony_ci{ 1013962306a36Sopenharmony_ci struct igb_nfc_filter *rule; 1014062306a36Sopenharmony_ci 1014162306a36Sopenharmony_ci spin_lock(&adapter->nfc_lock); 1014262306a36Sopenharmony_ci 1014362306a36Sopenharmony_ci hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) 1014462306a36Sopenharmony_ci igb_erase_filter(adapter, rule); 1014562306a36Sopenharmony_ci 1014662306a36Sopenharmony_ci hlist_for_each_entry(rule, &adapter->cls_flower_list, nfc_node) 1014762306a36Sopenharmony_ci igb_erase_filter(adapter, rule); 1014862306a36Sopenharmony_ci 1014962306a36Sopenharmony_ci spin_unlock(&adapter->nfc_lock); 1015062306a36Sopenharmony_ci} 1015162306a36Sopenharmony_ci 1015262306a36Sopenharmony_cistatic void igb_nfc_filter_restore(struct igb_adapter *adapter) 1015362306a36Sopenharmony_ci{ 1015462306a36Sopenharmony_ci struct igb_nfc_filter *rule; 1015562306a36Sopenharmony_ci 1015662306a36Sopenharmony_ci spin_lock(&adapter->nfc_lock); 1015762306a36Sopenharmony_ci 1015862306a36Sopenharmony_ci hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) 1015962306a36Sopenharmony_ci igb_add_filter(adapter, rule); 1016062306a36Sopenharmony_ci 1016162306a36Sopenharmony_ci spin_unlock(&adapter->nfc_lock); 1016262306a36Sopenharmony_ci} 1016362306a36Sopenharmony_ci/* igb_main.c */ 10164