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