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